42 for (
int i = 0; i <
mHalfEdge.count(); i++ )
51 QgsDebugMsg( QStringLiteral(
"performing consistency test" ) );
53 for (
int i = 0; i <
mHalfEdge.count(); i++ )
59 QgsDebugMsg( QStringLiteral(
"warning, first test failed" ) );
63 QgsDebugMsg( QStringLiteral(
"warning, second test failed" ) );
66 QgsDebugMsg( QStringLiteral(
"consistency test finished" ) );
72 int currentpoint = -10;
75 for (
const QgsPoint &point : points )
79 if ( actpoint != -100 )
85 if ( actpoint == -100 )
90 for ( ; i < points.size(); ++i )
93 if ( currentpoint != -100 && actpoint != -100 && currentpoint != actpoint )
97 actpoint = currentpoint;
125 unsigned int zedge =
insertEdge( -10, -10, -1,
false,
false );
126 unsigned int fedge =
insertEdge( static_cast<int>( zedge ), static_cast<int>( zedge ), 0,
false,
false );
127 (
mHalfEdge.at( zedge ) )->setDual( static_cast<int>( fedge ) );
128 (
mHalfEdge.at( zedge ) )->setNext( static_cast<int>( fedge ) );
137 QgsDebugMsg( QStringLiteral(
"second point is the same as the first point, it thus has not been inserted" ) );
144 unsigned int sedge =
insertEdge( -10, -10, 1,
false,
false );
145 unsigned int tedge =
insertEdge( static_cast<int>( sedge ), 0, 0,
false,
false );
146 unsigned int foedge =
insertEdge( -10, 4, 1,
false,
false );
147 unsigned int fiedge =
insertEdge( static_cast<int>( foedge ), 1, -1,
false,
false );
148 mHalfEdge.at( sedge )->setDual( static_cast<int>( tedge ) );
149 mHalfEdge.at( sedge )->setNext( static_cast<int>( fiedge ) );
150 mHalfEdge.at( foedge )->setDual( static_cast<int>( fiedge ) );
151 mHalfEdge.at( foedge )->setNext( static_cast<int>( tedge ) );
152 mHalfEdge.at( 0 )->setNext( static_cast<int>( foedge ) );
153 mHalfEdge.at( 1 )->setNext( static_cast<int>( sedge ) );
165 unsigned int edgea =
insertEdge( -10, -10, 2,
false,
false );
166 unsigned int edgeb =
insertEdge( static_cast<int>( edgea ), 5, 1,
false,
false );
167 unsigned int edgec =
insertEdge( -10, static_cast<int>( edgeb ), 2,
false,
false );
168 unsigned int edged =
insertEdge( -10, 2, 0,
false,
false );
169 unsigned int edgee =
insertEdge( static_cast<int>( edged ), -10, 2,
false,
false );
170 unsigned int edgef =
insertEdge( static_cast<int>( edgec ), 1, -1,
false,
false );
171 mHalfEdge.at( edgea )->setDual( static_cast<int>( edgeb ) );
172 mHalfEdge.at( edgea )->setNext( static_cast<int>( edged ) );
173 mHalfEdge.at( edgec )->setDual( static_cast<int>( edgef ) );
174 mHalfEdge.at( edged )->setDual( static_cast<int>( edgee ) );
175 mHalfEdge.at( edgee )->setNext( static_cast<int>( edgef ) );
176 mHalfEdge.at( 5 )->setNext( static_cast<int>( edgec ) );
177 mHalfEdge.at( 1 )->setNext( static_cast<int>( edgee ) );
178 mHalfEdge.at( 2 )->setNext( static_cast<int>( edgea ) );
184 unsigned int edgea =
insertEdge( -10, -10, 2,
false,
false );
185 unsigned int edgeb =
insertEdge( static_cast<int>( edgea ), 0, 0,
false,
false );
186 unsigned int edgec =
insertEdge( -10, static_cast<int>( edgeb ), 2,
false,
false );
187 unsigned int edged =
insertEdge( -10, 3, 1,
false,
false );
188 unsigned int edgee =
insertEdge( static_cast<int>( edged ), -10, 2,
false,
false );
189 unsigned int edgef =
insertEdge( static_cast<int>( edgec ), 4, -1,
false,
false );
190 mHalfEdge.at( edgea )->setDual( static_cast<int>( edgeb ) );
191 mHalfEdge.at( edgea )->setNext( static_cast<int>( edged ) );
192 mHalfEdge.at( edgec )->setDual( static_cast<int>( edgef ) );
193 mHalfEdge.at( edged )->setDual( static_cast<int>( edgee ) );
194 mHalfEdge.at( edgee )->setNext( static_cast<int>( edgef ) );
195 mHalfEdge.at( 0 )->setNext( static_cast<int>( edgec ) );
196 mHalfEdge.at( 4 )->setNext( static_cast<int>( edgee ) );
197 mHalfEdge.at( 3 )->setNext( static_cast<int>( edgea ) );
203 QgsDebugMsg( QStringLiteral(
"error: third point is on the same line as the first and the second point. It thus has not been inserted into the triangulation" ) );
254 unsigned int edge5 =
insertEdge( edge3, -10, -1,
false,
false );
267 unsigned int index = ccwedge;
274 if ( toswap == cwedge )
284 else if ( number >= 0 )
286 int nextnumber =
mHalfEdge[number]->getNext();
291 unsigned int edge2 =
insertEdge( static_cast<int>( edge1 ), -10,
mPointVector.count() - 1,
false, false );
293 unsigned int edge4 =
insertEdge( static_cast<int>( edge3 ), static_cast<int>( edge1 ),
mPointVector.count() - 1,
false, false );
295 unsigned int edge6 =
insertEdge( static_cast<int>( edge5 ), static_cast<int>( edge3 ),
mPointVector.count() - 1,
false, false );
298 mHalfEdge.at( edge1 )->setDual( static_cast<int>( edge2 ) );
299 mHalfEdge.at( edge2 )->setNext( static_cast<int>( edge5 ) );
300 mHalfEdge.at( edge3 )->setDual( static_cast<int>( edge4 ) );
301 mHalfEdge.at( edge5 )->setDual( static_cast<int>( edge6 ) );
302 mHalfEdge.at( number )->setNext( static_cast<int>( edge2 ) );
303 mHalfEdge.at( nextnumber )->setNext( static_cast<int>( edge4 ) );
304 mHalfEdge.at( nextnextnumber )->setNext( static_cast<int>( edge6 ) );
313 else if ( number == -20 )
348 else if ( number == -100 || number == -5 )
356 else if ( number == -25 )
361 existingPoint->
setZ( std::max( newPoint->
z(), existingPoint->
z() ) );
379 for (
int i = 0; i <
mHalfEdge.count(); i++ )
393 if ( control > 1000000 )
399 for (
int i = 0; i <
mHalfEdge.count(); i++ )
409 int topoint =
mHalfEdge[actedge]->getPoint();
411 if ( frompoint == -1 || topoint == -1 )
413 for (
int i = 0; i <
mHalfEdge.count(); i++ )
432 else if ( leftofnumber <= 0.0 )
451 int firstendp = 0, secendp = 0, thendp = 0, fouendp = 0;
472 else if ( leftofvalue == 0 )
478 secendp =
mHalfEdge[actedge]->getPoint();
480 else if ( nulls == 1 )
484 fouendp =
mHalfEdge[actedge]->getPoint();
527 if ( numinstabs > 0 )
537 if ( firstendp == thendp || firstendp == fouendp )
543 else if ( secendp == thendp || secendp == fouendp )
572 if ( x1 < x2 && x1 < x3 )
576 else if ( x2 < x1 && x2 < x3 )
580 else if ( x3 < x1 && x3 < x2 )
629 QgsDebugMsg( QStringLiteral(
"warning, null pointer" ) );
642 QgsDebugMsg( QStringLiteral(
"warning, null pointer" ) );
653 QgsPoint *ptc =
mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getNext()]->getNext()]->getPoint()];
654 QgsPoint *ptd =
mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint()];
657 doSwap( edge, recursiveDeep );
666 unsigned int edge1 = edge;
667 unsigned int edge2 =
mHalfEdge[edge]->getDual();
668 unsigned int edge3 =
mHalfEdge[edge]->getNext();
684 unsigned int edge1 = edge;
685 unsigned int edge2 =
mHalfEdge[edge]->getDual();
686 unsigned int edge3 =
mHalfEdge[edge]->getNext();
706 void DualEdgeTriangulation::draw( QPainter *p,
double xlowleft,
double ylowleft,
double xupright,
double yupright,
double width,
double height )
const 716 bool *control =
new bool[
mHalfEdge.count()];
717 bool *control2 =
new bool[
mHalfEdge.count()];
719 for (
unsigned int i = 0; i <=
mHalfEdge.count() - 1; i++ )
725 if ( ( ( xupright - xlowleft ) / width ) > ( ( yupright - ylowleft ) / height ) )
727 double lowerborder = -( height * ( xupright - xlowleft ) / width - yupright );
728 for (
unsigned int i = 0; i <
mHalfEdge.count() - 1; i++ )
742 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 ) )
748 QColor
c( 255, 0, 0 );
750 p->drawPolygon( pa );
755 control2[
mHalfEdge[i]->getNext()] =
true;
756 control2[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()] =
true;
790 double rightborder = width * ( yupright - ylowleft ) / height + xlowleft;
791 for (
unsigned int i = 0; i <
mHalfEdge.count() - 1; i++ )
805 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 ) )
811 QColor
c( 255, 0, 0 );
813 p->drawPolygon( pa );
818 control2[
mHalfEdge[i]->getNext()] =
true;
819 control2[mHalfEdge[mHalfEdge[i]->getNext()]->getNext()] =
true;
864 int nextnextedge = firstedge;
868 edge =
mHalfEdge[nextnextedge]->getDual();
871 theedge = nextnextedge;
875 nextnextedge =
mHalfEdge[nextedge]->getNext();
877 while ( nextnextedge != firstedge );
879 if ( theedge == -10 )
881 QgsDebugMsg( QStringLiteral(
"warning, error: the points are: %1 and %2" ).arg( p1 ).arg( p2 ) );
895 if ( firstedge == -1 )
900 int actedge = firstedge;
901 int edge, nextedge, nextnextedge;
908 nextnextedge =
mHalfEdge[nextedge]->getNext();
910 if (
mHalfEdge[nextnextedge]->getBreak() )
918 actedge = nextnextedge;
920 while ( nextnextedge != firstedge );
940 else if ( edge >= 0 )
959 else if ( edge == -20 )
964 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
982 else if ( edge == -25 )
987 int ptnr1 =
mHalfEdge[edge1]->getPoint();
988 int ptnr2 =
mHalfEdge[edge2]->getPoint();
989 int ptnr3 =
mHalfEdge[edge3]->getPoint();
1004 else if ( edge == -5 )
1009 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1029 QgsDebugMsg( QStringLiteral(
"problem: the edge is: %1" ).arg( edge ) );
1047 else if ( edge >= 0 )
1049 int ptnr1 =
mHalfEdge[edge]->getPoint();
1063 else if ( edge == -20 )
1068 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1083 else if ( edge == -25 )
1086 int edge2 =
mHalfEdge[edge1]->getNext();
1087 int edge3 =
mHalfEdge[edge2]->getNext();
1088 int ptnr1 =
mHalfEdge[edge1]->getPoint();
1089 int ptnr2 =
mHalfEdge[edge2]->getPoint();
1090 int ptnr3 =
mHalfEdge[edge3]->getPoint();
1091 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1106 else if ( edge == -5 )
1111 if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1148 QList<int> crossedEdges;
1151 int pointingedge = 0;
1155 if ( pointingedge == -1 )
1161 int actedge =
mHalfEdge[pointingedge]->getDual();
1168 if ( control > 17000 )
1170 QgsDebugMsg( QStringLiteral(
"warning, endless loop" ) );
1219 if ( dista <= distb )
1225 else if ( distb <= dista )
1241 float frac = distpart / disttot;
1243 if ( frac == 0 || frac == 1 )
1255 else if ( frac == 1 )
1286 crossedEdges.append(
mHalfEdge[actedge]->getNext() );
1302 p3 = mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getPoint();
1303 p4 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1305 double dista = std::sqrt( ( crosspoint.
x() - mPointVector[p3]->x() ) * ( crosspoint.
x() - mPointVector[p3]->x() ) + ( crosspoint.
y() - mPointVector[p3]->y() ) * ( crosspoint.
y() - mPointVector[p3]->y() ) );
1306 double distb = std::sqrt( ( crosspoint.
x() - mPointVector[p4]->x() ) * ( crosspoint.
x() - mPointVector[p4]->x() ) + ( crosspoint.
y() - mPointVector[p4]->y() ) * ( crosspoint.
y() - mPointVector[p4]->y() ) );
1307 if ( dista <= distb )
1313 else if ( distb <= dista )
1324 p3 = mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getPoint();
1325 p4 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1327 double distpart = std::sqrt( ( crosspoint.
x() - mPointVector[p3]->x() ) * ( crosspoint.
x() - mPointVector[p3]->x() ) + ( crosspoint.
y() - mPointVector[p3]->y() ) * ( crosspoint.
y() - mPointVector[p3]->y() ) );
1328 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() ) );
1329 float frac = distpart / disttot;
1330 if ( frac == 0 || frac == 1 )
1334 int newpoint =
splitHalfEdge( mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext(), frac );
1340 crossedEdges.append( mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext() );
1343 else if (
MathUtils::lineIntersection( mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint()], mPointVector[p1], mPointVector[p2] ) )
1349 p3 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1350 p4 = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint();
1352 double dista = std::sqrt( ( crosspoint.
x() - mPointVector[p3]->x() ) * ( crosspoint.
x() - mPointVector[p3]->x() ) + ( crosspoint.
y() - mPointVector[p3]->y() ) * ( crosspoint.
y() - mPointVector[p3]->y() ) );
1353 double distb = std::sqrt( ( crosspoint.
x() - mPointVector[p4]->x() ) * ( crosspoint.
x() - mPointVector[p4]->x() ) + ( crosspoint.
y() - mPointVector[p4]->y() ) * ( crosspoint.
y() - mPointVector[p4]->y() ) );
1354 if ( dista <= distb )
1360 else if ( distb <= dista )
1371 p3 = mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getPoint();
1372 p4 = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext()]->getPoint();
1374 double distpart = std::sqrt( ( crosspoint.
x() - mPointVector[p3]->x() ) * ( crosspoint.
x() - mPointVector[p3]->x() ) + ( crosspoint.
y() - mPointVector[p3]->y() ) * ( crosspoint.
y() - mPointVector[p3]->y() ) );
1375 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() ) );
1376 float frac = distpart / disttot;
1377 if ( frac == 0 || frac == 1 )
1381 int newpoint =
splitHalfEdge( mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext(), frac );
1387 crossedEdges.append( mHalfEdge[mHalfEdge[mHalfEdge[crossedEdges.last()]->getDual()]->getNext()]->getNext() );
1397 QList<int>::const_iterator iter;
1398 for ( iter = crossedEdges.constBegin(); iter != crossedEdges.constEnd(); ++iter )
1400 mHalfEdge[( *( iter ) )]->setForced(
false );
1401 mHalfEdge[( *( iter ) )]->setBreak(
false );
1409 QList<int> freelist = crossedEdges;
1412 QList<int> leftPolygon;
1413 QList<int> rightPolygon;
1416 int firstedge = freelist.first();
1417 mHalfEdge[firstedge]->setForced(
true );
1419 leftPolygon.append( firstedge );
1420 int dualfirstedge =
mHalfEdge[freelist.first()]->getDual();
1421 mHalfEdge[dualfirstedge]->setForced(
true );
1423 rightPolygon.append( dualfirstedge );
1424 freelist.pop_front();
1428 QList<int>::const_iterator leftiter;
1429 leftiter = crossedEdges.constEnd();
1434 if ( newpoint != actpointl )
1437 actpointl = newpoint;
1439 leftPolygon.append( theedge );
1441 if ( leftiter == crossedEdges.constBegin() )
1447 leftPolygon.append(
mHalfEdge[crossedEdges.first()]->getNext() );
1450 QList<int>::const_iterator rightiter;
1452 for ( rightiter = crossedEdges.constBegin(); rightiter != crossedEdges.constEnd(); ++rightiter )
1455 if ( newpoint != actpointr )
1458 actpointr = newpoint;
1460 rightPolygon.append( theedge );
1466 rightPolygon.append(
mHalfEdge[
mHalfEdge[crossedEdges.last()]->getDual()]->getNext() );
1467 mHalfEdge[rightPolygon.last()]->setNext( dualfirstedge );
1470 int actedgel = leftPolygon[1];
1471 leftiter = leftPolygon.constBegin();
1473 for ( ; leftiter != leftPolygon.constEnd(); ++leftiter )
1475 mHalfEdge[actedgel]->setNext( ( *leftiter ) );
1476 actedgel = ( *leftiter );
1480 int actedger = rightPolygon[1];
1481 rightiter = rightPolygon.constBegin();
1483 for ( ; rightiter != rightPolygon.constEnd(); ++rightiter )
1485 mHalfEdge[actedger]->setNext( ( *rightiter ) );
1486 actedger = ( *( rightiter ) );
1491 mHalfEdge[leftPolygon.first()]->setNext( ( *( ++( leftiter = leftPolygon.constBegin() ) ) ) );
1492 mHalfEdge[leftPolygon.first()]->setPoint( p2 );
1493 mHalfEdge[leftPolygon.last()]->setNext( firstedge );
1494 mHalfEdge[rightPolygon.first()]->setNext( ( *( ++( rightiter = rightPolygon.constBegin() ) ) ) );
1495 mHalfEdge[rightPolygon.first()]->setPoint( p1 );
1496 mHalfEdge[rightPolygon.last()]->setNext( dualfirstedge );
1502 for ( iter = crossedEdges.constBegin(); iter != crossedEdges.constEnd(); ++iter )
1507 return leftPolygon.first();
1537 QgsDebugMsg( QStringLiteral(
"am in eliminateHorizontalTriangles" ) );
1538 double minangle = 0;
1542 bool swapped =
false;
1543 bool *control =
new bool[
mHalfEdge.count()];
1545 for (
int i = 0; i <=
mHalfEdge.count() - 1; i++ )
1551 for (
int i = 0; i <=
mHalfEdge.count() - 1; i++ )
1569 if ( p1 == -1 || p2 == -1 || p3 == -1 )
1577 double el1, el2, el3;
1582 if ( el1 == el2 && el2 == el3 )
1630 std::map<int, double> edge_angle;
1631 std::multimap<double, int> angle_edge;
1632 QSet<int> dontexamine;
1643 for (
int i = 0; i < nhalfedges - 1; i++ )
1646 int nextnext =
mHalfEdge[next]->getNext();
1657 Q_UNUSED( pointno );
1668 for (
int i = 0; i <
mHalfEdge.count() - 1; i++ )
1674 if ( p1 == -1 || p2 == -1 || p3 == -1 )
1680 bool twoforcededges;
1685 if ( angle < mintol && !twoforcededges )
1687 edge_angle.insert( std::make_pair( i, angle ) );
1688 angle_edge.insert( std::make_pair( angle, i ) );
1693 for ( std::multimap<double, int>::const_iterator it = angle_edge.begin(); it != angle_edge.end(); ++it )
1695 QgsDebugMsg( QStringLiteral(
"angle: %1" ).arg( it->first ) );
1699 double minangle = 0;
1702 int minedgenextnext;
1706 while ( !edge_angle.empty() )
1708 minangle = angle_edge.begin()->first;
1709 QgsDebugMsg( QStringLiteral(
"minangle: %1" ).arg( minangle ) );
1710 minedge = angle_edge.begin()->second;
1711 minedgenext =
mHalfEdge[minedge]->getNext();
1712 minedgenextnext =
mHalfEdge[minedgenext]->getNext();
1717 QgsDebugMsg( QStringLiteral(
"warning, calculation of circumcenter failed" ) );
1719 dontexamine.insert( minedge );
1720 edge_angle.erase( minedge );
1721 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
1722 while ( minedgeiter->second != minedge )
1726 angle_edge.erase( minedgeiter );
1733 QgsDebugMsg( QStringLiteral(
"put circumcenter %1//%2 on dontexamine list because it is outside the convex hull" )
1734 .arg( circumcenter.
x() ).arg( circumcenter.
y() ) );
1735 dontexamine.insert( minedge );
1736 edge_angle.erase( minedge );
1737 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
1738 while ( minedgeiter->second != minedge )
1742 angle_edge.erase( minedgeiter );
1748 bool encroached =
false;
1750 #if 0 //slow version 1752 for (
int i = 0; i < numhalfedges; i++ )
1766 int actedge = pointingedge;
1769 double angle1, angle2, angle3;
1781 if ( pt1 == -1 || pt2 == -1 || pt3 == -1 )
1791 bool twoforcededges1, twoforcededges2, twoforcededges3;
1795 twoforcededges1 =
true;
1799 twoforcededges1 =
false;
1804 twoforcededges2 =
true;
1808 twoforcededges2 =
false;
1813 twoforcededges3 =
true;
1817 twoforcededges3 =
false;
1821 QSet<int>::iterator ed1iter = dontexamine.find( ed1 );
1822 if ( ed1iter != dontexamine.end() )
1825 dontexamine.erase( ed1iter );
1830 std::map<int, double>::iterator tempit1;
1831 tempit1 = edge_angle.find( ed1 );
1832 if ( tempit1 != edge_angle.end() )
1835 double angle = tempit1->second;
1836 edge_angle.erase( ed1 );
1837 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
1838 while ( tempit2->second != ed1 )
1842 angle_edge.erase( tempit2 );
1846 if ( angle1 < mintol && !twoforcededges1 )
1848 edge_angle.insert( std::make_pair( ed1, angle1 ) );
1849 angle_edge.insert( std::make_pair( angle1, ed1 ) );
1853 QSet<int>::iterator ed2iter = dontexamine.find( ed2 );
1854 if ( ed2iter != dontexamine.end() )
1857 dontexamine.erase( ed2iter );
1862 std::map<int, double>::iterator tempit1;
1863 tempit1 = edge_angle.find( ed2 );
1864 if ( tempit1 != edge_angle.end() )
1867 double angle = tempit1->second;
1868 edge_angle.erase( ed2 );
1869 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
1870 while ( tempit2->second != ed2 )
1874 angle_edge.erase( tempit2 );
1878 if ( angle2 < mintol && !twoforcededges2 )
1880 edge_angle.insert( std::make_pair( ed2, angle2 ) );
1881 angle_edge.insert( std::make_pair( angle2, ed2 ) );
1885 QSet<int>::iterator ed3iter = dontexamine.find( ed3 );
1886 if ( ed3iter != dontexamine.end() )
1889 dontexamine.erase( ed3iter );
1894 std::map<int, double>::iterator tempit1;
1895 tempit1 = edge_angle.find( ed3 );
1896 if ( tempit1 != edge_angle.end() )
1899 double angle = tempit1->second;
1900 edge_angle.erase( ed3 );
1901 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
1902 while ( tempit2->second != ed3 )
1906 angle_edge.erase( tempit2 );
1910 if ( angle3 < mintol && !twoforcededges3 )
1912 edge_angle.insert( std::make_pair( ed3, angle3 ) );
1913 angle_edge.insert( std::make_pair( angle3, ed3 ) );
1918 while ( actedge != pointingedge );
1922 #endif //end slow version 1926 QSet<int> influenceedges;
1928 if ( baseedge == -5 )
1931 edge_angle.erase( minedge );
1932 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
1933 while ( minedgeiter->second != minedge )
1937 angle_edge.erase( minedgeiter );
1940 else if ( baseedge == -25 )
1943 edge_angle.erase( minedge );
1944 std::multimap<double, int>::iterator minedgeiter = angle_edge.find( minangle );
1945 while ( minedgeiter->second != minedge )
1949 angle_edge.erase( minedgeiter );
1952 else if ( baseedge == -20 )
1961 for ( QSet<int>::iterator it = influenceedges.begin(); it != influenceedges.end(); ++it )
1973 int actedge = pointingedge;
1976 double angle1, angle2, angle3;
1988 if ( pt1 == -1 || pt2 == -1 || pt3 == -1 )
1998 bool twoforcededges1, twoforcededges2, twoforcededges3;
2010 QSet<int>::iterator ed1iter = dontexamine.find( ed1 );
2011 if ( ed1iter != dontexamine.end() )
2014 dontexamine.erase( ed1iter );
2019 std::map<int, double>::iterator tempit1;
2020 tempit1 = edge_angle.find( ed1 );
2021 if ( tempit1 != edge_angle.end() )
2024 double angle = tempit1->second;
2025 edge_angle.erase( ed1 );
2026 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2027 while ( tempit2->second != ed1 )
2031 angle_edge.erase( tempit2 );
2035 if ( angle1 < mintol && !twoforcededges1 )
2037 edge_angle.insert( std::make_pair( ed1, angle1 ) );
2038 angle_edge.insert( std::make_pair( angle1, ed1 ) );
2042 QSet<int>::iterator ed2iter = dontexamine.find( ed2 );
2043 if ( ed2iter != dontexamine.end() )
2046 dontexamine.erase( ed2iter );
2051 std::map<int, double>::iterator tempit1;
2052 tempit1 = edge_angle.find( ed2 );
2053 if ( tempit1 != edge_angle.end() )
2056 double angle = tempit1->second;
2057 edge_angle.erase( ed2 );
2058 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2059 while ( tempit2->second != ed2 )
2063 angle_edge.erase( tempit2 );
2067 if ( angle2 < mintol && !twoforcededges2 )
2069 edge_angle.insert( std::make_pair( ed2, angle2 ) );
2070 angle_edge.insert( std::make_pair( angle2, ed2 ) );
2074 QSet<int>::iterator ed3iter = dontexamine.find( ed3 );
2075 if ( ed3iter != dontexamine.end() )
2078 dontexamine.erase( ed3iter );
2083 std::map<int, double>::iterator tempit1;
2084 tempit1 = edge_angle.find( ed3 );
2085 if ( tempit1 != edge_angle.end() )
2088 double angle = tempit1->second;
2089 edge_angle.erase( ed3 );
2090 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2091 while ( tempit2->second != ed3 )
2095 angle_edge.erase( tempit2 );
2099 if ( angle3 < mintol && !twoforcededges3 )
2101 edge_angle.insert( std::make_pair( ed3, angle3 ) );
2102 angle_edge.insert( std::make_pair( angle3, ed3 ) );
2107 while ( actedge != pointingedge );
2125 if ( pointno == -100 )
2127 QgsDebugMsg( QStringLiteral(
"put circumcenter %1//%2 on dontexamine list because of numerical instabilities" )
2128 .arg( circumcenter.
x() ).arg( circumcenter.
y() ) );
2132 QgsDebugMsg( QStringLiteral(
"put circumcenter %1//%2 on dontexamine list because it is already inserted" )
2133 .arg( circumcenter.
x() ).arg( circumcenter.
y() ) );
2145 QgsDebugMsg( QStringLiteral(
"point is not present in the triangulation" ) );
2149 dontexamine.insert( minedge );
2150 edge_angle.erase( minedge );
2151 std::multimap<double, int>::iterator minedgeiter = angle_edge.lower_bound( minangle );
2152 while ( minedgeiter->second != minedge )
2156 angle_edge.erase( minedgeiter );
2161 QgsDebugMsg( QStringLiteral(
"circumcenter added" ) );
2167 int actedge = pointingedge;
2170 double angle1, angle2, angle3;
2182 if ( pt1 == -1 || pt2 == -1 || pt3 == -1 )
2192 bool twoforcededges1, twoforcededges2, twoforcededges3;
2202 QSet<int>::iterator ed1iter = dontexamine.find( ed1 );
2203 if ( ed1iter != dontexamine.end() )
2206 dontexamine.erase( ed1iter );
2211 std::map<int, double>::iterator tempit1;
2212 tempit1 = edge_angle.find( ed1 );
2213 if ( tempit1 != edge_angle.end() )
2216 double angle = tempit1->second;
2217 edge_angle.erase( ed1 );
2218 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2219 while ( tempit2->second != ed1 )
2223 angle_edge.erase( tempit2 );
2227 if ( angle1 < mintol && !twoforcededges1 )
2229 edge_angle.insert( std::make_pair( ed1, angle1 ) );
2230 angle_edge.insert( std::make_pair( angle1, ed1 ) );
2235 QSet<int>::iterator ed2iter = dontexamine.find( ed2 );
2236 if ( ed2iter != dontexamine.end() )
2239 dontexamine.erase( ed2iter );
2244 std::map<int, double>::iterator tempit1;
2245 tempit1 = edge_angle.find( ed2 );
2246 if ( tempit1 != edge_angle.end() )
2249 double angle = tempit1->second;
2250 edge_angle.erase( ed2 );
2251 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2252 while ( tempit2->second != ed2 )
2256 angle_edge.erase( tempit2 );
2260 if ( angle2 < mintol && !twoforcededges2 )
2262 edge_angle.insert( std::make_pair( ed2, angle2 ) );
2263 angle_edge.insert( std::make_pair( angle2, ed2 ) );
2267 QSet<int>::iterator ed3iter = dontexamine.find( ed3 );
2268 if ( ed3iter != dontexamine.end() )
2271 dontexamine.erase( ed3iter );
2276 std::map<int, double>::iterator tempit1;
2277 tempit1 = edge_angle.find( ed3 );
2278 if ( tempit1 != edge_angle.end() )
2281 double angle = tempit1->second;
2282 edge_angle.erase( ed3 );
2283 std::multimap<double, int>::iterator tempit2 = angle_edge.lower_bound( angle );
2284 while ( tempit2->second != ed3 )
2288 angle_edge.erase( tempit2 );
2292 if ( angle3 < mintol && !twoforcededges3 )
2294 edge_angle.insert( std::make_pair( ed3, angle3 ) );
2295 angle_edge.insert( std::make_pair( angle3, ed3 ) );
2300 while ( actedge != pointingedge );
2306 for ( QSet<int>::iterator it = dontexamine.begin(); it != dontexamine.end(); ++it )
2308 QgsDebugMsg( QStringLiteral(
"edge nr. %1 is in dontexamine" ).arg( *it ) );
2330 QgsPoint *ptc =
mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getNext()]->getNext()]->getPoint()];
2331 QgsPoint *ptd =
mPointVector[mHalfEdge[mHalfEdge[mHalfEdge[edge]->getDual()]->getNext()]->getPoint()];
2355 if ( poly->count() == 3 )
2361 QList<int>::const_iterator iterator = ++( poly->constBegin() );
2363 int distedge = ( *iterator );
2364 int nextdistedge =
mHalfEdge[( *iterator )]->getNext();
2367 while ( iterator != --( poly->constEnd() ) )
2371 distedge = ( *iterator );
2372 nextdistedge = mHalfEdge[( *iterator )]->getNext();
2378 if ( nextdistedge == ( *( --poly->end() ) ) )
2380 int inserta = free->first();
2381 int insertb =
mHalfEdge[inserta]->getDual();
2384 mHalfEdge[inserta]->setNext( ( poly->at( 1 ) ) );
2386 mHalfEdge[insertb]->setNext( nextdistedge );
2388 mHalfEdge[distedge]->setNext( inserta );
2389 mHalfEdge[mainedge]->setNext( insertb );
2392 for ( iterator = ( ++( poly->constBegin() ) ); ( *iterator ) != nextdistedge; ++iterator )
2394 polya.append( ( *iterator ) );
2396 polya.prepend( inserta );
2400 for ( iterator = polya.begin(); iterator != polya.end(); ++iterator )
2409 else if ( distedge == ( *( ++poly->begin() ) ) )
2411 int inserta = free->first();
2412 int insertb =
mHalfEdge[inserta]->getDual();
2415 mHalfEdge[inserta]->setNext( ( poly->at( 2 ) ) );
2417 mHalfEdge[insertb]->setNext( mainedge );
2419 mHalfEdge[distedge]->setNext( insertb );
2420 mHalfEdge[( *( --poly->end() ) )]->setNext( inserta );
2423 iterator = poly->constBegin();
2425 while ( iterator != poly->constEnd() )
2427 polya.append( ( *iterator ) );
2430 polya.prepend( inserta );
2437 int inserta = free->first();
2438 int insertb =
mHalfEdge[inserta]->getDual();
2441 int insertc = free->first();
2442 int insertd =
mHalfEdge[insertc]->getDual();
2445 mHalfEdge[inserta]->setNext( ( poly->at( 1 ) ) );
2449 mHalfEdge[insertc]->setNext( nextdistedge );
2451 mHalfEdge[insertd]->setNext( mainedge );
2454 mHalfEdge[distedge]->setNext( inserta );
2455 mHalfEdge[mainedge]->setNext( insertb );
2456 mHalfEdge[( *( --poly->end() ) )]->setNext( insertc );
2462 for ( iterator = ++( poly->constBegin() ); ( *iterator ) != nextdistedge; ++iterator )
2464 polya.append( ( *iterator ) );
2466 polya.prepend( inserta );
2469 while ( iterator != poly->constEnd() )
2471 polyb.append( ( *iterator ) );
2474 polyb.prepend( insertc );
2483 QgsDebugMsg( QStringLiteral(
"warning, null pointer" ) );
2501 QgsDebugMsg( QStringLiteral(
"warning, instability detected: Point coordinates: %1//%2" ).arg( x ).arg( y ) );
2535 actedge =
mHalfEdge[actedge]->getDual();
2541 actedge =
mHalfEdge[actedge]->getNext();
2558 if ( numinstabs > 0 )
2560 QgsDebugMsg( QStringLiteral(
"numerical instabilities" ) );
2573 bool DualEdgeTriangulation::readFromTAFF( QString filename )
2575 QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
2577 QFile file( filename );
2578 file.open( IO_Raw | IO_ReadOnly );
2579 QBuffer buffer( file.readAll() );
2582 QTextStream textstream( &buffer );
2583 buffer.open( IO_ReadOnly );
2586 int numberofhalfedges;
2590 while ( buff.mid( 0, 4 ) !=
"TRIA" )
2592 buff = textstream.readLine();
2594 while ( buff.mid( 0, 4 ) !=
"NEDG" )
2596 buff = textstream.readLine();
2598 numberofhalfedges = buff.section(
' ', 1, 1 ).toInt();
2602 while ( buff.mid( 0, 4 ) !=
"DATA" )
2607 int nr1, nr2, dual1, dual2, point1, point2, next1, next2, fo1, fo2, b1, b2;
2608 bool forced1, forced2, break1, break2;
2612 QProgressBar *edgebar =
new QProgressBar();
2613 edgebar->setCaption(
"Reading edges…" );
2614 edgebar->setTotalSteps( numberofhalfedges / 2 );
2615 edgebar->setMinimumWidth( 400 );
2616 edgebar->move( 500, 500 );
2619 for (
int i = 0; i < numberofhalfedges / 2; i++ )
2621 if ( i % 1000 == 0 )
2623 edgebar->setProgress( i );
2627 textstream >> point1;
2628 textstream >> next1;
2652 textstream >> point2;
2653 textstream >> next2;
2696 edgebar->setProgress( numberofhalfedges / 2 );
2700 for (
int i = 0; i < numberofhalfedges; i++ )
2707 if ( a != -1 && b != -1 && c != -1 && d != -1 )
2715 while ( buff.mid( 0, 4 ) !=
"POIN" )
2717 buff = textstream.readLine();
2720 while ( buff.mid( 0, 4 ) !=
"NPTS" )
2722 buff = textstream.readLine();
2725 numberofpoints = buff.section(
' ', 1, 1 ).toInt();
2728 while ( buff.mid( 0, 4 ) !=
"DATA" )
2733 QProgressBar *pointbar =
new QProgressBar();
2734 pointbar->setCaption( tr(
"Reading points…" ) );
2735 pointbar->setTotalSteps( numberofpoints );
2736 pointbar->setMinimumWidth( 400 );
2737 pointbar->move( 500, 500 );
2742 for (
int i = 0; i < numberofpoints; i++ )
2744 if ( i % 1000 == 0 )
2746 pointbar->setProgress( i );
2772 else if ( x >
xMax )
2781 else if ( y >
yMax )
2788 pointbar->setProgress( numberofpoints );
2790 QApplication::restoreOverrideCursor();
2794 bool DualEdgeTriangulation::saveToTAFF( QString filename )
const 2796 QFile outputfile( filename );
2797 if ( !outputfile.open( IO_WriteOnly ) )
2799 QMessageBox::warning( 0, tr(
"Warning" ), tr(
"File could not be written." ), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton );
2803 QTextStream outstream( &outputfile );
2804 outstream.precision( 9 );
2807 outstream <<
"TRIA" << std::endl << std::flush;
2808 outstream <<
"NEDG " <<
mHalfEdge.count() << std::endl << std::flush;
2809 outstream <<
"PANO 1" << std::endl << std::flush;
2810 outstream <<
"DATA ";
2812 bool *cont =
new bool[
mHalfEdge.count()];
2813 for (
unsigned int i = 0; i <=
mHalfEdge.count() - 1; i++ )
2818 for (
unsigned int i = 0; i <
mHalfEdge.count(); i++ )
2827 outstream << dual <<
" " <<
mHalfEdge[dual]->getPoint() <<
" " <<
mHalfEdge[dual]->getNext() <<
" " <<
mHalfEdge[dual]->getForced() <<
" " <<
mHalfEdge[dual]->getBreak() <<
" ";
2831 outstream << std::endl << std::flush;
2832 outstream << std::endl << std::flush;
2837 outstream <<
"POIN" << std::endl << std::flush;
2839 outstream <<
"PATT 3" << std::endl << std::flush;
2840 outstream <<
"DATA ";
2845 outstream << p->getX() <<
" " << p->getY() <<
" " << p->getZ() <<
" ";
2847 outstream << std::endl << std::flush;
2848 outstream << std::endl << std::flush;
2869 if ( point1 && point2 && point3 )
2872 double dist1, dist2, dist3;
2876 if ( dist1 <= dist2 && dist1 <= dist3 )
2884 else if ( dist2 <= dist1 && dist2 <= dist3 )
2892 else if ( dist3 <= dist1 && dist3 <= dist2 )
2931 if ( point1 && point2 && point3 )
2933 double dist1, dist2, dist3;
2937 if ( dist1 <= dist2 && dist1 <= dist3 )
2944 else if ( dist2 <= dist1 && dist2 <= dist3 )
2951 else if ( dist3 <= dist1 && dist3 <= dist2 )
2958 QList<int> *list =
new QList<int>();
2967 QgsDebugMsg( QStringLiteral(
"warning: null pointer" ) );
2973 QgsDebugMsg( QStringLiteral(
"Edge number negative" ) );
2985 bool *alreadyVisitedEdges =
new bool[
mHalfEdge.size()];
2986 if ( !alreadyVisitedEdges )
2992 for (
int i = 0; i <
mHalfEdge.size(); ++i )
2994 alreadyVisitedEdges[i] =
false;
2997 for (
int i = 0; i <
mHalfEdge.size(); ++i )
3017 QString attributeString;
3022 attributeString = QStringLiteral(
"break line" );
3026 attributeString = QStringLiteral(
"structure line" );
3033 alreadyVisitedEdges[i] =
true;
3036 delete [] alreadyVisitedEdges;
3053 if ( angle2 < minangle )
3058 if ( angle3 < minangle )
3063 if ( angle4 < minangle )
3068 if ( angle5 < minangle )
3073 if ( angle6 < minangle )
3084 if ( position < 0 || position > 1 )
3086 QgsDebugMsg( QStringLiteral(
"warning, position is not between 0 and 1" ) );
3095 p->
setZ( zvaluepoint.
z() );
3102 QgsDebugMsg( QStringLiteral(
"inserting point nr. %1, %2//%3//%4" ).arg(
mPointVector.count() ).arg( p->
x() ).arg( p->
y() ).arg( p->
z() ) );
3106 int dualedge =
mHalfEdge[edge]->getDual();
3143 if (
set.find( edge ) ==
set.end() )
bool getBreak() const
Returns, whether the HalfEdge belongs to a break line or not.
Triangulation * mDecorator
Pointer to the decorator using this triangulation. It it is used directly, mDecorator equals this...
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
void setBreakEdgeColor(int r, int g, int b) override
Sets the color of the breaklines.
void triangulatePolygon(QList< int > *poly, QList< int > *free, int mainedge)
Divides a polygon in a triangle and two polygons and calls itself recursively for these two polygons...
int getOppositePoint(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 baseEdgeOfPoint(int point)
Returns the number of an edge which points to the point with number 'point' or -1 if there is an erro...
int getPoint() const
Returns the number of the point at which this HalfEdge points.
int splitHalfEdge(int edge, float position)
Inserts a new point on the halfedge with number 'edge'. The position can have a value from 0 to 1 (e...
void setZ(double z)
Sets the point's z-coordinate.
unsigned int insertEdge(int dual, int next, int point, bool mbreak, bool forced)
Inserts an edge and makes sure, everything is OK with the storage of the edge. The number of the Half...
int mTwiceInsPoint
If a point has been inserted twice, its number is stored in this member.
A class to represent a 2D point.
An interface for objects which accept features via addFeature(s) methods.
QgsPoint * getPoint(int i) const override
Draws the points, edges and the forced lines.
bool halfEdgeBBoxTest(int edge, double xlowleft, double ylowleft, double xupright, double yupright) const
Tests, if the bounding box of the halfedge with index i intersects the specified bounding box...
double yMin
Y-coordinate of the lower left corner of the bounding box.
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'.
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...
int getNumberOfPoints() const override
Returns the number of points.
bool setAttribute(int field, const QVariant &attr)
Set an attribute's value by field index.
SourceType
Describes the type of input data.
void addLine(const QVector< QgsPoint > &points, QgsInterpolator::SourceType lineType) override
Adds a line (e.g.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
double xMax
X-coordinate of the upper right corner of the bounding box.
void doSwap(unsigned int edge, unsigned int recursiveDeep)
Swaps 'edge' and test recursively for other swaps (delaunay criterion)
bool ANALYSIS_EXPORT inDiametral(QgsPoint *p1, QgsPoint *p2, QgsPoint *point)
Tests, whether 'point' is inside the diametral circle through 'p1' and 'p2'.
unsigned int mUnstableEdge
If an instability occurs in 'baseEdgeOfTriangle', mUnstableEdge is set to the value of the current ed...
bool checkSwap(unsigned int edge, unsigned int recursiveDeep)
Checks, if 'edge' has to be swapped because of the empty circle criterion. If so, doSwap(...
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 getTriangle(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...
void doOnlySwap(unsigned int edge)
Swaps 'edge' and does no recursiv testing.
QVector< HalfEdge * > mHalfEdge
Stores pointers to the HalfEdges.
void setForcedCrossBehavior(Triangulation::ForcedCrossBehavior b) override
Sets the behavior of the triangulation in case of crossing forced lines.
Base class for feedback objects to be used for cancelation of something running in a worker thread...
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...
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
void setEdgeColor(int r, int g, int b) override
Sets the color of the normal edges.
void setTriangleInterpolator(TriangleInterpolator *interpolator) override
Sets an interpolator object.
Class Vector3D represents a 3D-Vector, capable to store x-,y- and z-coordinates in double values...
This is an interface for interpolator classes for triangulations.
double yMax
Y-coordinate of the upper right corner of the bounding box.
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
bool getForced() const
Returns, whether the HalfEdge belongs to a constrained edge or not.
bool edgeOnConvexHull(int edge)
Returns true, if a half edge is on the convex hull and false otherwise.
QColor mForcedEdgeColor
Color to paint the forced edges.
void evaluateInfluenceRegion(QgsPoint *point, int edge, QSet< int > &set)
Function needed for the ruppert algorithm. Tests, if point is in the circle through both endpoints of...
double swapMinAngle(int edge) const
Calculates the minimum angle, which would be present, if the specified halfedge would be swapped...
bool saveTriangulation(QgsFeatureSink *sink, QgsFeedback *feedback=nullptr) const override
Saves the triangulation features to a feature sink.
int addPoint(const QgsPoint &p) override
Adds a point to the triangulation.
virtual bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr)
Adds a single feature to the sink.
~DualEdgeTriangulation() override
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 distPointFromLine(QgsPoint *thepoint, QgsPoint *p1, QgsPoint *p2)
Calculates the (2 dimensional) distance from 'thepoint' to the line defined by p1 and p2...
QColor mBreakEdgeColor
Color to paint the breaklines.
Point geometry type, with support for z-dimension and m-values.
int insertForcedSegment(int p1, int p2, QgsInterpolator::SourceType segmentType)
Inserts a forced segment between the points with the numbers p1 and p2 into the triangulation and ret...
void setBreak(bool b)
Sets the break flag.
void setPoint(int p)
Sets the number of point at which this HalfEdge points.
int getDual() const
Returns the number of the dual HalfEdge.
unsigned int mEdgeWithPoint
If an inserted point is exactly on an existing edge, 'baseEdgeOfTriangle' returns -20 and sets the va...
int baseEdgeOfTriangle(const QgsPoint &point)
Returns the number of a HalfEdge from a triangle in which 'point' is in. If the number -10 is returne...
bool swapPossible(unsigned int edge)
Returns true, if it is possible to swap an edge, otherwise false(concave quad or edge on (or outside)...
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...
void performConsistencyTest() override
Performs a consistency check, remove this later.
void setX(double x)
Sets the point's x-coordinate.
Triangulation::ForcedCrossBehavior mForcedCrossBehavior
Member to store the behavior in case of crossing forced segments.
virtual int addPoint(const QgsPoint &point)=0
Adds a point to the triangulation.
void setY(double y)
Sets the point's y-coordinate.
unsigned int mEdgeInside
Number of an edge which does not point to the virtual point. It continuously updated for a fast searc...
The second inserted forced line is snapped to the closest vertice of the first inserted forced line...
TriangleInterpolator * mTriangleInterpolator
Association to an interpolator object.
bool ANALYSIS_EXPORT inCircle(QgsPoint *testp, QgsPoint *p1, QgsPoint *p2, QgsPoint *p3)
Tests, whether 'testp' is inside the circle through 'p1', 'p2' and 'p3'.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
bool isCanceled() const
Tells whether the operation has been canceled already.
bool calcNormal(double x, double y, Vector3D *result) override
Calculates the normal at a point on the surface.
void eliminateHorizontalTriangles() override
Eliminates the horizontal triangles by swapping or by insertion of new points.
virtual bool calcNormVec(double x, double y, Vector3D *result)=0
Calculates the normal vector and assigns it to vec.
void setForcedEdgeColor(int r, int g, int b) override
Sets the color of the forced edges.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
QList< int > getSurroundingTriangles(int pointno) override
Returns a pointer to a value list with the information of the triangles surrounding (counterclockwise...
static const int MAX_BASE_ITERATIONS
Threshold for the leftOfTest to handle numerical instabilities.
void setDual(int d)
Sets the number of the dual HalfEdge.
QVector< QgsPoint * > mPointVector
Stores pointers to all points in the triangulations (including the points contained in the lines) ...
void setForced(bool f)
Sets the forced flag.
QColor mEdgeColor
Color to paint the normal edges.
double xMin
X-coordinate of the lower left corner of the bounding box.
void ruppertRefinement() override
Adds points to make the triangles better shaped (algorithm of ruppert)
QList< int > * getPointsAroundEdge(double x, double y) override
Returns a value list with the numbers of the four points, which would be affected by an edge swap...
ForcedCrossBehavior
Enumeration describing the behavior, if two forced lines cross.
void setNext(int n)
Sets the number of the next HalfEdge.
virtual bool calcPoint(double x, double y, QgsPoint &result)=0
Calculates x-, y and z-value of the point on the surface and assigns it to 'result'.
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'. Negativ values mean left a...
unsigned int mEdgeOutside
Number of an edge on the outside of the convex hull. It is updated in method 'baseEdgeOfTriangle' to ...
bool swapEdge(double x, double y) override
Reads the dual edge structure of a taff file.