|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtOpenGL module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qtriangulator_p.h" |
|
43 |
|
44 #include <QtGui/qdialog.h> |
|
45 #include <QtGui/qevent.h> |
|
46 #include <QtGui/qpainter.h> |
|
47 #include <QtGui/qpainterpath.h> |
|
48 #include <QtGui/private/qbezier_p.h> |
|
49 #include <QtGui/private/qdatabuffer_p.h> |
|
50 #include <QtCore/qbitarray.h> |
|
51 #include <QtCore/qvarlengtharray.h> |
|
52 #include <QtCore/qqueue.h> |
|
53 #include <QtCore/qglobal.h> |
|
54 #include <QtCore/qpoint.h> |
|
55 #include <QtCore/qalgorithms.h> |
|
56 #include <QtDebug> |
|
57 |
|
58 #include <math.h> |
|
59 |
|
60 QT_BEGIN_NAMESPACE |
|
61 |
|
62 //#define Q_TRIANGULATOR_DEBUG |
|
63 |
|
64 #define Q_FIXED_POINT_SCALE 32 |
|
65 |
|
66 // Quick sort. |
|
67 template <class T, class LessThan> |
|
68 static void sort(T *array, int count, LessThan lessThan) |
|
69 { |
|
70 // If the number of elements fall below some threshold, use insertion sort. |
|
71 const int INSERTION_SORT_LIMIT = 7; // About 7 is fastest on my computer... |
|
72 if (count <= INSERTION_SORT_LIMIT) { |
|
73 for (int i = 1; i < count; ++i) { |
|
74 T temp = array[i]; |
|
75 int j = i; |
|
76 while (j > 0 && lessThan(temp, array[j - 1])) { |
|
77 array[j] = array[j - 1]; |
|
78 --j; |
|
79 } |
|
80 array[j] = temp; |
|
81 } |
|
82 return; |
|
83 } |
|
84 |
|
85 int high = count - 1; |
|
86 int low = 0; |
|
87 int mid = high / 2; |
|
88 if (lessThan(array[mid], array[low])) |
|
89 qSwap(array[mid], array[low]); |
|
90 if (lessThan(array[high], array[mid])) |
|
91 qSwap(array[high], array[mid]); |
|
92 if (lessThan(array[mid], array[low])) |
|
93 qSwap(array[mid], array[low]); |
|
94 |
|
95 --high; |
|
96 ++low; |
|
97 qSwap(array[mid], array[high]); |
|
98 int pivot = high; |
|
99 --high; |
|
100 |
|
101 while (low <= high) { |
|
102 while (!lessThan(array[pivot], array[low])) { |
|
103 ++low; |
|
104 if (low > high) |
|
105 goto sort_loop_end; |
|
106 } |
|
107 while (!lessThan(array[high], array[pivot])) { |
|
108 --high; |
|
109 if (low > high) |
|
110 goto sort_loop_end; |
|
111 } |
|
112 qSwap(array[low], array[high]); |
|
113 ++low; |
|
114 --high; |
|
115 } |
|
116 sort_loop_end: |
|
117 if (low != pivot) |
|
118 qSwap(array[pivot], array[low]); |
|
119 sort(array, low, lessThan); |
|
120 sort(array + low + 1, count - low - 1, lessThan); |
|
121 } |
|
122 |
|
123 // Quick sort. |
|
124 template <class T> |
|
125 static void sort(T *array, int count) |
|
126 { |
|
127 // If the number of elements fall below some threshold, use insertion sort. |
|
128 const int INSERTION_SORT_LIMIT = 25; // About 25 is fastest on my computer... |
|
129 if (count <= INSERTION_SORT_LIMIT) { |
|
130 for (int i = 1; i < count; ++i) { |
|
131 T temp = array[i]; |
|
132 int j = i; |
|
133 while (j > 0 && (temp < array[j - 1])) { |
|
134 array[j] = array[j - 1]; |
|
135 --j; |
|
136 } |
|
137 array[j] = temp; |
|
138 } |
|
139 return; |
|
140 } |
|
141 |
|
142 int high = count - 1; |
|
143 int low = 0; |
|
144 int mid = high / 2; |
|
145 if ((array[mid] < array[low])) |
|
146 qSwap(array[mid], array[low]); |
|
147 if ((array[high] < array[mid])) |
|
148 qSwap(array[high], array[mid]); |
|
149 if ((array[mid] < array[low])) |
|
150 qSwap(array[mid], array[low]); |
|
151 |
|
152 --high; |
|
153 ++low; |
|
154 qSwap(array[mid], array[high]); |
|
155 int pivot = high; |
|
156 --high; |
|
157 |
|
158 while (low <= high) { |
|
159 while (!(array[pivot] < array[low])) { |
|
160 ++low; |
|
161 if (low > high) |
|
162 goto sort_loop_end; |
|
163 } |
|
164 while (!(array[high] < array[pivot])) { |
|
165 --high; |
|
166 if (low > high) |
|
167 goto sort_loop_end; |
|
168 } |
|
169 qSwap(array[low], array[high]); |
|
170 ++low; |
|
171 --high; |
|
172 } |
|
173 sort_loop_end: |
|
174 if (low != pivot) |
|
175 qSwap(array[pivot], array[low]); |
|
176 sort(array, low); |
|
177 sort(array + low + 1, count - low - 1); |
|
178 } |
|
179 |
|
180 //============================================================================// |
|
181 // QFraction // |
|
182 //============================================================================// |
|
183 |
|
184 // Fraction must be in the range [0, 1) |
|
185 struct QFraction |
|
186 { |
|
187 // Comparison operators must not be called on invalid fractions. |
|
188 inline bool operator < (const QFraction &other) const; |
|
189 inline bool operator == (const QFraction &other) const; |
|
190 inline bool operator != (const QFraction &other) const {return !(*this == other);} |
|
191 inline bool operator > (const QFraction &other) const {return other < *this;} |
|
192 inline bool operator >= (const QFraction &other) const {return !(*this < other);} |
|
193 inline bool operator <= (const QFraction &other) const {return !(*this > other);} |
|
194 |
|
195 inline bool isValid() const {return denominator != 0;} |
|
196 |
|
197 // numerator and denominator must not have common denominators. |
|
198 quint64 numerator, denominator; |
|
199 }; |
|
200 |
|
201 static inline quint64 gcd(quint64 x, quint64 y) |
|
202 { |
|
203 while (y != 0) { |
|
204 quint64 z = y; |
|
205 y = x % y; |
|
206 x = z; |
|
207 } |
|
208 return x; |
|
209 } |
|
210 |
|
211 static inline int compare(quint64 a, quint64 b) |
|
212 { |
|
213 return (a > b) - (a < b); |
|
214 } |
|
215 |
|
216 // Compare a/b with c/d. |
|
217 // Return negative if less, 0 if equal, positive if greater. |
|
218 // a < b, c < d |
|
219 static int qCompareFractions(quint64 a, quint64 b, quint64 c, quint64 d) |
|
220 { |
|
221 const quint64 LIMIT = Q_UINT64_C(0x100000000); |
|
222 for (;;) { |
|
223 // If the products 'ad' and 'bc' fit into 64 bits, they can be directly compared. |
|
224 if (b < LIMIT && d < LIMIT) |
|
225 return compare(a * d, b * c); |
|
226 |
|
227 if (a == 0 || c == 0) |
|
228 return compare(a, c); |
|
229 |
|
230 // a/b < c/d <=> d/c < b/a |
|
231 quint64 b_div_a = b / a; |
|
232 quint64 d_div_c = d / c; |
|
233 if (b_div_a != d_div_c) |
|
234 return compare(d_div_c, b_div_a); |
|
235 |
|
236 // floor(d/c) == floor(b/a) |
|
237 // frac(d/c) < frac(b/a) ? |
|
238 // frac(x/y) = (x%y)/y |
|
239 d -= d_div_c * c; //d %= c; |
|
240 b -= b_div_a * a; //b %= a; |
|
241 qSwap(a, d); |
|
242 qSwap(b, c); |
|
243 } |
|
244 } |
|
245 |
|
246 // Fraction must be in the range [0, 1) |
|
247 // Assume input is valid. |
|
248 static QFraction qFraction(quint64 n, quint64 d) { |
|
249 QFraction result; |
|
250 if (n == 0) { |
|
251 result.numerator = 0; |
|
252 result.denominator = 1; |
|
253 } else { |
|
254 quint64 g = gcd(n, d); |
|
255 result.numerator = n / g; |
|
256 result.denominator = d / g; |
|
257 } |
|
258 return result; |
|
259 } |
|
260 |
|
261 inline bool QFraction::operator < (const QFraction &other) const |
|
262 { |
|
263 return qCompareFractions(numerator, denominator, other.numerator, other.denominator) < 0; |
|
264 } |
|
265 |
|
266 inline bool QFraction::operator == (const QFraction &other) const |
|
267 { |
|
268 return numerator == other.numerator && denominator == other.denominator; |
|
269 } |
|
270 |
|
271 //============================================================================// |
|
272 // QPodPoint // |
|
273 //============================================================================// |
|
274 |
|
275 struct QPodPoint |
|
276 { |
|
277 inline bool operator < (const QPodPoint &other) const |
|
278 { |
|
279 if (y != other.y) |
|
280 return y < other.y; |
|
281 return x < other.x; |
|
282 } |
|
283 |
|
284 inline bool operator > (const QPodPoint &other) const {return other < *this;} |
|
285 inline bool operator <= (const QPodPoint &other) const {return !(*this > other);} |
|
286 inline bool operator >= (const QPodPoint &other) const {return !(*this < other);} |
|
287 inline bool operator == (const QPodPoint &other) const {return x == other.x && y == other.y;} |
|
288 inline bool operator != (const QPodPoint &other) const {return x != other.x || y != other.y;} |
|
289 |
|
290 inline QPodPoint &operator += (const QPodPoint &other) {x += other.x; y += other.y; return *this;} |
|
291 inline QPodPoint &operator -= (const QPodPoint &other) {x -= other.x; y -= other.y; return *this;} |
|
292 inline QPodPoint operator + (const QPodPoint &other) const {QPodPoint result = {x + other.x, y + other.y}; return result;} |
|
293 inline QPodPoint operator - (const QPodPoint &other) const {QPodPoint result = {x - other.x, y - other.y}; return result;} |
|
294 |
|
295 int x; |
|
296 int y; |
|
297 }; |
|
298 |
|
299 static inline qint64 qCross(const QPodPoint &u, const QPodPoint &v) |
|
300 { |
|
301 return qint64(u.x) * qint64(v.y) - qint64(u.y) * qint64(v.x); |
|
302 } |
|
303 |
|
304 static inline qint64 qDot(const QPodPoint &u, const QPodPoint &v) |
|
305 { |
|
306 return qint64(u.x) * qint64(v.x) + qint64(u.y) * qint64(v.y); |
|
307 } |
|
308 |
|
309 // Return positive value if 'p' is to the right of the line 'v1'->'v2', negative if left of the |
|
310 // line and zero if exactly on the line. |
|
311 // The returned value is the z-component of the qCross product between 'v2-v1' and 'p-v1', |
|
312 // which is twice the signed area of the triangle 'p'->'v1'->'v2' (positive for CW order). |
|
313 static inline qint64 qPointDistanceFromLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2) |
|
314 { |
|
315 return qCross(v2 - v1, p - v1); |
|
316 } |
|
317 |
|
318 static inline bool qPointIsLeftOfLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2) |
|
319 { |
|
320 return qPointDistanceFromLine(p, v1, v2) < 0; |
|
321 } |
|
322 |
|
323 // Return: |
|
324 // -1 if u < v |
|
325 // 0 if u == v |
|
326 // 1 if u > v |
|
327 static int comparePoints(const QPodPoint &u, const QPodPoint &v) |
|
328 { |
|
329 if (u.y < v.y) |
|
330 return -1; |
|
331 if (u.y > v.y) |
|
332 return 1; |
|
333 if (u.x < v.x) |
|
334 return -1; |
|
335 if (u.x > v.x) |
|
336 return 1; |
|
337 return 0; |
|
338 } |
|
339 |
|
340 //============================================================================// |
|
341 // QIntersectionPoint // |
|
342 //============================================================================// |
|
343 |
|
344 struct QIntersectionPoint |
|
345 { |
|
346 inline bool isValid() const {return xOffset.isValid() && yOffset.isValid();} |
|
347 QPodPoint round() const; |
|
348 inline bool isAccurate() const {return xOffset.numerator == 0 && yOffset.numerator == 0;} |
|
349 bool operator < (const QIntersectionPoint &other) const; |
|
350 bool operator == (const QIntersectionPoint &other) const; |
|
351 inline bool operator != (const QIntersectionPoint &other) const {return !(*this == other);} |
|
352 inline bool operator > (const QIntersectionPoint &other) const {return other < *this;} |
|
353 inline bool operator >= (const QIntersectionPoint &other) const {return !(*this < other);} |
|
354 inline bool operator <= (const QIntersectionPoint &other) const {return !(*this > other);} |
|
355 bool isOnLine(const QPodPoint &u, const QPodPoint &v) const; |
|
356 |
|
357 QPodPoint upperLeft; |
|
358 QFraction xOffset; |
|
359 QFraction yOffset; |
|
360 }; |
|
361 |
|
362 static inline QIntersectionPoint qIntersectionPoint(const QPodPoint &point) |
|
363 { |
|
364 // upperLeft = point, xOffset = 0/1, yOffset = 0/1. |
|
365 QIntersectionPoint p = {{point.x, point.y}, {0, 1}, {0, 1}}; |
|
366 return p; |
|
367 } |
|
368 |
|
369 static inline QIntersectionPoint qIntersectionPoint(int x, int y) |
|
370 { |
|
371 // upperLeft = (x, y), xOffset = 0/1, yOffset = 0/1. |
|
372 QIntersectionPoint p = {{x, y}, {0, 1}, {0, 1}}; |
|
373 return p; |
|
374 } |
|
375 |
|
376 static QIntersectionPoint qIntersectionPoint(const QPodPoint &u1, const QPodPoint &u2, const QPodPoint &v1, const QPodPoint &v2) |
|
377 { |
|
378 QIntersectionPoint result = {{0, 0}, {0, 0}, {0, 0}}; |
|
379 |
|
380 QPodPoint u = u2 - u1; |
|
381 QPodPoint v = v2 - v1; |
|
382 qint64 d1 = qCross(u, v1 - u1); |
|
383 qint64 d2 = qCross(u, v2 - u1); |
|
384 qint64 det = d2 - d1; |
|
385 qint64 d3 = qCross(v, u1 - v1); |
|
386 qint64 d4 = d3 - det; //qCross(v, u2 - v1); |
|
387 |
|
388 // Check that the math is correct. |
|
389 Q_ASSERT(d4 == qCross(v, u2 - v1)); |
|
390 |
|
391 // The intersection point can be expressed as: |
|
392 // v1 - v * d1/det |
|
393 // v2 - v * d2/det |
|
394 // u1 + u * d3/det |
|
395 // u2 + u * d4/det |
|
396 |
|
397 // I'm only interested in lines that are crossing, so ignore parallel lines even if they overlap. |
|
398 if (det == 0) |
|
399 return result; |
|
400 |
|
401 if (det < 0) { |
|
402 det = -det; |
|
403 d1 = -d1; |
|
404 d2 = -d2; |
|
405 d3 = -d3; |
|
406 d4 = -d4; |
|
407 } |
|
408 |
|
409 // I'm only interested in lines intersecting at their interior, not at their end points. |
|
410 // The lines intersect at their interior if and only if 'd1 < 0', 'd2 > 0', 'd3 < 0' and 'd4 > 0'. |
|
411 if (d1 >= 0 || d2 <= 0 || d3 <= 0 || d4 >= 0) |
|
412 return result; |
|
413 |
|
414 // Calculate the intersection point as follows: |
|
415 // v1 - v * d1/det | v1 <= v2 (component-wise) |
|
416 // v2 - v * d2/det | v2 < v1 (component-wise) |
|
417 |
|
418 // Assuming 21 bits per vector component. |
|
419 // TODO: Make code path for 31 bits per vector component. |
|
420 if (v.x >= 0) { |
|
421 result.upperLeft.x = v1.x + (-v.x * d1) / det; |
|
422 result.xOffset = qFraction(quint64(-v.x * d1) % quint64(det), quint64(det)); |
|
423 } else { |
|
424 result.upperLeft.x = v2.x + (-v.x * d2) / det; |
|
425 result.xOffset = qFraction(quint64(-v.x * d2) % quint64(det), quint64(det)); |
|
426 } |
|
427 |
|
428 if (v.y >= 0) { |
|
429 result.upperLeft.y = v1.y + (-v.y * d1) / det; |
|
430 result.yOffset = qFraction(quint64(-v.y * d1) % quint64(det), quint64(det)); |
|
431 } else { |
|
432 result.upperLeft.y = v2.y + (-v.y * d2) / det; |
|
433 result.yOffset = qFraction(quint64(-v.y * d2) % quint64(det), quint64(det)); |
|
434 } |
|
435 |
|
436 Q_ASSERT(result.xOffset.isValid()); |
|
437 Q_ASSERT(result.yOffset.isValid()); |
|
438 return result; |
|
439 } |
|
440 |
|
441 QPodPoint QIntersectionPoint::round() const |
|
442 { |
|
443 QPodPoint result = upperLeft; |
|
444 if (2 * xOffset.numerator >= xOffset.denominator) |
|
445 ++result.x; |
|
446 if (2 * yOffset.numerator >= yOffset.denominator) |
|
447 ++result.y; |
|
448 return result; |
|
449 } |
|
450 |
|
451 bool QIntersectionPoint::operator < (const QIntersectionPoint &other) const |
|
452 { |
|
453 if (upperLeft.y != other.upperLeft.y) |
|
454 return upperLeft.y < other.upperLeft.y; |
|
455 if (yOffset != other.yOffset) |
|
456 return yOffset < other.yOffset; |
|
457 if (upperLeft.x != other.upperLeft.x) |
|
458 return upperLeft.x < other.upperLeft.x; |
|
459 return xOffset < other.xOffset; |
|
460 } |
|
461 |
|
462 bool QIntersectionPoint::operator == (const QIntersectionPoint &other) const |
|
463 { |
|
464 return upperLeft == other.upperLeft && xOffset == other.xOffset && yOffset == other.yOffset; |
|
465 } |
|
466 |
|
467 // Returns true if this point is on the infinite line passing through 'u' and 'v'. |
|
468 bool QIntersectionPoint::isOnLine(const QPodPoint &u, const QPodPoint &v) const |
|
469 { |
|
470 // TODO: Make code path for coordinates with more than 21 bits. |
|
471 const QPodPoint p = upperLeft - u; |
|
472 const QPodPoint q = v - u; |
|
473 bool isHorizontal = p.y == 0 && yOffset.numerator == 0; |
|
474 bool isVertical = p.x == 0 && xOffset.numerator == 0; |
|
475 if (isHorizontal && isVertical) |
|
476 return true; |
|
477 if (isHorizontal) |
|
478 return q.y == 0; |
|
479 if (q.y == 0) |
|
480 return false; |
|
481 if (isVertical) |
|
482 return q.x == 0; |
|
483 if (q.x == 0) |
|
484 return false; |
|
485 |
|
486 // At this point, 'p+offset' and 'q' cannot lie on the x or y axis. |
|
487 |
|
488 if (((q.x < 0) == (q.y < 0)) != ((p.x < 0) == (p.y < 0))) |
|
489 return false; // 'p + offset' and 'q' pass through different quadrants. |
|
490 |
|
491 // Move all coordinates into the first quadrant. |
|
492 quint64 nx, ny; |
|
493 if (p.x < 0) |
|
494 nx = quint64(-p.x) * xOffset.denominator - xOffset.numerator; |
|
495 else |
|
496 nx = quint64(p.x) * xOffset.denominator + xOffset.numerator; |
|
497 if (p.y < 0) |
|
498 ny = quint64(-p.y) * yOffset.denominator - yOffset.numerator; |
|
499 else |
|
500 ny = quint64(p.y) * yOffset.denominator + yOffset.numerator; |
|
501 |
|
502 return qFraction(quint64(qAbs(q.x)) * xOffset.denominator, quint64(qAbs(q.y)) * yOffset.denominator) == qFraction(nx, ny); |
|
503 } |
|
504 |
|
505 //============================================================================// |
|
506 // QMaxHeap // |
|
507 //============================================================================// |
|
508 |
|
509 template <class T> |
|
510 class QMaxHeap |
|
511 { |
|
512 public: |
|
513 QMaxHeap() : m_data(0) {} |
|
514 inline int size() const {return m_data.size();} |
|
515 inline bool empty() const {return m_data.isEmpty();} |
|
516 inline bool isEmpty() const {return m_data.isEmpty();} |
|
517 void push(const T &x); |
|
518 T pop(); |
|
519 inline const T &top() const {return m_data.first();} |
|
520 private: |
|
521 static inline int parent(int i) {return (i - 1) / 2;} |
|
522 static inline int left(int i) {return 2 * i + 1;} |
|
523 static inline int right(int i) {return 2 * i + 2;} |
|
524 |
|
525 QDataBuffer<T> m_data; |
|
526 }; |
|
527 |
|
528 template <class T> |
|
529 void QMaxHeap<T>::push(const T &x) |
|
530 { |
|
531 int current = m_data.size(); |
|
532 int parent = QMaxHeap::parent(current); |
|
533 m_data.add(x); |
|
534 while (current != 0 && m_data.at(parent) < x) { |
|
535 m_data.at(current) = m_data.at(parent); |
|
536 current = parent; |
|
537 parent = QMaxHeap::parent(current); |
|
538 } |
|
539 m_data.at(current) = x; |
|
540 } |
|
541 |
|
542 template <class T> |
|
543 T QMaxHeap<T>::pop() |
|
544 { |
|
545 T result = m_data.first(); |
|
546 T back = m_data.last(); |
|
547 m_data.pop_back(); |
|
548 if (!m_data.isEmpty()) { |
|
549 int current = 0; |
|
550 for (;;) { |
|
551 int left = QMaxHeap::left(current); |
|
552 int right = QMaxHeap::right(current); |
|
553 if (left >= m_data.size()) |
|
554 break; |
|
555 int greater = left; |
|
556 if (right < m_data.size() && m_data.at(left) < m_data.at(right)) |
|
557 greater = right; |
|
558 if (m_data.at(greater) < back) |
|
559 break; |
|
560 m_data.at(current) = m_data.at(greater); |
|
561 current = greater; |
|
562 } |
|
563 m_data.at(current) = back; |
|
564 } |
|
565 return result; |
|
566 } |
|
567 |
|
568 //============================================================================// |
|
569 // QRBTree // |
|
570 //============================================================================// |
|
571 |
|
572 template <class T> |
|
573 struct QRBTree |
|
574 { |
|
575 struct Node |
|
576 { |
|
577 inline Node() : parent(0), left(0), right(0), red(true) { } |
|
578 inline ~Node() {if (left) delete left; if (right) delete right;} |
|
579 T data; |
|
580 Node *parent; |
|
581 Node *left; |
|
582 Node *right; |
|
583 bool red; |
|
584 }; |
|
585 |
|
586 inline QRBTree() : root(0), freeList(0) { } |
|
587 inline ~QRBTree(); |
|
588 |
|
589 inline void clear(); |
|
590 |
|
591 void attachBefore(Node *parent, Node *child); |
|
592 void attachAfter(Node *parent, Node *child); |
|
593 |
|
594 inline Node *front(Node *node) const; |
|
595 inline Node *back(Node *node) const; |
|
596 Node *next(Node *node) const; |
|
597 Node *previous(Node *node) const; |
|
598 |
|
599 inline void deleteNode(Node *&node); |
|
600 inline Node *newNode(); |
|
601 |
|
602 // Return 1 if 'left' comes after 'right', 0 if equal, and -1 otherwise. |
|
603 // 'left' and 'right' cannot be null. |
|
604 int order(Node *left, Node *right); |
|
605 inline bool verify() const; |
|
606 |
|
607 private: |
|
608 void rotateLeft(Node *node); |
|
609 void rotateRight(Node *node); |
|
610 void update(Node *node); |
|
611 |
|
612 inline void attachLeft(Node *parent, Node *child); |
|
613 inline void attachRight(Node *parent, Node *child); |
|
614 |
|
615 int blackDepth(Node *top) const; |
|
616 bool checkRedBlackProperty(Node *top) const; |
|
617 |
|
618 void swapNodes(Node *n1, Node *n2); |
|
619 void detach(Node *node); |
|
620 |
|
621 // 'node' must be black. rebalance will reduce the depth of black nodes by one in the sibling tree. |
|
622 void rebalance(Node *node); |
|
623 |
|
624 public: |
|
625 Node *root; |
|
626 private: |
|
627 Node *freeList; |
|
628 }; |
|
629 |
|
630 template <class T> |
|
631 inline QRBTree<T>::~QRBTree() |
|
632 { |
|
633 clear(); |
|
634 while (freeList) { |
|
635 // Avoid recursively calling the destructor, as this list may become large. |
|
636 Node *next = freeList->right; |
|
637 freeList->right = 0; |
|
638 delete freeList; |
|
639 freeList = next; |
|
640 } |
|
641 } |
|
642 |
|
643 template <class T> |
|
644 inline void QRBTree<T>::clear() |
|
645 { |
|
646 if (root) |
|
647 delete root; |
|
648 root = 0; |
|
649 } |
|
650 |
|
651 template <class T> |
|
652 void QRBTree<T>::rotateLeft(Node *node) |
|
653 { |
|
654 // | | // |
|
655 // N B // |
|
656 // / \ / \ // |
|
657 // A B ---> N D // |
|
658 // / \ / \ // |
|
659 // C D A C // |
|
660 |
|
661 Node *&ref = (node->parent ? (node == node->parent->left ? node->parent->left : node->parent->right) : root); |
|
662 ref = node->right; |
|
663 node->right->parent = node->parent; |
|
664 |
|
665 // : // |
|
666 // N // |
|
667 // / :| // |
|
668 // A B // |
|
669 // / \ // |
|
670 // C D // |
|
671 |
|
672 node->right = ref->left; |
|
673 if (ref->left) |
|
674 ref->left->parent = node; |
|
675 |
|
676 // : | // |
|
677 // N B // |
|
678 // / \ : \ // |
|
679 // A C D // |
|
680 |
|
681 ref->left = node; |
|
682 node->parent = ref; |
|
683 |
|
684 // | // |
|
685 // B // |
|
686 // / \ // |
|
687 // N D // |
|
688 // / \ // |
|
689 // A C // |
|
690 } |
|
691 |
|
692 template <class T> |
|
693 void QRBTree<T>::rotateRight(Node *node) |
|
694 { |
|
695 // | | // |
|
696 // N A // |
|
697 // / \ / \ // |
|
698 // A B ---> C N // |
|
699 // / \ / \ // |
|
700 // C D D B // |
|
701 |
|
702 Node *&ref = (node->parent ? (node == node->parent->left ? node->parent->left : node->parent->right) : root); |
|
703 ref = node->left; |
|
704 node->left->parent = node->parent; |
|
705 |
|
706 node->left = ref->right; |
|
707 if (ref->right) |
|
708 ref->right->parent = node; |
|
709 |
|
710 ref->right = node; |
|
711 node->parent = ref; |
|
712 } |
|
713 |
|
714 template <class T> |
|
715 void QRBTree<T>::update(Node *node) // call this after inserting a node |
|
716 { |
|
717 for (;;) { |
|
718 Node *parent = node->parent; |
|
719 |
|
720 // if the node is the root, color it black |
|
721 if (!parent) { |
|
722 node->red = false; |
|
723 return; |
|
724 } |
|
725 |
|
726 // if the parent is black, the node can be left red |
|
727 if (!parent->red) |
|
728 return; |
|
729 |
|
730 // at this point, the parent is red and cannot be the root |
|
731 Node *grandpa = parent->parent; |
|
732 Q_ASSERT(grandpa); |
|
733 |
|
734 Node *uncle = (parent == grandpa->left ? grandpa->right : grandpa->left); |
|
735 if (uncle && uncle->red) { |
|
736 // grandpa's black, parent and uncle are red. |
|
737 // let parent and uncle be black, grandpa red and recursively update grandpa. |
|
738 Q_ASSERT(!grandpa->red); |
|
739 parent->red = false; |
|
740 uncle->red = false; |
|
741 grandpa->red = true; |
|
742 node = grandpa; |
|
743 continue; |
|
744 } |
|
745 |
|
746 // at this point, uncle is black |
|
747 if (node == parent->right && parent == grandpa->left) |
|
748 rotateLeft(node = parent); |
|
749 else if (node == parent->left && parent == grandpa->right) |
|
750 rotateRight(node = parent); |
|
751 parent = node->parent; |
|
752 |
|
753 if (parent == grandpa->left) { |
|
754 rotateRight(grandpa); |
|
755 parent->red = false; |
|
756 grandpa->red = true; |
|
757 } else { |
|
758 rotateLeft(grandpa); |
|
759 parent->red = false; |
|
760 grandpa->red = true; |
|
761 } |
|
762 return; |
|
763 } |
|
764 } |
|
765 |
|
766 template <class T> |
|
767 inline void QRBTree<T>::attachLeft(Node *parent, Node *child) |
|
768 { |
|
769 Q_ASSERT(!parent->left); |
|
770 parent->left = child; |
|
771 child->parent = parent; |
|
772 update(child); |
|
773 } |
|
774 |
|
775 template <class T> |
|
776 inline void QRBTree<T>::attachRight(Node *parent, Node *child) |
|
777 { |
|
778 Q_ASSERT(!parent->right); |
|
779 parent->right = child; |
|
780 child->parent = parent; |
|
781 update(child); |
|
782 } |
|
783 |
|
784 template <class T> |
|
785 void QRBTree<T>::attachBefore(Node *parent, Node *child) |
|
786 { |
|
787 if (!root) |
|
788 update(root = child); |
|
789 else if (!parent) |
|
790 attachRight(back(root), child); |
|
791 else if (parent->left) |
|
792 attachRight(back(parent->left), child); |
|
793 else |
|
794 attachLeft(parent, child); |
|
795 } |
|
796 |
|
797 template <class T> |
|
798 void QRBTree<T>::attachAfter(Node *parent, Node *child) |
|
799 { |
|
800 if (!root) |
|
801 update(root = child); |
|
802 else if (!parent) |
|
803 attachLeft(front(root), child); |
|
804 else if (parent->right) |
|
805 attachLeft(front(parent->right), child); |
|
806 else |
|
807 attachRight(parent, child); |
|
808 } |
|
809 |
|
810 template <class T> |
|
811 void QRBTree<T>::swapNodes(Node *n1, Node *n2) |
|
812 { |
|
813 // Since iterators must not be invalidated, it is not sufficient to only swap the data. |
|
814 if (n1->parent == n2) { |
|
815 n1->parent = n2->parent; |
|
816 n2->parent = n1; |
|
817 } else if (n2->parent == n1) { |
|
818 n2->parent = n1->parent; |
|
819 n1->parent = n2; |
|
820 } else { |
|
821 qSwap(n1->parent, n2->parent); |
|
822 } |
|
823 |
|
824 qSwap(n1->left, n2->left); |
|
825 qSwap(n1->right, n2->right); |
|
826 qSwap(n1->red, n2->red); |
|
827 |
|
828 if (n1->parent) { |
|
829 if (n1->parent->left == n2) |
|
830 n1->parent->left = n1; |
|
831 else |
|
832 n1->parent->right = n1; |
|
833 } else { |
|
834 root = n1; |
|
835 } |
|
836 |
|
837 if (n2->parent) { |
|
838 if (n2->parent->left == n1) |
|
839 n2->parent->left = n2; |
|
840 else |
|
841 n2->parent->right = n2; |
|
842 } else { |
|
843 root = n2; |
|
844 } |
|
845 |
|
846 if (n1->left) |
|
847 n1->left->parent = n1; |
|
848 if (n1->right) |
|
849 n1->right->parent = n1; |
|
850 |
|
851 if (n2->left) |
|
852 n2->left->parent = n2; |
|
853 if (n2->right) |
|
854 n2->right->parent = n2; |
|
855 } |
|
856 |
|
857 template <class T> |
|
858 void QRBTree<T>::detach(Node *node) // call this before removing a node. |
|
859 { |
|
860 if (node->right) |
|
861 swapNodes(node, front(node->right)); |
|
862 |
|
863 Node *child = (node->left ? node->left : node->right); |
|
864 |
|
865 if (!node->red) { |
|
866 if (child && child->red) |
|
867 child->red = false; |
|
868 else |
|
869 rebalance(node); |
|
870 } |
|
871 |
|
872 Node *&ref = (node->parent ? (node == node->parent->left ? node->parent->left : node->parent->right) : root); |
|
873 ref = child; |
|
874 if (child) |
|
875 child->parent = node->parent; |
|
876 node->left = node->right = node->parent = 0; |
|
877 } |
|
878 |
|
879 // 'node' must be black. rebalance will reduce the depth of black nodes by one in the sibling tree. |
|
880 template <class T> |
|
881 void QRBTree<T>::rebalance(Node *node) |
|
882 { |
|
883 Q_ASSERT(!node->red); |
|
884 for (;;) { |
|
885 if (!node->parent) |
|
886 return; |
|
887 |
|
888 // at this point, node is not a parent, it is black, thus it must have a sibling. |
|
889 Node *sibling = (node == node->parent->left ? node->parent->right : node->parent->left); |
|
890 Q_ASSERT(sibling); |
|
891 |
|
892 if (sibling->red) { |
|
893 sibling->red = false; |
|
894 node->parent->red = true; |
|
895 if (node == node->parent->left) |
|
896 rotateLeft(node->parent); |
|
897 else |
|
898 rotateRight(node->parent); |
|
899 sibling = (node == node->parent->left ? node->parent->right : node->parent->left); |
|
900 Q_ASSERT(sibling); |
|
901 } |
|
902 |
|
903 // at this point, the sibling is black. |
|
904 Q_ASSERT(!sibling->red); |
|
905 |
|
906 if ((!sibling->left || !sibling->left->red) && (!sibling->right || !sibling->right->red)) { |
|
907 bool parentWasRed = node->parent->red; |
|
908 sibling->red = true; |
|
909 node->parent->red = false; |
|
910 if (parentWasRed) |
|
911 return; |
|
912 node = node->parent; |
|
913 continue; |
|
914 } |
|
915 |
|
916 // at this point, at least one of the sibling's children is red. |
|
917 |
|
918 if (node == node->parent->left) { |
|
919 if (!sibling->right || !sibling->right->red) { |
|
920 Q_ASSERT(sibling->left); |
|
921 sibling->red = true; |
|
922 sibling->left->red = false; |
|
923 rotateRight(sibling); |
|
924 |
|
925 sibling = sibling->parent; |
|
926 Q_ASSERT(sibling); |
|
927 } |
|
928 sibling->red = node->parent->red; |
|
929 node->parent->red = false; |
|
930 |
|
931 Q_ASSERT(sibling->right->red); |
|
932 sibling->right->red = false; |
|
933 rotateLeft(node->parent); |
|
934 } else { |
|
935 if (!sibling->left || !sibling->left->red) { |
|
936 Q_ASSERT(sibling->right); |
|
937 sibling->red = true; |
|
938 sibling->right->red = false; |
|
939 rotateLeft(sibling); |
|
940 |
|
941 sibling = sibling->parent; |
|
942 Q_ASSERT(sibling); |
|
943 } |
|
944 sibling->red = node->parent->red; |
|
945 node->parent->red = false; |
|
946 |
|
947 Q_ASSERT(sibling->left->red); |
|
948 sibling->left->red = false; |
|
949 rotateRight(node->parent); |
|
950 } |
|
951 return; |
|
952 } |
|
953 } |
|
954 |
|
955 template <class T> |
|
956 inline typename QRBTree<T>::Node *QRBTree<T>::front(Node *node) const |
|
957 { |
|
958 while (node->left) |
|
959 node = node->left; |
|
960 return node; |
|
961 } |
|
962 |
|
963 template <class T> |
|
964 inline typename QRBTree<T>::Node *QRBTree<T>::back(Node *node) const |
|
965 { |
|
966 while (node->right) |
|
967 node = node->right; |
|
968 return node; |
|
969 } |
|
970 |
|
971 template <class T> |
|
972 typename QRBTree<T>::Node *QRBTree<T>::next(Node *node) const |
|
973 { |
|
974 if (node->right) |
|
975 return front(node->right); |
|
976 while (node->parent && node == node->parent->right) |
|
977 node = node->parent; |
|
978 return node->parent; |
|
979 } |
|
980 |
|
981 template <class T> |
|
982 typename QRBTree<T>::Node *QRBTree<T>::previous(Node *node) const |
|
983 { |
|
984 if (node->left) |
|
985 return back(node->left); |
|
986 while (node->parent && node == node->parent->left) |
|
987 node = node->parent; |
|
988 return node->parent; |
|
989 } |
|
990 |
|
991 template <class T> |
|
992 int QRBTree<T>::blackDepth(Node *top) const |
|
993 { |
|
994 if (!top) |
|
995 return 0; |
|
996 int leftDepth = blackDepth(top->left); |
|
997 int rightDepth = blackDepth(top->right); |
|
998 if (leftDepth != rightDepth) |
|
999 return -1; |
|
1000 if (!top->red) |
|
1001 ++leftDepth; |
|
1002 return leftDepth; |
|
1003 } |
|
1004 |
|
1005 template <class T> |
|
1006 bool QRBTree<T>::checkRedBlackProperty(Node *top) const |
|
1007 { |
|
1008 if (!top) |
|
1009 return true; |
|
1010 if (top->left && !checkRedBlackProperty(top->left)) |
|
1011 return false; |
|
1012 if (top->right && !checkRedBlackProperty(top->right)) |
|
1013 return false; |
|
1014 return !(top->red && ((top->left && top->left->red) || (top->right && top->right->red))); |
|
1015 } |
|
1016 |
|
1017 template <class T> |
|
1018 inline bool QRBTree<T>::verify() const |
|
1019 { |
|
1020 return checkRedBlackProperty(root) && blackDepth(root) != -1; |
|
1021 } |
|
1022 |
|
1023 template <class T> |
|
1024 inline void QRBTree<T>::deleteNode(Node *&node) |
|
1025 { |
|
1026 Q_ASSERT(node); |
|
1027 detach(node); |
|
1028 node->right = freeList; |
|
1029 freeList = node; |
|
1030 node = 0; |
|
1031 } |
|
1032 |
|
1033 template <class T> |
|
1034 inline typename QRBTree<T>::Node *QRBTree<T>::newNode() |
|
1035 { |
|
1036 if (freeList) { |
|
1037 Node *node = freeList; |
|
1038 freeList = freeList->right; |
|
1039 node->parent = node->left = node->right = 0; |
|
1040 node->red = true; |
|
1041 return node; |
|
1042 } |
|
1043 return new Node; |
|
1044 } |
|
1045 |
|
1046 // Return 1 if 'left' comes after 'right', 0 if equal, and -1 otherwise. |
|
1047 // 'left' and 'right' cannot be null. |
|
1048 template <class T> |
|
1049 int QRBTree<T>::order(Node *left, Node *right) |
|
1050 { |
|
1051 Q_ASSERT(left && right); |
|
1052 if (left == right) |
|
1053 return 0; |
|
1054 |
|
1055 QVector<Node *> leftAncestors; |
|
1056 QVector<Node *> rightAncestors; |
|
1057 while (left) { |
|
1058 leftAncestors.push_back(left); |
|
1059 left = left->parent; |
|
1060 } |
|
1061 while (right) { |
|
1062 rightAncestors.push_back(right); |
|
1063 right = right->parent; |
|
1064 } |
|
1065 Q_ASSERT(leftAncestors.back() == root && rightAncestors.back() == root); |
|
1066 |
|
1067 while (!leftAncestors.empty() && !rightAncestors.empty() && leftAncestors.back() == rightAncestors.back()) { |
|
1068 leftAncestors.pop_back(); |
|
1069 rightAncestors.pop_back(); |
|
1070 } |
|
1071 |
|
1072 if (!leftAncestors.empty()) |
|
1073 return (leftAncestors.back() == leftAncestors.back()->parent->left ? -1 : 1); |
|
1074 |
|
1075 if (!rightAncestors.empty()) |
|
1076 return (rightAncestors.back() == rightAncestors.back()->parent->right ? -1 : 1); |
|
1077 |
|
1078 // The code should never reach this point. |
|
1079 Q_ASSERT(!leftAncestors.empty() || !rightAncestors.empty()); |
|
1080 return 0; |
|
1081 } |
|
1082 |
|
1083 //============================================================================// |
|
1084 // QInt64Hash // |
|
1085 //============================================================================// |
|
1086 |
|
1087 // Copied from qhash.cpp |
|
1088 static const uchar prime_deltas[] = { |
|
1089 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3, |
|
1090 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0 |
|
1091 }; |
|
1092 |
|
1093 // Copied from qhash.cpp |
|
1094 static inline int primeForNumBits(int numBits) |
|
1095 { |
|
1096 return (1 << numBits) + prime_deltas[numBits]; |
|
1097 } |
|
1098 |
|
1099 static inline int primeForCount(int count) |
|
1100 { |
|
1101 int low = 0; |
|
1102 int high = 32; |
|
1103 for (int i = 0; i < 5; ++i) { |
|
1104 int mid = (high + low) / 2; |
|
1105 if (count >= 1 << mid) |
|
1106 low = mid; |
|
1107 else |
|
1108 high = mid; |
|
1109 } |
|
1110 return primeForNumBits(high); |
|
1111 } |
|
1112 |
|
1113 // Hash set of quint64s. Elements cannot be removed without clearing the |
|
1114 // entire set. A value of -1 is used to mark unused entries. |
|
1115 class QInt64Set |
|
1116 { |
|
1117 public: |
|
1118 inline QInt64Set(int capacity = 64); |
|
1119 inline ~QInt64Set() {if (m_array) delete[] m_array;} |
|
1120 inline bool isValid() const {return m_array;} |
|
1121 void insert(quint64 key); |
|
1122 bool contains(quint64 key) const; |
|
1123 inline void clear(); |
|
1124 private: |
|
1125 bool rehash(int capacity); |
|
1126 |
|
1127 static const quint64 UNUSED; |
|
1128 |
|
1129 quint64 *m_array; |
|
1130 int m_capacity; |
|
1131 int m_count; |
|
1132 }; |
|
1133 |
|
1134 const quint64 QInt64Set::UNUSED = quint64(-1); |
|
1135 |
|
1136 inline QInt64Set::QInt64Set(int capacity) |
|
1137 { |
|
1138 m_capacity = primeForCount(capacity); |
|
1139 m_array = new quint64[m_capacity]; |
|
1140 if (m_array) |
|
1141 clear(); |
|
1142 else |
|
1143 m_capacity = 0; |
|
1144 } |
|
1145 |
|
1146 bool QInt64Set::rehash(int capacity) |
|
1147 { |
|
1148 quint64 *oldArray = m_array; |
|
1149 int oldCapacity = m_capacity; |
|
1150 |
|
1151 m_capacity = capacity; |
|
1152 m_array = new quint64[m_capacity]; |
|
1153 if (m_array) { |
|
1154 clear(); |
|
1155 if (oldArray) { |
|
1156 for (int i = 0; i < oldCapacity; ++i) { |
|
1157 if (oldArray[i] != UNUSED) |
|
1158 insert(oldArray[i]); |
|
1159 } |
|
1160 delete[] oldArray; |
|
1161 } |
|
1162 return true; |
|
1163 } else { |
|
1164 m_capacity = oldCapacity; |
|
1165 m_array = oldArray; |
|
1166 return false; |
|
1167 } |
|
1168 } |
|
1169 |
|
1170 void QInt64Set::insert(quint64 key) |
|
1171 { |
|
1172 if (m_count > 3 * m_capacity / 4) |
|
1173 rehash(primeForCount(2 * m_capacity)); |
|
1174 Q_ASSERT_X(m_array, "QInt64Hash<T>::insert", "Hash set not allocated."); |
|
1175 int index = int(key % m_capacity); |
|
1176 for (int i = 0; i < m_capacity; ++i) { |
|
1177 index += i; |
|
1178 if (index >= m_capacity) |
|
1179 index -= m_capacity; |
|
1180 if (m_array[index] == key) |
|
1181 return; |
|
1182 if (m_array[index] == UNUSED) { |
|
1183 ++m_count; |
|
1184 m_array[index] = key; |
|
1185 return; |
|
1186 } |
|
1187 } |
|
1188 Q_ASSERT_X(0, "QInt64Hash<T>::insert", "Hash set full."); |
|
1189 } |
|
1190 |
|
1191 bool QInt64Set::contains(quint64 key) const |
|
1192 { |
|
1193 Q_ASSERT_X(m_array, "QInt64Hash<T>::contains", "Hash set not allocated."); |
|
1194 int index = int(key % m_capacity); |
|
1195 for (int i = 0; i < m_capacity; ++i) { |
|
1196 index += i; |
|
1197 if (index >= m_capacity) |
|
1198 index -= m_capacity; |
|
1199 if (m_array[index] == key) |
|
1200 return true; |
|
1201 if (m_array[index] == UNUSED) |
|
1202 return false; |
|
1203 } |
|
1204 return false; |
|
1205 } |
|
1206 |
|
1207 inline void QInt64Set::clear() |
|
1208 { |
|
1209 Q_ASSERT_X(m_array, "QInt64Hash<T>::clear", "Hash set not allocated."); |
|
1210 for (int i = 0; i < m_capacity; ++i) |
|
1211 m_array[i] = UNUSED; |
|
1212 m_count = 0; |
|
1213 } |
|
1214 |
|
1215 //============================================================================// |
|
1216 // QRingBuffer // |
|
1217 //============================================================================// |
|
1218 |
|
1219 // T must be POD. |
|
1220 template <class T> |
|
1221 class QRingBuffer |
|
1222 { |
|
1223 public: |
|
1224 inline QRingBuffer() : m_array(0), m_head(0), m_size(0), m_capacity(0) { } |
|
1225 inline ~QRingBuffer() {if (m_array) delete[] m_array;} |
|
1226 bool reallocate(int capacity); |
|
1227 inline const T &head() const {Q_ASSERT(m_size > 0); return m_array[m_head];} |
|
1228 inline const T &dequeue(); |
|
1229 inline void enqueue(const T &x); |
|
1230 inline bool isEmpty() const {return m_size == 0;} |
|
1231 private: |
|
1232 T *m_array; |
|
1233 int m_head; |
|
1234 int m_size; |
|
1235 int m_capacity; |
|
1236 }; |
|
1237 |
|
1238 template <class T> |
|
1239 bool QRingBuffer<T>::reallocate(int capacity) |
|
1240 { |
|
1241 T *oldArray = m_array; |
|
1242 m_array = new T[capacity]; |
|
1243 if (m_array) { |
|
1244 if (oldArray) { |
|
1245 if (m_head + m_size > m_capacity) { |
|
1246 memcpy(m_array, oldArray + m_head, (m_capacity - m_head) * sizeof(T)); |
|
1247 memcpy(m_array + (m_capacity - m_head), oldArray, (m_head + m_size - m_capacity) * sizeof(T)); |
|
1248 } else { |
|
1249 memcpy(m_array, oldArray + m_head, m_size * sizeof(T)); |
|
1250 } |
|
1251 delete[] oldArray; |
|
1252 } |
|
1253 m_capacity = capacity; |
|
1254 m_head = 0; |
|
1255 return true; |
|
1256 } else { |
|
1257 m_array = oldArray; |
|
1258 return false; |
|
1259 } |
|
1260 } |
|
1261 |
|
1262 template <class T> |
|
1263 inline const T &QRingBuffer<T>::dequeue() |
|
1264 { |
|
1265 Q_ASSERT(m_size > 0); |
|
1266 Q_ASSERT(m_array); |
|
1267 Q_ASSERT(m_capacity >= m_size); |
|
1268 int index = m_head; |
|
1269 if (++m_head >= m_capacity) |
|
1270 m_head -= m_capacity; |
|
1271 --m_size; |
|
1272 return m_array[index]; |
|
1273 } |
|
1274 |
|
1275 template <class T> |
|
1276 inline void QRingBuffer<T>::enqueue(const T &x) |
|
1277 { |
|
1278 if (m_size == m_capacity) |
|
1279 reallocate(qMax(2 * m_capacity, 64)); |
|
1280 int index = m_head + m_size; |
|
1281 if (index >= m_capacity) |
|
1282 index -= m_capacity; |
|
1283 m_array[index] = x; |
|
1284 ++m_size; |
|
1285 } |
|
1286 |
|
1287 //============================================================================// |
|
1288 // QTriangulator // |
|
1289 //============================================================================// |
|
1290 |
|
1291 class QTriangulator |
|
1292 { |
|
1293 public: |
|
1294 typedef QVarLengthArray<int, 6> ShortArray; |
|
1295 |
|
1296 //================================// |
|
1297 // QTriangulator::ComplexToSimple // |
|
1298 //================================// |
|
1299 friend class ComplexToSimple; |
|
1300 class ComplexToSimple |
|
1301 { |
|
1302 public: |
|
1303 inline ComplexToSimple(QTriangulator *parent) : m_parent(parent), |
|
1304 m_edges(0), m_events(0), m_splits(0) { } |
|
1305 void decompose(); |
|
1306 private: |
|
1307 struct Edge |
|
1308 { |
|
1309 inline int &upper() {return pointingUp ? to : from;} |
|
1310 inline int &lower() {return pointingUp ? from : to;} |
|
1311 inline int upper() const {return pointingUp ? to : from;} |
|
1312 inline int lower() const {return pointingUp ? from : to;} |
|
1313 |
|
1314 QRBTree<int>::Node *node; |
|
1315 int from, to; // vertex |
|
1316 int next, previous; // edge |
|
1317 int winding; |
|
1318 bool mayIntersect; |
|
1319 bool pointingUp, originallyPointingUp; |
|
1320 }; |
|
1321 |
|
1322 friend class CompareEdges; |
|
1323 class CompareEdges |
|
1324 { |
|
1325 public: |
|
1326 inline CompareEdges(ComplexToSimple *parent) : m_parent(parent) { } |
|
1327 bool operator () (int i, int j) const; |
|
1328 private: |
|
1329 ComplexToSimple *m_parent; |
|
1330 }; |
|
1331 |
|
1332 struct Intersection |
|
1333 { |
|
1334 bool operator < (const Intersection &other) const {return other.intersectionPoint < intersectionPoint;} |
|
1335 |
|
1336 QIntersectionPoint intersectionPoint; |
|
1337 int vertex; |
|
1338 int leftEdge; |
|
1339 int rightEdge; |
|
1340 }; |
|
1341 |
|
1342 struct Split |
|
1343 { |
|
1344 int vertex; |
|
1345 int edge; |
|
1346 bool accurate; |
|
1347 }; |
|
1348 |
|
1349 struct Event |
|
1350 { |
|
1351 enum Type {Upper, Lower}; |
|
1352 inline bool operator < (const Event &other) const; |
|
1353 |
|
1354 QPodPoint point; |
|
1355 Type type; |
|
1356 int edge; |
|
1357 }; |
|
1358 |
|
1359 #ifdef Q_TRIANGULATOR_DEBUG |
|
1360 friend class DebugDialog; |
|
1361 friend class QTriangulator; |
|
1362 class DebugDialog : public QDialog |
|
1363 { |
|
1364 public: |
|
1365 DebugDialog(ComplexToSimple *parent, int currentVertex); |
|
1366 protected: |
|
1367 void paintEvent(QPaintEvent *); |
|
1368 void wheelEvent(QWheelEvent *); |
|
1369 void mouseMoveEvent(QMouseEvent *); |
|
1370 void mousePressEvent(QMouseEvent *); |
|
1371 private: |
|
1372 ComplexToSimple *m_parent; |
|
1373 QRectF m_window; |
|
1374 QPoint m_lastMousePos; |
|
1375 int m_vertex; |
|
1376 }; |
|
1377 #endif |
|
1378 |
|
1379 void initEdges(); |
|
1380 bool calculateIntersection(int left, int right); |
|
1381 bool edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const; |
|
1382 QRBTree<int>::Node *searchEdgeLeftOf(int edgeIndex) const; |
|
1383 QRBTree<int>::Node *searchEdgeLeftOf(int edgeIndex, QRBTree<int>::Node *after) const; |
|
1384 QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> bounds(const QPodPoint &point) const; |
|
1385 QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> outerBounds(const QPodPoint &point) const; |
|
1386 void splitEdgeListRange(QRBTree<int>::Node *leftmost, QRBTree<int>::Node *rightmost, int vertex, const QIntersectionPoint &intersectionPoint); |
|
1387 void reorderEdgeListRange(QRBTree<int>::Node *leftmost, QRBTree<int>::Node *rightmost); |
|
1388 void sortEdgeList(const QPodPoint eventPoint); |
|
1389 void fillPriorityQueue(); |
|
1390 void calculateIntersections(); |
|
1391 int splitEdge(int splitIndex); |
|
1392 bool splitEdgesAtIntersections(); |
|
1393 void insertEdgeIntoVectorIfWanted(ShortArray &orderedEdges, int i); |
|
1394 void removeUnwantedEdgesAndConnect(); |
|
1395 void removeUnusedPoints(); |
|
1396 |
|
1397 QTriangulator *m_parent; |
|
1398 QDataBuffer<Edge> m_edges; |
|
1399 QRBTree<int> m_edgeList; |
|
1400 QDataBuffer<Event> m_events; |
|
1401 QDataBuffer<Split> m_splits; |
|
1402 QMaxHeap<Intersection> m_topIntersection; |
|
1403 QInt64Set m_processedEdgePairs; |
|
1404 int m_initialPointCount; |
|
1405 }; |
|
1406 #ifdef Q_TRIANGULATOR_DEBUG |
|
1407 friend class ComplexToSimple::DebugDialog; |
|
1408 #endif |
|
1409 |
|
1410 //=================================// |
|
1411 // QTriangulator::SimpleToMonotone // |
|
1412 //=================================// |
|
1413 friend class SimpleToMonotone; |
|
1414 class SimpleToMonotone |
|
1415 { |
|
1416 public: |
|
1417 inline SimpleToMonotone(QTriangulator *parent) : m_parent(parent), m_edges(0), m_upperVertex(0) { } |
|
1418 void decompose(); |
|
1419 private: |
|
1420 enum VertexType {MergeVertex, EndVertex, RegularVertex, StartVertex, SplitVertex}; |
|
1421 |
|
1422 struct Edge |
|
1423 { |
|
1424 QRBTree<int>::Node *node; |
|
1425 int helper, twin, next, previous; |
|
1426 quint32 from, to; |
|
1427 VertexType type; |
|
1428 bool pointingUp; |
|
1429 int upper() const {return (pointingUp ? to : from);} |
|
1430 int lower() const {return (pointingUp ? from : to);} |
|
1431 }; |
|
1432 |
|
1433 friend class CompareVertices; |
|
1434 class CompareVertices |
|
1435 { |
|
1436 public: |
|
1437 CompareVertices(SimpleToMonotone *parent) : m_parent(parent) { } |
|
1438 bool operator () (int i, int j) const; |
|
1439 private: |
|
1440 SimpleToMonotone *m_parent; |
|
1441 }; |
|
1442 |
|
1443 void setupDataStructures(); |
|
1444 void removeZeroLengthEdges(); |
|
1445 void fillPriorityQueue(); |
|
1446 bool edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const; |
|
1447 // Returns the rightmost edge not to the right of the given edge. |
|
1448 QRBTree<int>::Node *searchEdgeLeftOfEdge(int edgeIndex) const; |
|
1449 // Returns the rightmost edge left of the given point. |
|
1450 QRBTree<int>::Node *searchEdgeLeftOfPoint(int pointIndex) const; |
|
1451 void classifyVertex(int i); |
|
1452 void classifyVertices(); |
|
1453 bool pointIsInSector(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2, const QPodPoint &v3); |
|
1454 bool pointIsInSector(int vertex, int sector); |
|
1455 int findSector(int edge, int vertex); |
|
1456 void createDiagonal(int lower, int upper); |
|
1457 void monotoneDecomposition(); |
|
1458 |
|
1459 QTriangulator *m_parent; |
|
1460 QRBTree<int> m_edgeList; |
|
1461 QDataBuffer<Edge> m_edges; |
|
1462 QDataBuffer<int> m_upperVertex; |
|
1463 bool m_clockwiseOrder; |
|
1464 }; |
|
1465 |
|
1466 //====================================// |
|
1467 // QTriangulator::MonotoneToTriangles // |
|
1468 //====================================// |
|
1469 friend class MonotoneToTriangles; |
|
1470 class MonotoneToTriangles |
|
1471 { |
|
1472 public: |
|
1473 inline MonotoneToTriangles(QTriangulator *parent) : m_parent(parent) { } |
|
1474 void decompose(); |
|
1475 private: |
|
1476 inline quint32 indices(int index) const {return m_parent->m_indices.at(index + m_first);} |
|
1477 inline int next(int index) const {return (index + 1) % m_length;} |
|
1478 inline int previous(int index) const {return (index + m_length - 1) % m_length;} |
|
1479 inline bool less(int i, int j) const {return m_parent->m_vertices.at(indices(i)) < m_parent->m_vertices.at(indices(j));} |
|
1480 inline bool leftOfEdge(int i, int j, int k) const |
|
1481 { |
|
1482 return qPointIsLeftOfLine(m_parent->m_vertices.at(indices(i)), |
|
1483 m_parent->m_vertices.at(indices(j)), m_parent->m_vertices.at(indices(k))); |
|
1484 } |
|
1485 |
|
1486 QTriangulator *m_parent; |
|
1487 int m_first; |
|
1488 int m_length; |
|
1489 }; |
|
1490 |
|
1491 inline QTriangulator() : m_vertices(0) { } |
|
1492 |
|
1493 // Call this only once. |
|
1494 void initialize(const qreal *polygon, int count, uint hint, const QTransform &matrix); |
|
1495 // Call this only once. |
|
1496 void initialize(const QVectorPath &path, const QTransform &matrix, qreal lod); |
|
1497 // Call this only once. |
|
1498 void initialize(const QPainterPath &path, const QTransform &matrix, qreal lod); |
|
1499 // Call either triangulate() or polyline() only once. |
|
1500 QTriangleSet triangulate(); |
|
1501 QPolylineSet polyline(); |
|
1502 private: |
|
1503 QDataBuffer<QPodPoint> m_vertices; |
|
1504 QVector<quint32> m_indices; |
|
1505 uint m_hint; |
|
1506 }; |
|
1507 |
|
1508 //============================================================================// |
|
1509 // QTriangulator // |
|
1510 //============================================================================// |
|
1511 |
|
1512 QTriangleSet QTriangulator::triangulate() |
|
1513 { |
|
1514 for (int i = 0; i < m_vertices.size(); ++i) { |
|
1515 Q_ASSERT(qAbs(m_vertices.at(i).x) < (1 << 21)); |
|
1516 Q_ASSERT(qAbs(m_vertices.at(i).y) < (1 << 21)); |
|
1517 } |
|
1518 |
|
1519 if (!(m_hint & (QVectorPath::OddEvenFill | QVectorPath::WindingFill))) |
|
1520 m_hint |= QVectorPath::OddEvenFill; |
|
1521 |
|
1522 if (m_hint & QVectorPath::NonConvexShapeMask) { |
|
1523 ComplexToSimple c2s(this); |
|
1524 c2s.decompose(); |
|
1525 SimpleToMonotone s2m(this); |
|
1526 s2m.decompose(); |
|
1527 } |
|
1528 MonotoneToTriangles m2t(this); |
|
1529 m2t.decompose(); |
|
1530 |
|
1531 QTriangleSet result; |
|
1532 result.indices = m_indices; |
|
1533 result.vertices.resize(2 * m_vertices.size()); |
|
1534 for (int i = 0; i < m_vertices.size(); ++i) { |
|
1535 result.vertices[2 * i + 0] = qreal(m_vertices.at(i).x) / Q_FIXED_POINT_SCALE; |
|
1536 result.vertices[2 * i + 1] = qreal(m_vertices.at(i).y) / Q_FIXED_POINT_SCALE; |
|
1537 } |
|
1538 return result; |
|
1539 } |
|
1540 |
|
1541 QPolylineSet QTriangulator::polyline() |
|
1542 { |
|
1543 QPolylineSet result; |
|
1544 result.indices = m_indices; |
|
1545 result.vertices.resize(2 * m_vertices.size()); |
|
1546 for (int i = 0; i < m_vertices.size(); ++i) { |
|
1547 result.vertices[2 * i + 0] = qreal(m_vertices.at(i).x) / Q_FIXED_POINT_SCALE; |
|
1548 result.vertices[2 * i + 1] = qreal(m_vertices.at(i).y) / Q_FIXED_POINT_SCALE; |
|
1549 } |
|
1550 return result; |
|
1551 } |
|
1552 |
|
1553 void QTriangulator::initialize(const qreal *polygon, int count, uint hint, const QTransform &matrix) |
|
1554 { |
|
1555 m_hint = hint; |
|
1556 m_vertices.resize(count); |
|
1557 m_indices.resize(count + 1); |
|
1558 for (int i = 0; i < count; ++i) { |
|
1559 qreal x, y; |
|
1560 matrix.map(polygon[2 * i + 0], polygon[2 * i + 1], &x, &y); |
|
1561 m_vertices.at(i).x = qRound(x * Q_FIXED_POINT_SCALE); |
|
1562 m_vertices.at(i).y = qRound(y * Q_FIXED_POINT_SCALE); |
|
1563 m_indices[i] = i; |
|
1564 } |
|
1565 m_indices[count] = Q_TRIANGULATE_END_OF_POLYGON; |
|
1566 } |
|
1567 |
|
1568 void QTriangulator::initialize(const QVectorPath &path, const QTransform &matrix, qreal lod) |
|
1569 { |
|
1570 m_hint = path.hints(); |
|
1571 // Curved paths will be converted to complex polygons. |
|
1572 m_hint &= ~QVectorPath::CurvedShapeMask; |
|
1573 |
|
1574 const qreal *p = path.points(); |
|
1575 const QPainterPath::ElementType *e = path.elements(); |
|
1576 if (e) { |
|
1577 for (int i = 0; i < path.elementCount(); ++i, ++e, p += 2) { |
|
1578 switch (*e) { |
|
1579 case QPainterPath::MoveToElement: |
|
1580 if (!m_indices.isEmpty()) |
|
1581 m_indices.push_back(Q_TRIANGULATE_END_OF_POLYGON); |
|
1582 // Fall through. |
|
1583 case QPainterPath::LineToElement: |
|
1584 m_indices.push_back(quint32(m_vertices.size())); |
|
1585 m_vertices.resize(m_vertices.size() + 1); |
|
1586 qreal x, y; |
|
1587 matrix.map(p[0], p[1], &x, &y); |
|
1588 m_vertices.last().x = qRound(x * Q_FIXED_POINT_SCALE); |
|
1589 m_vertices.last().y = qRound(y * Q_FIXED_POINT_SCALE); |
|
1590 break; |
|
1591 case QPainterPath::CurveToElement: |
|
1592 { |
|
1593 qreal pts[8]; |
|
1594 for (int i = 0; i < 4; ++i) |
|
1595 matrix.map(p[2 * i - 2], p[2 * i - 1], &pts[2 * i + 0], &pts[2 * i + 1]); |
|
1596 for (int i = 0; i < 8; ++i) |
|
1597 pts[i] *= lod; |
|
1598 QBezier bezier = QBezier::fromPoints(QPointF(pts[0], pts[1]), QPointF(pts[2], pts[3]), QPointF(pts[4], pts[5]), QPointF(pts[6], pts[7])); |
|
1599 QPolygonF poly = bezier.toPolygon(); |
|
1600 // Skip first point, it already exists in 'm_vertices'. |
|
1601 for (int j = 1; j < poly.size(); ++j) { |
|
1602 m_indices.push_back(quint32(m_vertices.size())); |
|
1603 m_vertices.resize(m_vertices.size() + 1); |
|
1604 m_vertices.last().x = qRound(poly.at(j).x() * Q_FIXED_POINT_SCALE / lod); |
|
1605 m_vertices.last().y = qRound(poly.at(j).y() * Q_FIXED_POINT_SCALE / lod); |
|
1606 } |
|
1607 } |
|
1608 i += 2; |
|
1609 e += 2; |
|
1610 p += 4; |
|
1611 break; |
|
1612 default: |
|
1613 Q_ASSERT_X(0, "QTriangulator::triangulate", "Unexpected element type."); |
|
1614 break; |
|
1615 } |
|
1616 } |
|
1617 } else { |
|
1618 for (int i = 0; i < path.elementCount(); ++i, p += 2) { |
|
1619 m_indices.push_back(quint32(m_vertices.size())); |
|
1620 m_vertices.resize(m_vertices.size() + 1); |
|
1621 qreal x, y; |
|
1622 matrix.map(p[0], p[1], &x, &y); |
|
1623 m_vertices.last().x = qRound(x * Q_FIXED_POINT_SCALE); |
|
1624 m_vertices.last().y = qRound(y * Q_FIXED_POINT_SCALE); |
|
1625 } |
|
1626 } |
|
1627 m_indices.push_back(Q_TRIANGULATE_END_OF_POLYGON); |
|
1628 } |
|
1629 |
|
1630 void QTriangulator::initialize(const QPainterPath &path, const QTransform &matrix, qreal lod) |
|
1631 { |
|
1632 initialize(qtVectorPathForPath(path), matrix, lod); |
|
1633 } |
|
1634 |
|
1635 //============================================================================// |
|
1636 // QTriangulator::ComplexToSimple // |
|
1637 //============================================================================// |
|
1638 |
|
1639 void QTriangulator::ComplexToSimple::decompose() |
|
1640 { |
|
1641 m_initialPointCount = m_parent->m_vertices.size(); |
|
1642 initEdges(); |
|
1643 do { |
|
1644 calculateIntersections(); |
|
1645 } while (splitEdgesAtIntersections()); |
|
1646 |
|
1647 removeUnwantedEdgesAndConnect(); |
|
1648 removeUnusedPoints(); |
|
1649 |
|
1650 m_parent->m_indices.clear(); |
|
1651 QBitArray processed(m_edges.size(), false); |
|
1652 for (int first = 0; first < m_edges.size(); ++first) { |
|
1653 // If already processed, or if unused path, skip. |
|
1654 if (processed.at(first) || m_edges.at(first).next == -1) |
|
1655 continue; |
|
1656 |
|
1657 int i = first; |
|
1658 do { |
|
1659 Q_ASSERT(!processed.at(i)); |
|
1660 Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i); |
|
1661 m_parent->m_indices.push_back(m_edges.at(i).from); |
|
1662 processed.setBit(i); |
|
1663 i = m_edges.at(i).next; // CCW order |
|
1664 } while (i != first); |
|
1665 m_parent->m_indices.push_back(Q_TRIANGULATE_END_OF_POLYGON); |
|
1666 } |
|
1667 } |
|
1668 |
|
1669 void QTriangulator::ComplexToSimple::initEdges() |
|
1670 { |
|
1671 // Initialize edge structure. |
|
1672 // 'next' and 'previous' are not being initialized at this point. |
|
1673 int first = 0; |
|
1674 for (int i = 0; i < m_parent->m_indices.size(); ++i) { |
|
1675 if (m_parent->m_indices.at(i) == Q_TRIANGULATE_END_OF_POLYGON) { |
|
1676 if (m_edges.size() != first) |
|
1677 m_edges.last().to = m_edges.at(first).from; |
|
1678 first = m_edges.size(); |
|
1679 } else { |
|
1680 Q_ASSERT(i + 1 < m_parent->m_indices.size()); |
|
1681 // {node, from, to, next, previous, winding, mayIntersect, pointingUp, originallyPointingUp} |
|
1682 Edge edge = {0, m_parent->m_indices.at(i), m_parent->m_indices.at(i + 1), -1, -1, 0, true, false, false}; |
|
1683 m_edges.add(edge); |
|
1684 } |
|
1685 } |
|
1686 if (first != m_edges.size()) |
|
1687 m_edges.last().to = m_edges.at(first).from; |
|
1688 for (int i = 0; i < m_edges.size(); ++i) { |
|
1689 m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp = |
|
1690 m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from); |
|
1691 } |
|
1692 } |
|
1693 |
|
1694 // Return true if new intersection was found |
|
1695 bool QTriangulator::ComplexToSimple::calculateIntersection(int left, int right) |
|
1696 { |
|
1697 const Edge &e1 = m_edges.at(left); |
|
1698 const Edge &e2 = m_edges.at(right); |
|
1699 |
|
1700 const QPodPoint &u1 = m_parent->m_vertices.at(e1.from); |
|
1701 const QPodPoint &u2 = m_parent->m_vertices.at(e1.to); |
|
1702 const QPodPoint &v1 = m_parent->m_vertices.at(e2.from); |
|
1703 const QPodPoint &v2 = m_parent->m_vertices.at(e2.to); |
|
1704 if (qMax(u1.x, u2.x) <= qMin(v1.x, v2.x)) |
|
1705 return false; |
|
1706 |
|
1707 quint64 key = (left > right ? (quint64(right) << 32) | quint64(left) : (quint64(left) << 32) | quint64(right)); |
|
1708 if (m_processedEdgePairs.contains(key)) |
|
1709 return false; |
|
1710 m_processedEdgePairs.insert(key); |
|
1711 |
|
1712 Intersection intersection; |
|
1713 intersection.leftEdge = left; |
|
1714 intersection.rightEdge = right; |
|
1715 intersection.intersectionPoint = qIntersectionPoint(u1, u2, v1, v2); |
|
1716 |
|
1717 if (!intersection.intersectionPoint.isValid()) |
|
1718 return false; |
|
1719 |
|
1720 Q_ASSERT(intersection.intersectionPoint.isOnLine(u1, u2)); |
|
1721 Q_ASSERT(intersection.intersectionPoint.isOnLine(v1, v2)); |
|
1722 |
|
1723 intersection.vertex = m_parent->m_vertices.size(); |
|
1724 m_topIntersection.push(intersection); |
|
1725 m_parent->m_vertices.add(intersection.intersectionPoint.round()); |
|
1726 return true; |
|
1727 } |
|
1728 |
|
1729 bool QTriangulator::ComplexToSimple::edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const |
|
1730 { |
|
1731 const Edge &leftEdge = m_edges.at(leftEdgeIndex); |
|
1732 const Edge &rightEdge = m_edges.at(rightEdgeIndex); |
|
1733 const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper()); |
|
1734 const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower()); |
|
1735 const QPodPoint &upper = m_parent->m_vertices.at(leftEdge.upper()); |
|
1736 if (upper.x < qMin(l.x, u.x)) |
|
1737 return true; |
|
1738 if (upper.x > qMax(l.x, u.x)) |
|
1739 return false; |
|
1740 qint64 d = qPointDistanceFromLine(upper, l, u); |
|
1741 // d < 0: left, d > 0: right, d == 0: on top |
|
1742 if (d == 0) |
|
1743 d = qPointDistanceFromLine(m_parent->m_vertices.at(leftEdge.lower()), l, u); |
|
1744 return d < 0; |
|
1745 } |
|
1746 |
|
1747 QRBTree<int>::Node *QTriangulator::ComplexToSimple::searchEdgeLeftOf(int edgeIndex) const |
|
1748 { |
|
1749 QRBTree<int>::Node *current = m_edgeList.root; |
|
1750 QRBTree<int>::Node *result = 0; |
|
1751 while (current) { |
|
1752 if (edgeIsLeftOfEdge(edgeIndex, current->data)) { |
|
1753 current = current->left; |
|
1754 } else { |
|
1755 result = current; |
|
1756 current = current->right; |
|
1757 } |
|
1758 } |
|
1759 return result; |
|
1760 } |
|
1761 |
|
1762 QRBTree<int>::Node *QTriangulator::ComplexToSimple::searchEdgeLeftOf(int edgeIndex, QRBTree<int>::Node *after) const |
|
1763 { |
|
1764 if (!m_edgeList.root) |
|
1765 return after; |
|
1766 QRBTree<int>::Node *result = after; |
|
1767 QRBTree<int>::Node *current = (after ? m_edgeList.next(after) : m_edgeList.front(m_edgeList.root)); |
|
1768 while (current) { |
|
1769 if (edgeIsLeftOfEdge(edgeIndex, current->data)) |
|
1770 return result; |
|
1771 result = current; |
|
1772 current = m_edgeList.next(current); |
|
1773 } |
|
1774 return result; |
|
1775 } |
|
1776 |
|
1777 QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> QTriangulator::ComplexToSimple::bounds(const QPodPoint &point) const |
|
1778 { |
|
1779 QRBTree<int>::Node *current = m_edgeList.root; |
|
1780 QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> result(0, 0); |
|
1781 while (current) { |
|
1782 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); |
|
1783 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); |
|
1784 qint64 d = qPointDistanceFromLine(point, v1, v2); |
|
1785 if (d == 0) { |
|
1786 result.first = result.second = current; |
|
1787 break; |
|
1788 } |
|
1789 current = (d < 0 ? current->left : current->right); |
|
1790 } |
|
1791 if (current == 0) |
|
1792 return result; |
|
1793 |
|
1794 current = result.first->left; |
|
1795 while (current) { |
|
1796 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); |
|
1797 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); |
|
1798 qint64 d = qPointDistanceFromLine(point, v1, v2); |
|
1799 Q_ASSERT(d >= 0); |
|
1800 if (d == 0) { |
|
1801 result.first = current; |
|
1802 current = current->left; |
|
1803 } else { |
|
1804 current = current->right; |
|
1805 } |
|
1806 } |
|
1807 |
|
1808 current = result.second->right; |
|
1809 while (current) { |
|
1810 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); |
|
1811 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); |
|
1812 qint64 d = qPointDistanceFromLine(point, v1, v2); |
|
1813 Q_ASSERT(d <= 0); |
|
1814 if (d == 0) { |
|
1815 result.second = current; |
|
1816 current = current->right; |
|
1817 } else { |
|
1818 current = current->left; |
|
1819 } |
|
1820 } |
|
1821 |
|
1822 return result; |
|
1823 } |
|
1824 |
|
1825 QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> QTriangulator::ComplexToSimple::outerBounds(const QPodPoint &point) const |
|
1826 { |
|
1827 QRBTree<int>::Node *current = m_edgeList.root; |
|
1828 QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> result(0, 0); |
|
1829 |
|
1830 while (current) { |
|
1831 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); |
|
1832 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); |
|
1833 qint64 d = qPointDistanceFromLine(point, v1, v2); |
|
1834 if (d == 0) |
|
1835 break; |
|
1836 if (d < 0) { |
|
1837 result.second = current; |
|
1838 current = current->left; |
|
1839 } else { |
|
1840 result.first = current; |
|
1841 current = current->right; |
|
1842 } |
|
1843 } |
|
1844 |
|
1845 if (!current) |
|
1846 return result; |
|
1847 |
|
1848 QRBTree<int>::Node *mid = current; |
|
1849 |
|
1850 current = mid->left; |
|
1851 while (current) { |
|
1852 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); |
|
1853 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); |
|
1854 qint64 d = qPointDistanceFromLine(point, v1, v2); |
|
1855 Q_ASSERT(d >= 0); |
|
1856 if (d == 0) { |
|
1857 current = current->left; |
|
1858 } else { |
|
1859 result.first = current; |
|
1860 current = current->right; |
|
1861 } |
|
1862 } |
|
1863 |
|
1864 current = mid->right; |
|
1865 while (current) { |
|
1866 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); |
|
1867 const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); |
|
1868 qint64 d = qPointDistanceFromLine(point, v1, v2); |
|
1869 Q_ASSERT(d <= 0); |
|
1870 if (d == 0) { |
|
1871 current = current->right; |
|
1872 } else { |
|
1873 result.second = current; |
|
1874 current = current->left; |
|
1875 } |
|
1876 } |
|
1877 |
|
1878 return result; |
|
1879 } |
|
1880 |
|
1881 void QTriangulator::ComplexToSimple::splitEdgeListRange(QRBTree<int>::Node *leftmost, QRBTree<int>::Node *rightmost, int vertex, const QIntersectionPoint &intersectionPoint) |
|
1882 { |
|
1883 Q_ASSERT(leftmost && rightmost); |
|
1884 |
|
1885 // Split. |
|
1886 for (;;) { |
|
1887 const QPodPoint &u = m_parent->m_vertices.at(m_edges.at(leftmost->data).from); |
|
1888 const QPodPoint &v = m_parent->m_vertices.at(m_edges.at(leftmost->data).to); |
|
1889 Q_ASSERT(intersectionPoint.isOnLine(u, v)); |
|
1890 const Split split = {vertex, leftmost->data, intersectionPoint.isAccurate()}; |
|
1891 if (intersectionPoint.xOffset.numerator != 0 || intersectionPoint.yOffset.numerator != 0 || (intersectionPoint.upperLeft != u && intersectionPoint.upperLeft != v)) |
|
1892 m_splits.add(split); |
|
1893 if (leftmost == rightmost) |
|
1894 break; |
|
1895 leftmost = m_edgeList.next(leftmost); |
|
1896 } |
|
1897 } |
|
1898 |
|
1899 |
|
1900 void QTriangulator::ComplexToSimple::reorderEdgeListRange(QRBTree<int>::Node *leftmost, QRBTree<int>::Node *rightmost) |
|
1901 { |
|
1902 Q_ASSERT(leftmost && rightmost); |
|
1903 |
|
1904 QRBTree<int>::Node *storeLeftmost = leftmost; |
|
1905 QRBTree<int>::Node *storeRightmost = rightmost; |
|
1906 |
|
1907 // Reorder. |
|
1908 while (leftmost != rightmost) { |
|
1909 Edge &left = m_edges.at(leftmost->data); |
|
1910 Edge &right = m_edges.at(rightmost->data); |
|
1911 qSwap(left.node, right.node); |
|
1912 qSwap(leftmost->data, rightmost->data); |
|
1913 leftmost = m_edgeList.next(leftmost); |
|
1914 if (leftmost == rightmost) |
|
1915 break; |
|
1916 rightmost = m_edgeList.previous(rightmost); |
|
1917 } |
|
1918 |
|
1919 rightmost = m_edgeList.next(storeRightmost); |
|
1920 leftmost = m_edgeList.previous(storeLeftmost); |
|
1921 if (leftmost) |
|
1922 calculateIntersection(leftmost->data, storeLeftmost->data); |
|
1923 if (rightmost) |
|
1924 calculateIntersection(storeRightmost->data, rightmost->data); |
|
1925 } |
|
1926 |
|
1927 void QTriangulator::ComplexToSimple::sortEdgeList(const QPodPoint eventPoint) |
|
1928 { |
|
1929 QIntersectionPoint eventPoint2 = qIntersectionPoint(eventPoint); |
|
1930 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint < eventPoint2) { |
|
1931 Intersection intersection = m_topIntersection.pop(); |
|
1932 |
|
1933 QIntersectionPoint currentIntersectionPoint = intersection.intersectionPoint; |
|
1934 int currentVertex = intersection.vertex; |
|
1935 |
|
1936 QRBTree<int>::Node *leftmost = m_edges.at(intersection.leftEdge).node; |
|
1937 QRBTree<int>::Node *rightmost = m_edges.at(intersection.rightEdge).node; |
|
1938 |
|
1939 for (;;) { |
|
1940 QRBTree<int>::Node *previous = m_edgeList.previous(leftmost); |
|
1941 if (!previous) |
|
1942 break; |
|
1943 const Edge &edge = m_edges.at(previous->data); |
|
1944 const QPodPoint &u = m_parent->m_vertices.at(edge.from); |
|
1945 const QPodPoint &v = m_parent->m_vertices.at(edge.to); |
|
1946 if (!currentIntersectionPoint.isOnLine(u, v)) { |
|
1947 Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0); |
|
1948 break; |
|
1949 } |
|
1950 leftmost = previous; |
|
1951 } |
|
1952 |
|
1953 for (;;) { |
|
1954 QRBTree<int>::Node *next = m_edgeList.next(rightmost); |
|
1955 if (!next) |
|
1956 break; |
|
1957 const Edge &edge = m_edges.at(next->data); |
|
1958 const QPodPoint &u = m_parent->m_vertices.at(edge.from); |
|
1959 const QPodPoint &v = m_parent->m_vertices.at(edge.to); |
|
1960 if (!currentIntersectionPoint.isOnLine(u, v)) { |
|
1961 Q_ASSERT(!currentIntersectionPoint.isAccurate() || qCross(currentIntersectionPoint.upperLeft - u, v - u) != 0); |
|
1962 break; |
|
1963 } |
|
1964 rightmost = next; |
|
1965 } |
|
1966 |
|
1967 Q_ASSERT(leftmost && rightmost); |
|
1968 splitEdgeListRange(leftmost, rightmost, currentVertex, currentIntersectionPoint); |
|
1969 reorderEdgeListRange(leftmost, rightmost); |
|
1970 |
|
1971 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= currentIntersectionPoint) |
|
1972 m_topIntersection.pop(); |
|
1973 |
|
1974 #ifdef Q_TRIANGULATOR_DEBUG |
|
1975 DebugDialog dialog(this, intersection.vertex); |
|
1976 dialog.exec(); |
|
1977 #endif |
|
1978 |
|
1979 } |
|
1980 } |
|
1981 |
|
1982 void QTriangulator::ComplexToSimple::fillPriorityQueue() |
|
1983 { |
|
1984 m_events.reset(); |
|
1985 m_events.reserve(m_edges.size() * 2); |
|
1986 for (int i = 0; i < m_edges.size(); ++i) { |
|
1987 Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1); |
|
1988 Q_ASSERT(m_edges.at(i).node == 0); |
|
1989 Q_ASSERT(m_edges.at(i).pointingUp == m_edges.at(i).originallyPointingUp); |
|
1990 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))); |
|
1991 // Ignore zero-length edges. |
|
1992 if (m_parent->m_vertices.at(m_edges.at(i).to) != m_parent->m_vertices.at(m_edges.at(i).from)) { |
|
1993 QPodPoint upper = m_parent->m_vertices.at(m_edges.at(i).upper()); |
|
1994 QPodPoint lower = m_parent->m_vertices.at(m_edges.at(i).lower()); |
|
1995 Event upperEvent = {{upper.x, upper.y}, Event::Upper, i}; |
|
1996 Event lowerEvent = {{lower.x, lower.y}, Event::Lower, i}; |
|
1997 m_events.add(upperEvent); |
|
1998 m_events.add(lowerEvent); |
|
1999 } |
|
2000 } |
|
2001 //qSort(m_events.data(), m_events.data() + m_events.size()); |
|
2002 sort(m_events.data(), m_events.size()); |
|
2003 } |
|
2004 |
|
2005 void QTriangulator::ComplexToSimple::calculateIntersections() |
|
2006 { |
|
2007 fillPriorityQueue(); |
|
2008 |
|
2009 Q_ASSERT(m_topIntersection.empty()); |
|
2010 Q_ASSERT(m_edgeList.root == 0); |
|
2011 |
|
2012 // Find all intersection points. |
|
2013 while (!m_events.isEmpty()) { |
|
2014 Event event = m_events.last(); |
|
2015 sortEdgeList(event.point); |
|
2016 |
|
2017 // Find all edges in the edge list that contain the current vertex and mark them to be split later. |
|
2018 QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> range = bounds(event.point); |
|
2019 QRBTree<int>::Node *leftNode = range.first ? m_edgeList.previous(range.first) : 0; |
|
2020 int vertex = (event.type == Event::Upper ? m_edges.at(event.edge).upper() : m_edges.at(event.edge).lower()); |
|
2021 QIntersectionPoint eventPoint = qIntersectionPoint(event.point); |
|
2022 |
|
2023 if (range.first != 0) { |
|
2024 splitEdgeListRange(range.first, range.second, vertex, eventPoint); |
|
2025 reorderEdgeListRange(range.first, range.second); |
|
2026 } |
|
2027 |
|
2028 // Handle the edges with start or end point in the current vertex. |
|
2029 while (!m_events.isEmpty() && m_events.last().point == event.point) { |
|
2030 event = m_events.last(); |
|
2031 m_events.pop_back(); |
|
2032 int i = event.edge; |
|
2033 |
|
2034 if (m_edges.at(i).node) { |
|
2035 // Remove edge from edge list. |
|
2036 Q_ASSERT(event.type == Event::Lower); |
|
2037 QRBTree<int>::Node *left = m_edgeList.previous(m_edges.at(i).node); |
|
2038 QRBTree<int>::Node *right = m_edgeList.next(m_edges.at(i).node); |
|
2039 m_edgeList.deleteNode(m_edges.at(i).node); |
|
2040 if (!left || !right) |
|
2041 continue; |
|
2042 calculateIntersection(left->data, right->data); |
|
2043 } else { |
|
2044 // Insert edge into edge list. |
|
2045 Q_ASSERT(event.type == Event::Upper); |
|
2046 QRBTree<int>::Node *left = searchEdgeLeftOf(i, leftNode); |
|
2047 m_edgeList.attachAfter(left, m_edges.at(i).node = m_edgeList.newNode()); |
|
2048 m_edges.at(i).node->data = i; |
|
2049 QRBTree<int>::Node *right = m_edgeList.next(m_edges.at(i).node); |
|
2050 if (left) |
|
2051 calculateIntersection(left->data, i); |
|
2052 if (right) |
|
2053 calculateIntersection(i, right->data); |
|
2054 } |
|
2055 } |
|
2056 while (!m_topIntersection.isEmpty() && m_topIntersection.top().intersectionPoint <= eventPoint) |
|
2057 m_topIntersection.pop(); |
|
2058 #ifdef Q_TRIANGULATOR_DEBUG |
|
2059 DebugDialog dialog(this, vertex); |
|
2060 dialog.exec(); |
|
2061 #endif |
|
2062 } |
|
2063 m_processedEdgePairs.clear(); |
|
2064 } |
|
2065 |
|
2066 // Split an edge into two pieces at the given point. |
|
2067 // The upper piece is pushed to the end of the 'm_edges' vector. |
|
2068 // The lower piece replaces the old edge. |
|
2069 // Return the edge whose 'from' is 'pointIndex'. |
|
2070 int QTriangulator::ComplexToSimple::splitEdge(int splitIndex) |
|
2071 { |
|
2072 const Split &split = m_splits.at(splitIndex); |
|
2073 Edge &lowerEdge = m_edges.at(split.edge); |
|
2074 Q_ASSERT(lowerEdge.node == 0); |
|
2075 Q_ASSERT(lowerEdge.previous == -1 && lowerEdge.next == -1); |
|
2076 |
|
2077 if (lowerEdge.from == split.vertex) |
|
2078 return split.edge; |
|
2079 if (lowerEdge.to == split.vertex) |
|
2080 return lowerEdge.next; |
|
2081 |
|
2082 // Check that angle >= 90 degrees. |
|
2083 //Q_ASSERT(qDot(m_points.at(m_edges.at(edgeIndex).from) - m_points.at(pointIndex), |
|
2084 // m_points.at(m_edges.at(edgeIndex).to) - m_points.at(pointIndex)) <= 0); |
|
2085 |
|
2086 Edge upperEdge = lowerEdge; |
|
2087 upperEdge.mayIntersect |= !split.accurate; // The edge may have been split before at an inaccurate split point. |
|
2088 lowerEdge.mayIntersect = !split.accurate; |
|
2089 if (lowerEdge.pointingUp) { |
|
2090 lowerEdge.to = upperEdge.from = split.vertex; |
|
2091 m_edges.add(upperEdge); |
|
2092 return m_edges.size() - 1; |
|
2093 } else { |
|
2094 lowerEdge.from = upperEdge.to = split.vertex; |
|
2095 m_edges.add(upperEdge); |
|
2096 return split.edge; |
|
2097 } |
|
2098 } |
|
2099 |
|
2100 bool QTriangulator::ComplexToSimple::splitEdgesAtIntersections() |
|
2101 { |
|
2102 for (int i = 0; i < m_edges.size(); ++i) |
|
2103 m_edges.at(i).mayIntersect = false; |
|
2104 bool checkForNewIntersections = false; |
|
2105 for (int i = 0; i < m_splits.size(); ++i) { |
|
2106 splitEdge(i); |
|
2107 checkForNewIntersections |= !m_splits.at(i).accurate; |
|
2108 } |
|
2109 for (int i = 0; i < m_edges.size(); ++i) { |
|
2110 m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp = |
|
2111 m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from); |
|
2112 } |
|
2113 m_splits.reset(); |
|
2114 return checkForNewIntersections; |
|
2115 } |
|
2116 |
|
2117 void QTriangulator::ComplexToSimple::insertEdgeIntoVectorIfWanted(ShortArray &orderedEdges, int i) |
|
2118 { |
|
2119 // Edges with zero length should not reach this part. |
|
2120 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(i).from) != m_parent->m_vertices.at(m_edges.at(i).to)); |
|
2121 |
|
2122 // Skip edges with unwanted winding number. |
|
2123 int windingNumber = m_edges.at(i).winding; |
|
2124 if (m_edges.at(i).originallyPointingUp) |
|
2125 ++windingNumber; |
|
2126 |
|
2127 // Make sure exactly one fill rule is specified. |
|
2128 Q_ASSERT(((m_parent->m_hint & QVectorPath::WindingFill) != 0) != ((m_parent->m_hint & QVectorPath::OddEvenFill) != 0)); |
|
2129 |
|
2130 if ((m_parent->m_hint & QVectorPath::WindingFill) && windingNumber != 0 && windingNumber != 1) |
|
2131 return; |
|
2132 |
|
2133 // Skip cancelling edges. |
|
2134 if (!orderedEdges.isEmpty()) { |
|
2135 int j = orderedEdges[orderedEdges.size() - 1]; |
|
2136 // If the last edge is already connected in one end, it should not be cancelled. |
|
2137 if (m_edges.at(j).next == -1 && m_edges.at(j).previous == -1 |
|
2138 && (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(j).to)) |
|
2139 && (m_parent->m_vertices.at(m_edges.at(i).to) == m_parent->m_vertices.at(m_edges.at(j).from))) { |
|
2140 orderedEdges.removeLast(); |
|
2141 return; |
|
2142 } |
|
2143 } |
|
2144 orderedEdges.append(i); |
|
2145 } |
|
2146 |
|
2147 void QTriangulator::ComplexToSimple::removeUnwantedEdgesAndConnect() |
|
2148 { |
|
2149 Q_ASSERT(m_edgeList.root == 0); |
|
2150 // Initialize priority queue. |
|
2151 fillPriorityQueue(); |
|
2152 |
|
2153 ShortArray orderedEdges; |
|
2154 |
|
2155 while (!m_events.isEmpty()) { |
|
2156 Event event = m_events.last(); |
|
2157 int edgeIndex = event.edge; |
|
2158 |
|
2159 // Check that all the edges in the list crosses the current scanline |
|
2160 //if (m_edgeList.root) { |
|
2161 // for (QRBTree<int>::Node *node = m_edgeList.front(m_edgeList.root); node; node = m_edgeList.next(node)) { |
|
2162 // Q_ASSERT(event.point <= m_points.at(m_edges.at(node->data).lower())); |
|
2163 // } |
|
2164 //} |
|
2165 |
|
2166 orderedEdges.clear(); |
|
2167 QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> b = outerBounds(event.point); |
|
2168 if (m_edgeList.root) { |
|
2169 QRBTree<int>::Node *current = (b.first ? m_edgeList.next(b.first) : m_edgeList.front(m_edgeList.root)); |
|
2170 // Process edges that are going to be removed from the edge list at the current event point. |
|
2171 while (current != b.second) { |
|
2172 Q_ASSERT(current); |
|
2173 Q_ASSERT(m_edges.at(current->data).node == current); |
|
2174 Q_ASSERT(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))); |
|
2175 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); |
|
2176 insertEdgeIntoVectorIfWanted(orderedEdges, current->data); |
|
2177 current = m_edgeList.next(current); |
|
2178 } |
|
2179 } |
|
2180 |
|
2181 // Remove edges above the event point, insert edges below the event point. |
|
2182 do { |
|
2183 event = m_events.last(); |
|
2184 m_events.pop_back(); |
|
2185 edgeIndex = event.edge; |
|
2186 |
|
2187 // Edges with zero length should not reach this part. |
|
2188 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(edgeIndex).from) != m_parent->m_vertices.at(m_edges.at(edgeIndex).to)); |
|
2189 |
|
2190 if (m_edges.at(edgeIndex).node) { |
|
2191 Q_ASSERT(event.type == Event::Lower); |
|
2192 Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).lower())); |
|
2193 m_edgeList.deleteNode(m_edges.at(edgeIndex).node); |
|
2194 } else { |
|
2195 Q_ASSERT(event.type == Event::Upper); |
|
2196 Q_ASSERT(event.point == m_parent->m_vertices.at(m_edges.at(event.edge).upper())); |
|
2197 QRBTree<int>::Node *left = searchEdgeLeftOf(edgeIndex, b.first); |
|
2198 m_edgeList.attachAfter(left, m_edges.at(edgeIndex).node = m_edgeList.newNode()); |
|
2199 m_edges.at(edgeIndex).node->data = edgeIndex; |
|
2200 } |
|
2201 } while (!m_events.isEmpty() && m_events.last().point == event.point); |
|
2202 |
|
2203 if (m_edgeList.root) { |
|
2204 QRBTree<int>::Node *current = (b.first ? m_edgeList.next(b.first) : m_edgeList.front(m_edgeList.root)); |
|
2205 |
|
2206 // Calculate winding number and turn counter-clockwise. |
|
2207 int currentWindingNumber = (b.first ? m_edges.at(b.first->data).winding : 0); |
|
2208 while (current != b.second) { |
|
2209 Q_ASSERT(current); |
|
2210 //Q_ASSERT(b.second == 0 || m_edgeList.order(current, b.second) < 0); |
|
2211 int i = current->data; |
|
2212 Q_ASSERT(m_edges.at(i).node == current); |
|
2213 |
|
2214 // Winding number. |
|
2215 int ccwWindingNumber = m_edges.at(i).winding = currentWindingNumber; |
|
2216 if (m_edges.at(i).originallyPointingUp) { |
|
2217 --m_edges.at(i).winding; |
|
2218 } else { |
|
2219 ++m_edges.at(i).winding; |
|
2220 ++ccwWindingNumber; |
|
2221 } |
|
2222 currentWindingNumber = m_edges.at(i).winding; |
|
2223 |
|
2224 // Turn counter-clockwise. |
|
2225 if ((ccwWindingNumber & 1) == 0) { |
|
2226 Q_ASSERT(m_edges.at(i).previous == -1 && m_edges.at(i).next == -1); |
|
2227 qSwap(m_edges.at(i).from, m_edges.at(i).to); |
|
2228 m_edges.at(i).pointingUp = !m_edges.at(i).pointingUp; |
|
2229 } |
|
2230 |
|
2231 current = m_edgeList.next(current); |
|
2232 } |
|
2233 |
|
2234 // Process edges that were inserted into the edge list at the current event point. |
|
2235 current = (b.second ? m_edgeList.previous(b.second) : m_edgeList.back(m_edgeList.root)); |
|
2236 while (current != b.first) { |
|
2237 Q_ASSERT(current); |
|
2238 Q_ASSERT(m_edges.at(current->data).node == current); |
|
2239 insertEdgeIntoVectorIfWanted(orderedEdges, current->data); |
|
2240 current = m_edgeList.previous(current); |
|
2241 } |
|
2242 } |
|
2243 if (orderedEdges.isEmpty()) |
|
2244 continue; |
|
2245 |
|
2246 Q_ASSERT((orderedEdges.size() & 1) == 0); |
|
2247 |
|
2248 // Connect edges. |
|
2249 // First make sure the first edge point towards the current point. |
|
2250 int i; |
|
2251 if (m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).from) == event.point) { |
|
2252 i = 1; |
|
2253 int copy = orderedEdges[0]; // Make copy in case the append() will cause a reallocation. |
|
2254 orderedEdges.append(copy); |
|
2255 } else { |
|
2256 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[0]).to) == event.point); |
|
2257 i = 0; |
|
2258 } |
|
2259 |
|
2260 // Remove references to duplicate points. First find the point with lowest index. |
|
2261 int pointIndex = INT_MAX; |
|
2262 for (int j = i; j < orderedEdges.size(); j += 2) { |
|
2263 Q_ASSERT(j + 1 < orderedEdges.size()); |
|
2264 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j]).to) == event.point); |
|
2265 Q_ASSERT(m_parent->m_vertices.at(m_edges.at(orderedEdges[j + 1]).from) == event.point); |
|
2266 if (m_edges.at(orderedEdges[j]).to < pointIndex) |
|
2267 pointIndex = m_edges.at(orderedEdges[j]).to; |
|
2268 if (m_edges.at(orderedEdges[j + 1]).from < pointIndex) |
|
2269 pointIndex = m_edges.at(orderedEdges[j + 1]).from; |
|
2270 } |
|
2271 |
|
2272 for (; i < orderedEdges.size(); i += 2) { |
|
2273 // Remove references to duplicate points by making all edges reference one common point. |
|
2274 m_edges.at(orderedEdges[i]).to = m_edges.at(orderedEdges[i + 1]).from = pointIndex; |
|
2275 |
|
2276 Q_ASSERT(m_edges.at(orderedEdges[i]).pointingUp || m_edges.at(orderedEdges[i]).previous != -1); |
|
2277 Q_ASSERT(!m_edges.at(orderedEdges[i + 1]).pointingUp || m_edges.at(orderedEdges[i + 1]).next != -1); |
|
2278 |
|
2279 m_edges.at(orderedEdges[i]).next = orderedEdges[i + 1]; |
|
2280 m_edges.at(orderedEdges[i + 1]).previous = orderedEdges[i]; |
|
2281 } |
|
2282 } // end while |
|
2283 } |
|
2284 |
|
2285 void QTriangulator::ComplexToSimple::removeUnusedPoints() { |
|
2286 QBitArray used(m_parent->m_vertices.size(), false); |
|
2287 for (int i = 0; i < m_edges.size(); ++i) { |
|
2288 Q_ASSERT((m_edges.at(i).previous == -1) == (m_edges.at(i).next == -1)); |
|
2289 if (m_edges.at(i).next != -1) |
|
2290 used.setBit(m_edges.at(i).from); |
|
2291 } |
|
2292 QDataBuffer<quint32> newMapping(m_parent->m_vertices.size()); |
|
2293 newMapping.resize(m_parent->m_vertices.size()); |
|
2294 int count = 0; |
|
2295 for (int i = 0; i < m_parent->m_vertices.size(); ++i) { |
|
2296 if (used.at(i)) { |
|
2297 m_parent->m_vertices.at(count) = m_parent->m_vertices.at(i); |
|
2298 newMapping.at(i) = count; |
|
2299 ++count; |
|
2300 } |
|
2301 } |
|
2302 m_parent->m_vertices.resize(count); |
|
2303 for (int i = 0; i < m_edges.size(); ++i) { |
|
2304 m_edges.at(i).from = newMapping.at(m_edges.at(i).from); |
|
2305 m_edges.at(i).to = newMapping.at(m_edges.at(i).to); |
|
2306 } |
|
2307 } |
|
2308 |
|
2309 bool QTriangulator::ComplexToSimple::CompareEdges::operator () (int i, int j) const |
|
2310 { |
|
2311 int cmp = comparePoints(m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(i).from), |
|
2312 m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(j).from)); |
|
2313 if (cmp == 0) { |
|
2314 cmp = comparePoints(m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(i).to), |
|
2315 m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(j).to)); |
|
2316 } |
|
2317 return cmp > 0; |
|
2318 } |
|
2319 |
|
2320 inline bool QTriangulator::ComplexToSimple::Event::operator < (const Event &other) const |
|
2321 { |
|
2322 if (point == other.point) |
|
2323 return type < other.type; // 'Lower' has higher priority than 'Upper'. |
|
2324 return other.point < point; |
|
2325 } |
|
2326 |
|
2327 //============================================================================// |
|
2328 // QTriangulator::ComplexToSimple::DebugDialog // |
|
2329 //============================================================================// |
|
2330 |
|
2331 #ifdef Q_TRIANGULATOR_DEBUG |
|
2332 |
|
2333 QTriangulator::ComplexToSimple::DebugDialog::DebugDialog(ComplexToSimple *parent, int currentVertex) |
|
2334 : m_parent(parent), m_vertex(currentVertex) |
|
2335 { |
|
2336 QDataBuffer<QPodPoint> &vertices = m_parent->m_parent->m_vertices; |
|
2337 if (vertices.isEmpty()) |
|
2338 return; |
|
2339 |
|
2340 int minX, maxX, minY, maxY; |
|
2341 minX = maxX = vertices.at(0).x; |
|
2342 minY = maxY = vertices.at(0).y; |
|
2343 for (int i = 1; i < vertices.size(); ++i) { |
|
2344 minX = qMin(minX, vertices.at(i).x); |
|
2345 maxX = qMax(maxX, vertices.at(i).x); |
|
2346 minY = qMin(minY, vertices.at(i).y); |
|
2347 maxY = qMax(maxY, vertices.at(i).y); |
|
2348 } |
|
2349 int w = maxX - minX; |
|
2350 int h = maxY - minY; |
|
2351 qreal border = qMin(w, h) / 10.0; |
|
2352 m_window = QRectF(minX - border, minY - border, (maxX - minX + 2 * border), (maxY - minY + 2 * border)); |
|
2353 } |
|
2354 |
|
2355 void QTriangulator::ComplexToSimple::DebugDialog::paintEvent(QPaintEvent *) |
|
2356 { |
|
2357 QPainter p(this); |
|
2358 p.setRenderHint(QPainter::Antialiasing, true); |
|
2359 p.fillRect(rect(), Qt::black); |
|
2360 QDataBuffer<QPodPoint> &vertices = m_parent->m_parent->m_vertices; |
|
2361 if (vertices.isEmpty()) |
|
2362 return; |
|
2363 |
|
2364 qreal halfPointSize = qMin(m_window.width(), m_window.height()) / 300.0; |
|
2365 p.setWindow(m_window.toRect()); |
|
2366 |
|
2367 p.setPen(Qt::white); |
|
2368 |
|
2369 QDataBuffer<Edge> &edges = m_parent->m_edges; |
|
2370 for (int i = 0; i < edges.size(); ++i) { |
|
2371 QPodPoint u = vertices.at(edges.at(i).from); |
|
2372 QPodPoint v = vertices.at(edges.at(i).to); |
|
2373 p.drawLine(u.x, u.y, v.x, v.y); |
|
2374 } |
|
2375 |
|
2376 for (int i = 0; i < vertices.size(); ++i) { |
|
2377 QPodPoint q = vertices.at(i); |
|
2378 p.fillRect(QRectF(q.x - halfPointSize, q.y - halfPointSize, 2 * halfPointSize, 2 * halfPointSize), Qt::red); |
|
2379 } |
|
2380 |
|
2381 Qt::GlobalColor colors[6] = {Qt::red, Qt::green, Qt::blue, Qt::cyan, Qt::magenta, Qt::yellow}; |
|
2382 p.setOpacity(0.5); |
|
2383 int count = 0; |
|
2384 if (m_parent->m_edgeList.root) { |
|
2385 QRBTree<int>::Node *current = m_parent->m_edgeList.front(m_parent->m_edgeList.root); |
|
2386 while (current) { |
|
2387 p.setPen(colors[count++ % 6]); |
|
2388 QPodPoint u = vertices.at(edges.at(current->data).from); |
|
2389 QPodPoint v = vertices.at(edges.at(current->data).to); |
|
2390 p.drawLine(u.x, u.y, v.x, v.y); |
|
2391 current = m_parent->m_edgeList.next(current); |
|
2392 } |
|
2393 } |
|
2394 |
|
2395 p.setOpacity(1.0); |
|
2396 QPodPoint q = vertices.at(m_vertex); |
|
2397 p.fillRect(QRectF(q.x - halfPointSize, q.y - halfPointSize, 2 * halfPointSize, 2 * halfPointSize), Qt::green); |
|
2398 |
|
2399 p.setPen(Qt::gray); |
|
2400 QDataBuffer<Split> &splits = m_parent->m_splits; |
|
2401 for (int i = 0; i < splits.size(); ++i) { |
|
2402 QPodPoint q = vertices.at(splits.at(i).vertex); |
|
2403 QPodPoint u = vertices.at(edges.at(splits.at(i).edge).from) - q; |
|
2404 QPodPoint v = vertices.at(edges.at(splits.at(i).edge).to) - q; |
|
2405 qreal uLen = sqrt(qreal(qDot(u, u))); |
|
2406 qreal vLen = sqrt(qreal(qDot(v, v))); |
|
2407 if (uLen) { |
|
2408 u.x *= 2 * halfPointSize / uLen; |
|
2409 u.y *= 2 * halfPointSize / uLen; |
|
2410 } |
|
2411 if (vLen) { |
|
2412 v.x *= 2 * halfPointSize / vLen; |
|
2413 v.y *= 2 * halfPointSize / vLen; |
|
2414 } |
|
2415 u += q; |
|
2416 v += q; |
|
2417 p.drawLine(u.x, u.y, v.x, v.y); |
|
2418 } |
|
2419 } |
|
2420 |
|
2421 void QTriangulator::ComplexToSimple::DebugDialog::wheelEvent(QWheelEvent *event) |
|
2422 { |
|
2423 qreal scale = exp(-0.001 * event->delta()); |
|
2424 QPointF center = m_window.center(); |
|
2425 QPointF delta = scale * (m_window.bottomRight() - center); |
|
2426 m_window = QRectF(center - delta, center + delta); |
|
2427 event->accept(); |
|
2428 update(); |
|
2429 } |
|
2430 |
|
2431 void QTriangulator::ComplexToSimple::DebugDialog::mouseMoveEvent(QMouseEvent *event) |
|
2432 { |
|
2433 if (event->buttons() & Qt::LeftButton) { |
|
2434 QPointF delta = event->pos() - m_lastMousePos; |
|
2435 delta.setX(delta.x() * m_window.width() / width()); |
|
2436 delta.setY(delta.y() * m_window.height() / height()); |
|
2437 m_window.translate(-delta.x(), -delta.y()); |
|
2438 m_lastMousePos = event->pos(); |
|
2439 event->accept(); |
|
2440 update(); |
|
2441 } |
|
2442 } |
|
2443 |
|
2444 void QTriangulator::ComplexToSimple::DebugDialog::mousePressEvent(QMouseEvent *event) |
|
2445 { |
|
2446 if (event->button() == Qt::LeftButton) |
|
2447 m_lastMousePos = event->pos(); |
|
2448 event->accept(); |
|
2449 } |
|
2450 |
|
2451 |
|
2452 #endif |
|
2453 |
|
2454 //============================================================================// |
|
2455 // QTriangulator::SimpleToMonotone // |
|
2456 //============================================================================// |
|
2457 |
|
2458 void QTriangulator::SimpleToMonotone::decompose() |
|
2459 { |
|
2460 setupDataStructures(); |
|
2461 removeZeroLengthEdges(); |
|
2462 monotoneDecomposition(); |
|
2463 |
|
2464 m_parent->m_indices.clear(); |
|
2465 QBitArray processed(m_edges.size(), false); |
|
2466 for (int first = 0; first < m_edges.size(); ++first) { |
|
2467 if (processed.at(first)) |
|
2468 continue; |
|
2469 int i = first; |
|
2470 do { |
|
2471 Q_ASSERT(!processed.at(i)); |
|
2472 Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i); |
|
2473 m_parent->m_indices.push_back(m_edges.at(i).from); |
|
2474 processed.setBit(i); |
|
2475 i = m_edges.at(i).next; |
|
2476 } while (i != first); |
|
2477 if (m_parent->m_indices.size() > 0 && m_parent->m_indices.back() != Q_TRIANGULATE_END_OF_POLYGON) |
|
2478 m_parent->m_indices.push_back(Q_TRIANGULATE_END_OF_POLYGON); |
|
2479 } |
|
2480 } |
|
2481 |
|
2482 void QTriangulator::SimpleToMonotone::setupDataStructures() |
|
2483 { |
|
2484 int i = 0; |
|
2485 Edge e; |
|
2486 e.node = 0; |
|
2487 e.twin = -1; |
|
2488 |
|
2489 while (i + 3 <= m_parent->m_indices.size()) { |
|
2490 int start = m_edges.size(); |
|
2491 |
|
2492 do { |
|
2493 e.from = m_parent->m_indices.at(i); |
|
2494 e.type = RegularVertex; |
|
2495 e.next = m_edges.size() + 1; |
|
2496 e.previous = m_edges.size() - 1; |
|
2497 m_edges.add(e); |
|
2498 ++i; |
|
2499 Q_ASSERT(i < m_parent->m_indices.size()); |
|
2500 } while (m_parent->m_indices.at(i) != Q_TRIANGULATE_END_OF_POLYGON); |
|
2501 |
|
2502 m_edges.last().next = start; |
|
2503 m_edges.at(start).previous = m_edges.size() - 1; |
|
2504 ++i; // Skip Q_TRIANGULATE_END_OF_POLYGON. |
|
2505 } |
|
2506 |
|
2507 for (i = 0; i < m_edges.size(); ++i) { |
|
2508 m_edges.at(i).to = m_edges.at(m_edges.at(i).next).from; |
|
2509 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); |
|
2510 m_edges.at(i).helper = -1; // Not initialized here. |
|
2511 } |
|
2512 } |
|
2513 |
|
2514 void QTriangulator::SimpleToMonotone::removeZeroLengthEdges() |
|
2515 { |
|
2516 for (int i = 0; i < m_edges.size(); ++i) { |
|
2517 if (m_parent->m_vertices.at(m_edges.at(i).from) == m_parent->m_vertices.at(m_edges.at(i).to)) { |
|
2518 m_edges.at(m_edges.at(i).previous).next = m_edges.at(i).next; |
|
2519 m_edges.at(m_edges.at(i).next).previous = m_edges.at(i).previous; |
|
2520 m_edges.at(m_edges.at(i).next).from = m_edges.at(i).from; |
|
2521 m_edges.at(i).next = -1; // Mark as removed. |
|
2522 } |
|
2523 } |
|
2524 |
|
2525 QDataBuffer<int> newMapping(m_edges.size()); |
|
2526 newMapping.resize(m_edges.size()); |
|
2527 int count = 0; |
|
2528 for (int i = 0; i < m_edges.size(); ++i) { |
|
2529 if (m_edges.at(i).next != -1) { |
|
2530 m_edges.at(count) = m_edges.at(i); |
|
2531 newMapping.at(i) = count; |
|
2532 ++count; |
|
2533 } |
|
2534 } |
|
2535 m_edges.resize(count); |
|
2536 for (int i = 0; i < m_edges.size(); ++i) { |
|
2537 m_edges.at(i).next = newMapping.at(m_edges.at(i).next); |
|
2538 m_edges.at(i).previous = newMapping.at(m_edges.at(i).previous); |
|
2539 } |
|
2540 } |
|
2541 |
|
2542 void QTriangulator::SimpleToMonotone::fillPriorityQueue() |
|
2543 { |
|
2544 m_upperVertex.reset(); |
|
2545 m_upperVertex.reserve(m_edges.size()); |
|
2546 for (int i = 0; i < m_edges.size(); ++i) |
|
2547 m_upperVertex.add(i); |
|
2548 CompareVertices cmp(this); |
|
2549 //qSort(m_upperVertex.data(), m_upperVertex.data() + m_upperVertex.size(), cmp); |
|
2550 sort(m_upperVertex.data(), m_upperVertex.size(), cmp); |
|
2551 //for (int i = 1; i < m_upperVertex.size(); ++i) { |
|
2552 // Q_ASSERT(!cmp(m_upperVertex.at(i), m_upperVertex.at(i - 1))); |
|
2553 //} |
|
2554 } |
|
2555 |
|
2556 bool QTriangulator::SimpleToMonotone::edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const |
|
2557 { |
|
2558 const Edge &leftEdge = m_edges.at(leftEdgeIndex); |
|
2559 const Edge &rightEdge = m_edges.at(rightEdgeIndex); |
|
2560 const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper()); |
|
2561 const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower()); |
|
2562 qint64 d = qPointDistanceFromLine(m_parent->m_vertices.at(leftEdge.upper()), l, u); |
|
2563 // d < 0: left, d > 0: right, d == 0: on top |
|
2564 if (d == 0) |
|
2565 d = qPointDistanceFromLine(m_parent->m_vertices.at(leftEdge.lower()), l, u); |
|
2566 return d < 0; |
|
2567 } |
|
2568 |
|
2569 // Returns the rightmost edge not to the right of the given edge. |
|
2570 QRBTree<int>::Node *QTriangulator::SimpleToMonotone::searchEdgeLeftOfEdge(int edgeIndex) const |
|
2571 { |
|
2572 QRBTree<int>::Node *current = m_edgeList.root; |
|
2573 QRBTree<int>::Node *result = 0; |
|
2574 while (current) { |
|
2575 if (edgeIsLeftOfEdge(edgeIndex, current->data)) { |
|
2576 current = current->left; |
|
2577 } else { |
|
2578 result = current; |
|
2579 current = current->right; |
|
2580 } |
|
2581 } |
|
2582 return result; |
|
2583 } |
|
2584 |
|
2585 // Returns the rightmost edge left of the given point. |
|
2586 QRBTree<int>::Node *QTriangulator::SimpleToMonotone::searchEdgeLeftOfPoint(int pointIndex) const |
|
2587 { |
|
2588 QRBTree<int>::Node *current = m_edgeList.root; |
|
2589 QRBTree<int>::Node *result = 0; |
|
2590 while (current) { |
|
2591 const QPodPoint &p1 = m_parent->m_vertices.at(m_edges.at(current->data).lower()); |
|
2592 const QPodPoint &p2 = m_parent->m_vertices.at(m_edges.at(current->data).upper()); |
|
2593 qint64 d = qPointDistanceFromLine(m_parent->m_vertices.at(pointIndex), p1, p2); |
|
2594 if (d <= 0) { |
|
2595 current = current->left; |
|
2596 } else { |
|
2597 result = current; |
|
2598 current = current->right; |
|
2599 } |
|
2600 } |
|
2601 return result; |
|
2602 } |
|
2603 |
|
2604 void QTriangulator::SimpleToMonotone::classifyVertex(int i) |
|
2605 { |
|
2606 Edge &e2 = m_edges.at(i); |
|
2607 const Edge &e1 = m_edges.at(e2.previous); |
|
2608 |
|
2609 bool startOrSplit = (e1.pointingUp && !e2.pointingUp); |
|
2610 bool endOrMerge = (!e1.pointingUp && e2.pointingUp); |
|
2611 |
|
2612 const QPodPoint &p1 = m_parent->m_vertices.at(e1.from); |
|
2613 const QPodPoint &p2 = m_parent->m_vertices.at(e2.from); |
|
2614 const QPodPoint &p3 = m_parent->m_vertices.at(e2.to); |
|
2615 qint64 d = qPointDistanceFromLine(p1, p2, p3); |
|
2616 Q_ASSERT(d != 0 || (!startOrSplit && !endOrMerge)); |
|
2617 |
|
2618 e2.type = RegularVertex; |
|
2619 |
|
2620 if (m_clockwiseOrder) { |
|
2621 if (startOrSplit) |
|
2622 e2.type = (d < 0 ? SplitVertex : StartVertex); |
|
2623 else if (endOrMerge) |
|
2624 e2.type = (d < 0 ? MergeVertex : EndVertex); |
|
2625 } else { |
|
2626 if (startOrSplit) |
|
2627 e2.type = (d > 0 ? SplitVertex : StartVertex); |
|
2628 else if (endOrMerge) |
|
2629 e2.type = (d > 0 ? MergeVertex : EndVertex); |
|
2630 } |
|
2631 } |
|
2632 |
|
2633 void QTriangulator::SimpleToMonotone::classifyVertices() |
|
2634 { |
|
2635 for (int i = 0; i < m_edges.size(); ++i) |
|
2636 classifyVertex(i); |
|
2637 } |
|
2638 |
|
2639 bool QTriangulator::SimpleToMonotone::pointIsInSector(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2, const QPodPoint &v3) |
|
2640 { |
|
2641 bool leftOfPreviousEdge = !qPointIsLeftOfLine(p, v2, v1); |
|
2642 bool leftOfNextEdge = !qPointIsLeftOfLine(p, v3, v2); |
|
2643 |
|
2644 if (qPointIsLeftOfLine(v1, v2, v3)) |
|
2645 return leftOfPreviousEdge && leftOfNextEdge; |
|
2646 else |
|
2647 return leftOfPreviousEdge || leftOfNextEdge; |
|
2648 } |
|
2649 |
|
2650 bool QTriangulator::SimpleToMonotone::pointIsInSector(int vertex, int sector) |
|
2651 { |
|
2652 const QPodPoint ¢er = m_parent->m_vertices.at(m_edges.at(sector).from); |
|
2653 // Handle degenerate edges. |
|
2654 while (m_parent->m_vertices.at(m_edges.at(vertex).from) == center) |
|
2655 vertex = m_edges.at(vertex).next; |
|
2656 int next = m_edges.at(sector).next; |
|
2657 while (m_parent->m_vertices.at(m_edges.at(next).from) == center) |
|
2658 next = m_edges.at(next).next; |
|
2659 int previous = m_edges.at(sector).previous; |
|
2660 while (m_parent->m_vertices.at(m_edges.at(previous).from) == center) |
|
2661 previous = m_edges.at(previous).previous; |
|
2662 |
|
2663 const QPodPoint &p = m_parent->m_vertices.at(m_edges.at(vertex).from); |
|
2664 const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(previous).from); |
|
2665 const QPodPoint &v3 = m_parent->m_vertices.at(m_edges.at(next).from); |
|
2666 if (m_clockwiseOrder) |
|
2667 return pointIsInSector(p, v3, center, v1); |
|
2668 else |
|
2669 return pointIsInSector(p, v1, center, v3); |
|
2670 } |
|
2671 |
|
2672 int QTriangulator::SimpleToMonotone::findSector(int edge, int vertex) |
|
2673 { |
|
2674 while (!pointIsInSector(vertex, edge)) { |
|
2675 edge = m_edges.at(m_edges.at(edge).previous).twin; |
|
2676 Q_ASSERT(edge != -1); |
|
2677 } |
|
2678 return edge; |
|
2679 } |
|
2680 |
|
2681 void QTriangulator::SimpleToMonotone::createDiagonal(int lower, int upper) |
|
2682 { |
|
2683 lower = findSector(lower, upper); |
|
2684 upper = findSector(upper, lower); |
|
2685 |
|
2686 int prevLower = m_edges.at(lower).previous; |
|
2687 int prevUpper = m_edges.at(upper).previous; |
|
2688 |
|
2689 Edge e; |
|
2690 |
|
2691 e.twin = m_edges.size() + 1; |
|
2692 e.next = upper; |
|
2693 e.previous = prevLower; |
|
2694 e.from = m_edges.at(lower).from; |
|
2695 e.to = m_edges.at(upper).from; |
|
2696 m_edges.at(upper).previous = m_edges.at(prevLower).next = int(m_edges.size()); |
|
2697 m_edges.add(e); |
|
2698 |
|
2699 e.twin = m_edges.size() - 1; |
|
2700 e.next = lower; |
|
2701 e.previous = prevUpper; |
|
2702 e.from = m_edges.at(upper).from; |
|
2703 e.to = m_edges.at(lower).from; |
|
2704 m_edges.at(lower).previous = m_edges.at(prevUpper).next = int(m_edges.size()); |
|
2705 m_edges.add(e); |
|
2706 } |
|
2707 |
|
2708 void QTriangulator::SimpleToMonotone::monotoneDecomposition() |
|
2709 { |
|
2710 if (m_edges.isEmpty()) |
|
2711 return; |
|
2712 |
|
2713 Q_ASSERT(!m_edgeList.root); |
|
2714 QDataBuffer<QPair<int, int> > diagonals(m_upperVertex.size()); |
|
2715 |
|
2716 int i = 0; |
|
2717 for (int index = 1; index < m_edges.size(); ++index) { |
|
2718 if (m_parent->m_vertices.at(m_edges.at(index).from) < m_parent->m_vertices.at(m_edges.at(i).from)) |
|
2719 i = index; |
|
2720 } |
|
2721 Q_ASSERT(i < m_edges.size()); |
|
2722 int j = m_edges.at(i).previous; |
|
2723 Q_ASSERT(j < m_edges.size()); |
|
2724 m_clockwiseOrder = qPointIsLeftOfLine(m_parent->m_vertices.at(m_edges.at(i).from), |
|
2725 m_parent->m_vertices.at(m_edges.at(j).from), m_parent->m_vertices.at(m_edges.at(i).to)); |
|
2726 |
|
2727 classifyVertices(); |
|
2728 fillPriorityQueue(); |
|
2729 |
|
2730 // debug: set helpers explicitly (shouldn't be necessary) |
|
2731 //for (int i = 0; i < m_edges.size(); ++i) |
|
2732 // m_edges.at(i).helper = m_edges.at(i).upper(); |
|
2733 |
|
2734 while (!m_upperVertex.isEmpty()) { |
|
2735 i = m_upperVertex.last(); |
|
2736 Q_ASSERT(i < m_edges.size()); |
|
2737 m_upperVertex.pop_back(); |
|
2738 j = m_edges.at(i).previous; |
|
2739 Q_ASSERT(j < m_edges.size()); |
|
2740 |
|
2741 QRBTree<int>::Node *leftEdgeNode = 0; |
|
2742 |
|
2743 switch (m_edges.at(i).type) { |
|
2744 case RegularVertex: |
|
2745 // If polygon interior is to the right of the vertex... |
|
2746 if (m_edges.at(i).pointingUp == m_clockwiseOrder) { |
|
2747 if (m_edges.at(i).node) { |
|
2748 Q_ASSERT(!m_edges.at(j).node); |
|
2749 if (m_edges.at(m_edges.at(i).helper).type == MergeVertex) |
|
2750 diagonals.add(QPair<int, int>(i, m_edges.at(i).helper)); |
|
2751 m_edges.at(j).node = m_edges.at(i).node; |
|
2752 m_edges.at(i).node = 0; |
|
2753 m_edges.at(j).node->data = j; |
|
2754 m_edges.at(j).helper = i; |
|
2755 } else if (m_edges.at(j).node) { |
|
2756 Q_ASSERT(!m_edges.at(i).node); |
|
2757 if (m_edges.at(m_edges.at(j).helper).type == MergeVertex) |
|
2758 diagonals.add(QPair<int, int>(i, m_edges.at(j).helper)); |
|
2759 m_edges.at(i).node = m_edges.at(j).node; |
|
2760 m_edges.at(j).node = 0; |
|
2761 m_edges.at(i).node->data = i; |
|
2762 m_edges.at(i).helper = i; |
|
2763 } else { |
|
2764 qWarning("Inconsistent polygon. (#1)"); |
|
2765 } |
|
2766 } else { |
|
2767 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from); |
|
2768 if (leftEdgeNode) { |
|
2769 if (m_edges.at(m_edges.at(leftEdgeNode->data).helper).type == MergeVertex) |
|
2770 diagonals.add(QPair<int, int>(i, m_edges.at(leftEdgeNode->data).helper)); |
|
2771 m_edges.at(leftEdgeNode->data).helper = i; |
|
2772 } else { |
|
2773 qWarning("Inconsistent polygon. (#2)"); |
|
2774 } |
|
2775 } |
|
2776 break; |
|
2777 case SplitVertex: |
|
2778 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from); |
|
2779 if (leftEdgeNode) { |
|
2780 diagonals.add(QPair<int, int>(i, m_edges.at(leftEdgeNode->data).helper)); |
|
2781 m_edges.at(leftEdgeNode->data).helper = i; |
|
2782 } else { |
|
2783 qWarning("Inconsistent polygon. (#3)"); |
|
2784 } |
|
2785 // Fall through. |
|
2786 case StartVertex: |
|
2787 if (m_clockwiseOrder) { |
|
2788 leftEdgeNode = searchEdgeLeftOfEdge(j); |
|
2789 QRBTree<int>::Node *node = m_edgeList.newNode(); |
|
2790 node->data = j; |
|
2791 m_edges.at(j).node = node; |
|
2792 m_edges.at(j).helper = i; |
|
2793 m_edgeList.attachAfter(leftEdgeNode, node); |
|
2794 Q_ASSERT(m_edgeList.verify()); |
|
2795 } else { |
|
2796 leftEdgeNode = searchEdgeLeftOfEdge(i); |
|
2797 QRBTree<int>::Node *node = m_edgeList.newNode(); |
|
2798 node->data = i; |
|
2799 m_edges.at(i).node = node; |
|
2800 m_edges.at(i).helper = i; |
|
2801 m_edgeList.attachAfter(leftEdgeNode, node); |
|
2802 Q_ASSERT(m_edgeList.verify()); |
|
2803 } |
|
2804 break; |
|
2805 case MergeVertex: |
|
2806 leftEdgeNode = searchEdgeLeftOfPoint(m_edges.at(i).from); |
|
2807 if (leftEdgeNode) { |
|
2808 if (m_edges.at(m_edges.at(leftEdgeNode->data).helper).type == MergeVertex) |
|
2809 diagonals.add(QPair<int, int>(i, m_edges.at(leftEdgeNode->data).helper)); |
|
2810 m_edges.at(leftEdgeNode->data).helper = i; |
|
2811 } else { |
|
2812 qWarning("Inconsistent polygon. (#4)"); |
|
2813 } |
|
2814 // Fall through. |
|
2815 case EndVertex: |
|
2816 if (m_clockwiseOrder) { |
|
2817 if (m_edges.at(m_edges.at(i).helper).type == MergeVertex) |
|
2818 diagonals.add(QPair<int, int>(i, m_edges.at(i).helper)); |
|
2819 if (m_edges.at(i).node) { |
|
2820 m_edgeList.deleteNode(m_edges.at(i).node); |
|
2821 Q_ASSERT(m_edgeList.verify()); |
|
2822 } else { |
|
2823 qWarning("Inconsistent polygon. (#5)"); |
|
2824 } |
|
2825 } else { |
|
2826 if (m_edges.at(m_edges.at(j).helper).type == MergeVertex) |
|
2827 diagonals.add(QPair<int, int>(i, m_edges.at(j).helper)); |
|
2828 if (m_edges.at(j).node) { |
|
2829 m_edgeList.deleteNode(m_edges.at(j).node); |
|
2830 Q_ASSERT(m_edgeList.verify()); |
|
2831 } else { |
|
2832 qWarning("Inconsistent polygon. (#6)"); |
|
2833 } |
|
2834 } |
|
2835 break; |
|
2836 } |
|
2837 } |
|
2838 |
|
2839 for (int i = 0; i < diagonals.size(); ++i) |
|
2840 createDiagonal(diagonals.at(i).first, diagonals.at(i).second); |
|
2841 } |
|
2842 |
|
2843 bool QTriangulator::SimpleToMonotone::CompareVertices::operator () (int i, int j) const |
|
2844 { |
|
2845 if (m_parent->m_edges.at(i).from == m_parent->m_edges.at(j).from) |
|
2846 return m_parent->m_edges.at(i).type > m_parent->m_edges.at(j).type; |
|
2847 return m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(i).from) > |
|
2848 m_parent->m_parent->m_vertices.at(m_parent->m_edges.at(j).from); |
|
2849 } |
|
2850 |
|
2851 //============================================================================// |
|
2852 // QTriangulator::MonotoneToTriangles // |
|
2853 //============================================================================// |
|
2854 |
|
2855 void QTriangulator::MonotoneToTriangles::decompose() |
|
2856 { |
|
2857 QVector<quint32> result; |
|
2858 QDataBuffer<int> stack(m_parent->m_indices.size()); |
|
2859 m_first = 0; |
|
2860 // Require at least three more indices. |
|
2861 while (m_first + 3 <= m_parent->m_indices.size()) { |
|
2862 m_length = 0; |
|
2863 while (m_parent->m_indices.at(m_first + m_length) != Q_TRIANGULATE_END_OF_POLYGON) { |
|
2864 ++m_length; |
|
2865 Q_ASSERT(m_first + m_length < m_parent->m_indices.size()); |
|
2866 } |
|
2867 if (m_length < 3) { |
|
2868 m_first += m_length + 1; |
|
2869 continue; |
|
2870 } |
|
2871 |
|
2872 int minimum = 0; |
|
2873 while (less(next(minimum), minimum)) |
|
2874 minimum = next(minimum); |
|
2875 while (less(previous(minimum), minimum)) |
|
2876 minimum = previous(minimum); |
|
2877 |
|
2878 stack.reset(); |
|
2879 stack.add(minimum); |
|
2880 int left = previous(minimum); |
|
2881 int right = next(minimum); |
|
2882 bool stackIsOnLeftSide; |
|
2883 bool clockwiseOrder = leftOfEdge(minimum, left, right); |
|
2884 |
|
2885 if (less(left, right)) { |
|
2886 stack.add(left); |
|
2887 left = previous(left); |
|
2888 stackIsOnLeftSide = true; |
|
2889 } else { |
|
2890 stack.add(right); |
|
2891 right = next(right); |
|
2892 stackIsOnLeftSide = false; |
|
2893 } |
|
2894 |
|
2895 for (int count = 0; count + 2 < m_length; ++count) |
|
2896 { |
|
2897 Q_ASSERT(stack.size() >= 2); |
|
2898 if (less(left, right)) { |
|
2899 if (stackIsOnLeftSide == false) { |
|
2900 for (int i = 0; i + 1 < stack.size(); ++i) { |
|
2901 result.push_back(indices(stack.at(i + 1))); |
|
2902 result.push_back(indices(left)); |
|
2903 result.push_back(indices(stack.at(i))); |
|
2904 } |
|
2905 stack.first() = stack.last(); |
|
2906 stack.resize(1); |
|
2907 } else { |
|
2908 while (stack.size() >= 2 && (clockwiseOrder ^ !leftOfEdge(left, stack.at(stack.size() - 2), stack.last()))) { |
|
2909 result.push_back(indices(stack.at(stack.size() - 2))); |
|
2910 result.push_back(indices(left)); |
|
2911 result.push_back(indices(stack.last())); |
|
2912 stack.pop_back(); |
|
2913 } |
|
2914 } |
|
2915 stack.add(left); |
|
2916 left = previous(left); |
|
2917 stackIsOnLeftSide = true; |
|
2918 } else { |
|
2919 if (stackIsOnLeftSide == true) { |
|
2920 for (int i = 0; i + 1 < stack.size(); ++i) { |
|
2921 result.push_back(indices(stack.at(i))); |
|
2922 result.push_back(indices(right)); |
|
2923 result.push_back(indices(stack.at(i + 1))); |
|
2924 } |
|
2925 stack.first() = stack.last(); |
|
2926 stack.resize(1); |
|
2927 } else { |
|
2928 while (stack.size() >= 2 && (clockwiseOrder ^ !leftOfEdge(right, stack.last(), stack.at(stack.size() - 2)))) { |
|
2929 result.push_back(indices(stack.last())); |
|
2930 result.push_back(indices(right)); |
|
2931 result.push_back(indices(stack.at(stack.size() - 2))); |
|
2932 stack.pop_back(); |
|
2933 } |
|
2934 } |
|
2935 stack.add(right); |
|
2936 right = next(right); |
|
2937 stackIsOnLeftSide = false; |
|
2938 } |
|
2939 } |
|
2940 |
|
2941 m_first += m_length + 1; |
|
2942 } |
|
2943 m_parent->m_indices = result; |
|
2944 } |
|
2945 |
|
2946 //============================================================================// |
|
2947 // qTriangulate // |
|
2948 //============================================================================// |
|
2949 |
|
2950 QTriangleSet qTriangulate(const qreal *polygon, int count, uint hint, const QTransform &matrix) |
|
2951 { |
|
2952 QTriangulator triangulator; |
|
2953 triangulator.initialize(polygon, count, hint, matrix); |
|
2954 return triangulator.triangulate(); |
|
2955 } |
|
2956 |
|
2957 QTriangleSet qTriangulate(const QVectorPath &path, const QTransform &matrix, qreal lod) |
|
2958 { |
|
2959 QTriangulator triangulator; |
|
2960 triangulator.initialize(path, matrix, lod); |
|
2961 return triangulator.triangulate(); |
|
2962 } |
|
2963 |
|
2964 QTriangleSet qTriangulate(const QPainterPath &path, const QTransform &matrix, qreal lod) |
|
2965 { |
|
2966 QTriangulator triangulator; |
|
2967 triangulator.initialize(path, matrix, lod); |
|
2968 return triangulator.triangulate(); |
|
2969 } |
|
2970 |
|
2971 QPolylineSet qPolyline(const QVectorPath &path, const QTransform &matrix, qreal lod) |
|
2972 { |
|
2973 QTriangulator triangulator; |
|
2974 triangulator.initialize(path, matrix, lod); |
|
2975 return triangulator.polyline(); |
|
2976 } |
|
2977 |
|
2978 QPolylineSet qPolyline(const QPainterPath &path, const QTransform &matrix, qreal lod) |
|
2979 { |
|
2980 QTriangulator triangulator; |
|
2981 triangulator.initialize(path, matrix, lod); |
|
2982 return triangulator.polyline(); |
|
2983 } |
|
2984 |
|
2985 QT_END_NAMESPACE |