84 static qreal dot(const QPointF &a, const QPointF &b) |
84 static qreal dot(const QPointF &a, const QPointF &b) |
85 { |
85 { |
86 return a.x() * b.x() + a.y() * b.y(); |
86 return a.x() * b.x() + a.y() * b.y(); |
87 } |
87 } |
88 |
88 |
89 static QPointF normalize(const QPointF &p) |
89 static void normalize(double &x, double &y) |
90 { |
90 { |
91 return p / qSqrt(p.x() * p.x() + p.y() * p.y()); |
91 double reciprocal = 1 / qSqrt(x * x + y * y); |
|
92 x *= reciprocal; |
|
93 y *= reciprocal; |
92 } |
94 } |
93 |
95 |
94 struct QIntersection |
96 struct QIntersection |
95 { |
97 { |
96 qreal alphaA; |
98 qreal alphaA; |
1015 qreal QWingedEdge::delta(int vertex, int a, int b) const |
1017 qreal QWingedEdge::delta(int vertex, int a, int b) const |
1016 { |
1018 { |
1017 const QPathEdge *ap = edge(a); |
1019 const QPathEdge *ap = edge(a); |
1018 const QPathEdge *bp = edge(b); |
1020 const QPathEdge *bp = edge(b); |
1019 |
1021 |
1020 qreal a_angle = ap->angle; |
1022 double a_angle = ap->angle; |
1021 qreal b_angle = bp->angle; |
1023 double b_angle = bp->angle; |
1022 |
1024 |
1023 if (vertex == ap->second) |
1025 if (vertex == ap->second) |
1024 a_angle = ap->invAngle; |
1026 a_angle = ap->invAngle; |
1025 |
1027 |
1026 if (vertex == bp->second) |
1028 if (vertex == bp->second) |
1027 b_angle = bp->invAngle; |
1029 b_angle = bp->invAngle; |
1028 |
1030 |
1029 qreal result = b_angle - a_angle; |
1031 double result = b_angle - a_angle; |
1030 |
1032 |
1031 if (result >= 128.) |
1033 if (result >= 128.) |
1032 return result - 128.; |
1034 return result - 128.; |
1033 else if (result < 0) |
1035 else if (result < 0) |
1034 return result + 128.; |
1036 return result + 128.; |
1035 else |
1037 else |
1036 return result; |
1038 return result; |
1037 } |
1039 } |
1038 |
1040 |
1039 static inline QPointF tangentAt(const QWingedEdge &list, int vi, int ei) |
|
1040 { |
|
1041 const QPathEdge *ep = list.edge(ei); |
|
1042 Q_ASSERT(ep); |
|
1043 |
|
1044 qreal sign; |
|
1045 |
|
1046 if (ep->first == vi) { |
|
1047 sign = 1; |
|
1048 } else { |
|
1049 sign = -1; |
|
1050 } |
|
1051 |
|
1052 const QPointF a = *list.vertex(ep->first); |
|
1053 const QPointF b = *list.vertex(ep->second); |
|
1054 QPointF normal = b - a; |
|
1055 |
|
1056 return normalize(sign * normal); |
|
1057 } |
|
1058 |
|
1059 static inline QPointF midPoint(const QWingedEdge &list, int ei) |
1041 static inline QPointF midPoint(const QWingedEdge &list, int ei) |
1060 { |
1042 { |
1061 const QPathEdge *ep = list.edge(ei); |
1043 const QPathEdge *ep = list.edge(ei); |
1062 Q_ASSERT(ep); |
1044 Q_ASSERT(ep); |
1063 |
1045 |
1189 } while (status.edge != ap->edge); |
1171 } while (status.edge != ap->edge); |
1190 |
1172 |
1191 return -1; |
1173 return -1; |
1192 } |
1174 } |
1193 |
1175 |
1194 static qreal computeAngle(const QPointF &v) |
1176 static double computeAngle(const QPointF &v) |
1195 { |
1177 { |
1196 #if 1 |
1178 #if 1 |
1197 if (v.x() == 0) { |
1179 if (v.x() == 0) { |
1198 return v.y() <= 0 ? 0 : 64.; |
1180 return v.y() <= 0 ? 0 : 64.; |
1199 } else if (v.y() == 0) { |
1181 } else if (v.y() == 0) { |
1200 return v.x() <= 0 ? 32. : 96.; |
1182 return v.x() <= 0 ? 32. : 96.; |
1201 } |
1183 } |
1202 |
1184 |
1203 QPointF nv = normalize(v); |
1185 double vx = v.x(); |
1204 if (nv.y() < 0) { |
1186 double vy = v.y(); |
1205 if (nv.x() < 0) { // 0 - 32 |
1187 normalize(vx, vy); |
1206 return -32. * nv.x(); |
1188 if (vy < 0) { |
|
1189 if (vx < 0) { // 0 - 32 |
|
1190 return -32. * vx; |
1207 } else { // 96 - 128 |
1191 } else { // 96 - 128 |
1208 return 128. - 32. * nv.x(); |
1192 return 128. - 32. * vx; |
1209 } |
1193 } |
1210 } else { // 32 - 96 |
1194 } else { // 32 - 96 |
1211 return 64. + 32 * nv.x(); |
1195 return 64. + 32. * vx; |
1212 } |
1196 } |
1213 #else |
1197 #else |
1214 // doesn't seem to be robust enough |
1198 // doesn't seem to be robust enough |
1215 return qAtan2(v.x(), v.y()) + Q_PI; |
1199 return qAtan2(v.x(), v.y()) + Q_PI; |
1216 #endif |
1200 #endif |