21#define QDEBUG if (1
){} else qDebug
136 enum { default_alloc = 32 };
200 void addIntersection(
const Edge *e1,
const Edge *e2);
245 return (((qint64) ((quint64) a ^ (quint64) b)) >= 0 );
250 qint64 a1 = v1->y - v0->y;
251 qint64 b1 = v0->x - v1->x;
253 qint64 a2 = other.v1->y - other.v0->y;
254 qint64 b2 = other.v0->x - other.v1->x;
256 qint64 det = a1 * b2 - a2 * b1;
260 qint64 c1 = qint64(v1->x) * v0->y - qint64(v0->x) * v1->y;
262 qint64 r3 = a1 * other.v0->x + b1 * other.v0->y + c1;
263 qint64 r4 = a1 * other.v1->x + b1 * other.v1->y + c1;
267 QDEBUG() <<
" " << r3 << r4;
268 if (r3 != 0 && r4 != 0 && sameSign( r3, r4 ))
271 qint64 c2 = qint64(other.v1->x) * other.v0->y - qint64(other.v0->x) * other.v1->y;
273 qint64 r1 = a2 * v0->x + b2 * v0->y + c2;
274 qint64 r2 = a2 * v1->x + b2 * v1->y + c2;
278 QDEBUG() <<
" " << r1 << r2;
279 if (r1 != 0 && r2 != 0 && sameSign( r1, r2 ))
285 qint64 offset = det < 0 ? -det : det;
288 qint64 num = a2 * c1 - a1 * c2;
289 *y = ( num < 0 ? num - offset : num + offset ) / det;
291 *det_positive = (det > 0);
301 qint64 a1 = v1->y - v0->y;
302 qint64 b1 = v0->x - v1->x;
303 qint64 a2 = other.v1->y - other.v0->y;
304 qint64 b2 = other.v0->x - other.v1->x;
306 qint64 c2 = qint64(other.v1->x) * other.v0->y - qint64(other.v0->x) * other.v1->y;
308 qint64 det = a1 * b2 - a2 * b1;
312 qint64 r1 = a2 * v0->x + b2 * v0->y + c2;
320 qint64 c1 = qint64(v1->x) * v0->y - qint64(v0->x) * v1->y;
322 qint64 offset = det < 0 ? -det : det;
325 qint64 num = a2 * c1 - a1 * c2;
326 qint64 yi = ( num < 0 ? num - offset : num + offset ) / det;
329 return ((yi > y) ^ (det < 0));
350 qint64 d = v1->x - v0->x;
370 if (!
edges || maxActiveEdges > default_alloc) {
371 max_edges = maxActiveEdges;
372 int s = qMax(maxActiveEdges + 1, default_alloc + 1);
373 edges = q_check_ptr((Edge **)realloc(edges, s*
sizeof(Edge *)));
374 edge_table = q_check_ptr((Edge *)realloc(edge_table, s*
sizeof(Edge)));
375 old = q_check_ptr((Edge **)realloc(old, s*
sizeof(Edge *)));
380 for (
int i = 0; i < maxActiveEdges; ++i)
381 edge_table[i]
.edge = i+1;
382 edge_table[maxActiveEdges]
.edge = -1;
387 if (max_edges > default_alloc) {
409 int pos = min + ((max - min + 1) >> 1);
426 int pos = min + ((max - min) >> 1);
440 for (
int i = 0; i <
size; ++i) {
442 if (item_edge == edge)
451 for (
int i = 0; i <
size; ++i) {
477 (*e)
->edge = first_unused;
478 first_unused = (*e - edge_table);
486 Edge *edge = edge_table + first_unused;
487 first_unused = edge
->edge;
488 Q_ASSERT(first_unused != -1);
508 for (
int i = pos1; i <= pos2; ++i)
533 storage = q_check_ptr((Vertex *)realloc(storage, size*
sizeof(Vertex)));
534 sorted = q_check_ptr((Vertex **)realloc(sorted, size*
sizeof(Vertex *)));
576 qreal xmin(points[0].x());
577 qreal xmax(points[0].x());
578 qreal ymin(points[0].y());
579 qreal ymax(points[0].y());
598 xmin = qMin(xmin, points[i+1].x());
599 xmax = qMax(xmax, points[i+1].x());
600 ymin = qMin(ymin, points[i+1].y());
601 ymax = qMax(ymax, points[i+1].y());
607 if (v
->x == x_next && v
->y == y_next) {
615 else if (y_prev > y_curr)
621 *maxActiveEdges += 2;
627 else if (y_prev > y_curr)
635 else if (y_curr > y_next)
642 *maxActiveEdges += 2;
651 QDEBUG() <<
"maxActiveEdges=" << *maxActiveEdges;
655 return QRectF(xmin, ymin, xmax-xmin, ymax-ymin);
698 int testListSize = 0;
704 if (testListSize > tlSize - 2) {
705 tlSize = qMax(tlSize*2, 16);
706 tl = q_check_ptr((QCoincidingEdge *)realloc(tl, tlSize*
sizeof(QCoincidingEdge)));
709 tl[testListSize]
.start = n;
711 tl[testListSize]
.used =
false;
712 tl[testListSize]
.before =
true;
716 tl[testListSize]
.start = n;
718 tl[testListSize]
.used =
false;
719 tl[testListSize]
.before =
false;
727 std::sort(tl, tl + testListSize);
730QT_WARNING_DISABLE_CLANG(
"-Wfor-loop-analysis")
731 for (
int j = 0; j < testListSize; ++j) {
735 for (
int k = j + 1; k < testListSize; ++k) {
736 if (tl[j].end->x != tl[k].end->x
737 || tl[j].end->y != tl[k].end->y
741 if (!winding || tl[j].before != tl[k].before) {
742 cancelEdges(tl[j], tl[k]);
819 QDEBUG() <<
"PROCESS INTERSECTIONS";
822 Intersections::iterator it = intersections.begin();
827 QDEBUG() <<
" swapping intersecting edges ";
840 min = qMin(edgePos, min);
841 max = qMax(edgePos, max);
857 Q_ASSERT(min != max);
858 QDEBUG() <<
"sorting between" << min <<
"and" << max <<
"xpos=" << xmin << xmax;
860 QDEBUG() <<
" adding edge on left";
864 QDEBUG() <<
" adding edge on right";
870 for (
int i = min; i <= max; ++i)
871 QDEBUG() <<
" " << scanline.edges[i]->edge <<
"at pos" << i;
873 for (
int i = min; i <= max; ++i) {
928 QDEBUG() <<
" adding edge" << start <<
"at position" << pos;
952 Q_ASSERT(v
->y == next
->y);
968static void checkLinkChain(
const QTessellatorPrivate::Intersections &intersections,
969 QTessellatorPrivate::Intersection i)
974 QTessellatorPrivate::IntersectionLink l = intersections.value(i);
978 Q_ASSERT(l.next != -1);
979 Q_ASSERT(l.prev != -1);
981 QTessellatorPrivate::Intersection i2 = i;
983 QTessellatorPrivate::IntersectionLink l2 = intersections.value(i2);
985 Q_ASSERT(l2.next != -1);
986 Q_ASSERT(l2.prev != -1);
987 Q_ASSERT(l.next == i2.edge);
988 Q_ASSERT(l2.prev == i.edge);
1003 Q_ASSERT(l
.next != -1);
1004 Q_ASSERT(l
.prev != -1);
1011 Q_ASSERT(l2
.next != -1);
1012 Q_ASSERT(l2
.prev != -1);
1038 QDEBUG() <<
" no intersection";
1046 QDEBUG() <<
" ----->>>>>> WRONG ORDER!";
1068 checkLinkChain(intersections, i1);
1069 checkLinkChain(intersections, i2);
1070 Q_ASSERT(edgeInChain(i1, i2.edge));
1073 }
else if (link1
.next == -1 || link2
.next == -1) {
1074 if (link2
.next == -1) {
1076 qSwap(link1, link2);
1078 Q_ASSERT(link1
.next == -1);
1080 checkLinkChain(intersections, i2);
1091 Q_ASSERT(link
.prev != -1);
1095 bool connected = edgeInChain(i1, i2
.edge);
1099 checkLinkChain(intersections, i1);
1100 checkLinkChain(intersections, i2);
1125 checkLinkChain(intersections, i1);
1126 checkLinkChain(intersections, i2);
1127 Q_ASSERT(edgeInChain(i1, i2.edge));
1137 QDEBUG() <<
"INTERSECTIONS";
1140 for (
int i = 0; i < scanline.size; ++i) {
1141 Edge *e = scanline.edges[i];
1142 QDEBUG() <<
" " << i << e->edge <<
"isect=(" << e->intersect_left << e->intersect_right
1152 addIntersection(e1, e2);
1156 if (intersections.constBegin().key().y == y) {
1157 QDEBUG() <<
"----------------> intersection on same line";
1158 scanline.clearMarks();
1159 scanline.processIntersections(y, &intersections);
1184 Q_ASSERT(points[0] == points[nPoints-1]);
1188 QDEBUG()<<
"POINTS:";
1189 for (
int i = 0; i < nPoints; ++i) {
1190 QDEBUG() << points[i];
1198 int maxActiveEdges = 0;
1199 QRectF br = d->collectAndSortVertices(points, &maxActiveEdges);
1203 QDEBUG() <<
"nPoints = " << nPoints <<
"using " << d->vertices.nPoints;
1204 QDEBUG()<<
"VERTICES:";
1205 for (
int i = 0; i < d->vertices.nPoints; ++i) {
1206 QDEBUG() <<
" " << i <<
": "
1207 <<
"point=" << d->vertices.position(d->vertices.sorted[i])
1208 <<
"flags=" << d->vertices.sorted[i]->flags
1209 <<
"pos=(" << Q27Dot5ToDouble(d->vertices.sorted[i]->x) <<
'/'
1210 << Q27Dot5ToDouble(d->vertices.sorted[i]->y) <<
')';
1236 QDEBUG()<<
"===== edges:";
1237 for (
int i = 0; i < d->scanline.size; ++i) {
1238 QDEBUG() <<
" " << d->scanline.edges[i]->edge
1239 <<
"p0= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v0->x)
1240 <<
'/' << Q27Dot5ToDouble(d->scanline.edges[i]->v0->y)
1241 <<
") p1= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v1->x)
1242 <<
'/' << Q27Dot5ToDouble(d->scanline.edges[i]->v1->y) <<
')'
1243 <<
"x=" << Q27Dot5ToDouble(d->scanline.edges[i]->positionAt(d->y))
1245 << ((i < d->scanline.size - 1)
1246 ? d->scanline.edges[i]->isLeftOf(*d->scanline.edges[i+1], d->y)
1260 Q_ASSERT(points[0] == points[nPoints-1]);
1266 for (
int i = 0; i < nPoints; ++i) {
1271 int left = 0, right = 0;
1274 for (
int i = 1; i < nPoints; ++i) {
1279 left = (top + nPoints - 1) % nPoints;
1280 right = (top + 1) % nPoints;
1283 left = (left + nPoints - 1) % nPoints;
1286 right = (right + 1) % nPoints;
1302 if (cross < 0 || (cross == 0 && dLeft
.x > 0)) {
1314 left = (left + nPoints - dir) % nPoints;
1319 right = (right + nPoints + dir) % nPoints;
1339 right = (right + nPoints + dir) % nPoints;
1345 left = (left + nPoints - dir) % nPoints;
1358 QPointF pa = a_, pb = b_;
1367 if (delta
.x == 0 && delta
.y == 0)
1370 qreal hw = 0.5 * width;
1380 Vertex bottomLeft = { a
.x - halfWidth, b
.y };
1381 Vertex bottomRight = { a
.x + halfWidth, b
.y };
1385 }
else if (delta
.y == 0) {
1396 Vertex bottomLeft = { a
.x, a
.y + halfWidth };
1397 Vertex bottomRight = { b
.x, a
.y + halfWidth };
1402 QPointF perp(pb.y() - pa.y(), pa.x() - pb.x());
1403 qreal length = qSqrt(perp.x() * perp.x() + perp.y() * perp.y());
1405 if (qFuzzyIsNull(length))
1409 perp *= hw / length;
1411 QPointF pta = pa + perp;
1412 QPointF ptb = pa - perp;
1413 QPointF ptc = pb - perp;
1414 QPointF ptd = pb + perp;
bool operator()(const Edge *e1, const Edge *e2)
void insert(int pos, const Edge &e)
int findEdgePosition(Q27Dot5 x, Q27Dot5 y) const
void markEdges(int pos1, int pos2)
int findEdge(int edge) const
void swap(int p1, int p2)
int findEdgePosition(const Edge &e) const
void init(int maxActiveEdges)
void processIntersections()
QMap< Intersection, IntersectionLink > Intersections
QRectF collectAndSortVertices(const QPointF *points, int *maxActiveEdges)
Intersections intersections
void cancelCoincidingEdges()
void emitEdges(QTessellator *tessellator)
void tessellateConvex(const QPointF *points, int nPoints)
void tessellateRect(const QPointF &a, const QPointF &b, qreal width)
QRectF tessellate(const QPointF *points, int nPoints)
virtual void addTrap(const Trapezoid &trap)=0
static bool compareVertex(const QTessellatorPrivate::Vertex *p1, const QTessellatorPrivate::Vertex *p2)
static const bool emit_clever
static void cancelEdges(QCoincidingEdge &e1, QCoincidingEdge &e2)
static const bool mark_clever
static void fillTrapezoid(Q27Dot5 y1, Q27Dot5 y2, int left, int right, const QTessellatorPrivate::Vertices &vertices, QTessellator::Trapezoid *trap)
static bool sameSign(qint64 a, qint64 b)
#define FloatToQ27Dot5(i)
#define Q27Dot5ToDouble(i)
bool operator<(const QCoincidingEdge &e2) const
QTessellatorPrivate::Vertex * start
QTessellatorPrivate::Vertex * end
Edge(const Vertices &v, int _edge)
bool intersect(const Edge &other, Q27Dot5 *y, bool *det_positive) const
bool isLeftOf(const Edge &other, Q27Dot5 y) const
Q27Dot5 positionAt(Q27Dot5 y) const
bool operator<(const Intersection &other) const
int nextPos(const Vertex *v) const
void init(int maxVertices)
int position(const Vertex *v) const
const Vertex * operator[](int i) const
Vertex * operator[](int i)
int prevPos(const Vertex *v) const
const Vertex * next(const Vertex *v) const
const Vertex * prev(const Vertex *v) const
const Vertex * bottomRight
const Vertex * bottomLeft