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>
25#define QTRIANGULATOR_MAX (1
<< 21
)
26#define Q_FIXED_POINT_SCALE 32
27#define QTRIANGULATOR_FIXED_POINT_MAX ((qreal(QTRIANGULATOR_MAX - 1
)) / qreal(Q_FIXED_POINT_SCALE))
63 inline bool isValid()
const {
return denominator != 0;}
79static inline int compare(quint64 a, quint64 b)
81 return (a > b) - (a < b);
89 const quint64 LIMIT = Q_UINT64_C(0x100000000);
92 if (b < LIMIT && d < LIMIT)
93 return compare(a * d, b * c);
99 quint64 b_div_a = b / a;
100 quint64 d_div_c = d / c;
101 if (b_div_a != d_div_c)
102 return compare(d_div_c, b_div_a);
119 result.numerator = 0;
120 result.denominator = 1;
122 quint64 g = gcd(n, d);
123 result.numerator = n / g;
124 result.denominator = d / g;
131 return qCompareFractions(numerator, denominator, other.numerator, other.denominator) < 0;
136 return numerator == other.numerator && denominator == other.denominator;
169 return qint64(u
.x) * qint64(v
.y) - qint64(u
.y) * qint64(v
.x);
172#ifdef Q_TRIANGULATOR_DEBUG
173static inline qint64 qDot(
const QPodPoint &u,
const QPodPoint &v)
175 return qint64(u.x) * qint64(v.x) + qint64(u.y) * qint64(v.y);
185 return qCross(v2 - v1, p - v1);
190 return QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(p, v1, v2) < 0;
199 inline bool isValid()
const {
return xOffset.isValid() && yOffset.isValid();}
201 inline bool isAccurate()
const {
return xOffset.numerator == 0 && yOffset.numerator == 0;}
228 qint64 d1 = qCross(u, v1 - u1);
229 qint64 d2 = qCross(u, v2 - u1);
230 qint64 det = d2 - d1;
231 qint64 d3 = qCross(v, u1 - v1);
232 qint64 d4 = d3 - det;
235 Q_ASSERT(d4 == qCross(v, u2 - v1));
257 if (d1 >= 0 || d2 <= 0 || d3 <= 0 || d4 >= 0)
268 result.xOffset = qFraction(quint64(-v.x * d1) % quint64(det), quint64(det));
271 result.xOffset = qFraction(quint64(-v.x * d2) % quint64(det), quint64(det));
276 result.yOffset = qFraction(quint64(-v.y * d1) % quint64(det), quint64(det));
279 result.yOffset = qFraction(quint64(-v.y * d2) % quint64(det), quint64(det));
282 Q_ASSERT(result.xOffset.isValid());
283 Q_ASSERT(result.yOffset.isValid());
290 if (2 * xOffset.numerator >= xOffset.denominator)
292 if (2 * yOffset.numerator >= yOffset.denominator)
301 if (yOffset != other.yOffset)
302 return yOffset < other.yOffset;
305 return xOffset < other.xOffset;
310 return upperLeft == other.upperLeft && xOffset == other.xOffset && yOffset == other.yOffset;
319 bool isHorizontal = p.y == 0 && yOffset.numerator == 0;
320 bool isVertical = p.x == 0 && xOffset.numerator == 0;
321 if (isHorizontal && isVertical)
334 if (((q
.x < 0) == (q
.y < 0)) != ((p
.x < 0) == (p
.y < 0)))
340 nx = quint64(-p.x) * xOffset.denominator - xOffset.numerator;
342 nx = quint64(p.x) * xOffset.denominator + xOffset.numerator;
344 ny = quint64(-p.y) * yOffset.denominator - yOffset.numerator;
346 ny = quint64(p.y) * yOffset.denominator + yOffset.numerator;
348 return qFraction(quint64(qAbs(q.x)) * xOffset.denominator, quint64(qAbs(q.y)) * yOffset.denominator) == qFraction(nx, ny);
360 inline int size()
const {
return m_data.size();}
361 inline bool empty()
const {
return m_data.isEmpty();}
362 inline bool isEmpty()
const {
return m_data.isEmpty();}
365 inline const T &
top()
const {
return m_data.first();}
367 static inline int parent(
int i) {
return (i - 1) / 2;}
368 static inline int left(
int i) {
return 2 * i + 1;}
369 static inline int right(
int i) {
return 2 * i + 2;}
371 QDataBuffer<T> m_data;
377 int current = m_data.size();
378 int parent =
QMaxHeap::parent(current);
380 while (current != 0 && m_data.at(parent) < x) {
381 m_data.at(current) = m_data.at(parent);
385 m_data.at(current) = x;
391 T result = m_data.first();
392 T back = m_data.last();
394 if (!m_data.isEmpty()) {
398 int right =
QMaxHeap::right(current);
399 if (left >= m_data.size())
402 if (right < m_data.size() && m_data.at(left) < m_data.at(right))
404 if (m_data.at(greater) < back)
406 m_data.at(current) = m_data.at(greater);
409 m_data.at(current) = back;
420 Q_ASSERT(count >= 0);
423 constexpr auto primeForNumBits = [](
int numBits) ->
int
425 constexpr uchar prime_deltas[] = {
426 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 17, 27, 3,
427 1, 29, 3, 21, 7, 17, 15, 9, 43, 35, 15, 0, 0, 0, 0, 0
430 return (1 << numBits) + prime_deltas[numBits];
435 for (
int i = 0; i < 5; ++i) {
436 int mid = (high + low) / 2;
437 if (uint(count) >= (1u << mid))
442 return primeForNumBits(high);
458 bool rehash(
int capacity);
460 static const quint64 UNUSED;
467const quint64
QInt64Set::UNUSED = quint64(-1);
472 m_array =
new quint64[m_capacity];
478 quint64 *oldArray = m_array;
479 int oldCapacity = m_capacity;
481 m_capacity = capacity;
482 m_array =
new quint64[m_capacity];
484 for (
int i = 0; i < oldCapacity; ++i) {
485 if (oldArray[i] != UNUSED)
494 if (m_count > 3 * m_capacity / 4)
496 int index =
int(key % m_capacity);
497 for (
int i = 0; i < m_capacity; ++i) {
499 if (index >= m_capacity)
501 if (m_array[index] == key)
503 if (m_array[index] == UNUSED) {
505 m_array[index] = key;
509 Q_ASSERT_X(0,
"QInt64Hash<T>::insert",
"Hash set full.");
514 int index =
int(key % m_capacity);
515 for (
int i = 0; i < m_capacity; ++i) {
517 if (index >= m_capacity)
519 if (m_array[index] == key)
521 if (m_array[index] == UNUSED)
529 for (
int i = 0; i < m_capacity; ++i)
546 friend class ComplexToSimple;
556 inline int &upper() {
return pointingUp ? to : from;}
557 inline int &lower() {
return pointingUp ? from : to;}
558 inline int upper()
const {
return pointingUp ? to : from;}
559 inline int lower()
const {
return pointingUp ? from : to;}
561 QRBTree<
int>::Node *node;
566 bool pointingUp, originallyPointingUp;
571 bool operator < (
const Intersection &other)
const {
return other.intersectionPoint < intersectionPoint;}
588 enum Type {Upper, Lower};
589 inline bool operator < (
const Event &other)
const;
596#ifdef Q_TRIANGULATOR_DEBUG
617 bool calculateIntersection(
int left,
int right);
618 bool edgeIsLeftOfEdge(
int leftEdgeIndex,
int rightEdgeIndex)
const;
619 QRBTree<
int>::Node *searchEdgeLeftOf(
int edgeIndex)
const;
620 QRBTree<
int>::Node *searchEdgeLeftOf(
int edgeIndex, QRBTree<
int>::Node *after)
const;
623 void splitEdgeListRange(QRBTree<
int>::Node *leftmost, QRBTree<
int>::Node *rightmost,
int vertex,
const QIntersectionPoint &intersectionPoint);
624 void reorderEdgeListRange(QRBTree<
int>::Node *leftmost, QRBTree<
int>::Node *rightmost);
625 void sortEdgeList(
const QPodPoint eventPoint);
626 void fillPriorityQueue();
627 void calculateIntersections();
628 int splitEdge(
int splitIndex);
629 bool splitEdgesAtIntersections();
630 void insertEdgeIntoVectorIfWanted(
ShortArray &orderedEdges,
int i);
631 void removeUnwantedEdgesAndConnect();
632 void removeUnusedPoints();
635 QDataBuffer<Edge> m_edges;
636 QRBTree<
int> m_edgeList;
637 QDataBuffer<Event> m_events;
638 QDataBuffer<Split> m_splits;
639 QMaxHeap<Intersection> m_topIntersection;
641 int m_initialPointCount;
643#ifdef Q_TRIANGULATOR_DEBUG
650 friend class SimpleToMonotone;
658 enum VertexType {MergeVertex, EndVertex, RegularVertex, StartVertex, SplitVertex};
662 QRBTree<
int>::Node *node;
663 int helper, twin, next, previous;
667 int upper()
const {
return (pointingUp ? to : from);}
668 int lower()
const {
return (pointingUp ? from : to);}
671 friend class CompareVertices;
672 class CompareVertices
676 bool operator () (
int i,
int j)
const;
681 void setupDataStructures();
682 void removeZeroLengthEdges();
683 void fillPriorityQueue();
684 bool edgeIsLeftOfEdge(
int leftEdgeIndex,
int rightEdgeIndex)
const;
686 QRBTree<
int>::Node *searchEdgeLeftOfEdge(
int edgeIndex)
const;
688 QRBTree<
int>::Node *searchEdgeLeftOfPoint(
int pointIndex)
const;
689 void classifyVertex(
int i);
690 void classifyVertices();
692 bool pointIsInSector(
int vertex,
int sector);
693 int findSector(
int edge,
int vertex);
694 void createDiagonal(
int lower,
int upper);
695 void monotoneDecomposition();
698 QRBTree<
int> m_edgeList;
699 QDataBuffer<Edge> m_edges;
700 QDataBuffer<
int> m_upperVertex;
701 bool m_clockwiseOrder;
707 friend class MonotoneToTriangles;
712 : m_parent(parent), m_first(0), m_length(0) { }
715 inline T indices(
int index)
const {
return m_parent->m_indices.at(index + m_first);}
716 inline int next(
int index)
const {
return (index + 1) % m_length;}
717 inline int previous(
int index)
const {
return (index + m_length - 1) % m_length;}
718 inline bool less(
int i,
int j)
const {
return m_parent->m_vertices.at((qint32)indices(i)) < m_parent->m_vertices.at(indices(j));}
719 inline bool leftOfEdge(
int i,
int j,
int k)
const
721 return qPointIsLeftOfLine(m_parent->m_vertices.at((qint32)indices(i)),
722 m_parent->m_vertices.at((qint32)indices(j)), m_parent->m_vertices.at((qint32)indices(k)));
734 void initialize(
const qreal *polygon,
int count, uint hint,
const QTransform &matrix);
736 void initialize(
const QVectorPath &path,
const QTransform &matrix, qreal lod);
738 void initialize(
const QPainterPath &path,
const QTransform &matrix, qreal lod);
743 QDataBuffer<QPodPoint> m_vertices;
755 for (
int i = 0; i < m_vertices.size(); ++i) {
760 if (!(m_hint & (QVectorPath::OddEvenFill | QVectorPath::WindingFill)))
761 m_hint |= QVectorPath::OddEvenFill;
763 if (m_hint & QVectorPath::NonConvexShapeMask) {
773 result.indices = m_indices;
774 result.vertices.resize(2 * m_vertices.size());
775 for (
int i = 0; i < m_vertices.size(); ++i) {
785 for (
int i = 0; i < m_vertices.size(); ++i) {
790 if (!(m_hint & (QVectorPath::OddEvenFill | QVectorPath::WindingFill)))
791 m_hint |= QVectorPath::OddEvenFill;
793 if (m_hint & QVectorPath::NonConvexShapeMask) {
799 result.indices = m_indices;
800 result.vertices.resize(2 * m_vertices.size());
801 for (
int i = 0; i < m_vertices.size(); ++i) {
812 m_vertices.resize(count);
813 m_indices.resize(count + 1);
814 for (
int i = 0; i < count; ++i) {
816 matrix.map(polygon[2 * i + 0], polygon[2 * i + 1], &x, &y);
817 m_vertices.at(i).x = qToClampedFixedPoint(x);
818 m_vertices.at(i).y = qToClampedFixedPoint(y);
821 m_indices[count] = T(-1);
827 m_hint = path.hints();
829 m_hint &= ~QVectorPath::CurvedShapeMask;
831 const qreal *p = path.points();
832 const QPainterPath::ElementType *e = path.elements();
834 for (
int i = 0; i < path.elementCount(); ++i, ++e, p += 2) {
836 case QPainterPath::MoveToElement:
837 if (!m_indices.isEmpty())
838 m_indices.push_back(T(-1));
840 case QPainterPath::LineToElement:
841 m_indices.push_back(T(m_vertices.size()));
842 m_vertices.resize(m_vertices.size() + 1);
844 matrix.map(p[0], p[1], &x, &y);
845 m_vertices.last().x = qToClampedFixedPoint(x);
846 m_vertices.last().y = qToClampedFixedPoint(y);
848 case QPainterPath::CurveToElement:
851 for (
int i = 0; i < 4; ++i)
852 matrix.map(p[2 * i - 2], p[2 * i - 1], &pts[2 * i + 0], &pts[2 * i + 1]);
853 for (
int i = 0; i < 8; ++i)
855 QBezier bezier = QBezier::fromPoints(QPointF(pts[0], pts[1]), QPointF(pts[2], pts[3]), QPointF(pts[4], pts[5]), QPointF(pts[6], pts[7]));
856 QPolygonF poly = bezier.toPolygon();
858 for (
int j = 1; j < poly.size(); ++j) {
859 m_indices.push_back(T(m_vertices.size()));
860 m_vertices.resize(m_vertices.size() + 1);
861 m_vertices.last().x = qToClampedFixedPoint(poly.at(j).x() / lod);
862 m_vertices.last().y = qToClampedFixedPoint(poly.at(j).y() / lod);
870 Q_ASSERT_X(0,
"QTriangulator::triangulate",
"Unexpected element type.");
875 for (
int i = 0; i < path.elementCount(); ++i, p += 2) {
876 m_indices.push_back(T(m_vertices.size()));
877 m_vertices.resize(m_vertices.size() + 1);
879 matrix.map(p[0], p[1], &x, &y);
880 m_vertices.last().x = qToClampedFixedPoint(x);
881 m_vertices.last().y = qToClampedFixedPoint(y);
884 m_indices.push_back(T(-1));
890 initialize(qtVectorPathForPath(path), matrix, lod);
899 m_initialPointCount = m_parent->m_vertices.size();
902 calculateIntersections();
903 }
while (splitEdgesAtIntersections());
905 removeUnwantedEdgesAndConnect();
906 removeUnusedPoints();
908 m_parent->m_indices.clear();
909 QBitArray processed(m_edges.size(),
false);
910 for (
int first = 0; first < m_edges.size(); ++first) {
912 if (processed.at(first) || m_edges.at(first).next == -1)
917 Q_ASSERT(!processed.at(i));
918 Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i);
919 m_parent->m_indices.push_back(m_edges.at(i).from);
921 i = m_edges.at(i).next;
922 }
while (i != first);
923 m_parent->m_indices.push_back(T(-1));
933 for (
int i = 0; i < m_parent->m_indices.size(); ++i) {
934 if (m_parent->m_indices.at(i) == T(-1)) {
935 if (m_edges.size() != first)
936 m_edges.last().to = m_edges.at(first).from;
937 first = m_edges.size();
939 Q_ASSERT(i + 1 < m_parent->m_indices.size());
941 Edge edge = {
nullptr,
int(m_parent->m_indices.at(i)),
int(m_parent->m_indices.at(i + 1)), -1, -1, 0,
true,
false,
false};
945 if (first != m_edges.size())
946 m_edges.last().to = m_edges.at(first).from;
947 for (
int i = 0; i < m_edges.size(); ++i) {
948 m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp =
949 m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from);
957 const Edge &e1 = m_edges.at(left);
958 const Edge &e2 = m_edges.at(right);
960 const QPodPoint &u1 = m_parent->m_vertices.at((qint32)e1.from);
961 const QPodPoint &u2 = m_parent->m_vertices.at((qint32)e1.to);
962 const QPodPoint &v1 = m_parent->m_vertices.at((qint32)e2.from);
963 const QPodPoint &v2 = m_parent->m_vertices.at((qint32)e2.to);
964 if (qMax(u1
.x, u2
.x) <= qMin(v1
.x, v2
.x))
967 quint64 key = (left > right ? (quint64(right) << 32) | quint64(left) : (quint64(left) << 32) | quint64(right));
968 if (m_processedEdgePairs.contains(key))
970 m_processedEdgePairs.insert(key);
972 Intersection intersection;
973 intersection.leftEdge = left;
974 intersection.rightEdge = right;
975 intersection.intersectionPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(u1, u2, v1, v2);
977 if (!intersection.intersectionPoint.isValid())
980 Q_ASSERT(intersection.intersectionPoint.isOnLine(u1, u2));
981 Q_ASSERT(intersection.intersectionPoint.isOnLine(v1, v2));
983 intersection.vertex = m_parent->m_vertices.size();
984 m_topIntersection.push(intersection);
985 m_parent->m_vertices.add(intersection.intersectionPoint.round());
992 const Edge &leftEdge = m_edges.at(leftEdgeIndex);
993 const Edge &rightEdge = m_edges.at(rightEdgeIndex);
994 const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper());
995 const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower());
996 const QPodPoint &upper = m_parent->m_vertices.at(leftEdge.upper());
997 if (upper
.x < qMin(l
.x, u
.x))
999 if (upper
.x > qMax(l
.x, u
.x))
1001 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(upper, l, u);
1004 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.lower()), l, u);
1008template <
typename T>
1011 QRBTree<
int>::Node *current = m_edgeList.root;
1012 QRBTree<
int>::Node *result =
nullptr;
1014 if (edgeIsLeftOfEdge(edgeIndex, current->data)) {
1015 current = current->left;
1018 current = current->right;
1024template <
typename T>
1027 if (!m_edgeList.root)
1029 QRBTree<
int>::Node *result = after;
1030 QRBTree<
int>::Node *current = (after ? m_edgeList.next(after) : m_edgeList.front(m_edgeList.root));
1032 if (edgeIsLeftOfEdge(edgeIndex, current->data))
1035 current = m_edgeList.next(current);
1040template <
typename T>
1041std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> QTriangulator<T>::ComplexToSimple::bounds(
const QPodPoint &point)
const
1043 QRBTree<
int>::Node *current = m_edgeList.root;
1044 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> result(
nullptr,
nullptr);
1046 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1047 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1048 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1050 result.first = result.second = current;
1053 current = (d < 0 ? current->left : current->right);
1055 if (current ==
nullptr)
1058 current = result.first->left;
1060 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1061 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1062 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1065 result.first = current;
1066 current = current->left;
1068 current = current->right;
1072 current = result.second->right;
1074 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1075 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1076 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1079 result.second = current;
1080 current = current->right;
1082 current = current->left;
1089template <
typename T>
1090std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> QTriangulator<T>::ComplexToSimple::outerBounds(
const QPodPoint &point)
const
1092 QRBTree<
int>::Node *current = m_edgeList.root;
1093 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> result(
nullptr,
nullptr);
1096 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1097 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1098 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1102 result.second = current;
1103 current = current->left;
1105 result.first = current;
1106 current = current->right;
1113 QRBTree<
int>::Node *mid = current;
1115 current = mid->left;
1117 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1118 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1119 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1122 current = current->left;
1124 result.first = current;
1125 current = current->right;
1129 current = mid->right;
1131 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1132 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1133 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
1136 current = current->right;
1138 result.second = current;
1139 current = current->left;
1146template <
typename T>
1149 Q_ASSERT(leftmost && rightmost);
1153 const QPodPoint &u = m_parent->m_vertices.at(m_edges.at(leftmost->data).from);
1154 const QPodPoint &v = m_parent->m_vertices.at(m_edges.at(leftmost->data).to);
1156 const Split split = {vertex, leftmost->data, intersectionPoint
.isAccurate()};
1157 if (intersectionPoint.xOffset.numerator != 0 || intersectionPoint.yOffset.numerator != 0 || (intersectionPoint.upperLeft != u && intersectionPoint.upperLeft != v))
1158 m_splits.add(split);
1159 if (leftmost == rightmost)
1161 leftmost = m_edgeList.next(leftmost);
1165template <
typename T>
1168 Q_ASSERT(leftmost && rightmost);
1170 QRBTree<
int>::Node *storeLeftmost = leftmost;
1171 QRBTree<
int>::Node *storeRightmost = rightmost;
1174 while (leftmost != rightmost) {
1175 Edge &left = m_edges.at(leftmost->data);
1176 Edge &right = m_edges.at(rightmost->data);
1177 qSwap(left.node, right.node);
1178 qSwap(leftmost->data, rightmost->data);
1179 leftmost = m_edgeList.next(leftmost);
1180 if (leftmost == rightmost)
1182 rightmost = m_edgeList.previous(rightmost);
1185 rightmost = m_edgeList.next(storeRightmost);
1186 leftmost = m_edgeList.previous(storeLeftmost);
1188 calculateIntersection(leftmost->data, storeLeftmost->data);
1190 calculateIntersection(storeRightmost->data, rightmost->data);
1193template <
typename T>
1196 QIntersectionPoint eventPoint2 = QT_PREPEND_NAMESPACE(qIntersectionPoint)(eventPoint);
1197 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint < eventPoint2) {
1198 Intersection intersection = m_topIntersection.pop();
1201 int currentVertex = intersection.vertex;
1203 QRBTree<
int>::Node *leftmost = m_edges.at(intersection.leftEdge).node;
1204 QRBTree<
int>::Node *rightmost = m_edges.at(intersection.rightEdge).node;
1207 QRBTree<
int>::Node *previous = m_edgeList.previous(leftmost);
1210 const Edge &edge = m_edges.at(previous->data);
1211 const QPodPoint &u = m_parent->m_vertices.at((qint32)edge.from);
1212 const QPodPoint &v = m_parent->m_vertices.at((qint32)edge.to);
1214 Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0);
1217 leftmost = previous;
1221 QRBTree<
int>::Node *next = m_edgeList.next(rightmost);
1224 const Edge &edge = m_edges.at(next->data);
1225 const QPodPoint &u = m_parent->m_vertices.at((qint32)edge.from);
1226 const QPodPoint &v = m_parent->m_vertices.at((qint32)edge.to);
1228 Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0);
1234 Q_ASSERT(leftmost && rightmost);
1235 splitEdgeListRange(leftmost, rightmost, currentVertex, currentIntersectionPoint);
1236 reorderEdgeListRange(leftmost, rightmost);
1238 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= currentIntersectionPoint)
1239 m_topIntersection.pop();
1241#ifdef Q_TRIANGULATOR_DEBUG
1242 DebugDialog dialog(
this, intersection.vertex);
1249template <
typename T>
1253 m_events.reserve(m_edges.size() * 2);
1254 for (
int i = 0; i < m_edges.size(); ++i) {
1255 Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1);
1256 Q_ASSERT(m_edges.at(i).node ==
nullptr);
1257 Q_ASSERT(m_edges.at(i).pointingUp == m_edges.at(i).originallyPointingUp);
1258 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)));
1260 if (m_parent->m_vertices.at(m_edges.at(i).to) != m_parent->m_vertices.at(m_edges.at(i).from)) {
1261 QPodPoint upper = m_parent->m_vertices.at(m_edges.at(i).upper());
1262 QPodPoint lower = m_parent->m_vertices.at(m_edges.at(i).lower());
1263 Event upperEvent = {{upper
.x, upper
.y}, Event::Upper, i};
1264 Event lowerEvent = {{lower
.x, lower
.y}, Event::Lower, i};
1265 m_events.add(upperEvent);
1266 m_events.add(lowerEvent);
1270 std::sort(m_events.data(), m_events.data() + m_events.size());
1273template <
typename T>
1276 fillPriorityQueue();
1278 Q_ASSERT(m_topIntersection.empty());
1279 Q_ASSERT(m_edgeList.root ==
nullptr);
1282 while (!m_events.isEmpty()) {
1283 Event event = m_events.last();
1284 sortEdgeList(event.point);
1287 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> range = bounds(event.point);
1288 QRBTree<
int>::Node *leftNode = range.first ? m_edgeList.previous(range.first) :
nullptr;
1289 int vertex = (event.type == Event::Upper ? m_edges.at(event.edge).upper() : m_edges.at(event.edge).lower());
1290 QIntersectionPoint eventPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(event.point);
1292 if (range.first !=
nullptr) {
1293 splitEdgeListRange(range.first, range.second, vertex, eventPoint);
1294 reorderEdgeListRange(range.first, range.second);
1298 while (!m_events.isEmpty() && m_events.last().point == event.point) {
1299 event = m_events.last();
1300 m_events.pop_back();
1303 if (m_edges.at(i).node) {
1305 Q_ASSERT(event.type == Event::Lower);
1306 QRBTree<
int>::Node *left = m_edgeList.previous(m_edges.at(i).node);
1307 QRBTree<
int>::Node *right = m_edgeList.next(m_edges.at(i).node);
1308 m_edgeList.deleteNode(m_edges.at(i).node);
1309 if (!left || !right)
1311 calculateIntersection(left->data, right->data);
1314 Q_ASSERT(event.type == Event::Upper);
1315 QRBTree<
int>::Node *left = searchEdgeLeftOf(i, leftNode);
1316 m_edgeList.attachAfter(left, m_edges.at(i).node = m_edgeList.newNode());
1317 m_edges.at(i).node->data = i;
1318 QRBTree<
int>::Node *right = m_edgeList.next(m_edges.at(i).node);
1320 calculateIntersection(left->data, i);
1322 calculateIntersection(i, right->data);
1325 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= eventPoint)
1326 m_topIntersection.pop();
1327#ifdef Q_TRIANGULATOR_DEBUG
1328 DebugDialog dialog(
this, vertex);
1332 m_processedEdgePairs.clear();
1339template <
typename T>
1342 const Split &split = m_splits.at(splitIndex);
1343 Edge &lowerEdge = m_edges.at(split.edge);
1344 Q_ASSERT(lowerEdge.node ==
nullptr);
1345 Q_ASSERT(lowerEdge.previous == -1 && lowerEdge.next == -1);
1347 if (lowerEdge.from == split.vertex)
1349 if (lowerEdge.to == split.vertex)
1350 return lowerEdge.next;
1356 Edge upperEdge = lowerEdge;
1357 upperEdge.mayIntersect |= !split.accurate;
1358 lowerEdge.mayIntersect = !split.accurate;
1359 if (lowerEdge.pointingUp) {
1360 lowerEdge.to = upperEdge.from = split.vertex;
1361 m_edges.add(upperEdge);
1362 return m_edges.size() - 1;
1364 lowerEdge.from = upperEdge.to = split.vertex;
1365 m_edges.add(upperEdge);
1370template <
typename T>
1373 for (
int i = 0; i < m_edges.size(); ++i)
1374 m_edges.at(i).mayIntersect =
false;
1375 bool checkForNewIntersections =
false;
1376 for (
int i = 0; i < m_splits.size(); ++i) {
1378 checkForNewIntersections |= !m_splits.at(i).accurate;
1380 for (
int i = 0; i < m_edges.size(); ++i) {
1381 m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp =
1382 m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from);
1385 return checkForNewIntersections;
1388template <
typename T>
1392 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(i).from) != m_parent->m_vertices.at(m_edges.at(i).to));
1395 int windingNumber = m_edges.at(i).winding;
1396 if (m_edges.at(i).originallyPointingUp)
1400 Q_ASSERT(((m_parent->m_hint & QVectorPath::WindingFill) != 0) != ((m_parent->m_hint & QVectorPath::OddEvenFill) != 0));
1402 if ((m_parent->m_hint & QVectorPath::WindingFill) && windingNumber != 0 && windingNumber != 1)
1406 if (!orderedEdges.isEmpty()) {
1407 int j = orderedEdges[orderedEdges.size() - 1];
1409 if (m_edges.at(j).next == -1 && m_edges.at(j).previous == -1
1410 && (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(j).to))
1411 && (m_parent->m_vertices.at(m_edges.at(i).to) == m_parent->m_vertices.at(m_edges.at(j).from))) {
1412 orderedEdges.removeLast();
1416 orderedEdges.append(i);
1419template <
typename T>
1422 Q_ASSERT(m_edgeList.root ==
nullptr);
1424 fillPriorityQueue();
1428 while (!m_events.isEmpty()) {
1429 Event event = m_events.last();
1430 int edgeIndex = event.edge;
1439 orderedEdges.clear();
1440 std::pair<QRBTree<
int>::Node *, QRBTree<
int>::Node *> b = outerBounds(event.point);
1441 if (m_edgeList.root) {
1442 QRBTree<
int>::Node *current = (b.first ? m_edgeList.next(b.first) : m_edgeList.front(m_edgeList.root));
1444 while (current != b.second) {
1446 Q_ASSERT(m_edges.at(current->data).node == current);
1447 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)));
1448 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);
1449 insertEdgeIntoVectorIfWanted(orderedEdges, current->data);
1450 current = m_edgeList.next(current);
1456 event = m_events.last();
1457 m_events.pop_back();
1458 edgeIndex = event.edge;
1461 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(edgeIndex).from) != m_parent->m_vertices.at(m_edges.at(edgeIndex).to));
1463 if (m_edges.at(edgeIndex).node) {
1464 Q_ASSERT(event.type == Event::Lower);
1465 Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).lower()));
1466 m_edgeList.deleteNode(m_edges.at(edgeIndex).node);
1468 Q_ASSERT(event.type == Event::Upper);
1469 Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).upper()));
1470 QRBTree<
int>::Node *left = searchEdgeLeftOf(edgeIndex, b.first);
1471 m_edgeList.attachAfter(left, m_edges.at(edgeIndex).node = m_edgeList.newNode());
1472 m_edges.at(edgeIndex).node->data = edgeIndex;
1474 }
while (!m_events.isEmpty() && m_events.last().point == event.point);
1476 if (m_edgeList.root) {
1477 QRBTree<
int>::Node *current = (b.first ? m_edgeList.next(b.first) : m_edgeList.front(m_edgeList.root));
1480 int currentWindingNumber = (b.first ? m_edges.at(b.first->data).winding : 0);
1481 while (current != b.second) {
1484 int i = current->data;
1485 Q_ASSERT(m_edges.at(i).node == current);
1488 int ccwWindingNumber = m_edges.at(i).winding = currentWindingNumber;
1489 if (m_edges.at(i).originallyPointingUp) {
1490 --m_edges.at(i).winding;
1492 ++m_edges.at(i).winding;
1495 currentWindingNumber = m_edges.at(i).winding;
1498 if ((ccwWindingNumber & 1) == 0) {
1499 Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1);
1500 qSwap(m_edges.at(i).from, m_edges.at(i).to);
1501 m_edges.at(i).pointingUp = !m_edges.at(i).pointingUp;
1504 current = m_edgeList.next(current);
1508 current = (b.second ? m_edgeList.previous(b.second) : m_edgeList.back(m_edgeList.root));
1509 while (current != b.first) {
1511 Q_ASSERT(m_edges.at(current->data).node == current);
1512 insertEdgeIntoVectorIfWanted(orderedEdges, current->data);
1513 current = m_edgeList.previous(current);
1516 if (orderedEdges.isEmpty())
1519 Q_ASSERT((orderedEdges.size() & 1) == 0);
1524 if (m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).from) == event.point) {
1526 int copy = orderedEdges[0];
1527 orderedEdges.append(copy);
1529 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).to) == event.point);
1534 int pointIndex = INT_MAX;
1535 for (
int j = i; j < orderedEdges.size(); j += 2) {
1536 Q_ASSERT(j + 1 < orderedEdges.size());
1537 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j]).to) == event.point);
1538 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j + 1]).from) == event.point);
1539 if (m_edges.at(orderedEdges[j]).to < pointIndex)
1540 pointIndex = m_edges.at(orderedEdges[j]).to;
1541 if (m_edges.at(orderedEdges[j + 1]).from < pointIndex)
1542 pointIndex = m_edges.at(orderedEdges[j + 1]).from;
1545 for (; i < orderedEdges.size(); i += 2) {
1547 m_edges.at(orderedEdges[i]).to = m_edges.at(orderedEdges[i + 1]).from = pointIndex;
1549 Q_ASSERT(m_edges.at(orderedEdges[i]).pointingUp || m_edges.at(orderedEdges[i]).previous != -1);
1550 Q_ASSERT(!m_edges.at(orderedEdges[i + 1]).pointingUp || m_edges.at(orderedEdges[i + 1]).next != -1);
1552 m_edges.at(orderedEdges[i]).next = orderedEdges[i + 1];
1553 m_edges.at(orderedEdges[i + 1]).previous = orderedEdges[i];
1558template <
typename T>
1560 QBitArray used(m_parent->m_vertices.size(),
false);
1561 for (
int i = 0; i < m_edges.size(); ++i) {
1562 Q_ASSERT((m_edges.at(i).previous == -1) == (m_edges.at(i).next == -1));
1563 if (m_edges.at(i).next != -1)
1564 used.setBit(m_edges.at(i).from);
1566 QDataBuffer<quint32> newMapping(m_parent->m_vertices.size());
1567 newMapping.resize(m_parent->m_vertices.size());
1569 for (
int i = 0; i < m_parent->m_vertices.size(); ++i) {
1571 m_parent->m_vertices.at(count) = m_parent->m_vertices.at(i);
1572 newMapping.at(i) = count;
1576 m_parent->m_vertices.resize(count);
1577 for (
int i = 0; i < m_edges.size(); ++i) {
1578 m_edges.at(i).from = newMapping.at(m_edges.at(i).from);
1579 m_edges.at(i).to = newMapping.at(m_edges.at(i).to);
1583template <
typename T>
1586 if (point
== other.point)
1587 return type < other.type;
1588 return other.point
< point;
1595#ifdef Q_TRIANGULATOR_DEBUG
1596template <
typename T>
1597QTriangulator<T>::ComplexToSimple::DebugDialog::DebugDialog(ComplexToSimple *parent,
int currentVertex)
1598 : m_parent(parent), m_vertex(currentVertex)
1600 QDataBuffer<QPodPoint> &vertices = m_parent->m_parent->m_vertices;
1601 if (vertices.isEmpty())
1604 int minX, maxX, minY, maxY;
1605 minX = maxX = vertices.at(0).x;
1606 minY = maxY = vertices.at(0).y;
1607 for (
int i = 1; i < vertices.size(); ++i) {
1608 minX = qMin(minX, vertices.at(i).x);
1609 maxX = qMax(maxX, vertices.at(i).x);
1610 minY = qMin(minY, vertices.at(i).y);
1611 maxY = qMax(maxY, vertices.at(i).y);
1613 int w = maxX - minX;
1614 int h = maxY - minY;
1615 qreal border = qMin(w, h) / 10.0;
1616 m_window = QRectF(minX - border, minY - border, (maxX - minX + 2 * border), (maxY - minY + 2 * border));
1619template <
typename T>
1620void QTriangulator<T>::ComplexToSimple::DebugDialog::paintEvent(QPaintEvent *)
1623 p.setRenderHint(QPainter::Antialiasing,
true);
1624 p.fillRect(rect(), Qt::black);
1625 QDataBuffer<QPodPoint> &vertices = m_parent->m_parent->m_vertices;
1626 if (vertices.isEmpty())
1629 qreal halfPointSize = qMin(m_window.width(), m_window.height()) / 300.0;
1630 p.setWindow(m_window.toRect());
1632 p.setPen(Qt::white);
1634 QDataBuffer<Edge> &edges = m_parent->m_edges;
1635 for (
int i = 0; i < edges.size(); ++i) {
1636 QPodPoint u = vertices.at(edges.at(i).from);
1637 QPodPoint v = vertices.at(edges.at(i).to);
1638 p.drawLine(u.x, u.y, v.x, v.y);
1641 for (
int i = 0; i < vertices.size(); ++i) {
1642 QPodPoint q = vertices.at(i);
1643 p.fillRect(QRectF(q.x - halfPointSize, q.y - halfPointSize, 2 * halfPointSize, 2 * halfPointSize), Qt::red);
1646 Qt::GlobalColor colors[6] = {Qt::red, Qt::green, Qt::blue, Qt::cyan, Qt::magenta, Qt::yellow};
1649 if (m_parent->m_edgeList.root) {
1650 QRBTree<
int>::Node *current = m_parent->m_edgeList.front(m_parent->m_edgeList.root);
1652 p.setPen(colors[count++ % 6]);
1653 QPodPoint u = vertices.at(edges.at(current->data).from);
1654 QPodPoint v = vertices.at(edges.at(current->data).to);
1655 p.drawLine(u.x, u.y, v.x, v.y);
1656 current = m_parent->m_edgeList.next(current);
1661 QPodPoint q = vertices.at(m_vertex);
1662 p.fillRect(QRectF(q.x - halfPointSize, q.y - halfPointSize, 2 * halfPointSize, 2 * halfPointSize), Qt::green);
1665 QDataBuffer<Split> &splits = m_parent->m_splits;
1666 for (
int i = 0; i < splits.size(); ++i) {
1667 QPodPoint q = vertices.at(splits.at(i).vertex);
1668 QPodPoint u = vertices.at(edges.at(splits.at(i).edge).from) - q;
1669 QPodPoint v = vertices.at(edges.at(splits.at(i).edge).to) - q;
1670 qreal uLen = qSqrt(qDot(u, u));
1671 qreal vLen = qSqrt(qDot(v, v));
1673 u.x *= 2 * halfPointSize / uLen;
1674 u.y *= 2 * halfPointSize / uLen;
1677 v.x *= 2 * halfPointSize / vLen;
1678 v.y *= 2 * halfPointSize / vLen;
1682 p.drawLine(u.x, u.y, v.x, v.y);
1686template <
typename T>
1687void QTriangulator<T>::ComplexToSimple::DebugDialog::wheelEvent(QWheelEvent *event)
1689 qreal scale = qExp(-0.001 * event->delta());
1690 QPointF center = m_window.center();
1691 QPointF delta = scale * (m_window.bottomRight() - center);
1692 m_window = QRectF(center - delta, center + delta);
1697template <
typename T>
1698void QTriangulator<T>::ComplexToSimple::DebugDialog::mouseMoveEvent(QMouseEvent *event)
1700 if (event->buttons() & Qt::LeftButton) {
1701 QPointF delta = event->pos() - m_lastMousePos;
1702 delta.setX(delta.x() * m_window.width() / width());
1703 delta.setY(delta.y() * m_window.height() / height());
1704 m_window.translate(-delta.x(), -delta.y());
1705 m_lastMousePos = event->pos();
1711template <
typename T>
1712void QTriangulator<T>::ComplexToSimple::DebugDialog::mousePressEvent(QMouseEvent *event)
1714 if (event->button() == Qt::LeftButton)
1715 m_lastMousePos = event->pos();
1725template <
typename T>
1728 setupDataStructures();
1729 removeZeroLengthEdges();
1730 monotoneDecomposition();
1732 m_parent->m_indices.clear();
1733 QBitArray processed(m_edges.size(),
false);
1734 for (
int first = 0; first < m_edges.size(); ++first) {
1735 if (processed.at(first))
1739 Q_ASSERT(!processed.at(i));
1740 Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i);
1741 m_parent->m_indices.push_back(m_edges.at(i).from);
1742 processed.setBit(i);
1743 i = m_edges.at(i).next;
1744 }
while (i != first);
1745 if (m_parent->m_indices.size() > 0 && m_parent->m_indices.back() != T(-1))
1746 m_parent->m_indices.push_back(T(-1));
1750template <
typename T>
1758 while (i + 3 <= m_parent->m_indices.size()) {
1759 int start = m_edges.size();
1762 e.from = m_parent->m_indices.at(i);
1763 e.type = RegularVertex;
1764 e.next = m_edges.size() + 1;
1765 e.previous = m_edges.size() - 1;
1768 Q_ASSERT(i < m_parent->m_indices.size());
1769 }
while (m_parent->m_indices.at(i) != T(-1));
1771 m_edges.last().next = start;
1772 m_edges.at(start).previous = m_edges.size() - 1;
1776 for (i = 0; i < m_edges.size(); ++i) {
1777 m_edges.at(i).to = m_edges.at(m_edges.at(i).next).from;
1778 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);
1779 m_edges.at(i).helper = -1;
1783template <
typename T>
1786 for (
int i = 0; i < m_edges.size(); ++i) {
1787 if (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(i).to)) {
1788 m_edges.at(m_edges.at(i).previous).next = m_edges.at(i).next;
1789 m_edges.at(m_edges.at(i).next).previous = m_edges.at(i).previous;
1790 m_edges.at(m_edges.at(i).next).from = m_edges.at(i).from;
1791 m_edges.at(i).next = -1;
1795 QDataBuffer<
int> newMapping(m_edges.size());
1796 newMapping.resize(m_edges.size());
1798 for (
int i = 0; i < m_edges.size(); ++i) {
1799 if (m_edges.at(i).next != -1) {
1800 m_edges.at(count) = m_edges.at(i);
1801 newMapping.at(i) = count;
1805 m_edges.resize(count);
1806 for (
int i = 0; i < m_edges.size(); ++i) {
1807 m_edges.at(i).next = newMapping.at(m_edges.at(i).next);
1808 m_edges.at(i).previous = newMapping.at(m_edges.at(i).previous);
1812template <
typename T>
1815 m_upperVertex.reset();
1816 m_upperVertex.reserve(m_edges.size());
1817 for (
int i = 0; i < m_edges.size(); ++i)
1818 m_upperVertex.add(i);
1819 CompareVertices cmp(
this);
1820 std::sort(m_upperVertex.data(), m_upperVertex.data() + m_upperVertex.size(), cmp);
1826template <
typename T>
1829 const Edge &leftEdge = m_edges.at(leftEdgeIndex);
1830 const Edge &rightEdge = m_edges.at(rightEdgeIndex);
1831 const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper());
1832 const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower());
1833 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.upper()), l, u);
1836 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.lower()), l, u);
1841template <
typename T>
1844 QRBTree<
int>::Node *current = m_edgeList.root;
1845 QRBTree<
int>::Node *result =
nullptr;
1847 if (edgeIsLeftOfEdge(edgeIndex, current->data)) {
1848 current = current->left;
1851 current = current->right;
1858template <
typename T>
1861 QRBTree<
int>::Node *current = m_edgeList.root;
1862 QRBTree<
int>::Node *result =
nullptr;
1864 const QPodPoint &p1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
1865 const QPodPoint &p2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
1866 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(pointIndex), p1, p2);
1868 current = current->left;
1871 current = current->right;
1877template <
typename T>
1880 Edge &e2 = m_edges.at(i);
1881 const Edge &e1 = m_edges.at(e2.previous);
1883 bool startOrSplit = (e1.pointingUp && !e2.pointingUp);
1884 bool endOrMerge = (!e1.pointingUp && e2.pointingUp);
1886 const QPodPoint &p1 = m_parent->m_vertices.at(e1.from);
1887 const QPodPoint &p2 = m_parent->m_vertices.at(e2.from);
1888 const QPodPoint &p3 = m_parent->m_vertices.at(e2.to);
1889 qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(p1, p2, p3);
1890 Q_ASSERT(d != 0 || (!startOrSplit && !endOrMerge));
1892 e2.type = RegularVertex;
1894 if (m_clockwiseOrder) {
1896 e2.type = (d < 0 ? SplitVertex : StartVertex);
1897 else if (endOrMerge)
1898 e2.type = (d < 0 ? MergeVertex : EndVertex);
1901 e2.type = (d > 0 ? SplitVertex : StartVertex);
1902 else if (endOrMerge)
1903 e2.type = (d > 0 ? MergeVertex : EndVertex);
1907template <
typename T>
1910 for (
int i = 0; i < m_edges.size(); ++i)
1914template <
typename T>
1921 return leftOfPreviousEdge && leftOfNextEdge;
1923 return leftOfPreviousEdge || leftOfNextEdge;
1926template <
typename T>
1929 const QPodPoint ¢er = m_parent->m_vertices.at(m_edges.at(sector).from);
1931 while (m_parent->m_vertices.at(m_edges.at(vertex).from) == center)
1932 vertex = m_edges.at(vertex).next;
1933 int next = m_edges.at(sector).next;
1934 while (m_parent->m_vertices.at(m_edges.at(next).from) == center)
1935 next = m_edges.at(next).next;
1936 int previous = m_edges.at(sector).previous;
1937 while (m_parent->m_vertices.at(m_edges.at(previous).from) == center)
1938 previous = m_edges.at(previous).previous;
1940 const QPodPoint &p = m_parent->m_vertices.at(m_edges.at(vertex).from);
1941 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(previous).from);
1942 const QPodPoint &v3 = m_parent->m_vertices.at(m_edges.at(next).from);
1943 if (m_clockwiseOrder)
1944 return pointIsInSector(p, v3, center, v1);
1946 return pointIsInSector(p, v1, center, v3);
1949template <
typename T>
1952 while (!pointIsInSector(vertex, edge)) {
1953 edge = m_edges.at(m_edges.at(edge).previous).twin;
1954 Q_ASSERT(edge != -1);
1959template <
typename T>
1962 lower = findSector(lower, upper);
1963 upper = findSector(upper, lower);
1965 int prevLower = m_edges.at(lower).previous;
1966 int prevUpper = m_edges.at(upper).previous;
1970 e.twin = m_edges.size() + 1;
1972 e.previous = prevLower;
1973 e.from = m_edges.at(lower).from;
1974 e.to = m_edges.at(upper).from;
1975 m_edges.at(upper).previous = m_edges.at(prevLower).next =
int(m_edges.size());
1978 e.twin = m_edges.size() - 1;
1980 e.previous = prevUpper;
1981 e.from = m_edges.at(upper).from;
1982 e.to = m_edges.at(lower).from;
1983 m_edges.at(lower).previous = m_edges.at(prevUpper).next =
int(m_edges.size());
1987template <
typename T>
1990 if (m_edges.isEmpty())
1993 Q_ASSERT(!m_edgeList.root);
1994 QDataBuffer<std::pair<
int,
int> > diagonals(m_upperVertex.size());
1997 for (
int index = 1; index < m_edges.size(); ++index) {
1998 if (m_parent->m_vertices.at(m_edges.at(index).from) < m_parent->m_vertices.at(m_edges.at(i).from))
2001 Q_ASSERT(i < m_edges.size());
2002 int j = m_edges.at(i).previous;
2003 Q_ASSERT(j < m_edges.size());
2004 m_clockwiseOrder = qPointIsLeftOfLine(m_parent->m_vertices.at((quint32)m_edges.at(i).from),
2005 m_parent->m_vertices.at((quint32)m_edges.at(j).from), m_parent->m_vertices.at((quint32)m_edges.at(i).to));
2008 fillPriorityQueue();
2014 while (!m_upperVertex.isEmpty()) {
2015 i = m_upperVertex.last();
2016 Q_ASSERT(i < m_edges.size());
2017 m_upperVertex.pop_back();
2018 j = m_edges.at(i).previous;
2019 Q_ASSERT(j < m_edges.size());
2021 QRBTree<
int>::Node *leftEdgeNode =
nullptr;
2023 switch (m_edges.at(i).type) {
2026 if (m_edges.at(i).pointingUp == m_clockwiseOrder) {
2027 if (m_edges.at(i).node) {
2028 Q_ASSERT(!m_edges.at(j).node);
2029 if (m_edges.at(m_edges.at(i).helper).type == MergeVertex)
2030 diagonals.add(std::pair<
int,
int>(i, m_edges.at(i).helper));
2031 m_edges.at(j).node = m_edges.at(i).node;
2032 m_edges.at(i).node =
nullptr;
2033 m_edges.at(j).node->data = j;
2034 m_edges.at(j).helper = i;
2035 }
else if (m_edges.at(j).node) {
2036 Q_ASSERT(!m_edges.at(i).node);
2037 if (m_edges.at(m_edges.at(j).helper).type == MergeVertex)
2038 diagonals.add(std::pair<
int,
int>(i, m_edges.at(j).helper));
2039 m_edges.at(i).node = m_edges.at(j).node;
2040 m_edges.at(j).node =
nullptr;
2041 m_edges.at(i).node->data = i;
2042 m_edges.at(i).helper = i;
2044 qWarning(
"Inconsistent polygon. (#1)");
2047 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from);
2049 if (m_edges.at(m_edges.at(leftEdgeNode->data).helper).type == MergeVertex)
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. (#2)");
2058 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from);
2060 diagonals.add(std::pair<
int,
int>(i, m_edges.at(leftEdgeNode->data).helper));
2061 m_edges.at(leftEdgeNode->data).helper = i;
2063 qWarning(
"Inconsistent polygon. (#3)");
2067 if (m_clockwiseOrder) {
2068 leftEdgeNode = searchEdgeLeftOfEdge(j);
2069 QRBTree<
int>::Node *node = m_edgeList.newNode();
2071 m_edges.at(j).node = node;
2072 m_edges.at(j).helper = i;
2073 m_edgeList.attachAfter(leftEdgeNode, node);
2074 Q_ASSERT(m_edgeList.validate());
2076 leftEdgeNode = searchEdgeLeftOfEdge(i);
2077 QRBTree<
int>::Node *node = m_edgeList.newNode();
2079 m_edges.at(i).node = node;
2080 m_edges.at(i).helper = i;
2081 m_edgeList.attachAfter(leftEdgeNode, node);
2082 Q_ASSERT(m_edgeList.validate());
2086 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from);
2088 if (m_edges.at(m_edges.at(leftEdgeNode->data).helper).type == MergeVertex)
2089 diagonals.add(std::pair<
int,
int>(i, m_edges.at(leftEdgeNode->data).helper));
2090 m_edges.at(leftEdgeNode->data).helper = i;
2092 qWarning(
"Inconsistent polygon. (#4)");
2096 if (m_clockwiseOrder) {
2097 if (m_edges.at(m_edges.at(i).helper).type == MergeVertex)
2098 diagonals.add(std::pair<
int,
int>(i, m_edges.at(i).helper));
2099 if (m_edges.at(i).node) {
2100 m_edgeList.deleteNode(m_edges.at(i).node);
2101 Q_ASSERT(m_edgeList.validate());
2103 qWarning(
"Inconsistent polygon. (#5)");
2106 if (m_edges.at(m_edges.at(j).helper).type == MergeVertex)
2107 diagonals.add(std::pair<
int,
int>(i, m_edges.at(j).helper));
2108 if (m_edges.at(j).node) {
2109 m_edgeList.deleteNode(m_edges.at(j).node);
2110 Q_ASSERT(m_edgeList.validate());
2112 qWarning(
"Inconsistent polygon. (#6)");
2119 for (
int i = 0; i < diagonals.size(); ++i)
2120 createDiagonal(diagonals.at(i).first, diagonals.at(i).second);
2123template <
typename T>
2126 if (m_parent->m_edges.at(i).from == m_parent->m_edges.at(j).from)
2127 return m_parent->m_edges.at(i).type > m_parent->m_edges.at(j).type;
2128 return m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(i).from) >
2129 m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(j).from);
2135template <
typename T>
2139 QDataBuffer<
int> stack(m_parent->m_indices.size());
2142 while (m_first + 3 <= m_parent->m_indices.size()) {
2144 while (m_parent->m_indices.at(m_first + m_length) != T(-1)) {
2146 Q_ASSERT(m_first + m_length < m_parent->m_indices.size());
2149 m_first += m_length + 1;
2154 while (less(next(minimum), minimum))
2155 minimum = next(minimum);
2156 while (less(previous(minimum), minimum))
2157 minimum = previous(minimum);
2161 int left = previous(minimum);
2162 int right = next(minimum);
2163 bool stackIsOnLeftSide;
2164 bool clockwiseOrder = leftOfEdge(minimum, left, right);
2166 if (less(left, right)) {
2168 left = previous(left);
2169 stackIsOnLeftSide =
true;
2172 right = next(right);
2173 stackIsOnLeftSide =
false;
2176 for (
int count = 0; count + 2 < m_length; ++count)
2178 Q_ASSERT(stack.size() >= 2);
2179 if (less(left, right)) {
2180 if (stackIsOnLeftSide ==
false) {
2181 for (
int i = 0; i + 1 < stack.size(); ++i) {
2182 result.push_back(indices(stack.at(i + 1)));
2183 result.push_back(indices(left));
2184 result.push_back(indices(stack.at(i)));
2186 stack.first() = stack.last();
2189 while (stack.size() >= 2 && (clockwiseOrder ^ !leftOfEdge(left, stack.at(stack.size() - 2), stack.last()))) {
2190 result.push_back(indices(stack.at(stack.size() - 2)));
2191 result.push_back(indices(left));
2192 result.push_back(indices(stack.last()));
2197 left = previous(left);
2198 stackIsOnLeftSide =
true;
2200 if (stackIsOnLeftSide ==
true) {
2201 for (
int i = 0; i + 1 < stack.size(); ++i) {
2202 result.push_back(indices(stack.at(i)));
2203 result.push_back(indices(right));
2204 result.push_back(indices(stack.at(i + 1)));
2206 stack.first() = stack.last();
2209 while (stack.size() >= 2 && (clockwiseOrder ^ !leftOfEdge(right, stack.last(), stack.at(stack.size() - 2)))) {
2210 result.push_back(indices(stack.last()));
2211 result.push_back(indices(right));
2212 result.push_back(indices(stack.at(stack.size() - 2)));
2217 right = next(right);
2218 stackIsOnLeftSide =
false;
2222 m_first += m_length + 1;
2224 m_parent->m_indices = result;
2231Q_GUI_EXPORT QTriangleSet qTriangulate(
const qreal *polygon,
2232 int count, uint hint,
const QTransform &matrix,
2233 bool allowUintIndices)
2235 QTriangleSet triangleSet;
2236 if (allowUintIndices) {
2237 QTriangulator<quint32> triangulator;
2238 triangulator.initialize(polygon, count, hint, matrix);
2239 QVertexSet<quint32> vertexSet = triangulator.triangulate();
2240 triangleSet.vertices = vertexSet.vertices;
2241 triangleSet.indices.setDataUint(vertexSet.indices);
2244 QTriangulator<quint16> triangulator;
2245 triangulator.initialize(polygon, count, hint, matrix);
2246 QVertexSet<quint16> vertexSet = triangulator.triangulate();
2247 triangleSet.vertices = vertexSet.vertices;
2248 triangleSet.indices.setDataUshort(vertexSet.indices);
2253Q_GUI_EXPORT QTriangleSet qTriangulate(
const QVectorPath &path,
2254 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2256 QTriangleSet triangleSet;
2260 if (allowUintIndices) {
2261 QTriangulator<quint32> triangulator;
2262 triangulator.initialize(path, matrix, lod);
2263 QVertexSet<quint32> vertexSet = triangulator.triangulate();
2264 triangleSet.vertices = vertexSet.vertices;
2265 triangleSet.indices.setDataUint(vertexSet.indices);
2267 QTriangulator<quint16> triangulator;
2268 triangulator.initialize(path, matrix, lod);
2269 QVertexSet<quint16> vertexSet = triangulator.triangulate();
2270 triangleSet.vertices = vertexSet.vertices;
2271 triangleSet.indices.setDataUshort(vertexSet.indices);
2277 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2280 if (allowUintIndices) {
2281 QTriangulator<quint32> triangulator;
2282 triangulator.initialize(path, matrix, lod);
2283 QVertexSet<quint32> vertexSet = triangulator.triangulate();
2284 triangleSet.vertices = vertexSet.vertices;
2285 triangleSet.indices.setDataUint(vertexSet.indices);
2287 QTriangulator<quint16> triangulator;
2288 triangulator.initialize(path, matrix, lod);
2289 QVertexSet<quint16> vertexSet = triangulator.triangulate();
2290 triangleSet.vertices = vertexSet.vertices;
2291 triangleSet.indices.setDataUshort(vertexSet.indices);
2297 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2300 if (allowUintIndices) {
2301 QTriangulator<quint32> triangulator;
2302 triangulator.initialize(path, matrix, lod);
2303 QVertexSet<quint32> vertexSet = triangulator.polyline();
2304 polyLineSet.vertices = vertexSet.vertices;
2305 polyLineSet.indices.setDataUint(vertexSet.indices);
2307 QTriangulator<quint16> triangulator;
2308 triangulator.initialize(path, matrix, lod);
2309 QVertexSet<quint16> vertexSet = triangulator.polyline();
2310 polyLineSet.vertices = vertexSet.vertices;
2311 polyLineSet.indices.setDataUshort(vertexSet.indices);
2317 const QTransform &matrix, qreal lod,
bool allowUintIndices)
2320 if (allowUintIndices) {
2321 QTriangulator<quint32> triangulator;
2322 triangulator.initialize(path, matrix, lod);
2323 QVertexSet<quint32> vertexSet = triangulator.polyline();
2324 polyLineSet.vertices = vertexSet.vertices;
2325 polyLineSet.indices.setDataUint(vertexSet.indices);
2327 QTriangulator<quint16> triangulator;
2328 triangulator.initialize(path, matrix, lod);
2329 QVertexSet<quint16> vertexSet = triangulator.polyline();
2330 polyLineSet.vertices = vertexSet.vertices;
2331 polyLineSet.indices.setDataUshort(vertexSet.indices);
2338#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)
#define QTRIANGULATOR_FIXED_POINT_MAX
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)
#define QTRIANGULATOR_MAX
static qint64 qPointDistanceFromLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2)
static int qToClampedFixedPoint(qreal c)
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
QVertexSet< T > & operator=(const QVertexSet< T > &other)
QVertexSet(const QVertexSet< T > &other)