30 const double x2 = point2.
x() - point1.
x();
31 const double y2 = point2.
y() - point1.
y();
32 const double x3 = point3.
x() - point1.
x();
33 const double y3 = point3.
y() - point1.
y();
35 const double denom = x2 * y3 - y2 * x3;
41 frac = ( x2 * ( x2 - x3 ) + y2 * ( y2 - y3 ) ) / denom;
42 const double cx = ( x3 + frac * y3 ) / 2;
43 const double cy = ( y3 - frac * x3 ) / 2;
44 const double squaredRadius = ( cx * cx + cy * cy );
45 const QgsPoint center( cx + point1.
x(), cy + point1.
y() );
52 qDeleteAll( mPointVector );
53 qDeleteAll( mHalfEdge );
60 for (
int i = 0; i < mHalfEdge.count(); i++ )
62 const int a = mHalfEdge[mHalfEdge[i]->getDual()]->getDual();
63 const int b = mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getNext();
66 QgsDebugError( QStringLiteral(
"warning, first test failed" ) );
70 QgsDebugError( QStringLiteral(
"warning, second test failed" ) );
79 int currentpoint = -10;
86 if ( actpoint != -100 )
92 if ( actpoint == -100 )
97 for ( ; i < points.size(); ++i )
99 currentpoint =
addPoint( points.at( i ) );
100 if ( currentpoint != -100 && actpoint != -100 && currentpoint != actpoint )
102 insertForcedSegment( actpoint, currentpoint, lineType );
104 actpoint = currentpoint;
111 if ( mPointVector.isEmpty() )
120 mXMin = std::min( p.
x(), mXMin );
121 mXMax = std::max( p.
x(), mXMax );
122 mYMin = std::min( p.
y(), mYMin );
123 mYMax = std::max( p.
y(), mYMax );
127 mPointVector.append(
new QgsPoint( p ) );
130 if ( mDimension == -1 )
132 const unsigned int zedge = insertEdge( -10, -10, -1,
false,
false );
133 const unsigned int fedge = insertEdge(
static_cast<int>( zedge ),
static_cast<int>( zedge ), 0,
false,
false );
134 ( mHalfEdge.at( zedge ) )->setDual(
static_cast<int>( fedge ) );
135 ( mHalfEdge.at( zedge ) )->setNext(
static_cast<int>( fedge ) );
138 else if ( mDimension == 0 )
141 if ( p.
x() == mPointVector[0]->x() && p.
y() == mPointVector[0]->y() )
148 const unsigned int edgeFromPoint0ToPoint1 = insertEdge( -10, -10, 1,
false,
false );
149 const unsigned int edgeFromPoint1ToPoint0 = insertEdge( edgeFromPoint0ToPoint1, -10, 0,
false,
false );
150 const unsigned int edgeFromVirtualToPoint1Side1 = insertEdge( -10, -10, 1,
false,
false );
151 const unsigned int edgeFromPoint1ToVirtualSide1 = insertEdge( edgeFromVirtualToPoint1Side1, 1, -1,
false,
false );
152 const unsigned int edgeFromVirtualToPoint1Side2 = insertEdge( -10, edgeFromPoint1ToPoint0, 1,
false,
false );
153 const unsigned int edgeFromPoint1ToVirtualSide2 = insertEdge( edgeFromVirtualToPoint1Side2, edgeFromVirtualToPoint1Side1, -1,
false,
false );
154 const unsigned int edgeFromVirtualToPoint0Side2 = insertEdge( -10, -10, 0,
false,
false );
155 const unsigned int edgeFromPoint0ToVirtualSide2 = insertEdge( edgeFromVirtualToPoint0Side2, edgeFromVirtualToPoint1Side2, -1,
false,
false );
156 mHalfEdge.at( edgeFromPoint1ToPoint0 )->setNext( edgeFromPoint0ToVirtualSide2 );
157 mHalfEdge.at( edgeFromPoint0ToPoint1 )->setDual( edgeFromPoint1ToPoint0 );
158 mHalfEdge.at( edgeFromPoint0ToPoint1 )->setNext( edgeFromPoint1ToVirtualSide1 );
159 mHalfEdge.at( edgeFromVirtualToPoint1Side1 )->setDual( edgeFromPoint1ToVirtualSide1 );
160 mHalfEdge.at( edgeFromVirtualToPoint1Side1 )->setNext( edgeFromPoint1ToVirtualSide2 );
161 mHalfEdge.at( 0 )->setNext(
static_cast<int>( edgeFromVirtualToPoint0Side2 ) );
162 mHalfEdge.at( 1 )->setNext(
static_cast<int>( edgeFromPoint0ToPoint1 ) );
163 mHalfEdge.at( edgeFromVirtualToPoint1Side2 )->setDual( edgeFromPoint1ToVirtualSide2 );
164 mHalfEdge.at( edgeFromVirtualToPoint0Side2 )->setDual( edgeFromPoint0ToVirtualSide2 );
165 mHalfEdge.at( edgeFromVirtualToPoint0Side2 )->setNext( 0 );
167 mEdgeOutside = edgeFromPoint0ToPoint1;
170 else if ( mDimension == 1 )
172 if ( mEdgeOutside < 0 || mHalfEdge[mEdgeOutside]->getPoint() < 0 || mHalfEdge[mHalfEdge[mEdgeOutside]->getDual()]->getPoint() < 0 )
173 mEdgeOutside = firstEdgeOutSide();
174 if ( mEdgeOutside < 0 || mHalfEdge[mEdgeOutside]->getPoint() < 0 || mHalfEdge[mHalfEdge[mEdgeOutside]->getDual()]->getPoint() < 0 )
177 const double leftOfNumber =
MathUtils::leftOf( p, mPointVector[mHalfEdge[mHalfEdge[mEdgeOutside]->getDual()]->getPoint()], mPointVector[mHalfEdge[mEdgeOutside]->getPoint()] );
183 int closestEdge = -1;
184 double distance = std::numeric_limits<double>::max();
185 const int firstEdge = mEdgeOutside;
188 const int point1 = mHalfEdge[mEdgeOutside]->getPoint();
189 const int point2 = mHalfEdge[mHalfEdge[mEdgeOutside]->getDual()]->getPoint();
190 const double distance1 = p.
distance( *mPointVector[point1] );
196 const double distance2 = p.
distance( *mPointVector[point2] );
203 const double edgeLength = mPointVector[point1]->distance( *mPointVector[point2] );
205 if ( distance1 < edgeLength && distance2 < edgeLength )
208 const int newPoint = mPointVector.count() - 1;
211 const int edgeFromNewPointToPoint1 = mEdgeOutside;
212 const int edgeFromNewPointToPoint2 = mHalfEdge[mEdgeOutside]->getDual();
214 const int edgeFromPoint1ToVirtualSide2 = mHalfEdge[edgeFromNewPointToPoint1]->getNext();
215 const int edgeFromVirtualToPoint1Side1 = mHalfEdge[mHalfEdge[edgeFromNewPointToPoint2]->getNext()]->getNext();
216 const int edgeFromPoint2ToVirtualSide1 = mHalfEdge[edgeFromNewPointToPoint2]->getNext();
217 const int edgeFromVirtualToPoint2Side2 = mHalfEdge[mHalfEdge[edgeFromNewPointToPoint1]->getNext()]->getNext();
219 const int edgeFromVirtualToNewPointSide1 = insertEdge( -10, edgeFromNewPointToPoint2, newPoint,
false,
false );
220 const int edgeFromNewPointToVirtualSide1 = insertEdge( edgeFromVirtualToNewPointSide1, edgeFromVirtualToPoint1Side1, -1,
false,
false );
221 const int edgeFromVirtualToNewPointSide2 = insertEdge( -10, edgeFromNewPointToPoint1, newPoint,
false,
false );
222 const int edgeFromNewPointToVirtualSide2 = insertEdge( edgeFromVirtualToNewPointSide2, edgeFromVirtualToPoint2Side2, -1,
false,
false );
223 const int edgeFromPoint1ToNewPoint = insertEdge( edgeFromNewPointToPoint1, edgeFromNewPointToVirtualSide1, newPoint,
false,
false );
224 const int edgeFromPoint2ToNewPoint = insertEdge( edgeFromNewPointToPoint2, edgeFromNewPointToVirtualSide2, newPoint,
false,
false );
225 mHalfEdge.at( edgeFromVirtualToNewPointSide1 )->setDual( edgeFromNewPointToVirtualSide1 );
226 mHalfEdge.at( edgeFromVirtualToNewPointSide2 )->setDual( edgeFromNewPointToVirtualSide2 );
228 mHalfEdge.at( edgeFromPoint1ToVirtualSide2 )->setNext( edgeFromVirtualToNewPointSide2 );
229 mHalfEdge.at( edgeFromVirtualToPoint1Side1 )->setNext( edgeFromPoint1ToNewPoint );
230 mHalfEdge.at( edgeFromPoint2ToVirtualSide1 )->setNext( edgeFromVirtualToNewPointSide1 );
231 mHalfEdge.at( edgeFromVirtualToPoint2Side2 )->setNext( edgeFromPoint2ToNewPoint );
232 mHalfEdge.at( edgeFromNewPointToPoint1 )->setDual( edgeFromPoint1ToNewPoint );
233 mHalfEdge.at( edgeFromNewPointToPoint2 )->setDual( edgeFromPoint2ToNewPoint );
238 if ( distance1 < distance )
240 closestEdge = mEdgeOutside;
241 distance = distance1;
243 else if ( distance2 < distance )
245 closestEdge = mHalfEdge[mEdgeOutside]->getDual();
246 distance = distance2;
249 mEdgeOutside = mHalfEdge[mHalfEdge[mHalfEdge[mEdgeOutside]->getNext()]->getDual()]->getNext();
250 }
while ( mEdgeOutside != firstEdge && mHalfEdge[mEdgeOutside]->getPoint() != -1 && mHalfEdge[mHalfEdge[mEdgeOutside]->getDual()]->getPoint() != -1 );
252 if ( closestEdge < 0 )
256 const int extremePoint = mHalfEdge[closestEdge]->getPoint();
257 const int newPoint = mPointVector.count() - 1;
259 const int edgeFromExtremeToOpposite = mHalfEdge[closestEdge]->getDual();
261 const int edgeFromVirtualToExtremeSide1 = mHalfEdge[mHalfEdge[closestEdge]->getNext()]->getDual();
262 const int edgeFromVirtualToExtremeSide2 = mHalfEdge[mHalfEdge[mHalfEdge[closestEdge]->getDual()]->getNext()]->getNext();
263 const int edgeFromExtremeToVirtualSide2 = mHalfEdge[edgeFromVirtualToExtremeSide2]->getDual();
265 const int edgeFromExtremeToNewPoint = insertEdge( -10, -10, newPoint,
false,
false );
266 const int edgeFromNewPointToExtreme = insertEdge( edgeFromExtremeToNewPoint, edgeFromExtremeToVirtualSide2, extremePoint,
false,
false );
267 const int edgeFromNewPointToVirtualSide1 = insertEdge( -10, edgeFromVirtualToExtremeSide1, -1,
false,
false );
268 const int edgeFromVirtualToNewPointSide1 = insertEdge( edgeFromNewPointToVirtualSide1, -10, newPoint,
false,
false );
269 const int edgeFromNewPointToVirtualSide2 = insertEdge( -10, edgeFromVirtualToNewPointSide1, -1,
false,
false );
270 const int edgeFromVirtualToNewPointSide2 = insertEdge( edgeFromNewPointToVirtualSide2, edgeFromNewPointToExtreme, newPoint,
false,
false );
271 mHalfEdge.at( edgeFromExtremeToNewPoint )->setDual( edgeFromNewPointToExtreme );
272 mHalfEdge.at( edgeFromExtremeToNewPoint )->setNext( edgeFromNewPointToVirtualSide1 );
273 mHalfEdge.at( edgeFromNewPointToVirtualSide1 )->setDual( edgeFromVirtualToNewPointSide1 );
274 mHalfEdge.at( edgeFromNewPointToVirtualSide2 )->setDual( edgeFromVirtualToNewPointSide2 );
275 mHalfEdge.at( edgeFromVirtualToNewPointSide1 )->setNext( edgeFromNewPointToVirtualSide2 );
277 mHalfEdge.at( edgeFromVirtualToExtremeSide1 )->setNext( edgeFromExtremeToNewPoint );
278 mHalfEdge.at( edgeFromVirtualToExtremeSide2 )->setNext( edgeFromExtremeToOpposite );
279 mHalfEdge.at( edgeFromExtremeToVirtualSide2 )->setNext( edgeFromVirtualToNewPointSide2 );
286 mEdgeOutside = mHalfEdge[mEdgeOutside]->getDual();
289 const int newPoint = mPointVector.count() - 1;
292 int cwEdge = mEdgeOutside;
293 while ( mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext()]->getPoint() != -1 )
295 mHalfEdge[mHalfEdge[cwEdge]->getNext()]->setPoint( newPoint );
296 cwEdge = mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext();
299 const int edgeFromLastCwPointToVirtualPoint = mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext();
300 const int edgeFromLastCwPointToNewPointPoint = mHalfEdge[cwEdge]->getNext();
301 const int edgeFromNewPointPointToLastCwPoint = mHalfEdge[edgeFromLastCwPointToNewPointPoint]->getDual();
303 const int edgeFromNewPointtoVirtualPoint = insertEdge( -10, -10, -1,
false,
false );
304 const int edgeFromVirtualPointToNewPoint = insertEdge( edgeFromNewPointtoVirtualPoint, edgeFromNewPointPointToLastCwPoint, newPoint,
false,
false );
305 mHalfEdge.at( edgeFromLastCwPointToNewPointPoint )->setPoint( newPoint );
306 mHalfEdge.at( edgeFromNewPointtoVirtualPoint )->setDual( edgeFromVirtualPointToNewPoint );
307 mHalfEdge.at( edgeFromLastCwPointToVirtualPoint )->setNext( edgeFromVirtualPointToNewPoint );
310 int ccwEdge = mEdgeOutside;
311 while ( mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getDual()]->getNext()]->getDual()]->getNext()]->getPoint() != -1 )
313 mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getDual()]->setPoint( newPoint );
314 ccwEdge = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getDual()]->getNext()]->getDual()]->getNext()]->getDual();
317 const int edgeToLastCcwPoint = mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getDual()]->getNext()]->getDual();
318 const int edgeFromLastCcwPointToNewPoint = mHalfEdge[edgeToLastCcwPoint]->getNext();
319 mHalfEdge.at( edgeFromNewPointtoVirtualPoint )->setNext( edgeToLastCcwPoint );
320 mHalfEdge.at( edgeFromLastCcwPointToNewPoint )->setNext( edgeFromNewPointtoVirtualPoint );
321 mHalfEdge.at( edgeFromLastCcwPointToNewPoint )->setPoint( newPoint );
325 const int number = baseEdgeOfTriangle( p );
330 unsigned int cwEdge = mEdgeOutside;
331 unsigned int ccwEdge = mEdgeOutside;
334 mHalfEdge[mHalfEdge[mEdgeOutside]->getNext()]->setPoint( mPointVector.count() - 1 );
337 while (
MathUtils::leftOf( *mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext()]->getPoint()], &p, mPointVector[mHalfEdge[cwEdge]->getPoint()] ) < ( -
leftOfTresh ) )
340 mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext()]->getNext()]->setPoint( mPointVector.count() - 1 );
342 cwEdge = (
unsigned int ) mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext();
346 const unsigned int edge1 = insertEdge( mHalfEdge[cwEdge]->getNext(), -10, mHalfEdge[cwEdge]->getPoint(),
false,
false );
347 const unsigned int edge2 = insertEdge( mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual(), -10, -1,
false,
false );
348 const unsigned int edge3 = insertEdge( -10, edge1, mPointVector.count() - 1,
false,
false );
351 mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->setDual( edge2 );
352 mHalfEdge[mHalfEdge[cwEdge]->getNext()]->setDual( edge1 );
353 mHalfEdge[edge1]->setNext( edge2 );
354 mHalfEdge[edge2]->setNext( edge3 );
357 while (
MathUtils::leftOf( *mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getPoint()], mPointVector[mPointVector.count() - 1], mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getDual()]->getNext()]->getPoint()] ) < ( -
leftOfTresh ) )
360 mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getDual()]->setPoint( mPointVector.count() - 1 );
362 ccwEdge = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getDual()]->getNext()]->getNext();
366 const unsigned int edge4 = insertEdge( mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext(), -10, mPointVector.count() - 1,
false,
false );
367 const unsigned int edge5 = insertEdge( edge3, -10, -1,
false,
false );
368 const unsigned int edge6 = insertEdge( mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getDual(), edge4, mHalfEdge[mHalfEdge[ccwEdge]->getDual()]->getPoint(),
false,
false );
372 mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getDual()]->setDual( edge6 );
373 mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->setDual( edge4 );
374 mHalfEdge[edge4]->setNext( edge5 );
375 mHalfEdge[edge5]->setNext( edge6 );
376 mHalfEdge[edge3]->setDual( edge5 );
379 unsigned int index = ccwEdge;
384 index = mHalfEdge[mHalfEdge[mHalfEdge[index]->getNext()]->getDual()]->getNext();
385 checkSwapRecursively( toswap, 0 );
386 if ( toswap == cwEdge )
392 else if ( number >= 0 )
394 const int nextnumber = mHalfEdge[number]->getNext();
395 const int nextnextnumber = mHalfEdge[mHalfEdge[number]->getNext()]->getNext();
398 const unsigned int edge1 = insertEdge( -10, nextnumber, mHalfEdge[number]->getPoint(),
false,
false );
399 const unsigned int edge2 = insertEdge(
static_cast<int>( edge1 ), -10, mPointVector.count() - 1,
false,
false );
400 const unsigned int edge3 = insertEdge( -10, nextnextnumber, mHalfEdge[nextnumber]->getPoint(),
false,
false );
401 const unsigned int edge4 = insertEdge(
static_cast<int>( edge3 ),
static_cast<int>( edge1 ), mPointVector.count() - 1,
false,
false );
402 const unsigned int edge5 = insertEdge( -10, number, mHalfEdge[nextnextnumber]->getPoint(),
false,
false );
403 const unsigned int edge6 = insertEdge(
static_cast<int>( edge5 ),
static_cast<int>( edge3 ), mPointVector.count() - 1,
false,
false );
406 mHalfEdge.at( edge1 )->setDual(
static_cast<int>( edge2 ) );
407 mHalfEdge.at( edge2 )->setNext(
static_cast<int>( edge5 ) );
408 mHalfEdge.at( edge3 )->setDual(
static_cast<int>( edge4 ) );
409 mHalfEdge.at( edge5 )->setDual(
static_cast<int>( edge6 ) );
410 mHalfEdge.at( number )->setNext(
static_cast<int>( edge2 ) );
411 mHalfEdge.at( nextnumber )->setNext(
static_cast<int>( edge4 ) );
412 mHalfEdge.at( nextnextnumber )->setNext(
static_cast<int>( edge6 ) );
415 checkSwapRecursively( number, 0 );
416 checkSwapRecursively( nextnumber, 0 );
417 checkSwapRecursively( nextnextnumber, 0 );
420 else if ( number == -20 )
425 const int point1 = mHalfEdge[mEdgeWithPoint]->getPoint();
426 const int point2 = mHalfEdge[mHalfEdge[mEdgeWithPoint]->getDual()]->getPoint();
427 const double distance1 = p.
distance( *mPointVector[point1] );
433 const double distance2 = p.
distance( *mPointVector[point2] );
440 const int edgea = mEdgeWithPoint;
441 const int edgeb = mHalfEdge[mEdgeWithPoint]->getDual();
442 const int edgec = mHalfEdge[edgea]->getNext();
443 const int edged = mHalfEdge[edgec]->getNext();
444 const int edgee = mHalfEdge[edgeb]->getNext();
445 const int edgef = mHalfEdge[edgee]->getNext();
448 const int nedge1 = insertEdge( -10, mHalfEdge[edgea]->getNext(), mHalfEdge[edgea]->getPoint(),
false,
false );
449 const int nedge2 = insertEdge( nedge1, -10, mPointVector.count() - 1,
false,
false );
450 const int nedge3 = insertEdge( -10, edged, mHalfEdge[edgec]->getPoint(),
false,
false );
451 const int nedge4 = insertEdge( nedge3, nedge1, mPointVector.count() - 1,
false,
false );
452 const int nedge5 = insertEdge( -10, edgef, mHalfEdge[edgee]->getPoint(),
false,
false );
453 const int nedge6 = insertEdge( nedge5, edgeb, mPointVector.count() - 1,
false,
false );
456 mHalfEdge[nedge1]->setDual( nedge2 );
457 mHalfEdge[nedge2]->setNext( nedge5 );
458 mHalfEdge[nedge3]->setDual( nedge4 );
459 mHalfEdge[nedge5]->setDual( nedge6 );
460 mHalfEdge[edgea]->setPoint( mPointVector.count() - 1 );
461 mHalfEdge[edgea]->setNext( nedge3 );
462 mHalfEdge[edgec]->setNext( nedge4 );
463 mHalfEdge[edgee]->setNext( nedge6 );
464 mHalfEdge[edgef]->setNext( nedge2 );
467 checkSwapRecursively( edgec, 0 );
468 checkSwapRecursively( edged, 0 );
469 checkSwapRecursively( edgee, 0 );
470 checkSwapRecursively( edgef, 0 );
473 else if ( number == -100 || number == -5 )
479 else if ( number == -25 )
482 QgsPoint *newPoint = mPointVector[mPointVector.count() - 1];
483 QgsPoint *existingPoint = mPointVector[mTwiceInsPoint];
484 existingPoint->
setZ( std::max( newPoint->
z(), existingPoint->
z() ) );
487 return mTwiceInsPoint;
491 return ( mPointVector.count() - 1 );
494int QgsDualEdgeTriangulation::baseEdgeOfPoint(
int point )
496 unsigned int actedge = mEdgeInside;
498 if ( mPointVector.count() < 4 ||
point == -1 || mDimension == 1 )
500 int fromVirtualPoint = -1;
502 for (
int i = 0; i < mHalfEdge.count(); i++ )
504 if ( mHalfEdge[i]->getPoint() ==
point )
506 if ( mHalfEdge[mHalfEdge[i]->getDual()]->getPoint() != -1 )
509 fromVirtualPoint = i;
512 return fromVirtualPoint;
520 if ( control > 1000000 )
526 for (
int i = 0; i < mHalfEdge.count(); i++ )
528 if ( mHalfEdge[i]->getPoint() ==
point && mHalfEdge[mHalfEdge[i]->getNext()]->getPoint() != -1 )
535 const int fromPoint = mHalfEdge[mHalfEdge[actedge]->getDual()]->getPoint();
536 const int toPoint = mHalfEdge[actedge]->getPoint();
538 if ( fromPoint == -1 || toPoint == -1 )
540 for (
int i = 0; i < mHalfEdge.count(); i++ )
542 if ( mHalfEdge[i]->getPoint() ==
point && mHalfEdge[mHalfEdge[i]->getNext()]->getPoint() != -1 )
550 const double leftOfNumber =
MathUtils::leftOf( *mPointVector[
point], mPointVector[mHalfEdge[mHalfEdge[actedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[actedge]->getPoint()] );
553 if ( mHalfEdge[actedge]->getPoint() ==
point && mHalfEdge[mHalfEdge[actedge]->getNext()]->getPoint() != -1 )
555 mEdgeInside = actedge;
558 else if ( leftOfNumber <= 0.0 )
560 actedge = mHalfEdge[actedge]->getNext();
564 actedge = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[actedge]->getDual()]->getNext()]->getNext()]->getDual();
569int QgsDualEdgeTriangulation::baseEdgeOfTriangle(
const QgsPoint &point )
571 unsigned int actEdge = mEdgeInside;
572 if ( mHalfEdge.at( actEdge )->getPoint() < 0 )
573 actEdge = mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( actEdge )->getDual() )->getNext() )->getDual();
574 if ( mHalfEdge.at( mHalfEdge.at( actEdge )->getDual() )->getPoint() < 0 )
575 actEdge = mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getDual();
581 int firstEndPoint = 0, secEndPoint = 0, thEndPoint = 0, fouEndPoint = 0;
585 if ( runs > MAX_BASE_ITERATIONS )
591 const double leftOfValue =
MathUtils::leftOf(
point, mPointVector.at( mHalfEdge.at( mHalfEdge.at( actEdge )->getDual() )->getPoint() ), mPointVector.at( mHalfEdge.at( actEdge )->getPoint() ) );
606 firstEndPoint = mHalfEdge.at( mHalfEdge.at( actEdge )->getDual() )->getPoint();
607 secEndPoint = mHalfEdge.at( actEdge )->getPoint();
609 else if ( nulls == 1 )
612 thEndPoint = mHalfEdge.at( mHalfEdge.at( actEdge )->getDual() )->getPoint();
613 fouEndPoint = mHalfEdge.at( actEdge )->getPoint();
616 mEdgeWithPoint = actEdge;
625 actEdge = mHalfEdge.at( actEdge )->getDual();
630 actEdge = mHalfEdge.at( actEdge )->getNext();
631 if ( mHalfEdge.at( actEdge )->getPoint() == -1 )
637 mEdgeOutside = (
unsigned int ) mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getNext();
638 mEdgeInside = mHalfEdge.at( mHalfEdge.at( mEdgeOutside )->getDual() )->getNext();
644 if ( numInstabs > 0 )
647 mUnstableEdge = actEdge;
654 if ( firstEndPoint == thEndPoint || firstEndPoint == fouEndPoint )
657 mTwiceInsPoint = firstEndPoint;
660 else if ( secEndPoint == thEndPoint || secEndPoint == fouEndPoint )
663 mTwiceInsPoint = secEndPoint;
675 mEdgeInside = actEdge;
678 nr1 = mHalfEdge.at( actEdge )->getPoint();
679 nr2 = mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getPoint();
680 nr3 = mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getNext() )->getPoint();
681 const double x1 = mPointVector.at( nr1 )->x();
682 const double y1 = mPointVector.at( nr1 )->y();
683 const double x2 = mPointVector.at( nr2 )->x();
684 const double y2 = mPointVector.at( nr2 )->y();
685 const double x3 = mPointVector.at( nr3 )->x();
686 const double y3 = mPointVector.at( nr3 )->y();
689 if ( x1 < x2 && x1 < x3 )
693 else if ( x2 < x1 && x2 < x3 )
695 return mHalfEdge.at( actEdge )->getNext();
697 else if ( x3 < x1 && x3 < x2 )
699 return mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getNext();
710 return mHalfEdge.at( actEdge )->getNext();
717 return mHalfEdge.at( actEdge )->getNext();
721 return mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getNext();
732 return mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getNext();
740 if ( mTriangleInterpolator )
742 return mTriangleInterpolator->
calcNormVec( x, y, result );
753 if ( mTriangleInterpolator )
755 return mTriangleInterpolator->
calcPoint( x, y, result );
764bool QgsDualEdgeTriangulation::checkSwapRecursively(
unsigned int edge,
unsigned int recursiveDeep )
766 if ( swapPossible( edge ) )
768 QgsPoint *pta = mPointVector.at( mHalfEdge.at( edge )->getPoint() );
769 QgsPoint *ptb = mPointVector.at( mHalfEdge.at( mHalfEdge.at( edge )->getNext() )->getPoint() );
770 QgsPoint *ptc = mPointVector.at( mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( edge )->getNext() )->getNext() )->getPoint() );
771 QgsPoint *ptd = mPointVector.at( mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( edge )->getDual() )->getNext() )->getPoint() );
772 if ( inCircle( *ptd, *pta, *ptb, *ptc ) )
774 doSwapRecursively( edge, recursiveDeep );
781bool QgsDualEdgeTriangulation::isEdgeNeedSwap(
unsigned int edge )
const
783 if ( swapPossible( edge ) )
785 QgsPoint *pta = mPointVector[mHalfEdge[edge]->getPoint()];
786 QgsPoint *ptb = mPointVector[mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint()];
787 QgsPoint *ptc = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getNext()]->getNext()]->getPoint()];
788 QgsPoint *ptd = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint()];
789 return inCircle( *ptd, *pta, *ptb, *ptc );
795void QgsDualEdgeTriangulation::doOnlySwap(
unsigned int edge )
797 const unsigned int edge1 = edge;
798 const unsigned int edge2 = mHalfEdge[edge]->getDual();
799 const unsigned int edge3 = mHalfEdge[edge]->getNext();
800 const unsigned int edge4 = mHalfEdge[mHalfEdge[edge]->getNext()]->getNext();
801 const unsigned int edge5 = mHalfEdge[mHalfEdge[edge]->getDual()]->getNext();
802 const unsigned int edge6 = mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getNext();
803 mHalfEdge[edge1]->setNext( edge4 );
804 mHalfEdge[edge2]->setNext( edge6 );
805 mHalfEdge[edge3]->setNext( edge2 );
806 mHalfEdge[edge4]->setNext( edge5 );
807 mHalfEdge[edge5]->setNext( edge1 );
808 mHalfEdge[edge6]->setNext( edge3 );
809 mHalfEdge[edge1]->setPoint( mHalfEdge[edge3]->getPoint() );
810 mHalfEdge[edge2]->setPoint( mHalfEdge[edge5]->getPoint() );
813void QgsDualEdgeTriangulation::doSwapRecursively(
unsigned int edge,
unsigned int recursiveDeep )
815 const unsigned int edge1 = edge;
816 const unsigned int edge2 = mHalfEdge.at( edge )->getDual();
817 const unsigned int edge3 = mHalfEdge.at( edge )->getNext();
818 const unsigned int edge4 = mHalfEdge.at( mHalfEdge.at( edge )->getNext() )->getNext();
819 const unsigned int edge5 = mHalfEdge.at( mHalfEdge.at( edge )->getDual() )->getNext();
820 const unsigned int edge6 = mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( edge )->getDual() )->getNext() )->getNext();
821 mHalfEdge.at( edge1 )->setNext( edge4 );
822 mHalfEdge.at( edge2 )->setNext( edge6 );
823 mHalfEdge.at( edge3 )->setNext( edge2 );
824 mHalfEdge.at( edge4 )->setNext( edge5 );
825 mHalfEdge.at( edge5 )->setNext( edge1 );
826 mHalfEdge.at( edge6 )->setNext( edge3 );
827 mHalfEdge.at( edge1 )->setPoint( mHalfEdge.at( edge3 )->getPoint() );
828 mHalfEdge.at( edge2 )->setPoint( mHalfEdge.at( edge5 )->getPoint() );
831 if ( recursiveDeep < 100 )
833 checkSwapRecursively( edge3, recursiveDeep );
834 checkSwapRecursively( edge6, recursiveDeep );
835 checkSwapRecursively( edge4, recursiveDeep );
836 checkSwapRecursively( edge5, recursiveDeep );
840 QStack<int> edgesToSwap;
841 edgesToSwap.push( edge3 );
842 edgesToSwap.push( edge6 );
843 edgesToSwap.push( edge4 );
844 edgesToSwap.push( edge5 );
846 while ( !edgesToSwap.isEmpty() && loopCount < 10000 )
849 const unsigned int e1 = edgesToSwap.pop();
850 if ( isEdgeNeedSwap( e1 ) )
852 const unsigned int e2 = mHalfEdge.at( e1 )->getDual();
853 const unsigned int e3 = mHalfEdge.at( e1 )->getNext();
854 const unsigned int e4 = mHalfEdge.at( mHalfEdge.at( e1 )->getNext() )->getNext();
855 const unsigned int e5 = mHalfEdge.at( mHalfEdge.at( e1 )->getDual() )->getNext();
856 const unsigned int e6 = mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( e1 )->getDual() )->getNext() )->getNext();
857 mHalfEdge.at( e1 )->setNext( e4 );
858 mHalfEdge.at( e2 )->setNext( e6 );
859 mHalfEdge.at( e3 )->setNext( e2 );
860 mHalfEdge.at( e4 )->setNext( e5 );
861 mHalfEdge.at( e5 )->setNext( e1 );
862 mHalfEdge.at( e6 )->setNext( e3 );
863 mHalfEdge.at( e1 )->setPoint( mHalfEdge.at( e3 )->getPoint() );
864 mHalfEdge.at( e2 )->setPoint( mHalfEdge.at( e5 )->getPoint() );
866 edgesToSwap.push( e3 );
867 edgesToSwap.push( e6 );
868 edgesToSwap.push( e4 );
869 edgesToSwap.push( e5 );
876void DualEdgeTriangulation::draw( QPainter *p,
double xlowleft,
double ylowleft,
double xupright,
double yupright,
double width,
double height )
const
879 if ( mPointVector.isEmpty() )
884 p->setPen( mEdgeColor );
886 bool *control =
new bool[mHalfEdge.count()];
887 bool *control2 =
new bool[mHalfEdge.count()];
889 for (
unsigned int i = 0; i <= mHalfEdge.count() - 1; i++ )
895 if ( ( ( xupright - xlowleft ) / width ) > ( ( yupright - ylowleft ) / height ) )
897 double lowerborder = -( height * ( xupright - xlowleft ) / width - yupright );
898 for (
unsigned int i = 0; i < mHalfEdge.count() - 1; i++ )
900 if ( mHalfEdge[i]->getPoint() == -1 || mHalfEdge[mHalfEdge[i]->getDual()]->getPoint() == -1 )
907 if ( mHalfEdge[i]->getPoint() != -1 && mHalfEdge[mHalfEdge[i]->getNext()]->getPoint() != -1 && mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint() != -1 )
909 p1 = mPointVector[mHalfEdge[i]->getPoint()]->getZ();
910 p2 = mPointVector[mHalfEdge[mHalfEdge[i]->getNext()]->getPoint()]->getZ();
911 p3 = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint()]->getZ();
912 if ( p1 == p2 && p2 == p3 && halfEdgeBBoxTest( i, xlowleft, lowerborder, xupright, yupright ) && halfEdgeBBoxTest( mHalfEdge[i]->getNext(), xlowleft, lowerborder, xupright, yupright ) && halfEdgeBBoxTest( mHalfEdge[mHalfEdge[i]->getNext()]->getNext(), xlowleft, lowerborder, xupright, yupright ) )
915 pa.setPoint( 0, ( mPointVector[mHalfEdge[i]->getPoint()]->getX() - xlowleft ) / ( xupright - xlowleft )*width, ( yupright - mPointVector[mHalfEdge[i]->getPoint()]->getY() ) / ( xupright - xlowleft )*width );
916 pa.setPoint( 1, ( mPointVector[mHalfEdge[mHalfEdge[i]->getNext()]->getPoint()]->getX() - xlowleft ) / ( xupright - xlowleft )*width, ( yupright - mPointVector[mHalfEdge[mHalfEdge[i]->getNext()]->getPoint()]->getY() ) / ( xupright - xlowleft )*width );
917 pa.setPoint( 2, ( mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint()]->getX() - xlowleft ) / ( xupright - xlowleft )*width, ( yupright - mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint()]->getY() ) / ( xupright - xlowleft )*width );
918 QColor
c( 255, 0, 0 );
920 p->drawPolygon( pa );
925 control2[mHalfEdge[i]->getNext()] =
true;
926 control2[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()] =
true;
933 if ( halfEdgeBBoxTest( i, xlowleft, lowerborder, xupright, yupright ) )
935 if ( mHalfEdge[i]->getBreak() )
937 p->setPen( mBreakEdgeColor );
939 else if ( mHalfEdge[i]->getForced() )
941 p->setPen( mForcedEdgeColor );
945 p->drawLine( ( mPointVector[mHalfEdge[i]->getPoint()]->getX() - xlowleft ) / ( xupright - xlowleft )*width, ( yupright - mPointVector[mHalfEdge[i]->getPoint()]->getY() ) / ( xupright - xlowleft )*width, ( mPointVector[mHalfEdge[mHalfEdge[i]->getDual()]->getPoint()]->getX() - xlowleft ) / ( xupright - xlowleft )*width, ( yupright - mPointVector[mHalfEdge[mHalfEdge[i]->getDual()]->getPoint()]->getY() ) / ( xupright - xlowleft )*width );
947 if ( mHalfEdge[i]->getForced() )
949 p->setPen( mEdgeColor );
955 control[mHalfEdge[i]->getDual()] =
true;
960 double rightborder = width * ( yupright - ylowleft ) / height + xlowleft;
961 for (
unsigned int i = 0; i < mHalfEdge.count() - 1; i++ )
963 if ( mHalfEdge[i]->getPoint() == -1 || mHalfEdge[mHalfEdge[i]->getDual()]->getPoint() == -1 )
970 if ( mHalfEdge[i]->getPoint() != -1 && mHalfEdge[mHalfEdge[i]->getNext()]->getPoint() != -1 && mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint() != -1 )
972 p1 = mPointVector[mHalfEdge[i]->getPoint()]->getZ();
973 p2 = mPointVector[mHalfEdge[mHalfEdge[i]->getNext()]->getPoint()]->getZ();
974 p3 = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint()]->getZ();
975 if ( p1 == p2 && p2 == p3 && halfEdgeBBoxTest( i, xlowleft, ylowleft, rightborder, yupright ) && halfEdgeBBoxTest( mHalfEdge[i]->getNext(), xlowleft, ylowleft, rightborder, yupright ) && halfEdgeBBoxTest( mHalfEdge[mHalfEdge[i]->getNext()]->getNext(), xlowleft, ylowleft, rightborder, yupright ) )
978 pa.setPoint( 0, ( mPointVector[mHalfEdge[i]->getPoint()]->getX() - xlowleft ) / ( yupright - ylowleft )*height, ( yupright - mPointVector[mHalfEdge[i]->getPoint()]->getY() ) / ( yupright - ylowleft )*height );
979 pa.setPoint( 1, ( mPointVector[mHalfEdge[mHalfEdge[i]->getNext()]->getPoint()]->getX() - xlowleft ) / ( yupright - ylowleft )*height, ( yupright - mPointVector[mHalfEdge[mHalfEdge[i]->getNext()]->getPoint()]->getY() ) / ( yupright - ylowleft )*height );
980 pa.setPoint( 2, ( mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint()]->getX() - xlowleft ) / ( yupright - ylowleft )*height, ( yupright - mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint()]->getY() ) / ( yupright - ylowleft )*height );
981 QColor
c( 255, 0, 0 );
983 p->drawPolygon( pa );
988 control2[mHalfEdge[i]->getNext()] =
true;
989 control2[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()] =
true;
997 if ( halfEdgeBBoxTest( i, xlowleft, ylowleft, rightborder, yupright ) )
999 if ( mHalfEdge[i]->getBreak() )
1001 p->setPen( mBreakEdgeColor );
1003 else if ( mHalfEdge[i]->getForced() )
1005 p->setPen( mForcedEdgeColor );
1008 p->drawLine( ( mPointVector[mHalfEdge[i]->getPoint()]->getX() - xlowleft ) / ( yupright - ylowleft )*height, ( yupright - mPointVector[mHalfEdge[i]->getPoint()]->getY() ) / ( yupright - ylowleft )*height, ( mPointVector[mHalfEdge[mHalfEdge[i]->getDual()]->getPoint()]->getX() - xlowleft ) / ( yupright - ylowleft )*height, ( yupright - mPointVector[mHalfEdge[mHalfEdge[i]->getDual()]->getPoint()]->getY() ) / ( yupright - ylowleft )*height );
1010 if ( mHalfEdge[i]->getForced() )
1012 p->setPen( mEdgeColor );
1017 control[mHalfEdge[i]->getDual()] =
true;
1029 const int firstedge = baseEdgeOfPoint( p2 );
1033 int nextnextedge = firstedge;
1037 edge = mHalfEdge[nextnextedge]->getDual();
1038 if ( mHalfEdge[edge]->getPoint() == p1 )
1040 theedge = nextnextedge;
1043 nextedge = mHalfEdge[edge]->getNext();
1044 nextnextedge = mHalfEdge[nextedge]->getNext();
1045 }
while ( nextnextedge != firstedge );
1047 if ( theedge == -10 )
1054 return mHalfEdge[mHalfEdge[mHalfEdge[theedge]->getDual()]->getNext()]->getPoint();
1059 const int firstedge = baseEdgeOfPoint( pointno );
1062 if ( firstedge == -1 )
1067 int actedge = firstedge;
1068 int edge, nextedge, nextnextedge;
1071 edge = mHalfEdge[actedge]->getDual();
1072 vlist.append( mHalfEdge[edge]->getPoint() );
1073 nextedge = mHalfEdge[edge]->getNext();
1074 vlist.append( mHalfEdge[nextedge]->getPoint() );
1075 nextnextedge = mHalfEdge[nextedge]->getNext();
1076 vlist.append( mHalfEdge[nextnextedge]->getPoint() );
1077 if ( mHalfEdge[nextnextedge]->getBreak() )
1079 vlist.append( -10 );
1083 vlist.append( -20 );
1085 actedge = nextnextedge;
1086 }
while ( nextnextedge != firstedge );
1093 if ( mPointVector.size() < 3 )
1099 const int edge = baseEdgeOfTriangle(
point );
1105 else if ( edge >= 0 )
1107 const int ptnr1 = mHalfEdge[edge]->getPoint();
1108 const int ptnr2 = mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint();
1109 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[edge]->getNext()]->getNext()]->getPoint();
1110 p1.
setX( mPointVector[ptnr1]->x() );
1111 p1.
setY( mPointVector[ptnr1]->y() );
1112 p1.
setZ( mPointVector[ptnr1]->z() );
1113 p2.
setX( mPointVector[ptnr2]->x() );
1114 p2.
setY( mPointVector[ptnr2]->y() );
1115 p2.
setZ( mPointVector[ptnr2]->z() );
1116 p3.
setX( mPointVector[ptnr3]->x() );
1117 p3.
setY( mPointVector[ptnr3]->y() );
1118 p3.
setZ( mPointVector[ptnr3]->z() );
1124 else if ( edge == -20 )
1126 const int ptnr1 = mHalfEdge[mEdgeWithPoint]->getPoint();
1127 const int ptnr2 = mHalfEdge[mHalfEdge[mEdgeWithPoint]->getNext()]->getPoint();
1128 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[mEdgeWithPoint]->getNext()]->getNext()]->getPoint();
1129 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1133 p1.
setX( mPointVector[ptnr1]->x() );
1134 p1.
setY( mPointVector[ptnr1]->y() );
1135 p1.
setZ( mPointVector[ptnr1]->z() );
1136 p2.
setX( mPointVector[ptnr2]->x() );
1137 p2.
setY( mPointVector[ptnr2]->y() );
1138 p2.
setZ( mPointVector[ptnr2]->z() );
1139 p3.
setX( mPointVector[ptnr3]->x() );
1140 p3.
setY( mPointVector[ptnr3]->y() );
1141 p3.
setZ( mPointVector[ptnr3]->z() );
1147 else if ( edge == -25 )
1149 const int edge1 = baseEdgeOfPoint( mTwiceInsPoint );
1150 const int edge2 = mHalfEdge[edge1]->getNext();
1151 const int edge3 = mHalfEdge[edge2]->getNext();
1152 const int ptnr1 = mHalfEdge[edge1]->getPoint();
1153 const int ptnr2 = mHalfEdge[edge2]->getPoint();
1154 const int ptnr3 = mHalfEdge[edge3]->getPoint();
1155 p1.
setX( mPointVector[ptnr1]->x() );
1156 p1.
setY( mPointVector[ptnr1]->y() );
1157 p1.
setZ( mPointVector[ptnr1]->z() );
1158 p2.
setX( mPointVector[ptnr2]->x() );
1159 p2.
setY( mPointVector[ptnr2]->y() );
1160 p2.
setZ( mPointVector[ptnr2]->z() );
1161 p3.
setX( mPointVector[ptnr3]->x() );
1162 p3.
setY( mPointVector[ptnr3]->y() );
1163 p3.
setZ( mPointVector[ptnr3]->z() );
1169 else if ( edge == -5 )
1171 const int ptnr1 = mHalfEdge[mUnstableEdge]->getPoint();
1172 const int ptnr2 = mHalfEdge[mHalfEdge[mUnstableEdge]->getNext()]->getPoint();
1173 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[mUnstableEdge]->getNext()]->getNext()]->getPoint();
1174 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1178 p1.
setX( mPointVector[ptnr1]->x() );
1179 p1.
setY( mPointVector[ptnr1]->y() );
1180 p1.
setZ( mPointVector[ptnr1]->z() );
1181 p2.
setX( mPointVector[ptnr2]->x() );
1182 p2.
setY( mPointVector[ptnr2]->y() );
1183 p2.
setZ( mPointVector[ptnr2]->z() );
1184 p3.
setX( mPointVector[ptnr3]->x() );
1185 p3.
setY( mPointVector[ptnr3]->y() );
1186 p3.
setZ( mPointVector[ptnr3]->z() );
1201 if ( mPointVector.size() < 3 )
1207 const int edge = baseEdgeOfTriangle(
point );
1212 else if ( edge >= 0 )
1214 const int ptnr1 = mHalfEdge[edge]->getPoint();
1215 const int ptnr2 = mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint();
1216 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[edge]->getNext()]->getNext()]->getPoint();
1217 p1.
setX( mPointVector[ptnr1]->x() );
1218 p1.
setY( mPointVector[ptnr1]->y() );
1219 p1.
setZ( mPointVector[ptnr1]->z() );
1220 p2.
setX( mPointVector[ptnr2]->x() );
1221 p2.
setY( mPointVector[ptnr2]->y() );
1222 p2.
setZ( mPointVector[ptnr2]->z() );
1223 p3.
setX( mPointVector[ptnr3]->x() );
1224 p3.
setY( mPointVector[ptnr3]->y() );
1225 p3.
setZ( mPointVector[ptnr3]->z() );
1228 else if ( edge == -20 )
1230 const int ptnr1 = mHalfEdge[mEdgeWithPoint]->getPoint();
1231 const int ptnr2 = mHalfEdge[mHalfEdge[mEdgeWithPoint]->getNext()]->getPoint();
1232 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[mEdgeWithPoint]->getNext()]->getNext()]->getPoint();
1233 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1237 p1.
setX( mPointVector[ptnr1]->x() );
1238 p1.
setY( mPointVector[ptnr1]->y() );
1239 p1.
setZ( mPointVector[ptnr1]->z() );
1240 p2.
setX( mPointVector[ptnr2]->x() );
1241 p2.
setY( mPointVector[ptnr2]->y() );
1242 p2.
setZ( mPointVector[ptnr2]->z() );
1243 p3.
setX( mPointVector[ptnr3]->x() );
1244 p3.
setY( mPointVector[ptnr3]->y() );
1245 p3.
setZ( mPointVector[ptnr3]->z() );
1248 else if ( edge == -25 )
1250 const int edge1 = baseEdgeOfPoint( mTwiceInsPoint );
1251 const int edge2 = mHalfEdge[edge1]->getNext();
1252 const int edge3 = mHalfEdge[edge2]->getNext();
1253 const int ptnr1 = mHalfEdge[edge1]->getPoint();
1254 const int ptnr2 = mHalfEdge[edge2]->getPoint();
1255 const int ptnr3 = mHalfEdge[edge3]->getPoint();
1256 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1260 p1.
setX( mPointVector[ptnr1]->x() );
1261 p1.
setY( mPointVector[ptnr1]->y() );
1262 p1.
setZ( mPointVector[ptnr1]->z() );
1263 p2.
setX( mPointVector[ptnr2]->x() );
1264 p2.
setY( mPointVector[ptnr2]->y() );
1265 p2.
setZ( mPointVector[ptnr2]->z() );
1266 p3.
setX( mPointVector[ptnr3]->x() );
1267 p3.
setY( mPointVector[ptnr3]->y() );
1268 p3.
setZ( mPointVector[ptnr3]->z() );
1271 else if ( edge == -5 )
1273 const int ptnr1 = mHalfEdge[mUnstableEdge]->getPoint();
1274 const int ptnr2 = mHalfEdge[mHalfEdge[mUnstableEdge]->getNext()]->getPoint();
1275 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[mUnstableEdge]->getNext()]->getNext()]->getPoint();
1276 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1280 p1.
setX( mPointVector[ptnr1]->x() );
1281 p1.
setY( mPointVector[ptnr1]->y() );
1282 p1.
setZ( mPointVector[ptnr1]->z() );
1283 p2.
setX( mPointVector[ptnr2]->x() );
1284 p2.
setY( mPointVector[ptnr2]->y() );
1285 p2.
setZ( mPointVector[ptnr2]->z() );
1286 p3.
setX( mPointVector[ptnr3]->x() );
1287 p3.
setY( mPointVector[ptnr3]->y() );
1288 p3.
setZ( mPointVector[ptnr3]->z() );
1297unsigned int QgsDualEdgeTriangulation::insertEdge(
int dual,
int next,
int point,
bool mbreak,
bool forced )
1300 mHalfEdge.append( edge );
1301 return mHalfEdge.count() - 1;
1304static bool altitudeTriangleIsSmall(
const QgsPoint &pointBase1,
const QgsPoint &pointBase2,
const QgsPoint &pt3,
double tolerance )
1307 const double x1 = pointBase1.
x();
1308 const double y1 = pointBase1.
y();
1309 const double x2 = pointBase2.
x();
1310 const double y2 = pointBase2.
y();
1311 const double X = pt3.
x();
1312 const double Y = pt3.
y();
1321 t = ( X * ny - Y * nx - x1 * ny + y1 * nx ) / ( ( x2 - x1 ) * ny - ( y2 - y1 ) * nx );
1322 projectedPoint.
setX( x1 + t * ( x2 - x1 ) );
1323 projectedPoint.
setY( y1 + t * ( y2 - y1 ) );
1325 return pt3.
distance( projectedPoint ) < tolerance;
1335 QgsPoint *point1 = mPointVector.at( p1 );
1336 QgsPoint *point2 = mPointVector.at( p2 );
1339 QList<int> crossedEdges;
1342 int pointingEdge = 0;
1344 pointingEdge = baseEdgeOfPoint( p1 );
1346 if ( pointingEdge == -1 )
1352 int actEdge = mHalfEdge[pointingEdge]->getDual();
1353 const int firstActEdge = actEdge;
1360 if ( control > 100 )
1366 if ( mHalfEdge[actEdge]->getPoint() == -1 )
1368 actEdge = mHalfEdge[mHalfEdge[mHalfEdge[actEdge]->getNext()]->getNext()]->getDual();
1373 if ( mHalfEdge[actEdge]->getPoint() == p2 )
1375 mHalfEdge[actEdge]->setForced(
true );
1377 mHalfEdge[mHalfEdge[actEdge]->getDual()]->setForced(
true );
1383 if ( ( point2->
y() - point1->
y() ) / ( mPointVector[mHalfEdge[actEdge]->getPoint()]->y() - point1->
y() ) == ( point2->
x() - point1->
x() ) / ( mPointVector[mHalfEdge[actEdge]->getPoint()]->x() - point1->
x() )
1384 && ( ( point2->
y() - point1->
y() ) >= 0 ) == ( ( mPointVector[mHalfEdge[actEdge]->getPoint()]->y() - point1->
y() ) > 0 )
1385 && ( ( point2->
x() - point1->
x() ) >= 0 ) == ( ( mPointVector[mHalfEdge[actEdge]->getPoint()]->x() - point1->
x() ) > 0 ) )
1388 mHalfEdge[actEdge]->setForced(
true );
1390 mHalfEdge[mHalfEdge[actEdge]->getDual()]->setForced(
true );
1392 const int a = insertForcedSegment( mHalfEdge[actEdge]->getPoint(), p2, segmentType );
1397 const int oppositeEdge = mHalfEdge[actEdge]->getNext();
1399 if ( mHalfEdge[oppositeEdge]->getPoint() == -1 || mHalfEdge[mHalfEdge[oppositeEdge]->getDual()]->getPoint() == -1 )
1401 actEdge = mHalfEdge[mHalfEdge[oppositeEdge]->getNext()]->getDual();
1405 QgsPoint *oppositePoint1 = mPointVector[mHalfEdge[oppositeEdge]->getPoint()];
1406 QgsPoint *oppositePoint2 = mPointVector[mHalfEdge[mHalfEdge[oppositeEdge]->getDual()]->getPoint()];
1408 if ( altitudeTriangleIsSmall( *oppositePoint1, *oppositePoint2, *point1, oppositePoint1->
distance( *oppositePoint2 ) / 500 ) )
1414 if (
MathUtils::lineIntersection( point1, point2, mPointVector[mHalfEdge[oppositeEdge]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[oppositeEdge]->getDual()]->getPoint()] ) )
1420 p3 = mHalfEdge[mHalfEdge[actEdge]->getNext()]->getPoint();
1421 p4 = mHalfEdge[mHalfEdge[mHalfEdge[actEdge]->getNext()]->getDual()]->getPoint();
1423 const double dista = crosspoint.distance( *mPointVector[p3] );
1424 const double distb = crosspoint.distance( *mPointVector[p4] );
1425 if ( dista <= distb )
1427 insertForcedSegment( p1, p3, segmentType );
1428 const int e = insertForcedSegment( p3, p2, segmentType );
1431 else if ( distb <= dista )
1433 insertForcedSegment( p1, p4, segmentType );
1434 const int e = insertForcedSegment( p4, p2, segmentType );
1443 p3 = mHalfEdge[mHalfEdge[actEdge]->getNext()]->getPoint();
1444 p4 = mHalfEdge[mHalfEdge[mHalfEdge[actEdge]->getNext()]->getDual()]->getPoint();
1446 const double distpart = crosspoint.distance( *mPointVector[p4] );
1447 const double disttot = mPointVector[p3]->distance( *mPointVector[p4] );
1448 const float frac = distpart / disttot;
1450 if ( frac == 0 || frac == 1 )
1455 mHalfEdge[actEdge]->setForced(
true );
1457 mHalfEdge[mHalfEdge[actEdge]->getDual()]->setForced(
true );
1459 const int a = insertForcedSegment( p4, p2, segmentType );
1462 else if ( frac == 1 )
1465 mHalfEdge[actEdge]->setForced(
true );
1467 mHalfEdge[mHalfEdge[actEdge]->getDual()]->setForced(
true );
1471 const int a = insertForcedSegment( p3, p2, segmentType );
1482 const int newpoint = splitHalfEdge( mHalfEdge[actEdge]->getNext(), frac );
1483 insertForcedSegment( p1, newpoint, segmentType );
1484 const int e = insertForcedSegment( newpoint, p2, segmentType );
1490 crossedEdges.append( oppositeEdge );
1493 actEdge = mHalfEdge[mHalfEdge[oppositeEdge]->getNext()]->getDual();
1494 }
while ( actEdge != firstActEdge );
1496 if ( crossedEdges.isEmpty() )
1498 int lastEdgeOppositePointIndex = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1501 while ( lastEdgeOppositePointIndex != p2 )
1503 QgsPoint *lastEdgePoint1 = mPointVector[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getPoint()];
1504 QgsPoint *lastEdgePoint2 = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint()];
1505 QgsPoint *lastEdgeOppositePoint = mPointVector[lastEdgeOppositePointIndex];
1513 p3 = mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getPoint();
1514 p4 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1516 const double dista = crosspoint.distance( *mPointVector[p3] );
1517 const double distb = crosspoint.distance( *mPointVector[p4] );
1518 if ( dista <= distb )
1520 insertForcedSegment( p1, p3, segmentType );
1521 const int e = insertForcedSegment( p3, p2, segmentType );
1524 else if ( distb <= dista )
1526 insertForcedSegment( p1, p4, segmentType );
1527 const int e = insertForcedSegment( p4, p2, segmentType );
1531 else if ( mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getForced() && mForcedCrossBehavior ==
QgsTriangulation::InsertVertex )
1535 p3 = mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getPoint();
1536 p4 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1538 const double distpart = crosspoint.distance( *mPointVector[p3] );
1539 const double disttot = mPointVector[p3]->distance( *mPointVector[p4] );
1540 const float frac = distpart / disttot;
1541 if ( frac == 0 || frac == 1 )
1545 const int newpoint = splitHalfEdge( mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext(), frac );
1546 insertForcedSegment( p1, newpoint, segmentType );
1547 const int e = insertForcedSegment( newpoint, p2, segmentType );
1551 crossedEdges.append( mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext() );
1555 if ( mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getForced() && mForcedCrossBehavior ==
QgsTriangulation::SnappingTypeVertex )
1559 p3 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1560 p4 = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint();
1562 const double dista = crosspoint.distance( *mPointVector[p3] );
1563 const double distb = crosspoint.distance( *mPointVector[p4] );
1564 if ( dista <= distb )
1566 insertForcedSegment( p1, p3, segmentType );
1567 const int e = insertForcedSegment( p3, p2, segmentType );
1570 else if ( distb <= dista )
1572 insertForcedSegment( p1, p4, segmentType );
1573 const int e = insertForcedSegment( p4, p2, segmentType );
1577 else if ( mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getForced() && mForcedCrossBehavior ==
QgsTriangulation::InsertVertex )
1581 p3 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1582 p4 = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint();
1584 const double distpart = crosspoint.distance( *mPointVector[p3] );
1585 const double disttot = mPointVector[p3]->distance( *mPointVector[p4] );
1586 const float frac = distpart / disttot;
1587 if ( frac == 0 || frac == 1 )
1591 const int newpoint = splitHalfEdge( mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext(), frac );
1592 insertForcedSegment( p1, newpoint, segmentType );
1593 const int e = insertForcedSegment( newpoint, p2, segmentType );
1597 crossedEdges.append( mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext() );
1604 lastEdgeOppositePointIndex = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1608 QgsPoint *lastEdgePoint1 = mPointVector[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getPoint()];
1609 QgsPoint *lastEdgePoint2 = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint()];
1610 QgsPoint *lastEdgeOppositePoint = mPointVector[lastEdgeOppositePointIndex];
1611 if ( altitudeTriangleIsSmall( *lastEdgePoint1, *lastEdgePoint2, *lastEdgeOppositePoint, lastEdgePoint1->
distance( *lastEdgePoint2 ) / 500 ) )
1615 QList<int>::const_iterator iter;
1616 for ( iter = crossedEdges.constBegin(); iter != crossedEdges.constEnd(); ++iter )
1618 mHalfEdge[( *( iter ) )]->setForced(
false );
1619 mHalfEdge[( *( iter ) )]->setBreak(
false );
1620 mHalfEdge[mHalfEdge[( *( iter ) )]->getDual()]->setForced(
false );
1621 mHalfEdge[mHalfEdge[( *( iter ) )]->getDual()]->setBreak(
false );
1626 QList<int> freelist = crossedEdges;
1629 QList<int> leftPolygon;
1630 QList<int> rightPolygon;
1633 const int firstedge = freelist.first();
1634 mHalfEdge[firstedge]->setForced(
true );
1636 leftPolygon.append( firstedge );
1637 const int dualfirstedge = mHalfEdge[freelist.first()]->getDual();
1638 mHalfEdge[dualfirstedge]->setForced(
true );
1640 rightPolygon.append( dualfirstedge );
1641 freelist.pop_front();
1645 QList<int>::const_iterator leftiter;
1646 leftiter = crossedEdges.constEnd();
1650 const int newpoint = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[( *leftiter )]->getDual()]->getNext()]->getNext()]->getPoint();
1651 if ( newpoint != actpointl )
1654 actpointl = newpoint;
1655 const int theedge = mHalfEdge[mHalfEdge[mHalfEdge[( *leftiter )]->getDual()]->getNext()]->getNext();
1656 leftPolygon.append( theedge );
1658 if ( leftiter == crossedEdges.constBegin() )
1666 leftPolygon.append( mHalfEdge[crossedEdges.first()]->getNext() );
1669 QList<int>::const_iterator rightiter;
1671 for ( rightiter = crossedEdges.constBegin(); rightiter != crossedEdges.constEnd(); ++rightiter )
1673 const int newpoint = mHalfEdge[mHalfEdge[mHalfEdge[( *rightiter )]->getNext()]->getNext()]->getPoint();
1674 if ( newpoint != actpointr )
1677 actpointr = newpoint;
1678 const int theedge = mHalfEdge[mHalfEdge[( *rightiter )]->getNext()]->getNext();
1679 rightPolygon.append( theedge );
1685 rightPolygon.append( mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext() );
1686 mHalfEdge[rightPolygon.last()]->setNext( dualfirstedge );
1689 int actedgel = leftPolygon[1];
1690 leftiter = leftPolygon.constBegin();
1692 for ( ; leftiter != leftPolygon.constEnd(); ++leftiter )
1694 mHalfEdge[actedgel]->setNext( ( *leftiter ) );
1695 actedgel = ( *leftiter );
1699 int actedger = rightPolygon[1];
1700 rightiter = rightPolygon.constBegin();
1702 for ( ; rightiter != rightPolygon.constEnd(); ++rightiter )
1704 mHalfEdge[actedger]->setNext( ( *rightiter ) );
1705 actedger = ( *( rightiter ) );
1710 mHalfEdge[leftPolygon.first()]->setNext( ( *( ++( leftiter = leftPolygon.constBegin() ) ) ) );
1711 mHalfEdge[leftPolygon.first()]->setPoint( p2 );
1712 mHalfEdge[leftPolygon.last()]->setNext( firstedge );
1713 mHalfEdge[rightPolygon.first()]->setNext( ( *( ++( rightiter = rightPolygon.constBegin() ) ) ) );
1714 mHalfEdge[rightPolygon.first()]->setPoint( p1 );
1715 mHalfEdge[rightPolygon.last()]->setNext( dualfirstedge );
1717 triangulatePolygon( &leftPolygon, &freelist, firstedge );
1718 triangulatePolygon( &rightPolygon, &freelist, dualfirstedge );
1721 for ( iter = crossedEdges.constBegin(); iter != crossedEdges.constEnd(); ++iter )
1723 checkSwapRecursively( ( *( iter ) ), 0 );
1726 return leftPolygon.first();
1731 mForcedCrossBehavior = b;
1736 mTriangleInterpolator = interpolator;
1742 const double minangle = 0;
1746 bool swapped =
false;
1747 bool *control =
new bool[mHalfEdge.count()];
1749 for (
int i = 0; i <= mHalfEdge.count() - 1; i++ )
1755 for (
int i = 0; i <= mHalfEdge.count() - 1; i++ )
1764 e2 = mHalfEdge[e1]->getNext();
1765 e3 = mHalfEdge[e2]->getNext();
1768 p1 = mHalfEdge[e1]->getPoint();
1769 p2 = mHalfEdge[e2]->getPoint();
1770 p3 = mHalfEdge[e3]->getPoint();
1773 if ( p1 == -1 || p2 == -1 || p3 == -1 )
1781 double el1, el2, el3;
1782 el1 = mPointVector[p1]->z();
1783 el2 = mPointVector[p2]->z();
1784 el3 = mPointVector[p3]->z();
1786 if ( el1 == el2 && el2 == el3 )
1789 if ( swapPossible( ( uint ) e1 ) && mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[e1]->getDual()]->getNext()]->getPoint()]->z() != el1 && swapMinAngle( e1 ) > minangle )
1791 doOnlySwap( ( uint ) e1 );
1794 else if ( swapPossible( ( uint ) e2 ) && mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[e2]->getDual()]->getNext()]->getPoint()]->z() != el2 && swapMinAngle( e2 ) > minangle )
1796 doOnlySwap( ( uint ) e2 );
1799 else if ( swapPossible( ( uint ) e3 ) && mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[e3]->getDual()]->getNext()]->getPoint()]->z() != el3 && swapMinAngle( e3 ) > minangle )
1801 doOnlySwap( ( uint ) e3 );
1831 const double mintol = 17;
1834 std::map<int, double> edge_angle;
1835 std::multimap<double, int> angle_edge;
1836 QSet<int> dontexamine;
1845 const int nhalfedges = mHalfEdge.count();
1847 for (
int i = 0; i < nhalfedges - 1; i++ )
1849 const int next = mHalfEdge[i]->getNext();
1850 const int nextnext = mHalfEdge[next]->getNext();
1852 if ( mHalfEdge[next]->getPoint() != -1 && ( mHalfEdge[i]->getForced() || mHalfEdge[mHalfEdge[mHalfEdge[i]->getDual()]->getNext()]->getPoint() == -1 ) )
1854 if ( !( ( mHalfEdge[next]->getForced() || edgeOnConvexHull( next ) ) || ( mHalfEdge[nextnext]->getForced() || edgeOnConvexHull( nextnext ) ) ) )
1857 while (
MathUtils::inDiametral( mPointVector[mHalfEdge[mHalfEdge[i]->getDual()]->getPoint()], mPointVector[mHalfEdge[i]->getPoint()], mPointVector[mHalfEdge[next]->getPoint()] ) )
1860 const int pointno = splitHalfEdge( i, 0.5 );
1872 for (
int i = 0; i < mHalfEdge.count() - 1; i++ )
1874 p1 = mHalfEdge[mHalfEdge[i]->getDual()]->getPoint();
1875 p2 = mHalfEdge[i]->getPoint();
1876 p3 = mHalfEdge[mHalfEdge[i]->getNext()]->getPoint();
1878 if ( p1 == -1 || p2 == -1 || p3 == -1 )
1882 angle =
MathUtils::angle( mPointVector[p1], mPointVector[p2], mPointVector[p3], mPointVector[p2] );
1884 bool twoforcededges;
1887 twoforcededges = ( mHalfEdge[i]->getForced() || edgeOnConvexHull( i ) ) && ( mHalfEdge[mHalfEdge[i]->getNext()]->getForced() || edgeOnConvexHull( mHalfEdge[i]->getNext() ) );
1889 if ( angle < mintol && !twoforcededges )
1891 edge_angle.insert( std::make_pair( i, angle ) );
1892 angle_edge.insert( std::make_pair( angle, i ) );
1897 for ( std::multimap<double, int>::const_iterator it = angle_edge.begin(); it != angle_edge.end(); ++it )
1903 double minangle = 0;
1906 int minedgenextnext;
1910 while ( !edge_angle.empty() )
1912 minangle = angle_edge.begin()->first;
1914 minedge = angle_edge.begin()->second;
1915 minedgenext = mHalfEdge[minedge]->getNext();
1916 minedgenextnext = mHalfEdge[minedgenext]->getNext();
1919 if ( !
MathUtils::circumcenter( mPointVector[mHalfEdge[minedge]->getPoint()], mPointVector[mHalfEdge[minedgenext]->getPoint()], mPointVector[mHalfEdge[minedgenextnext]->getPoint()], &circumcenter ) )
1921 QgsDebugError( QStringLiteral(
"warning, calculation of circumcenter failed" ) );
1923 dontexamine.insert( minedge );
1924 edge_angle.erase( minedge );
1925 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
1926 while ( minedgeiter->second != minedge )
1930 angle_edge.erase( minedgeiter );
1934 if ( !
pointInside( circumcenter.x(), circumcenter.y() ) )
1937 QgsDebugError( QStringLiteral(
"put circumcenter %1//%2 on dontexamine list because it is outside the convex hull" )
1938 .arg( circumcenter.x() )
1939 .arg( circumcenter.y() ) );
1940 dontexamine.insert( minedge );
1941 edge_angle.erase( minedge );
1942 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
1943 while ( minedgeiter->second != minedge )
1947 angle_edge.erase( minedgeiter );
1953 bool encroached =
false;
1956 int numhalfedges = mHalfEdge.count();
1957 for (
int i = 0; i < numhalfedges; i++ )
1959 if ( mHalfEdge[i]->getForced() || edgeOnConvexHull( i ) )
1961 if (
MathUtils::inDiametral( mPointVector[mHalfEdge[i]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[i]->getDual()]->getPoint()], &circumcenter ) )
1966 int pointno = splitHalfEdge( i, 0.5 );
1969 int pointingedge = baseEdgeOfPoint( pointno );
1971 int actedge = pointingedge;
1974 double angle1, angle2, angle3;
1978 ed1 = mHalfEdge[actedge]->getDual();
1979 pt1 = mHalfEdge[ed1]->getPoint();
1980 ed2 = mHalfEdge[ed1]->getNext();
1981 pt2 = mHalfEdge[ed2]->getPoint();
1982 ed3 = mHalfEdge[ed2]->getNext();
1983 pt3 = mHalfEdge[ed3]->getPoint();
1986 if ( pt1 == -1 || pt2 == -1 || pt3 == -1 )
1991 angle1 =
MathUtils::angle( mPointVector[pt3], mPointVector[pt1], mPointVector[pt2], mPointVector[pt1] );
1992 angle2 =
MathUtils::angle( mPointVector[pt1], mPointVector[pt2], mPointVector[pt3], mPointVector[pt2] );
1993 angle3 =
MathUtils::angle( mPointVector[pt2], mPointVector[pt3], mPointVector[pt1], mPointVector[pt3] );
1996 bool twoforcededges1, twoforcededges2, twoforcededges3;
1998 if ( ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) ) && ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) ) )
2000 twoforcededges1 =
true;
2004 twoforcededges1 =
false;
2007 if ( ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) ) && ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) ) )
2009 twoforcededges2 =
true;
2013 twoforcededges2 =
false;
2016 if ( ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) ) && ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) ) )
2018 twoforcededges3 =
true;
2022 twoforcededges3 =
false;
2026 QSet<int>::iterator ed1iter = dontexamine.find( ed1 );
2027 if ( ed1iter != dontexamine.end() )
2030 dontexamine.erase( ed1iter );
2035 std::map<int, double>::iterator tempit1;
2036 tempit1 = edge_angle.find( ed1 );
2037 if ( tempit1 != edge_angle.end() )
2040 double angle = tempit1->second;
2041 edge_angle.erase( ed1 );
2042 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2043 while ( tempit2->second != ed1 )
2047 angle_edge.erase( tempit2 );
2051 if ( angle1 < mintol && !twoforcededges1 )
2053 edge_angle.insert( std::make_pair( ed1, angle1 ) );
2054 angle_edge.insert( std::make_pair( angle1, ed1 ) );
2058 QSet<int>::iterator ed2iter = dontexamine.find( ed2 );
2059 if ( ed2iter != dontexamine.end() )
2062 dontexamine.erase( ed2iter );
2067 std::map<int, double>::iterator tempit1;
2068 tempit1 = edge_angle.find( ed2 );
2069 if ( tempit1 != edge_angle.end() )
2072 double angle = tempit1->second;
2073 edge_angle.erase( ed2 );
2074 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2075 while ( tempit2->second != ed2 )
2079 angle_edge.erase( tempit2 );
2083 if ( angle2 < mintol && !twoforcededges2 )
2085 edge_angle.insert( std::make_pair( ed2, angle2 ) );
2086 angle_edge.insert( std::make_pair( angle2, ed2 ) );
2090 QSet<int>::iterator ed3iter = dontexamine.find( ed3 );
2091 if ( ed3iter != dontexamine.end() )
2094 dontexamine.erase( ed3iter );
2099 std::map<int, double>::iterator tempit1;
2100 tempit1 = edge_angle.find( ed3 );
2101 if ( tempit1 != edge_angle.end() )
2104 double angle = tempit1->second;
2105 edge_angle.erase( ed3 );
2106 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2107 while ( tempit2->second != ed3 )
2111 angle_edge.erase( tempit2 );
2115 if ( angle3 < mintol && !twoforcededges3 )
2117 edge_angle.insert( std::make_pair( ed3, angle3 ) );
2118 angle_edge.insert( std::make_pair( angle3, ed3 ) );
2123 while ( actedge != pointingedge );
2131 QSet<int> influenceedges;
2132 int baseedge = baseEdgeOfTriangle( circumcenter );
2133 if ( baseedge == -5 )
2136 edge_angle.erase( minedge );
2137 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
2138 while ( minedgeiter->second != minedge )
2142 angle_edge.erase( minedgeiter );
2145 else if ( baseedge == -25 )
2148 edge_angle.erase( minedge );
2149 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
2150 while ( minedgeiter->second != minedge )
2154 angle_edge.erase( minedgeiter );
2157 else if ( baseedge == -20 )
2159 baseedge = mEdgeWithPoint;
2162 evaluateInfluenceRegion( &circumcenter, baseedge, influenceedges );
2163 evaluateInfluenceRegion( &circumcenter, mHalfEdge[baseedge]->getNext(), influenceedges );
2164 evaluateInfluenceRegion( &circumcenter, mHalfEdge[mHalfEdge[baseedge]->getNext()]->getNext(), influenceedges );
2166 for ( QSet<int>::iterator it = influenceedges.begin(); it != influenceedges.end(); ++it )
2168 if ( ( mHalfEdge[*it]->getForced() || edgeOnConvexHull( *it ) ) &&
MathUtils::inDiametral( mPointVector[mHalfEdge[*it]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[*it]->getDual()]->getPoint()], &circumcenter ) )
2172 const int pointno = splitHalfEdge( *it, 0.5 );
2176 const int pointingedge = baseEdgeOfPoint( pointno );
2178 int actedge = pointingedge;
2181 double angle1, angle2, angle3;
2185 ed1 = mHalfEdge[actedge]->getDual();
2186 pt1 = mHalfEdge[ed1]->getPoint();
2187 ed2 = mHalfEdge[ed1]->getNext();
2188 pt2 = mHalfEdge[ed2]->getPoint();
2189 ed3 = mHalfEdge[ed2]->getNext();
2190 pt3 = mHalfEdge[ed3]->getPoint();
2193 if ( pt1 == -1 || pt2 == -1 || pt3 == -1 )
2198 angle1 =
MathUtils::angle( mPointVector[pt3], mPointVector[pt1], mPointVector[pt2], mPointVector[pt1] );
2199 angle2 =
MathUtils::angle( mPointVector[pt1], mPointVector[pt2], mPointVector[pt3], mPointVector[pt2] );
2200 angle3 =
MathUtils::angle( mPointVector[pt2], mPointVector[pt3], mPointVector[pt1], mPointVector[pt3] );
2203 bool twoforcededges1, twoforcededges2, twoforcededges3;
2206 twoforcededges1 = ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) ) && ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) );
2208 twoforcededges2 = ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) ) && ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) );
2210 twoforcededges3 = ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) ) && ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) );
2214 const QSet<int>::iterator ed1iter = dontexamine.find( ed1 );
2215 if ( ed1iter != dontexamine.end() )
2218 dontexamine.erase( ed1iter );
2223 std::map<int, double>::iterator tempit1;
2224 tempit1 = edge_angle.find( ed1 );
2225 if ( tempit1 != edge_angle.end() )
2228 const double angle = tempit1->second;
2229 edge_angle.erase( ed1 );
2230 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2231 while ( tempit2->second != ed1 )
2235 angle_edge.erase( tempit2 );
2239 if ( angle1 < mintol && !twoforcededges1 )
2241 edge_angle.insert( std::make_pair( ed1, angle1 ) );
2242 angle_edge.insert( std::make_pair( angle1, ed1 ) );
2246 const QSet<int>::iterator ed2iter = dontexamine.find( ed2 );
2247 if ( ed2iter != dontexamine.end() )
2250 dontexamine.erase( ed2iter );
2255 std::map<int, double>::iterator tempit1;
2256 tempit1 = edge_angle.find( ed2 );
2257 if ( tempit1 != edge_angle.end() )
2260 const double angle = tempit1->second;
2261 edge_angle.erase( ed2 );
2262 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2263 while ( tempit2->second != ed2 )
2267 angle_edge.erase( tempit2 );
2271 if ( angle2 < mintol && !twoforcededges2 )
2273 edge_angle.insert( std::make_pair( ed2, angle2 ) );
2274 angle_edge.insert( std::make_pair( angle2, ed2 ) );
2278 const QSet<int>::iterator ed3iter = dontexamine.find( ed3 );
2279 if ( ed3iter != dontexamine.end() )
2282 dontexamine.erase( ed3iter );
2287 std::map<int, double>::iterator tempit1;
2288 tempit1 = edge_angle.find( ed3 );
2289 if ( tempit1 != edge_angle.end() )
2292 const double angle = tempit1->second;
2293 edge_angle.erase( ed3 );
2294 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2295 while ( tempit2->second != ed3 )
2299 angle_edge.erase( tempit2 );
2303 if ( angle3 < mintol && !twoforcededges3 )
2305 edge_angle.insert( std::make_pair( ed3, angle3 ) );
2306 angle_edge.insert( std::make_pair( angle3, ed3 ) );
2310 }
while ( actedge != pointingedge );
2323 calcPoint( circumcenter.x(), circumcenter.y(), p );
2326 if ( pointno == -100 || pointno == mTwiceInsPoint )
2328 if ( pointno == -100 )
2330 QgsDebugError( QStringLiteral(
"put circumcenter %1//%2 on dontexamine list because of numerical instabilities" )
2331 .arg( circumcenter.x() )
2332 .arg( circumcenter.y() ) );
2334 else if ( pointno == mTwiceInsPoint )
2336 QgsDebugError( QStringLiteral(
"put circumcenter %1//%2 on dontexamine list because it is already inserted" )
2337 .arg( circumcenter.x() )
2338 .arg( circumcenter.y() ) );
2341 for (
int i = 0; i < mPointVector.count(); i++ )
2343 if ( mPointVector[i]->x() == circumcenter.x() && mPointVector[i]->y() == circumcenter.y() )
2350 QgsDebugError( QStringLiteral(
"point is not present in the triangulation" ) );
2354 dontexamine.insert( minedge );
2355 edge_angle.erase( minedge );
2356 std::multimap<double, int>::iterator minedgeiter = angle_edge.lower_bound( minangle );
2357 while ( minedgeiter->second != minedge )
2361 angle_edge.erase( minedgeiter );
2370 const int pointingedge = baseEdgeOfPoint( pointno );
2372 int actedge = pointingedge;
2375 double angle1, angle2, angle3;
2379 ed1 = mHalfEdge[actedge]->getDual();
2380 pt1 = mHalfEdge[ed1]->getPoint();
2381 ed2 = mHalfEdge[ed1]->getNext();
2382 pt2 = mHalfEdge[ed2]->getPoint();
2383 ed3 = mHalfEdge[ed2]->getNext();
2384 pt3 = mHalfEdge[ed3]->getPoint();
2387 if ( pt1 == -1 || pt2 == -1 || pt3 == -1 )
2392 angle1 =
MathUtils::angle( mPointVector[pt3], mPointVector[pt1], mPointVector[pt2], mPointVector[pt1] );
2393 angle2 =
MathUtils::angle( mPointVector[pt1], mPointVector[pt2], mPointVector[pt3], mPointVector[pt2] );
2394 angle3 =
MathUtils::angle( mPointVector[pt2], mPointVector[pt3], mPointVector[pt1], mPointVector[pt3] );
2397 bool twoforcededges1, twoforcededges2, twoforcededges3;
2399 twoforcededges1 = ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) ) && ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) );
2401 twoforcededges2 = ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) ) && ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) );
2403 twoforcededges3 = ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) ) && ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) );
2407 const QSet<int>::iterator ed1iter = dontexamine.find( ed1 );
2408 if ( ed1iter != dontexamine.end() )
2411 dontexamine.erase( ed1iter );
2416 std::map<int, double>::iterator tempit1;
2417 tempit1 = edge_angle.find( ed1 );
2418 if ( tempit1 != edge_angle.end() )
2421 const double angle = tempit1->second;
2422 edge_angle.erase( ed1 );
2423 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2424 while ( tempit2->second != ed1 )
2428 angle_edge.erase( tempit2 );
2432 if ( angle1 < mintol && !twoforcededges1 )
2434 edge_angle.insert( std::make_pair( ed1, angle1 ) );
2435 angle_edge.insert( std::make_pair( angle1, ed1 ) );
2440 const QSet<int>::iterator ed2iter = dontexamine.find( ed2 );
2441 if ( ed2iter != dontexamine.end() )
2444 dontexamine.erase( ed2iter );
2449 std::map<int, double>::iterator tempit1;
2450 tempit1 = edge_angle.find( ed2 );
2451 if ( tempit1 != edge_angle.end() )
2454 const double angle = tempit1->second;
2455 edge_angle.erase( ed2 );
2456 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2457 while ( tempit2->second != ed2 )
2461 angle_edge.erase( tempit2 );
2465 if ( angle2 < mintol && !twoforcededges2 )
2467 edge_angle.insert( std::make_pair( ed2, angle2 ) );
2468 angle_edge.insert( std::make_pair( angle2, ed2 ) );
2472 const QSet<int>::iterator ed3iter = dontexamine.find( ed3 );
2473 if ( ed3iter != dontexamine.end() )
2476 dontexamine.erase( ed3iter );
2481 std::map<int, double>::iterator tempit1;
2482 tempit1 = edge_angle.find( ed3 );
2483 if ( tempit1 != edge_angle.end() )
2486 const double angle = tempit1->second;
2487 edge_angle.erase( ed3 );
2488 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2489 while ( tempit2->second != ed3 )
2493 angle_edge.erase( tempit2 );
2497 if ( angle3 < mintol && !twoforcededges3 )
2499 edge_angle.insert( std::make_pair( ed3, angle3 ) );
2500 angle_edge.insert( std::make_pair( angle3, ed3 ) );
2504 }
while ( actedge != pointingedge );
2510 for ( QSet<int>::iterator it = dontexamine.begin(); it != dontexamine.end(); ++it )
2512 QgsDebugMsgLevel( QStringLiteral(
"edge nr. %1 is in dontexamine" ).arg( *it ), 2 );
2518bool QgsDualEdgeTriangulation::swapPossible(
unsigned int edge )
const
2521 if ( mHalfEdge[edge]->getForced() )
2527 if ( mHalfEdge[edge]->getPoint() == -1 || mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint() == -1 || mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint() == -1 || mHalfEdge[mHalfEdge[edge]->getDual()]->getPoint() == -1 )
2532 QgsPoint *pta = mPointVector[mHalfEdge[edge]->getPoint()];
2533 QgsPoint *ptb = mPointVector[mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint()];
2534 QgsPoint *ptc = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getNext()]->getNext()]->getPoint()];
2535 QgsPoint *ptd = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint()];
2555void QgsDualEdgeTriangulation::triangulatePolygon( QList<int> *poly, QList<int> *free,
int mainedge )
2559 if ( poly->count() == 3 )
2565 QList<int>::const_iterator iterator = ++( poly->constBegin() );
2566 double distance =
MathUtils::distPointFromLine( mPointVector[mHalfEdge[( *iterator )]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[mainedge]->getPoint()] );
2567 int distedge = ( *iterator );
2568 int nextdistedge = mHalfEdge[( *iterator )]->getNext();
2571 while ( iterator != --( poly->constEnd() ) )
2573 if (
MathUtils::distPointFromLine( mPointVector[mHalfEdge[( *iterator )]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[mainedge]->getPoint()] ) < distance )
2575 distedge = ( *iterator );
2576 nextdistedge = mHalfEdge[( *iterator )]->getNext();
2577 distance =
MathUtils::distPointFromLine( mPointVector[mHalfEdge[( *iterator )]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[mainedge]->getPoint()] );
2582 if ( nextdistedge == ( *( --poly->end() ) ) )
2584 const int inserta = free->first();
2585 const int insertb = mHalfEdge[inserta]->getDual();
2588 mHalfEdge[inserta]->setNext( ( poly->at( 1 ) ) );
2589 mHalfEdge[inserta]->setPoint( mHalfEdge[mainedge]->getPoint() );
2590 mHalfEdge[insertb]->setNext( nextdistedge );
2591 mHalfEdge[insertb]->setPoint( mHalfEdge[distedge]->getPoint() );
2592 mHalfEdge[distedge]->setNext( inserta );
2593 mHalfEdge[mainedge]->setNext( insertb );
2596 for ( iterator = ( ++( poly->constBegin() ) ); ( *iterator ) != nextdistedge; ++iterator )
2598 polya.append( ( *iterator ) );
2600 polya.prepend( inserta );
2604 for ( iterator = polya.begin(); iterator != polya.end(); ++iterator )
2610 triangulatePolygon( &polya, free, inserta );
2613 else if ( distedge == ( *( ++poly->begin() ) ) )
2615 const int inserta = free->first();
2616 const int insertb = mHalfEdge[inserta]->getDual();
2619 mHalfEdge[inserta]->setNext( ( poly->at( 2 ) ) );
2620 mHalfEdge[inserta]->setPoint( mHalfEdge[distedge]->getPoint() );
2621 mHalfEdge[insertb]->setNext( mainedge );
2622 mHalfEdge[insertb]->setPoint( mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint() );
2623 mHalfEdge[distedge]->setNext( insertb );
2624 mHalfEdge[( *( --poly->end() ) )]->setNext( inserta );
2627 iterator = poly->constBegin();
2629 while ( iterator != poly->constEnd() )
2631 polya.append( ( *iterator ) );
2634 polya.prepend( inserta );
2636 triangulatePolygon( &polya, free, inserta );
2641 const int inserta = free->first();
2642 const int insertb = mHalfEdge[inserta]->getDual();
2645 const int insertc = free->first();
2646 const int insertd = mHalfEdge[insertc]->getDual();
2649 mHalfEdge[inserta]->setNext( ( poly->at( 1 ) ) );
2650 mHalfEdge[inserta]->setPoint( mHalfEdge[mainedge]->getPoint() );
2651 mHalfEdge[insertb]->setNext( insertd );
2652 mHalfEdge[insertb]->setPoint( mHalfEdge[distedge]->getPoint() );
2653 mHalfEdge[insertc]->setNext( nextdistedge );
2654 mHalfEdge[insertc]->setPoint( mHalfEdge[distedge]->getPoint() );
2655 mHalfEdge[insertd]->setNext( mainedge );
2656 mHalfEdge[insertd]->setPoint( mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint() );
2658 mHalfEdge[distedge]->setNext( inserta );
2659 mHalfEdge[mainedge]->setNext( insertb );
2660 mHalfEdge[( *( --poly->end() ) )]->setNext( insertc );
2666 for ( iterator = ++( poly->constBegin() ); ( *iterator ) != nextdistedge; ++iterator )
2668 polya.append( ( *iterator ) );
2670 polya.prepend( inserta );
2673 while ( iterator != poly->constEnd() )
2675 polyb.append( ( *iterator ) );
2678 polyb.prepend( insertc );
2680 triangulatePolygon( &polya, free, inserta );
2681 triangulatePolygon( &polyb, free, insertc );
2694 unsigned int actedge = mEdgeInside;
2702 if ( runs > MAX_BASE_ITERATIONS )
2704 QgsDebugError( QStringLiteral(
"warning, instability detected: Point coordinates: %1//%2" ).arg( x ).arg( y ) );
2708 if (
MathUtils::leftOf(
point, mPointVector[mHalfEdge[mHalfEdge[actedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[actedge]->getPoint()] ) < ( -
leftOfTresh ) )
2717 else if ( fabs(
MathUtils::leftOf(
point, mPointVector[mHalfEdge[mHalfEdge[actedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[actedge]->getPoint()] ) ) <=
leftOfTresh )
2720 mEdgeWithPoint = actedge;
2730 actedge = mHalfEdge[actedge]->getDual();
2736 actedge = mHalfEdge[actedge]->getNext();
2737 if ( mHalfEdge[actedge]->getPoint() == -1 )
2743 mEdgeOutside = (
unsigned int ) mHalfEdge[mHalfEdge[actedge]->getNext()]->getNext();
2753 if ( numinstabs > 0 )
2755 QgsDebugError( QStringLiteral(
"numerical instabilities" ) );
2763 mEdgeInside = actedge;
2768bool DualEdgeTriangulation::readFromTAFF( QString filename )
2770 QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
2772 QFile file( filename );
2773 file.open( IO_Raw | IO_ReadOnly );
2774 QBuffer buffer( file.readAll() );
2777 QTextStream textstream( &buffer );
2778 buffer.open( IO_ReadOnly );
2781 int numberofhalfedges;
2785 while ( buff.mid( 0, 4 ) !=
"TRIA" )
2787 buff = textstream.readLine();
2789 while ( buff.mid( 0, 4 ) !=
"NEDG" )
2791 buff = textstream.readLine();
2793 numberofhalfedges = buff.section(
' ', 1, 1 ).toInt();
2794 mHalfEdge.resize( numberofhalfedges );
2797 while ( buff.mid( 0, 4 ) !=
"DATA" )
2802 int nr1, nr2, dual1, dual2, point1, point2, next1, next2, fo1, fo2, b1, b2;
2803 bool forced1, forced2, break1, break2;
2807 QProgressBar *edgebar =
new QProgressBar();
2808 edgebar->setCaption( tr(
"Reading edges…" ) );
2809 edgebar->setTotalSteps( numberofhalfedges / 2 );
2810 edgebar->setMinimumWidth( 400 );
2811 edgebar->move( 500, 500 );
2814 for (
int i = 0; i < numberofhalfedges / 2; i++ )
2816 if ( i % 1000 == 0 )
2818 edgebar->setProgress( i );
2822 textstream >> point1;
2823 textstream >> next1;
2847 textstream >> point2;
2848 textstream >> next2;
2886 mHalfEdge.insert( nr1, hf1 );
2887 mHalfEdge.insert( nr2, hf2 );
2891 edgebar->setProgress( numberofhalfedges / 2 );
2895 for (
int i = 0; i < numberofhalfedges; i++ )
2898 a = mHalfEdge[i]->getPoint();
2899 b = mHalfEdge[mHalfEdge[i]->getDual()]->getPoint();
2900 c = mHalfEdge[mHalfEdge[i]->getNext()]->getPoint();
2901 d = mHalfEdge[mHalfEdge[mHalfEdge[i]->getDual()]->getNext()]->getPoint();
2902 if ( a != -1 && b != -1 &&
c != -1 && d != -1 )
2910 while ( buff.mid( 0, 4 ) !=
"POIN" )
2912 buff = textstream.readLine();
2915 while ( buff.mid( 0, 4 ) !=
"NPTS" )
2917 buff = textstream.readLine();
2920 numberofpoints = buff.section(
' ', 1, 1 ).toInt();
2921 mPointVector.resize( numberofpoints );
2923 while ( buff.mid( 0, 4 ) !=
"DATA" )
2928 QProgressBar *pointbar =
new QProgressBar();
2929 pointbar->setCaption( tr(
"Reading points…" ) );
2930 pointbar->setTotalSteps( numberofpoints );
2931 pointbar->setMinimumWidth( 400 );
2932 pointbar->move( 500, 500 );
2937 for (
int i = 0; i < numberofpoints; i++ )
2939 if ( i % 1000 == 0 )
2941 pointbar->setProgress( i );
2951 mPointVector.insert( i, p );
2967 else if ( x > xMax )
2976 else if ( y > yMax )
2983 pointbar->setProgress( numberofpoints );
2985 QApplication::restoreOverrideCursor();
2989bool DualEdgeTriangulation::saveToTAFF( QString filename )
const
2991 QFile outputfile( filename );
2992 if ( !outputfile.open( IO_WriteOnly ) )
2994 QMessageBox::warning( 0, tr(
"Warning" ), tr(
"File could not be written." ), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton );
2998 QTextStream outstream( &outputfile );
2999 outstream.precision( 9 );
3002 outstream <<
"TRIA" << std::endl << std::flush;
3003 outstream <<
"NEDG " << mHalfEdge.count() << std::endl << std::flush;
3004 outstream <<
"PANO 1" << std::endl << std::flush;
3005 outstream <<
"DATA ";
3007 bool *cont =
new bool[mHalfEdge.count()];
3008 for (
unsigned int i = 0; i <= mHalfEdge.count() - 1; i++ )
3013 for (
unsigned int i = 0; i < mHalfEdge.count(); i++ )
3020 int dual = mHalfEdge[i]->getDual();
3021 outstream << i <<
" " << mHalfEdge[i]->getPoint() <<
" " << mHalfEdge[i]->getNext() <<
" " << mHalfEdge[i]->getForced() <<
" " << mHalfEdge[i]->getBreak() <<
" ";
3022 outstream << dual <<
" " << mHalfEdge[dual]->getPoint() <<
" " << mHalfEdge[dual]->getNext() <<
" " << mHalfEdge[dual]->getForced() <<
" " << mHalfEdge[dual]->getBreak() <<
" ";
3026 outstream << std::endl << std::flush;
3027 outstream << std::endl << std::flush;
3032 outstream <<
"POIN" << std::endl << std::flush;
3033 outstream <<
"NPTS " << getNumberOfPoints() << std::endl << std::flush;
3034 outstream <<
"PATT 3" << std::endl << std::flush;
3035 outstream <<
"DATA ";
3037 for (
int i = 0; i < getNumberOfPoints(); i++ )
3040 outstream << p->getX() <<
" " << p->getY() <<
" " << p->getZ() <<
" ";
3042 outstream << std::endl << std::flush;
3043 outstream << std::endl << std::flush;
3052 const int edge1 = baseEdgeOfTriangle( p );
3059 edge2 = mHalfEdge[edge1]->getNext();
3060 edge3 = mHalfEdge[edge2]->getNext();
3061 point1 =
point( mHalfEdge[edge1]->getPoint() );
3062 point2 =
point( mHalfEdge[edge2]->getPoint() );
3063 point3 =
point( mHalfEdge[edge3]->getPoint() );
3064 if ( point1 && point2 && point3 )
3067 double dist1, dist2, dist3;
3071 if ( dist1 <= dist2 && dist1 <= dist3 )
3074 if ( swapPossible( edge1 ) )
3076 doOnlySwap( edge1 );
3079 else if ( dist2 <= dist1 && dist2 <= dist3 )
3082 if ( swapPossible( edge2 ) )
3084 doOnlySwap( edge2 );
3087 else if ( dist3 <= dist1 && dist3 <= dist2 )
3090 if ( swapPossible( edge3 ) )
3092 doOnlySwap( edge3 );
3114 const int edge1 = baseEdgeOfTriangle( p );
3117 const int edge2 = mHalfEdge[edge1]->getNext();
3118 const int edge3 = mHalfEdge[edge2]->getNext();
3122 if ( point1 && point2 && point3 )
3128 if ( dist1 <= dist2 && dist1 <= dist3 )
3130 p1 = mHalfEdge[edge1]->getPoint();
3131 p2 = mHalfEdge[mHalfEdge[edge1]->getNext()]->getPoint();
3132 p3 = mHalfEdge[mHalfEdge[edge1]->getDual()]->getPoint();
3133 p4 = mHalfEdge[mHalfEdge[mHalfEdge[edge1]->getDual()]->getNext()]->getPoint();
3135 else if ( dist2 <= dist1 && dist2 <= dist3 )
3137 p1 = mHalfEdge[edge2]->getPoint();
3138 p2 = mHalfEdge[mHalfEdge[edge2]->getNext()]->getPoint();
3139 p3 = mHalfEdge[mHalfEdge[edge2]->getDual()]->getPoint();
3140 p4 = mHalfEdge[mHalfEdge[mHalfEdge[edge2]->getDual()]->getNext()]->getPoint();
3144 p1 = mHalfEdge[edge3]->getPoint();
3145 p2 = mHalfEdge[mHalfEdge[edge3]->getNext()]->getPoint();
3146 p3 = mHalfEdge[mHalfEdge[edge3]->getDual()]->getPoint();
3147 p4 = mHalfEdge[mHalfEdge[mHalfEdge[edge3]->getDual()]->getNext()]->getPoint();
3175 bool *alreadyVisitedEdges =
new bool[mHalfEdge.size()];
3176 if ( !alreadyVisitedEdges )
3182 for (
int i = 0; i < mHalfEdge.size(); ++i )
3184 alreadyVisitedEdges[i] =
false;
3187 for (
int i = 0; i < mHalfEdge.size(); ++i )
3192 HalfEdge *currentEdge = mHalfEdge[i];
3193 if ( currentEdge->
getPoint() != -1 && mHalfEdge[currentEdge->
getDual()]->getPoint() != -1 && !alreadyVisitedEdges[currentEdge->
getDual()] )
3199 QgsPoint *p2 = mPointVector[mHalfEdge[currentEdge->
getDual()]->getPoint()];
3207 QString attributeString;
3212 attributeString = QStringLiteral(
"break line" );
3216 attributeString = QStringLiteral(
"structure line" );
3223 alreadyVisitedEdges[i] =
true;
3226 delete[] alreadyVisitedEdges;
3236 QVector<bool> edgeToTreat( mHalfEdge.count(),
true );
3237 QHash<HalfEdge *, int> edgesHash;
3238 for (
int i = 0; i < mHalfEdge.count(); ++i )
3240 edgesHash.insert( mHalfEdge[i], i );
3249 const int edgeCount = edgeToTreat.count();
3250 for (
int i = 0; i < edgeCount; ++i )
3252 bool containVirtualPoint =
false;
3253 if ( edgeToTreat[i] )
3255 HalfEdge *currentEdge = mHalfEdge[i];
3260 edgeToTreat[edgesHash.value( currentEdge )] =
false;
3261 face.append( currentEdge->
getPoint() );
3262 containVirtualPoint |= currentEdge->
getPoint() == -1;
3263 currentEdge = mHalfEdge.at( currentEdge->
getNext() );
3264 }
while ( currentEdge != firstEdge && !containVirtualPoint && ( !feedback || !feedback->
isCanceled() ) );
3265 if ( !containVirtualPoint )
3266 mesh.
faces.append( face );
3277double QgsDualEdgeTriangulation::swapMinAngle(
int edge )
const
3280 QgsPoint *p2 =
point( mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint() );
3281 QgsPoint *p3 =
point( mHalfEdge[mHalfEdge[edge]->getDual()]->getPoint() );
3282 QgsPoint *p4 =
point( mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint() );
3289 if ( angle2 < minangle )
3294 if ( angle3 < minangle )
3299 if ( angle4 < minangle )
3304 if ( angle5 < minangle )
3309 if ( angle6 < minangle )
3317int QgsDualEdgeTriangulation::splitHalfEdge(
int edge,
float position )
3320 if ( position < 0 || position > 1 )
3322 QgsDebugError( QStringLiteral(
"warning, position is not between 0 and 1" ) );
3326 QgsPoint *p =
new QgsPoint( mPointVector[mHalfEdge[edge]->getPoint()]->x() * position + mPointVector[mHalfEdge[mHalfEdge[edge]->getDual()]->getPoint()]->x() * ( 1 - position ), mPointVector[mHalfEdge[edge]->getPoint()]->y() * position + mPointVector[mHalfEdge[mHalfEdge[edge]->getDual()]->getPoint()]->y() * ( 1 - position ), 0 );
3331 p->
setZ( zvaluepoint.z() );
3334 if ( mPointVector.count() >= mPointVector.size() )
3336 mPointVector.resize( mPointVector.count() + 1 );
3338 QgsDebugMsgLevel( QStringLiteral(
"inserting point nr. %1, %2//%3//%4" ).arg( mPointVector.count() ).arg( p->
x() ).arg( p->
y() ).arg( p->
z() ), 2 );
3339 mPointVector.insert( mPointVector.count(), p );
3342 const int dualedge = mHalfEdge[edge]->getDual();
3343 const int edge1 = insertEdge( -10, -10, mPointVector.count() - 1,
false,
false );
3344 const int edge2 = insertEdge( edge1, mHalfEdge[mHalfEdge[edge]->getNext()]->getNext(), mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint(),
false,
false );
3345 const int edge3 = insertEdge( -10, mHalfEdge[mHalfEdge[dualedge]->getNext()]->getNext(), mHalfEdge[mHalfEdge[dualedge]->getNext()]->getPoint(),
false,
false );
3346 const int edge4 = insertEdge( edge3, dualedge, mPointVector.count() - 1,
false,
false );
3347 const int edge5 = insertEdge( -10, mHalfEdge[edge]->getNext(), mHalfEdge[edge]->getPoint(), mHalfEdge[edge]->getBreak(), mHalfEdge[edge]->getForced() );
3348 const int edge6 = insertEdge( edge5, edge3, mPointVector.count() - 1, mHalfEdge[dualedge]->getBreak(), mHalfEdge[dualedge]->getForced() );
3349 mHalfEdge[edge1]->setDual( edge2 );
3350 mHalfEdge[edge1]->setNext( edge5 );
3351 mHalfEdge[edge3]->setDual( edge4 );
3352 mHalfEdge[edge5]->setDual( edge6 );
3355 mHalfEdge[mHalfEdge[edge]->getNext()]->setNext( edge1 );
3356 mHalfEdge[mHalfEdge[dualedge]->getNext()]->setNext( edge4 );
3357 mHalfEdge[edge]->setNext( edge2 );
3358 mHalfEdge[edge]->setPoint( mPointVector.count() - 1 );
3359 mHalfEdge[mHalfEdge[edge3]->getNext()]->setNext( edge6 );
3362 checkSwapRecursively( mHalfEdge[edge5]->getNext(), 0 );
3363 checkSwapRecursively( mHalfEdge[edge2]->getNext(), 0 );
3364 checkSwapRecursively( mHalfEdge[dualedge]->getNext(), 0 );
3365 checkSwapRecursively( mHalfEdge[edge3]->getNext(), 0 );
3369 return mPointVector.count() - 1;
3372bool QgsDualEdgeTriangulation::edgeOnConvexHull(
int edge )
3374 return ( mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint() == -1 || mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint() == -1 );
3377void QgsDualEdgeTriangulation::evaluateInfluenceRegion(
QgsPoint *point,
int edge, QSet<int> &set )
3379 if ( set.find( edge ) == set.end() )
3388 if ( !mHalfEdge[edge]->getForced() && !edgeOnConvexHull( edge ) )
3391 if (
inCircle( *
point, *mPointVector[mHalfEdge[mHalfEdge[edge]->getDual()]->getPoint()], *mPointVector[mHalfEdge[edge]->getPoint()], *mPointVector[mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint()] ) )
3393 evaluateInfluenceRegion(
point, mHalfEdge[mHalfEdge[edge]->getDual()]->getNext(), set );
3394 evaluateInfluenceRegion(
point, mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getNext(), set );
3399int QgsDualEdgeTriangulation::firstEdgeOutSide()
3402 while ( ( mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint() != -1 || mHalfEdge[edge]->getPoint() == -1 || mHalfEdge[mHalfEdge[edge]->getDual()]->getPoint() == -1 ) && edge < mHalfEdge.count() )
3407 if ( edge >= mHalfEdge.count() )
3413void QgsDualEdgeTriangulation::removeLastPoint()
3415 if ( mPointVector.isEmpty() )
3417 QgsPoint *p = mPointVector.takeLast();
bool getForced() const
Returns, whether the HalfEdge belongs to a constrained edge or not.
int getNext() const
Returns the number of the next HalfEdge.
void setNext(int n)
Sets the number of the next HalfEdge.
void setPoint(int p)
Sets the number of point at which this HalfEdge points.
int getPoint() const
Returns the number of the point at which this HalfEdge points.
int getDual() const
Returns the number of the dual HalfEdge.
void setDual(int d)
Sets the number of the dual HalfEdge.
void setForced(bool f)
Sets the forced flag.
bool getBreak() const
Returns, whether the HalfEdge belongs to a break line or not.
void setBreak(bool b)
Sets the break flag.
bool saveTriangulation(QgsFeatureSink *sink, QgsFeedback *feedback=nullptr) const override
Saves the triangulation features to a feature sink.
QgsPoint * point(int i) const override
Draws the points, edges and the forced lines.
QList< int > surroundingTriangles(int pointno) override
Returns a value list with the information of the triangles surrounding (counterclockwise) a point.
void ruppertRefinement() override
Adds points to make the triangles better shaped (algorithm of ruppert)
bool pointInside(double x, double y) override
Returns true, if the point with coordinates x and y is inside the convex hull and false otherwise.
void setTriangleInterpolator(TriangleInterpolator *interpolator) override
Sets an interpolator object.
void performConsistencyTest() override
Performs a consistency check, remove this later.
int oppositePoint(int p1, int p2) override
Returns the number of the point opposite to the triangle points p1, p2 (which have to be on a halfedg...
int addPoint(const QgsPoint &p) override
Adds a point to the triangulation.
virtual QgsMesh triangulationToMesh(QgsFeedback *feedback=nullptr) const override
Returns a QgsMesh corresponding to the triangulation.
void setForcedCrossBehavior(QgsTriangulation::ForcedCrossBehavior b) override
Sets the behavior of the triangulation in case of crossing forced lines.
bool calcNormal(double x, double y, QgsPoint &result) override
Calculates the normal at a point on the surface.
void addLine(const QVector< QgsPoint > &points, QgsInterpolator::SourceType lineType) override
Adds a line (e.g.
bool calcPoint(double x, double y, QgsPoint &result) override
Calculates x-, y and z-value of the point on the surface and assigns it to 'result'.
void eliminateHorizontalTriangles() override
Eliminates the horizontal triangles by swapping or by insertion of new points.
bool triangleVertices(double x, double y, QgsPoint &p1, int &n1, QgsPoint &p2, int &n2, QgsPoint &p3, int &n3) override
Finds out in which triangle the point with coordinates x and y is and assigns the numbers of the vert...
~QgsDualEdgeTriangulation() override
bool swapEdge(double x, double y) override
Swaps the edge which is closest to the point with x and y coordinates (if this is possible)
QList< int > pointsAroundEdge(double x, double y) override
Returns a value list with the numbers of the four points, which would be affected by an edge swap....
An interface for objects which accept features via addFeature(s) methods.
virtual bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags())
Adds a single feature to the sink.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Q_INVOKABLE bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
SourceType
Describes the type of input data.
@ SourceBreakLines
Break lines.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
void setY(double y)
Sets the point's y-coordinate.
void setX(double x)
Sets the point's x-coordinate.
double distance(double x, double y) const
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
void setZ(double z)
Sets the point's z-coordinate.
double distanceSquared(double x, double y) const
Returns the Cartesian 2D squared distance between this point a specified x, y coordinate.
ForcedCrossBehavior
Enumeration describing the behavior, if two forced lines cross.
@ SnappingTypeVertex
The second inserted forced line is snapped to the closest vertice of the first inserted forced line.
This is an interface for interpolator classes for triangulations.
virtual bool calcNormVec(double x, double y, QgsPoint &result)=0
Calculates the normal vector and assigns it to vec.
virtual bool calcPoint(double x, double y, QgsPoint &result)=0
Performs a linear interpolation in a triangle and assigns the x-,y- and z-coordinates to point.
bool ANALYSIS_EXPORT inDiametral(QgsPoint *p1, QgsPoint *p2, QgsPoint *point)
Tests, whether 'point' is inside the diametral circle through 'p1' and 'p2'.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
bool ANALYSIS_EXPORT lineIntersection(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Returns true, if line1 (p1 to p2) and line2 (p3 to p4) intersect. If the lines have an endpoint in co...
bool ANALYSIS_EXPORT circumcenter(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *result)
Calculates the center of the circle passing through p1, p2 and p3. Returns true in case of success an...
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'. Negative values mean left ...
double ANALYSIS_EXPORT distPointFromLine(QgsPoint *thepoint, QgsPoint *p1, QgsPoint *p2)
Calculates the (2 dimensional) distance from 'thepoint' to the line defined by p1 and p2.
bool ANALYSIS_EXPORT inCircle(QgsPoint *testp, QgsPoint *p1, QgsPoint *p2, QgsPoint *p3)
Tests, whether 'testp' is inside the circle through 'p1', 'p2' and 'p3'.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QVector< int > QgsMeshFace
List of vertex indexes.
Mesh - vertices, edges and faces.
QVector< QgsMeshVertex > vertices
QVector< QgsMeshFace > faces