21#define QDEBUG if (1){} else qDebug
106 void init(
int maxActiveEdges);
136 enum { default_alloc = 32 };
143 void init(
int maxVertices);
200 void addIntersection(
const Edge *e1,
const Edge *e2);
267 QDEBUG() <<
" " << r3 << r4;
268 if (r3 != 0 && r4 != 0 &&
sameSign( r3, r4 ))
291 *det_positive = (det > 0);
315 return edge <
other.edge;
329 return ((yi >
y) ^ (det < 0));
335 if (
p1->y ==
p2->y) {
338 return p1->x <
p2->x;
340 return p1->y <
p2->y;
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);
428 if (edges[
pos]->isLeftOf(
e,
e.v0->y)) {
440 for (
int i = 0;
i <
size; ++
i) {
441 int item_edge = edges[
i]->edge;
442 if (item_edge == edge)
451 for (
int i = 0;
i <
size; ++
i) {
452 edges[
i]->mark =
false;
453 edges[
i]->intersect_left =
false;
454 edges[
i]->intersect_right =
false;
477 (*e)->edge = first_unused;
478 first_unused = (*
e - edge_table);
486 Edge *edge = edge_table + first_unused;
487 first_unused = edge->
edge;
508 for (
int i = pos1;
i <= pos2; ++
i)
509 edges[
i]->mark =
true;
531 if (!
storage || maxVertices > allocated) {
532 int size =
qMax((
int)default_alloc, maxVertices);
535 allocated = maxVertices;
541 if (allocated > default_alloc) {
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;
701 if (
v->x !=
n->x ||
v->y !=
n->y)
704 if (testListSize > tlSize - 2) {
705 tlSize =
qMax(tlSize*2, 16);
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);
731 for (
int j = 0;
j < testListSize; ++
j) {
735 for (
int k =
j + 1; k < testListSize; ++k) {
741 if (!
winding || tl[
j].before != tl[k].before) {
819 QDEBUG() <<
"PROCESS INTERSECTIONS";
827 QDEBUG() <<
" swapping intersecting edges ";
840 min =
qMin(edgePos, min);
841 max =
qMax(edgePos, 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)
873 for (
int i = min;
i <= max; ++
i) {
994bool QTessellatorPrivate::edgeInChain(Intersection
i,
int edge)
1006 Intersection i2 =
i;
1022void QTessellatorPrivate::addIntersection(
const Edge *e1,
const Edge *e2)
1024 const IntersectionLink emptyLink = {-1, -1};
1027 if (e2->edge ==
next)
1030 if (e2->edge == prev)
1035 bool isect = e1->intersect(*e2, &yi, &det_positive);
1036 QDEBUG(
"checking edges %d and %d", e1->edge, e2->edge);
1038 QDEBUG() <<
" no intersection";
1046 QDEBUG() <<
" ----->>>>>> WRONG ORDER!";
1049 QDEBUG() <<
" between edges " << e1->edge <<
"and" << e2->edge <<
"at point ("
1062 if (link1.next == -1 && link2.next == -1) {
1063 link1.
next = link1.prev = i2.edge;
1064 link2.next = link2.prev = i1.edge;
1065 }
else if (link1.next == i2.edge || link1.prev == i2.edge
1066 || link2.next == i1.edge || link2.prev == i1.edge) {
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);
1083 link1.next = i2.edge;
1084 link1.prev = link2.prev;
1085 link2.prev = i1.edge;
1088 other.edge = link1.prev;
1092 link.next = i1.edge;
1095 bool connected = edgeInChain(i1, i2.edge);
1105 Intersection other1;
1107 other1.edge = link1.next;
1109 Intersection other2;
1111 other2.edge = link2.
next;
1114 linko1.
prev = i2.edge;
1115 link2.next = other1.edge;
1117 linko2.prev = i1.edge;
1118 link1.next = other2.edge;
1127 Q_ASSERT(edgeInChain(i1, i2.edge));
1137 QDEBUG() <<
"INTERSECTIONS";
1142 QDEBUG() <<
" " <<
i <<
e->edge <<
"isect=(" <<
e->intersect_left <<
e->intersect_right
1152 addIntersection(e1, e2);
1157 QDEBUG() <<
"----------------> intersection on same line";
1189 for (
int i = 0;
i < nPoints; ++
i) {
1195 d->vertices.nPoints = nPoints;
1196 d->vertices.init(nPoints);
1198 int maxActiveEdges = 0;
1199 QRectF br =
d->collectAndSortVertices(
points, &maxActiveEdges);
1200 d->cancelCoincidingEdges();
1203 QDEBUG() <<
"nPoints = " << nPoints <<
"using " <<
d->vertices.nPoints;
1205 for (
int i = 0;
i <
d->vertices.nPoints; ++
i) {
1207 <<
"point=" <<
d->vertices.position(
d->vertices.sorted[
i])
1208 <<
"flags=" <<
d->vertices.sorted[
i]->flags
1214 d->scanline.init(maxActiveEdges);
1216 d->currentVertex = 0;
1218 while (
d->currentVertex <
d->vertices.nPoints) {
1219 d->scanline.clearMarks();
1221 d->y =
d->vertices.sorted[
d->currentVertex]->y;
1222 if (!
d->intersections.isEmpty())
1223 d->y =
qMin(
d->y,
d->intersections.constBegin().key().y);
1227 d->scanline.prepareLine();
1228 d->processIntersections();
1231 d->addIntersections();
1233 d->scanline.lineDone();
1236 QDEBUG()<<
"===== edges:";
1237 for (
int i = 0;
i <
d->scanline.size; ++
i) {
1238 QDEBUG() <<
" " <<
d->scanline.edges[
i]->edge
1245 << ((
i <
d->scanline.size - 1)
1246 ?
d->scanline.edges[
i]->isLeftOf(*
d->scanline.edges[
i+1],
d->y)
1253 d->intersections.clear();
1263 d->vertices.nPoints = nPoints;
1264 d->vertices.init(nPoints);
1266 for (
int i = 0;
i < nPoints; ++
i) {
1274 for (
int i = 1;
i < nPoints; ++
i) {
1275 if (
d->vertices[
i]->y <
d->vertices[
top]->y)
1279 left = (
top + nPoints - 1) % nPoints;
1283 left = (
left + nPoints - 1) % nPoints;
1294 d->vertices[
top]->y -
d->vertices[
left]->y };
1297 d->vertices[
right]->y -
d->vertices[
top]->y };
1299 Q27Dot5 cross = dLeft.
x * dRight.
y - dLeft.
y * dRight.
x;
1302 if (cross < 0 || (cross == 0 && dLeft.
x > 0)) {
1313 lastLeft =
d->vertices[
left];
1318 lastRight =
d->vertices[
right];
1323 trap.
top =
qMax(lastRight->
y, lastLeft->
y);
1336 if (
d->vertices[
right]->y <
d->vertices[
left]->y) {
1338 lastRight =
d->vertices[
right];
1344 lastLeft =
d->vertices[
left];
1367 if (delta.
x == 0 && delta.
y == 0)
1378 Vertex topLeft = {
a.
x - halfWidth,
a.y };
1379 Vertex topRight = {
a.
x + halfWidth,
a.y };
1380 Vertex bottomLeft = {
a.
x - halfWidth,
b.y };
1381 Vertex bottomRight = {
a.
x + halfWidth,
b.y };
1385 }
else if (delta.
y == 0) {
1394 Vertex topLeft = {
a.
x,
a.y - halfWidth };
1395 Vertex topRight = {
b.
x,
a.y - halfWidth };
1396 Vertex bottomLeft = {
a.
x,
a.y + halfWidth };
1397 Vertex bottomRight = {
b.
x,
a.y + halfWidth };
iterator insert(const Key &key, const T &value)
T value(const Key &key, const T &defaultValue=T()) const
size_type remove(const Key &key)
iterator find(const Key &key)
const_iterator constBegin() const
\inmodule QtCore\reentrant
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
\inmodule QtCore\reentrant
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)
void init(int maxActiveEdges)
void processIntersections()
QRectF collectAndSortVertices(const QPointF *points, int *maxActiveEdges)
QMap< Intersection, IntersectionLink > Intersections
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
QSet< QString >::iterator it
Combined button and popup list for selecting options.
#define QT_WARNING_DISABLE_CLANG(text)
bool qFuzzyIsNull(qfloat16 f) noexcept
qfloat16 qSqrt(qfloat16 f)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLdouble GLdouble GLdouble GLdouble top
GLenum GLuint GLintptr offset
GLfixed GLfixed GLint GLint GLfixed points
GLfixed GLfixed GLfixed y2
static bool compareVertex(const QTessellatorPrivate::Vertex *p1, const QTessellatorPrivate::Vertex *p2)
static void cancelEdges(QCoincidingEdge &e1, QCoincidingEdge &e2)
static const bool mark_clever
static const bool emit_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)
unsigned long long quint64
QTessellatorPrivate::Vertex * end
bool operator<(const QCoincidingEdge &e2) const
QTessellatorPrivate::Vertex * start
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
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