6#include <QtGui/qevent.h>
7#include <QtGui/qpainter.h>
8#include <QtGui/qpainterpath.h>
9#include <QtGui/private/qbezier_p.h>
10#include <QtGui/private/qdatabuffer_p.h>
11#include <QtCore/qbitarray.h>
12#include <QtCore/qvarlengtharray.h>
13#include <QtCore/qqueue.h>
14#include <QtCore/qglobal.h>
15#include <QtCore/qpoint.h>
16#include <QtCore/qalgorithms.h>
17#include <private/qrbtree_p.h>
23#define Q_FIXED_POINT_SCALE 32
28 inline QVertexSet() { }
29 inline QVertexSet(
const QVertexSet<T> &other) : vertices(other.vertices), indices(other.indices) { }
30 QVertexSet<T> &operator = (
const QVertexSet<T> &other) {vertices = other.vertices; indices = other.indices;
return *
this;}
33 QList<qreal> vertices;
52 inline bool isValid()
const {
return denominator != 0;}
68static inline int compare(quint64 a, quint64 b)
70 return (a > b) - (a < b);
78 const quint64 LIMIT = Q_UINT64_C(0x100000000);
81 if (b < LIMIT && d < LIMIT)
82 return compare(a * d, b * c);
88 quint64 b_div_a = b / a;
89 quint64 d_div_c = d / c;
90 if (b_div_a != d_div_c)
91 return compare(d_div_c, b_div_a);
108 result.numerator = 0;
109 result.denominator = 1;
111 quint64 g = gcd(n, d);
112 result.numerator = n / g;
113 result.denominator = d / g;
120 return qCompareFractions(numerator, denominator, other.numerator, other.denominator) < 0;
125 return numerator == other.numerator && denominator == other.denominator;
158 return qint64(u
.x) * qint64(v
.y) - qint64(u
.y) * qint64(v
.x);
161#ifdef Q_TRIANGULATOR_DEBUG
162static inline qint64 qDot(
const QPodPoint &u,
const QPodPoint &v)
164 return qint64(u.x) * qint64(v.x) + qint64(u.y) * qint64(v.y);
174 return qCross(v2 - v1, p - v1);
179 return QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(p, v1, v2) < 0;
188 inline bool isValid()
const {
return xOffset.isValid() && yOffset.isValid();}
190 inline bool isAccurate()
const {
return xOffset.numerator == 0 && yOffset.numerator == 0;}
217 qint64 d1 = qCross(u, v1 - u1);
218 qint64 d2 = qCross(u, v2 - u1);
219 qint64 det = d2 - d1;
220 qint64 d3 = qCross(v, u1 - v1);
221 qint64 d4 = d3 - det;
224 Q_ASSERT(d4 == qCross(v, u2 - v1));
246 if (d1 >= 0 || d2 <= 0 || d3 <= 0 || d4 >= 0)
257 result.xOffset = qFraction(quint64(-v.x * d1) % quint64(det), quint64(det));
260 result.xOffset = qFraction(quint64(-v.x * d2) % quint64(det), quint64(det));
265 result.yOffset = qFraction(quint64(-v.y * d1) % quint64(det), quint64(det));
268 result.yOffset = qFraction(quint64(-v.y * d2) % quint64(det), quint64(det));
271 Q_ASSERT(result.xOffset.isValid());
272 Q_ASSERT(result.yOffset.isValid());
279 if (2 * xOffset.numerator >= xOffset.denominator)
281 if (2 * yOffset.numerator >= yOffset.denominator)
290 if (yOffset != other.yOffset)
291 return yOffset < other.yOffset;
294 return xOffset < other.xOffset;
299 return upperLeft == other.upperLeft && xOffset == other.xOffset && yOffset == other.yOffset;
308 bool isHorizontal = p.y == 0 && yOffset.numerator == 0;
309 bool isVertical = p.x == 0 && xOffset.numerator == 0;
310 if (isHorizontal && isVertical)
323 if (((q
.x < 0) == (q
.y < 0)) != ((p
.x < 0) == (p
.y < 0)))
329 nx = quint64(-p.x) * xOffset.denominator - xOffset.numerator;
331 nx = quint64(p.x) * xOffset.denominator + xOffset.numerator;
333 ny = quint64(-p.y) * yOffset.denominator - yOffset.numerator;
335 ny = quint64(p.y) * yOffset.denominator + yOffset.numerator;
337 return qFraction(quint64(qAbs(q.x)) * xOffset.denominator, quint64(qAbs(q.y)) * yOffset.denominator) == qFraction(nx, ny);
349 inline int size()
const {
return m_data.size();}
350 inline bool empty()
const {
return m_data.isEmpty();}
351 inline bool isEmpty()
const {
return m_data.isEmpty();}
354 inline const T &
top()
const {
return m_data.first();}
356 static inline int parent(
int i) {
return (i - 1) / 2;}
357 static inline int left(
int i) {
return 2 * i + 1;}
358 static inline int right(
int i) {
return 2 * i + 2;}
360 QDataBuffer<T> m_data;
366 int current = m_data.size();
367 int parent =
QMaxHeap::parent(current);
369 while (current != 0 && m_data.at(parent) < x) {
370 m_data.at(current) = m_data.at(parent);
374 m_data.at(current) = x;
380 T result = m_data.first();
381 T back = m_data.last();
383 if (!m_data.isEmpty()) {
387 int right =
QMaxHeap::right(current);
388 if (left >= m_data.size())
391 if (right < m_data.size() && m_data.at(left) < m_data.at(right))
393 if (m_data.at(greater) < back)
395 m_data.at(current) = m_data.at(greater);
398 m_data.at(current) = back;
409 Q_ASSERT(count >= 0);
412 constexpr auto primeForNumBits = [](
int numBits) ->
int
414 constexpr uchar prime_deltas[] = {
415 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 17, 27, 3,
416 1, 29, 3, 21, 7, 17, 15, 9, 43, 35, 15, 0, 0, 0, 0, 0
419 return (1 << numBits) + prime_deltas[numBits];
424 for (
int i = 0; i < 5; ++i) {
425 int mid = (high + low) / 2;
426 if (uint(count) >= (1u << mid))
431 return primeForNumBits(high);
447 bool rehash(
int capacity);
449 static const quint64 UNUSED;
456const quint64
QInt64Set::UNUSED = quint64(-1);
461 m_array =
new quint64[m_capacity];
467 quint64 *oldArray = m_array;
468 int oldCapacity = m_capacity;
470 m_capacity = capacity;
471 m_array =
new quint64[m_capacity];
473 for (
int i = 0; i < oldCapacity; ++i) {
474 if (oldArray[i] != UNUSED)
483 if (m_count > 3 * m_capacity / 4)
485 int index =
int(key % m_capacity);
486 for (
int i = 0; i < m_capacity; ++i) {
488 if (index >= m_capacity)
490 if (m_array[index] == key)
492 if (m_array[index] == UNUSED) {
494 m_array[index] = key;
498 Q_ASSERT_X(0,
"QInt64Hash<T>::insert",
"Hash set full.");
503 int index =
int(key % m_capacity);
504 for (
int i = 0; i < m_capacity; ++i) {
506 if (index >= m_capacity)
508 if (m_array[index] == key)
510 if (m_array[index] == UNUSED)
518 for (
int i = 0; i < m_capacity; ++i)
535 friend class ComplexToSimple;
545 inline int &upper() {
return pointingUp ? to : from;}
546 inline int &lower() {
return pointingUp ? from : to;}
547 inline int upper()
const {
return pointingUp ? to : from;}
548 inline int lower()
const {
return pointingUp ? from : to;}
550 QRBTree<
int>::Node *node;
555 bool pointingUp, originallyPointingUp;
560 bool operator < (
const Intersection &other)
const {
return other.intersectionPoint < intersectionPoint;}
577 enum Type {Upper, Lower};
578 inline bool operator < (
const Event &other)
const;
585#ifdef Q_TRIANGULATOR_DEBUG
606 bool calculateIntersection(
int left,
int right);
607 bool edgeIsLeftOfEdge(
int leftEdgeIndex,
int rightEdgeIndex)
const;
608 QRBTree<
int>::Node *searchEdgeLeftOf(
int edgeIndex)
const;
609 QRBTree<
int>::Node *searchEdgeLeftOf(
int edgeIndex, QRBTree<
int>::Node *after)
const;
612 void splitEdgeListRange(QRBTree<
int>::Node *leftmost, QRBTree<
int>::Node *rightmost,
int vertex,
const QIntersectionPoint &intersectionPoint);
613 void reorderEdgeListRange(QRBTree<
int>::Node *leftmost, QRBTree<
int>::Node *rightmost);
614 void sortEdgeList(
const QPodPoint eventPoint);
615 void fillPriorityQueue();
616 void calculateIntersections();
617 int splitEdge(
int splitIndex);
618 bool splitEdgesAtIntersections();
619 void insertEdgeIntoVectorIfWanted(
ShortArray &orderedEdges,
int i);
620 void removeUnwantedEdgesAndConnect();
621 void removeUnusedPoints();
624 QDataBuffer<Edge> m_edges;
625 QRBTree<
int> m_edgeList;
626 QDataBuffer<Event> m_events;
627 QDataBuffer<Split> m_splits;
628 QMaxHeap<Intersection> m_topIntersection;
630 int m_initialPointCount;
632#ifdef Q_TRIANGULATOR_DEBUG
639 friend class SimpleToMonotone;
647 enum VertexType {MergeVertex, EndVertex, RegularVertex, StartVertex, SplitVertex};
651 QRBTree<
int>::Node *node;
652 int helper, twin, next, previous;
656 int upper()
const {
return (pointingUp ? to : from);}
657 int lower()
const {
return (pointingUp ? from : to);}
660 friend class CompareVertices;
661 class CompareVertices
665 bool operator () (
int i,
int j)
const;
670 void setupDataStructures();
671 void removeZeroLengthEdges();
672 void fillPriorityQueue();
673 bool edgeIsLeftOfEdge(
int leftEdgeIndex,
int rightEdgeIndex)
const;
675 QRBTree<
int>::Node *searchEdgeLeftOfEdge(
int edgeIndex)
const;
677 QRBTree<
int>::Node *searchEdgeLeftOfPoint(
int pointIndex)
const;
678 void classifyVertex(
int i);
679 void classifyVertices();
681 bool pointIsInSector(
int vertex,
int sector);
682 int findSector(
int edge,
int vertex);
683 void createDiagonal(
int lower,
int upper);
684 void monotoneDecomposition();
687 QRBTree<
int> m_edgeList;
688 QDataBuffer<Edge> m_edges;
689 QDataBuffer<
int> m_upperVertex;
690 bool m_clockwiseOrder;
696 friend class MonotoneToTriangles;
701 : m_parent(parent), m_first(0), m_length(0) { }
704 inline T indices(
int index)
const {
return m_parent->m_indices.at(index + m_first);}
705 inline int next(
int index)
const {
return (index + 1) % m_length;}
706 inline int previous(
int index)
const {
return (index + m_length - 1) % m_length;}
707 inline bool less(
int i,
int j)
const {
return m_parent->m_vertices.at((qint32)indices(i)) < m_parent->m_vertices.at(indices(j));}
708 inline bool leftOfEdge(
int i,
int j,
int k)
const
710 return qPointIsLeftOfLine(m_parent->m_vertices.at((qint32)indices(i)),
711 m_parent->m_vertices.at((qint32)indices(j)), m_parent->m_vertices.at((qint32)indices(k)));
723 void initialize(
const qreal *polygon,
int count, uint hint,
const QTransform &matrix);
725 void initialize(
const QVectorPath &path,
const QTransform &matrix, qreal lod);
727 void initialize(
const QPainterPath &path,
const QTransform &matrix, qreal lod);
732 QDataBuffer<QPodPoint> m_vertices;
744 for (
int i = 0; i < m_vertices.size(); ++i) {
745 Q_ASSERT(qAbs(m_vertices.at(i).x) < (1 << 21));
746 Q_ASSERT(qAbs(m_vertices.at(i).y) < (1 << 21));
749 if (!(m_hint & (QVectorPath::OddEvenFill | QVectorPath::WindingFill)))
750 m_hint |= QVectorPath::OddEvenFill;
752 if (m_hint & QVectorPath::NonConvexShapeMask) {
761 QVertexSet<T> result;
762 result.indices = m_indices;
763 result.vertices.resize(2 * m_vertices.size());
764 for (
int i = 0; i < m_vertices.size(); ++i) {
774 for (
int i = 0; i < m_vertices.size(); ++i) {
775 Q_ASSERT(qAbs(m_vertices.at(i).x) < (1 << 21));
776 Q_ASSERT(qAbs(m_vertices.at(i).y) < (1 << 21));
779 if (!(m_hint & (QVectorPath::OddEvenFill | QVectorPath::WindingFill)))
780 m_hint |= QVectorPath::OddEvenFill;
782 if (m_hint & QVectorPath::NonConvexShapeMask) {
787 QVertexSet<T> result;
788 result.indices = m_indices;
789 result.vertices.resize(2 * m_vertices.size());
790 for (
int i = 0; i < m_vertices.size(); ++i) {
801 m_vertices.resize(count);
802 m_indices.resize(count + 1);
803 for (
int i = 0; i < count; ++i) {
805 matrix.map(polygon[2 * i + 0], polygon[2 * i + 1], &x, &y);
810 m_indices[count] = T(-1);
816 m_hint = path.hints();
818 m_hint &= ~QVectorPath::CurvedShapeMask;
820 const qreal *p = path.points();
821 const QPainterPath::ElementType *e = path.elements();
823 for (
int i = 0; i < path.elementCount(); ++i, ++e, p += 2) {
825 case QPainterPath::MoveToElement:
826 if (!m_indices.isEmpty())
827 m_indices.push_back(T(-1));
829 case QPainterPath::LineToElement:
830 m_indices.push_back(T(m_vertices.size()));
831 m_vertices.resize(m_vertices.size() + 1);
833 matrix.map(p[0], p[1], &x, &y);
837 case QPainterPath::CurveToElement:
840 for (
int i = 0; i < 4; ++i)
841 matrix.map(p[2 * i - 2], p[2 * i - 1], &pts[2 * i + 0], &pts[2 * i + 1]);
842 for (
int i = 0; i < 8; ++i)
844 QBezier bezier = QBezier::fromPoints(QPointF(pts[0], pts[1]), QPointF(pts[2], pts[3]), QPointF(pts[4], pts[5]), QPointF(pts[6], pts[7]));
845 QPolygonF poly = bezier.toPolygon();
847 for (
int j = 1; j < poly.size(); ++j) {
848 m_indices.push_back(T(m_vertices.size()));
849 m_vertices.resize(m_vertices.size() + 1);
859 Q_ASSERT_X(0,
"QTriangulator::triangulate",
"Unexpected element type.");
864 for (
int i = 0; i < path.elementCount(); ++i, p += 2) {
865 m_indices.push_back(T(m_vertices.size()));
866 m_vertices.resize(m_vertices.size() + 1);
868 matrix.map(p[0], p[1], &x, &y);
873 m_indices.push_back(T(-1));
879 initialize(qtVectorPathForPath(path), matrix, lod);
888 m_initialPointCount = m_parent->m_vertices.size();
891 calculateIntersections();
892 }
while (splitEdgesAtIntersections());
894 removeUnwantedEdgesAndConnect();
895 removeUnusedPoints();
897 m_parent->m_indices.clear();
898 QBitArray processed(m_edges.size(),
false);
899 for (
int first = 0; first < m_edges.size(); ++first) {
901 if (processed.at(first) || m_edges.at(first).next == -1)
906 Q_ASSERT(!processed.at(i));
907 Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i);
908 m_parent->m_indices.push_back(m_edges.at(i).from);
910 i = m_edges.at(i).next;
911 }
while (i != first);
912 m_parent->m_indices.push_back(T(-1));
922 for (
int i = 0; i < m_parent->m_indices.size(); ++i) {
923 if (m_parent->m_indices.at(i) == T(-1)) {
924 if (m_edges.size() != first)
925 m_edges.last().to = m_edges.at(first).from;
926 first = m_edges.size();
928 Q_ASSERT(i + 1 < m_parent->m_indices.size());
930 Edge edge = {
nullptr,
int(m_parent->m_indices.at(i)),
int(m_parent->m_indices.at(i + 1)), -1, -1, 0,
true,
false,
false};
934 if (first != m_edges.size())
935 m_edges.last().to = m_edges.at(first).from;
936 for (
int i = 0; i < m_edges.size(); ++i) {
937 m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp =
938 m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from);
946 const Edge &e1 = m_edges.at(left);
947 const Edge &e2 = m_edges.at(right);
949 const QPodPoint &u1 = m_parent->m_vertices.at((qint32)e1.from);
950 const QPodPoint &u2 = m_parent->m_vertices.at((qint32)e1.to);
951 const QPodPoint &v1 = m_parent->m_vertices.at((qint32)e2.from);
952 const QPodPoint &v2 = m_parent->m_vertices.at((qint32)e2.to);
953 if (qMax(u1
.x, u2
.x) <= qMin(v1
.x, v2
.x))
956 quint64 key = (left > right ? (quint64(right) << 32) | quint64(left) : (quint64(left) << 32) | quint64(right));
957 if (m_processedEdgePairs.contains(key))
959 m_processedEdgePairs.insert(key);
961 Intersection intersection;
962 intersection.leftEdge = left;
963 intersection.rightEdge = right;
964 intersection.intersectionPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(u1, u2, v1, v2);
966 if (!intersection.intersectionPoint.isValid())
969 Q_ASSERT(intersection.intersectionPoint.isOnLine(u1, u2));
970 Q_ASSERT(intersection.intersectionPoint.isOnLine(v1, v2));
972 intersection.vertex = m_parent->m_vertices.size();
973 m_topIntersection.push(intersection);
974 m_parent->m_vertices.add(intersection.intersectionPoint.round());
981 const Edge &leftEdge = m_edges.at(leftEdgeIndex);
982 const Edge &rightEdge = m_edges.at(rightEdgeIndex);
983 const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper());
984 const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower());
985 const QPodPoint &upper = m_parent->m_vertices.at(leftEdge.upper());
986 if (upper
.x < qMin(l
.x, u
.x))
988 if (upper
.x > qMax(l
.x, u
.x))
990 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(upper, l, u);
993 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.lower()), l, u);
1000 QRBTree<
int>::Node *current = m_edgeList.root;
1001 QRBTree<
int>::Node *result =
nullptr;
1003 if (edgeIsLeftOfEdge(edgeIndex, current->data)) {
1004 current = current->left;
1007 current = current->right;
1013template <
typename T>
1016 if (!m_edgeList.root)
1018 QRBTree<
int>::Node *result = after;
1019 QRBTree<
int>::Node *current = (after ? m_edgeList.next(after) : m_edgeList.front(m_edgeList.root));
1021 if (edgeIsLeftOfEdge(edgeIndex, current->data))
1024 current = m_edgeList.next(current);
1029template <
typename T>
1030std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> QTriangulator<T>::ComplexToSimple::bounds(
const QPodPoint &point)
const
1032 QRBTree<
int>::Node *current = m_edgeList.root;
1033 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> result(
nullptr,
nullptr);
1035 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1036 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1037 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1039 result.first = result.second = current;
1042 current = (d < 0 ? current->left : current->right);
1044 if (current ==
nullptr)
1047 current = result.first->left;
1049 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1050 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1051 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1054 result.first = current;
1055 current = current->left;
1057 current = current->right;
1061 current = result.second->right;
1063 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1064 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1065 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1068 result.second = current;
1069 current = current->right;
1071 current = current->left;
1078template <
typename T>
1079std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> QTriangulator<T>::ComplexToSimple::outerBounds(
const QPodPoint &point)
const
1081 QRBTree<
int>::Node *current = m_edgeList.root;
1082 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> result(
nullptr,
nullptr);
1085 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1086 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1087 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1091 result.second = current;
1092 current = current->left;
1094 result.first = current;
1095 current = current->right;
1102 QRBTree<
int>::Node *mid = current;
1104 current = mid->left;
1106 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1107 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1108 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1111 current = current->left;
1113 result.first = current;
1114 current = current->right;
1118 current = mid->right;
1120 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1121 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1122 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1125 current = current->right;
1127 result.second = current;
1128 current = current->left;
1135template <
typename T>
1138 Q_ASSERT(leftmost && rightmost);
1142 const QPodPoint &u = m_parent->m_vertices.at(m_edges.at(leftmost->data).from);
1143 const QPodPoint &v = m_parent->m_vertices.at(m_edges.at(leftmost->data).to);
1145 const Split split = {vertex, leftmost->data, intersectionPoint
.isAccurate()};
1146 if (intersectionPoint.xOffset.numerator != 0 || intersectionPoint.yOffset.numerator != 0 || (intersectionPoint.upperLeft != u && intersectionPoint.upperLeft != v))
1147 m_splits.add(split);
1148 if (leftmost == rightmost)
1150 leftmost = m_edgeList.next(leftmost);
1154template <
typename T>
1157 Q_ASSERT(leftmost && rightmost);
1159 QRBTree<
int>::Node *storeLeftmost = leftmost;
1160 QRBTree<
int>::Node *storeRightmost = rightmost;
1163 while (leftmost != rightmost) {
1164 Edge &left = m_edges.at(leftmost->data);
1165 Edge &right = m_edges.at(rightmost->data);
1166 qSwap(left.node, right.node);
1167 qSwap(leftmost->data, rightmost->data);
1168 leftmost = m_edgeList.next(leftmost);
1169 if (leftmost == rightmost)
1171 rightmost = m_edgeList.previous(rightmost);
1174 rightmost = m_edgeList.next(storeRightmost);
1175 leftmost = m_edgeList.previous(storeLeftmost);
1177 calculateIntersection(leftmost->data, storeLeftmost->data);
1179 calculateIntersection(storeRightmost->data, rightmost->data);
1182template <
typename T>
1185 QIntersectionPoint eventPoint2 = QT_PREPEND_NAMESPACE(qIntersectionPoint)(eventPoint);
1186 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint < eventPoint2) {
1187 Intersection intersection = m_topIntersection.pop();
1190 int currentVertex = intersection.vertex;
1192 QRBTree<
int>::Node *leftmost = m_edges.at(intersection.leftEdge).node;
1193 QRBTree<
int>::Node *rightmost = m_edges.at(intersection.rightEdge).node;
1196 QRBTree<
int>::Node *previous = m_edgeList.previous(leftmost);
1199 const Edge &edge = m_edges.at(previous->data);
1200 const QPodPoint &u = m_parent->m_vertices.at((qint32)edge.from);
1201 const QPodPoint &v = m_parent->m_vertices.at((qint32)edge.to);
1203 Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0);
1206 leftmost = previous;
1210 QRBTree<
int>::Node *next = m_edgeList.next(rightmost);
1213 const Edge &edge = m_edges.at(next->data);
1214 const QPodPoint &u = m_parent->m_vertices.at((qint32)edge.from);
1215 const QPodPoint &v = m_parent->m_vertices.at((qint32)edge.to);
1217 Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0);
1223 Q_ASSERT(leftmost && rightmost);
1224 splitEdgeListRange(leftmost, rightmost, currentVertex, currentIntersectionPoint);
1225 reorderEdgeListRange(leftmost, rightmost);
1227 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= currentIntersectionPoint)
1228 m_topIntersection.pop();
1230#ifdef Q_TRIANGULATOR_DEBUG
1231 DebugDialog dialog(
this, intersection.vertex);
1238template <
typename T>
1242 m_events.reserve(m_edges.size() * 2);
1243 for (
int i = 0; i < m_edges.size(); ++i) {
1244 Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1);
1245 Q_ASSERT(m_edges.at(i).node ==
nullptr);
1246 Q_ASSERT(m_edges.at(i).pointingUp == m_edges.at(i).originallyPointingUp);
1247 Q_ASSERT(m_edges.at(i).pointingUp == (m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from)));
1249 if (m_parent->m_vertices.at(m_edges.at(i).to) != m_parent->m_vertices.at(m_edges.at(i).from)) {
1250 QPodPoint upper = m_parent->m_vertices.at(m_edges.at(i).upper());
1251 QPodPoint lower = m_parent->m_vertices.at(m_edges.at(i).lower());
1252 Event upperEvent = {{upper
.x, upper
.y}, Event::Upper, i};
1253 Event lowerEvent = {{lower
.x, lower
.y}, Event::Lower, i};
1254 m_events.add(upperEvent);
1255 m_events.add(lowerEvent);
1259 std::sort(m_events.data(), m_events.data() + m_events.size());
1262template <
typename T>
1265 fillPriorityQueue();
1267 Q_ASSERT(m_topIntersection.empty());
1268 Q_ASSERT(m_edgeList.root ==
nullptr);
1271 while (!m_events.isEmpty()) {
1272 Event event = m_events.last();
1273 sortEdgeList(event.point);
1276 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> range = bounds(event.point);
1277 QRBTree<
int>::Node *leftNode = range.first ? m_edgeList.previous(range.first) :
nullptr;
1278 int vertex = (event.type == Event::Upper ? m_edges.at(event.edge).upper() : m_edges.at(event.edge).lower());
1279 QIntersectionPoint eventPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(event.point);
1281 if (range.first !=
nullptr) {
1282 splitEdgeListRange(range.first, range.second, vertex, eventPoint);
1283 reorderEdgeListRange(range.first, range.second);
1287 while (!m_events.isEmpty() && m_events.last().point == event.point) {
1288 event = m_events.last();
1289 m_events.pop_back();
1292 if (m_edges.at(i).node) {
1294 Q_ASSERT(event.type == Event::Lower);
1295 QRBTree<
int>::Node *left = m_edgeList.previous(m_edges.at(i).node);
1296 QRBTree<
int>::Node *right = m_edgeList.next(m_edges.at(i).node);
1297 m_edgeList.deleteNode(m_edges.at(i).node);
1298 if (!left || !right)
1300 calculateIntersection(left->data, right->data);
1303 Q_ASSERT(event.type == Event::Upper);
1304 QRBTree<
int>::Node *left = searchEdgeLeftOf(i, leftNode);
1305 m_edgeList.attachAfter(left, m_edges.at(i).node = m_edgeList.newNode());
1306 m_edges.at(i).node->data = i;
1307 QRBTree<
int>::Node *right = m_edgeList.next(m_edges.at(i).node);
1309 calculateIntersection(left->data, i);
1311 calculateIntersection(i, right->data);
1314 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= eventPoint)
1315 m_topIntersection.pop();
1316#ifdef Q_TRIANGULATOR_DEBUG
1317 DebugDialog dialog(
this, vertex);
1321 m_processedEdgePairs.clear();
1328template <
typename T>
1331 const Split &split = m_splits.at(splitIndex);
1332 Edge &lowerEdge = m_edges.at(split.edge);
1333 Q_ASSERT(lowerEdge.node ==
nullptr);
1334 Q_ASSERT(lowerEdge.previous == -1 && lowerEdge.next == -1);
1336 if (lowerEdge.from == split.vertex)
1338 if (lowerEdge.to == split.vertex)
1339 return lowerEdge.next;
1345 Edge upperEdge = lowerEdge;
1346 upperEdge.mayIntersect |= !split.accurate;
1347 lowerEdge.mayIntersect = !split.accurate;
1348 if (lowerEdge.pointingUp) {
1349 lowerEdge.to = upperEdge.from = split.vertex;
1350 m_edges.add(upperEdge);
1351 return m_edges.size() - 1;
1353 lowerEdge.from = upperEdge.to = split.vertex;
1354 m_edges.add(upperEdge);
1359template <
typename T>
1362 for (
int i = 0; i < m_edges.size(); ++i)
1363 m_edges.at(i).mayIntersect =
false;
1364 bool checkForNewIntersections =
false;
1365 for (
int i = 0; i < m_splits.size(); ++i) {
1367 checkForNewIntersections |= !m_splits.at(i).accurate;
1369 for (
int i = 0; i < m_edges.size(); ++i) {
1370 m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp =
1371 m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from);
1374 return checkForNewIntersections;
1377template <
typename T>
1381 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(i).from) != m_parent->m_vertices.at(m_edges.at(i).to));
1384 int windingNumber = m_edges.at(i).winding;
1385 if (m_edges.at(i).originallyPointingUp)
1389 Q_ASSERT(((m_parent->m_hint & QVectorPath::WindingFill) != 0) != ((m_parent->m_hint & QVectorPath::OddEvenFill) != 0));
1391 if ((m_parent->m_hint & QVectorPath::WindingFill) && windingNumber != 0 && windingNumber != 1)
1395 if (!orderedEdges.isEmpty()) {
1396 int j = orderedEdges[orderedEdges.size() - 1];
1398 if (m_edges.at(j).next == -1 && m_edges.at(j).previous == -1
1399 && (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(j).to))
1400 && (m_parent->m_vertices.at(m_edges.at(i).to) == m_parent->m_vertices.at(m_edges.at(j).from))) {
1401 orderedEdges.removeLast();
1405 orderedEdges.append(i);
1408template <
typename T>
1411 Q_ASSERT(m_edgeList.root ==
nullptr);
1413 fillPriorityQueue();
1417 while (!m_events.isEmpty()) {
1418 Event event = m_events.last();
1419 int edgeIndex = event.edge;
1428 orderedEdges.clear();
1429 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> b = outerBounds(event.point);
1430 if (m_edgeList.root) {
1431 QRBTree<
int>::Node *current = (b.first ? m_edgeList.next(b.first) : m_edgeList.front(m_edgeList.root));
1433 while (current != b.second) {
1435 Q_ASSERT(m_edges.at(current->data).node == current);
1436 Q_ASSERT(QT_PREPEND_NAMESPACE(qIntersectionPoint)(event.point).isOnLine(m_parent->m_vertices.at(m_edges.at(current->data).from), m_parent->m_vertices.at(m_edges.at(current->data).to)));
1437 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(current->data).from) == event.point || m_parent->m_vertices.at(m_edges.at(current->data).to) == event.point);
1438 insertEdgeIntoVectorIfWanted(orderedEdges, current->data);
1439 current = m_edgeList.next(current);
1445 event = m_events.last();
1446 m_events.pop_back();
1447 edgeIndex = event.edge;
1450 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(edgeIndex).from) != m_parent->m_vertices.at(m_edges.at(edgeIndex).to));
1452 if (m_edges.at(edgeIndex).node) {
1453 Q_ASSERT(event.type == Event::Lower);
1454 Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).lower()));
1455 m_edgeList.deleteNode(m_edges.at(edgeIndex).node);
1457 Q_ASSERT(event.type == Event::Upper);
1458 Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).upper()));
1459 QRBTree<
int>::Node *left = searchEdgeLeftOf(edgeIndex, b.first);
1460 m_edgeList.attachAfter(left, m_edges.at(edgeIndex).node = m_edgeList.newNode());
1461 m_edges.at(edgeIndex).node->data = edgeIndex;
1463 }
while (!m_events.isEmpty() && m_events.last().point == event.point);
1465 if (m_edgeList.root) {
1466 QRBTree<
int>::Node *current = (b.first ? m_edgeList.next(b.first) : m_edgeList.front(m_edgeList.root));
1469 int currentWindingNumber = (b.first ? m_edges.at(b.first->data).winding : 0);
1470 while (current != b.second) {
1473 int i = current->data;
1474 Q_ASSERT(m_edges.at(i).node == current);
1477 int ccwWindingNumber = m_edges.at(i).winding = currentWindingNumber;
1478 if (m_edges.at(i).originallyPointingUp) {
1479 --m_edges.at(i).winding;
1481 ++m_edges.at(i).winding;
1484 currentWindingNumber = m_edges.at(i).winding;
1487 if ((ccwWindingNumber & 1) == 0) {
1488 Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1);
1489 qSwap(m_edges.at(i).from, m_edges.at(i).to);
1490 m_edges.at(i).pointingUp = !m_edges.at(i).pointingUp;
1493 current = m_edgeList.next(current);
1497 current = (b.second ? m_edgeList.previous(b.second) : m_edgeList.back(m_edgeList.root));
1498 while (current != b.first) {
1500 Q_ASSERT(m_edges.at(current->data).node == current);
1501 insertEdgeIntoVectorIfWanted(orderedEdges, current->data);
1502 current = m_edgeList.previous(current);
1505 if (orderedEdges.isEmpty())
1508 Q_ASSERT((orderedEdges.size() & 1) == 0);
1513 if (m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).from) == event.point) {
1515 int copy = orderedEdges[0];
1516 orderedEdges.append(copy);
1518 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).to) == event.point);
1523 int pointIndex = INT_MAX;
1524 for (
int j = i; j < orderedEdges.size(); j += 2) {
1525 Q_ASSERT(j + 1 < orderedEdges.size());
1526 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j]).to) == event.point);
1527 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j + 1]).from) == event.point);
1528 if (m_edges.at(orderedEdges[j]).to < pointIndex)
1529 pointIndex = m_edges.at(orderedEdges[j]).to;
1530 if (m_edges.at(orderedEdges[j + 1]).from < pointIndex)
1531 pointIndex = m_edges.at(orderedEdges[j + 1]).from;
1534 for (; i < orderedEdges.size(); i += 2) {
1536 m_edges.at(orderedEdges[i]).to = m_edges.at(orderedEdges[i + 1]).from = pointIndex;
1538 Q_ASSERT(m_edges.at(orderedEdges[i]).pointingUp || m_edges.at(orderedEdges[i]).previous != -1);
1539 Q_ASSERT(!m_edges.at(orderedEdges[i + 1]).pointingUp || m_edges.at(orderedEdges[i + 1]).next != -1);
1541 m_edges.at(orderedEdges[i]).next = orderedEdges[i + 1];
1542 m_edges.at(orderedEdges[i + 1]).previous = orderedEdges[i];
1547template <
typename T>
1549 QBitArray used(m_parent->m_vertices.size(),
false);
1550 for (
int i = 0; i < m_edges.size(); ++i) {
1551 Q_ASSERT((m_edges.at(i).previous == -1) == (m_edges.at(i).next == -1));
1552 if (m_edges.at(i).next != -1)
1553 used.setBit(m_edges.at(i).from);
1555 QDataBuffer<quint32> newMapping(m_parent->m_vertices.size());
1556 newMapping.resize(m_parent->m_vertices.size());
1558 for (
int i = 0; i < m_parent->m_vertices.size(); ++i) {
1560 m_parent->m_vertices.at(count) = m_parent->m_vertices.at(i);
1561 newMapping.at(i) = count;
1565 m_parent->m_vertices.resize(count);
1566 for (
int i = 0; i < m_edges.size(); ++i) {
1567 m_edges.at(i).from = newMapping.at(m_edges.at(i).from);
1568 m_edges.at(i).to = newMapping.at(m_edges.at(i).to);
1572template <
typename T>
1575 if (point
== other.point)
1576 return type < other.type;
1577 return other.point
< point;
1584#ifdef Q_TRIANGULATOR_DEBUG
1585template <
typename T>
1586QTriangulator<T>::ComplexToSimple::DebugDialog::DebugDialog(ComplexToSimple *parent,
int currentVertex)
1587 : m_parent(parent), m_vertex(currentVertex)
1589 QDataBuffer<QPodPoint> &vertices = m_parent->m_parent->m_vertices;
1590 if (vertices.isEmpty())
1593 int minX, maxX, minY, maxY;
1594 minX = maxX = vertices.at(0).x;
1595 minY = maxY = vertices.at(0).y;
1596 for (
int i = 1; i < vertices.size(); ++i) {
1597 minX = qMin(minX, vertices.at(i).x);
1598 maxX = qMax(maxX, vertices.at(i).x);
1599 minY = qMin(minY, vertices.at(i).y);
1600 maxY = qMax(maxY, vertices.at(i).y);
1602 int w = maxX - minX;
1603 int h = maxY - minY;
1604 qreal border = qMin(w, h) / 10.0;
1605 m_window = QRectF(minX - border, minY - border, (maxX - minX + 2 * border), (maxY - minY + 2 * border));
1608template <
typename T>
1609void QTriangulator<T>::ComplexToSimple::DebugDialog::paintEvent(QPaintEvent *)
1612 p.setRenderHint(QPainter::Antialiasing,
true);
1613 p.fillRect(rect(), Qt::black);
1614 QDataBuffer<QPodPoint> &vertices = m_parent->m_parent->m_vertices;
1615 if (vertices.isEmpty())
1618 qreal halfPointSize = qMin(m_window.width(), m_window.height()) / 300.0;
1619 p.setWindow(m_window.toRect());
1621 p.setPen(Qt::white);
1623 QDataBuffer<Edge> &edges = m_parent->m_edges;
1624 for (
int i = 0; i < edges.size(); ++i) {
1625 QPodPoint u = vertices.at(edges.at(i).from);
1626 QPodPoint v = vertices.at(edges.at(i).to);
1627 p.drawLine(u.x, u.y, v.x, v.y);
1630 for (
int i = 0; i < vertices.size(); ++i) {
1631 QPodPoint q = vertices.at(i);
1632 p.fillRect(QRectF(q.x - halfPointSize, q.y - halfPointSize, 2 * halfPointSize, 2 * halfPointSize), Qt::red);
1635 Qt::GlobalColor colors[6] = {Qt::red, Qt::green, Qt::blue, Qt::cyan, Qt::magenta, Qt::yellow};
1638 if (m_parent->m_edgeList.root) {
1639 QRBTree<
int>::Node *current = m_parent->m_edgeList.front(m_parent->m_edgeList.root);
1641 p.setPen(colors[count++ % 6]);
1642 QPodPoint u = vertices.at(edges.at(current->data).from);
1643 QPodPoint v = vertices.at(edges.at(current->data).to);
1644 p.drawLine(u.x, u.y, v.x, v.y);
1645 current = m_parent->m_edgeList.next(current);
1650 QPodPoint q = vertices.at(m_vertex);
1651 p.fillRect(QRectF(q.x - halfPointSize, q.y - halfPointSize, 2 * halfPointSize, 2 * halfPointSize), Qt::green);
1654 QDataBuffer<Split> &splits = m_parent->m_splits;
1655 for (
int i = 0; i < splits.size(); ++i) {
1656 QPodPoint q = vertices.at(splits.at(i).vertex);
1657 QPodPoint u = vertices.at(edges.at(splits.at(i).edge).from) - q;
1658 QPodPoint v = vertices.at(edges.at(splits.at(i).edge).to) - q;
1659 qreal uLen = qSqrt(qDot(u, u));
1660 qreal vLen = qSqrt(qDot(v, v));
1662 u.x *= 2 * halfPointSize / uLen;
1663 u.y *= 2 * halfPointSize / uLen;
1666 v.x *= 2 * halfPointSize / vLen;
1667 v.y *= 2 * halfPointSize / vLen;
1671 p.drawLine(u.x, u.y, v.x, v.y);
1675template <
typename T>
1676void QTriangulator<T>::ComplexToSimple::DebugDialog::wheelEvent(QWheelEvent *event)
1678 qreal scale = qExp(-0.001 * event->delta());
1679 QPointF center = m_window.center();
1680 QPointF delta = scale * (m_window.bottomRight() - center);
1681 m_window = QRectF(center - delta, center + delta);
1686template <
typename T>
1687void QTriangulator<T>::ComplexToSimple::DebugDialog::mouseMoveEvent(QMouseEvent *event)
1689 if (event->buttons() & Qt::LeftButton) {
1690 QPointF delta = event->pos() - m_lastMousePos;
1691 delta.setX(delta.x() * m_window.width() / width());
1692 delta.setY(delta.y() * m_window.height() / height());
1693 m_window.translate(-delta.x(), -delta.y());
1694 m_lastMousePos = event->pos();
1700template <
typename T>
1701void QTriangulator<T>::ComplexToSimple::DebugDialog::mousePressEvent(QMouseEvent *event)
1703 if (event->button() == Qt::LeftButton)
1704 m_lastMousePos = event->pos();
1714template <
typename T>
1717 setupDataStructures();
1718 removeZeroLengthEdges();
1719 monotoneDecomposition();
1721 m_parent->m_indices.clear();
1722 QBitArray processed(m_edges.size(),
false);
1723 for (
int first = 0; first < m_edges.size(); ++first) {
1724 if (processed.at(first))
1728 Q_ASSERT(!processed.at(i));
1729 Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i);
1730 m_parent->m_indices.push_back(m_edges.at(i).from);
1731 processed.setBit(i);
1732 i = m_edges.at(i).next;
1733 }
while (i != first);
1734 if (m_parent->m_indices.size() > 0 && m_parent->m_indices.back() != T(-1))
1735 m_parent->m_indices.push_back(T(-1));
1739template <
typename T>
1747 while (i + 3 <= m_parent->m_indices.size()) {
1748 int start = m_edges.size();
1751 e.from = m_parent->m_indices.at(i);
1752 e.type = RegularVertex;
1753 e.next = m_edges.size() + 1;
1754 e.previous = m_edges.size() - 1;
1757 Q_ASSERT(i < m_parent->m_indices.size());
1758 }
while (m_parent->m_indices.at(i) != T(-1));
1760 m_edges.last().next = start;
1761 m_edges.at(start).previous = m_edges.size() - 1;
1765 for (i = 0; i < m_edges.size(); ++i) {
1766 m_edges.at(i).to = m_edges.at(m_edges.at(i).next).from;
1767 m_edges.at(i).pointingUp = m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from);
1768 m_edges.at(i).helper = -1;
1772template <
typename T>
1775 for (
int i = 0; i < m_edges.size(); ++i) {
1776 if (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(i).to)) {
1777 m_edges.at(m_edges.at(i).previous).next = m_edges.at(i).next;
1778 m_edges.at(m_edges.at(i).next).previous = m_edges.at(i).previous;
1779 m_edges.at(m_edges.at(i).next).from = m_edges.at(i).from;
1780 m_edges.at(i).next = -1;
1784 QDataBuffer<
int> newMapping(m_edges.size());
1785 newMapping.resize(m_edges.size());
1787 for (
int i = 0; i < m_edges.size(); ++i) {
1788 if (m_edges.at(i).next != -1) {
1789 m_edges.at(count) = m_edges.at(i);
1790 newMapping.at(i) = count;
1794 m_edges.resize(count);
1795 for (
int i = 0; i < m_edges.size(); ++i) {
1796 m_edges.at(i).next = newMapping.at(m_edges.at(i).next);
1797 m_edges.at(i).previous = newMapping.at(m_edges.at(i).previous);
1801template <
typename T>
1804 m_upperVertex.reset();
1805 m_upperVertex.reserve(m_edges.size());
1806 for (
int i = 0; i < m_edges.size(); ++i)
1807 m_upperVertex.add(i);
1808 CompareVertices cmp(
this);
1809 std::sort(m_upperVertex.data(), m_upperVertex.data() + m_upperVertex.size(), cmp);
1815template <
typename T>
1818 const Edge &leftEdge = m_edges.at(leftEdgeIndex);
1819 const Edge &rightEdge = m_edges.at(rightEdgeIndex);
1820 const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper());
1821 const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower());
1822 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.upper()), l, u);
1825 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.lower()), l, u);
1830template <
typename T>
1833 QRBTree<
int>::Node *current = m_edgeList.root;
1834 QRBTree<
int>::Node *result =
nullptr;
1836 if (edgeIsLeftOfEdge(edgeIndex, current->data)) {
1837 current = current->left;
1840 current = current->right;
1847template <
typename T>
1850 QRBTree<
int>::Node *current = m_edgeList.root;
1851 QRBTree<
int>::Node *result =
nullptr;
1853 const QPodPoint &p1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1854 const QPodPoint &p2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1855 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(pointIndex), p1, p2);
1857 current = current->left;
1860 current = current->right;
1866template <
typename T>
1869 Edge &e2 = m_edges.at(i);
1870 const Edge &e1 = m_edges.at(e2.previous);
1872 bool startOrSplit = (e1.pointingUp && !e2.pointingUp);
1873 bool endOrMerge = (!e1.pointingUp && e2.pointingUp);
1875 const QPodPoint &p1 = m_parent->m_vertices.at(e1.from);
1876 const QPodPoint &p2 = m_parent->m_vertices.at(e2.from);
1877 const QPodPoint &p3 = m_parent->m_vertices.at(e2.to);
1878 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(p1, p2, p3);
1879 Q_ASSERT(d != 0 || (!startOrSplit && !endOrMerge));
1881 e2.type = RegularVertex;
1883 if (m_clockwiseOrder) {
1885 e2.type = (d < 0 ? SplitVertex : StartVertex);
1886 else if (endOrMerge)
1887 e2.type = (d < 0 ? MergeVertex : EndVertex);
1890 e2.type = (d > 0 ? SplitVertex : StartVertex);
1891 else if (endOrMerge)
1892 e2.type = (d > 0 ? MergeVertex : EndVertex);
1896template <
typename T>
1899 for (
int i = 0; i < m_edges.size(); ++i)
1903template <
typename T>
1910 return leftOfPreviousEdge && leftOfNextEdge;
1912 return leftOfPreviousEdge || leftOfNextEdge;
1915template <
typename T>
1918 const QPodPoint ¢er = m_parent->m_vertices.at(m_edges.at(sector).from);
1920 while (m_parent->m_vertices.at(m_edges.at(vertex).from) == center)
1921 vertex = m_edges.at(vertex).next;
1922 int next = m_edges.at(sector).next;
1923 while (m_parent->m_vertices.at(m_edges.at(next).from) == center)
1924 next = m_edges.at(next).next;
1925 int previous = m_edges.at(sector).previous;
1926 while (m_parent->m_vertices.at(m_edges.at(previous).from) == center)
1927 previous = m_edges.at(previous).previous;
1929 const QPodPoint &p = m_parent->m_vertices.at(m_edges.at(vertex).from);
1930 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(previous).from);
1931 const QPodPoint &v3 = m_parent->m_vertices.at(m_edges.at(next).from);
1932 if (m_clockwiseOrder)
1933 return pointIsInSector(p, v3, center, v1);
1935 return pointIsInSector(p, v1, center, v3);
1938template <
typename T>
1941 while (!pointIsInSector(vertex, edge)) {
1942 edge = m_edges.at(m_edges.at(edge).previous).twin;
1943 Q_ASSERT(edge != -1);
1948template <
typename T>
1951 lower = findSector(lower, upper);
1952 upper = findSector(upper, lower);
1954 int prevLower = m_edges.at(lower).previous;
1955 int prevUpper = m_edges.at(upper).previous;
1959 e.twin = m_edges.size() + 1;
1961 e.previous = prevLower;
1962 e.from = m_edges.at(lower).from;
1963 e.to = m_edges.at(upper).from;
1964 m_edges.at(upper).previous = m_edges.at(prevLower).next =
int(m_edges.size());
1967 e.twin = m_edges.size() - 1;
1969 e.previous = prevUpper;
1970 e.from = m_edges.at(upper).from;
1971 e.to = m_edges.at(lower).from;
1972 m_edges.at(lower).previous = m_edges.at(prevUpper).next =
int(m_edges.size());
1976template <
typename T>
1979 if (m_edges.isEmpty())
1982 Q_ASSERT(!m_edgeList.root);
1983 QDataBuffer<std::pair<
int,
int> > diagonals(m_upperVertex.size());
1986 for (
int index = 1; index < m_edges.size(); ++index) {
1987 if (m_parent->m_vertices.at(m_edges.at(index).from) < m_parent->m_vertices.at(m_edges.at(i).from))
1990 Q_ASSERT(i < m_edges.size());
1991 int j = m_edges.at(i).previous;
1992 Q_ASSERT(j < m_edges.size());
1993 m_clockwiseOrder = qPointIsLeftOfLine(m_parent->m_vertices.at((quint32)m_edges.at(i).from),
1994 m_parent->m_vertices.at((quint32)m_edges.at(j).from), m_parent->m_vertices.at((quint32)m_edges.at(i).to));
1997 fillPriorityQueue();
2003 while (!m_upperVertex.isEmpty()) {
2004 i = m_upperVertex.last();
2005 Q_ASSERT(i < m_edges.size());
2006 m_upperVertex.pop_back();
2007 j = m_edges.at(i).previous;
2008 Q_ASSERT(j < m_edges.size());
2010 QRBTree<
int>::Node *leftEdgeNode =
nullptr;
2012 switch (m_edges.at(i).type) {
2015 if (m_edges.at(i).pointingUp == m_clockwiseOrder) {
2016 if (m_edges.at(i).node) {
2017 Q_ASSERT(!m_edges.at(j).node);
2018 if (m_edges.at(m_edges.at(i).helper).type == MergeVertex)
2019 diagonals.add(std::pair<
int,
int>(i, m_edges.at(i).helper));
2020 m_edges.at(j).node = m_edges.at(i).node;
2021 m_edges.at(i).node =
nullptr;
2022 m_edges.at(j).node->data = j;
2023 m_edges.at(j).helper = i;
2024 }
else if (m_edges.at(j).node) {
2025 Q_ASSERT(!m_edges.at(i).node);
2026 if (m_edges.at(m_edges.at(j).helper).type == MergeVertex)
2027 diagonals.add(std::pair<
int,
int>(i, m_edges.at(j).helper));
2028 m_edges.at(i).node = m_edges.at(j).node;
2029 m_edges.at(j).node =
nullptr;
2030 m_edges.at(i).node->data = i;
2031 m_edges.at(i).helper = i;
2033 qWarning(
"Inconsistent polygon. (#1)");
2036 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from);
2038 if (m_edges.at(m_edges.at(leftEdgeNode->data).helper).type == MergeVertex)
2039 diagonals.add(std::pair<
int,
int>(i, m_edges.at(leftEdgeNode->data).helper));
2040 m_edges.at(leftEdgeNode->data).helper = i;
2042 qWarning(
"Inconsistent polygon. (#2)");
2047 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from);
2049 diagonals.add(std::pair<
int,
int>(i, m_edges.at(leftEdgeNode->data).helper));
2050 m_edges.at(leftEdgeNode->data).helper = i;
2052 qWarning(
"Inconsistent polygon. (#3)");
2056 if (m_clockwiseOrder) {
2057 leftEdgeNode = searchEdgeLeftOfEdge(j);
2058 QRBTree<
int>::Node *node = m_edgeList.newNode();
2060 m_edges.at(j).node = node;
2061 m_edges.at(j).helper = i;
2062 m_edgeList.attachAfter(leftEdgeNode, node);
2063 Q_ASSERT(m_edgeList.validate());
2065 leftEdgeNode = searchEdgeLeftOfEdge(i);
2066 QRBTree<
int>::Node *node = m_edgeList.newNode();
2068 m_edges.at(i).node = node;
2069 m_edges.at(i).helper = i;
2070 m_edgeList.attachAfter(leftEdgeNode, node);
2071 Q_ASSERT(m_edgeList.validate());
2075 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from);
2077 if (m_edges.at(m_edges.at(leftEdgeNode->data).helper).type == MergeVertex)
2078 diagonals.add(std::pair<
int,
int>(i, m_edges.at(leftEdgeNode->data).helper));
2079 m_edges.at(leftEdgeNode->data).helper = i;
2081 qWarning(
"Inconsistent polygon. (#4)");
2085 if (m_clockwiseOrder) {
2086 if (m_edges.at(m_edges.at(i).helper).type == MergeVertex)
2087 diagonals.add(std::pair<
int,
int>(i, m_edges.at(i).helper));
2088 if (m_edges.at(i).node) {
2089 m_edgeList.deleteNode(m_edges.at(i).node);
2090 Q_ASSERT(m_edgeList.validate());
2092 qWarning(
"Inconsistent polygon. (#5)");
2095 if (m_edges.at(m_edges.at(j).helper).type == MergeVertex)
2096 diagonals.add(std::pair<
int,
int>(i, m_edges.at(j).helper));
2097 if (m_edges.at(j).node) {
2098 m_edgeList.deleteNode(m_edges.at(j).node);
2099 Q_ASSERT(m_edgeList.validate());
2101 qWarning(
"Inconsistent polygon. (#6)");
2108 for (
int i = 0; i < diagonals.size(); ++i)
2109 createDiagonal(diagonals.at(i).first, diagonals.at(i).second);
2112template <
typename T>
2115 if (m_parent->m_edges.at(i).from == m_parent->m_edges.at(j).from)
2116 return m_parent->m_edges.at(i).type > m_parent->m_edges.at(j).type;
2117 return m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(i).from) >
2118 m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(j).from);
2124template <
typename T>
2128 QDataBuffer<
int> stack(m_parent->m_indices.size());
2131 while (m_first + 3 <= m_parent->m_indices.size()) {
2133 while (m_parent->m_indices.at(m_first + m_length) != T(-1)) {
2135 Q_ASSERT(m_first + m_length < m_parent->m_indices.size());
2138 m_first += m_length + 1;
2143 while (less(next(minimum), minimum))
2144 minimum = next(minimum);
2145 while (less(previous(minimum), minimum))
2146 minimum = previous(minimum);
2150 int left = previous(minimum);
2151 int right = next(minimum);
2152 bool stackIsOnLeftSide;
2153 bool clockwiseOrder = leftOfEdge(minimum, left, right);
2155 if (less(left, right)) {
2157 left = previous(left);
2158 stackIsOnLeftSide =
true;
2161 right = next(right);
2162 stackIsOnLeftSide =
false;
2165 for (
int count = 0; count + 2 < m_length; ++count)
2167 Q_ASSERT(stack.size() >= 2);
2168 if (less(left, right)) {
2169 if (stackIsOnLeftSide ==
false) {
2170 for (
int i = 0; i + 1 < stack.size(); ++i) {
2171 result.push_back(indices(stack.at(i + 1)));
2172 result.push_back(indices(left));
2173 result.push_back(indices(stack.at(i)));
2175 stack.first() = stack.last();
2178 while (stack.size() >= 2 && (clockwiseOrder ^ !leftOfEdge(left, stack.at(stack.size() - 2), stack.last()))) {
2179 result.push_back(indices(stack.at(stack.size() - 2)));
2180 result.push_back(indices(left));
2181 result.push_back(indices(stack.last()));
2186 left = previous(left);
2187 stackIsOnLeftSide =
true;
2189 if (stackIsOnLeftSide ==
true) {
2190 for (
int i = 0; i + 1 < stack.size(); ++i) {
2191 result.push_back(indices(stack.at(i)));
2192 result.push_back(indices(right));
2193 result.push_back(indices(stack.at(i + 1)));
2195 stack.first() = stack.last();
2198 while (stack.size() >= 2 && (clockwiseOrder ^ !leftOfEdge(right, stack.last(), stack.at(stack.size() - 2)))) {
2199 result.push_back(indices(stack.last()));
2200 result.push_back(indices(right));
2201 result.push_back(indices(stack.at(stack.size() - 2)));
2206 right = next(right);
2207 stackIsOnLeftSide =
false;
2211 m_first += m_length + 1;
2213 m_parent->m_indices = result;
2220Q_GUI_EXPORT QTriangleSet qTriangulate(
const qreal *polygon,
2221 int count, uint hint,
const QTransform &matrix,
2222 bool allowUintIndices)
2224 QTriangleSet triangleSet;
2225 if (allowUintIndices) {
2226 QTriangulator<quint32> triangulator;
2227 triangulator.initialize(polygon, count, hint, matrix);
2228 QVertexSet<quint32> vertexSet = triangulator.triangulate();
2229 triangleSet.vertices = vertexSet.vertices;
2230 triangleSet.indices.setDataUint(vertexSet.indices);
2233 QTriangulator<quint16> triangulator;
2234 triangulator.initialize(polygon, count, hint, matrix);
2235 QVertexSet<quint16> vertexSet = triangulator.triangulate();
2236 triangleSet.vertices = vertexSet.vertices;
2237 triangleSet.indices.setDataUshort(vertexSet.indices);
2242Q_GUI_EXPORT QTriangleSet qTriangulate(
const QVectorPath &path,
2243 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2245 QTriangleSet triangleSet;
2249 if (allowUintIndices) {
2250 QTriangulator<quint32> triangulator;
2251 triangulator.initialize(path, matrix, lod);
2252 QVertexSet<quint32> vertexSet = triangulator.triangulate();
2253 triangleSet.vertices = vertexSet.vertices;
2254 triangleSet.indices.setDataUint(vertexSet.indices);
2256 QTriangulator<quint16> triangulator;
2257 triangulator.initialize(path, matrix, lod);
2258 QVertexSet<quint16> vertexSet = triangulator.triangulate();
2259 triangleSet.vertices = vertexSet.vertices;
2260 triangleSet.indices.setDataUshort(vertexSet.indices);
2266 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2269 if (allowUintIndices) {
2270 QTriangulator<quint32> triangulator;
2271 triangulator.initialize(path, matrix, lod);
2272 QVertexSet<quint32> vertexSet = triangulator.triangulate();
2273 triangleSet.vertices = vertexSet.vertices;
2274 triangleSet.indices.setDataUint(vertexSet.indices);
2276 QTriangulator<quint16> triangulator;
2277 triangulator.initialize(path, matrix, lod);
2278 QVertexSet<quint16> vertexSet = triangulator.triangulate();
2279 triangleSet.vertices = vertexSet.vertices;
2280 triangleSet.indices.setDataUshort(vertexSet.indices);
2286 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2289 if (allowUintIndices) {
2290 QTriangulator<quint32> triangulator;
2291 triangulator.initialize(path, matrix, lod);
2292 QVertexSet<quint32> vertexSet = triangulator.polyline();
2293 polyLineSet.vertices = vertexSet.vertices;
2294 polyLineSet.indices.setDataUint(vertexSet.indices);
2296 QTriangulator<quint16> triangulator;
2297 triangulator.initialize(path, matrix, lod);
2298 QVertexSet<quint16> vertexSet = triangulator.polyline();
2299 polyLineSet.vertices = vertexSet.vertices;
2300 polyLineSet.indices.setDataUshort(vertexSet.indices);
2306 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2309 if (allowUintIndices) {
2310 QTriangulator<quint32> triangulator;
2311 triangulator.initialize(path, matrix, lod);
2312 QVertexSet<quint32> vertexSet = triangulator.polyline();
2313 polyLineSet.vertices = vertexSet.vertices;
2314 polyLineSet.indices.setDataUint(vertexSet.indices);
2316 QTriangulator<quint16> triangulator;
2317 triangulator.initialize(path, matrix, lod);
2318 QVertexSet<quint16> vertexSet = triangulator.polyline();
2319 polyLineSet.vertices = vertexSet.vertices;
2320 polyLineSet.indices.setDataUshort(vertexSet.indices);
2327#undef Q_FIXED_POINT_SCALE
bool contains(quint64 key) const
ComplexToSimple(QTriangulator< T > *parent)
MonotoneToTriangles(QTriangulator< T > *parent)
SimpleToMonotone(QTriangulator< T > *parent)
QVarLengthArray< int, 6 > ShortArray
void initialize(const qreal *polygon, int count, uint hint, const QTransform &matrix)
QVertexSet< T > polyline()
void initialize(const QVectorPath &path, const QTransform &matrix, qreal lod)
QVertexSet< T > triangulate()
#define Q_FIXED_POINT_SCALE
static int primeForCount(int count)
static QIntersectionPoint qIntersectionPoint(const QPodPoint &u1, const QPodPoint &u2, const QPodPoint &v1, const QPodPoint &v2)
static int compare(quint64 a, quint64 b)
static QIntersectionPoint qIntersectionPoint(const QPodPoint &point)
static QFraction qFraction(quint64 n, quint64 d)
static qint64 qCross(const QPodPoint &u, const QPodPoint &v)
QPolylineSet qPolyline(const QVectorPath &path, const QTransform &matrix, qreal lod, bool allowUintIndices)
QTriangleSet qTriangulate(const QPainterPath &path, const QTransform &matrix, qreal lod, bool allowUintIndices)
static quint64 gcd(quint64 x, quint64 y)
static int qCompareFractions(quint64 a, quint64 b, quint64 c, quint64 d)
static qint64 qPointDistanceFromLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2)
static bool qPointIsLeftOfLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2)
bool operator<=(const QFraction &other) const
bool operator!=(const QFraction &other) const
bool operator>(const QFraction &other) const
bool operator<(const QFraction &other) const
bool operator>=(const QFraction &other) const
bool operator==(const QFraction &other) const
bool operator<(const QIntersectionPoint &other) const
bool operator>(const QIntersectionPoint &other) const
bool isOnLine(const QPodPoint &u, const QPodPoint &v) const
bool operator>=(const QIntersectionPoint &other) const
bool operator<=(const QIntersectionPoint &other) const
bool operator==(const QIntersectionPoint &other) const
bool operator!=(const QIntersectionPoint &other) const
bool operator>=(const QPodPoint &other) const
QPodPoint & operator+=(const QPodPoint &other)
QPodPoint operator-(const QPodPoint &other) const
QPodPoint operator+(const QPodPoint &other) const
bool operator!=(const QPodPoint &other) const
QPodPoint & operator-=(const QPodPoint &other)
bool operator<=(const QPodPoint &other) const
bool operator>(const QPodPoint &other) const
bool operator<(const QPodPoint &other) const
bool operator==(const QPodPoint &other) const