| 1 | /****************************************************************************
|
|---|
| 2 | **
|
|---|
| 3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|---|
| 4 | ** All rights reserved.
|
|---|
| 5 | ** Contact: Nokia Corporation ([email protected])
|
|---|
| 6 | **
|
|---|
| 7 | ** This file is part of the QtOpenGL module of the Qt Toolkit.
|
|---|
| 8 | **
|
|---|
| 9 | ** $QT_BEGIN_LICENSE:LGPL$
|
|---|
| 10 | ** Commercial Usage
|
|---|
| 11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
|---|
| 12 | ** accordance with the Qt Commercial License Agreement provided with the
|
|---|
| 13 | ** Software or, alternatively, in accordance with the terms contained in
|
|---|
| 14 | ** a written agreement between you and Nokia.
|
|---|
| 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 | ** GNU General Public License Usage
|
|---|
| 29 | ** Alternatively, this file may be used under the terms of the GNU
|
|---|
| 30 | ** General Public License version 3.0 as published by the Free Software
|
|---|
| 31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
|---|
| 32 | ** packaging of this file. Please review the following information to
|
|---|
| 33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
|---|
| 34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
|---|
| 35 | **
|
|---|
| 36 | ** If you have questions regarding the use of this file, please contact
|
|---|
| 37 | ** Nokia at [email protected].
|
|---|
| 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 | #include <private/qgl_p.h>
|
|---|
| 61 |
|
|---|
| 62 | QT_BEGIN_NAMESPACE
|
|---|
| 63 |
|
|---|
| 64 | //#define Q_TRIANGULATOR_DEBUG
|
|---|
| 65 |
|
|---|
| 66 | #define Q_FIXED_POINT_SCALE 32
|
|---|
| 67 |
|
|---|
| 68 | // Quick sort.
|
|---|
| 69 | template <class T, class LessThan>
|
|---|
| 70 | #ifdef Q_CC_RVCT // RVCT 2.2 doesn't see recursive _static_ template function
|
|---|
| 71 | void sort(T *array, int count, LessThan lessThan)
|
|---|
| 72 | #else
|
|---|
| 73 | static void sort(T *array, int count, LessThan lessThan)
|
|---|
| 74 | #endif
|
|---|
| 75 | {
|
|---|
| 76 | // If the number of elements fall below some threshold, use insertion sort.
|
|---|
| 77 | const int INSERTION_SORT_LIMIT = 7; // About 7 is fastest on my computer...
|
|---|
| 78 | if (count <= INSERTION_SORT_LIMIT) {
|
|---|
| 79 | for (int i = 1; i < count; ++i) {
|
|---|
| 80 | T temp = array[i];
|
|---|
| 81 | int j = i;
|
|---|
| 82 | while (j > 0 && lessThan(temp, array[j - 1])) {
|
|---|
| 83 | array[j] = array[j - 1];
|
|---|
| 84 | --j;
|
|---|
| 85 | }
|
|---|
| 86 | array[j] = temp;
|
|---|
| 87 | }
|
|---|
| 88 | return;
|
|---|
| 89 | }
|
|---|
| 90 |
|
|---|
| 91 | int high = count - 1;
|
|---|
| 92 | int low = 0;
|
|---|
| 93 | int mid = high / 2;
|
|---|
| 94 | if (lessThan(array[mid], array[low]))
|
|---|
| 95 | qSwap(array[mid], array[low]);
|
|---|
| 96 | if (lessThan(array[high], array[mid]))
|
|---|
| 97 | qSwap(array[high], array[mid]);
|
|---|
| 98 | if (lessThan(array[mid], array[low]))
|
|---|
| 99 | qSwap(array[mid], array[low]);
|
|---|
| 100 |
|
|---|
| 101 | --high;
|
|---|
| 102 | ++low;
|
|---|
| 103 | qSwap(array[mid], array[high]);
|
|---|
| 104 | int pivot = high;
|
|---|
| 105 | --high;
|
|---|
| 106 |
|
|---|
| 107 | while (low <= high) {
|
|---|
| 108 | while (!lessThan(array[pivot], array[low])) {
|
|---|
| 109 | ++low;
|
|---|
| 110 | if (low > high)
|
|---|
| 111 | goto sort_loop_end;
|
|---|
| 112 | }
|
|---|
| 113 | while (!lessThan(array[high], array[pivot])) {
|
|---|
| 114 | --high;
|
|---|
| 115 | if (low > high)
|
|---|
| 116 | goto sort_loop_end;
|
|---|
| 117 | }
|
|---|
| 118 | qSwap(array[low], array[high]);
|
|---|
| 119 | ++low;
|
|---|
| 120 | --high;
|
|---|
| 121 | }
|
|---|
| 122 | sort_loop_end:
|
|---|
| 123 | if (low != pivot)
|
|---|
| 124 | qSwap(array[pivot], array[low]);
|
|---|
| 125 | sort(array, low, lessThan);
|
|---|
| 126 | sort(array + low + 1, count - low - 1, lessThan);
|
|---|
| 127 | }
|
|---|
| 128 |
|
|---|
| 129 | // Quick sort.
|
|---|
| 130 | template <class T>
|
|---|
| 131 | #ifdef Q_CC_RVCT
|
|---|
| 132 | void sort(T *array, int count) // RVCT 2.2 doesn't see recursive _static_ template function
|
|---|
| 133 | #else
|
|---|
| 134 | static void sort(T *array, int count)
|
|---|
| 135 | #endif
|
|---|
| 136 | {
|
|---|
| 137 | // If the number of elements fall below some threshold, use insertion sort.
|
|---|
| 138 | const int INSERTION_SORT_LIMIT = 25; // About 25 is fastest on my computer...
|
|---|
| 139 | if (count <= INSERTION_SORT_LIMIT) {
|
|---|
| 140 | for (int i = 1; i < count; ++i) {
|
|---|
| 141 | T temp = array[i];
|
|---|
| 142 | int j = i;
|
|---|
| 143 | while (j > 0 && (temp < array[j - 1])) {
|
|---|
| 144 | array[j] = array[j - 1];
|
|---|
| 145 | --j;
|
|---|
| 146 | }
|
|---|
| 147 | array[j] = temp;
|
|---|
| 148 | }
|
|---|
| 149 | return;
|
|---|
| 150 | }
|
|---|
| 151 |
|
|---|
| 152 | int high = count - 1;
|
|---|
| 153 | int low = 0;
|
|---|
| 154 | int mid = high / 2;
|
|---|
| 155 | if ((array[mid] < array[low]))
|
|---|
| 156 | qSwap(array[mid], array[low]);
|
|---|
| 157 | if ((array[high] < array[mid]))
|
|---|
| 158 | qSwap(array[high], array[mid]);
|
|---|
| 159 | if ((array[mid] < array[low]))
|
|---|
| 160 | qSwap(array[mid], array[low]);
|
|---|
| 161 |
|
|---|
| 162 | --high;
|
|---|
| 163 | ++low;
|
|---|
| 164 | qSwap(array[mid], array[high]);
|
|---|
| 165 | int pivot = high;
|
|---|
| 166 | --high;
|
|---|
| 167 |
|
|---|
| 168 | while (low <= high) {
|
|---|
| 169 | while (!(array[pivot] < array[low])) {
|
|---|
| 170 | ++low;
|
|---|
| 171 | if (low > high)
|
|---|
| 172 | goto sort_loop_end;
|
|---|
| 173 | }
|
|---|
| 174 | while (!(array[high] < array[pivot])) {
|
|---|
| 175 | --high;
|
|---|
| 176 | if (low > high)
|
|---|
| 177 | goto sort_loop_end;
|
|---|
| 178 | }
|
|---|
| 179 | qSwap(array[low], array[high]);
|
|---|
| 180 | ++low;
|
|---|
| 181 | --high;
|
|---|
| 182 | }
|
|---|
| 183 | sort_loop_end:
|
|---|
| 184 | if (low != pivot)
|
|---|
| 185 | qSwap(array[pivot], array[low]);
|
|---|
| 186 | sort(array, low);
|
|---|
| 187 | sort(array + low + 1, count - low - 1);
|
|---|
| 188 | }
|
|---|
| 189 |
|
|---|
| 190 | template<typename T>
|
|---|
| 191 | struct QVertexSet
|
|---|
| 192 | {
|
|---|
| 193 | inline QVertexSet() { }
|
|---|
| 194 | inline QVertexSet(const QVertexSet<T> &other) : vertices(other.vertices), indices(other.indices) { }
|
|---|
| 195 | QVertexSet<T> &operator = (const QVertexSet<T> &other) {vertices = other.vertices; indices = other.indices; return *this;}
|
|---|
| 196 |
|
|---|
| 197 | // The vertices of a triangle are given by: (x[i[n]], y[i[n]]), (x[j[n]], y[j[n]]), (x[k[n]], y[k[n]]), n = 0, 1, ...
|
|---|
| 198 | QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...]
|
|---|
| 199 | QVector<T> indices; // [i[0], j[0], k[0], i[1], j[1], k[1], i[2], ...]
|
|---|
| 200 | };
|
|---|
| 201 |
|
|---|
| 202 | //============================================================================//
|
|---|
| 203 | // QFraction //
|
|---|
| 204 | //============================================================================//
|
|---|
| 205 |
|
|---|
| 206 | // Fraction must be in the range [0, 1)
|
|---|
| 207 | struct QFraction
|
|---|
| 208 | {
|
|---|
| 209 | // Comparison operators must not be called on invalid fractions.
|
|---|
| 210 | inline bool operator < (const QFraction &other) const;
|
|---|
| 211 | inline bool operator == (const QFraction &other) const;
|
|---|
| 212 | inline bool operator != (const QFraction &other) const {return !(*this == other);}
|
|---|
| 213 | inline bool operator > (const QFraction &other) const {return other < *this;}
|
|---|
| 214 | inline bool operator >= (const QFraction &other) const {return !(*this < other);}
|
|---|
| 215 | inline bool operator <= (const QFraction &other) const {return !(*this > other);}
|
|---|
| 216 |
|
|---|
| 217 | inline bool isValid() const {return denominator != 0;}
|
|---|
| 218 |
|
|---|
| 219 | // numerator and denominator must not have common denominators.
|
|---|
| 220 | quint64 numerator, denominator;
|
|---|
| 221 | };
|
|---|
| 222 |
|
|---|
| 223 | static inline quint64 gcd(quint64 x, quint64 y)
|
|---|
| 224 | {
|
|---|
| 225 | while (y != 0) {
|
|---|
| 226 | quint64 z = y;
|
|---|
| 227 | y = x % y;
|
|---|
| 228 | x = z;
|
|---|
| 229 | }
|
|---|
| 230 | return x;
|
|---|
| 231 | }
|
|---|
| 232 |
|
|---|
| 233 | static inline int compare(quint64 a, quint64 b)
|
|---|
| 234 | {
|
|---|
| 235 | return (a > b) - (a < b);
|
|---|
| 236 | }
|
|---|
| 237 |
|
|---|
| 238 | // Compare a/b with c/d.
|
|---|
| 239 | // Return negative if less, 0 if equal, positive if greater.
|
|---|
| 240 | // a < b, c < d
|
|---|
| 241 | static int qCompareFractions(quint64 a, quint64 b, quint64 c, quint64 d)
|
|---|
| 242 | {
|
|---|
| 243 | const quint64 LIMIT = Q_UINT64_C(0x100000000);
|
|---|
| 244 | for (;;) {
|
|---|
| 245 | // If the products 'ad' and 'bc' fit into 64 bits, they can be directly compared.
|
|---|
| 246 | if (b < LIMIT && d < LIMIT)
|
|---|
| 247 | return compare(a * d, b * c);
|
|---|
| 248 |
|
|---|
| 249 | if (a == 0 || c == 0)
|
|---|
| 250 | return compare(a, c);
|
|---|
| 251 |
|
|---|
| 252 | // a/b < c/d <=> d/c < b/a
|
|---|
| 253 | quint64 b_div_a = b / a;
|
|---|
| 254 | quint64 d_div_c = d / c;
|
|---|
| 255 | if (b_div_a != d_div_c)
|
|---|
| 256 | return compare(d_div_c, b_div_a);
|
|---|
| 257 |
|
|---|
| 258 | // floor(d/c) == floor(b/a)
|
|---|
| 259 | // frac(d/c) < frac(b/a) ?
|
|---|
| 260 | // frac(x/y) = (x%y)/y
|
|---|
| 261 | d -= d_div_c * c; //d %= c;
|
|---|
| 262 | b -= b_div_a * a; //b %= a;
|
|---|
| 263 | qSwap(a, d);
|
|---|
| 264 | qSwap(b, c);
|
|---|
| 265 | }
|
|---|
| 266 | }
|
|---|
| 267 |
|
|---|
| 268 | // Fraction must be in the range [0, 1)
|
|---|
| 269 | // Assume input is valid.
|
|---|
| 270 | static QFraction qFraction(quint64 n, quint64 d) {
|
|---|
| 271 | QFraction result;
|
|---|
| 272 | if (n == 0) {
|
|---|
| 273 | result.numerator = 0;
|
|---|
| 274 | result.denominator = 1;
|
|---|
| 275 | } else {
|
|---|
| 276 | quint64 g = gcd(n, d);
|
|---|
| 277 | result.numerator = n / g;
|
|---|
| 278 | result.denominator = d / g;
|
|---|
| 279 | }
|
|---|
| 280 | return result;
|
|---|
| 281 | }
|
|---|
| 282 |
|
|---|
| 283 | inline bool QFraction::operator < (const QFraction &other) const
|
|---|
| 284 | {
|
|---|
| 285 | return qCompareFractions(numerator, denominator, other.numerator, other.denominator) < 0;
|
|---|
| 286 | }
|
|---|
| 287 |
|
|---|
| 288 | inline bool QFraction::operator == (const QFraction &other) const
|
|---|
| 289 | {
|
|---|
| 290 | return numerator == other.numerator && denominator == other.denominator;
|
|---|
| 291 | }
|
|---|
| 292 |
|
|---|
| 293 | //============================================================================//
|
|---|
| 294 | // QPodPoint //
|
|---|
| 295 | //============================================================================//
|
|---|
| 296 |
|
|---|
| 297 | struct QPodPoint
|
|---|
| 298 | {
|
|---|
| 299 | inline bool operator < (const QPodPoint &other) const
|
|---|
| 300 | {
|
|---|
| 301 | if (y != other.y)
|
|---|
| 302 | return y < other.y;
|
|---|
| 303 | return x < other.x;
|
|---|
| 304 | }
|
|---|
| 305 |
|
|---|
| 306 | inline bool operator > (const QPodPoint &other) const {return other < *this;}
|
|---|
| 307 | inline bool operator <= (const QPodPoint &other) const {return !(*this > other);}
|
|---|
| 308 | inline bool operator >= (const QPodPoint &other) const {return !(*this < other);}
|
|---|
| 309 | inline bool operator == (const QPodPoint &other) const {return x == other.x && y == other.y;}
|
|---|
| 310 | inline bool operator != (const QPodPoint &other) const {return x != other.x || y != other.y;}
|
|---|
| 311 |
|
|---|
| 312 | inline QPodPoint &operator += (const QPodPoint &other) {x += other.x; y += other.y; return *this;}
|
|---|
| 313 | inline QPodPoint &operator -= (const QPodPoint &other) {x -= other.x; y -= other.y; return *this;}
|
|---|
| 314 | inline QPodPoint operator + (const QPodPoint &other) const {QPodPoint result = {x + other.x, y + other.y}; return result;}
|
|---|
| 315 | inline QPodPoint operator - (const QPodPoint &other) const {QPodPoint result = {x - other.x, y - other.y}; return result;}
|
|---|
| 316 |
|
|---|
| 317 | int x;
|
|---|
| 318 | int y;
|
|---|
| 319 | };
|
|---|
| 320 |
|
|---|
| 321 | static inline qint64 qCross(const QPodPoint &u, const QPodPoint &v)
|
|---|
| 322 | {
|
|---|
| 323 | return qint64(u.x) * qint64(v.y) - qint64(u.y) * qint64(v.x);
|
|---|
| 324 | }
|
|---|
| 325 |
|
|---|
| 326 | static inline qint64 qDot(const QPodPoint &u, const QPodPoint &v)
|
|---|
| 327 | {
|
|---|
| 328 | return qint64(u.x) * qint64(v.x) + qint64(u.y) * qint64(v.y);
|
|---|
| 329 | }
|
|---|
| 330 |
|
|---|
| 331 | // Return positive value if 'p' is to the right of the line 'v1'->'v2', negative if left of the
|
|---|
| 332 | // line and zero if exactly on the line.
|
|---|
| 333 | // The returned value is the z-component of the qCross product between 'v2-v1' and 'p-v1',
|
|---|
| 334 | // which is twice the signed area of the triangle 'p'->'v1'->'v2' (positive for CW order).
|
|---|
| 335 | static inline qint64 qPointDistanceFromLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2)
|
|---|
| 336 | {
|
|---|
| 337 | return qCross(v2 - v1, p - v1);
|
|---|
| 338 | }
|
|---|
| 339 |
|
|---|
| 340 | static inline bool qPointIsLeftOfLine(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2)
|
|---|
| 341 | {
|
|---|
| 342 | return QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(p, v1, v2) < 0;
|
|---|
| 343 | }
|
|---|
| 344 |
|
|---|
| 345 | // Return:
|
|---|
| 346 | // -1 if u < v
|
|---|
| 347 | // 0 if u == v
|
|---|
| 348 | // 1 if u > v
|
|---|
| 349 | static int comparePoints(const QPodPoint &u, const QPodPoint &v)
|
|---|
| 350 | {
|
|---|
| 351 | if (u.y < v.y)
|
|---|
| 352 | return -1;
|
|---|
| 353 | if (u.y > v.y)
|
|---|
| 354 | return 1;
|
|---|
| 355 | if (u.x < v.x)
|
|---|
| 356 | return -1;
|
|---|
| 357 | if (u.x > v.x)
|
|---|
| 358 | return 1;
|
|---|
| 359 | return 0;
|
|---|
| 360 | }
|
|---|
| 361 |
|
|---|
| 362 | //============================================================================//
|
|---|
| 363 | // QIntersectionPoint //
|
|---|
| 364 | //============================================================================//
|
|---|
| 365 |
|
|---|
| 366 | struct QIntersectionPoint
|
|---|
| 367 | {
|
|---|
| 368 | inline bool isValid() const {return xOffset.isValid() && yOffset.isValid();}
|
|---|
| 369 | QPodPoint round() const;
|
|---|
| 370 | inline bool isAccurate() const {return xOffset.numerator == 0 && yOffset.numerator == 0;}
|
|---|
| 371 | bool operator < (const QIntersectionPoint &other) const;
|
|---|
| 372 | bool operator == (const QIntersectionPoint &other) const;
|
|---|
| 373 | inline bool operator != (const QIntersectionPoint &other) const {return !(*this == other);}
|
|---|
| 374 | inline bool operator > (const QIntersectionPoint &other) const {return other < *this;}
|
|---|
| 375 | inline bool operator >= (const QIntersectionPoint &other) const {return !(*this < other);}
|
|---|
| 376 | inline bool operator <= (const QIntersectionPoint &other) const {return !(*this > other);}
|
|---|
| 377 | bool isOnLine(const QPodPoint &u, const QPodPoint &v) const;
|
|---|
| 378 |
|
|---|
| 379 | QPodPoint upperLeft;
|
|---|
| 380 | QFraction xOffset;
|
|---|
| 381 | QFraction yOffset;
|
|---|
| 382 | };
|
|---|
| 383 |
|
|---|
| 384 | static inline QIntersectionPoint qIntersectionPoint(const QPodPoint &point)
|
|---|
| 385 | {
|
|---|
| 386 | // upperLeft = point, xOffset = 0/1, yOffset = 0/1.
|
|---|
| 387 | QIntersectionPoint p = {{point.x, point.y}, {0, 1}, {0, 1}};
|
|---|
| 388 | return p;
|
|---|
| 389 | }
|
|---|
| 390 |
|
|---|
| 391 | static inline QIntersectionPoint qIntersectionPoint(int x, int y)
|
|---|
| 392 | {
|
|---|
| 393 | // upperLeft = (x, y), xOffset = 0/1, yOffset = 0/1.
|
|---|
| 394 | QIntersectionPoint p = {{x, y}, {0, 1}, {0, 1}};
|
|---|
| 395 | return p;
|
|---|
| 396 | }
|
|---|
| 397 |
|
|---|
| 398 | static QIntersectionPoint qIntersectionPoint(const QPodPoint &u1, const QPodPoint &u2, const QPodPoint &v1, const QPodPoint &v2)
|
|---|
| 399 | {
|
|---|
| 400 | QIntersectionPoint result = {{0, 0}, {0, 0}, {0, 0}};
|
|---|
| 401 |
|
|---|
| 402 | QPodPoint u = u2 - u1;
|
|---|
| 403 | QPodPoint v = v2 - v1;
|
|---|
| 404 | qint64 d1 = qCross(u, v1 - u1);
|
|---|
| 405 | qint64 d2 = qCross(u, v2 - u1);
|
|---|
| 406 | qint64 det = d2 - d1;
|
|---|
| 407 | qint64 d3 = qCross(v, u1 - v1);
|
|---|
| 408 | qint64 d4 = d3 - det; //qCross(v, u2 - v1);
|
|---|
| 409 |
|
|---|
| 410 | // Check that the math is correct.
|
|---|
| 411 | Q_ASSERT(d4 == qCross(v, u2 - v1));
|
|---|
| 412 |
|
|---|
| 413 | // The intersection point can be expressed as:
|
|---|
| 414 | // v1 - v * d1/det
|
|---|
| 415 | // v2 - v * d2/det
|
|---|
| 416 | // u1 + u * d3/det
|
|---|
| 417 | // u2 + u * d4/det
|
|---|
| 418 |
|
|---|
| 419 | // I'm only interested in lines that are crossing, so ignore parallel lines even if they overlap.
|
|---|
| 420 | if (det == 0)
|
|---|
| 421 | return result;
|
|---|
| 422 |
|
|---|
| 423 | if (det < 0) {
|
|---|
| 424 | det = -det;
|
|---|
| 425 | d1 = -d1;
|
|---|
| 426 | d2 = -d2;
|
|---|
| 427 | d3 = -d3;
|
|---|
| 428 | d4 = -d4;
|
|---|
| 429 | }
|
|---|
| 430 |
|
|---|
| 431 | // I'm only interested in lines intersecting at their interior, not at their end points.
|
|---|
| 432 | // The lines intersect at their interior if and only if 'd1 < 0', 'd2 > 0', 'd3 < 0' and 'd4 > 0'.
|
|---|
| 433 | if (d1 >= 0 || d2 <= 0 || d3 <= 0 || d4 >= 0)
|
|---|
| 434 | return result;
|
|---|
| 435 |
|
|---|
| 436 | // Calculate the intersection point as follows:
|
|---|
| 437 | // v1 - v * d1/det | v1 <= v2 (component-wise)
|
|---|
| 438 | // v2 - v * d2/det | v2 < v1 (component-wise)
|
|---|
| 439 |
|
|---|
| 440 | // Assuming 21 bits per vector component.
|
|---|
| 441 | // TODO: Make code path for 31 bits per vector component.
|
|---|
| 442 | if (v.x >= 0) {
|
|---|
| 443 | result.upperLeft.x = v1.x + (-v.x * d1) / det;
|
|---|
| 444 | result.xOffset = qFraction(quint64(-v.x * d1) % quint64(det), quint64(det));
|
|---|
| 445 | } else {
|
|---|
| 446 | result.upperLeft.x = v2.x + (-v.x * d2) / det;
|
|---|
| 447 | result.xOffset = qFraction(quint64(-v.x * d2) % quint64(det), quint64(det));
|
|---|
| 448 | }
|
|---|
| 449 |
|
|---|
| 450 | if (v.y >= 0) {
|
|---|
| 451 | result.upperLeft.y = v1.y + (-v.y * d1) / det;
|
|---|
| 452 | result.yOffset = qFraction(quint64(-v.y * d1) % quint64(det), quint64(det));
|
|---|
| 453 | } else {
|
|---|
| 454 | result.upperLeft.y = v2.y + (-v.y * d2) / det;
|
|---|
| 455 | result.yOffset = qFraction(quint64(-v.y * d2) % quint64(det), quint64(det));
|
|---|
| 456 | }
|
|---|
| 457 |
|
|---|
| 458 | Q_ASSERT(result.xOffset.isValid());
|
|---|
| 459 | Q_ASSERT(result.yOffset.isValid());
|
|---|
| 460 | return result;
|
|---|
| 461 | }
|
|---|
| 462 |
|
|---|
| 463 | QPodPoint QIntersectionPoint::round() const
|
|---|
| 464 | {
|
|---|
| 465 | QPodPoint result = upperLeft;
|
|---|
| 466 | if (2 * xOffset.numerator >= xOffset.denominator)
|
|---|
| 467 | ++result.x;
|
|---|
| 468 | if (2 * yOffset.numerator >= yOffset.denominator)
|
|---|
| 469 | ++result.y;
|
|---|
| 470 | return result;
|
|---|
| 471 | }
|
|---|
| 472 |
|
|---|
| 473 | bool QIntersectionPoint::operator < (const QIntersectionPoint &other) const
|
|---|
| 474 | {
|
|---|
| 475 | if (upperLeft.y != other.upperLeft.y)
|
|---|
| 476 | return upperLeft.y < other.upperLeft.y;
|
|---|
| 477 | if (yOffset != other.yOffset)
|
|---|
| 478 | return yOffset < other.yOffset;
|
|---|
| 479 | if (upperLeft.x != other.upperLeft.x)
|
|---|
| 480 | return upperLeft.x < other.upperLeft.x;
|
|---|
| 481 | return xOffset < other.xOffset;
|
|---|
| 482 | }
|
|---|
| 483 |
|
|---|
| 484 | bool QIntersectionPoint::operator == (const QIntersectionPoint &other) const
|
|---|
| 485 | {
|
|---|
| 486 | return upperLeft == other.upperLeft && xOffset == other.xOffset && yOffset == other.yOffset;
|
|---|
| 487 | }
|
|---|
| 488 |
|
|---|
| 489 | // Returns true if this point is on the infinite line passing through 'u' and 'v'.
|
|---|
| 490 | bool QIntersectionPoint::isOnLine(const QPodPoint &u, const QPodPoint &v) const
|
|---|
| 491 | {
|
|---|
| 492 | // TODO: Make code path for coordinates with more than 21 bits.
|
|---|
| 493 | const QPodPoint p = upperLeft - u;
|
|---|
| 494 | const QPodPoint q = v - u;
|
|---|
| 495 | bool isHorizontal = p.y == 0 && yOffset.numerator == 0;
|
|---|
| 496 | bool isVertical = p.x == 0 && xOffset.numerator == 0;
|
|---|
| 497 | if (isHorizontal && isVertical)
|
|---|
| 498 | return true;
|
|---|
| 499 | if (isHorizontal)
|
|---|
| 500 | return q.y == 0;
|
|---|
| 501 | if (q.y == 0)
|
|---|
| 502 | return false;
|
|---|
| 503 | if (isVertical)
|
|---|
| 504 | return q.x == 0;
|
|---|
| 505 | if (q.x == 0)
|
|---|
| 506 | return false;
|
|---|
| 507 |
|
|---|
| 508 | // At this point, 'p+offset' and 'q' cannot lie on the x or y axis.
|
|---|
| 509 |
|
|---|
| 510 | if (((q.x < 0) == (q.y < 0)) != ((p.x < 0) == (p.y < 0)))
|
|---|
| 511 | return false; // 'p + offset' and 'q' pass through different quadrants.
|
|---|
| 512 |
|
|---|
| 513 | // Move all coordinates into the first quadrant.
|
|---|
| 514 | quint64 nx, ny;
|
|---|
| 515 | if (p.x < 0)
|
|---|
| 516 | nx = quint64(-p.x) * xOffset.denominator - xOffset.numerator;
|
|---|
| 517 | else
|
|---|
| 518 | nx = quint64(p.x) * xOffset.denominator + xOffset.numerator;
|
|---|
| 519 | if (p.y < 0)
|
|---|
| 520 | ny = quint64(-p.y) * yOffset.denominator - yOffset.numerator;
|
|---|
| 521 | else
|
|---|
| 522 | ny = quint64(p.y) * yOffset.denominator + yOffset.numerator;
|
|---|
| 523 |
|
|---|
| 524 | return qFraction(quint64(qAbs(q.x)) * xOffset.denominator, quint64(qAbs(q.y)) * yOffset.denominator) == qFraction(nx, ny);
|
|---|
| 525 | }
|
|---|
| 526 |
|
|---|
| 527 | //============================================================================//
|
|---|
| 528 | // QMaxHeap //
|
|---|
| 529 | //============================================================================//
|
|---|
| 530 |
|
|---|
| 531 | template <class T>
|
|---|
| 532 | class QMaxHeap
|
|---|
| 533 | {
|
|---|
| 534 | public:
|
|---|
| 535 | QMaxHeap() : m_data(0) {}
|
|---|
| 536 | inline int size() const {return m_data.size();}
|
|---|
| 537 | inline bool empty() const {return m_data.isEmpty();}
|
|---|
| 538 | inline bool isEmpty() const {return m_data.isEmpty();}
|
|---|
| 539 | void push(const T &x);
|
|---|
| 540 | T pop();
|
|---|
| 541 | inline const T &top() const {return m_data.first();}
|
|---|
| 542 | private:
|
|---|
| 543 | static inline int parent(int i) {return (i - 1) / 2;}
|
|---|
| 544 | static inline int left(int i) {return 2 * i + 1;}
|
|---|
| 545 | static inline int right(int i) {return 2 * i + 2;}
|
|---|
| 546 |
|
|---|
| 547 | QDataBuffer<T> m_data;
|
|---|
| 548 | };
|
|---|
| 549 |
|
|---|
| 550 | template <class T>
|
|---|
| 551 | void QMaxHeap<T>::push(const T &x)
|
|---|
| 552 | {
|
|---|
| 553 | int current = m_data.size();
|
|---|
| 554 | int parent = QMaxHeap::parent(current);
|
|---|
| 555 | m_data.add(x);
|
|---|
| 556 | while (current != 0 && m_data.at(parent) < x) {
|
|---|
| 557 | m_data.at(current) = m_data.at(parent);
|
|---|
| 558 | current = parent;
|
|---|
| 559 | parent = QMaxHeap::parent(current);
|
|---|
| 560 | }
|
|---|
| 561 | m_data.at(current) = x;
|
|---|
| 562 | }
|
|---|
| 563 |
|
|---|
| 564 | template <class T>
|
|---|
| 565 | T QMaxHeap<T>::pop()
|
|---|
| 566 | {
|
|---|
| 567 | T result = m_data.first();
|
|---|
| 568 | T back = m_data.last();
|
|---|
| 569 | m_data.pop_back();
|
|---|
| 570 | if (!m_data.isEmpty()) {
|
|---|
| 571 | int current = 0;
|
|---|
| 572 | for (;;) {
|
|---|
| 573 | int left = QMaxHeap::left(current);
|
|---|
| 574 | int right = QMaxHeap::right(current);
|
|---|
| 575 | if (left >= m_data.size())
|
|---|
| 576 | break;
|
|---|
| 577 | int greater = left;
|
|---|
| 578 | if (right < m_data.size() && m_data.at(left) < m_data.at(right))
|
|---|
| 579 | greater = right;
|
|---|
| 580 | if (m_data.at(greater) < back)
|
|---|
| 581 | break;
|
|---|
| 582 | m_data.at(current) = m_data.at(greater);
|
|---|
| 583 | current = greater;
|
|---|
| 584 | }
|
|---|
| 585 | m_data.at(current) = back;
|
|---|
| 586 | }
|
|---|
| 587 | return result;
|
|---|
| 588 | }
|
|---|
| 589 |
|
|---|
| 590 | //============================================================================//
|
|---|
| 591 | // QRBTree //
|
|---|
| 592 | //============================================================================//
|
|---|
| 593 |
|
|---|
| 594 | template <class T>
|
|---|
| 595 | struct QRBTree
|
|---|
| 596 | {
|
|---|
| 597 | struct Node
|
|---|
| 598 | {
|
|---|
| 599 | inline Node() : parent(0), left(0), right(0), red(true) { }
|
|---|
| 600 | inline ~Node() {if (left) delete left; if (right) delete right;}
|
|---|
| 601 | T data;
|
|---|
| 602 | Node *parent;
|
|---|
| 603 | Node *left;
|
|---|
| 604 | Node *right;
|
|---|
| 605 | bool red;
|
|---|
| 606 | };
|
|---|
| 607 |
|
|---|
| 608 | inline QRBTree() : root(0), freeList(0) { }
|
|---|
| 609 | inline ~QRBTree();
|
|---|
| 610 |
|
|---|
| 611 | inline void clear();
|
|---|
| 612 |
|
|---|
| 613 | void attachBefore(Node *parent, Node *child);
|
|---|
| 614 | void attachAfter(Node *parent, Node *child);
|
|---|
| 615 |
|
|---|
| 616 | inline Node *front(Node *node) const;
|
|---|
| 617 | inline Node *back(Node *node) const;
|
|---|
| 618 | Node *next(Node *node) const;
|
|---|
| 619 | Node *previous(Node *node) const;
|
|---|
| 620 |
|
|---|
| 621 | inline void deleteNode(Node *&node);
|
|---|
| 622 | inline Node *newNode();
|
|---|
| 623 |
|
|---|
| 624 | // Return 1 if 'left' comes after 'right', 0 if equal, and -1 otherwise.
|
|---|
| 625 | // 'left' and 'right' cannot be null.
|
|---|
| 626 | int order(Node *left, Node *right);
|
|---|
| 627 | inline bool validate() const;
|
|---|
| 628 |
|
|---|
| 629 | private:
|
|---|
| 630 | void rotateLeft(Node *node);
|
|---|
| 631 | void rotateRight(Node *node);
|
|---|
| 632 | void update(Node *node);
|
|---|
| 633 |
|
|---|
| 634 | inline void attachLeft(Node *parent, Node *child);
|
|---|
| 635 | inline void attachRight(Node *parent, Node *child);
|
|---|
| 636 |
|
|---|
| 637 | int blackDepth(Node *top) const;
|
|---|
| 638 | bool checkRedBlackProperty(Node *top) const;
|
|---|
| 639 |
|
|---|
| 640 | void swapNodes(Node *n1, Node *n2);
|
|---|
| 641 | void detach(Node *node);
|
|---|
| 642 |
|
|---|
| 643 | // 'node' must be black. rebalance will reduce the depth of black nodes by one in the sibling tree.
|
|---|
| 644 | void rebalance(Node *node);
|
|---|
| 645 |
|
|---|
| 646 | public:
|
|---|
| 647 | Node *root;
|
|---|
| 648 | private:
|
|---|
| 649 | Node *freeList;
|
|---|
| 650 | };
|
|---|
| 651 |
|
|---|
| 652 | template <class T>
|
|---|
| 653 | inline QRBTree<T>::~QRBTree()
|
|---|
| 654 | {
|
|---|
| 655 | clear();
|
|---|
| 656 | while (freeList) {
|
|---|
| 657 | // Avoid recursively calling the destructor, as this list may become large.
|
|---|
| 658 | Node *next = freeList->right;
|
|---|
| 659 | freeList->right = 0;
|
|---|
| 660 | delete freeList;
|
|---|
| 661 | freeList = next;
|
|---|
| 662 | }
|
|---|
| 663 | }
|
|---|
| 664 |
|
|---|
| 665 | template <class T>
|
|---|
| 666 | inline void QRBTree<T>::clear()
|
|---|
| 667 | {
|
|---|
| 668 | if (root)
|
|---|
| 669 | delete root;
|
|---|
| 670 | root = 0;
|
|---|
| 671 | }
|
|---|
| 672 |
|
|---|
| 673 | template <class T>
|
|---|
| 674 | void QRBTree<T>::rotateLeft(Node *node)
|
|---|
| 675 | {
|
|---|
| 676 | // | | //
|
|---|
| 677 | // N B //
|
|---|
| 678 | // / \ / \ //
|
|---|
| 679 | // A B ---> N D //
|
|---|
| 680 | // / \ / \ //
|
|---|
| 681 | // C D A C //
|
|---|
| 682 |
|
|---|
| 683 | Node *&ref = (node->parent ? (node == node->parent->left ? node->parent->left : node->parent->right) : root);
|
|---|
| 684 | ref = node->right;
|
|---|
| 685 | node->right->parent = node->parent;
|
|---|
| 686 |
|
|---|
| 687 | // : //
|
|---|
| 688 | // N //
|
|---|
| 689 | // / :| //
|
|---|
| 690 | // A B //
|
|---|
| 691 | // / \ //
|
|---|
| 692 | // C D //
|
|---|
| 693 |
|
|---|
| 694 | node->right = ref->left;
|
|---|
| 695 | if (ref->left)
|
|---|
| 696 | ref->left->parent = node;
|
|---|
| 697 |
|
|---|
| 698 | // : | //
|
|---|
| 699 | // N B //
|
|---|
| 700 | // / \ : \ //
|
|---|
| 701 | // A C D //
|
|---|
| 702 |
|
|---|
| 703 | ref->left = node;
|
|---|
| 704 | node->parent = ref;
|
|---|
| 705 |
|
|---|
| 706 | // | //
|
|---|
| 707 | // B //
|
|---|
| 708 | // / \ //
|
|---|
| 709 | // N D //
|
|---|
| 710 | // / \ //
|
|---|
| 711 | // A C //
|
|---|
| 712 | }
|
|---|
| 713 |
|
|---|
| 714 | template <class T>
|
|---|
| 715 | void QRBTree<T>::rotateRight(Node *node)
|
|---|
| 716 | {
|
|---|
| 717 | // | | //
|
|---|
| 718 | // N A //
|
|---|
| 719 | // / \ / \ //
|
|---|
| 720 | // A B ---> C N //
|
|---|
| 721 | // / \ / \ //
|
|---|
| 722 | // C D D B //
|
|---|
| 723 |
|
|---|
| 724 | Node *&ref = (node->parent ? (node == node->parent->left ? node->parent->left : node->parent->right) : root);
|
|---|
| 725 | ref = node->left;
|
|---|
| 726 | node->left->parent = node->parent;
|
|---|
| 727 |
|
|---|
| 728 | node->left = ref->right;
|
|---|
| 729 | if (ref->right)
|
|---|
| 730 | ref->right->parent = node;
|
|---|
| 731 |
|
|---|
| 732 | ref->right = node;
|
|---|
| 733 | node->parent = ref;
|
|---|
| 734 | }
|
|---|
| 735 |
|
|---|
| 736 | template <class T>
|
|---|
| 737 | void QRBTree<T>::update(Node *node) // call this after inserting a node
|
|---|
| 738 | {
|
|---|
| 739 | for (;;) {
|
|---|
| 740 | Node *parent = node->parent;
|
|---|
| 741 |
|
|---|
| 742 | // if the node is the root, color it black
|
|---|
| 743 | if (!parent) {
|
|---|
| 744 | node->red = false;
|
|---|
| 745 | return;
|
|---|
| 746 | }
|
|---|
| 747 |
|
|---|
| 748 | // if the parent is black, the node can be left red
|
|---|
| 749 | if (!parent->red)
|
|---|
| 750 | return;
|
|---|
| 751 |
|
|---|
| 752 | // at this point, the parent is red and cannot be the root
|
|---|
| 753 | Node *grandpa = parent->parent;
|
|---|
| 754 | Q_ASSERT(grandpa);
|
|---|
| 755 |
|
|---|
| 756 | Node *uncle = (parent == grandpa->left ? grandpa->right : grandpa->left);
|
|---|
| 757 | if (uncle && uncle->red) {
|
|---|
| 758 | // grandpa's black, parent and uncle are red.
|
|---|
| 759 | // let parent and uncle be black, grandpa red and recursively update grandpa.
|
|---|
| 760 | Q_ASSERT(!grandpa->red);
|
|---|
| 761 | parent->red = false;
|
|---|
| 762 | uncle->red = false;
|
|---|
| 763 | grandpa->red = true;
|
|---|
| 764 | node = grandpa;
|
|---|
| 765 | continue;
|
|---|
| 766 | }
|
|---|
| 767 |
|
|---|
| 768 | // at this point, uncle is black
|
|---|
| 769 | if (node == parent->right && parent == grandpa->left)
|
|---|
| 770 | rotateLeft(node = parent);
|
|---|
| 771 | else if (node == parent->left && parent == grandpa->right)
|
|---|
| 772 | rotateRight(node = parent);
|
|---|
| 773 | parent = node->parent;
|
|---|
| 774 |
|
|---|
| 775 | if (parent == grandpa->left) {
|
|---|
| 776 | rotateRight(grandpa);
|
|---|
| 777 | parent->red = false;
|
|---|
| 778 | grandpa->red = true;
|
|---|
| 779 | } else {
|
|---|
| 780 | rotateLeft(grandpa);
|
|---|
| 781 | parent->red = false;
|
|---|
| 782 | grandpa->red = true;
|
|---|
| 783 | }
|
|---|
| 784 | return;
|
|---|
| 785 | }
|
|---|
| 786 | }
|
|---|
| 787 |
|
|---|
| 788 | template <class T>
|
|---|
| 789 | inline void QRBTree<T>::attachLeft(Node *parent, Node *child)
|
|---|
| 790 | {
|
|---|
| 791 | Q_ASSERT(!parent->left);
|
|---|
| 792 | parent->left = child;
|
|---|
| 793 | child->parent = parent;
|
|---|
| 794 | update(child);
|
|---|
| 795 | }
|
|---|
| 796 |
|
|---|
| 797 | template <class T>
|
|---|
| 798 | inline void QRBTree<T>::attachRight(Node *parent, Node *child)
|
|---|
| 799 | {
|
|---|
| 800 | Q_ASSERT(!parent->right);
|
|---|
| 801 | parent->right = child;
|
|---|
| 802 | child->parent = parent;
|
|---|
| 803 | update(child);
|
|---|
| 804 | }
|
|---|
| 805 |
|
|---|
| 806 | template <class T>
|
|---|
| 807 | void QRBTree<T>::attachBefore(Node *parent, Node *child)
|
|---|
| 808 | {
|
|---|
| 809 | if (!root)
|
|---|
| 810 | update(root = child);
|
|---|
| 811 | else if (!parent)
|
|---|
| 812 | attachRight(back(root), child);
|
|---|
| 813 | else if (parent->left)
|
|---|
| 814 | attachRight(back(parent->left), child);
|
|---|
| 815 | else
|
|---|
| 816 | attachLeft(parent, child);
|
|---|
| 817 | }
|
|---|
| 818 |
|
|---|
| 819 | template <class T>
|
|---|
| 820 | void QRBTree<T>::attachAfter(Node *parent, Node *child)
|
|---|
| 821 | {
|
|---|
| 822 | if (!root)
|
|---|
| 823 | update(root = child);
|
|---|
| 824 | else if (!parent)
|
|---|
| 825 | attachLeft(front(root), child);
|
|---|
| 826 | else if (parent->right)
|
|---|
| 827 | attachLeft(front(parent->right), child);
|
|---|
| 828 | else
|
|---|
| 829 | attachRight(parent, child);
|
|---|
| 830 | }
|
|---|
| 831 |
|
|---|
| 832 | template <class T>
|
|---|
| 833 | void QRBTree<T>::swapNodes(Node *n1, Node *n2)
|
|---|
| 834 | {
|
|---|
| 835 | // Since iterators must not be invalidated, it is not sufficient to only swap the data.
|
|---|
| 836 | if (n1->parent == n2) {
|
|---|
| 837 | n1->parent = n2->parent;
|
|---|
| 838 | n2->parent = n1;
|
|---|
| 839 | } else if (n2->parent == n1) {
|
|---|
| 840 | n2->parent = n1->parent;
|
|---|
| 841 | n1->parent = n2;
|
|---|
| 842 | } else {
|
|---|
| 843 | qSwap(n1->parent, n2->parent);
|
|---|
| 844 | }
|
|---|
| 845 |
|
|---|
| 846 | qSwap(n1->left, n2->left);
|
|---|
| 847 | qSwap(n1->right, n2->right);
|
|---|
| 848 | qSwap(n1->red, n2->red);
|
|---|
| 849 |
|
|---|
| 850 | if (n1->parent) {
|
|---|
| 851 | if (n1->parent->left == n2)
|
|---|
| 852 | n1->parent->left = n1;
|
|---|
| 853 | else
|
|---|
| 854 | n1->parent->right = n1;
|
|---|
| 855 | } else {
|
|---|
| 856 | root = n1;
|
|---|
| 857 | }
|
|---|
| 858 |
|
|---|
| 859 | if (n2->parent) {
|
|---|
| 860 | if (n2->parent->left == n1)
|
|---|
| 861 | n2->parent->left = n2;
|
|---|
| 862 | else
|
|---|
| 863 | n2->parent->right = n2;
|
|---|
| 864 | } else {
|
|---|
| 865 | root = n2;
|
|---|
| 866 | }
|
|---|
| 867 |
|
|---|
| 868 | if (n1->left)
|
|---|
| 869 | n1->left->parent = n1;
|
|---|
| 870 | if (n1->right)
|
|---|
| 871 | n1->right->parent = n1;
|
|---|
| 872 |
|
|---|
| 873 | if (n2->left)
|
|---|
| 874 | n2->left->parent = n2;
|
|---|
| 875 | if (n2->right)
|
|---|
| 876 | n2->right->parent = n2;
|
|---|
| 877 | }
|
|---|
| 878 |
|
|---|
| 879 | template <class T>
|
|---|
| 880 | void QRBTree<T>::detach(Node *node) // call this before removing a node.
|
|---|
| 881 | {
|
|---|
| 882 | if (node->right)
|
|---|
| 883 | swapNodes(node, front(node->right));
|
|---|
| 884 |
|
|---|
| 885 | Node *child = (node->left ? node->left : node->right);
|
|---|
| 886 |
|
|---|
| 887 | if (!node->red) {
|
|---|
| 888 | if (child && child->red)
|
|---|
| 889 | child->red = false;
|
|---|
| 890 | else
|
|---|
| 891 | rebalance(node);
|
|---|
| 892 | }
|
|---|
| 893 |
|
|---|
| 894 | Node *&ref = (node->parent ? (node == node->parent->left ? node->parent->left : node->parent->right) : root);
|
|---|
| 895 | ref = child;
|
|---|
| 896 | if (child)
|
|---|
| 897 | child->parent = node->parent;
|
|---|
| 898 | node->left = node->right = node->parent = 0;
|
|---|
| 899 | }
|
|---|
| 900 |
|
|---|
| 901 | // 'node' must be black. rebalance will reduce the depth of black nodes by one in the sibling tree.
|
|---|
| 902 | template <class T>
|
|---|
| 903 | void QRBTree<T>::rebalance(Node *node)
|
|---|
| 904 | {
|
|---|
| 905 | Q_ASSERT(!node->red);
|
|---|
| 906 | for (;;) {
|
|---|
| 907 | if (!node->parent)
|
|---|
| 908 | return;
|
|---|
| 909 |
|
|---|
| 910 | // at this point, node is not a parent, it is black, thus it must have a sibling.
|
|---|
| 911 | Node *sibling = (node == node->parent->left ? node->parent->right : node->parent->left);
|
|---|
| 912 | Q_ASSERT(sibling);
|
|---|
| 913 |
|
|---|
| 914 | if (sibling->red) {
|
|---|
| 915 | sibling->red = false;
|
|---|
| 916 | node->parent->red = true;
|
|---|
| 917 | if (node == node->parent->left)
|
|---|
| 918 | rotateLeft(node->parent);
|
|---|
| 919 | else
|
|---|
| 920 | rotateRight(node->parent);
|
|---|
| 921 | sibling = (node == node->parent->left ? node->parent->right : node->parent->left);
|
|---|
| 922 | Q_ASSERT(sibling);
|
|---|
| 923 | }
|
|---|
| 924 |
|
|---|
| 925 | // at this point, the sibling is black.
|
|---|
| 926 | Q_ASSERT(!sibling->red);
|
|---|
| 927 |
|
|---|
| 928 | if ((!sibling->left || !sibling->left->red) && (!sibling->right || !sibling->right->red)) {
|
|---|
| 929 | bool parentWasRed = node->parent->red;
|
|---|
| 930 | sibling->red = true;
|
|---|
| 931 | node->parent->red = false;
|
|---|
| 932 | if (parentWasRed)
|
|---|
| 933 | return;
|
|---|
| 934 | node = node->parent;
|
|---|
| 935 | continue;
|
|---|
| 936 | }
|
|---|
| 937 |
|
|---|
| 938 | // at this point, at least one of the sibling's children is red.
|
|---|
| 939 |
|
|---|
| 940 | if (node == node->parent->left) {
|
|---|
| 941 | if (!sibling->right || !sibling->right->red) {
|
|---|
| 942 | Q_ASSERT(sibling->left);
|
|---|
| 943 | sibling->red = true;
|
|---|
| 944 | sibling->left->red = false;
|
|---|
| 945 | rotateRight(sibling);
|
|---|
| 946 |
|
|---|
| 947 | sibling = sibling->parent;
|
|---|
| 948 | Q_ASSERT(sibling);
|
|---|
| 949 | }
|
|---|
| 950 | sibling->red = node->parent->red;
|
|---|
| 951 | node->parent->red = false;
|
|---|
| 952 |
|
|---|
| 953 | Q_ASSERT(sibling->right->red);
|
|---|
| 954 | sibling->right->red = false;
|
|---|
| 955 | rotateLeft(node->parent);
|
|---|
| 956 | } else {
|
|---|
| 957 | if (!sibling->left || !sibling->left->red) {
|
|---|
| 958 | Q_ASSERT(sibling->right);
|
|---|
| 959 | sibling->red = true;
|
|---|
| 960 | sibling->right->red = false;
|
|---|
| 961 | rotateLeft(sibling);
|
|---|
| 962 |
|
|---|
| 963 | sibling = sibling->parent;
|
|---|
| 964 | Q_ASSERT(sibling);
|
|---|
| 965 | }
|
|---|
| 966 | sibling->red = node->parent->red;
|
|---|
| 967 | node->parent->red = false;
|
|---|
| 968 |
|
|---|
| 969 | Q_ASSERT(sibling->left->red);
|
|---|
| 970 | sibling->left->red = false;
|
|---|
| 971 | rotateRight(node->parent);
|
|---|
| 972 | }
|
|---|
| 973 | return;
|
|---|
| 974 | }
|
|---|
| 975 | }
|
|---|
| 976 |
|
|---|
| 977 | template <class T>
|
|---|
| 978 | inline typename QRBTree<T>::Node *QRBTree<T>::front(Node *node) const
|
|---|
| 979 | {
|
|---|
| 980 | while (node->left)
|
|---|
| 981 | node = node->left;
|
|---|
| 982 | return node;
|
|---|
| 983 | }
|
|---|
| 984 |
|
|---|
| 985 | template <class T>
|
|---|
| 986 | inline typename QRBTree<T>::Node *QRBTree<T>::back(Node *node) const
|
|---|
| 987 | {
|
|---|
| 988 | while (node->right)
|
|---|
| 989 | node = node->right;
|
|---|
| 990 | return node;
|
|---|
| 991 | }
|
|---|
| 992 |
|
|---|
| 993 | template <class T>
|
|---|
| 994 | typename QRBTree<T>::Node *QRBTree<T>::next(Node *node) const
|
|---|
| 995 | {
|
|---|
| 996 | if (node->right)
|
|---|
| 997 | return front(node->right);
|
|---|
| 998 | while (node->parent && node == node->parent->right)
|
|---|
| 999 | node = node->parent;
|
|---|
| 1000 | return node->parent;
|
|---|
| 1001 | }
|
|---|
| 1002 |
|
|---|
| 1003 | template <class T>
|
|---|
| 1004 | typename QRBTree<T>::Node *QRBTree<T>::previous(Node *node) const
|
|---|
| 1005 | {
|
|---|
| 1006 | if (node->left)
|
|---|
| 1007 | return back(node->left);
|
|---|
| 1008 | while (node->parent && node == node->parent->left)
|
|---|
| 1009 | node = node->parent;
|
|---|
| 1010 | return node->parent;
|
|---|
| 1011 | }
|
|---|
| 1012 |
|
|---|
| 1013 | template <class T>
|
|---|
| 1014 | int QRBTree<T>::blackDepth(Node *top) const
|
|---|
| 1015 | {
|
|---|
| 1016 | if (!top)
|
|---|
| 1017 | return 0;
|
|---|
| 1018 | int leftDepth = blackDepth(top->left);
|
|---|
| 1019 | int rightDepth = blackDepth(top->right);
|
|---|
| 1020 | if (leftDepth != rightDepth)
|
|---|
| 1021 | return -1;
|
|---|
| 1022 | if (!top->red)
|
|---|
| 1023 | ++leftDepth;
|
|---|
| 1024 | return leftDepth;
|
|---|
| 1025 | }
|
|---|
| 1026 |
|
|---|
| 1027 | template <class T>
|
|---|
| 1028 | bool QRBTree<T>::checkRedBlackProperty(Node *top) const
|
|---|
| 1029 | {
|
|---|
| 1030 | if (!top)
|
|---|
| 1031 | return true;
|
|---|
| 1032 | if (top->left && !checkRedBlackProperty(top->left))
|
|---|
| 1033 | return false;
|
|---|
| 1034 | if (top->right && !checkRedBlackProperty(top->right))
|
|---|
| 1035 | return false;
|
|---|
| 1036 | return !(top->red && ((top->left && top->left->red) || (top->right && top->right->red)));
|
|---|
| 1037 | }
|
|---|
| 1038 |
|
|---|
| 1039 | template <class T>
|
|---|
| 1040 | inline bool QRBTree<T>::validate() const
|
|---|
| 1041 | {
|
|---|
| 1042 | return checkRedBlackProperty(root) && blackDepth(root) != -1;
|
|---|
| 1043 | }
|
|---|
| 1044 |
|
|---|
| 1045 | template <class T>
|
|---|
| 1046 | inline void QRBTree<T>::deleteNode(Node *&node)
|
|---|
| 1047 | {
|
|---|
| 1048 | Q_ASSERT(node);
|
|---|
| 1049 | detach(node);
|
|---|
| 1050 | node->right = freeList;
|
|---|
| 1051 | freeList = node;
|
|---|
| 1052 | node = 0;
|
|---|
| 1053 | }
|
|---|
| 1054 |
|
|---|
| 1055 | template <class T>
|
|---|
| 1056 | inline typename QRBTree<T>::Node *QRBTree<T>::newNode()
|
|---|
| 1057 | {
|
|---|
| 1058 | if (freeList) {
|
|---|
| 1059 | Node *node = freeList;
|
|---|
| 1060 | freeList = freeList->right;
|
|---|
| 1061 | node->parent = node->left = node->right = 0;
|
|---|
| 1062 | node->red = true;
|
|---|
| 1063 | return node;
|
|---|
| 1064 | }
|
|---|
| 1065 | return new Node;
|
|---|
| 1066 | }
|
|---|
| 1067 |
|
|---|
| 1068 | // Return 1 if 'left' comes after 'right', 0 if equal, and -1 otherwise.
|
|---|
| 1069 | // 'left' and 'right' cannot be null.
|
|---|
| 1070 | template <class T>
|
|---|
| 1071 | int QRBTree<T>::order(Node *left, Node *right)
|
|---|
| 1072 | {
|
|---|
| 1073 | Q_ASSERT(left && right);
|
|---|
| 1074 | if (left == right)
|
|---|
| 1075 | return 0;
|
|---|
| 1076 |
|
|---|
| 1077 | QVector<Node *> leftAncestors;
|
|---|
| 1078 | QVector<Node *> rightAncestors;
|
|---|
| 1079 | while (left) {
|
|---|
| 1080 | leftAncestors.push_back(left);
|
|---|
| 1081 | left = left->parent;
|
|---|
| 1082 | }
|
|---|
| 1083 | while (right) {
|
|---|
| 1084 | rightAncestors.push_back(right);
|
|---|
| 1085 | right = right->parent;
|
|---|
| 1086 | }
|
|---|
| 1087 | Q_ASSERT(leftAncestors.back() == root && rightAncestors.back() == root);
|
|---|
| 1088 |
|
|---|
| 1089 | while (!leftAncestors.empty() && !rightAncestors.empty() && leftAncestors.back() == rightAncestors.back()) {
|
|---|
| 1090 | leftAncestors.pop_back();
|
|---|
| 1091 | rightAncestors.pop_back();
|
|---|
| 1092 | }
|
|---|
| 1093 |
|
|---|
| 1094 | if (!leftAncestors.empty())
|
|---|
| 1095 | return (leftAncestors.back() == leftAncestors.back()->parent->left ? -1 : 1);
|
|---|
| 1096 |
|
|---|
| 1097 | if (!rightAncestors.empty())
|
|---|
| 1098 | return (rightAncestors.back() == rightAncestors.back()->parent->right ? -1 : 1);
|
|---|
| 1099 |
|
|---|
| 1100 | // The code should never reach this point.
|
|---|
| 1101 | Q_ASSERT(!leftAncestors.empty() || !rightAncestors.empty());
|
|---|
| 1102 | return 0;
|
|---|
| 1103 | }
|
|---|
| 1104 |
|
|---|
| 1105 | //============================================================================//
|
|---|
| 1106 | // QInt64Hash //
|
|---|
| 1107 | //============================================================================//
|
|---|
| 1108 |
|
|---|
| 1109 | // Copied from qhash.cpp
|
|---|
| 1110 | static const uchar prime_deltas[] = {
|
|---|
| 1111 | 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
|
|---|
| 1112 | 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
|
|---|
| 1113 | };
|
|---|
| 1114 |
|
|---|
| 1115 | // Copied from qhash.cpp
|
|---|
| 1116 | static inline int primeForNumBits(int numBits)
|
|---|
| 1117 | {
|
|---|
| 1118 | return (1 << numBits) + prime_deltas[numBits];
|
|---|
| 1119 | }
|
|---|
| 1120 |
|
|---|
| 1121 | static inline int primeForCount(int count)
|
|---|
| 1122 | {
|
|---|
| 1123 | int low = 0;
|
|---|
| 1124 | int high = 32;
|
|---|
| 1125 | for (int i = 0; i < 5; ++i) {
|
|---|
| 1126 | int mid = (high + low) / 2;
|
|---|
| 1127 | if (count >= 1 << mid)
|
|---|
| 1128 | low = mid;
|
|---|
| 1129 | else
|
|---|
| 1130 | high = mid;
|
|---|
| 1131 | }
|
|---|
| 1132 | return primeForNumBits(high);
|
|---|
| 1133 | }
|
|---|
| 1134 |
|
|---|
| 1135 | // Hash set of quint64s. Elements cannot be removed without clearing the
|
|---|
| 1136 | // entire set. A value of -1 is used to mark unused entries.
|
|---|
| 1137 | class QInt64Set
|
|---|
| 1138 | {
|
|---|
| 1139 | public:
|
|---|
| 1140 | inline QInt64Set(int capacity = 64);
|
|---|
| 1141 | inline ~QInt64Set() {if (m_array) delete[] m_array;}
|
|---|
| 1142 | inline bool isValid() const {return m_array;}
|
|---|
| 1143 | void insert(quint64 key);
|
|---|
| 1144 | bool contains(quint64 key) const;
|
|---|
| 1145 | inline void clear();
|
|---|
| 1146 | private:
|
|---|
| 1147 | bool rehash(int capacity);
|
|---|
| 1148 |
|
|---|
| 1149 | static const quint64 UNUSED;
|
|---|
| 1150 |
|
|---|
| 1151 | quint64 *m_array;
|
|---|
| 1152 | int m_capacity;
|
|---|
| 1153 | int m_count;
|
|---|
| 1154 | };
|
|---|
| 1155 |
|
|---|
| 1156 | const quint64 QInt64Set::UNUSED = quint64(-1);
|
|---|
| 1157 |
|
|---|
| 1158 | inline QInt64Set::QInt64Set(int capacity)
|
|---|
| 1159 | {
|
|---|
| 1160 | m_capacity = primeForCount(capacity);
|
|---|
| 1161 | m_array = new quint64[m_capacity];
|
|---|
| 1162 | if (m_array)
|
|---|
| 1163 | clear();
|
|---|
| 1164 | else
|
|---|
| 1165 | m_capacity = 0;
|
|---|
| 1166 | }
|
|---|
| 1167 |
|
|---|
| 1168 | bool QInt64Set::rehash(int capacity)
|
|---|
| 1169 | {
|
|---|
| 1170 | quint64 *oldArray = m_array;
|
|---|
| 1171 | int oldCapacity = m_capacity;
|
|---|
| 1172 |
|
|---|
| 1173 | m_capacity = capacity;
|
|---|
| 1174 | m_array = new quint64[m_capacity];
|
|---|
| 1175 | if (m_array) {
|
|---|
| 1176 | clear();
|
|---|
| 1177 | if (oldArray) {
|
|---|
| 1178 | for (int i = 0; i < oldCapacity; ++i) {
|
|---|
| 1179 | if (oldArray[i] != UNUSED)
|
|---|
| 1180 | insert(oldArray[i]);
|
|---|
| 1181 | }
|
|---|
| 1182 | delete[] oldArray;
|
|---|
| 1183 | }
|
|---|
| 1184 | return true;
|
|---|
| 1185 | } else {
|
|---|
| 1186 | m_capacity = oldCapacity;
|
|---|
| 1187 | m_array = oldArray;
|
|---|
| 1188 | return false;
|
|---|
| 1189 | }
|
|---|
| 1190 | }
|
|---|
| 1191 |
|
|---|
| 1192 | void QInt64Set::insert(quint64 key)
|
|---|
| 1193 | {
|
|---|
| 1194 | if (m_count > 3 * m_capacity / 4)
|
|---|
| 1195 | rehash(primeForCount(2 * m_capacity));
|
|---|
| 1196 | Q_ASSERT_X(m_array, "QInt64Hash<T>::insert", "Hash set not allocated.");
|
|---|
| 1197 | int index = int(key % m_capacity);
|
|---|
| 1198 | for (int i = 0; i < m_capacity; ++i) {
|
|---|
| 1199 | index += i;
|
|---|
| 1200 | if (index >= m_capacity)
|
|---|
| 1201 | index -= m_capacity;
|
|---|
| 1202 | if (m_array[index] == key)
|
|---|
| 1203 | return;
|
|---|
| 1204 | if (m_array[index] == UNUSED) {
|
|---|
| 1205 | ++m_count;
|
|---|
| 1206 | m_array[index] = key;
|
|---|
| 1207 | return;
|
|---|
| 1208 | }
|
|---|
| 1209 | }
|
|---|
| 1210 | Q_ASSERT_X(0, "QInt64Hash<T>::insert", "Hash set full.");
|
|---|
| 1211 | }
|
|---|
| 1212 |
|
|---|
| 1213 | bool QInt64Set::contains(quint64 key) const
|
|---|
| 1214 | {
|
|---|
| 1215 | Q_ASSERT_X(m_array, "QInt64Hash<T>::contains", "Hash set not allocated.");
|
|---|
| 1216 | int index = int(key % m_capacity);
|
|---|
| 1217 | for (int i = 0; i < m_capacity; ++i) {
|
|---|
| 1218 | index += i;
|
|---|
| 1219 | if (index >= m_capacity)
|
|---|
| 1220 | index -= m_capacity;
|
|---|
| 1221 | if (m_array[index] == key)
|
|---|
| 1222 | return true;
|
|---|
| 1223 | if (m_array[index] == UNUSED)
|
|---|
| 1224 | return false;
|
|---|
| 1225 | }
|
|---|
| 1226 | return false;
|
|---|
| 1227 | }
|
|---|
| 1228 |
|
|---|
| 1229 | inline void QInt64Set::clear()
|
|---|
| 1230 | {
|
|---|
| 1231 | Q_ASSERT_X(m_array, "QInt64Hash<T>::clear", "Hash set not allocated.");
|
|---|
| 1232 | for (int i = 0; i < m_capacity; ++i)
|
|---|
| 1233 | m_array[i] = UNUSED;
|
|---|
| 1234 | m_count = 0;
|
|---|
| 1235 | }
|
|---|
| 1236 |
|
|---|
| 1237 | //============================================================================//
|
|---|
| 1238 | // QRingBuffer //
|
|---|
| 1239 | //============================================================================//
|
|---|
| 1240 |
|
|---|
| 1241 | // T must be POD.
|
|---|
| 1242 | template <class T>
|
|---|
| 1243 | class QRingBuffer
|
|---|
| 1244 | {
|
|---|
| 1245 | public:
|
|---|
| 1246 | inline QRingBuffer() : m_array(0), m_head(0), m_size(0), m_capacity(0) { }
|
|---|
| 1247 | inline ~QRingBuffer() {if (m_array) delete[] m_array;}
|
|---|
| 1248 | bool reallocate(int capacity);
|
|---|
| 1249 | inline const T &head() const {Q_ASSERT(m_size > 0); return m_array[m_head];}
|
|---|
| 1250 | inline const T &dequeue();
|
|---|
| 1251 | inline void enqueue(const T &x);
|
|---|
| 1252 | inline bool isEmpty() const {return m_size == 0;}
|
|---|
| 1253 | private:
|
|---|
| 1254 | T *m_array;
|
|---|
| 1255 | int m_head;
|
|---|
| 1256 | int m_size;
|
|---|
| 1257 | int m_capacity;
|
|---|
| 1258 | };
|
|---|
| 1259 |
|
|---|
| 1260 | template <class T>
|
|---|
| 1261 | bool QRingBuffer<T>::reallocate(int capacity)
|
|---|
| 1262 | {
|
|---|
| 1263 | T *oldArray = m_array;
|
|---|
| 1264 | m_array = new T[capacity];
|
|---|
| 1265 | if (m_array) {
|
|---|
| 1266 | if (oldArray) {
|
|---|
| 1267 | if (m_head + m_size > m_capacity) {
|
|---|
| 1268 | memcpy(m_array, oldArray + m_head, (m_capacity - m_head) * sizeof(T));
|
|---|
| 1269 | memcpy(m_array + (m_capacity - m_head), oldArray, (m_head + m_size - m_capacity) * sizeof(T));
|
|---|
| 1270 | } else {
|
|---|
| 1271 | memcpy(m_array, oldArray + m_head, m_size * sizeof(T));
|
|---|
| 1272 | }
|
|---|
| 1273 | delete[] oldArray;
|
|---|
| 1274 | }
|
|---|
| 1275 | m_capacity = capacity;
|
|---|
| 1276 | m_head = 0;
|
|---|
| 1277 | return true;
|
|---|
| 1278 | } else {
|
|---|
| 1279 | m_array = oldArray;
|
|---|
| 1280 | return false;
|
|---|
| 1281 | }
|
|---|
| 1282 | }
|
|---|
| 1283 |
|
|---|
| 1284 | template <class T>
|
|---|
| 1285 | inline const T &QRingBuffer<T>::dequeue()
|
|---|
| 1286 | {
|
|---|
| 1287 | Q_ASSERT(m_size > 0);
|
|---|
| 1288 | Q_ASSERT(m_array);
|
|---|
| 1289 | Q_ASSERT(m_capacity >= m_size);
|
|---|
| 1290 | int index = m_head;
|
|---|
| 1291 | if (++m_head >= m_capacity)
|
|---|
| 1292 | m_head -= m_capacity;
|
|---|
| 1293 | --m_size;
|
|---|
| 1294 | return m_array[index];
|
|---|
| 1295 | }
|
|---|
| 1296 |
|
|---|
| 1297 | template <class T>
|
|---|
| 1298 | inline void QRingBuffer<T>::enqueue(const T &x)
|
|---|
| 1299 | {
|
|---|
| 1300 | if (m_size == m_capacity)
|
|---|
| 1301 | reallocate(qMax(2 * m_capacity, 64));
|
|---|
| 1302 | int index = m_head + m_size;
|
|---|
| 1303 | if (index >= m_capacity)
|
|---|
| 1304 | index -= m_capacity;
|
|---|
| 1305 | m_array[index] = x;
|
|---|
| 1306 | ++m_size;
|
|---|
| 1307 | }
|
|---|
| 1308 |
|
|---|
| 1309 | //============================================================================//
|
|---|
| 1310 | // QTriangulator //
|
|---|
| 1311 | //============================================================================//
|
|---|
| 1312 | template<typename T>
|
|---|
| 1313 | class QTriangulator
|
|---|
| 1314 | {
|
|---|
| 1315 | public:
|
|---|
| 1316 | typedef QVarLengthArray<int, 6> ShortArray;
|
|---|
| 1317 |
|
|---|
| 1318 | //================================//
|
|---|
| 1319 | // QTriangulator::ComplexToSimple //
|
|---|
| 1320 | //================================//
|
|---|
| 1321 | friend class ComplexToSimple;
|
|---|
| 1322 | class ComplexToSimple
|
|---|
| 1323 | {
|
|---|
| 1324 | public:
|
|---|
| 1325 | inline ComplexToSimple(QTriangulator<T> *parent) : m_parent(parent),
|
|---|
| 1326 | m_edges(0), m_events(0), m_splits(0) { }
|
|---|
| 1327 | void decompose();
|
|---|
| 1328 | private:
|
|---|
| 1329 | struct Edge
|
|---|
| 1330 | {
|
|---|
| 1331 | inline int &upper() {return pointingUp ? to : from;}
|
|---|
| 1332 | inline int &lower() {return pointingUp ? from : to;}
|
|---|
| 1333 | inline int upper() const {return pointingUp ? to : from;}
|
|---|
| 1334 | inline int lower() const {return pointingUp ? from : to;}
|
|---|
| 1335 |
|
|---|
| 1336 | QRBTree<int>::Node *node;
|
|---|
| 1337 | int from, to; // vertex
|
|---|
| 1338 | int next, previous; // edge
|
|---|
| 1339 | int winding;
|
|---|
| 1340 | bool mayIntersect;
|
|---|
| 1341 | bool pointingUp, originallyPointingUp;
|
|---|
| 1342 | };
|
|---|
| 1343 |
|
|---|
| 1344 | friend class CompareEdges;
|
|---|
| 1345 | class CompareEdges
|
|---|
| 1346 | {
|
|---|
| 1347 | public:
|
|---|
| 1348 | inline CompareEdges(ComplexToSimple *parent) : m_parent(parent) { }
|
|---|
| 1349 | bool operator () (int i, int j) const;
|
|---|
| 1350 | private:
|
|---|
| 1351 | ComplexToSimple *m_parent;
|
|---|
| 1352 | };
|
|---|
| 1353 |
|
|---|
| 1354 | struct Intersection
|
|---|
| 1355 | {
|
|---|
| 1356 | bool operator < (const Intersection &other) const {return other.intersectionPoint < intersectionPoint;}
|
|---|
| 1357 |
|
|---|
| 1358 | QIntersectionPoint intersectionPoint;
|
|---|
| 1359 | int vertex;
|
|---|
| 1360 | int leftEdge;
|
|---|
| 1361 | int rightEdge;
|
|---|
| 1362 | };
|
|---|
| 1363 |
|
|---|
| 1364 | struct Split
|
|---|
| 1365 | {
|
|---|
| 1366 | int vertex;
|
|---|
| 1367 | int edge;
|
|---|
| 1368 | bool accurate;
|
|---|
| 1369 | };
|
|---|
| 1370 |
|
|---|
| 1371 | struct Event
|
|---|
| 1372 | {
|
|---|
| 1373 | enum Type {Upper, Lower};
|
|---|
| 1374 | inline bool operator < (const Event &other) const;
|
|---|
| 1375 |
|
|---|
| 1376 | QPodPoint point;
|
|---|
| 1377 | Type type;
|
|---|
| 1378 | int edge;
|
|---|
| 1379 | };
|
|---|
| 1380 |
|
|---|
| 1381 | #ifdef Q_TRIANGULATOR_DEBUG
|
|---|
| 1382 | friend class DebugDialog;
|
|---|
| 1383 | friend class QTriangulator;
|
|---|
| 1384 | class DebugDialog : public QDialog
|
|---|
| 1385 | {
|
|---|
| 1386 | public:
|
|---|
| 1387 | DebugDialog(ComplexToSimple *parent, int currentVertex);
|
|---|
| 1388 | protected:
|
|---|
| 1389 | void paintEvent(QPaintEvent *);
|
|---|
| 1390 | void wheelEvent(QWheelEvent *);
|
|---|
| 1391 | void mouseMoveEvent(QMouseEvent *);
|
|---|
| 1392 | void mousePressEvent(QMouseEvent *);
|
|---|
| 1393 | private:
|
|---|
| 1394 | ComplexToSimple *m_parent;
|
|---|
| 1395 | QRectF m_window;
|
|---|
| 1396 | QPoint m_lastMousePos;
|
|---|
| 1397 | int m_vertex;
|
|---|
| 1398 | };
|
|---|
| 1399 | #endif
|
|---|
| 1400 |
|
|---|
| 1401 | void initEdges();
|
|---|
| 1402 | bool calculateIntersection(int left, int right);
|
|---|
| 1403 | bool edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const;
|
|---|
| 1404 | QRBTree<int>::Node *searchEdgeLeftOf(int edgeIndex) const;
|
|---|
| 1405 | QRBTree<int>::Node *searchEdgeLeftOf(int edgeIndex, QRBTree<int>::Node *after) const;
|
|---|
| 1406 | QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> bounds(const QPodPoint &point) const;
|
|---|
| 1407 | QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> outerBounds(const QPodPoint &point) const;
|
|---|
| 1408 | void splitEdgeListRange(QRBTree<int>::Node *leftmost, QRBTree<int>::Node *rightmost, int vertex, const QIntersectionPoint &intersectionPoint);
|
|---|
| 1409 | void reorderEdgeListRange(QRBTree<int>::Node *leftmost, QRBTree<int>::Node *rightmost);
|
|---|
| 1410 | void sortEdgeList(const QPodPoint eventPoint);
|
|---|
| 1411 | void fillPriorityQueue();
|
|---|
| 1412 | void calculateIntersections();
|
|---|
| 1413 | int splitEdge(int splitIndex);
|
|---|
| 1414 | bool splitEdgesAtIntersections();
|
|---|
| 1415 | void insertEdgeIntoVectorIfWanted(ShortArray &orderedEdges, int i);
|
|---|
| 1416 | void removeUnwantedEdgesAndConnect();
|
|---|
| 1417 | void removeUnusedPoints();
|
|---|
| 1418 |
|
|---|
| 1419 | QTriangulator *m_parent;
|
|---|
| 1420 | QDataBuffer<Edge> m_edges;
|
|---|
| 1421 | QRBTree<int> m_edgeList;
|
|---|
| 1422 | QDataBuffer<Event> m_events;
|
|---|
| 1423 | QDataBuffer<Split> m_splits;
|
|---|
| 1424 | QMaxHeap<Intersection> m_topIntersection;
|
|---|
| 1425 | QInt64Set m_processedEdgePairs;
|
|---|
| 1426 | int m_initialPointCount;
|
|---|
| 1427 | };
|
|---|
| 1428 | #ifdef Q_TRIANGULATOR_DEBUG
|
|---|
| 1429 | friend class ComplexToSimple::DebugDialog;
|
|---|
| 1430 | #endif
|
|---|
| 1431 |
|
|---|
| 1432 | //=================================//
|
|---|
| 1433 | // QTriangulator::SimpleToMonotone //
|
|---|
| 1434 | //=================================//
|
|---|
| 1435 | friend class SimpleToMonotone;
|
|---|
| 1436 | class SimpleToMonotone
|
|---|
| 1437 | {
|
|---|
| 1438 | public:
|
|---|
| 1439 | inline SimpleToMonotone(QTriangulator<T> *parent) : m_parent(parent), m_edges(0), m_upperVertex(0) { }
|
|---|
| 1440 | void decompose();
|
|---|
| 1441 | private:
|
|---|
| 1442 | enum VertexType {MergeVertex, EndVertex, RegularVertex, StartVertex, SplitVertex};
|
|---|
| 1443 |
|
|---|
| 1444 | struct Edge
|
|---|
| 1445 | {
|
|---|
| 1446 | QRBTree<int>::Node *node;
|
|---|
| 1447 | int helper, twin, next, previous;
|
|---|
| 1448 | T from, to;
|
|---|
| 1449 | VertexType type;
|
|---|
| 1450 | bool pointingUp;
|
|---|
| 1451 | int upper() const {return (pointingUp ? to : from);}
|
|---|
| 1452 | int lower() const {return (pointingUp ? from : to);}
|
|---|
| 1453 | };
|
|---|
| 1454 |
|
|---|
| 1455 | friend class CompareVertices;
|
|---|
| 1456 | class CompareVertices
|
|---|
| 1457 | {
|
|---|
| 1458 | public:
|
|---|
| 1459 | CompareVertices(SimpleToMonotone *parent) : m_parent(parent) { }
|
|---|
| 1460 | bool operator () (int i, int j) const;
|
|---|
| 1461 | private:
|
|---|
| 1462 | SimpleToMonotone *m_parent;
|
|---|
| 1463 | };
|
|---|
| 1464 |
|
|---|
| 1465 | void setupDataStructures();
|
|---|
| 1466 | void removeZeroLengthEdges();
|
|---|
| 1467 | void fillPriorityQueue();
|
|---|
| 1468 | bool edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const;
|
|---|
| 1469 | // Returns the rightmost edge not to the right of the given edge.
|
|---|
| 1470 | QRBTree<int>::Node *searchEdgeLeftOfEdge(int edgeIndex) const;
|
|---|
| 1471 | // Returns the rightmost edge left of the given point.
|
|---|
| 1472 | QRBTree<int>::Node *searchEdgeLeftOfPoint(int pointIndex) const;
|
|---|
| 1473 | void classifyVertex(int i);
|
|---|
| 1474 | void classifyVertices();
|
|---|
| 1475 | bool pointIsInSector(const QPodPoint &p, const QPodPoint &v1, const QPodPoint &v2, const QPodPoint &v3);
|
|---|
| 1476 | bool pointIsInSector(int vertex, int sector);
|
|---|
| 1477 | int findSector(int edge, int vertex);
|
|---|
| 1478 | void createDiagonal(int lower, int upper);
|
|---|
| 1479 | void monotoneDecomposition();
|
|---|
| 1480 |
|
|---|
| 1481 | QTriangulator *m_parent;
|
|---|
| 1482 | QRBTree<int> m_edgeList;
|
|---|
| 1483 | QDataBuffer<Edge> m_edges;
|
|---|
| 1484 | QDataBuffer<int> m_upperVertex;
|
|---|
| 1485 | bool m_clockwiseOrder;
|
|---|
| 1486 | };
|
|---|
| 1487 |
|
|---|
| 1488 | //====================================//
|
|---|
| 1489 | // QTriangulator::MonotoneToTriangles //
|
|---|
| 1490 | //====================================//
|
|---|
| 1491 | friend class MonotoneToTriangles;
|
|---|
| 1492 | class MonotoneToTriangles
|
|---|
| 1493 | {
|
|---|
| 1494 | public:
|
|---|
| 1495 | inline MonotoneToTriangles(QTriangulator<T> *parent) : m_parent(parent) { }
|
|---|
| 1496 | void decompose();
|
|---|
| 1497 | private:
|
|---|
| 1498 | inline T indices(int index) const {return m_parent->m_indices.at(index + m_first);}
|
|---|
| 1499 | inline int next(int index) const {return (index + 1) % m_length;}
|
|---|
| 1500 | inline int previous(int index) const {return (index + m_length - 1) % m_length;}
|
|---|
| 1501 | inline bool less(int i, int j) const {return m_parent->m_vertices.at((qint32)indices(i)) < m_parent->m_vertices.at(indices(j));}
|
|---|
| 1502 | inline bool leftOfEdge(int i, int j, int k) const
|
|---|
| 1503 | {
|
|---|
| 1504 | return qPointIsLeftOfLine(m_parent->m_vertices.at((qint32)indices(i)),
|
|---|
| 1505 | m_parent->m_vertices.at((qint32)indices(j)), m_parent->m_vertices.at((qint32)indices(k)));
|
|---|
| 1506 | }
|
|---|
| 1507 |
|
|---|
| 1508 | QTriangulator<T> *m_parent;
|
|---|
| 1509 | int m_first;
|
|---|
| 1510 | int m_length;
|
|---|
| 1511 | };
|
|---|
| 1512 |
|
|---|
| 1513 | inline QTriangulator() : m_vertices(0) { }
|
|---|
| 1514 |
|
|---|
| 1515 | // Call this only once.
|
|---|
| 1516 | void initialize(const qreal *polygon, int count, uint hint, const QTransform &matrix);
|
|---|
| 1517 | // Call this only once.
|
|---|
| 1518 | void initialize(const QVectorPath &path, const QTransform &matrix, qreal lod);
|
|---|
| 1519 | // Call this only once.
|
|---|
| 1520 | void initialize(const QPainterPath &path, const QTransform &matrix, qreal lod);
|
|---|
| 1521 | // Call either triangulate() or polyline() only once.
|
|---|
| 1522 | QVertexSet<T> triangulate();
|
|---|
| 1523 | QVertexSet<T> polyline();
|
|---|
| 1524 | private:
|
|---|
| 1525 | QDataBuffer<QPodPoint> m_vertices;
|
|---|
| 1526 | QVector<T> m_indices;
|
|---|
| 1527 | uint m_hint;
|
|---|
| 1528 | };
|
|---|
| 1529 |
|
|---|
| 1530 | //============================================================================//
|
|---|
| 1531 | // QTriangulator //
|
|---|
| 1532 | //============================================================================//
|
|---|
| 1533 |
|
|---|
| 1534 | template <typename T>
|
|---|
| 1535 | QVertexSet<T> QTriangulator<T>::triangulate()
|
|---|
| 1536 | {
|
|---|
| 1537 | for (int i = 0; i < m_vertices.size(); ++i) {
|
|---|
| 1538 | Q_ASSERT(qAbs(m_vertices.at(i).x) < (1 << 21));
|
|---|
| 1539 | Q_ASSERT(qAbs(m_vertices.at(i).y) < (1 << 21));
|
|---|
| 1540 | }
|
|---|
| 1541 |
|
|---|
| 1542 | if (!(m_hint & (QVectorPath::OddEvenFill | QVectorPath::WindingFill)))
|
|---|
| 1543 | m_hint |= QVectorPath::OddEvenFill;
|
|---|
| 1544 |
|
|---|
| 1545 | if (m_hint & QVectorPath::NonConvexShapeMask) {
|
|---|
| 1546 | ComplexToSimple c2s(this);
|
|---|
| 1547 | c2s.decompose();
|
|---|
| 1548 | SimpleToMonotone s2m(this);
|
|---|
| 1549 | s2m.decompose();
|
|---|
| 1550 | }
|
|---|
| 1551 | MonotoneToTriangles m2t(this);
|
|---|
| 1552 | m2t.decompose();
|
|---|
| 1553 |
|
|---|
| 1554 | QVertexSet<T> result;
|
|---|
| 1555 | result.indices = m_indices;
|
|---|
| 1556 | result.vertices.resize(2 * m_vertices.size());
|
|---|
| 1557 | for (int i = 0; i < m_vertices.size(); ++i) {
|
|---|
| 1558 | result.vertices[2 * i + 0] = qreal(m_vertices.at(i).x) / Q_FIXED_POINT_SCALE;
|
|---|
| 1559 | result.vertices[2 * i + 1] = qreal(m_vertices.at(i).y) / Q_FIXED_POINT_SCALE;
|
|---|
| 1560 | }
|
|---|
| 1561 | return result;
|
|---|
| 1562 | }
|
|---|
| 1563 |
|
|---|
| 1564 | template <typename T>
|
|---|
| 1565 | QVertexSet<T> QTriangulator<T>::polyline()
|
|---|
| 1566 | {
|
|---|
| 1567 | QVertexSet<T> result;
|
|---|
| 1568 | result.indices = m_indices;
|
|---|
| 1569 | result.vertices.resize(2 * m_vertices.size());
|
|---|
| 1570 | for (int i = 0; i < m_vertices.size(); ++i) {
|
|---|
| 1571 | result.vertices[2 * i + 0] = qreal(m_vertices.at(i).x) / Q_FIXED_POINT_SCALE;
|
|---|
| 1572 | result.vertices[2 * i + 1] = qreal(m_vertices.at(i).y) / Q_FIXED_POINT_SCALE;
|
|---|
| 1573 | }
|
|---|
| 1574 | return result;
|
|---|
| 1575 | }
|
|---|
| 1576 |
|
|---|
| 1577 | template <typename T>
|
|---|
| 1578 | void QTriangulator<T>::initialize(const qreal *polygon, int count, uint hint, const QTransform &matrix)
|
|---|
| 1579 | {
|
|---|
| 1580 | m_hint = hint;
|
|---|
| 1581 | m_vertices.resize(count);
|
|---|
| 1582 | m_indices.resize(count + 1);
|
|---|
| 1583 | for (int i = 0; i < count; ++i) {
|
|---|
| 1584 | qreal x, y;
|
|---|
| 1585 | matrix.map(polygon[2 * i + 0], polygon[2 * i + 1], &x, &y);
|
|---|
| 1586 | m_vertices.at(i).x = qRound(x * Q_FIXED_POINT_SCALE);
|
|---|
| 1587 | m_vertices.at(i).y = qRound(y * Q_FIXED_POINT_SCALE);
|
|---|
| 1588 | m_indices[i] = i;
|
|---|
| 1589 | }
|
|---|
| 1590 | m_indices[count] = T(-1); //Q_TRIANGULATE_END_OF_POLYGON
|
|---|
| 1591 | }
|
|---|
| 1592 |
|
|---|
| 1593 | template <typename T>
|
|---|
| 1594 | void QTriangulator<T>::initialize(const QVectorPath &path, const QTransform &matrix, qreal lod)
|
|---|
| 1595 | {
|
|---|
| 1596 | m_hint = path.hints();
|
|---|
| 1597 | // Curved paths will be converted to complex polygons.
|
|---|
| 1598 | m_hint &= ~QVectorPath::CurvedShapeMask;
|
|---|
| 1599 |
|
|---|
| 1600 | const qreal *p = path.points();
|
|---|
| 1601 | const QPainterPath::ElementType *e = path.elements();
|
|---|
| 1602 | if (e) {
|
|---|
| 1603 | for (int i = 0; i < path.elementCount(); ++i, ++e, p += 2) {
|
|---|
| 1604 | switch (*e) {
|
|---|
| 1605 | case QPainterPath::MoveToElement:
|
|---|
| 1606 | if (!m_indices.isEmpty())
|
|---|
| 1607 | m_indices.push_back(T(-1)); // Q_TRIANGULATE_END_OF_POLYGON
|
|---|
| 1608 | // Fall through.
|
|---|
| 1609 | case QPainterPath::LineToElement:
|
|---|
| 1610 | m_indices.push_back(T(m_vertices.size()));
|
|---|
| 1611 | m_vertices.resize(m_vertices.size() + 1);
|
|---|
| 1612 | qreal x, y;
|
|---|
| 1613 | matrix.map(p[0], p[1], &x, &y);
|
|---|
| 1614 | m_vertices.last().x = qRound(x * Q_FIXED_POINT_SCALE);
|
|---|
| 1615 | m_vertices.last().y = qRound(y * Q_FIXED_POINT_SCALE);
|
|---|
| 1616 | break;
|
|---|
| 1617 | case QPainterPath::CurveToElement:
|
|---|
| 1618 | {
|
|---|
| 1619 | qreal pts[8];
|
|---|
| 1620 | for (int i = 0; i < 4; ++i)
|
|---|
| 1621 | matrix.map(p[2 * i - 2], p[2 * i - 1], &pts[2 * i + 0], &pts[2 * i + 1]);
|
|---|
| 1622 | for (int i = 0; i < 8; ++i)
|
|---|
| 1623 | pts[i] *= lod;
|
|---|
| 1624 | QBezier bezier = QBezier::fromPoints(QPointF(pts[0], pts[1]), QPointF(pts[2], pts[3]), QPointF(pts[4], pts[5]), QPointF(pts[6], pts[7]));
|
|---|
| 1625 | QPolygonF poly = bezier.toPolygon();
|
|---|
| 1626 | // Skip first point, it already exists in 'm_vertices'.
|
|---|
| 1627 | for (int j = 1; j < poly.size(); ++j) {
|
|---|
| 1628 | m_indices.push_back(T(m_vertices.size()));
|
|---|
| 1629 | m_vertices.resize(m_vertices.size() + 1);
|
|---|
| 1630 | m_vertices.last().x = qRound(poly.at(j).x() * Q_FIXED_POINT_SCALE / lod);
|
|---|
| 1631 | m_vertices.last().y = qRound(poly.at(j).y() * Q_FIXED_POINT_SCALE / lod);
|
|---|
| 1632 | }
|
|---|
| 1633 | }
|
|---|
| 1634 | i += 2;
|
|---|
| 1635 | e += 2;
|
|---|
| 1636 | p += 4;
|
|---|
| 1637 | break;
|
|---|
| 1638 | default:
|
|---|
| 1639 | Q_ASSERT_X(0, "QTriangulator::triangulate", "Unexpected element type.");
|
|---|
| 1640 | break;
|
|---|
| 1641 | }
|
|---|
| 1642 | }
|
|---|
| 1643 | } else {
|
|---|
| 1644 | for (int i = 0; i < path.elementCount(); ++i, p += 2) {
|
|---|
| 1645 | m_indices.push_back(T(m_vertices.size()));
|
|---|
| 1646 | m_vertices.resize(m_vertices.size() + 1);
|
|---|
| 1647 | qreal x, y;
|
|---|
| 1648 | matrix.map(p[0], p[1], &x, &y);
|
|---|
| 1649 | m_vertices.last().x = qRound(x * Q_FIXED_POINT_SCALE);
|
|---|
| 1650 | m_vertices.last().y = qRound(y * Q_FIXED_POINT_SCALE);
|
|---|
| 1651 | }
|
|---|
| 1652 | }
|
|---|
| 1653 | m_indices.push_back(T(-1)); // Q_TRIANGULATE_END_OF_POLYGON
|
|---|
| 1654 | }
|
|---|
| 1655 |
|
|---|
| 1656 | template <typename T>
|
|---|
| 1657 | void QTriangulator<T>::initialize(const QPainterPath &path, const QTransform &matrix, qreal lod)
|
|---|
| 1658 | {
|
|---|
| 1659 | initialize(qtVectorPathForPath(path), matrix, lod);
|
|---|
| 1660 | }
|
|---|
| 1661 |
|
|---|
| 1662 | //============================================================================//
|
|---|
| 1663 | // QTriangulator::ComplexToSimple //
|
|---|
| 1664 | //============================================================================//
|
|---|
| 1665 | template <typename T>
|
|---|
| 1666 | void QTriangulator<T>::ComplexToSimple::decompose()
|
|---|
| 1667 | {
|
|---|
| 1668 | m_initialPointCount = m_parent->m_vertices.size();
|
|---|
| 1669 | initEdges();
|
|---|
| 1670 | do {
|
|---|
| 1671 | calculateIntersections();
|
|---|
| 1672 | } while (splitEdgesAtIntersections());
|
|---|
| 1673 |
|
|---|
| 1674 | removeUnwantedEdgesAndConnect();
|
|---|
| 1675 | removeUnusedPoints();
|
|---|
| 1676 |
|
|---|
| 1677 | m_parent->m_indices.clear();
|
|---|
| 1678 | QBitArray processed(m_edges.size(), false);
|
|---|
| 1679 | for (int first = 0; first < m_edges.size(); ++first) {
|
|---|
| 1680 | // If already processed, or if unused path, skip.
|
|---|
| 1681 | if (processed.at(first) || m_edges.at(first).next == -1)
|
|---|
| 1682 | continue;
|
|---|
| 1683 |
|
|---|
| 1684 | int i = first;
|
|---|
| 1685 | do {
|
|---|
| 1686 | Q_ASSERT(!processed.at(i));
|
|---|
| 1687 | Q_ASSERT(m_edges.at(m_edges.at(i).next).previous == i);
|
|---|
| 1688 | m_parent->m_indices.push_back(m_edges.at(i).from);
|
|---|
| 1689 | processed.setBit(i);
|
|---|
| 1690 | i = m_edges.at(i).next; // CCW order
|
|---|
| 1691 | } while (i != first);
|
|---|
| 1692 | m_parent->m_indices.push_back(T(-1)); // Q_TRIANGULATE_END_OF_POLYGON
|
|---|
| 1693 | }
|
|---|
| 1694 | }
|
|---|
| 1695 |
|
|---|
| 1696 | template <typename T>
|
|---|
| 1697 | void QTriangulator<T>::ComplexToSimple::initEdges()
|
|---|
| 1698 | {
|
|---|
| 1699 | // Initialize edge structure.
|
|---|
| 1700 | // 'next' and 'previous' are not being initialized at this point.
|
|---|
| 1701 | int first = 0;
|
|---|
| 1702 | for (int i = 0; i < m_parent->m_indices.size(); ++i) {
|
|---|
| 1703 | if (m_parent->m_indices.at(i) == T(-1)) { // Q_TRIANGULATE_END_OF_POLYGON
|
|---|
| 1704 | if (m_edges.size() != first)
|
|---|
| 1705 | m_edges.last().to = m_edges.at(first).from;
|
|---|
| 1706 | first = m_edges.size();
|
|---|
| 1707 | } else {
|
|---|
| 1708 | Q_ASSERT(i + 1 < m_parent->m_indices.size());
|
|---|
| 1709 | // {node, from, to, next, previous, winding, mayIntersect, pointingUp, originallyPointingUp}
|
|---|
| 1710 | Edge edge = {0, m_parent->m_indices.at(i), m_parent->m_indices.at(i + 1), -1, -1, 0, true, false, false};
|
|---|
| 1711 | m_edges.add(edge);
|
|---|
| 1712 | }
|
|---|
| 1713 | }
|
|---|
| 1714 | if (first != m_edges.size())
|
|---|
| 1715 | m_edges.last().to = m_edges.at(first).from;
|
|---|
| 1716 | for (int i = 0; i < m_edges.size(); ++i) {
|
|---|
| 1717 | m_edges.at(i).originallyPointingUp = m_edges.at(i).pointingUp =
|
|---|
| 1718 | m_parent->m_vertices.at(m_edges.at(i).to) < m_parent->m_vertices.at(m_edges.at(i).from);
|
|---|
| 1719 | }
|
|---|
| 1720 | }
|
|---|
| 1721 |
|
|---|
| 1722 | // Return true if new intersection was found
|
|---|
| 1723 | template <typename T>
|
|---|
| 1724 | bool QTriangulator<T>::ComplexToSimple::calculateIntersection(int left, int right)
|
|---|
| 1725 | {
|
|---|
| 1726 | const Edge &e1 = m_edges.at(left);
|
|---|
| 1727 | const Edge &e2 = m_edges.at(right);
|
|---|
| 1728 |
|
|---|
| 1729 | const QPodPoint &u1 = m_parent->m_vertices.at((qint32)e1.from);
|
|---|
| 1730 | const QPodPoint &u2 = m_parent->m_vertices.at((qint32)e1.to);
|
|---|
| 1731 | const QPodPoint &v1 = m_parent->m_vertices.at((qint32)e2.from);
|
|---|
| 1732 | const QPodPoint &v2 = m_parent->m_vertices.at((qint32)e2.to);
|
|---|
| 1733 | if (qMax(u1.x, u2.x) <= qMin(v1.x, v2.x))
|
|---|
| 1734 | return false;
|
|---|
| 1735 |
|
|---|
| 1736 | quint64 key = (left > right ? (quint64(right) << 32) | quint64(left) : (quint64(left) << 32) | quint64(right));
|
|---|
| 1737 | if (m_processedEdgePairs.contains(key))
|
|---|
| 1738 | return false;
|
|---|
| 1739 | m_processedEdgePairs.insert(key);
|
|---|
| 1740 |
|
|---|
| 1741 | Intersection intersection;
|
|---|
| 1742 | intersection.leftEdge = left;
|
|---|
| 1743 | intersection.rightEdge = right;
|
|---|
| 1744 | intersection.intersectionPoint = QT_PREPEND_NAMESPACE(qIntersectionPoint)(u1, u2, v1, v2);
|
|---|
| 1745 |
|
|---|
| 1746 | if (!intersection.intersectionPoint.isValid())
|
|---|
| 1747 | return false;
|
|---|
| 1748 |
|
|---|
| 1749 | Q_ASSERT(intersection.intersectionPoint.isOnLine(u1, u2));
|
|---|
| 1750 | Q_ASSERT(intersection.intersectionPoint.isOnLine(v1, v2));
|
|---|
| 1751 |
|
|---|
| 1752 | intersection.vertex = m_parent->m_vertices.size();
|
|---|
| 1753 | m_topIntersection.push(intersection);
|
|---|
| 1754 | m_parent->m_vertices.add(intersection.intersectionPoint.round());
|
|---|
| 1755 | return true;
|
|---|
| 1756 | }
|
|---|
| 1757 |
|
|---|
| 1758 | template <typename T>
|
|---|
| 1759 | bool QTriangulator<T>::ComplexToSimple::edgeIsLeftOfEdge(int leftEdgeIndex, int rightEdgeIndex) const
|
|---|
| 1760 | {
|
|---|
| 1761 | const Edge &leftEdge = m_edges.at(leftEdgeIndex);
|
|---|
| 1762 | const Edge &rightEdge = m_edges.at(rightEdgeIndex);
|
|---|
| 1763 | const QPodPoint &u = m_parent->m_vertices.at(rightEdge.upper());
|
|---|
| 1764 | const QPodPoint &l = m_parent->m_vertices.at(rightEdge.lower());
|
|---|
| 1765 | const QPodPoint &upper = m_parent->m_vertices.at(leftEdge.upper());
|
|---|
| 1766 | if (upper.x < qMin(l.x, u.x))
|
|---|
| 1767 | return true;
|
|---|
| 1768 | if (upper.x > qMax(l.x, u.x))
|
|---|
| 1769 | return false;
|
|---|
| 1770 | qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(upper, l, u);
|
|---|
| 1771 | // d < 0: left, d > 0: right, d == 0: on top
|
|---|
| 1772 | if (d == 0)
|
|---|
| 1773 | d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(m_parent->m_vertices.at(leftEdge.lower()), l, u);
|
|---|
| 1774 | return d < 0;
|
|---|
| 1775 | }
|
|---|
| 1776 |
|
|---|
| 1777 | template <typename T>
|
|---|
| 1778 | QRBTree<int>::Node *QTriangulator<T>::ComplexToSimple::searchEdgeLeftOf(int edgeIndex) const
|
|---|
| 1779 | {
|
|---|
| 1780 | QRBTree<int>::Node *current = m_edgeList.root;
|
|---|
| 1781 | QRBTree<int>::Node *result = 0;
|
|---|
| 1782 | while (current) {
|
|---|
| 1783 | if (edgeIsLeftOfEdge(edgeIndex, current->data)) {
|
|---|
| 1784 | current = current->left;
|
|---|
| 1785 | } else {
|
|---|
| 1786 | result = current;
|
|---|
| 1787 | current = current->right;
|
|---|
| 1788 | }
|
|---|
| 1789 | }
|
|---|
| 1790 | return result;
|
|---|
| 1791 | }
|
|---|
| 1792 |
|
|---|
| 1793 | template <typename T>
|
|---|
| 1794 | QRBTree<int>::Node *QTriangulator<T>::ComplexToSimple::searchEdgeLeftOf(int edgeIndex, QRBTree<int>::Node *after) const
|
|---|
| 1795 | {
|
|---|
| 1796 | if (!m_edgeList.root)
|
|---|
| 1797 | return after;
|
|---|
| 1798 | QRBTree<int>::Node *result = after;
|
|---|
| 1799 | QRBTree<int>::Node *current = (after ? m_edgeList.next(after) : m_edgeList.front(m_edgeList.root));
|
|---|
| 1800 | while (current) {
|
|---|
| 1801 | if (edgeIsLeftOfEdge(edgeIndex, current->data))
|
|---|
| 1802 | return result;
|
|---|
| 1803 | result = current;
|
|---|
| 1804 | current = m_edgeList.next(current);
|
|---|
| 1805 | }
|
|---|
| 1806 | return result;
|
|---|
| 1807 | }
|
|---|
| 1808 |
|
|---|
| 1809 | template <typename T>
|
|---|
| 1810 | QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> QTriangulator<T>::ComplexToSimple::bounds(const QPodPoint &point) const
|
|---|
| 1811 | {
|
|---|
| 1812 | QRBTree<int>::Node *current = m_edgeList.root;
|
|---|
| 1813 | QPair<QRBTree<int>::Node *, QRBTree<int>::Node *> result(0, 0);
|
|---|
| 1814 | while (current) {
|
|---|
| 1815 | const QPodPoint &v1 = m_parent->m_vertices.at(m_edges.at(current->data).lower());
|
|---|
| 1816 | const QPodPoint &v2 = m_parent->m_vertices.at(m_edges.at(current->data).upper());
|
|---|
| 1817 | qint64 d = QT_PREPEND_NAMESPACE(qPointDistanceFromLine)(point, v1, v2);
|
|---|
| 1818 | if (d == 0) {
|
|---|
| 1819 | result.first = result.second = current;
|
|---|
| 1820 | break;
|
|---|
| 1821 | }
|
|---|
| 1822 | current = (d < 0 ? current->left : current->right);
|
|---|
| 1823 | }
|
|---|
|
|---|