21#include <nlohmann/json.hpp>
33#include <QPainterPath>
36using namespace Qt::StringLiterals;
50 auto result = std::make_unique< QgsCompoundCurve >();
52 return result.release();
63 while ( i < mCurves.size() && j < otherCurve->mCurves.size() )
67 const int comparison = aGeom->
compareTo( bGeom );
68 if ( comparison != 0 )
75 if ( i < mCurves.size() )
79 if ( j < otherCurve->mCurves.size() )
88 return u
"CompoundCurve"_s;
100 mCurves.reserve( curve.mCurves.size() );
101 for (
const QgsCurve *
c : curve.mCurves )
103 mCurves.append( c->clone() );
110 if ( &curve !=
this )
113 for (
const QgsCurve *
c : curve.mCurves )
115 mCurves.append(
c->clone() );
129 qDeleteAll( mCurves );
136 if ( mCurves.empty() )
141 QgsBox3D bbox = mCurves.at( 0 )->boundingBox3D();
142 for (
int i = 1; i < mCurves.size(); ++i )
144 QgsBox3D curveBox = mCurves.at( i )->boundingBox3D();
153 if ( index < 1 || index >= size - 1 )
162 mCurves = std::move( curve2->mCurves );
167 mCurves.append( curve1->mCurves );
168 curve1->mCurves.clear();
190 for (
int i = 0; i <
nCurves; ++i )
193 wkbPtr -= 1 +
sizeof( int );
206 currentCurve->
fromWkb( wkbPtr );
207 mCurves.append( currentCurve );
222 QString secondWithoutParentheses =
parts.second;
223 secondWithoutParentheses = secondWithoutParentheses.remove(
'(' ).remove(
')' ).simplified().remove(
' ' );
224 if ( (
parts.second.compare(
"EMPTY"_L1, Qt::CaseInsensitive ) == 0 ) || secondWithoutParentheses.isEmpty() )
227 QString defaultChildWkbType = u
"LineString%1%2"_s.arg(
is3D() ? u
"Z"_s : QString(),
isMeasure() ? u
"M"_s : QString() );
230 for (
const QString &childWkt : blocks )
243 if ( !mCurves.back()->fromWkt( childWkt ) )
254 for (
const QgsCurve *curve : std::as_const( mCurves ) )
256 hasZ = hasZ || curve->is3D();
257 hasM = hasM || curve->isMeasure();
271 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
272 for (
const QgsCurve *curve : mCurves )
274 binarySize += curve->wkbSize( flags );
285 wkb << static_cast<quint32>(
wkbType() );
286 wkb << static_cast<quint32>( mCurves.size() );
287 for (
const QgsCurve *curve : mCurves )
289 wkb << curve->asWkb( flags );
302 for (
const QgsCurve *curve : mCurves )
304 QString childWkt = curve->asWkt( precision );
308 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
310 wkt += childWkt +
',';
312 if ( wkt.endsWith(
',' ) )
324 std::unique_ptr< QgsLineString > line(
curveToLine() );
325 QDomElement gml = line->asGml2( doc, precision, ns, axisOrder );
331 QDomElement compoundCurveElem = doc.createElementNS( ns, u
"CompositeCurve"_s );
334 return compoundCurveElem;
336 for (
const QgsCurve *curve : mCurves )
338 QDomElement curveMemberElem = doc.createElementNS( ns, u
"curveMember"_s );
339 QDomElement curveElem = curve->asGml3( doc, precision, ns, axisOrder );
340 curveMemberElem.appendChild( curveElem );
341 compoundCurveElem.appendChild( curveMemberElem );
344 return compoundCurveElem;
350 std::unique_ptr< QgsLineString > line(
curveToLine() );
351 return line->asJsonObject( precision );
357 for (
const QgsCurve *curve : mCurves )
359 length += curve->length();
366 if ( mCurves.empty() )
370 return mCurves.at( 0 )->startPoint();
375 if ( mCurves.empty() )
379 return mCurves.at( mCurves.size() - 1 )->endPoint();
385 if ( mCurves.empty() )
390 mCurves[0]->points( pts );
391 for (
int i = 1; i < mCurves.size(); ++i )
394 mCurves[i]->points( pList );
409 for (
int i = 0; i <
nCurves; ++i )
411 nPoints += mCurves.at( i )->numPoints() - 1;
419 if ( mCurves.isEmpty() )
424 if ( !curve->isEmpty() )
432 if ( mCurves.isEmpty() )
435 for (
int i = 0; i < mCurves.size(); ++i )
437 if ( !mCurves[i]->
isValid( error, flags ) )
439 error = QObject::tr(
"Curve[%1]: %2" ).arg( i + 1 ).arg( error );
449 for (
const QgsCurve *curve : mCurves )
451 const int curveIndex = curve->indexOf( point );
452 if ( curveIndex >= 0 )
453 return curveStart + curveIndex;
456 curveStart += curve->numPoints() - 1;
464 std::unique_ptr< QgsLineString > currentLine;
465 for (
const QgsCurve *curve : mCurves )
467 currentLine.reset( curve->curveToLine( tolerance, toleranceType ) );
468 line->
append( currentLine.get() );
479 std::unique_ptr<QgsCurve> gridified(
static_cast< QgsCurve *
>( curve->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, removeRedundantPoints ) ) );
482 result->mCurves.append( gridified.release() );
486 if ( result->mCurves.empty() )
489 return result.release();
494 std::unique_ptr< QgsLineString > line(
curveToLine() );
495 return line->simplifyByDistance( tolerance );
501 const QVector< QgsCurve * > curves = mCurves;
506 result = curve->removeDuplicateNodes( epsilon, useZValues ) || result;
507 if ( curve->numPoints() == 0 ||
qgsDoubleNear( curve->length(), 0.0, epsilon ) )
510 delete mCurves.takeAt( i );
518 curve->moveVertex(
QgsVertexId( -1, -1, 0 ), lastEnd );
529 if ( mCurves.empty() )
543 for (
const QgsCurve *curve : mCurves )
545 if ( curve->boundingBoxIntersects( box3d ) )
558 if ( mCurves.size() == 1 )
559 return mCurves.at( 0 );
566 if ( i < 0 || i >= mCurves.size() )
570 return mCurves.at( i );
578 if ( mCurves.empty() )
602 const bool canExtendPrevious = extendPrevious && previousLineString && newLineString;
603 if ( canExtendPrevious )
605 previousLineString->
append( newLineString );
620 if ( i < 0 || i >= mCurves.size() )
625 delete mCurves.takeAt( i );
638 if ( !mCurves.isEmpty() )
640 lastCurve = mCurves.at( mCurves.size() - 1 );
647 mCurves.append( line );
665 QVector< QgsCurve * > newCurves;
666 newCurves.reserve( mCurves.size() );
667 for (
QgsCurve *curve : std::as_const( mCurves ) )
669 if ( lastCurve && lastCurve->
wkbType() == curve->wkbType() )
693 for (
const QgsCurve *curve : mCurves )
701 for (
QgsCurve *curve : std::as_const( mCurves ) )
703 curve->transform( ct, d, transformZ );
710 for (
QgsCurve *curve : std::as_const( mCurves ) )
712 curve->transform( t, zTranslate, zScale, mTranslate, mScale );
721 for (
const QgsCurve *curve : mCurves )
723 if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
725 pp.lineTo( curve->startPoint().toQPointF() );
727 curve->addToPainterPath( pp );
735 for (
const QgsCurve *curve : mCurves )
737 if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
739 pp.lineTo( curve->startPoint().toQPointF() );
741 curve->addToPainterPath( pp );
748 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
749 if ( curveIds.empty() )
753 int curveId = curveIds.at( 0 ).first;
754 if ( curveId >= mCurves.size() )
759 bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
769 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
770 QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
771 for ( ; idIt != curveIds.constEnd(); ++idIt )
773 mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
776 bool success = !curveIds.isEmpty();
786 const QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
787 if ( curveIds.isEmpty() )
790 const int curveId = curveIds.at( 0 ).first;
791 QgsCurve *curve = mCurves.at( curveId );
792 const QgsVertexId subVertexId = curveIds.at( 0 ).second;
795 if ( curveIds.size() == 1 )
800 if ( circularString && subVertexId.
vertex % 2 == 1 )
810 auto curveC = std::make_unique<QgsCircularString>();
811 curveC->setPoints(
points.mid( subVertexId.
vertex + 1 ) );
812 mCurves.insert( curveId, curveC.release() );
816 auto curveB = std::make_unique<QgsLineString>();
817 curveB->setPoints( partB );
818 mCurves.insert( curveId, curveB.release() );
819 curve = mCurves.at( curveId );
821 if ( subVertexId.
vertex > 1 )
823 auto curveA = std::make_unique<QgsCircularString>();
824 curveA->setPoints(
points.mid( 0, subVertexId.
vertex ) );
825 mCurves.insert( curveId, curveA.release() );
840 else if ( curveIds.size() == 2 )
842 const int nextCurveId = curveIds.at( 1 ).first;
843 QgsCurve *nextCurve = mCurves.at( nextCurveId );
844 const QgsVertexId nextSubVertexId = curveIds.at( 1 ).second;
846 Q_ASSERT( nextCurveId == curveId + 1 );
848 Q_ASSERT( nextSubVertexId.
vertex == 0 );
878 mCurves.insert( curveId, line );
890 mCurves.insert( nextCurveId, line );
902 mCurves.insert( curveId, line );
910 if ( endPointOfFirst != startPointOfSecond )
915 mCurves.insert( nextCurveId, line );
921 bool success = !curveIds.isEmpty();
930 QMap<int, QList<QgsVertexId >> curveVertices;
938 const QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
940 if ( curveIds.isEmpty() )
943 const int firstCurveId = curveIds.at( 0 ).first;
944 const QgsVertexId firstCurveVertex = curveIds.at( 0 ).second;
945 curveVertices[firstCurveId].append( firstCurveVertex );
946 if ( curveIds.size() == 2 )
948 const int secondCurveId = curveIds.at( 1 ).first;
949 const QgsVertexId secondCurveVertex = curveIds.at( 1 ).second;
950 curveVertices[secondCurveId].append( secondCurveVertex );
955 QMapIterator<int, QList<QgsVertexId >> curveVerticesIt( curveVertices );
956 curveVerticesIt.toBack();
957 while ( curveVerticesIt.hasPrevious() )
959 curveVerticesIt.previous();
960 const int curveId = curveVerticesIt.key();
961 QgsCurve *curve = mCurves.at( curveId );
962 QList<QgsVertexId>
vertices = curveVerticesIt.value();
967 if ( circularString )
972 QList<QgsVertexId> circularVerticesToDelete;
973 circularVerticesToDelete.reserve(
vertices.size() );
975 QListIterator<QgsVertexId> curveVerticesIt(
vertices );
978 for (
size_t i =
vertices.size(); i-- > 0; )
983 if ( curveVertexId.vertex % 2 == 1 )
987 if ( !circularVerticesToDelete.isEmpty() )
989 if ( curveVertexId.vertex == circularVerticesToDelete.last().vertex - 1 )
991 circularVerticesToDelete.append( curveVertexId );
995 else if ( i != 0 && curveVertexId.vertex - 1 ==
vertices.at( i - 1 ).vertex )
997 circularVerticesToDelete.append( curveVertexId );
1004 if ( !circularVerticesToDelete.isEmpty() )
1006 if ( !curve->
deleteVertices( QSet<QgsVertexId>( circularVerticesToDelete.begin(), circularVerticesToDelete.end() ) ) )
1012 circularVerticesToDelete.clear();
1020 if ( curveVertexId.vertex <
points.length() - 2 )
1022 auto curveC = std::make_unique<QgsCircularString>();
1023 curveC->setPoints(
points.mid( curveVertexId.vertex + 1 ) );
1024 mCurves.insert( curveId, curveC.release() );
1028 auto curveB = std::make_unique<QgsLineString>();
1029 curveB->setPoints( partB );
1030 mCurves.insert( curveId, curveB.release() );
1031 curve = mCurves.at( curveId );
1033 if ( curveVertexId.vertex > 1 )
1035 auto curveA = std::make_unique<QgsCircularString>();
1036 curveA->setPoints(
points.mid( 0, curveVertexId.vertex ) );
1037 mCurves.insert( curveId, curveA.release() );
1039 curve = mCurves.at( curveId );
1046 circularVerticesToDelete.append( curveVertexId );
1050 if ( !circularVerticesToDelete.isEmpty() )
1052 if ( !curve->
deleteVertices( QSet<QgsVertexId>( circularVerticesToDelete.begin(), circularVerticesToDelete.end() ) ) )
1069 for (
int i = mCurves.size() - 1; i >= 0; i-- )
1078 if ( mCurves.isEmpty() )
1085 for (
size_t i = mCurves.size() - 1; i > 0; i-- )
1088 QgsCurve *previousCurve = mCurves.at( i - 1 );
1094 mCurves.insert( i, line );
1103QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId(
QgsVertexId id )
const
1105 QVector< QPair<int, QgsVertexId> > curveIds;
1107 int currentVertexIndex = 0;
1108 for (
int i = 0; i < mCurves.size(); ++i )
1110 int increment = mCurves.at( i )->numPoints() - 1;
1111 if (
id.vertex >= currentVertexIndex &&
id.vertex <= currentVertexIndex + increment )
1113 int curveVertexId =
id.vertex - currentVertexIndex;
1117 vid.
vertex = curveVertexId;
1118 curveIds.append( qMakePair( i, vid ) );
1119 if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) )
1122 curveIds.append( qMakePair( i + 1, vid ) );
1126 else if (
id.vertex >= currentVertexIndex &&
id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
1128 int curveVertexId =
id.vertex - currentVertexIndex;
1132 vid.
vertex = curveVertexId;
1133 curveIds.append( qMakePair( i, vid ) );
1136 currentVertexIndex += increment;
1157 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
1160 if ( curveIds.length() != 1 )
1163 int curveId = curveIds[0].first;
1165 QgsCurve *curve = mCurves[curveId];
1176 if ( subVertexId.
vertex % 2 == 0 )
1180 circularString->points(
points );
1186 auto curveA = std::make_unique<QgsCircularString>();
1187 curveA->setPoints( partA );
1188 auto curveB = std::make_unique<QgsLineString>();
1189 curveB->setPoints( partB );
1190 auto curveC = std::make_unique<QgsCircularString>();
1191 curveC->setPoints( partC );
1195 mCurves.insert( curveId, curveC.release() );
1196 mCurves.insert( curveId, curveB.release() );
1197 if ( subVertexId.
vertex > 1 )
1198 mCurves.insert( curveId, curveA.release() );
1205 lineString->points(
points );
1211 auto curveA = std::make_unique<QgsLineString>();
1212 curveA->setPoints( partA );
1213 auto curveB = std::make_unique<QgsCircularString>();
1214 curveB->setPoints( partB );
1215 auto curveC = std::make_unique<QgsLineString>();
1216 curveC->setPoints( partC );
1220 mCurves.insert( curveId, curveC.release() );
1221 mCurves.insert( curveId, curveB.release() );
1222 if ( subVertexId.
vertex > 1 )
1223 mCurves.insert( curveId, curveA.release() );
1241 int currentVertexId = 0;
1242 for (
int j = 0; j < mCurves.size(); ++j )
1244 int nCurvePoints = mCurves.at( j )->numPoints();
1245 if ( ( node - currentVertexId ) < nCurvePoints )
1247 return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
1249 currentVertexId += ( nCurvePoints - 1 );
1256 int currentVertexId = 0;
1257 for (
int j = 0; j < mCurves.size(); ++j )
1259 int nCurvePoints = mCurves.at( j )->numPoints();
1260 if ( ( index - currentVertexId ) < nCurvePoints )
1262 return mCurves.at( j )->xAt( index - currentVertexId );
1264 currentVertexId += ( nCurvePoints - 1 );
1271 int currentVertexId = 0;
1272 for (
int j = 0; j < mCurves.size(); ++j )
1274 int nCurvePoints = mCurves.at( j )->numPoints();
1275 if ( ( index - currentVertexId ) < nCurvePoints )
1277 return mCurves.at( j )->yAt( index - currentVertexId );
1279 currentVertexId += ( nCurvePoints - 1 );
1286 int currentVertexId = 0;
1287 for (
int j = 0; j < mCurves.size(); ++j )
1289 int nCurvePoints = mCurves.at( j )->numPoints();
1290 if ( ( index - currentVertexId ) < nCurvePoints )
1292 return mCurves.at( j )->zAt( index - currentVertexId );
1294 currentVertexId += ( nCurvePoints - 1 );
1301 int currentVertexId = 0;
1302 for (
int j = 0; j < mCurves.size(); ++j )
1304 int nCurvePoints = mCurves.at( j )->numPoints();
1305 if ( ( index - currentVertexId ) < nCurvePoints )
1307 return mCurves.at( j )->mAt( index - currentVertexId );
1309 currentVertexId += ( nCurvePoints - 1 );
1317 for (
QgsCurve *curve : std::as_const( mCurves ) )
1319 if ( !curve->transform( transformer ) )
1337 for (
QgsCurve *curve : std::as_const( mCurves ) )
1339 curve->filterVertices( filter );
1346 for (
QgsCurve *curve : std::as_const( mCurves ) )
1355 if ( mCurves.empty() )
1356 return std::make_tuple( std::make_unique< QgsCompoundCurve >(), std::make_unique< QgsCompoundCurve >() );
1360 auto curve1 = std::make_unique< QgsCompoundCurve >();
1361 std::unique_ptr< QgsCompoundCurve > curve2;
1363 for (
const QgsCurve *curve : mCurves )
1365 const int curveSize = curve->numPoints();
1366 if ( !curve2 && index < curveStart + curveSize )
1369 auto [p1, p2] = curve->splitCurveAtVertex( index - curveStart );
1370 if ( !p1->isEmpty() )
1371 curve1->addCurve( p1.release() );
1373 curve2 = std::make_unique< QgsCompoundCurve >();
1374 if ( !p2->isEmpty() )
1375 curve2->addCurve( p2.release() );
1380 curve2->addCurve( curve->clone() );
1382 curve1->addCurve( curve->clone() );
1387 curveStart += curve->numPoints() - 1;
1390 return std::make_tuple( std::move( curve1 ), curve2 ? std::move( curve2 ) : std::make_unique< QgsCompoundCurve >() );
1402 for (
const QgsCurve *curve : mCurves )
1419 for (
const QgsCurve *curve : mCurves )
1438 for (
const QgsCurve *curve : mCurves )
1440 if ( curve->hasCurvedSegments() )
1450 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
1451 if ( curveIds.size() == 1 )
1453 QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
1454 return curve->
vertexAngle( curveIds.at( 0 ).second );
1456 else if ( curveIds.size() > 1 )
1458 QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
1459 QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
1460 double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
1461 double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
1472 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
1474 for (
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
1476 length += mCurves.at( it->first )->segmentLength( it->second );
1484 for (
int i = mCurves.count() - 1; i >= 0; --i )
1486 QgsCurve *reversedCurve = mCurves.at( i )->reversed();
1487 clone->addCurve( reversedCurve );
1497 double distanceTraversed = 0;
1498 for (
const QgsCurve *curve : mCurves )
1500 const double thisCurveLength = curve->length();
1501 if ( distanceTraversed + thisCurveLength > distance ||
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
1504 const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
1507 return curve->interpolatePoint( distanceToPoint );
1510 distanceTraversed += thisCurveLength;
1518 if ( startDistance < 0 && endDistance < 0 )
1521 endDistance = std::max( startDistance, endDistance );
1522 auto substring = std::make_unique< QgsCompoundCurve >();
1524 double distanceTraversed = 0;
1525 for (
const QgsCurve *curve : mCurves )
1527 const double thisCurveLength = curve->length();
1528 if ( distanceTraversed + thisCurveLength < startDistance )
1534 std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
1536 substring->addCurve( part.release() );
1539 distanceTraversed += thisCurveLength;
1540 if ( distanceTraversed > endDistance )
1544 return substring.release();
1554 for (
QgsCurve *curve : std::as_const( mCurves ) )
1556 curve->addZValue( zValue );
1569 for (
QgsCurve *curve : std::as_const( mCurves ) )
1571 curve->addMValue( mValue );
1583 for (
QgsCurve *curve : std::as_const( mCurves ) )
1585 curve->dropZValue();
1597 for (
QgsCurve *curve : std::as_const( mCurves ) )
1599 curve->dropMValue();
1607 for (
QgsCurve *curve : std::as_const( mCurves ) )
1623 if ( fromVertex.
part != 0 || fromVertex.
ring != 0 || toVertex.
part != 0 || toVertex.
ring != 0 )
1626 const int fromVertexNumber = fromVertex.
vertex;
1627 const int toVertexNumber = toVertex.
vertex;
1630 if ( fromVertexNumber < 0 || fromVertexNumber >= totalVertices || toVertexNumber < 0 || toVertexNumber >= totalVertices )
1633 if ( fromVertexNumber == toVertexNumber )
1636 double totalDistance = 0.0;
1639 int currentVertexId = 0;
1640 int fromCurve = -1, toCurve = -1;
1641 int fromCurveVertex = -1, toCurveVertex = -1;
1644 for (
int j = 0; j < mCurves.size(); ++j )
1646 int nCurvePoints = mCurves.at( j )->numPoints();
1649 if ( fromCurve == -1 && fromVertexNumber >= currentVertexId && fromVertexNumber < currentVertexId + nCurvePoints )
1652 fromCurveVertex = fromVertexNumber - currentVertexId;
1656 if ( toCurve == -1 && toVertexNumber >= currentVertexId && toVertexNumber < currentVertexId + nCurvePoints )
1659 toCurveVertex = toVertexNumber - currentVertexId;
1663 currentVertexId += ( nCurvePoints - 1 );
1666 if ( fromCurve == -1 || toCurve == -1 )
1669 if ( fromCurve == toCurve )
1674 return mCurves.at( fromCurve )->distanceBetweenVertices( fromId, toId );
1681 if ( fromCurveVertex < mCurves.at( fromCurve )->numPoints() - 1 )
1684 QgsVertexId endId( 0, 0, mCurves.at( fromCurve )->numPoints() - 1 );
1685 totalDistance += mCurves.at( fromCurve )->distanceBetweenVertices( fromId, endId );
1689 for (
int j = fromCurve + 1; j < toCurve; ++j )
1691 totalDistance += mCurves.at( j )->length();
1695 if ( toCurveVertex > 0 )
1699 totalDistance += mCurves.at( toCurve )->distanceBetweenVertices( startId, toId );
1703 return totalDistance;
QFlags< GeometryValidityFlag > GeometryValidityFlags
Geometry validity flags.
VertexType
Types of vertex.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CompoundCurve
CompoundCurve.
@ CircularString
CircularString.
TransformDirection
Indicates the direction (forward or inverse) of a transform.
virtual bool fromWkb(QgsConstWkbPtr &wkb)=0
Sets the geometry from a WKB string.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
QgsVertexIterator vertices() const
Returns a read-only, Java-style iterator for traversal of vertices of all the geometry,...
bool isMeasure() const
Returns true if the geometry contains m values.
QFlags< WkbFlag > WkbFlags
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
AxisOrder
Axis order for GML generation.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
virtual bool deleteVertices(const QSet< QgsVertexId > &positions)=0
Deletes vertices within the geometry.
QgsAbstractGeometry & operator=(const QgsAbstractGeometry &geom)
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, Qgis::WkbType baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
virtual bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
virtual bool deleteVertex(QgsVertexId position)=0
Deletes a vertex within the geometry.
virtual int compareTo(const QgsAbstractGeometry *other) const
Comparator for sorting of geometry.
QgsAbstractGeometry()=default
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
static endian_t endian()
Returns whether this machine uses big or little endian.
A 3-dimensional box composed of x, y, z coordinates.
void combineWith(const QgsBox3D &box)
Expands the bbox so that it covers both the original rectangle and the given rectangle.
Circular string geometry type.
void points(QgsPointSequence &pts) const override
Returns a list of points within the curve.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
void sumUpArea(double &sum) const override
Sums up the area of the curve by iterating over the vertices (shoelace formula).
QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a new line string geometry corresponding to a segmentized approximation of the curve.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
QgsAbstractGeometry * simplifyByDistance(double tolerance) const override
Simplifies the geometry by applying the Douglas Peucker simplification by distance algorithm.
int compareToSameClass(const QgsAbstractGeometry *other) const final
Compares to an other geometry of the same class, and returns a integer for sorting of the two geometr...
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
QgsCompoundCurve * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
void condenseCurves()
Condenses the curves in this geometry by combining adjacent linestrings a to a single continuous line...
void close()
Appends first point if not already closed.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
int dimension() const override
Returns the inherent dimension of the geometry.
void filterVertices(const std::function< bool(const QgsPoint &) > &filter) override
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
std::tuple< std::unique_ptr< QgsCurve >, std::unique_ptr< QgsCurve > > splitCurveAtVertex(int index) const final
Splits the curve at the specified vertex index, returning two curves which represent the portion of t...
bool boundingBoxIntersects(const QgsBox3D &box3d) const override
Returns true if the bounding box of this geometry intersects with a box3d.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
QString geometryType() const override
Returns a unique string representing the geometry type.
double mAt(int index) const override
Returns the m-coordinate of the specified node in the line string.
double distanceBetweenVertices(QgsVertexId fromVertex, QgsVertexId toVertex) const override
Returns the distance along the curve between two vertices.
bool isEmpty() const override
Returns true if the geometry is empty.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
void transformVertices(const std::function< QgsPoint(const QgsPoint &) > &transform) override
Transforms the vertices from the geometry in place, applying the transform function to every vertex.
int nCurves() const
Returns the number of curves in the geometry.
bool toggleCircularAtVertex(QgsVertexId position)
Converts the vertex at the given position from/to circular.
QgsBox3D calculateBoundingBox3D() const override
Calculates the minimal 3D bounding box for the geometry.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
const QgsAbstractGeometry * simplifiedTypeRef() const override
Returns a reference to the simplest lossless representation of this geometry, e.g.
int wkbSize(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns the length of the QByteArray returned by asWkb().
bool deleteVertices(const QSet< QgsVertexId > &positions) override
Deletes vertices within the geometry.
void sumUpArea3D(double &sum) const override
Sums up the 3d area of the curve by iterating over the vertices (shoelace formula).
void swapXy() override
Swaps the x and y coordinates from the geometry.
void removeCurve(int i)
Removes a curve from the geometry.
void addCurve(QgsCurve *c, bool extendPrevious=false)
Adds a curve to the geometry (takes ownership).
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *std::numeric_limits< double >::epsilon()) const override
Searches for the closest segment of the geometry to a given point.
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
bool dropMValue() override
Drops any measure values which exist in the geometry.
QgsCompoundCurve & operator=(const QgsCompoundCurve &curve)
QgsCompoundCurve * clone() const override
Clones the geometry by performing a deep copy.
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
void points(QgsPointSequence &pts) const override
Returns a list of points within the curve.
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
~QgsCompoundCurve() override
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns a WKB representation of the geometry.
void clear() override
Clears the geometry, ie reset it to a null geometry.
int indexOf(const QgsPoint &point) const final
Returns the index of the first vertex matching the given point, or -1 if a matching vertex is not fou...
void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
QgsCompoundCurve * curveSubstring(double startDistance, double endDistance) const override
Returns a new curve representing a substring of this curve.
void scroll(int firstVertexIndex) final
Scrolls the curve vertices so that they start with the vertex at the given index.
double length() const override
Returns the planar, 2-dimensional length of the geometry.
void addToPainterPath(QPainterPath &path) const override
Adds a curve to a painter path.
QgsPoint * interpolatePoint(double distance) const override
Returns an interpolated point on the curve at the specified distance.
QgsCompoundCurve * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
bool pointAt(int node, QgsPoint &point, Qgis::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
QgsPoint startPoint() const override
Returns the starting point of the curve.
QgsCompoundCurve * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0, bool removeRedundantPoints=false) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
QgsPoint endPoint() const override
Returns the end point of the curve.
int numPoints() const override
Returns the number of points in the curve.
double zAt(int index) const override
Returns the z-coordinate of the specified node in the line string.
void addVertex(const QgsPoint &pt)
Adds a vertex to the end of the geometry.
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
Qgis::WkbType readHeader() const
readHeader
virtual int numPoints() const =0
Returns the number of points in the curve.
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
bool mHasCachedSummedUpArea
bool mHasCachedSummedUpArea3D
virtual bool isClosed() const
Returns true if the curve is closed.
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
QgsBox3D mBoundingBox
Cached bounding box.
virtual QgsPoint startPoint() const =0
Returns the starting point of the curve.
bool hasVertex(QgsVertexId position) const override
Returns true if the geometry contains a vertex matching the given position.
virtual QgsPoint endPoint() const =0
Returns the end point of the curve.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
static double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3)
Calculates the average angle (in radians) between the two linear segments from (x1,...
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType=QString())
Parses a WKT string and returns of list of blocks contained in the WKT.
static QPair< Qgis::WkbType, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
static double closestSegmentFromComponents(T &container, ComponentType ctype, const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon)
Line string geometry type, with support for z-dimension and m-values.
void append(const QgsLineString *line)
Appends the contents of another line string to the end of this line string.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
Point geometry type, with support for z-dimension and m-values.
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
static Qgis::WkbType dropM(Qgis::WkbType type)
Drops the m dimension (if present) for a WKB type and returns the new type.
static Qgis::WkbType dropZ(Qgis::WkbType type)
Drops the z dimension (if present) for a WKB type and returns the new type.
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
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
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QVector< QgsPoint > QgsPointSequence
Utility class for identifying a unique vertex within a geometry.