* @brief Emits a round-join fan filling the outer notch at vertex p, sweeping outer-side unit * normals n0 to n1 across nFan>=1 arc steps. A center vertex plus nFan+1 feathered rim * pairs (core at face, feather at edge) tile the arc as one core plus two feather triangles * per step, so the join is solid with an anti-aliased rim. */
| 135 | * per step, so the join is solid with an anti-aliased rim. |
| 136 | */ |
| 137 | static void emitFan(QSGGeometry::ColoredPoint2D* vertices, |
| 138 | quint32* indices, |
| 139 | int& v, |
| 140 | int& idx, |
| 141 | const QPointF& p, |
| 142 | const QPointF& n0, |
| 143 | const QPointF& n1, |
| 144 | const int nFan, |
| 145 | const double hw, |
| 146 | const QColor& color) |
| 147 | { |
| 148 | Q_ASSERT(vertices != nullptr); |
| 149 | Q_ASSERT(indices != nullptr); |
| 150 | Q_ASSERT(nFan >= 1); |
| 151 | |
| 152 | const double alpha = color.alphaF(); |
| 153 | const double face = std::max(0.25, hw - kFeatherPx * 0.5); |
| 154 | const double edge = face + kFeatherPx; |
| 155 | |
| 156 | const double dot = std::clamp(n0.x() * n1.x() + n0.y() * n1.y(), -1.0, 1.0); |
| 157 | const double cross = n0.x() * n1.y() - n0.y() * n1.x(); |
| 158 | const double sweep = std::atan2(cross, dot) / nFan; |
| 159 | const double cs = std::cos(sweep); |
| 160 | const double sn = std::sin(sweep); |
| 161 | |
| 162 | const int center = v; |
| 163 | setVertexColor(vertices[v++], static_cast<float>(p.x()), static_cast<float>(p.y()), color, alpha); |
| 164 | |
| 165 | double rx = n0.x(); |
| 166 | double ry = n0.y(); |
| 167 | for (int j = 0; j <= nFan; ++j) { |
| 168 | const double dx = (j == nFan) ? n1.x() : rx; |
| 169 | const double dy = (j == nFan) ? n1.y() : ry; |
| 170 | setVertexColor(vertices[v++], |
| 171 | static_cast<float>(p.x() + dx * face), |
| 172 | static_cast<float>(p.y() + dy * face), |
| 173 | color, |
| 174 | alpha); |
| 175 | setVertexColor(vertices[v++], |
| 176 | static_cast<float>(p.x() + dx * edge), |
| 177 | static_cast<float>(p.y() + dy * edge), |
| 178 | color, |
| 179 | 0.0); |
| 180 | const double nx = rx * cs - ry * sn; |
| 181 | ry = rx * sn + ry * cs; |
| 182 | rx = nx; |
| 183 | } |
| 184 | |
| 185 | for (int j = 0; j < nFan; ++j) { |
| 186 | const int c0 = center + 1 + 2 * j; |
| 187 | const int c1 = center + 1 + 2 * (j + 1); |
| 188 | indices[idx++] = static_cast<quint32>(center); |
| 189 | indices[idx++] = static_cast<quint32>(c0); |
| 190 | indices[idx++] = static_cast<quint32>(c1); |
| 191 | indices[idx++] = static_cast<quint32>(c0); |
| 192 | indices[idx++] = static_cast<quint32>(c0 + 1); |
| 193 | indices[idx++] = static_cast<quint32>(c1 + 1); |
| 194 | indices[idx++] = static_cast<quint32>(c0); |