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() );
53 if ( !mPointVector.isEmpty() )
55 for (
int i = 0; i < mPointVector.count(); i++ )
57 delete mPointVector[i];
62 if ( !mHalfEdge.isEmpty() )
64 for (
int i = 0; i < mHalfEdge.count(); i++ )
73 QgsDebugMsg( QStringLiteral(
"performing consistency test" ) );
75 for (
int i = 0; i < mHalfEdge.count(); i++ )
77 const int a = mHalfEdge[mHalfEdge[i]->getDual()]->getDual();
78 const int b = mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getNext();
81 QgsDebugMsg( QStringLiteral(
"warning, first test failed" ) );
85 QgsDebugMsg( QStringLiteral(
"warning, second test failed" ) );
88 QgsDebugMsg( QStringLiteral(
"consistency test finished" ) );
94 int currentpoint = -10;
101 if ( actpoint != -100 )
107 if ( actpoint == -100 )
112 for ( ; i < points.size(); ++i )
114 currentpoint =
addPoint( points.at( i ) );
115 if ( currentpoint != -100 && actpoint != -100 && currentpoint != actpoint )
117 insertForcedSegment( actpoint, currentpoint, lineType );
119 actpoint = currentpoint;
126 if ( mPointVector.isEmpty() )
135 mXMin = std::min( p.
x(), mXMin );
136 mXMax = std::max( p.
x(), mXMax );
137 mYMin = std::min( p.
y(), mYMin );
138 mYMax = std::max( p.
y(), mYMax );
142 mPointVector.append(
new QgsPoint( p ) );
145 if ( mDimension == -1 )
147 const unsigned int zedge = insertEdge( -10, -10, -1,
false,
false );
148 const unsigned int fedge = insertEdge(
static_cast<int>( zedge ),
static_cast<int>( zedge ), 0,
false,
false );
149 ( mHalfEdge.at( zedge ) )->setDual(
static_cast<int>( fedge ) );
150 ( mHalfEdge.at( zedge ) )->setNext(
static_cast<int>( fedge ) );
153 else if ( mDimension == 0 )
156 if ( p.
x() == mPointVector[0]->x() && p.
y() == mPointVector[0]->y() )
163 const unsigned int edgeFromPoint0ToPoint1 = insertEdge( -10, -10, 1,
false,
false );
164 const unsigned int edgeFromPoint1ToPoint0 = insertEdge( edgeFromPoint0ToPoint1, -10, 0,
false,
false );
165 const unsigned int edgeFromVirtualToPoint1Side1 = insertEdge( -10, -10, 1,
false,
false );
166 const unsigned int edgeFromPoint1ToVirtualSide1 = insertEdge( edgeFromVirtualToPoint1Side1, 1, -1,
false,
false );
167 const unsigned int edgeFromVirtualToPoint1Side2 = insertEdge( -10, edgeFromPoint1ToPoint0, 1,
false,
false );
168 const unsigned int edgeFromPoint1ToVirtualSide2 = insertEdge( edgeFromVirtualToPoint1Side2, edgeFromVirtualToPoint1Side1, -1,
false,
false );
169 const unsigned int edgeFromVirtualToPoint0Side2 = insertEdge( -10, -10, 0,
false,
false );
170 const unsigned int edgeFromPoint0ToVirtualSide2 = insertEdge( edgeFromVirtualToPoint0Side2, edgeFromVirtualToPoint1Side2, -1,
false,
false );
171 mHalfEdge.at( edgeFromPoint1ToPoint0 )->setNext( edgeFromPoint0ToVirtualSide2 );
172 mHalfEdge.at( edgeFromPoint0ToPoint1 )->setDual( edgeFromPoint1ToPoint0 );
173 mHalfEdge.at( edgeFromPoint0ToPoint1 )->setNext( edgeFromPoint1ToVirtualSide1 );
174 mHalfEdge.at( edgeFromVirtualToPoint1Side1 )->setDual( edgeFromPoint1ToVirtualSide1 );
175 mHalfEdge.at( edgeFromVirtualToPoint1Side1 )->setNext( edgeFromPoint1ToVirtualSide2 );
176 mHalfEdge.at( 0 )->setNext(
static_cast<int>( edgeFromVirtualToPoint0Side2 ) );
177 mHalfEdge.at( 1 )->setNext(
static_cast<int>( edgeFromPoint0ToPoint1 ) );
178 mHalfEdge.at( edgeFromVirtualToPoint1Side2 )->setDual( edgeFromPoint1ToVirtualSide2 );
179 mHalfEdge.at( edgeFromVirtualToPoint0Side2 )->setDual( edgeFromPoint0ToVirtualSide2 );
180 mHalfEdge.at( edgeFromVirtualToPoint0Side2 )->setNext( 0 );
182 mEdgeOutside = edgeFromPoint0ToPoint1;
185 else if ( mDimension == 1 )
187 if ( mEdgeOutside < 0 || mHalfEdge[mEdgeOutside]->getPoint() < 0 || mHalfEdge[mHalfEdge[mEdgeOutside]->getDual()]->getPoint() < 0 )
188 mEdgeOutside = firstEdgeOutSide();
189 if ( mEdgeOutside < 0 || mHalfEdge[mEdgeOutside]->getPoint() < 0 || mHalfEdge[mHalfEdge[mEdgeOutside]->getDual()]->getPoint() < 0 )
192 const double leftOfNumber =
MathUtils::leftOf( p, mPointVector[mHalfEdge[mHalfEdge[mEdgeOutside]->getDual()]->getPoint()], mPointVector[mHalfEdge[mEdgeOutside]->getPoint()] );
198 int closestEdge = -1;
199 double distance = std::numeric_limits<double>::max();
200 const int firstEdge = mEdgeOutside;
203 const int point1 = mHalfEdge[mEdgeOutside]->getPoint();
204 const int point2 = mHalfEdge[mHalfEdge[mEdgeOutside]->getDual()]->getPoint();
205 const double distance1 = p.
distance( *mPointVector[point1] );
211 const double distance2 = p.
distance( *mPointVector[point2] );
218 const double edgeLength = mPointVector[point1]->distance( *mPointVector[point2] );
220 if ( distance1 < edgeLength && distance2 < edgeLength )
223 const int newPoint = mPointVector.count() - 1;
226 const int edgeFromNewPointToPoint1 = mEdgeOutside;
227 const int edgeFromNewPointToPoint2 = mHalfEdge[mEdgeOutside]->getDual();
229 const int edgeFromPoint1ToVirtualSide2 = mHalfEdge[edgeFromNewPointToPoint1]->getNext();
230 const int edgeFromVirtualToPoint1Side1 = mHalfEdge[mHalfEdge[edgeFromNewPointToPoint2]->getNext()]->getNext();
231 const int edgeFromPoint2ToVirtualSide1 = mHalfEdge[edgeFromNewPointToPoint2]->getNext();
232 const int edgeFromVirtualToPoint2Side2 = mHalfEdge[mHalfEdge[edgeFromNewPointToPoint1]->getNext()]->getNext();
234 const int edgeFromVirtualToNewPointSide1 = insertEdge( -10, edgeFromNewPointToPoint2, newPoint,
false,
false );
235 const int edgeFromNewPointToVirtualSide1 = insertEdge( edgeFromVirtualToNewPointSide1, edgeFromVirtualToPoint1Side1, -1,
false,
false );
236 const int edgeFromVirtualToNewPointSide2 = insertEdge( -10, edgeFromNewPointToPoint1, newPoint,
false,
false );
237 const int edgeFromNewPointToVirtualSide2 = insertEdge( edgeFromVirtualToNewPointSide2, edgeFromVirtualToPoint2Side2, -1,
false,
false );
238 const int edgeFromPoint1ToNewPoint = insertEdge( edgeFromNewPointToPoint1, edgeFromNewPointToVirtualSide1, newPoint,
false,
false );
239 const int edgeFromPoint2ToNewPoint = insertEdge( edgeFromNewPointToPoint2, edgeFromNewPointToVirtualSide2, newPoint,
false,
false );
240 mHalfEdge.at( edgeFromVirtualToNewPointSide1 )->setDual( edgeFromNewPointToVirtualSide1 );
241 mHalfEdge.at( edgeFromVirtualToNewPointSide2 )->setDual( edgeFromNewPointToVirtualSide2 );
243 mHalfEdge.at( edgeFromPoint1ToVirtualSide2 )->setNext( edgeFromVirtualToNewPointSide2 );
244 mHalfEdge.at( edgeFromVirtualToPoint1Side1 )->setNext( edgeFromPoint1ToNewPoint );
245 mHalfEdge.at( edgeFromPoint2ToVirtualSide1 )->setNext( edgeFromVirtualToNewPointSide1 );
246 mHalfEdge.at( edgeFromVirtualToPoint2Side2 )->setNext( edgeFromPoint2ToNewPoint );
247 mHalfEdge.at( edgeFromNewPointToPoint1 )->setDual( edgeFromPoint1ToNewPoint );
248 mHalfEdge.at( edgeFromNewPointToPoint2 )->setDual( edgeFromPoint2ToNewPoint );
253 if ( distance1 < distance )
255 closestEdge = mEdgeOutside;
256 distance = distance1;
258 else if ( distance2 < distance )
260 closestEdge = mHalfEdge[mEdgeOutside]->getDual();
261 distance = distance2;
264 mEdgeOutside = mHalfEdge[mHalfEdge[mHalfEdge[mEdgeOutside]->getNext()]->getDual()]->getNext();
266 while ( mEdgeOutside != firstEdge && mHalfEdge[mEdgeOutside]->getPoint() != -1 && mHalfEdge[mHalfEdge[mEdgeOutside]->getDual()]->getPoint() != -1 );
268 if ( closestEdge < 0 )
272 const int extremPoint = mHalfEdge[closestEdge]->getPoint();
273 const int newPoint = mPointVector.count() - 1;
275 const int edgeFromExtremeToOpposite = mHalfEdge[closestEdge]->getDual();
277 const int edgeFromVirtualToExtremeSide1 = mHalfEdge[mHalfEdge[closestEdge]->getNext()]->getDual();
278 const int edgeFromVirtualToExtremeSide2 = mHalfEdge[mHalfEdge[mHalfEdge[closestEdge]->getDual()]->getNext()]->getNext();
279 const int edgeFromExtremeToVirtualSide2 = mHalfEdge[edgeFromVirtualToExtremeSide2]->getDual();
281 const int edgeFromExtremeToNewPoint = insertEdge( -10, -10, newPoint,
false,
false );
282 const int edgeFromNewPointToExtrem = insertEdge( edgeFromExtremeToNewPoint, edgeFromExtremeToVirtualSide2, extremPoint,
false,
false );
283 const int edgeFromNewPointToVirtualSide1 = insertEdge( -10, edgeFromVirtualToExtremeSide1, -1,
false,
false );
284 const int edgeFromVirtualToNewPointSide1 = insertEdge( edgeFromNewPointToVirtualSide1, -10, newPoint,
false,
false );
285 const int edgeFromNewPointToVirtualSide2 = insertEdge( -10, edgeFromVirtualToNewPointSide1, -1,
false,
false );
286 const int edgeFromVirtualToNewPointSide2 = insertEdge( edgeFromNewPointToVirtualSide2, edgeFromNewPointToExtrem, newPoint,
false,
false );
287 mHalfEdge.at( edgeFromExtremeToNewPoint )->setDual( edgeFromNewPointToExtrem );
288 mHalfEdge.at( edgeFromExtremeToNewPoint )->setNext( edgeFromNewPointToVirtualSide1 );
289 mHalfEdge.at( edgeFromNewPointToVirtualSide1 )->setDual( edgeFromVirtualToNewPointSide1 );
290 mHalfEdge.at( edgeFromNewPointToVirtualSide2 )->setDual( edgeFromVirtualToNewPointSide2 );
291 mHalfEdge.at( edgeFromVirtualToNewPointSide1 )->setNext( edgeFromNewPointToVirtualSide2 );
293 mHalfEdge.at( edgeFromVirtualToExtremeSide1 )->setNext( edgeFromExtremeToNewPoint );
294 mHalfEdge.at( edgeFromVirtualToExtremeSide2 )->setNext( edgeFromExtremeToOpposite );
295 mHalfEdge.at( edgeFromExtremeToVirtualSide2 )->setNext( edgeFromVirtualToNewPointSide2 );
302 mEdgeOutside = mHalfEdge[mEdgeOutside]->getDual();
305 const int newPoint = mPointVector.count() - 1;
308 int cwEdge = mEdgeOutside;
309 while ( mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext()]->getPoint() != -1 )
311 mHalfEdge[mHalfEdge[ cwEdge ]->getNext()]->setPoint( newPoint );
312 cwEdge = mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext();
315 const int edgeFromLastCwPointToVirtualPoint = mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext();
316 const int edgeFromLastCwPointToNewPointPoint = mHalfEdge[ cwEdge ]->getNext();
317 const int edgeFromNewPointPointToLastCwPoint = mHalfEdge[ edgeFromLastCwPointToNewPointPoint ]->getDual();
319 const int edgeFromNewPointtoVirtualPoint = insertEdge( -10, -10, -1,
false,
false );
320 const int edgeFromVirtualPointToNewPoint = insertEdge( edgeFromNewPointtoVirtualPoint, edgeFromNewPointPointToLastCwPoint, newPoint,
false,
false );
321 mHalfEdge.at( edgeFromLastCwPointToNewPointPoint )->setPoint( newPoint );
322 mHalfEdge.at( edgeFromNewPointtoVirtualPoint )->setDual( edgeFromVirtualPointToNewPoint );
323 mHalfEdge.at( edgeFromLastCwPointToVirtualPoint )->setNext( edgeFromVirtualPointToNewPoint );
326 int ccwEdge = mEdgeOutside;
327 while ( mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getDual()]->getNext()]->getDual()]->getNext()]->getPoint() != -1 )
329 mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ ccwEdge ]->getNext()]->getNext()]->getDual()]->setPoint( newPoint );
330 ccwEdge = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getDual()]->getNext()]->getDual()]->getNext()]->getDual();
333 const int edgeToLastCcwPoint = mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getDual()]->getNext()]->getDual();
334 const int edgeFromLastCcwPointToNewPoint = mHalfEdge[edgeToLastCcwPoint]->getNext();
335 mHalfEdge.at( edgeFromNewPointtoVirtualPoint )->setNext( edgeToLastCcwPoint );
336 mHalfEdge.at( edgeFromLastCcwPointToNewPoint )->setNext( edgeFromNewPointtoVirtualPoint );
337 mHalfEdge.at( edgeFromLastCcwPointToNewPoint )->setPoint( newPoint );
341 const int number = baseEdgeOfTriangle( p );
346 unsigned int cwEdge = mEdgeOutside;
347 unsigned int ccwEdge = mEdgeOutside;
350 mHalfEdge[mHalfEdge[mEdgeOutside]->getNext()]->setPoint( mPointVector.count() - 1 );
353 while (
MathUtils::leftOf( *mPointVector[ mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext()]->getPoint()],
354 &p, mPointVector[ mHalfEdge[cwEdge]->getPoint()] ) < ( -
leftOfTresh ) )
357 mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext()]->getNext()]->setPoint( mPointVector.count() - 1 );
359 cwEdge = (
unsigned int )mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->getNext();
363 const unsigned int edge1 = insertEdge( mHalfEdge[cwEdge]->getNext(), -10, mHalfEdge[cwEdge]->getPoint(),
false,
false );
364 const unsigned int edge2 = insertEdge( mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual(), -10, -1,
false,
false );
365 const unsigned int edge3 = insertEdge( -10, edge1, mPointVector.count() - 1,
false,
false );
368 mHalfEdge[mHalfEdge[mHalfEdge[cwEdge]->getNext()]->getDual()]->setDual( edge2 );
369 mHalfEdge[mHalfEdge[cwEdge]->getNext()]->setDual( edge1 );
370 mHalfEdge[edge1]->setNext( edge2 );
371 mHalfEdge[edge2]->setNext( edge3 );
374 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 ) )
377 mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getDual()]->setPoint( mPointVector.count() - 1 );
379 ccwEdge = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getDual()]->getNext()]->getNext();
383 const unsigned int edge4 = insertEdge( mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext(), -10, mPointVector.count() - 1,
false,
false );
384 const unsigned int edge5 = insertEdge( edge3, -10, -1,
false,
false );
385 const unsigned int edge6 = insertEdge( mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getDual(), edge4, mHalfEdge[mHalfEdge[ccwEdge]->getDual()]->getPoint(),
false,
false );
390 mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->getDual()]->setDual( edge6 );
391 mHalfEdge[mHalfEdge[mHalfEdge[ccwEdge]->getNext()]->getNext()]->setDual( edge4 );
392 mHalfEdge[edge4]->setNext( edge5 );
393 mHalfEdge[edge5]->setNext( edge6 );
394 mHalfEdge[edge3]->setDual( edge5 );
397 unsigned int index = ccwEdge;
402 index = mHalfEdge[mHalfEdge[mHalfEdge[index]->getNext()]->getDual()]->getNext();
403 checkSwapRecursively( toswap, 0 );
404 if ( toswap == cwEdge )
410 else if ( number >= 0 )
412 const int nextnumber = mHalfEdge[number]->getNext();
413 const int nextnextnumber = mHalfEdge[mHalfEdge[number]->getNext()]->getNext();
416 const unsigned int edge1 = insertEdge( -10, nextnumber, mHalfEdge[number]->getPoint(),
false,
false );
417 const unsigned int edge2 = insertEdge(
static_cast<int>( edge1 ), -10, mPointVector.count() - 1,
false,
false );
418 const unsigned int edge3 = insertEdge( -10, nextnextnumber, mHalfEdge[nextnumber]->getPoint(),
false,
false );
419 const unsigned int edge4 = insertEdge(
static_cast<int>( edge3 ),
static_cast<int>( edge1 ), mPointVector.count() - 1,
false,
false );
420 const unsigned int edge5 = insertEdge( -10, number, mHalfEdge[nextnextnumber]->getPoint(),
false,
false );
421 const unsigned int edge6 = insertEdge(
static_cast<int>( edge5 ),
static_cast<int>( edge3 ), mPointVector.count() - 1,
false,
false );
424 mHalfEdge.at( edge1 )->setDual(
static_cast<int>( edge2 ) );
425 mHalfEdge.at( edge2 )->setNext(
static_cast<int>( edge5 ) );
426 mHalfEdge.at( edge3 )->setDual(
static_cast<int>( edge4 ) );
427 mHalfEdge.at( edge5 )->setDual(
static_cast<int>( edge6 ) );
428 mHalfEdge.at( number )->setNext(
static_cast<int>( edge2 ) );
429 mHalfEdge.at( nextnumber )->setNext(
static_cast<int>( edge4 ) );
430 mHalfEdge.at( nextnextnumber )->setNext(
static_cast<int>( edge6 ) );
433 checkSwapRecursively( number, 0 );
434 checkSwapRecursively( nextnumber, 0 );
435 checkSwapRecursively( nextnextnumber, 0 );
438 else if ( number == -20 )
443 const int point1 = mHalfEdge[mEdgeWithPoint]->getPoint();
444 const int point2 = mHalfEdge[mHalfEdge[mEdgeWithPoint]->getDual()]->getPoint();
445 const double distance1 = p.
distance( *mPointVector[point1] );
451 const double distance2 = p.
distance( *mPointVector[point2] );
458 const int edgea = mEdgeWithPoint;
459 const int edgeb = mHalfEdge[mEdgeWithPoint]->getDual();
460 const int edgec = mHalfEdge[edgea]->getNext();
461 const int edged = mHalfEdge[edgec]->getNext();
462 const int edgee = mHalfEdge[edgeb]->getNext();
463 const int edgef = mHalfEdge[edgee]->getNext();
466 const int nedge1 = insertEdge( -10, mHalfEdge[edgea]->getNext(), mHalfEdge[edgea]->getPoint(),
false,
false );
467 const int nedge2 = insertEdge( nedge1, -10, mPointVector.count() - 1,
false,
false );
468 const int nedge3 = insertEdge( -10, edged, mHalfEdge[edgec]->getPoint(),
false,
false );
469 const int nedge4 = insertEdge( nedge3, nedge1, mPointVector.count() - 1,
false,
false );
470 const int nedge5 = insertEdge( -10, edgef, mHalfEdge[edgee]->getPoint(),
false,
false );
471 const int nedge6 = insertEdge( nedge5, edgeb, mPointVector.count() - 1,
false,
false );
474 mHalfEdge[nedge1]->setDual( nedge2 );
475 mHalfEdge[nedge2]->setNext( nedge5 );
476 mHalfEdge[nedge3]->setDual( nedge4 );
477 mHalfEdge[nedge5]->setDual( nedge6 );
478 mHalfEdge[edgea]->setPoint( mPointVector.count() - 1 );
479 mHalfEdge[edgea]->setNext( nedge3 );
480 mHalfEdge[edgec]->setNext( nedge4 );
481 mHalfEdge[edgee]->setNext( nedge6 );
482 mHalfEdge[edgef]->setNext( nedge2 );
485 checkSwapRecursively( edgec, 0 );
486 checkSwapRecursively( edged, 0 );
487 checkSwapRecursively( edgee, 0 );
488 checkSwapRecursively( edgef, 0 );
491 else if ( number == -100 || number == -5 )
497 else if ( number == -25 )
500 QgsPoint *newPoint = mPointVector[mPointVector.count() - 1];
501 QgsPoint *existingPoint = mPointVector[mTwiceInsPoint];
502 existingPoint->
setZ( std::max( newPoint->
z(), existingPoint->
z() ) );
505 return mTwiceInsPoint;
509 return ( mPointVector.count() - 1 );
512 int QgsDualEdgeTriangulation::baseEdgeOfPoint(
int point )
514 unsigned int actedge = mEdgeInside;
516 if ( mPointVector.count() < 4 ||
point == -1 || mDimension == 1 )
518 int fromVirtualPoint = -1;
520 for (
int i = 0; i < mHalfEdge.count(); i++ )
522 if ( mHalfEdge[i]->getPoint() ==
point )
524 if ( mHalfEdge[mHalfEdge[i]->getDual()]->getPoint() != -1 )
527 fromVirtualPoint = i;
530 return fromVirtualPoint;
538 if ( control > 1000000 )
544 for (
int i = 0; i < mHalfEdge.count(); i++ )
546 if ( mHalfEdge[i]->getPoint() ==
point && mHalfEdge[mHalfEdge[i]->getNext()]->getPoint() != -1 )
553 const int fromPoint = mHalfEdge[mHalfEdge[actedge]->getDual()]->getPoint();
554 const int toPoint = mHalfEdge[actedge]->getPoint();
556 if ( fromPoint == -1 || toPoint == -1 )
558 for (
int i = 0; i < mHalfEdge.count(); i++ )
560 if ( mHalfEdge[i]->getPoint() ==
point && mHalfEdge[mHalfEdge[i]->getNext()]->getPoint() != -1 )
568 const double leftOfNumber =
MathUtils::leftOf( *mPointVector[
point], mPointVector[mHalfEdge[mHalfEdge[actedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[actedge]->getPoint()] );
571 if ( mHalfEdge[actedge]->getPoint() ==
point && mHalfEdge[mHalfEdge[actedge]->getNext()]->getPoint() != -1 )
573 mEdgeInside = actedge;
576 else if ( leftOfNumber <= 0.0 )
578 actedge = mHalfEdge[actedge]->getNext();
582 actedge = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[actedge]->getDual()]->getNext()]->getNext()]->getDual();
587 int QgsDualEdgeTriangulation::baseEdgeOfTriangle(
const QgsPoint &point )
589 unsigned int actEdge = mEdgeInside;
590 if ( mHalfEdge.at( actEdge )->getPoint() < 0 )
591 actEdge = mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( actEdge )->getDual() )->getNext() )->getDual();
592 if ( mHalfEdge.at( mHalfEdge.at( actEdge )->getDual() )->getPoint() < 0 )
593 actEdge = mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getDual();
599 int firstEndPoint = 0, secEndPoint = 0, thEndPoint = 0, fouEndPoint = 0;
603 if ( runs > MAX_BASE_ITERATIONS )
609 const double leftOfValue =
MathUtils::leftOf(
point, mPointVector.at( mHalfEdge.at( mHalfEdge.at( actEdge )->getDual() )->getPoint() ), mPointVector.at( mHalfEdge.at( actEdge )->getPoint() ) );
624 firstEndPoint = mHalfEdge.at( mHalfEdge.at( actEdge )->getDual() )->getPoint();
625 secEndPoint = mHalfEdge.at( actEdge )->getPoint();
627 else if ( nulls == 1 )
630 thEndPoint = mHalfEdge.at( mHalfEdge.at( actEdge )->getDual() )->getPoint();
631 fouEndPoint = mHalfEdge.at( actEdge )->getPoint();
634 mEdgeWithPoint = actEdge;
643 actEdge = mHalfEdge.at( actEdge )->getDual();
648 actEdge = mHalfEdge.at( actEdge )->getNext();
649 if ( mHalfEdge.at( actEdge )->getPoint() == -1 )
655 mEdgeOutside = (
unsigned int )mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getNext();
656 mEdgeInside = mHalfEdge.at( mHalfEdge.at( mEdgeOutside )->getDual() )->getNext();
662 if ( numInstabs > 0 )
665 mUnstableEdge = actEdge;
672 if ( firstEndPoint == thEndPoint || firstEndPoint == fouEndPoint )
675 mTwiceInsPoint = firstEndPoint;
678 else if ( secEndPoint == thEndPoint || secEndPoint == fouEndPoint )
681 mTwiceInsPoint = secEndPoint;
693 mEdgeInside = actEdge;
696 nr1 = mHalfEdge.at( actEdge )->getPoint();
697 nr2 = mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getPoint();
698 nr3 = mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getNext() )->getPoint();
699 const double x1 = mPointVector.at( nr1 )->x();
700 const double y1 = mPointVector.at( nr1 )->y();
701 const double x2 = mPointVector.at( nr2 )->x();
702 const double y2 = mPointVector.at( nr2 )->y();
703 const double x3 = mPointVector.at( nr3 )->x();
704 const double y3 = mPointVector.at( nr3 )->y();
707 if ( x1 < x2 && x1 < x3 )
711 else if ( x2 < x1 && x2 < x3 )
713 return mHalfEdge.at( actEdge )->getNext();
715 else if ( x3 < x1 && x3 < x2 )
717 return mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getNext();
728 return mHalfEdge.at( actEdge )->getNext();
735 return mHalfEdge.at( actEdge )->getNext();
739 return mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getNext();
750 return mHalfEdge.at( mHalfEdge.at( actEdge )->getNext() )->getNext();
758 if ( mTriangleInterpolator )
760 return mTriangleInterpolator->
calcNormVec( x, y, result );
764 QgsDebugMsg( QStringLiteral(
"warning, null pointer" ) );
771 if ( mTriangleInterpolator )
773 return mTriangleInterpolator->
calcPoint( x, y, result );
777 QgsDebugMsg( QStringLiteral(
"warning, null pointer" ) );
782 bool QgsDualEdgeTriangulation::checkSwapRecursively(
unsigned int edge,
unsigned int recursiveDeep )
784 if ( swapPossible( edge ) )
786 QgsPoint *pta = mPointVector.at( mHalfEdge.at( edge )->getPoint() );
787 QgsPoint *ptb = mPointVector.at( mHalfEdge.at( mHalfEdge.at( edge )->getNext() )->getPoint() );
788 QgsPoint *ptc = mPointVector.at( mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( edge )->getNext( ) )->getNext() )->getPoint() );
789 QgsPoint *ptd = mPointVector.at( mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( edge )->getDual() )->getNext() )->getPoint() );
790 if ( inCircle( *ptd, *pta, *ptb, *ptc ) )
792 doSwapRecursively( edge, recursiveDeep );
799 bool QgsDualEdgeTriangulation::isEdgeNeedSwap(
unsigned int edge )
const
801 if ( swapPossible( edge ) )
803 QgsPoint *pta = mPointVector[mHalfEdge[edge]->getPoint()];
804 QgsPoint *ptb = mPointVector[mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint()];
805 QgsPoint *ptc = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getNext()]->getNext()]->getPoint()];
806 QgsPoint *ptd = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint()];
807 return inCircle( *ptd, *pta, *ptb, *ptc );
814 void QgsDualEdgeTriangulation::doOnlySwap(
unsigned int edge )
816 const unsigned int edge1 = edge;
817 const unsigned int edge2 = mHalfEdge[edge]->getDual();
818 const unsigned int edge3 = mHalfEdge[edge]->getNext();
819 const unsigned int edge4 = mHalfEdge[mHalfEdge[edge]->getNext()]->getNext();
820 const unsigned int edge5 = mHalfEdge[mHalfEdge[edge]->getDual()]->getNext();
821 const unsigned int edge6 = mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getNext();
822 mHalfEdge[edge1]->setNext( edge4 );
823 mHalfEdge[edge2]->setNext( edge6 );
824 mHalfEdge[edge3]->setNext( edge2 );
825 mHalfEdge[edge4]->setNext( edge5 );
826 mHalfEdge[edge5]->setNext( edge1 );
827 mHalfEdge[edge6]->setNext( edge3 );
828 mHalfEdge[edge1]->setPoint( mHalfEdge[edge3]->getPoint() );
829 mHalfEdge[edge2]->setPoint( mHalfEdge[edge5]->getPoint() );
832 void QgsDualEdgeTriangulation::doSwapRecursively(
unsigned int edge,
unsigned int recursiveDeep )
834 const unsigned int edge1 = edge;
835 const unsigned int edge2 = mHalfEdge.at( edge )->getDual();
836 const unsigned int edge3 = mHalfEdge.at( edge )->getNext();
837 const unsigned int edge4 = mHalfEdge.at( mHalfEdge.at( edge )->getNext() )->getNext();
838 const unsigned int edge5 = mHalfEdge.at( mHalfEdge.at( edge )->getDual() )->getNext();
839 const unsigned int edge6 = mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( edge )->getDual() )->getNext() )->getNext();
840 mHalfEdge.at( edge1 )->setNext( edge4 );
841 mHalfEdge.at( edge2 )->setNext( edge6 );
842 mHalfEdge.at( edge3 )->setNext( edge2 );
843 mHalfEdge.at( edge4 )->setNext( edge5 );
844 mHalfEdge.at( edge5 )->setNext( edge1 );
845 mHalfEdge.at( edge6 )->setNext( edge3 );
846 mHalfEdge.at( edge1 )->setPoint( mHalfEdge.at( edge3 )->getPoint() );
847 mHalfEdge.at( edge2 )->setPoint( mHalfEdge.at( edge5 )->getPoint() );
850 if ( recursiveDeep < 100 )
852 checkSwapRecursively( edge3, recursiveDeep );
853 checkSwapRecursively( edge6, recursiveDeep );
854 checkSwapRecursively( edge4, recursiveDeep );
855 checkSwapRecursively( edge5, recursiveDeep );
859 QStack<int> edgesToSwap;
860 edgesToSwap.push( edge3 );
861 edgesToSwap.push( edge6 );
862 edgesToSwap.push( edge4 );
863 edgesToSwap.push( edge5 );
865 while ( !edgesToSwap.isEmpty() && loopCount < 10000 )
868 const unsigned int e1 = edgesToSwap.pop();
869 if ( isEdgeNeedSwap( e1 ) )
871 const unsigned int e2 = mHalfEdge.at( e1 )->getDual();
872 const unsigned int e3 = mHalfEdge.at( e1 )->getNext();
873 const unsigned int e4 = mHalfEdge.at( mHalfEdge.at( e1 )->getNext() )->getNext();
874 const unsigned int e5 = mHalfEdge.at( mHalfEdge.at( e1 )->getDual() )->getNext();
875 const unsigned int e6 = mHalfEdge.at( mHalfEdge.at( mHalfEdge.at( e1 )->getDual() )->getNext() )->getNext();
876 mHalfEdge.at( e1 )->setNext( e4 );
877 mHalfEdge.at( e2 )->setNext( e6 );
878 mHalfEdge.at( e3 )->setNext( e2 );
879 mHalfEdge.at( e4 )->setNext( e5 );
880 mHalfEdge.at( e5 )->setNext( e1 );
881 mHalfEdge.at( e6 )->setNext( e3 );
882 mHalfEdge.at( e1 )->setPoint( mHalfEdge.at( e3 )->getPoint() );
883 mHalfEdge.at( e2 )->setPoint( mHalfEdge.at( e5 )->getPoint() );
885 edgesToSwap.push( e3 );
886 edgesToSwap.push( e6 );
887 edgesToSwap.push( e4 );
888 edgesToSwap.push( e5 );
896 void DualEdgeTriangulation::draw( QPainter *p,
double xlowleft,
double ylowleft,
double xupright,
double yupright,
double width,
double height )
const
899 if ( mPointVector.isEmpty() )
904 p->setPen( mEdgeColor );
906 bool *control =
new bool[mHalfEdge.count()];
907 bool *control2 =
new bool[mHalfEdge.count()];
909 for (
unsigned int i = 0; i <= mHalfEdge.count() - 1; i++ )
915 if ( ( ( xupright - xlowleft ) / width ) > ( ( yupright - ylowleft ) / height ) )
917 double lowerborder = -( height * ( xupright - xlowleft ) / width - yupright );
918 for (
unsigned int i = 0; i < mHalfEdge.count() - 1; i++ )
920 if ( mHalfEdge[i]->getPoint() == -1 || mHalfEdge[mHalfEdge[i]->getDual()]->getPoint() == -1 )
927 if ( mHalfEdge[i]->getPoint() != -1 && mHalfEdge[mHalfEdge[i]->getNext()]->getPoint() != -1 && mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint() != -1 )
929 p1 = mPointVector[mHalfEdge[i]->getPoint()]->getZ();
930 p2 = mPointVector[mHalfEdge[mHalfEdge[i]->getNext()]->getPoint()]->getZ();
931 p3 = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint()]->getZ();
932 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 ) )
935 pa.setPoint( 0, ( mPointVector[mHalfEdge[i]->getPoint()]->getX() - xlowleft ) / ( xupright - xlowleft )*width, ( yupright - mPointVector[mHalfEdge[i]->getPoint()]->getY() ) / ( xupright - xlowleft )*width );
936 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 );
937 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 );
938 QColor
c( 255, 0, 0 );
940 p->drawPolygon( pa );
945 control2[mHalfEdge[i]->getNext()] =
true;
946 control2[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()] =
true;
953 if ( halfEdgeBBoxTest( i, xlowleft, lowerborder, xupright, yupright ) )
955 if ( mHalfEdge[i]->getBreak() )
957 p->setPen( mBreakEdgeColor );
959 else if ( mHalfEdge[i]->getForced() )
961 p->setPen( mForcedEdgeColor );
965 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 );
967 if ( mHalfEdge[i]->getForced() )
969 p->setPen( mEdgeColor );
975 control[mHalfEdge[i]->getDual()] =
true;
980 double rightborder = width * ( yupright - ylowleft ) / height + xlowleft;
981 for (
unsigned int i = 0; i < mHalfEdge.count() - 1; i++ )
983 if ( mHalfEdge[i]->getPoint() == -1 || mHalfEdge[mHalfEdge[i]->getDual()]->getPoint() == -1 )
990 if ( mHalfEdge[i]->getPoint() != -1 && mHalfEdge[mHalfEdge[i]->getNext()]->getPoint() != -1 && mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint() != -1 )
992 p1 = mPointVector[mHalfEdge[i]->getPoint()]->getZ();
993 p2 = mPointVector[mHalfEdge[mHalfEdge[i]->getNext()]->getPoint()]->getZ();
994 p3 = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()]->getPoint()]->getZ();
995 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 ) )
998 pa.setPoint( 0, ( mPointVector[mHalfEdge[i]->getPoint()]->getX() - xlowleft ) / ( yupright - ylowleft )*height, ( yupright - mPointVector[mHalfEdge[i]->getPoint()]->getY() ) / ( yupright - ylowleft )*height );
999 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 );
1000 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 );
1001 QColor
c( 255, 0, 0 );
1003 p->drawPolygon( pa );
1008 control2[mHalfEdge[i]->getNext()] =
true;
1009 control2[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()] =
true;
1017 if ( halfEdgeBBoxTest( i, xlowleft, ylowleft, rightborder, yupright ) )
1019 if ( mHalfEdge[i]->getBreak() )
1021 p->setPen( mBreakEdgeColor );
1023 else if ( mHalfEdge[i]->getForced() )
1025 p->setPen( mForcedEdgeColor );
1028 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 );
1030 if ( mHalfEdge[i]->getForced() )
1032 p->setPen( mEdgeColor );
1037 control[mHalfEdge[i]->getDual()] =
true;
1050 const int firstedge = baseEdgeOfPoint( p2 );
1054 int nextnextedge = firstedge;
1058 edge = mHalfEdge[nextnextedge]->getDual();
1059 if ( mHalfEdge[edge]->getPoint() == p1 )
1061 theedge = nextnextedge;
1064 nextedge = mHalfEdge[edge]->getNext();
1065 nextnextedge = mHalfEdge[nextedge]->getNext();
1067 while ( nextnextedge != firstedge );
1069 if ( theedge == -10 )
1076 return mHalfEdge[mHalfEdge[mHalfEdge[theedge]->getDual()]->getNext()]->getPoint();
1082 const int firstedge = baseEdgeOfPoint( pointno );
1085 if ( firstedge == -1 )
1090 int actedge = firstedge;
1091 int edge, nextedge, nextnextedge;
1094 edge = mHalfEdge[actedge]->getDual();
1095 vlist.append( mHalfEdge[edge]->getPoint() );
1096 nextedge = mHalfEdge[edge]->getNext();
1097 vlist.append( mHalfEdge[nextedge]->getPoint() );
1098 nextnextedge = mHalfEdge[nextedge]->getNext();
1099 vlist.append( mHalfEdge[nextnextedge]->getPoint() );
1100 if ( mHalfEdge[nextnextedge]->getBreak() )
1102 vlist.append( -10 );
1106 vlist.append( -20 );
1108 actedge = nextnextedge;
1110 while ( nextnextedge != firstedge );
1118 if ( mPointVector.size() < 3 )
1124 const int edge = baseEdgeOfTriangle(
point );
1130 else if ( edge >= 0 )
1132 const int ptnr1 = mHalfEdge[edge]->getPoint();
1133 const int ptnr2 = mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint();
1134 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[edge]->getNext()]->getNext()]->getPoint();
1135 p1.
setX( mPointVector[ptnr1]->x() );
1136 p1.
setY( mPointVector[ptnr1]->y() );
1137 p1.
setZ( mPointVector[ptnr1]->z() );
1138 p2.
setX( mPointVector[ptnr2]->x() );
1139 p2.
setY( mPointVector[ptnr2]->y() );
1140 p2.
setZ( mPointVector[ptnr2]->z() );
1141 p3.
setX( mPointVector[ptnr3]->x() );
1142 p3.
setY( mPointVector[ptnr3]->y() );
1143 p3.
setZ( mPointVector[ptnr3]->z() );
1149 else if ( edge == -20 )
1151 const int ptnr1 = mHalfEdge[mEdgeWithPoint]->getPoint();
1152 const int ptnr2 = mHalfEdge[mHalfEdge[mEdgeWithPoint]->getNext()]->getPoint();
1153 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[mEdgeWithPoint]->getNext()]->getNext()]->getPoint();
1154 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1158 p1.
setX( mPointVector[ptnr1]->x() );
1159 p1.
setY( mPointVector[ptnr1]->y() );
1160 p1.
setZ( mPointVector[ptnr1]->z() );
1161 p2.
setX( mPointVector[ptnr2]->x() );
1162 p2.
setY( mPointVector[ptnr2]->y() );
1163 p2.
setZ( mPointVector[ptnr2]->z() );
1164 p3.
setX( mPointVector[ptnr3]->x() );
1165 p3.
setY( mPointVector[ptnr3]->y() );
1166 p3.
setZ( mPointVector[ptnr3]->z() );
1172 else if ( edge == -25 )
1174 const int edge1 = baseEdgeOfPoint( mTwiceInsPoint );
1175 const int edge2 = mHalfEdge[edge1]->getNext();
1176 const int edge3 = mHalfEdge[edge2]->getNext();
1177 const int ptnr1 = mHalfEdge[edge1]->getPoint();
1178 const int ptnr2 = mHalfEdge[edge2]->getPoint();
1179 const int ptnr3 = mHalfEdge[edge3]->getPoint();
1180 p1.
setX( mPointVector[ptnr1]->x() );
1181 p1.
setY( mPointVector[ptnr1]->y() );
1182 p1.
setZ( mPointVector[ptnr1]->z() );
1183 p2.
setX( mPointVector[ptnr2]->x() );
1184 p2.
setY( mPointVector[ptnr2]->y() );
1185 p2.
setZ( mPointVector[ptnr2]->z() );
1186 p3.
setX( mPointVector[ptnr3]->x() );
1187 p3.
setY( mPointVector[ptnr3]->y() );
1188 p3.
setZ( mPointVector[ptnr3]->z() );
1194 else if ( edge == -5 )
1196 const int ptnr1 = mHalfEdge[mUnstableEdge]->getPoint();
1197 const int ptnr2 = mHalfEdge[mHalfEdge[mUnstableEdge]->getNext()]->getPoint();
1198 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[mUnstableEdge]->getNext()]->getNext()]->getPoint();
1199 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1203 p1.
setX( mPointVector[ptnr1]->x() );
1204 p1.
setY( mPointVector[ptnr1]->y() );
1205 p1.
setZ( mPointVector[ptnr1]->z() );
1206 p2.
setX( mPointVector[ptnr2]->x() );
1207 p2.
setY( mPointVector[ptnr2]->y() );
1208 p2.
setZ( mPointVector[ptnr2]->z() );
1209 p3.
setX( mPointVector[ptnr3]->x() );
1210 p3.
setY( mPointVector[ptnr3]->y() );
1211 p3.
setZ( mPointVector[ptnr3]->z() );
1226 if ( mPointVector.size() < 3 )
1232 const int edge = baseEdgeOfTriangle(
point );
1237 else if ( edge >= 0 )
1239 const int ptnr1 = mHalfEdge[edge]->getPoint();
1240 const int ptnr2 = mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint();
1241 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[edge]->getNext()]->getNext()]->getPoint();
1242 p1.
setX( mPointVector[ptnr1]->x() );
1243 p1.
setY( mPointVector[ptnr1]->y() );
1244 p1.
setZ( mPointVector[ptnr1]->z() );
1245 p2.
setX( mPointVector[ptnr2]->x() );
1246 p2.
setY( mPointVector[ptnr2]->y() );
1247 p2.
setZ( mPointVector[ptnr2]->z() );
1248 p3.
setX( mPointVector[ptnr3]->x() );
1249 p3.
setY( mPointVector[ptnr3]->y() );
1250 p3.
setZ( mPointVector[ptnr3]->z() );
1253 else if ( edge == -20 )
1255 const int ptnr1 = mHalfEdge[mEdgeWithPoint]->getPoint();
1256 const int ptnr2 = mHalfEdge[mHalfEdge[mEdgeWithPoint]->getNext()]->getPoint();
1257 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[mEdgeWithPoint]->getNext()]->getNext()]->getPoint();
1258 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1262 p1.
setX( mPointVector[ptnr1]->x() );
1263 p1.
setY( mPointVector[ptnr1]->y() );
1264 p1.
setZ( mPointVector[ptnr1]->z() );
1265 p2.
setX( mPointVector[ptnr2]->x() );
1266 p2.
setY( mPointVector[ptnr2]->y() );
1267 p2.
setZ( mPointVector[ptnr2]->z() );
1268 p3.
setX( mPointVector[ptnr3]->x() );
1269 p3.
setY( mPointVector[ptnr3]->y() );
1270 p3.
setZ( mPointVector[ptnr3]->z() );
1273 else if ( edge == -25 )
1275 const int edge1 = baseEdgeOfPoint( mTwiceInsPoint );
1276 const int edge2 = mHalfEdge[edge1]->getNext();
1277 const int edge3 = mHalfEdge[edge2]->getNext();
1278 const int ptnr1 = mHalfEdge[edge1]->getPoint();
1279 const int ptnr2 = mHalfEdge[edge2]->getPoint();
1280 const int ptnr3 = mHalfEdge[edge3]->getPoint();
1281 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1285 p1.
setX( mPointVector[ptnr1]->x() );
1286 p1.
setY( mPointVector[ptnr1]->y() );
1287 p1.
setZ( mPointVector[ptnr1]->z() );
1288 p2.
setX( mPointVector[ptnr2]->x() );
1289 p2.
setY( mPointVector[ptnr2]->y() );
1290 p2.
setZ( mPointVector[ptnr2]->z() );
1291 p3.
setX( mPointVector[ptnr3]->x() );
1292 p3.
setY( mPointVector[ptnr3]->y() );
1293 p3.
setZ( mPointVector[ptnr3]->z() );
1296 else if ( edge == -5 )
1298 const int ptnr1 = mHalfEdge[mUnstableEdge]->getPoint();
1299 const int ptnr2 = mHalfEdge[mHalfEdge[mUnstableEdge]->getNext()]->getPoint();
1300 const int ptnr3 = mHalfEdge[mHalfEdge[mHalfEdge[mUnstableEdge]->getNext()]->getNext()]->getPoint();
1301 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1305 p1.
setX( mPointVector[ptnr1]->x() );
1306 p1.
setY( mPointVector[ptnr1]->y() );
1307 p1.
setZ( mPointVector[ptnr1]->z() );
1308 p2.
setX( mPointVector[ptnr2]->x() );
1309 p2.
setY( mPointVector[ptnr2]->y() );
1310 p2.
setZ( mPointVector[ptnr2]->z() );
1311 p3.
setX( mPointVector[ptnr3]->x() );
1312 p3.
setY( mPointVector[ptnr3]->y() );
1313 p3.
setZ( mPointVector[ptnr3]->z() );
1322 unsigned int QgsDualEdgeTriangulation::insertEdge(
int dual,
int next,
int point,
bool mbreak,
bool forced )
1325 mHalfEdge.append( edge );
1326 return mHalfEdge.count() - 1;
1330 static bool altitudeTriangleIsSmall(
const QgsPoint &pointBase1,
const QgsPoint &pointBase2,
const QgsPoint &pt3,
double tolerance )
1333 const double x1 = pointBase1.
x();
1334 const double y1 = pointBase1.
y();
1335 const double x2 = pointBase2.
x();
1336 const double y2 = pointBase2.
y();
1337 const double X = pt3.
x();
1338 const double Y = pt3.
y();
1347 t = ( X * ny - Y * nx - x1 * ny + y1 * nx ) / ( ( x2 - x1 ) * ny - ( y2 - y1 ) * nx );
1348 projectedPoint.
setX( x1 + t * ( x2 - x1 ) );
1349 projectedPoint.
setY( y1 + t * ( y2 - y1 ) );
1351 return pt3.
distance( projectedPoint ) < tolerance;
1361 QgsPoint *point1 = mPointVector.at( p1 );
1362 QgsPoint *point2 = mPointVector.at( p2 );
1365 QList<int> crossedEdges;
1368 int pointingEdge = 0;
1370 pointingEdge = baseEdgeOfPoint( p1 );
1372 if ( pointingEdge == -1 )
1378 int actEdge = mHalfEdge[pointingEdge]->getDual();
1379 const int firstActEdge = actEdge;
1386 if ( control > 100 )
1392 if ( mHalfEdge[actEdge]->getPoint() == -1 )
1394 actEdge = mHalfEdge[mHalfEdge[mHalfEdge[actEdge]->getNext()]->getNext()]->getDual();
1399 if ( mHalfEdge[actEdge]->getPoint() == p2 )
1401 mHalfEdge[actEdge]->setForced(
true );
1403 mHalfEdge[mHalfEdge[actEdge]->getDual()]->setForced(
true );
1409 if ( ( point2->
y() - point1->
y() ) / ( mPointVector[mHalfEdge[actEdge]->getPoint()]->y() - point1->
y() ) == ( point2->
x() - point1->
x() ) / ( mPointVector[mHalfEdge[actEdge]->getPoint()]->x() - point1->
x() )
1410 && ( ( point2->
y() - point1->
y() ) >= 0 ) == ( ( mPointVector[mHalfEdge[actEdge]->getPoint()]->y() - point1->
y() ) > 0 )
1411 && ( ( point2->
x() - point1->
x() ) >= 0 ) == ( ( mPointVector[mHalfEdge[actEdge]->getPoint()]->x() - point1->
x() ) > 0 ) )
1414 mHalfEdge[actEdge]->setForced(
true );
1416 mHalfEdge[mHalfEdge[actEdge]->getDual()]->setForced(
true );
1418 const int a = insertForcedSegment( mHalfEdge[actEdge]->getPoint(), p2, segmentType );
1423 const int oppositeEdge = mHalfEdge[actEdge]->getNext();
1425 if ( mHalfEdge[oppositeEdge]->getPoint() == -1 || mHalfEdge[mHalfEdge[oppositeEdge]->getDual()]->getPoint() == -1 )
1427 actEdge = mHalfEdge[mHalfEdge[oppositeEdge]->getNext()]->getDual();
1431 QgsPoint *oppositePoint1 = mPointVector[mHalfEdge[oppositeEdge]->getPoint()];
1432 QgsPoint *oppositePoint2 = mPointVector[mHalfEdge[mHalfEdge[oppositeEdge]->getDual()]->getPoint()];
1434 if ( altitudeTriangleIsSmall( *oppositePoint1, *oppositePoint2, *point1, oppositePoint1->
distance( *oppositePoint2 ) / 500 ) )
1442 mPointVector[mHalfEdge[oppositeEdge]->getPoint()],
1443 mPointVector[mHalfEdge[mHalfEdge[oppositeEdge]->getDual()]->getPoint()] ) )
1449 p3 = mHalfEdge[mHalfEdge[actEdge]->getNext()]->getPoint();
1450 p4 = mHalfEdge[mHalfEdge[mHalfEdge[actEdge]->getNext()]->getDual()]->getPoint();
1452 const double dista = std::sqrt( ( crosspoint.x() - mPointVector[p3]->x() ) * ( crosspoint.x() - mPointVector[p3]->x() ) + ( crosspoint.y() - mPointVector[p3]->y() ) * ( crosspoint.y() - mPointVector[p3]->y() ) );
1453 const double distb = std::sqrt( ( crosspoint.x() - mPointVector[p4]->x() ) * ( crosspoint.x() - mPointVector[p4]->x() ) + ( crosspoint.y() - mPointVector[p4]->y() ) * ( crosspoint.y() - mPointVector[p4]->y() ) );
1454 if ( dista <= distb )
1456 insertForcedSegment( p1, p3, segmentType );
1457 const int e = insertForcedSegment( p3, p2, segmentType );
1460 else if ( distb <= dista )
1462 insertForcedSegment( p1, p4, segmentType );
1463 const int e = insertForcedSegment( p4, p2, segmentType );
1472 p3 = mHalfEdge[mHalfEdge[actEdge]->getNext()]->getPoint();
1473 p4 = mHalfEdge[mHalfEdge[mHalfEdge[actEdge]->getNext()]->getDual()]->getPoint();
1475 const double distpart = std::sqrt( ( crosspoint.x() - mPointVector[p4]->x() ) * ( crosspoint.x() - mPointVector[p4]->x() ) + ( crosspoint.y() - mPointVector[p4]->y() ) * ( crosspoint.y() - mPointVector[p4]->y() ) );
1476 const double disttot = std::sqrt( ( mPointVector[p3]->x() - mPointVector[p4]->x() ) * ( mPointVector[p3]->x() - mPointVector[p4]->x() ) + ( mPointVector[p3]->y() - mPointVector[p4]->y() ) * ( mPointVector[p3]->y() - mPointVector[p4]->y() ) );
1477 const float frac = distpart / disttot;
1479 if ( frac == 0 || frac == 1 )
1484 mHalfEdge[actEdge]->setForced(
true );
1486 mHalfEdge[mHalfEdge[actEdge]->getDual()]->setForced(
true );
1488 const int a = insertForcedSegment( p4, p2, segmentType );
1491 else if ( frac == 1 )
1494 mHalfEdge[actEdge]->setForced(
true );
1496 mHalfEdge[mHalfEdge[actEdge]->getDual()]->setForced(
true );
1500 const int a = insertForcedSegment( p3, p2, segmentType );
1512 const int newpoint = splitHalfEdge( mHalfEdge[actEdge]->getNext(), frac );
1513 insertForcedSegment( p1, newpoint, segmentType );
1514 const int e = insertForcedSegment( newpoint, p2, segmentType );
1520 crossedEdges.append( oppositeEdge );
1523 actEdge = mHalfEdge[mHalfEdge[oppositeEdge]->getNext()]->getDual();
1525 while ( actEdge != firstActEdge );
1527 if ( crossedEdges.isEmpty() )
1529 int lastEdgeOppositePointIndex = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1532 while ( lastEdgeOppositePointIndex != p2 )
1534 QgsPoint *lastEdgePoint1 = mPointVector[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getPoint()];
1535 QgsPoint *lastEdgePoint2 = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint()];
1536 QgsPoint *lastEdgeOppositePoint = mPointVector[lastEdgeOppositePointIndex];
1545 p3 = mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getPoint();
1546 p4 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1548 const double dista = std::sqrt( ( crosspoint.x() - mPointVector[p3]->x() ) * ( crosspoint.x() - mPointVector[p3]->x() ) + ( crosspoint.y() - mPointVector[p3]->y() ) * ( crosspoint.y() - mPointVector[p3]->y() ) );
1549 const double distb = std::sqrt( ( crosspoint.x() - mPointVector[p4]->x() ) * ( crosspoint.x() - mPointVector[p4]->x() ) + ( crosspoint.y() - mPointVector[p4]->y() ) * ( crosspoint.y() - mPointVector[p4]->y() ) );
1550 if ( dista <= distb )
1552 insertForcedSegment( p1, p3, segmentType );
1553 const int e = insertForcedSegment( p3, p2, segmentType );
1556 else if ( distb <= dista )
1558 insertForcedSegment( p1, p4, segmentType );
1559 const int e = insertForcedSegment( p4, p2, segmentType );
1563 else if ( mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getForced() && mForcedCrossBehavior ==
QgsTriangulation::InsertVertex )
1567 p3 = mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getPoint();
1568 p4 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1570 const double distpart = std::sqrt( ( crosspoint.x() - mPointVector[p3]->x() ) * ( crosspoint.x() - mPointVector[p3]->x() ) + ( crosspoint.y() - mPointVector[p3]->y() ) * ( crosspoint.y() - mPointVector[p3]->y() ) );
1571 const double disttot = std::sqrt( ( mPointVector[p3]->x() - mPointVector[p4]->x() ) * ( mPointVector[p3]->x() - mPointVector[p4]->x() ) + ( mPointVector[p3]->y() - mPointVector[p4]->y() ) * ( mPointVector[p3]->y() - mPointVector[p4]->y() ) );
1572 const float frac = distpart / disttot;
1573 if ( frac == 0 || frac == 1 )
1577 const int newpoint = splitHalfEdge( mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext(), frac );
1578 insertForcedSegment( p1, newpoint, segmentType );
1579 const int e = insertForcedSegment( newpoint, p2, segmentType );
1583 crossedEdges.append( mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext() );
1588 if ( mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getForced() && mForcedCrossBehavior ==
QgsTriangulation::SnappingTypeVertex )
1592 p3 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1593 p4 = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint();
1595 const double dista = std::sqrt( ( crosspoint.x() - mPointVector[p3]->x() ) * ( crosspoint.x() - mPointVector[p3]->x() ) + ( crosspoint.y() - mPointVector[p3]->y() ) * ( crosspoint.y() - mPointVector[p3]->y() ) );
1596 const double distb = std::sqrt( ( crosspoint.x() - mPointVector[p4]->x() ) * ( crosspoint.x() - mPointVector[p4]->x() ) + ( crosspoint.y() - mPointVector[p4]->y() ) * ( crosspoint.y() - mPointVector[p4]->y() ) );
1597 if ( dista <= distb )
1599 insertForcedSegment( p1, p3, segmentType );
1600 const int e = insertForcedSegment( p3, p2, segmentType );
1603 else if ( distb <= dista )
1605 insertForcedSegment( p1, p4, segmentType );
1606 const int e = insertForcedSegment( p4, p2, segmentType );
1610 else if ( mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getForced() && mForcedCrossBehavior ==
QgsTriangulation::InsertVertex )
1614 p3 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1615 p4 = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint();
1617 const double distpart = std::sqrt( ( crosspoint.x() - mPointVector[p3]->x() ) * ( crosspoint.x() - mPointVector[p3]->x() ) + ( crosspoint.y() - mPointVector[p3]->y() ) * ( crosspoint.y() - mPointVector[p3]->y() ) );
1618 const double disttot = std::sqrt( ( mPointVector[p3]->x() - mPointVector[p4]->x() ) * ( mPointVector[p3]->x() - mPointVector[p4]->x() ) + ( mPointVector[p3]->y() - mPointVector[p4]->y() ) * ( mPointVector[p3]->y() - mPointVector[p4]->y() ) );
1619 const float frac = distpart / disttot;
1620 if ( frac == 0 || frac == 1 )
1624 const int newpoint = splitHalfEdge( mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext(), frac );
1625 insertForcedSegment( p1, newpoint, segmentType );
1626 const int e = insertForcedSegment( newpoint, p2, segmentType );
1630 crossedEdges.append( mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext() );
1637 lastEdgeOppositePointIndex = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1641 QgsPoint *lastEdgePoint1 = mPointVector[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getPoint()];
1642 QgsPoint *lastEdgePoint2 = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint()];
1643 QgsPoint *lastEdgeOppositePoint = mPointVector[lastEdgeOppositePointIndex];
1644 if ( altitudeTriangleIsSmall( *lastEdgePoint1, *lastEdgePoint2, *lastEdgeOppositePoint, lastEdgePoint1->
distance( *lastEdgePoint2 ) / 500 ) )
1648 QList<int>::const_iterator iter;
1649 for ( iter = crossedEdges.constBegin(); iter != crossedEdges.constEnd(); ++iter )
1651 mHalfEdge[( *( iter ) )]->setForced(
false );
1652 mHalfEdge[( *( iter ) )]->setBreak(
false );
1653 mHalfEdge[mHalfEdge[( *( iter ) )]->getDual()]->setForced(
false );
1654 mHalfEdge[mHalfEdge[( *( iter ) )]->getDual()]->setBreak(
false );
1659 QList<int> freelist = crossedEdges;
1662 QList<int> leftPolygon;
1663 QList<int> rightPolygon;
1666 const int firstedge = freelist.first();
1667 mHalfEdge[firstedge]->setForced(
true );
1669 leftPolygon.append( firstedge );
1670 const int dualfirstedge = mHalfEdge[freelist.first()]->getDual();
1671 mHalfEdge[dualfirstedge]->setForced(
true );
1673 rightPolygon.append( dualfirstedge );
1674 freelist.pop_front();
1678 QList<int>::const_iterator leftiter;
1679 leftiter = crossedEdges.constEnd();
1683 const int newpoint = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[( *leftiter )]->getDual()]->getNext()]->getNext()]->getPoint();
1684 if ( newpoint != actpointl )
1687 actpointl = newpoint;
1688 const int theedge = mHalfEdge[mHalfEdge[mHalfEdge[( *leftiter )]->getDual()]->getNext()]->getNext();
1689 leftPolygon.append( theedge );
1691 if ( leftiter == crossedEdges.constBegin() )
1697 leftPolygon.append( mHalfEdge[crossedEdges.first()]->getNext() );
1700 QList<int>::const_iterator rightiter;
1702 for ( rightiter = crossedEdges.constBegin(); rightiter != crossedEdges.constEnd(); ++rightiter )
1704 const int newpoint = mHalfEdge[mHalfEdge[mHalfEdge[( *rightiter )]->getNext()]->getNext()]->getPoint();
1705 if ( newpoint != actpointr )
1708 actpointr = newpoint;
1709 const int theedge = mHalfEdge[mHalfEdge[( *rightiter )]->getNext()]->getNext();
1710 rightPolygon.append( theedge );
1716 rightPolygon.append( mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext() );
1717 mHalfEdge[rightPolygon.last()]->setNext( dualfirstedge );
1720 int actedgel = leftPolygon[1];
1721 leftiter = leftPolygon.constBegin();
1723 for ( ; leftiter != leftPolygon.constEnd(); ++leftiter )
1725 mHalfEdge[actedgel]->setNext( ( *leftiter ) );
1726 actedgel = ( *leftiter );
1730 int actedger = rightPolygon[1];
1731 rightiter = rightPolygon.constBegin();
1733 for ( ; rightiter != rightPolygon.constEnd(); ++rightiter )
1735 mHalfEdge[actedger]->setNext( ( *rightiter ) );
1736 actedger = ( *( rightiter ) );
1741 mHalfEdge[leftPolygon.first()]->setNext( ( *( ++( leftiter = leftPolygon.constBegin() ) ) ) );
1742 mHalfEdge[leftPolygon.first()]->setPoint( p2 );
1743 mHalfEdge[leftPolygon.last()]->setNext( firstedge );
1744 mHalfEdge[rightPolygon.first()]->setNext( ( *( ++( rightiter = rightPolygon.constBegin() ) ) ) );
1745 mHalfEdge[rightPolygon.first()]->setPoint( p1 );
1746 mHalfEdge[rightPolygon.last()]->setNext( dualfirstedge );
1748 triangulatePolygon( &leftPolygon, &freelist, firstedge );
1749 triangulatePolygon( &rightPolygon, &freelist, dualfirstedge );
1752 for ( iter = crossedEdges.constBegin(); iter != crossedEdges.constEnd(); ++iter )
1754 checkSwapRecursively( ( *( iter ) ), 0 );
1757 return leftPolygon.first();
1762 mForcedCrossBehavior = b;
1767 mTriangleInterpolator = interpolator;
1773 const double minangle = 0;
1777 bool swapped =
false;
1778 bool *control =
new bool[mHalfEdge.count()];
1780 for (
int i = 0; i <= mHalfEdge.count() - 1; i++ )
1786 for (
int i = 0; i <= mHalfEdge.count() - 1; i++ )
1795 e2 = mHalfEdge[e1]->getNext();
1796 e3 = mHalfEdge[e2]->getNext();
1799 p1 = mHalfEdge[e1]->getPoint();
1800 p2 = mHalfEdge[e2]->getPoint();
1801 p3 = mHalfEdge[e3]->getPoint();
1804 if ( p1 == -1 || p2 == -1 || p3 == -1 )
1812 double el1, el2, el3;
1813 el1 = mPointVector[p1]->z();
1814 el2 = mPointVector[p2]->z();
1815 el3 = mPointVector[p3]->z();
1817 if ( el1 == el2 && el2 == el3 )
1820 if ( swapPossible( ( uint )e1 ) && mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[e1]->getDual()]->getNext()]->getPoint()]->z() != el1 && swapMinAngle( e1 ) > minangle )
1822 doOnlySwap( ( uint )e1 );
1825 else if ( swapPossible( ( uint )e2 ) && mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[e2]->getDual()]->getNext()]->getPoint()]->z() != el2 && swapMinAngle( e2 ) > minangle )
1827 doOnlySwap( ( uint )e2 );
1830 else if ( swapPossible( ( uint )e3 ) && mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[e3]->getDual()]->getNext()]->getPoint()]->z() != el3 && swapMinAngle( e3 ) > minangle )
1832 doOnlySwap( ( uint )e3 );
1862 const double mintol = 17;
1865 std::map<int, double> edge_angle;
1866 std::multimap<double, int> angle_edge;
1867 QSet<int> dontexamine;
1876 const int nhalfedges = mHalfEdge.count();
1878 for (
int i = 0; i < nhalfedges - 1; i++ )
1880 const int next = mHalfEdge[i]->getNext();
1881 const int nextnext = mHalfEdge[next]->getNext();
1883 if ( mHalfEdge[next]->getPoint() != -1 && ( mHalfEdge[i]->getForced() || mHalfEdge[mHalfEdge[mHalfEdge[i]->getDual()]->getNext()]->getPoint() == -1 ) )
1885 if ( !( ( mHalfEdge[next]->getForced() || edgeOnConvexHull( next ) ) || ( mHalfEdge[nextnext]->getForced() || edgeOnConvexHull( nextnext ) ) ) )
1888 while (
MathUtils::inDiametral( mPointVector[mHalfEdge[mHalfEdge[i]->getDual()]->getPoint()], mPointVector[mHalfEdge[i]->getPoint()], mPointVector[mHalfEdge[next]->getPoint()] ) )
1891 const int pointno = splitHalfEdge( i, 0.5 );
1903 for (
int i = 0; i < mHalfEdge.count() - 1; i++ )
1905 p1 = mHalfEdge[mHalfEdge[i]->getDual()]->getPoint();
1906 p2 = mHalfEdge[i]->getPoint();
1907 p3 = mHalfEdge[mHalfEdge[i]->getNext()]->getPoint();
1909 if ( p1 == -1 || p2 == -1 || p3 == -1 )
1915 bool twoforcededges;
1918 twoforcededges = ( mHalfEdge[i]->getForced() || edgeOnConvexHull( i ) ) && ( mHalfEdge[mHalfEdge[i]->getNext()]->getForced() || edgeOnConvexHull( mHalfEdge[i]->getNext() ) );
1920 if (
angle < mintol && !twoforcededges )
1922 edge_angle.insert( std::make_pair( i,
angle ) );
1923 angle_edge.insert( std::make_pair(
angle, i ) );
1928 for ( std::multimap<double, int>::const_iterator it = angle_edge.begin(); it != angle_edge.end(); ++it )
1930 QgsDebugMsg( QStringLiteral(
"angle: %1" ).arg( it->first ) );
1934 double minangle = 0;
1937 int minedgenextnext;
1941 while ( !edge_angle.empty() )
1943 minangle = angle_edge.begin()->first;
1944 QgsDebugMsg( QStringLiteral(
"minangle: %1" ).arg( minangle ) );
1945 minedge = angle_edge.begin()->second;
1946 minedgenext = mHalfEdge[minedge]->getNext();
1947 minedgenextnext = mHalfEdge[minedgenext]->getNext();
1950 if ( !
MathUtils::circumcenter( mPointVector[mHalfEdge[minedge]->getPoint()], mPointVector[mHalfEdge[minedgenext]->getPoint()], mPointVector[mHalfEdge[minedgenextnext]->getPoint()], &
circumcenter ) )
1952 QgsDebugMsg( QStringLiteral(
"warning, calculation of circumcenter failed" ) );
1954 dontexamine.insert( minedge );
1955 edge_angle.erase( minedge );
1956 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
1957 while ( minedgeiter->second != minedge )
1961 angle_edge.erase( minedgeiter );
1968 QgsDebugMsg( QStringLiteral(
"put circumcenter %1//%2 on dontexamine list because it is outside the convex hull" )
1970 dontexamine.insert( minedge );
1971 edge_angle.erase( minedge );
1972 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
1973 while ( minedgeiter->second != minedge )
1977 angle_edge.erase( minedgeiter );
1983 bool encroached =
false;
1986 int numhalfedges = mHalfEdge.count();
1987 for (
int i = 0; i < numhalfedges; i++ )
1989 if ( mHalfEdge[i]->getForced() || edgeOnConvexHull( i ) )
1996 int pointno = splitHalfEdge( i, 0.5 );
1999 int pointingedge = baseEdgeOfPoint( pointno );
2001 int actedge = pointingedge;
2004 double angle1, angle2, angle3;
2008 ed1 = mHalfEdge[actedge]->getDual();
2009 pt1 = mHalfEdge[ed1]->getPoint();
2010 ed2 = mHalfEdge[ed1]->getNext();
2011 pt2 = mHalfEdge[ed2]->getPoint();
2012 ed3 = mHalfEdge[ed2]->getNext();
2013 pt3 = mHalfEdge[ed3]->getPoint();
2016 if ( pt1 == -1 || pt2 == -1 || pt3 == -1 )
2021 angle1 =
MathUtils::angle( mPointVector[pt3], mPointVector[pt1], mPointVector[pt2], mPointVector[pt1] );
2022 angle2 =
MathUtils::angle( mPointVector[pt1], mPointVector[pt2], mPointVector[pt3], mPointVector[pt2] );
2023 angle3 =
MathUtils::angle( mPointVector[pt2], mPointVector[pt3], mPointVector[pt1], mPointVector[pt3] );
2026 bool twoforcededges1, twoforcededges2, twoforcededges3;
2028 if ( ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) ) && ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) ) )
2030 twoforcededges1 =
true;
2034 twoforcededges1 =
false;
2037 if ( ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) ) && ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) ) )
2039 twoforcededges2 =
true;
2043 twoforcededges2 =
false;
2046 if ( ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) ) && ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) ) )
2048 twoforcededges3 =
true;
2052 twoforcededges3 =
false;
2056 QSet<int>::iterator ed1iter = dontexamine.find( ed1 );
2057 if ( ed1iter != dontexamine.end() )
2060 dontexamine.erase( ed1iter );
2065 std::map<int, double>::iterator tempit1;
2066 tempit1 = edge_angle.find( ed1 );
2067 if ( tempit1 != edge_angle.end() )
2070 double angle = tempit1->second;
2071 edge_angle.erase( ed1 );
2072 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound(
angle );
2073 while ( tempit2->second != ed1 )
2077 angle_edge.erase( tempit2 );
2081 if ( angle1 < mintol && !twoforcededges1 )
2083 edge_angle.insert( std::make_pair( ed1, angle1 ) );
2084 angle_edge.insert( std::make_pair( angle1, ed1 ) );
2088 QSet<int>::iterator ed2iter = dontexamine.find( ed2 );
2089 if ( ed2iter != dontexamine.end() )
2092 dontexamine.erase( ed2iter );
2097 std::map<int, double>::iterator tempit1;
2098 tempit1 = edge_angle.find( ed2 );
2099 if ( tempit1 != edge_angle.end() )
2102 double angle = tempit1->second;
2103 edge_angle.erase( ed2 );
2104 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound(
angle );
2105 while ( tempit2->second != ed2 )
2109 angle_edge.erase( tempit2 );
2113 if ( angle2 < mintol && !twoforcededges2 )
2115 edge_angle.insert( std::make_pair( ed2, angle2 ) );
2116 angle_edge.insert( std::make_pair( angle2, ed2 ) );
2120 QSet<int>::iterator ed3iter = dontexamine.find( ed3 );
2121 if ( ed3iter != dontexamine.end() )
2124 dontexamine.erase( ed3iter );
2129 std::map<int, double>::iterator tempit1;
2130 tempit1 = edge_angle.find( ed3 );
2131 if ( tempit1 != edge_angle.end() )
2134 double angle = tempit1->second;
2135 edge_angle.erase( ed3 );
2136 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound(
angle );
2137 while ( tempit2->second != ed3 )
2141 angle_edge.erase( tempit2 );
2145 if ( angle3 < mintol && !twoforcededges3 )
2147 edge_angle.insert( std::make_pair( ed3, angle3 ) );
2148 angle_edge.insert( std::make_pair( angle3, ed3 ) );
2153 while ( actedge != pointingedge );
2161 QSet<int> influenceedges;
2163 if ( baseedge == -5 )
2166 edge_angle.erase( minedge );
2167 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
2168 while ( minedgeiter->second != minedge )
2172 angle_edge.erase( minedgeiter );
2175 else if ( baseedge == -25 )
2178 edge_angle.erase( minedge );
2179 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
2180 while ( minedgeiter->second != minedge )
2184 angle_edge.erase( minedgeiter );
2187 else if ( baseedge == -20 )
2189 baseedge = mEdgeWithPoint;
2192 evaluateInfluenceRegion( &
circumcenter, baseedge, influenceedges );
2193 evaluateInfluenceRegion( &
circumcenter, mHalfEdge[baseedge]->getNext(), influenceedges );
2194 evaluateInfluenceRegion( &
circumcenter, mHalfEdge[mHalfEdge[baseedge]->getNext()]->getNext(), influenceedges );
2196 for ( QSet<int>::iterator it = influenceedges.begin(); it != influenceedges.end(); ++it )
2198 if ( ( mHalfEdge[*it]->getForced() || edgeOnConvexHull( *it ) ) &&
MathUtils::inDiametral( mPointVector[mHalfEdge[*it]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[*it]->getDual()]->getPoint()], &
circumcenter ) )
2202 const int pointno = splitHalfEdge( *it, 0.5 );
2206 const int pointingedge = baseEdgeOfPoint( pointno );
2208 int actedge = pointingedge;
2211 double angle1, angle2, angle3;
2215 ed1 = mHalfEdge[actedge]->getDual();
2216 pt1 = mHalfEdge[ed1]->getPoint();
2217 ed2 = mHalfEdge[ed1]->getNext();
2218 pt2 = mHalfEdge[ed2]->getPoint();
2219 ed3 = mHalfEdge[ed2]->getNext();
2220 pt3 = mHalfEdge[ed3]->getPoint();
2223 if ( pt1 == -1 || pt2 == -1 || pt3 == -1 )
2228 angle1 =
MathUtils::angle( mPointVector[pt3], mPointVector[pt1], mPointVector[pt2], mPointVector[pt1] );
2229 angle2 =
MathUtils::angle( mPointVector[pt1], mPointVector[pt2], mPointVector[pt3], mPointVector[pt2] );
2230 angle3 =
MathUtils::angle( mPointVector[pt2], mPointVector[pt3], mPointVector[pt1], mPointVector[pt3] );
2233 bool twoforcededges1, twoforcededges2, twoforcededges3;
2237 twoforcededges1 = ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) ) && ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) );
2239 twoforcededges2 = ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) ) && ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) );
2241 twoforcededges3 = ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) ) && ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) );
2245 const QSet<int>::iterator ed1iter = dontexamine.find( ed1 );
2246 if ( ed1iter != dontexamine.end() )
2249 dontexamine.erase( ed1iter );
2254 std::map<int, double>::iterator tempit1;
2255 tempit1 = edge_angle.find( ed1 );
2256 if ( tempit1 != edge_angle.end() )
2259 const double angle = tempit1->second;
2260 edge_angle.erase( ed1 );
2261 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound(
angle );
2262 while ( tempit2->second != ed1 )
2266 angle_edge.erase( tempit2 );
2270 if ( angle1 < mintol && !twoforcededges1 )
2272 edge_angle.insert( std::make_pair( ed1, angle1 ) );
2273 angle_edge.insert( std::make_pair( angle1, ed1 ) );
2277 const QSet<int>::iterator ed2iter = dontexamine.find( ed2 );
2278 if ( ed2iter != dontexamine.end() )
2281 dontexamine.erase( ed2iter );
2286 std::map<int, double>::iterator tempit1;
2287 tempit1 = edge_angle.find( ed2 );
2288 if ( tempit1 != edge_angle.end() )
2291 const double angle = tempit1->second;
2292 edge_angle.erase( ed2 );
2293 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound(
angle );
2294 while ( tempit2->second != ed2 )
2298 angle_edge.erase( tempit2 );
2302 if ( angle2 < mintol && !twoforcededges2 )
2304 edge_angle.insert( std::make_pair( ed2, angle2 ) );
2305 angle_edge.insert( std::make_pair( angle2, ed2 ) );
2309 const QSet<int>::iterator ed3iter = dontexamine.find( ed3 );
2310 if ( ed3iter != dontexamine.end() )
2313 dontexamine.erase( ed3iter );
2318 std::map<int, double>::iterator tempit1;
2319 tempit1 = edge_angle.find( ed3 );
2320 if ( tempit1 != edge_angle.end() )
2323 const double angle = tempit1->second;
2324 edge_angle.erase( ed3 );
2325 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound(
angle );
2326 while ( tempit2->second != ed3 )
2330 angle_edge.erase( tempit2 );
2334 if ( angle3 < mintol && !twoforcededges3 )
2336 edge_angle.insert( std::make_pair( ed3, angle3 ) );
2337 angle_edge.insert( std::make_pair( angle3, ed3 ) );
2342 while ( actedge != pointingedge );
2358 if ( pointno == -100 || pointno == mTwiceInsPoint )
2360 if ( pointno == -100 )
2362 QgsDebugMsg( QStringLiteral(
"put circumcenter %1//%2 on dontexamine list because of numerical instabilities" )
2365 else if ( pointno == mTwiceInsPoint )
2367 QgsDebugMsg( QStringLiteral(
"put circumcenter %1//%2 on dontexamine list because it is already inserted" )
2371 for (
int i = 0; i < mPointVector.count(); i++ )
2380 QgsDebugMsg( QStringLiteral(
"point is not present in the triangulation" ) );
2384 dontexamine.insert( minedge );
2385 edge_angle.erase( minedge );
2386 std::multimap<double, int>::iterator minedgeiter = angle_edge.lower_bound( minangle );
2387 while ( minedgeiter->second != minedge )
2391 angle_edge.erase( minedgeiter );
2396 QgsDebugMsg( QStringLiteral(
"circumcenter added" ) );
2400 const int pointingedge = baseEdgeOfPoint( pointno );
2402 int actedge = pointingedge;
2405 double angle1, angle2, angle3;
2409 ed1 = mHalfEdge[actedge]->getDual();
2410 pt1 = mHalfEdge[ed1]->getPoint();
2411 ed2 = mHalfEdge[ed1]->getNext();
2412 pt2 = mHalfEdge[ed2]->getPoint();
2413 ed3 = mHalfEdge[ed2]->getNext();
2414 pt3 = mHalfEdge[ed3]->getPoint();
2417 if ( pt1 == -1 || pt2 == -1 || pt3 == -1 )
2422 angle1 =
MathUtils::angle( mPointVector[pt3], mPointVector[pt1], mPointVector[pt2], mPointVector[pt1] );
2423 angle2 =
MathUtils::angle( mPointVector[pt1], mPointVector[pt2], mPointVector[pt3], mPointVector[pt2] );
2424 angle3 =
MathUtils::angle( mPointVector[pt2], mPointVector[pt3], mPointVector[pt1], mPointVector[pt3] );
2427 bool twoforcededges1, twoforcededges2, twoforcededges3;
2429 twoforcededges1 = ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) ) && ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) );
2431 twoforcededges2 = ( mHalfEdge[ed2]->getForced() || edgeOnConvexHull( ed2 ) ) && ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) );
2433 twoforcededges3 = ( mHalfEdge[ed3]->getForced() || edgeOnConvexHull( ed3 ) ) && ( mHalfEdge[ed1]->getForced() || edgeOnConvexHull( ed1 ) );
2437 const QSet<int>::iterator ed1iter = dontexamine.find( ed1 );
2438 if ( ed1iter != dontexamine.end() )
2441 dontexamine.erase( ed1iter );
2446 std::map<int, double>::iterator tempit1;
2447 tempit1 = edge_angle.find( ed1 );
2448 if ( tempit1 != edge_angle.end() )
2451 const double angle = tempit1->second;
2452 edge_angle.erase( ed1 );
2453 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound(
angle );
2454 while ( tempit2->second != ed1 )
2458 angle_edge.erase( tempit2 );
2462 if ( angle1 < mintol && !twoforcededges1 )
2464 edge_angle.insert( std::make_pair( ed1, angle1 ) );
2465 angle_edge.insert( std::make_pair( angle1, ed1 ) );
2470 const QSet<int>::iterator ed2iter = dontexamine.find( ed2 );
2471 if ( ed2iter != dontexamine.end() )
2474 dontexamine.erase( ed2iter );
2479 std::map<int, double>::iterator tempit1;
2480 tempit1 = edge_angle.find( ed2 );
2481 if ( tempit1 != edge_angle.end() )
2484 const double angle = tempit1->second;
2485 edge_angle.erase( ed2 );
2486 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound(
angle );
2487 while ( tempit2->second != ed2 )
2491 angle_edge.erase( tempit2 );
2495 if ( angle2 < mintol && !twoforcededges2 )
2497 edge_angle.insert( std::make_pair( ed2, angle2 ) );
2498 angle_edge.insert( std::make_pair( angle2, ed2 ) );
2502 const QSet<int>::iterator ed3iter = dontexamine.find( ed3 );
2503 if ( ed3iter != dontexamine.end() )
2506 dontexamine.erase( ed3iter );
2511 std::map<int, double>::iterator tempit1;
2512 tempit1 = edge_angle.find( ed3 );
2513 if ( tempit1 != edge_angle.end() )
2516 const double angle = tempit1->second;
2517 edge_angle.erase( ed3 );
2518 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound(
angle );
2519 while ( tempit2->second != ed3 )
2523 angle_edge.erase( tempit2 );
2527 if ( angle3 < mintol && !twoforcededges3 )
2529 edge_angle.insert( std::make_pair( ed3, angle3 ) );
2530 angle_edge.insert( std::make_pair( angle3, ed3 ) );
2535 while ( actedge != pointingedge );
2541 for ( QSet<int>::iterator it = dontexamine.begin(); it != dontexamine.end(); ++it )
2543 QgsDebugMsg( QStringLiteral(
"edge nr. %1 is in dontexamine" ).arg( *it ) );
2549 bool QgsDualEdgeTriangulation::swapPossible(
unsigned int edge )
const
2552 if ( mHalfEdge[edge]->getForced() )
2558 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 )
2563 QgsPoint *pta = mPointVector[mHalfEdge[edge]->getPoint()];
2564 QgsPoint *ptb = mPointVector[mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint()];
2565 QgsPoint *ptc = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getNext()]->getNext()]->getPoint()];
2566 QgsPoint *ptd = mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint()];
2586 void QgsDualEdgeTriangulation::triangulatePolygon( QList<int> *poly, QList<int> *free,
int mainedge )
2590 if ( poly->count() == 3 )
2596 QList<int>::const_iterator iterator = ++( poly->constBegin() );
2597 double distance =
MathUtils::distPointFromLine( mPointVector[mHalfEdge[( *iterator )]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[mainedge]->getPoint()] );
2598 int distedge = ( *iterator );
2599 int nextdistedge = mHalfEdge[( *iterator )]->getNext();
2602 while ( iterator != --( poly->constEnd() ) )
2604 if (
MathUtils::distPointFromLine( mPointVector[mHalfEdge[( *iterator )]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[mainedge]->getPoint()] ) < distance )
2606 distedge = ( *iterator );
2607 nextdistedge = mHalfEdge[( *iterator )]->getNext();
2608 distance =
MathUtils::distPointFromLine( mPointVector[mHalfEdge[( *iterator )]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[mainedge]->getPoint()] );
2613 if ( nextdistedge == ( *( --poly->end() ) ) )
2615 const int inserta = free->first();
2616 const int insertb = mHalfEdge[inserta]->getDual();
2619 mHalfEdge[inserta]->setNext( ( poly->at( 1 ) ) );
2620 mHalfEdge[inserta]->setPoint( mHalfEdge[mainedge]->getPoint() );
2621 mHalfEdge[insertb]->setNext( nextdistedge );
2622 mHalfEdge[insertb]->setPoint( mHalfEdge[distedge]->getPoint() );
2623 mHalfEdge[distedge]->setNext( inserta );
2624 mHalfEdge[mainedge]->setNext( insertb );
2627 for ( iterator = ( ++( poly->constBegin() ) ); ( *iterator ) != nextdistedge; ++iterator )
2629 polya.append( ( *iterator ) );
2631 polya.prepend( inserta );
2635 for ( iterator = polya.begin(); iterator != polya.end(); ++iterator )
2641 triangulatePolygon( &polya, free, inserta );
2644 else if ( distedge == ( *( ++poly->begin() ) ) )
2646 const int inserta = free->first();
2647 const int insertb = mHalfEdge[inserta]->getDual();
2650 mHalfEdge[inserta]->setNext( ( poly->at( 2 ) ) );
2651 mHalfEdge[inserta]->setPoint( mHalfEdge[distedge]->getPoint() );
2652 mHalfEdge[insertb]->setNext( mainedge );
2653 mHalfEdge[insertb]->setPoint( mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint() );
2654 mHalfEdge[distedge]->setNext( insertb );
2655 mHalfEdge[( *( --poly->end() ) )]->setNext( inserta );
2658 iterator = poly->constBegin();
2660 while ( iterator != poly->constEnd() )
2662 polya.append( ( *iterator ) );
2665 polya.prepend( inserta );
2667 triangulatePolygon( &polya, free, inserta );
2672 const int inserta = free->first();
2673 const int insertb = mHalfEdge[inserta]->getDual();
2676 const int insertc = free->first();
2677 const int insertd = mHalfEdge[insertc]->getDual();
2680 mHalfEdge[inserta]->setNext( ( poly->at( 1 ) ) );
2681 mHalfEdge[inserta]->setPoint( mHalfEdge[mainedge]->getPoint() );
2682 mHalfEdge[insertb]->setNext( insertd );
2683 mHalfEdge[insertb]->setPoint( mHalfEdge[distedge]->getPoint() );
2684 mHalfEdge[insertc]->setNext( nextdistedge );
2685 mHalfEdge[insertc]->setPoint( mHalfEdge[distedge]->getPoint() );
2686 mHalfEdge[insertd]->setNext( mainedge );
2687 mHalfEdge[insertd]->setPoint( mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint() );
2689 mHalfEdge[distedge]->setNext( inserta );
2690 mHalfEdge[mainedge]->setNext( insertb );
2691 mHalfEdge[( *( --poly->end() ) )]->setNext( insertc );
2697 for ( iterator = ++( poly->constBegin() ); ( *iterator ) != nextdistedge; ++iterator )
2699 polya.append( ( *iterator ) );
2701 polya.prepend( inserta );
2704 while ( iterator != poly->constEnd() )
2706 polyb.append( ( *iterator ) );
2709 polyb.prepend( insertc );
2711 triangulatePolygon( &polya, free, inserta );
2712 triangulatePolygon( &polyb, free, insertc );
2718 QgsDebugMsg( QStringLiteral(
"warning, null pointer" ) );
2726 unsigned int actedge = mEdgeInside;
2734 if ( runs > MAX_BASE_ITERATIONS )
2736 QgsDebugMsg( QStringLiteral(
"warning, instability detected: Point coordinates: %1//%2" ).arg( x ).arg( y ) );
2740 if (
MathUtils::leftOf(
point, mPointVector[mHalfEdge[mHalfEdge[actedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[actedge]->getPoint()] ) < ( -
leftOfTresh ) )
2749 else if ( fabs(
MathUtils::leftOf(
point, mPointVector[mHalfEdge[mHalfEdge[actedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[actedge]->getPoint()] ) ) <=
leftOfTresh )
2752 mEdgeWithPoint = actedge;
2762 actedge = mHalfEdge[actedge]->getDual();
2768 actedge = mHalfEdge[actedge]->getNext();
2769 if ( mHalfEdge[actedge]->getPoint() == -1 )
2775 mEdgeOutside = (
unsigned int )mHalfEdge[mHalfEdge[actedge]->getNext()]->getNext();
2785 if ( numinstabs > 0 )
2787 QgsDebugMsg( QStringLiteral(
"numerical instabilities" ) );
2795 mEdgeInside = actedge;
2800 bool DualEdgeTriangulation::readFromTAFF( QString filename )
2802 QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
2804 QFile file( filename );
2805 file.open( IO_Raw | IO_ReadOnly );
2806 QBuffer buffer( file.readAll() );
2809 QTextStream textstream( &buffer );
2810 buffer.open( IO_ReadOnly );
2813 int numberofhalfedges;
2817 while ( buff.mid( 0, 4 ) !=
"TRIA" )
2819 buff = textstream.readLine();
2821 while ( buff.mid( 0, 4 ) !=
"NEDG" )
2823 buff = textstream.readLine();
2825 numberofhalfedges = buff.section(
' ', 1, 1 ).toInt();
2826 mHalfEdge.resize( numberofhalfedges );
2829 while ( buff.mid( 0, 4 ) !=
"DATA" )
2834 int nr1, nr2, dual1, dual2, point1, point2, next1, next2, fo1, fo2, b1, b2;
2835 bool forced1, forced2, break1, break2;
2839 QProgressBar *edgebar =
new QProgressBar();
2840 edgebar->setCaption( tr(
"Reading edges…" ) );
2841 edgebar->setTotalSteps( numberofhalfedges / 2 );
2842 edgebar->setMinimumWidth( 400 );
2843 edgebar->move( 500, 500 );
2846 for (
int i = 0; i < numberofhalfedges / 2; i++ )
2848 if ( i % 1000 == 0 )
2850 edgebar->setProgress( i );
2854 textstream >> point1;
2855 textstream >> next1;
2879 textstream >> point2;
2880 textstream >> next2;
2918 mHalfEdge.insert( nr1, hf1 );
2919 mHalfEdge.insert( nr2, hf2 );
2923 edgebar->setProgress( numberofhalfedges / 2 );
2927 for (
int i = 0; i < numberofhalfedges; i++ )
2930 a = mHalfEdge[i]->getPoint();
2931 b = mHalfEdge[mHalfEdge[i]->getDual()]->getPoint();
2932 c = mHalfEdge[mHalfEdge[i]->getNext()]->getPoint();
2933 d = mHalfEdge[mHalfEdge[mHalfEdge[i]->getDual()]->getNext()]->getPoint();
2934 if ( a != -1 && b != -1 &&
c != -1 && d != -1 )
2942 while ( buff.mid( 0, 4 ) !=
"POIN" )
2944 buff = textstream.readLine();
2947 while ( buff.mid( 0, 4 ) !=
"NPTS" )
2949 buff = textstream.readLine();
2952 numberofpoints = buff.section(
' ', 1, 1 ).toInt();
2953 mPointVector.resize( numberofpoints );
2955 while ( buff.mid( 0, 4 ) !=
"DATA" )
2960 QProgressBar *pointbar =
new QProgressBar();
2961 pointbar->setCaption( tr(
"Reading points…" ) );
2962 pointbar->setTotalSteps( numberofpoints );
2963 pointbar->setMinimumWidth( 400 );
2964 pointbar->move( 500, 500 );
2969 for (
int i = 0; i < numberofpoints; i++ )
2971 if ( i % 1000 == 0 )
2973 pointbar->setProgress( i );
2983 mPointVector.insert( i, p );
2999 else if ( x > xMax )
3008 else if ( y > yMax )
3015 pointbar->setProgress( numberofpoints );
3017 QApplication::restoreOverrideCursor();
3021 bool DualEdgeTriangulation::saveToTAFF( QString filename )
const
3023 QFile outputfile( filename );
3024 if ( !outputfile.open( IO_WriteOnly ) )
3026 QMessageBox::warning( 0, tr(
"Warning" ), tr(
"File could not be written." ), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton );
3030 QTextStream outstream( &outputfile );
3031 outstream.precision( 9 );
3034 outstream <<
"TRIA" << std::endl << std::flush;
3035 outstream <<
"NEDG " << mHalfEdge.count() << std::endl << std::flush;
3036 outstream <<
"PANO 1" << std::endl << std::flush;
3037 outstream <<
"DATA ";
3039 bool *cont =
new bool[mHalfEdge.count()];
3040 for (
unsigned int i = 0; i <= mHalfEdge.count() - 1; i++ )
3045 for (
unsigned int i = 0; i < mHalfEdge.count(); i++ )
3052 int dual = mHalfEdge[i]->getDual();
3053 outstream << i <<
" " << mHalfEdge[i]->getPoint() <<
" " << mHalfEdge[i]->getNext() <<
" " << mHalfEdge[i]->getForced() <<
" " << mHalfEdge[i]->getBreak() <<
" ";
3054 outstream << dual <<
" " << mHalfEdge[dual]->getPoint() <<
" " << mHalfEdge[dual]->getNext() <<
" " << mHalfEdge[dual]->getForced() <<
" " << mHalfEdge[dual]->getBreak() <<
" ";
3058 outstream << std::endl << std::flush;
3059 outstream << std::endl << std::flush;
3064 outstream <<
"POIN" << std::endl << std::flush;
3065 outstream <<
"NPTS " << getNumberOfPoints() << std::endl << std::flush;
3066 outstream <<
"PATT 3" << std::endl << std::flush;
3067 outstream <<
"DATA ";
3069 for (
int i = 0; i < getNumberOfPoints(); i++ )
3072 outstream << p->getX() <<
" " << p->getY() <<
" " << p->getZ() <<
" ";
3074 outstream << std::endl << std::flush;
3075 outstream << std::endl << std::flush;
3084 const int edge1 = baseEdgeOfTriangle( p );
3091 edge2 = mHalfEdge[edge1]->getNext();
3092 edge3 = mHalfEdge[edge2]->getNext();
3093 point1 =
point( mHalfEdge[edge1]->getPoint() );
3094 point2 =
point( mHalfEdge[edge2]->getPoint() );
3095 point3 =
point( mHalfEdge[edge3]->getPoint() );
3096 if ( point1 && point2 && point3 )
3099 double dist1, dist2, dist3;
3103 if ( dist1 <= dist2 && dist1 <= dist3 )
3106 if ( swapPossible( edge1 ) )
3108 doOnlySwap( edge1 );
3111 else if ( dist2 <= dist1 && dist2 <= dist3 )
3114 if ( swapPossible( edge2 ) )
3116 doOnlySwap( edge2 );
3119 else if ( dist3 <= dist1 && dist3 <= dist2 )
3122 if ( swapPossible( edge3 ) )
3124 doOnlySwap( edge3 );
3146 const int edge1 = baseEdgeOfTriangle( p );
3149 const int edge2 = mHalfEdge[edge1]->getNext();
3150 const int edge3 = mHalfEdge[edge2]->getNext();
3154 if ( point1 && point2 && point3 )
3160 if ( dist1 <= dist2 && dist1 <= dist3 )
3162 p1 = mHalfEdge[edge1]->getPoint();
3163 p2 = mHalfEdge[mHalfEdge[edge1]->getNext()]->getPoint();
3164 p3 = mHalfEdge[mHalfEdge[edge1]->getDual()]->getPoint();
3165 p4 = mHalfEdge[mHalfEdge[mHalfEdge[edge1]->getDual()]->getNext()]->getPoint();
3167 else if ( dist2 <= dist1 && dist2 <= dist3 )
3169 p1 = mHalfEdge[edge2]->getPoint();
3170 p2 = mHalfEdge[mHalfEdge[edge2]->getNext()]->getPoint();
3171 p3 = mHalfEdge[mHalfEdge[edge2]->getDual()]->getPoint();
3172 p4 = mHalfEdge[mHalfEdge[mHalfEdge[edge2]->getDual()]->getNext()]->getPoint();
3176 p1 = mHalfEdge[edge3]->getPoint();
3177 p2 = mHalfEdge[mHalfEdge[edge3]->getNext()]->getPoint();
3178 p3 = mHalfEdge[mHalfEdge[edge3]->getDual()]->getPoint();
3179 p4 = mHalfEdge[mHalfEdge[mHalfEdge[edge3]->getDual()]->getNext()]->getPoint();
3190 QgsDebugMsg( QStringLiteral(
"warning: null pointer" ) );
3195 QgsDebugMsg( QStringLiteral(
"Edge number negative" ) );
3207 bool *alreadyVisitedEdges =
new bool[mHalfEdge.size()];
3208 if ( !alreadyVisitedEdges )
3214 for (
int i = 0; i < mHalfEdge.size(); ++i )
3216 alreadyVisitedEdges[i] =
false;
3219 for (
int i = 0; i < mHalfEdge.size(); ++i )
3224 HalfEdge *currentEdge = mHalfEdge[i];
3225 if ( currentEdge->
getPoint() != -1 && mHalfEdge[currentEdge->
getDual()]->getPoint() != -1 && !alreadyVisitedEdges[currentEdge->
getDual()] )
3231 QgsPoint *p2 = mPointVector[mHalfEdge[currentEdge->
getDual()]->getPoint()];
3239 QString attributeString;
3244 attributeString = QStringLiteral(
"break line" );
3248 attributeString = QStringLiteral(
"structure line" );
3255 alreadyVisitedEdges[i] =
true;
3258 delete [] alreadyVisitedEdges;
3265 const QVector<bool> alreadyVisitedEdges( mHalfEdge.count(),
false );
3270 QVector< bool> edgeToTreat( mHalfEdge.count(),
true );
3271 QHash<HalfEdge *, int > edgesHash;
3272 for (
int i = 0; i < mHalfEdge.count(); ++i )
3274 edgesHash.insert( mHalfEdge[i], i );
3283 const int edgeCount = edgeToTreat.count();
3284 for (
int i = 0 ; i < edgeCount; ++i )
3286 bool containVirtualPoint =
false;
3287 if ( edgeToTreat[i] )
3289 HalfEdge *currentEdge = mHalfEdge[i];
3294 edgeToTreat[edgesHash.value( currentEdge )] =
false;
3295 face.append( currentEdge->
getPoint() );
3296 containVirtualPoint |= currentEdge->
getPoint() == -1;
3297 currentEdge = mHalfEdge.at( currentEdge->
getNext() );
3299 while ( currentEdge != firstEdge && !containVirtualPoint && ( !feedback || !feedback->
isCanceled() ) );
3300 if ( !containVirtualPoint )
3301 mesh.
faces.append( face );
3305 feedback->
setProgress( ( 100 * i ) / edgeCount ) ;
3312 double QgsDualEdgeTriangulation::swapMinAngle(
int edge )
const
3315 QgsPoint *p2 =
point( mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint() );
3316 QgsPoint *p3 =
point( mHalfEdge[mHalfEdge[edge]->getDual()]->getPoint() );
3317 QgsPoint *p4 =
point( mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint() );
3324 if ( angle2 < minangle )
3329 if ( angle3 < minangle )
3334 if ( angle4 < minangle )
3339 if ( angle5 < minangle )
3344 if ( angle6 < minangle )
3352 int QgsDualEdgeTriangulation::splitHalfEdge(
int edge,
float position )
3355 if ( position < 0 || position > 1 )
3357 QgsDebugMsg( QStringLiteral(
"warning, position is not between 0 and 1" ) );
3361 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 );
3366 p->
setZ( zvaluepoint.z() );
3369 if ( mPointVector.count() >= mPointVector.size() )
3371 mPointVector.resize( mPointVector.count() + 1 );
3373 QgsDebugMsg( QStringLiteral(
"inserting point nr. %1, %2//%3//%4" ).arg( mPointVector.count() ).arg( p->
x() ).arg( p->
y() ).arg( p->
z() ) );
3374 mPointVector.insert( mPointVector.count(), p );
3377 const int dualedge = mHalfEdge[edge]->getDual();
3378 const int edge1 = insertEdge( -10, -10, mPointVector.count() - 1,
false,
false );
3379 const int edge2 = insertEdge( edge1, mHalfEdge[mHalfEdge[edge]->getNext()]->getNext(), mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint(),
false,
false );
3380 const int edge3 = insertEdge( -10, mHalfEdge[mHalfEdge[dualedge]->getNext()]->getNext(), mHalfEdge[mHalfEdge[dualedge]->getNext()]->getPoint(),
false,
false );
3381 const int edge4 = insertEdge( edge3, dualedge, mPointVector.count() - 1,
false,
false );
3382 const int edge5 = insertEdge( -10, mHalfEdge[edge]->getNext(), mHalfEdge[edge]->getPoint(), mHalfEdge[edge]->getBreak(), mHalfEdge[edge]->getForced() );
3383 const int edge6 = insertEdge( edge5, edge3, mPointVector.count() - 1, mHalfEdge[dualedge]->getBreak(), mHalfEdge[dualedge]->getForced() );
3384 mHalfEdge[edge1]->setDual( edge2 );
3385 mHalfEdge[edge1]->setNext( edge5 );
3386 mHalfEdge[edge3]->setDual( edge4 );
3387 mHalfEdge[edge5]->setDual( edge6 );
3390 mHalfEdge[mHalfEdge[edge]->getNext()]->setNext( edge1 );
3391 mHalfEdge[mHalfEdge[dualedge]->getNext()]->setNext( edge4 );
3392 mHalfEdge[edge]->setNext( edge2 );
3393 mHalfEdge[edge]->setPoint( mPointVector.count() - 1 );
3394 mHalfEdge[mHalfEdge[edge3]->getNext()]->setNext( edge6 );
3397 checkSwapRecursively( mHalfEdge[edge5]->getNext(), 0 );
3398 checkSwapRecursively( mHalfEdge[edge2]->getNext(), 0 );
3399 checkSwapRecursively( mHalfEdge[dualedge]->getNext(), 0 );
3400 checkSwapRecursively( mHalfEdge[edge3]->getNext(), 0 );
3404 return mPointVector.count() - 1;
3407 bool QgsDualEdgeTriangulation::edgeOnConvexHull(
int edge )
3409 return ( mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint() == -1 || mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint() == -1 );
3412 void QgsDualEdgeTriangulation::evaluateInfluenceRegion(
QgsPoint *point,
int edge, QSet<int> &set )
3414 if ( set.find( edge ) == set.end() )
3423 if ( !mHalfEdge[edge]->getForced() && !edgeOnConvexHull( edge ) )
3426 if (
inCircle( *
point, *mPointVector[mHalfEdge[mHalfEdge[edge]->getDual()]->getPoint()], *mPointVector[mHalfEdge[edge]->getPoint()], *mPointVector[mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint()] ) )
3428 evaluateInfluenceRegion(
point, mHalfEdge[mHalfEdge[edge]->getDual()]->getNext(), set );
3429 evaluateInfluenceRegion(
point, mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getNext(), set );
3434 int QgsDualEdgeTriangulation::firstEdgeOutSide()
3437 while ( ( mHalfEdge[mHalfEdge[edge]->getNext()]->getPoint() != -1 ||
3438 mHalfEdge[edge]->getPoint() == -1 || mHalfEdge[mHalfEdge[edge]->getDual()]->getPoint() == -1 ) &&
3439 edge < mHalfEdge.count() )
3444 if ( edge >= mHalfEdge.count() )
3450 void QgsDualEdgeTriangulation::removeLastPoint()
3452 if ( mPointVector.isEmpty() )
3454 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...
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 SIP_HOLDGIL
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.
double distance(double x, double y) const SIP_HOLDGIL
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
void setX(double x) SIP_HOLDGIL
Sets the point's x-coordinate.
void setY(double y) SIP_HOLDGIL
Sets the point's y-coordinate.
void setZ(double z) SIP_HOLDGIL
Sets the point's z-coordinate.
double distanceSquared(double x, double y) const SIP_HOLDGIL
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.
QVector< int > QgsMeshFace
List of vertex indexes.
Mesh - vertices, edges and faces.
QVector< QgsMeshVertex > vertices
QVector< QgsMeshFace > faces