7#include <QtGui/qevent.h>
8#include <QtGui/qpainter.h>
9#include <QtGui/qpainterpath.h>
10#include <QtGui/private/qbezier_p.h>
11#include <QtGui/private/qdatabuffer_p.h>
12#include <QtCore/qbitarray.h>
13#include <QtCore/qvarlengtharray.h>
14#include <QtCore/qqueue.h>
15#include <QtCore/qglobal.h>
16#include <QtCore/qpoint.h>
17#include <QtCore/qalgorithms.h>
18#include <private/qrbtree_p.h>
24#define Q_FIXED_POINT_SCALE 32
29 inline QVertexSet() { }
30 inline QVertexSet(
const QVertexSet<T> &other) : vertices(other.vertices), indices(other.indices) { }
31 QVertexSet<T> &operator = (
const QVertexSet<T> &other) {vertices = other.vertices; indices = other.indices;
return *
this;}
34 QList<qreal> vertices;
53 inline bool isValid()
const {
return denominator != 0;}
69static inline int compare(quint64 a, quint64 b)
71 return (a > b) - (a < b);
79 const quint64 LIMIT = Q_UINT64_C(0x100000000);
82 if (b < LIMIT && d < LIMIT)
83 return compare(a * d, b * c);
89 quint64 b_div_a = b / a;
90 quint64 d_div_c = d / c;
91 if (b_div_a != d_div_c)
92 return compare(d_div_c, b_div_a);
109 result.numerator = 0;
110 result.denominator = 1;
112 quint64 g = gcd(n, d);
113 result.numerator = n / g;
114 result.denominator = d / g;
121 return qCompareFractions(numerator, denominator, other.numerator, other.denominator) < 0;
126 return numerator == other.numerator && denominator == other.denominator;
159 return qint64(u
.x) * qint64(v
.y) - qint64(u
.y) * qint64(v
.x);
162#ifdef Q_TRIANGULATOR_DEBUG
163static inline qint64 qDot(
const QPodPoint &u,
const QPodPoint &v)
165 return qint64(u.x) * qint64(v.x) + qint64(u.y) * qint64(v.y);
175 return qCross(v2 - v1, p - v1);
180 return QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(p, v1, v2) < 0;
189 inline bool isValid()
const {
return xOffset.isValid() && yOffset.isValid();}
191 inline bool isAccurate()
const {
return xOffset.numerator == 0 && yOffset.numerator == 0;}
218 qint64 d1 = qCross(u, v1 - u1);
219 qint64 d2 = qCross(u, v2 - u1);
220 qint64 det = d2 - d1;
221 qint64 d3 = qCross(v, u1 - v1);
222 qint64 d4 = d3 - det;
225 Q_ASSERT(d4 == qCross(v, u2 - v1));
247 if (d1 >= 0 || d2 <= 0 || d3 <= 0 || d4 >= 0)
258 result.xOffset = qFraction(quint64(-v.x * d1) % quint64(det), quint64(det));
261 result.xOffset = qFraction(quint64(-v.x * d2) % quint64(det), quint64(det));
266 result.yOffset = qFraction(quint64(-v.y * d1) % quint64(det), quint64(det));
269 result.yOffset = qFraction(quint64(-v.y * d2) % quint64(det), quint64(det));
272 Q_ASSERT(result.xOffset.isValid());
273 Q_ASSERT(result.yOffset.isValid());
280 if (2 * xOffset.numerator >= xOffset.denominator)
282 if (2 * yOffset.numerator >= yOffset.denominator)
291 if (yOffset != other.yOffset)
292 return yOffset < other.yOffset;
295 return xOffset < other.xOffset;
300 return upperLeft == other.upperLeft && xOffset == other.xOffset && yOffset == other.yOffset;
309 bool isHorizontal = p.y == 0 && yOffset.numerator == 0;
310 bool isVertical = p.x == 0 && xOffset.numerator == 0;
311 if (isHorizontal && isVertical)
324 if (((q
.x < 0) == (q
.y < 0)) != ((p
.x < 0) == (p
.y < 0)))
330 nx = quint64(-p.x) * xOffset.denominator - xOffset.numerator;
332 nx = quint64(p.x) * xOffset.denominator + xOffset.numerator;
334 ny = quint64(-p.y) * yOffset.denominator - yOffset.numerator;
336 ny = quint64(p.y) * yOffset.denominator + yOffset.numerator;
338 return qFraction(quint64(qAbs(q.x)) * xOffset.denominator, quint64(qAbs(q.y)) * yOffset.denominator) == qFraction(nx, ny);
350 inline int size()
const {
return m_data.size();}
351 inline bool empty()
const {
return m_data.isEmpty();}
352 inline bool isEmpty()
const {
return m_data.isEmpty();}
355 inline const T &
top()
const {
return m_data.first();}
357 static inline int parent(
int i) {
return (i - 1) / 2;}
358 static inline int left(
int i) {
return 2 * i + 1;}
359 static inline int right(
int i) {
return 2 * i + 2;}
361 QDataBuffer<T> m_data;
367 int current = m_data.size();
368 int parent =
QMaxHeap::parent(current);
370 while (current != 0 && m_data.at(parent) < x) {
371 m_data.at(current) = m_data.at(parent);
375 m_data.at(current) = x;
381 T result = m_data.first();
382 T back = m_data.last();
384 if (!m_data.isEmpty()) {
388 int right =
QMaxHeap::right(current);
389 if (left >= m_data.size())
392 if (right < m_data.size() && m_data.at(left) < m_data.at(right))
394 if (m_data.at(greater) < back)
396 m_data.at(current) = m_data.at(greater);
399 m_data.at(current) = back;
410 Q_ASSERT(count >= 0);
413 constexpr auto primeForNumBits = [](
int numBits) ->
int
415 constexpr uchar prime_deltas[] = {
416 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 17, 27, 3,
417 1, 29, 3, 21, 7, 17, 15, 9, 43, 35, 15, 0, 0, 0, 0, 0
420 return (1 << numBits) + prime_deltas[numBits];
425 for (
int i = 0; i < 5; ++i) {
426 int mid = (high + low) / 2;
427 if (uint(count) >= (1u << mid))
432 return primeForNumBits(high);
448 bool rehash(
int capacity);
450 static const quint64 UNUSED;
457const quint64
QInt64Set::UNUSED = quint64(-1);
462 m_array =
new quint64[m_capacity];
468 quint64 *oldArray = m_array;
469 int oldCapacity = m_capacity;
471 m_capacity = capacity;
472 m_array =
new quint64[m_capacity];
474 for (
int i = 0; i < oldCapacity; ++i) {
475 if (oldArray[i] != UNUSED)
484 if (m_count > 3 * m_capacity / 4)
486 int index =
int(key % m_capacity);
487 for (
int i = 0; i < m_capacity; ++i) {
489 if (index >= m_capacity)
491 if (m_array[index] == key)
493 if (m_array[index] == UNUSED) {
495 m_array[index] = key;
499 Q_ASSERT_X(0,
"QInt64Hash<T>::insert",
"Hash set full.");
504 int index =
int(key % m_capacity);
505 for (
int i = 0; i < m_capacity; ++i) {
507 if (index >= m_capacity)
509 if (m_array[index] == key)
511 if (m_array[index] == UNUSED)
519 for (
int i = 0; i < m_capacity; ++i)
536 friend class ComplexToSimple;
546 inline int &upper() {
return pointingUp ? to : from;}
547 inline int &lower() {
return pointingUp ? from : to;}
548 inline int upper()
const {
return pointingUp ? to : from;}
549 inline int lower()
const {
return pointingUp ? from : to;}
551 QRBTree<
int>::Node *node;
556 bool pointingUp, originallyPointingUp;
561 bool operator < (
const Intersection &other)
const {
return other.intersectionPoint < intersectionPoint;}
578 enum Type {Upper, Lower};
579 inline bool operator < (
const Event &other)
const;
586#ifdef Q_TRIANGULATOR_DEBUG
607 bool calculateIntersection(
int left,
int right);
608 bool edgeIsLeftOfEdge(
int leftEdgeIndex,
int rightEdgeIndex)
const;
609 QRBTree<
int>::Node *searchEdgeLeftOf(
int edgeIndex)
const;
610 QRBTree<
int>::Node *searchEdgeLeftOf(
int edgeIndex, QRBTree<
int>::Node *after)
const;
613 void splitEdgeListRange(QRBTree<
int>::Node *leftmost, QRBTree<
int>::Node *rightmost,
int vertex,
const QIntersectionPoint &intersectionPoint);
614 void reorderEdgeListRange(QRBTree<
int>::Node *leftmost, QRBTree<
int>::Node *rightmost);
615 void sortEdgeList(
const QPodPoint eventPoint);
616 void fillPriorityQueue();
617 void calculateIntersections();
618 int splitEdge(
int splitIndex);
619 bool splitEdgesAtIntersections();
620 void insertEdgeIntoVectorIfWanted(
ShortArray &orderedEdges,
int i);
621 void removeUnwantedEdgesAndConnect();
622 void removeUnusedPoints();
625 QDataBuffer<Edge> m_edges;
626 QRBTree<
int> m_edgeList;
627 QDataBuffer<Event> m_events;
628 QDataBuffer<Split> m_splits;
629 QMaxHeap<Intersection> m_topIntersection;
631 int m_initialPointCount;
633#ifdef Q_TRIANGULATOR_DEBUG
640 friend class SimpleToMonotone;
648 enum VertexType {MergeVertex, EndVertex, RegularVertex, StartVertex, SplitVertex};
652 QRBTree<
int>::Node *node;
653 int helper, twin, next, previous;
657 int upper()
const {
return (pointingUp ? to : from);}
658 int lower()
const {
return (pointingUp ? from : to);}
661 friend class CompareVertices;
662 class CompareVertices
666 bool operator () (
int i,
int j)
const;
671 void setupDataStructures();
672 void removeZeroLengthEdges();
673 void fillPriorityQueue();
674 bool edgeIsLeftOfEdge(
int leftEdgeIndex,
int rightEdgeIndex)
const;
676 QRBTree<
int>::Node *searchEdgeLeftOfEdge(
int edgeIndex)
const;
678 QRBTree<
int>::Node *searchEdgeLeftOfPoint(
int pointIndex)
const;
679 void classifyVertex(
int i);
680 void classifyVertices();
682 bool pointIsInSector(
int vertex,
int sector);
683 int findSector(
int edge,
int vertex);
684 void createDiagonal(
int lower,
int upper);
685 void monotoneDecomposition();
688 QRBTree<
int> m_edgeList;
689 QDataBuffer<Edge> m_edges;
690 QDataBuffer<
int> m_upperVertex;
691 bool m_clockwiseOrder;
697 friend class MonotoneToTriangles;
702 : m_parent(parent), m_first(0), m_length(0) { }
705 inline T indices(
int index)
const {
return m_parent->m_indices.at(index + m_first);}
706 inline int next(
int index)
const {
return (index + 1) % m_length;}
707 inline int previous(
int index)
const {
return (index + m_length - 1) % m_length;}
708 inline bool less(
int i,
int j)
const {
return m_parent->m_vertices.at((qint32)indices(i)) < m_parent->m_vertices.at(indices(j));}
709 inline bool leftOfEdge(
int i,
int j,
int k)
const
711 return qPointIsLeftOfLine(m_parent->m_vertices.at((qint32)indices(i)),
712 m_parent->m_vertices.at((qint32)indices(j)), m_parent->m_vertices.at((qint32)indices(k)));
724 void initialize(
const qreal *polygon,
int count, uint hint,
const QTransform &matrix);
726 void initialize(
const QVectorPath &path,
const QTransform &matrix, qreal lod);
728 void initialize(
const QPainterPath &path,
const QTransform &matrix, qreal lod);
733 QDataBuffer<QPodPoint> m_vertices;
745 for (
int i = 0; i < m_vertices.size(); ++i) {
746 Q_ASSERT(qAbs(m_vertices.at(i).x) < (1 << 21));
747 Q_ASSERT(qAbs(m_vertices.at(i).y) < (1 << 21));
750 if (!(m_hint & (QVectorPath::OddEvenFill | QVectorPath::WindingFill)))
751 m_hint |= QVectorPath::OddEvenFill;
753 if (m_hint & QVectorPath::NonConvexShapeMask) {
762 QVertexSet<T> result;
763 result.indices = m_indices;
764 result.vertices.resize(2 * m_vertices.size());
765 for (
int i = 0; i < m_vertices.size(); ++i) {
775 for (
int i = 0; i < m_vertices.size(); ++i) {
776 Q_ASSERT(qAbs(m_vertices.at(i).x) < (1 << 21));
777 Q_ASSERT(qAbs(m_vertices.at(i).y) < (1 << 21));
780 if (!(m_hint & (QVectorPath::OddEvenFill | QVectorPath::WindingFill)))
781 m_hint |= QVectorPath::OddEvenFill;
783 if (m_hint & QVectorPath::NonConvexShapeMask) {
788 QVertexSet<T> result;
789 result.indices = m_indices;
790 result.vertices.resize(2 * m_vertices.size());
791 for (
int i = 0; i < m_vertices.size(); ++i) {
802 m_vertices.resize(count);
803 m_indices.resize(count + 1);
804 for (
int i = 0; i < count; ++i) {
806 matrix.map(polygon[2 * i + 0], polygon[2 * i + 1], &x, &y);
811 m_indices[count] = T(-1);
817 m_hint = path.hints();
819 m_hint &= ~QVectorPath::CurvedShapeMask;
821 const qreal *p = path.points();
822 const QPainterPath::ElementType *e = path.elements();
824 for (
int i = 0; i < path.elementCount(); ++i, ++e, p += 2) {
826 case QPainterPath::MoveToElement:
827 if (!m_indices.isEmpty())
828 m_indices.push_back(T(-1));
830 case QPainterPath::LineToElement:
831 m_indices.push_back(T(m_vertices.size()));
832 m_vertices.resize(m_vertices.size() + 1);
834 matrix.map(p[0], p[1], &x, &y);
838 case QPainterPath::CurveToElement:
841 for (
int i = 0; i < 4; ++i)
842 matrix.map(p[2 * i - 2], p[2 * i - 1], &pts[2 * i + 0], &pts[2 * i + 1]);
843 for (
int i = 0; i < 8; ++i)
845 QBezier bezier = QBezier::fromPoints(QPointF(pts[0], pts[1]), QPointF(pts[2], pts[3]), QPointF(pts[4], pts[5]), QPointF(pts[6], pts[7]));
846 QPolygonF poly = bezier.toPolygon();
848 for (
int j = 1; j < poly.size(); ++j) {
849 m_indices.push_back(T(m_vertices.size()));
850 m_vertices.resize(m_vertices.size() + 1);
860 Q_ASSERT_X(0,
"QTriangulator::triangulate",
"Unexpected element type.");
865 for (
int i = 0; i < path.elementCount(); ++i, p += 2) {
866 m_indices.push_back(T(m_vertices.size()));
867 m_vertices.resize(m_vertices.size() + 1);
869 matrix.map(p[0], p[1], &x, &y);
874 m_indices.push_back(T(-1));
880 initialize(qtVectorPathForPath(path), matrix, lod);
889 m_initialPointCount = m_parent->m_vertices.size();
892 calculateIntersections();
893 }
while (splitEdgesAtIntersections());
895 removeUnwantedEdgesAndConnect();
896 removeUnusedPoints();
898 m_parent->m_indices.clear();
899 QBitArray processed(m_edges.size(),
false);
900 for (
int first = 0; first < m_edges.size(); ++first) {
902 if (processed.at(first) || m_edges.at(first).next == -1)
907 Q_ASSERT(!processed.at(i));
908 Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i);
909 m_parent->m_indices.push_back(m_edges.at(i).from);
911 i = m_edges.at(i).next;
912 }
while (i != first);
913 m_parent->m_indices.push_back(T(-1));
923 for (
int i = 0; i < m_parent->m_indices.size(); ++i) {
924 if (m_parent->m_indices.at(i) == T(-1)) {
925 if (m_edges.size() != first)
926 m_edges.last().to = m_edges.at(first).from;
927 first = m_edges.size();
929 Q_ASSERT(i + 1 < m_parent->m_indices.size());
931 Edge edge = {
nullptr,
int(m_parent->m_indices.at(i)),
int(m_parent->m_indices.at(i + 1)), -1, -1, 0,
true,
false,
false};
935 if (first != m_edges.size())
936 m_edges.last().to = m_edges.at(first).from;
937 for (
int i = 0; i < m_edges.size(); ++i) {
938 m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp =
939 m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from);
947 const Edge &e1 = m_edges.at(left);
948 const Edge &e2 = m_edges.at(right);
950 const QPodPoint &u1 = m_parent->m_vertices.at((qint32)e1.from);
951 const QPodPoint &u2 = m_parent->m_vertices.at((qint32)e1.to);
952 const QPodPoint &v1 = m_parent->m_vertices.at((qint32)e2.from);
953 const QPodPoint &v2 = m_parent->m_vertices.at((qint32)e2.to);
954 if (qMax(u1
.x, u2
.x) <= qMin(v1
.x, v2
.x))
957 quint64 key = (left > right ? (quint64(right) << 32) | quint64(left) : (quint64(left) << 32) | quint64(right));
958 if (m_processedEdgePairs.contains(key))
960 m_processedEdgePairs.insert(key);
962 Intersection intersection;
963 intersection.leftEdge = left;
964 intersection.rightEdge = right;
965 intersection.intersectionPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(u1, u2, v1, v2);
967 if (!intersection.intersectionPoint.isValid())
970 Q_ASSERT(intersection.intersectionPoint.isOnLine(u1, u2));
971 Q_ASSERT(intersection.intersectionPoint.isOnLine(v1, v2));
973 intersection.vertex = m_parent->m_vertices.size();
974 m_topIntersection.push(intersection);
975 m_parent->m_vertices.add(intersection.intersectionPoint.round());
982 const Edge &leftEdge = m_edges.at(leftEdgeIndex);
983 const Edge &rightEdge = m_edges.at(rightEdgeIndex);
984 const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper());
985 const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower());
986 const QPodPoint &upper = m_parent->m_vertices.at(leftEdge.upper());
987 if (upper
.x < qMin(l
.x, u
.x))
989 if (upper
.x > qMax(l
.x, u
.x))
991 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(upper, l, u);
994 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.lower()), l, u);
1001 QRBTree<
int>::Node *current = m_edgeList.root;
1002 QRBTree<
int>::Node *result =
nullptr;
1004 if (edgeIsLeftOfEdge(edgeIndex, current->data)) {
1005 current = current->left;
1008 current = current->right;
1014template <
typename T>
1017 if (!m_edgeList.root)
1019 QRBTree<
int>::Node *result = after;
1020 QRBTree<
int>::Node *current = (after ? m_edgeList.next(after) : m_edgeList.front(m_edgeList.root));
1022 if (edgeIsLeftOfEdge(edgeIndex, current->data))
1025 current = m_edgeList.next(current);
1030template <
typename T>
1031std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> QTriangulator<T>::ComplexToSimple::bounds(
const QPodPoint &point)
const
1033 QRBTree<
int>::Node *current = m_edgeList.root;
1034 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> result(
nullptr,
nullptr);
1036 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1037 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1038 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1040 result.first = result.second = current;
1043 current = (d < 0 ? current->left : current->right);
1045 if (current ==
nullptr)
1048 current = result.first->left;
1050 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1051 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1052 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1055 result.first = current;
1056 current = current->left;
1058 current = current->right;
1062 current = result.second->right;
1064 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1065 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1066 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1069 result.second = current;
1070 current = current->right;
1072 current = current->left;
1079template <
typename T>
1080std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> QTriangulator<T>::ComplexToSimple::outerBounds(
const QPodPoint &point)
const
1082 QRBTree<
int>::Node *current = m_edgeList.root;
1083 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> result(
nullptr,
nullptr);
1086 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1087 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1088 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1092 result.second = current;
1093 current = current->left;
1095 result.first = current;
1096 current = current->right;
1103 QRBTree<
int>::Node *mid = current;
1105 current = mid->left;
1107 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1108 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1109 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1112 current = current->left;
1114 result.first = current;
1115 current = current->right;
1119 current = mid->right;
1121 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1122 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1123 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1126 current = current->right;
1128 result.second = current;
1129 current = current->left;
1136template <
typename T>
1139 Q_ASSERT(leftmost && rightmost);
1143 const QPodPoint &u = m_parent->m_vertices.at(m_edges.at(leftmost->data).from);
1144 const QPodPoint &v = m_parent->m_vertices.at(m_edges.at(leftmost->data).to);
1146 const Split split = {vertex, leftmost->data, intersectionPoint
.isAccurate()};
1147 if (intersectionPoint.xOffset.numerator != 0 || intersectionPoint.yOffset.numerator != 0 || (intersectionPoint.upperLeft != u && intersectionPoint.upperLeft != v))
1148 m_splits.add(split);
1149 if (leftmost == rightmost)
1151 leftmost = m_edgeList.next(leftmost);
1155template <
typename T>
1158 Q_ASSERT(leftmost && rightmost);
1160 QRBTree<
int>::Node *storeLeftmost = leftmost;
1161 QRBTree<
int>::Node *storeRightmost = rightmost;
1164 while (leftmost != rightmost) {
1165 Edge &left = m_edges.at(leftmost->data);
1166 Edge &right = m_edges.at(rightmost->data);
1167 qSwap(left.node, right.node);
1168 qSwap(leftmost->data, rightmost->data);
1169 leftmost = m_edgeList.next(leftmost);
1170 if (leftmost == rightmost)
1172 rightmost = m_edgeList.previous(rightmost);
1175 rightmost = m_edgeList.next(storeRightmost);
1176 leftmost = m_edgeList.previous(storeLeftmost);
1178 calculateIntersection(leftmost->data, storeLeftmost->data);
1180 calculateIntersection(storeRightmost->data, rightmost->data);
1183template <
typename T>
1186 QIntersectionPoint eventPoint2 = QT_PREPEND_NAMESPACE(qIntersectionPoint)(eventPoint);
1187 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint < eventPoint2) {
1188 Intersection intersection = m_topIntersection.pop();
1191 int currentVertex = intersection.vertex;
1193 QRBTree<
int>::Node *leftmost = m_edges.at(intersection.leftEdge).node;
1194 QRBTree<
int>::Node *rightmost = m_edges.at(intersection.rightEdge).node;
1197 QRBTree<
int>::Node *previous = m_edgeList.previous(leftmost);
1200 const Edge &edge = m_edges.at(previous->data);
1201 const QPodPoint &u = m_parent->m_vertices.at((qint32)edge.from);
1202 const QPodPoint &v = m_parent->m_vertices.at((qint32)edge.to);
1204 Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0);
1207 leftmost = previous;
1211 QRBTree<
int>::Node *next = m_edgeList.next(rightmost);
1214 const Edge &edge = m_edges.at(next->data);
1215 const QPodPoint &u = m_parent->m_vertices.at((qint32)edge.from);
1216 const QPodPoint &v = m_parent->m_vertices.at((qint32)edge.to);
1218 Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0);
1224 Q_ASSERT(leftmost && rightmost);
1225 splitEdgeListRange(leftmost, rightmost, currentVertex, currentIntersectionPoint);
1226 reorderEdgeListRange(leftmost, rightmost);
1228 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= currentIntersectionPoint)
1229 m_topIntersection.pop();
1231#ifdef Q_TRIANGULATOR_DEBUG
1232 DebugDialog dialog(
this, intersection.vertex);
1239template <
typename T>
1243 m_events.reserve(m_edges.size() * 2);
1244 for (
int i = 0; i < m_edges.size(); ++i) {
1245 Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1);
1246 Q_ASSERT(m_edges.at(i).node ==
nullptr);
1247 Q_ASSERT(m_edges.at(i).pointingUp == m_edges.at(i).originallyPointingUp);
1248 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)));
1250 if (m_parent->m_vertices.at(m_edges.at(i).to) != m_parent->m_vertices.at(m_edges.at(i).from)) {
1251 QPodPoint upper = m_parent->m_vertices.at(m_edges.at(i).upper());
1252 QPodPoint lower = m_parent->m_vertices.at(m_edges.at(i).lower());
1253 Event upperEvent = {{upper
.x, upper
.y}, Event::Upper, i};
1254 Event lowerEvent = {{lower
.x, lower
.y}, Event::Lower, i};
1255 m_events.add(upperEvent);
1256 m_events.add(lowerEvent);
1260 std::sort(m_events.data(), m_events.data() + m_events.size());
1263template <
typename T>
1266 fillPriorityQueue();
1268 Q_ASSERT(m_topIntersection.empty());
1269 Q_ASSERT(m_edgeList.root ==
nullptr);
1272 while (!m_events.isEmpty()) {
1273 Event event = m_events.last();
1274 sortEdgeList(event.point);
1277 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> range = bounds(event.point);
1278 QRBTree<
int>::Node *leftNode = range.first ? m_edgeList.previous(range.first) :
nullptr;
1279 int vertex = (event.type == Event::Upper ? m_edges.at(event.edge).upper() : m_edges.at(event.edge).lower());
1280 QIntersectionPoint eventPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(event.point);
1282 if (range.first !=
nullptr) {
1283 splitEdgeListRange(range.first, range.second, vertex, eventPoint);
1284 reorderEdgeListRange(range.first, range.second);
1288 while (!m_events.isEmpty() && m_events.last().point == event.point) {
1289 event = m_events.last();
1290 m_events.pop_back();
1293 if (m_edges.at(i).node) {
1295 Q_ASSERT(event.type == Event::Lower);
1296 QRBTree<
int>::Node *left = m_edgeList.previous(m_edges.at(i).node);
1297 QRBTree<
int>::Node *right = m_edgeList.next(m_edges.at(i).node);
1298 m_edgeList.deleteNode(m_edges.at(i).node);
1299 if (!left || !right)
1301 calculateIntersection(left->data, right->data);
1304 Q_ASSERT(event.type == Event::Upper);
1305 QRBTree<
int>::Node *left = searchEdgeLeftOf(i, leftNode);
1306 m_edgeList.attachAfter(left, m_edges.at(i).node = m_edgeList.newNode());
1307 m_edges.at(i).node->data = i;
1308 QRBTree<
int>::Node *right = m_edgeList.next(m_edges.at(i).node);
1310 calculateIntersection(left->data, i);
1312 calculateIntersection(i, right->data);
1315 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= eventPoint)
1316 m_topIntersection.pop();
1317#ifdef Q_TRIANGULATOR_DEBUG
1318 DebugDialog dialog(
this, vertex);
1322 m_processedEdgePairs.clear();
1329template <
typename T>
1332 const Split &split = m_splits.at(splitIndex);
1333 Edge &lowerEdge = m_edges.at(split.edge);
1334 Q_ASSERT(lowerEdge.node ==
nullptr);
1335 Q_ASSERT(lowerEdge.previous == -1 && lowerEdge.next == -1);
1337 if (lowerEdge.from == split.vertex)
1339 if (lowerEdge.to == split.vertex)
1340 return lowerEdge.next;
1346 Edge upperEdge = lowerEdge;
1347 upperEdge.mayIntersect |= !split.accurate;
1348 lowerEdge.mayIntersect = !split.accurate;
1349 if (lowerEdge.pointingUp) {
1350 lowerEdge.to = upperEdge.from = split.vertex;
1351 m_edges.add(upperEdge);
1352 return m_edges.size() - 1;
1354 lowerEdge.from = upperEdge.to = split.vertex;
1355 m_edges.add(upperEdge);
1360template <
typename T>
1363 for (
int i = 0; i < m_edges.size(); ++i)
1364 m_edges.at(i).mayIntersect =
false;
1365 bool checkForNewIntersections =
false;
1366 for (
int i = 0; i < m_splits.size(); ++i) {
1368 checkForNewIntersections |= !m_splits.at(i).accurate;
1370 for (
int i = 0; i < m_edges.size(); ++i) {
1371 m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp =
1372 m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from);
1375 return checkForNewIntersections;
1378template <
typename T>
1382 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(i).from) != m_parent->m_vertices.at(m_edges.at(i).to));
1385 int windingNumber = m_edges.at(i).winding;
1386 if (m_edges.at(i).originallyPointingUp)
1390 Q_ASSERT(((m_parent->m_hint & QVectorPath::WindingFill) != 0) != ((m_parent->m_hint & QVectorPath::OddEvenFill) != 0));
1392 if ((m_parent->m_hint & QVectorPath::WindingFill) && windingNumber != 0 && windingNumber != 1)
1396 if (!orderedEdges.isEmpty()) {
1397 int j = orderedEdges[orderedEdges.size() - 1];
1399 if (m_edges.at(j).next == -1 && m_edges.at(j).previous == -1
1400 && (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(j).to))
1401 && (m_parent->m_vertices.at(m_edges.at(i).to) == m_parent->m_vertices.at(m_edges.at(j).from))) {
1402 orderedEdges.removeLast();
1406 orderedEdges.append(i);
1409template <
typename T>
1412 Q_ASSERT(m_edgeList.root ==
nullptr);
1414 fillPriorityQueue();
1418 while (!m_events.isEmpty()) {
1419 Event event = m_events.last();
1420 int edgeIndex = event.edge;
1429 orderedEdges.clear();
1430 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> b = outerBounds(event.point);
1431 if (m_edgeList.root) {
1432 QRBTree<
int>::Node *current = (b.first ? m_edgeList.next(b.first) : m_edgeList.front(m_edgeList.root));
1434 while (current != b.second) {
1436 Q_ASSERT(m_edges.at(current->data).node == current);
1437 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)));
1438 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);
1439 insertEdgeIntoVectorIfWanted(orderedEdges, current->data);
1440 current = m_edgeList.next(current);
1446 event = m_events.last();
1447 m_events.pop_back();
1448 edgeIndex = event.edge;
1451 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(edgeIndex).from) != m_parent->m_vertices.at(m_edges.at(edgeIndex).to));
1453 if (m_edges.at(edgeIndex).node) {
1454 Q_ASSERT(event.type == Event::Lower);
1455 Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).lower()));
1456 m_edgeList.deleteNode(m_edges.at(edgeIndex).node);
1458 Q_ASSERT(event.type == Event::Upper);
1459 Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).upper()));
1460 QRBTree<
int>::Node *left = searchEdgeLeftOf(edgeIndex, b.first);
1461 m_edgeList.attachAfter(left, m_edges.at(edgeIndex).node = m_edgeList.newNode());
1462 m_edges.at(edgeIndex).node->data = edgeIndex;
1464 }
while (!m_events.isEmpty() && m_events.last().point == event.point);
1466 if (m_edgeList.root) {
1467 QRBTree<
int>::Node *current = (b.first ? m_edgeList.next(b.first) : m_edgeList.front(m_edgeList.root));
1470 int currentWindingNumber = (b.first ? m_edges.at(b.first->data).winding : 0);
1471 while (current != b.second) {
1474 int i = current->data;
1475 Q_ASSERT(m_edges.at(i).node == current);
1478 int ccwWindingNumber = m_edges.at(i).winding = currentWindingNumber;
1479 if (m_edges.at(i).originallyPointingUp) {
1480 --m_edges.at(i).winding;
1482 ++m_edges.at(i).winding;
1485 currentWindingNumber = m_edges.at(i).winding;
1488 if ((ccwWindingNumber & 1) == 0) {
1489 Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1);
1490 qSwap(m_edges.at(i).from, m_edges.at(i).to);
1491 m_edges.at(i).pointingUp = !m_edges.at(i).pointingUp;
1494 current = m_edgeList.next(current);
1498 current = (b.second ? m_edgeList.previous(b.second) : m_edgeList.back(m_edgeList.root));
1499 while (current != b.first) {
1501 Q_ASSERT(m_edges.at(current->data).node == current);
1502 insertEdgeIntoVectorIfWanted(orderedEdges, current->data);
1503 current = m_edgeList.previous(current);
1506 if (orderedEdges.isEmpty())
1509 Q_ASSERT((orderedEdges.size() & 1) == 0);
1514 if (m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).from) == event.point) {
1516 int copy = orderedEdges[0];
1517 orderedEdges.append(copy);
1519 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).to) == event.point);
1524 int pointIndex = INT_MAX;
1525 for (
int j = i; j < orderedEdges.size(); j += 2) {
1526 Q_ASSERT(j + 1 < orderedEdges.size());
1527 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j]).to) == event.point);
1528 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j + 1]).from) == event.point);
1529 if (m_edges.at(orderedEdges[j]).to < pointIndex)
1530 pointIndex = m_edges.at(orderedEdges[j]).to;
1531 if (m_edges.at(orderedEdges[j + 1]).from < pointIndex)
1532 pointIndex = m_edges.at(orderedEdges[j + 1]).from;
1535 for (; i < orderedEdges.size(); i += 2) {
1537 m_edges.at(orderedEdges[i]).to = m_edges.at(orderedEdges[i + 1]).from = pointIndex;
1539 Q_ASSERT(m_edges.at(orderedEdges[i]).pointingUp || m_edges.at(orderedEdges[i]).previous != -1);
1540 Q_ASSERT(!m_edges.at(orderedEdges[i + 1]).pointingUp || m_edges.at(orderedEdges[i + 1]).next != -1);
1542 m_edges.at(orderedEdges[i]).next = orderedEdges[i + 1];
1543 m_edges.at(orderedEdges[i + 1]).previous = orderedEdges[i];
1548template <
typename T>
1550 QBitArray used(m_parent->m_vertices.size(),
false);
1551 for (
int i = 0; i < m_edges.size(); ++i) {
1552 Q_ASSERT((m_edges.at(i).previous == -1) == (m_edges.at(i).next == -1));
1553 if (m_edges.at(i).next != -1)
1554 used.setBit(m_edges.at(i).from);
1556 QDataBuffer<quint32> newMapping(m_parent->m_vertices.size());
1557 newMapping.resize(m_parent->m_vertices.size());
1559 for (
int i = 0; i < m_parent->m_vertices.size(); ++i) {
1561 m_parent->m_vertices.at(count) = m_parent->m_vertices.at(i);
1562 newMapping.at(i) = count;
1566 m_parent->m_vertices.resize(count);
1567 for (
int i = 0; i < m_edges.size(); ++i) {
1568 m_edges.at(i).from = newMapping.at(m_edges.at(i).from);
1569 m_edges.at(i).to = newMapping.at(m_edges.at(i).to);
1573template <
typename T>
1576 if (point
== other.point)
1577 return type < other.type;
1578 return other.point
< point;
1585#ifdef Q_TRIANGULATOR_DEBUG
1586template <
typename T>
1587QTriangulator<T>::ComplexToSimple::DebugDialog::DebugDialog(ComplexToSimple *parent,
int currentVertex)
1588 : m_parent(parent), m_vertex(currentVertex)
1590 QDataBuffer<QPodPoint> &vertices = m_parent->m_parent->m_vertices;
1591 if (vertices.isEmpty())
1594 int minX, maxX, minY, maxY;
1595 minX = maxX = vertices.at(0).x;
1596 minY = maxY = vertices.at(0).y;
1597 for (
int i = 1; i < vertices.size(); ++i) {
1598 minX = qMin(minX, vertices.at(i).x);
1599 maxX = qMax(maxX, vertices.at(i).x);
1600 minY = qMin(minY, vertices.at(i).y);
1601 maxY = qMax(maxY, vertices.at(i).y);
1603 int w = maxX - minX;
1604 int h = maxY - minY;
1605 qreal border = qMin(w, h) / 10.0;
1606 m_window = QRectF(minX - border, minY - border, (maxX - minX + 2 * border), (maxY - minY + 2 * border));
1609template <
typename T>
1610void QTriangulator<T>::ComplexToSimple::DebugDialog::paintEvent(QPaintEvent *)
1613 p.setRenderHint(QPainter::Antialiasing,
true);
1614 p.fillRect(rect(), Qt::black);
1615 QDataBuffer<QPodPoint> &vertices = m_parent->m_parent->m_vertices;
1616 if (vertices.isEmpty())
1619 qreal halfPointSize = qMin(m_window.width(), m_window.height()) / 300.0;
1620 p.setWindow(m_window.toRect());
1622 p.setPen(Qt::white);
1624 QDataBuffer<Edge> &edges = m_parent->m_edges;
1625 for (
int i = 0; i < edges.size(); ++i) {
1626 QPodPoint u = vertices.at(edges.at(i).from);
1627 QPodPoint v = vertices.at(edges.at(i).to);
1628 p.drawLine(u.x, u.y, v.x, v.y);
1631 for (
int i = 0; i < vertices.size(); ++i) {
1632 QPodPoint q = vertices.at(i);
1633 p.fillRect(QRectF(q.x - halfPointSize, q.y - halfPointSize, 2 * halfPointSize, 2 * halfPointSize), Qt::red);
1636 Qt::GlobalColor colors[6] = {Qt::red, Qt::green, Qt::blue, Qt::cyan, Qt::magenta, Qt::yellow};
1639 if (m_parent->m_edgeList.root) {
1640 QRBTree<
int>::Node *current = m_parent->m_edgeList.front(m_parent->m_edgeList.root);
1642 p.setPen(colors[count++ % 6]);
1643 QPodPoint u = vertices.at(edges.at(current->data).from);
1644 QPodPoint v = vertices.at(edges.at(current->data).to);
1645 p.drawLine(u.x, u.y, v.x, v.y);
1646 current = m_parent->m_edgeList.next(current);
1651 QPodPoint q = vertices.at(m_vertex);
1652 p.fillRect(QRectF(q.x - halfPointSize, q.y - halfPointSize, 2 * halfPointSize, 2 * halfPointSize), Qt::green);
1655 QDataBuffer<Split> &splits = m_parent->m_splits;
1656 for (
int i = 0; i < splits.size(); ++i) {
1657 QPodPoint q = vertices.at(splits.at(i).vertex);
1658 QPodPoint u = vertices.at(edges.at(splits.at(i).edge).from) - q;
1659 QPodPoint v = vertices.at(edges.at(splits.at(i).edge).to) - q;
1660 qreal uLen = qSqrt(qDot(u, u));
1661 qreal vLen = qSqrt(qDot(v, v));
1663 u.x *= 2 * halfPointSize / uLen;
1664 u.y *= 2 * halfPointSize / uLen;
1667 v.x *= 2 * halfPointSize / vLen;
1668 v.y *= 2 * halfPointSize / vLen;
1672 p.drawLine(u.x, u.y, v.x, v.y);
1676template <
typename T>
1677void QTriangulator<T>::ComplexToSimple::DebugDialog::wheelEvent(QWheelEvent *event)
1679 qreal scale = qExp(-0.001 * event->delta());
1680 QPointF center = m_window.center();
1681 QPointF delta = scale * (m_window.bottomRight() - center);
1682 m_window = QRectF(center - delta, center + delta);
1687template <
typename T>
1688void QTriangulator<T>::ComplexToSimple::DebugDialog::mouseMoveEvent(QMouseEvent *event)
1690 if (event->buttons() & Qt::LeftButton) {
1691 QPointF delta = event->pos() - m_lastMousePos;
1692 delta.setX(delta.x() * m_window.width() / width());
1693 delta.setY(delta.y() * m_window.height() / height());
1694 m_window.translate(-delta.x(), -delta.y());
1695 m_lastMousePos = event->pos();
1701template <
typename T>
1702void QTriangulator<T>::ComplexToSimple::DebugDialog::mousePressEvent(QMouseEvent *event)
1704 if (event->button() == Qt::LeftButton)
1705 m_lastMousePos = event->pos();
1715template <
typename T>
1718 setupDataStructures();
1719 removeZeroLengthEdges();
1720 monotoneDecomposition();
1722 m_parent->m_indices.clear();
1723 QBitArray processed(m_edges.size(),
false);
1724 for (
int first = 0; first < m_edges.size(); ++first) {
1725 if (processed.at(first))
1729 Q_ASSERT(!processed.at(i));
1730 Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i);
1731 m_parent->m_indices.push_back(m_edges.at(i).from);
1732 processed.setBit(i);
1733 i = m_edges.at(i).next;
1734 }
while (i != first);
1735 if (m_parent->m_indices.size() > 0 && m_parent->m_indices.back() != T(-1))
1736 m_parent->m_indices.push_back(T(-1));
1740template <
typename T>
1748 while (i + 3 <= m_parent->m_indices.size()) {
1749 int start = m_edges.size();
1752 e.from = m_parent->m_indices.at(i);
1753 e.type = RegularVertex;
1754 e.next = m_edges.size() + 1;
1755 e.previous = m_edges.size() - 1;
1758 Q_ASSERT(i < m_parent->m_indices.size());
1759 }
while (m_parent->m_indices.at(i) != T(-1));
1761 m_edges.last().next = start;
1762 m_edges.at(start).previous = m_edges.size() - 1;
1766 for (i = 0; i < m_edges.size(); ++i) {
1767 m_edges.at(i).to = m_edges.at(m_edges.at(i).next).from;
1768 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);
1769 m_edges.at(i).helper = -1;
1773template <
typename T>
1776 for (
int i = 0; i < m_edges.size(); ++i) {
1777 if (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(i).to)) {
1778 m_edges.at(m_edges.at(i).previous).next = m_edges.at(i).next;
1779 m_edges.at(m_edges.at(i).next).previous = m_edges.at(i).previous;
1780 m_edges.at(m_edges.at(i).next).from = m_edges.at(i).from;
1781 m_edges.at(i).next = -1;
1785 QDataBuffer<
int> newMapping(m_edges.size());
1786 newMapping.resize(m_edges.size());
1788 for (
int i = 0; i < m_edges.size(); ++i) {
1789 if (m_edges.at(i).next != -1) {
1790 m_edges.at(count) = m_edges.at(i);
1791 newMapping.at(i) = count;
1795 m_edges.resize(count);
1796 for (
int i = 0; i < m_edges.size(); ++i) {
1797 m_edges.at(i).next = newMapping.at(m_edges.at(i).next);
1798 m_edges.at(i).previous = newMapping.at(m_edges.at(i).previous);
1802template <
typename T>
1805 m_upperVertex.reset();
1806 m_upperVertex.reserve(m_edges.size());
1807 for (
int i = 0; i < m_edges.size(); ++i)
1808 m_upperVertex.add(i);
1809 CompareVertices cmp(
this);
1810 std::sort(m_upperVertex.data(), m_upperVertex.data() + m_upperVertex.size(), cmp);
1816template <
typename T>
1819 const Edge &leftEdge = m_edges.at(leftEdgeIndex);
1820 const Edge &rightEdge = m_edges.at(rightEdgeIndex);
1821 const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper());
1822 const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower());
1823 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.upper()), l, u);
1826 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.lower()), l, u);
1831template <
typename T>
1834 QRBTree<
int>::Node *current = m_edgeList.root;
1835 QRBTree<
int>::Node *result =
nullptr;
1837 if (edgeIsLeftOfEdge(edgeIndex, current->data)) {
1838 current = current->left;
1841 current = current->right;
1848template <
typename T>
1851 QRBTree<
int>::Node *current = m_edgeList.root;
1852 QRBTree<
int>::Node *result =
nullptr;
1854 const QPodPoint &p1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1855 const QPodPoint &p2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1856 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(pointIndex), p1, p2);
1858 current = current->left;
1861 current = current->right;
1867template <
typename T>
1870 Edge &e2 = m_edges.at(i);
1871 const Edge &e1 = m_edges.at(e2.previous);
1873 bool startOrSplit = (e1.pointingUp && !e2.pointingUp);
1874 bool endOrMerge = (!e1.pointingUp && e2.pointingUp);
1876 const QPodPoint &p1 = m_parent->m_vertices.at(e1.from);
1877 const QPodPoint &p2 = m_parent->m_vertices.at(e2.from);
1878 const QPodPoint &p3 = m_parent->m_vertices.at(e2.to);
1879 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(p1, p2, p3);
1880 Q_ASSERT(d != 0 || (!startOrSplit && !endOrMerge));
1882 e2.type = RegularVertex;
1884 if (m_clockwiseOrder) {
1886 e2.type = (d < 0 ? SplitVertex : StartVertex);
1887 else if (endOrMerge)
1888 e2.type = (d < 0 ? MergeVertex : EndVertex);
1891 e2.type = (d > 0 ? SplitVertex : StartVertex);
1892 else if (endOrMerge)
1893 e2.type = (d > 0 ? MergeVertex : EndVertex);
1897template <
typename T>
1900 for (
int i = 0; i < m_edges.size(); ++i)
1904template <
typename T>
1911 return leftOfPreviousEdge && leftOfNextEdge;
1913 return leftOfPreviousEdge || leftOfNextEdge;
1916template <
typename T>
1919 const QPodPoint ¢er = m_parent->m_vertices.at(m_edges.at(sector).from);
1921 while (m_parent->m_vertices.at(m_edges.at(vertex).from) == center)
1922 vertex = m_edges.at(vertex).next;
1923 int next = m_edges.at(sector).next;
1924 while (m_parent->m_vertices.at(m_edges.at(next).from) == center)
1925 next = m_edges.at(next).next;
1926 int previous = m_edges.at(sector).previous;
1927 while (m_parent->m_vertices.at(m_edges.at(previous).from) == center)
1928 previous = m_edges.at(previous).previous;
1930 const QPodPoint &p = m_parent->m_vertices.at(m_edges.at(vertex).from);
1931 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(previous).from);
1932 const QPodPoint &v3 = m_parent->m_vertices.at(m_edges.at(next).from);
1933 if (m_clockwiseOrder)
1934 return pointIsInSector(p, v3, center, v1);
1936 return pointIsInSector(p, v1, center, v3);
1939template <
typename T>
1942 while (!pointIsInSector(vertex, edge)) {
1943 edge = m_edges.at(m_edges.at(edge).previous).twin;
1944 Q_ASSERT(edge != -1);
1949template <
typename T>
1952 lower = findSector(lower, upper);
1953 upper = findSector(upper, lower);
1955 int prevLower = m_edges.at(lower).previous;
1956 int prevUpper = m_edges.at(upper).previous;
1960 e.twin = m_edges.size() + 1;
1962 e.previous = prevLower;
1963 e.from = m_edges.at(lower).from;
1964 e.to = m_edges.at(upper).from;
1965 m_edges.at(upper).previous = m_edges.at(prevLower).next =
int(m_edges.size());
1968 e.twin = m_edges.size() - 1;
1970 e.previous = prevUpper;
1971 e.from = m_edges.at(upper).from;
1972 e.to = m_edges.at(lower).from;
1973 m_edges.at(lower).previous = m_edges.at(prevUpper).next =
int(m_edges.size());
1977template <
typename T>
1980 if (m_edges.isEmpty())
1983 Q_ASSERT(!m_edgeList.root);
1984 QDataBuffer<std::pair<
int,
int> > diagonals(m_upperVertex.size());
1987 for (
int index = 1; index < m_edges.size(); ++index) {
1988 if (m_parent->m_vertices.at(m_edges.at(index).from) < m_parent->m_vertices.at(m_edges.at(i).from))
1991 Q_ASSERT(i < m_edges.size());
1992 int j = m_edges.at(i).previous;
1993 Q_ASSERT(j < m_edges.size());
1994 m_clockwiseOrder = qPointIsLeftOfLine(m_parent->m_vertices.at((quint32)m_edges.at(i).from),
1995 m_parent->m_vertices.at((quint32)m_edges.at(j).from), m_parent->m_vertices.at((quint32)m_edges.at(i).to));
1998 fillPriorityQueue();
2004 while (!m_upperVertex.isEmpty()) {
2005 i = m_upperVertex.last();
2006 Q_ASSERT(i < m_edges.size());
2007 m_upperVertex.pop_back();
2008 j = m_edges.at(i).previous;
2009 Q_ASSERT(j < m_edges.size());
2011 QRBTree<
int>::Node *leftEdgeNode =
nullptr;
2013 switch (m_edges.at(i).type) {
2016 if (m_edges.at(i).pointingUp == m_clockwiseOrder) {
2017 if (m_edges.at(i).node) {
2018 Q_ASSERT(!m_edges.at(j).node);
2019 if (m_edges.at(m_edges.at(i).helper).type == MergeVertex)
2020 diagonals.add(std::pair<
int,
int>(i, m_edges.at(i).helper));
2021 m_edges.at(j).node = m_edges.at(i).node;
2022 m_edges.at(i).node =
nullptr;
2023 m_edges.at(j).node->data = j;
2024 m_edges.at(j).helper = i;
2025 }
else if (m_edges.at(j).node) {
2026 Q_ASSERT(!m_edges.at(i).node);
2027 if (m_edges.at(m_edges.at(j).helper).type == MergeVertex)
2028 diagonals.add(std::pair<
int,
int>(i, m_edges.at(j).helper));
2029 m_edges.at(i).node = m_edges.at(j).node;
2030 m_edges.at(j).node =
nullptr;
2031 m_edges.at(i).node->data = i;
2032 m_edges.at(i).helper = i;
2034 qWarning(
"Inconsistent polygon. (#1)");
2037 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from);
2039 if (m_edges.at(m_edges.at(leftEdgeNode->data).helper).type == MergeVertex)
2040 diagonals.add(std::pair<
int,
int>(i, m_edges.at(leftEdgeNode->data).helper));
2041 m_edges.at(leftEdgeNode->data).helper = i;
2043 qWarning(
"Inconsistent polygon. (#2)");
2048 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from);
2050 diagonals.add(std::pair<
int,
int>(i, m_edges.at(leftEdgeNode->data).helper));
2051 m_edges.at(leftEdgeNode->data).helper = i;
2053 qWarning(
"Inconsistent polygon. (#3)");
2057 if (m_clockwiseOrder) {
2058 leftEdgeNode = searchEdgeLeftOfEdge(j);
2059 QRBTree<
int>::Node *node = m_edgeList.newNode();
2061 m_edges.at(j).node = node;
2062 m_edges.at(j).helper = i;
2063 m_edgeList.attachAfter(leftEdgeNode, node);
2064 Q_ASSERT(m_edgeList.validate());
2066 leftEdgeNode = searchEdgeLeftOfEdge(i);
2067 QRBTree<
int>::Node *node = m_edgeList.newNode();
2069 m_edges.at(i).node = node;
2070 m_edges.at(i).helper = i;
2071 m_edgeList.attachAfter(leftEdgeNode, node);
2072 Q_ASSERT(m_edgeList.validate());
2076 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from);
2078 if (m_edges.at(m_edges.at(leftEdgeNode->data).helper).type == MergeVertex)
2079 diagonals.add(std::pair<
int,
int>(i, m_edges.at(leftEdgeNode->data).helper));
2080 m_edges.at(leftEdgeNode->data).helper = i;
2082 qWarning(
"Inconsistent polygon. (#4)");
2086 if (m_clockwiseOrder) {
2087 if (m_edges.at(m_edges.at(i).helper).type == MergeVertex)
2088 diagonals.add(std::pair<
int,
int>(i, m_edges.at(i).helper));
2089 if (m_edges.at(i).node) {
2090 m_edgeList.deleteNode(m_edges.at(i).node);
2091 Q_ASSERT(m_edgeList.validate());
2093 qWarning(
"Inconsistent polygon. (#5)");
2096 if (m_edges.at(m_edges.at(j).helper).type == MergeVertex)
2097 diagonals.add(std::pair<
int,
int>(i, m_edges.at(j).helper));
2098 if (m_edges.at(j).node) {
2099 m_edgeList.deleteNode(m_edges.at(j).node);
2100 Q_ASSERT(m_edgeList.validate());
2102 qWarning(
"Inconsistent polygon. (#6)");
2109 for (
int i = 0; i < diagonals.size(); ++i)
2110 createDiagonal(diagonals.at(i).first, diagonals.at(i).second);
2113template <
typename T>
2116 if (m_parent->m_edges.at(i).from == m_parent->m_edges.at(j).from)
2117 return m_parent->m_edges.at(i).type > m_parent->m_edges.at(j).type;
2118 return m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(i).from) >
2119 m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(j).from);
2125template <
typename T>
2129 QDataBuffer<
int> stack(m_parent->m_indices.size());
2132 while (m_first + 3 <= m_parent->m_indices.size()) {
2134 while (m_parent->m_indices.at(m_first + m_length) != T(-1)) {
2136 Q_ASSERT(m_first + m_length < m_parent->m_indices.size());
2139 m_first += m_length + 1;
2144 while (less(next(minimum), minimum))
2145 minimum = next(minimum);
2146 while (less(previous(minimum), minimum))
2147 minimum = previous(minimum);
2151 int left = previous(minimum);
2152 int right = next(minimum);
2153 bool stackIsOnLeftSide;
2154 bool clockwiseOrder = leftOfEdge(minimum, left, right);
2156 if (less(left, right)) {
2158 left = previous(left);
2159 stackIsOnLeftSide =
true;
2162 right = next(right);
2163 stackIsOnLeftSide =
false;
2166 for (
int count = 0; count + 2 < m_length; ++count)
2168 Q_ASSERT(stack.size() >= 2);
2169 if (less(left, right)) {
2170 if (stackIsOnLeftSide ==
false) {
2171 for (
int i = 0; i + 1 < stack.size(); ++i) {
2172 result.push_back(indices(stack.at(i + 1)));
2173 result.push_back(indices(left));
2174 result.push_back(indices(stack.at(i)));
2176 stack.first() = stack.last();
2179 while (stack.size() >= 2 && (clockwiseOrder ^ !leftOfEdge(left, stack.at(stack.size() - 2), stack.last()))) {
2180 result.push_back(indices(stack.at(stack.size() - 2)));
2181 result.push_back(indices(left));
2182 result.push_back(indices(stack.last()));
2187 left = previous(left);
2188 stackIsOnLeftSide =
true;
2190 if (stackIsOnLeftSide ==
true) {
2191 for (
int i = 0; i + 1 < stack.size(); ++i) {
2192 result.push_back(indices(stack.at(i)));
2193 result.push_back(indices(right));
2194 result.push_back(indices(stack.at(i + 1)));
2196 stack.first() = stack.last();
2199 while (stack.size() >= 2 && (clockwiseOrder ^ !leftOfEdge(right, stack.last(), stack.at(stack.size() - 2)))) {
2200 result.push_back(indices(stack.last()));
2201 result.push_back(indices(right));
2202 result.push_back(indices(stack.at(stack.size() - 2)));
2207 right = next(right);
2208 stackIsOnLeftSide =
false;
2212 m_first += m_length + 1;
2214 m_parent->m_indices = result;
2221Q_GUI_EXPORT QTriangleSet qTriangulate(
const qreal *polygon,
2222 int count, uint hint,
const QTransform &matrix,
2223 bool allowUintIndices)
2225 QTriangleSet triangleSet;
2226 if (allowUintIndices) {
2227 QTriangulator<quint32> triangulator;
2228 triangulator.initialize(polygon, count, hint, matrix);
2229 QVertexSet<quint32> vertexSet = triangulator.triangulate();
2230 triangleSet.vertices = vertexSet.vertices;
2231 triangleSet.indices.setDataUint(vertexSet.indices);
2234 QTriangulator<quint16> triangulator;
2235 triangulator.initialize(polygon, count, hint, matrix);
2236 QVertexSet<quint16> vertexSet = triangulator.triangulate();
2237 triangleSet.vertices = vertexSet.vertices;
2238 triangleSet.indices.setDataUshort(vertexSet.indices);
2243Q_GUI_EXPORT QTriangleSet qTriangulate(
const QVectorPath &path,
2244 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2246 QTriangleSet triangleSet;
2250 if (allowUintIndices) {
2251 QTriangulator<quint32> triangulator;
2252 triangulator.initialize(path, matrix, lod);
2253 QVertexSet<quint32> vertexSet = triangulator.triangulate();
2254 triangleSet.vertices = vertexSet.vertices;
2255 triangleSet.indices.setDataUint(vertexSet.indices);
2257 QTriangulator<quint16> triangulator;
2258 triangulator.initialize(path, matrix, lod);
2259 QVertexSet<quint16> vertexSet = triangulator.triangulate();
2260 triangleSet.vertices = vertexSet.vertices;
2261 triangleSet.indices.setDataUshort(vertexSet.indices);
2267 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2270 if (allowUintIndices) {
2271 QTriangulator<quint32> triangulator;
2272 triangulator.initialize(path, matrix, lod);
2273 QVertexSet<quint32> vertexSet = triangulator.triangulate();
2274 triangleSet.vertices = vertexSet.vertices;
2275 triangleSet.indices.setDataUint(vertexSet.indices);
2277 QTriangulator<quint16> triangulator;
2278 triangulator.initialize(path, matrix, lod);
2279 QVertexSet<quint16> vertexSet = triangulator.triangulate();
2280 triangleSet.vertices = vertexSet.vertices;
2281 triangleSet.indices.setDataUshort(vertexSet.indices);
2287 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2290 if (allowUintIndices) {
2291 QTriangulator<quint32> triangulator;
2292 triangulator.initialize(path, matrix, lod);
2293 QVertexSet<quint32> vertexSet = triangulator.polyline();
2294 polyLineSet.vertices = vertexSet.vertices;
2295 polyLineSet.indices.setDataUint(vertexSet.indices);
2297 QTriangulator<quint16> triangulator;
2298 triangulator.initialize(path, matrix, lod);
2299 QVertexSet<quint16> vertexSet = triangulator.polyline();
2300 polyLineSet.vertices = vertexSet.vertices;
2301 polyLineSet.indices.setDataUshort(vertexSet.indices);
2307 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2310 if (allowUintIndices) {
2311 QTriangulator<quint32> triangulator;
2312 triangulator.initialize(path, matrix, lod);
2313 QVertexSet<quint32> vertexSet = triangulator.polyline();
2314 polyLineSet.vertices = vertexSet.vertices;
2315 polyLineSet.indices.setDataUint(vertexSet.indices);
2317 QTriangulator<quint16> triangulator;
2318 triangulator.initialize(path, matrix, lod);
2319 QVertexSet<quint16> vertexSet = triangulator.polyline();
2320 polyLineSet.vertices = vertexSet.vertices;
2321 polyLineSet.indices.setDataUshort(vertexSet.indices);
2328#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()
Combined button and popup list for selecting options.
#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