21#include <nlohmann/json.hpp>
33#include <QPainterPath>
47 auto result = std::make_unique< QgsCompoundCurve >();
49 return result.release();
60 while ( i < mCurves.size() && j < otherCurve->mCurves.size() )
64 const int comparison = aGeom->
compareTo( bGeom );
65 if ( comparison != 0 )
72 if ( i < mCurves.size() )
76 if ( j < otherCurve->mCurves.size() )
85 return u
"CompoundCurve"_s;
96 mCurves.reserve( curve.mCurves.size() );
99 mCurves.append( c->clone() );
106 if ( &curve !=
this )
109 for (
const QgsCurve *
c : curve.mCurves )
111 mCurves.append(
c->clone() );
125 qDeleteAll( mCurves );
132 if ( mCurves.empty() )
137 QgsBox3D bbox = mCurves.at( 0 )->boundingBox3D();
138 for (
int i = 1; i < mCurves.size(); ++i )
140 QgsBox3D curveBox = mCurves.at( i )->boundingBox3D();
149 if ( index < 1 || index >= size - 1 )
158 mCurves = std::move( curve2->mCurves );
163 mCurves.append( curve1->mCurves );
164 curve1->mCurves.clear();
186 for (
int i = 0; i <
nCurves; ++i )
189 wkbPtr -= 1 +
sizeof( int );
202 currentCurve->
fromWkb( wkbPtr );
203 mCurves.append( currentCurve );
218 QString secondWithoutParentheses =
parts.second;
219 secondWithoutParentheses = secondWithoutParentheses.remove(
'(' ).remove(
')' ).simplified().remove(
' ' );
220 if ( (
parts.second.compare(
"EMPTY"_L1, Qt::CaseInsensitive ) == 0 ) ||
221 secondWithoutParentheses.isEmpty() )
224 QString defaultChildWkbType = u
"LineString%1%2"_s.arg(
is3D() ? u
"Z"_s : QString(),
isMeasure() ? u
"M"_s : QString() );
227 for (
const QString &childWkt : blocks )
240 if ( !mCurves.back()->fromWkt( childWkt ) )
251 for (
const QgsCurve *curve : std::as_const( mCurves ) )
253 hasZ = hasZ || curve->is3D();
254 hasM = hasM || curve->isMeasure();
268 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
269 for (
const QgsCurve *curve : mCurves )
271 binarySize += curve->wkbSize( flags );
282 wkb << static_cast<quint32>(
wkbType() );
283 wkb << static_cast<quint32>( mCurves.size() );
284 for (
const QgsCurve *curve : mCurves )
286 wkb << curve->asWkb( flags );
299 for (
const QgsCurve *curve : mCurves )
301 QString childWkt = curve->asWkt( precision );
305 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
307 wkt += childWkt +
',';
309 if ( wkt.endsWith(
',' ) )
321 std::unique_ptr< QgsLineString > line(
curveToLine() );
322 QDomElement gml = line->asGml2( doc, precision, ns, axisOrder );
328 QDomElement compoundCurveElem = doc.createElementNS( ns, u
"CompositeCurve"_s );
331 return compoundCurveElem;
333 for (
const QgsCurve *curve : mCurves )
335 QDomElement curveMemberElem = doc.createElementNS( ns, u
"curveMember"_s );
336 QDomElement curveElem = curve->asGml3( doc, precision, ns, axisOrder );
337 curveMemberElem.appendChild( curveElem );
338 compoundCurveElem.appendChild( curveMemberElem );
341 return compoundCurveElem;
347 std::unique_ptr< QgsLineString > line(
curveToLine() );
348 return line->asJsonObject( precision );
354 for (
const QgsCurve *curve : mCurves )
356 length += curve->length();
363 if ( mCurves.empty() )
367 return mCurves.at( 0 )->startPoint();
372 if ( mCurves.empty() )
376 return mCurves.at( mCurves.size() - 1 )->endPoint();
382 if ( mCurves.empty() )
387 mCurves[0]->points( pts );
388 for (
int i = 1; i < mCurves.size(); ++i )
391 mCurves[i]->points( pList );
406 for (
int i = 0; i <
nCurves; ++i )
408 nPoints += mCurves.at( i )->numPoints() - 1;
416 if ( mCurves.isEmpty() )
421 if ( !curve->isEmpty() )
429 if ( mCurves.isEmpty() )
432 for (
int i = 0; i < mCurves.size() ; ++i )
434 if ( !mCurves[i]->
isValid( error, flags ) )
436 error = QObject::tr(
"Curve[%1]: %2" ).arg( i + 1 ).arg( error );
446 for (
const QgsCurve *curve : mCurves )
448 const int curveIndex = curve->indexOf( point );
449 if ( curveIndex >= 0 )
450 return curveStart + curveIndex;
453 curveStart += curve->numPoints() - 1;
461 std::unique_ptr< QgsLineString > currentLine;
462 for (
const QgsCurve *curve : mCurves )
464 currentLine.reset( curve->curveToLine( tolerance, toleranceType ) );
465 line->
append( currentLine.get() );
476 std::unique_ptr<QgsCurve> gridified(
static_cast< QgsCurve *
>( curve->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, removeRedundantPoints ) ) );
479 result->mCurves.append( gridified.release() );
483 if ( result->mCurves.empty() )
486 return result.release();
491 std::unique_ptr< QgsLineString > line(
curveToLine() );
492 return line->simplifyByDistance( tolerance );
498 const QVector< QgsCurve * > curves = mCurves;
503 result = curve->removeDuplicateNodes( epsilon, useZValues ) || result;
504 if ( curve->numPoints() == 0 ||
qgsDoubleNear( curve->length(), 0.0, epsilon ) )
507 delete mCurves.takeAt( i );
515 curve->moveVertex(
QgsVertexId( -1, -1, 0 ), lastEnd );
526 if ( mCurves.empty() )
540 for (
const QgsCurve *curve : mCurves )
542 if ( curve->boundingBoxIntersects( box3d ) )
555 if ( mCurves.size() == 1 )
556 return mCurves.at( 0 );
563 if ( i < 0 || i >= mCurves.size() )
567 return mCurves.at( i );
575 if ( mCurves.empty() )
599 const bool canExtendPrevious = extendPrevious && previousLineString && newLineString;
600 if ( canExtendPrevious )
602 previousLineString->
append( newLineString );
617 if ( i < 0 || i >= mCurves.size() )
622 delete mCurves.takeAt( i );
635 if ( !mCurves.isEmpty() )
637 lastCurve = mCurves.at( mCurves.size() - 1 );
644 mCurves.append( line );
662 QVector< QgsCurve * > newCurves;
663 newCurves.reserve( mCurves.size() );
664 for (
QgsCurve *curve : std::as_const( mCurves ) )
666 if ( lastCurve && lastCurve->
wkbType() == curve->wkbType() )
690 for (
const QgsCurve *curve : mCurves )
698 for (
QgsCurve *curve : std::as_const( mCurves ) )
700 curve->transform( ct, d, transformZ );
707 for (
QgsCurve *curve : std::as_const( mCurves ) )
709 curve->transform( t, zTranslate, zScale, mTranslate, mScale );
718 for (
const QgsCurve *curve : mCurves )
720 if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
722 pp.lineTo( curve->startPoint().toQPointF() );
724 curve->addToPainterPath( pp );
732 for (
const QgsCurve *curve : mCurves )
734 if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
736 pp.lineTo( curve->startPoint().toQPointF() );
738 curve->addToPainterPath( pp );
745 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
746 if ( curveIds.empty() )
750 int curveId = curveIds.at( 0 ).first;
751 if ( curveId >= mCurves.size() )
756 bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
766 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
767 QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
768 for ( ; idIt != curveIds.constEnd(); ++idIt )
770 mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
773 bool success = !curveIds.isEmpty();
783 const QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
784 if ( curveIds.isEmpty() )
787 const int curveId = curveIds.at( 0 ).first;
788 QgsCurve *curve = mCurves.at( curveId );
789 const QgsVertexId subVertexId = curveIds.at( 0 ).second;
792 if ( curveIds.size() == 1 )
797 if ( circularString && subVertexId.
vertex % 2 == 1 )
807 auto curveC = std::make_unique<QgsCircularString>();
808 curveC->setPoints(
points.mid( subVertexId.
vertex + 1 ) );
809 mCurves.insert( curveId, curveC.release() );
813 auto curveB = std::make_unique<QgsLineString>();
814 curveB->setPoints( partB );
815 mCurves.insert( curveId, curveB.release() );
816 curve = mCurves.at( curveId );
818 if ( subVertexId.
vertex > 1 )
820 auto curveA = std::make_unique<QgsCircularString>();
821 curveA->setPoints(
points.mid( 0, subVertexId.
vertex ) );
822 mCurves.insert( curveId, curveA.release() );
837 else if ( curveIds.size() == 2 )
839 const int nextCurveId = curveIds.at( 1 ).first;
840 QgsCurve *nextCurve = mCurves.at( nextCurveId );
841 const QgsVertexId nextSubVertexId = curveIds.at( 1 ).second;
843 Q_ASSERT( nextCurveId == curveId + 1 );
845 Q_ASSERT( nextSubVertexId.
vertex == 0 );
875 mCurves.insert( curveId, line );
887 mCurves.insert( nextCurveId, line );
900 mCurves.insert( curveId, line );
908 if ( endPointOfFirst != startPointOfSecond )
913 mCurves.insert( nextCurveId, line );
919 bool success = !curveIds.isEmpty();
925QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId(
QgsVertexId id )
const
927 QVector< QPair<int, QgsVertexId> > curveIds;
929 int currentVertexIndex = 0;
930 for (
int i = 0; i < mCurves.size(); ++i )
932 int increment = mCurves.at( i )->numPoints() - 1;
933 if (
id.vertex >= currentVertexIndex &&
id.vertex <= currentVertexIndex + increment )
935 int curveVertexId =
id.vertex - currentVertexIndex;
939 vid.
vertex = curveVertexId;
940 curveIds.append( qMakePair( i, vid ) );
941 if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) )
944 curveIds.append( qMakePair( i + 1, vid ) );
948 else if (
id.vertex >= currentVertexIndex &&
id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
950 int curveVertexId =
id.vertex - currentVertexIndex;
954 vid.
vertex = curveVertexId;
955 curveIds.append( qMakePair( i, vid ) );
958 currentVertexIndex += increment;
980 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
983 if ( curveIds.length() != 1 )
986 int curveId = curveIds[0].first;
999 if ( subVertexId.
vertex % 2 == 0 )
1003 circularString->points(
points );
1009 auto curveA = std::make_unique<QgsCircularString>();
1010 curveA->setPoints( partA );
1011 auto curveB = std::make_unique<QgsLineString>();
1012 curveB->setPoints( partB );
1013 auto curveC = std::make_unique<QgsCircularString>();
1014 curveC->setPoints( partC );
1018 mCurves.insert( curveId, curveC.release() );
1019 mCurves.insert( curveId, curveB.release() );
1020 if ( subVertexId.
vertex > 1 )
1021 mCurves.insert( curveId, curveA.release() );
1028 lineString->points(
points );
1034 auto curveA = std::make_unique<QgsLineString>();
1035 curveA->setPoints( partA );
1036 auto curveB = std::make_unique<QgsCircularString>();
1037 curveB->setPoints( partB );
1038 auto curveC = std::make_unique<QgsLineString>();
1039 curveC->setPoints( partC );
1043 mCurves.insert( curveId, curveC.release() );
1044 mCurves.insert( curveId, curveB.release() );
1045 if ( subVertexId.
vertex > 1 )
1046 mCurves.insert( curveId, curveA.release() );
1064 int currentVertexId = 0;
1065 for (
int j = 0; j < mCurves.size(); ++j )
1067 int nCurvePoints = mCurves.at( j )->numPoints();
1068 if ( ( node - currentVertexId ) < nCurvePoints )
1070 return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
1072 currentVertexId += ( nCurvePoints - 1 );
1079 int currentVertexId = 0;
1080 for (
int j = 0; j < mCurves.size(); ++j )
1082 int nCurvePoints = mCurves.at( j )->numPoints();
1083 if ( ( index - currentVertexId ) < nCurvePoints )
1085 return mCurves.at( j )->xAt( index - currentVertexId );
1087 currentVertexId += ( nCurvePoints - 1 );
1094 int currentVertexId = 0;
1095 for (
int j = 0; j < mCurves.size(); ++j )
1097 int nCurvePoints = mCurves.at( j )->numPoints();
1098 if ( ( index - currentVertexId ) < nCurvePoints )
1100 return mCurves.at( j )->yAt( index - currentVertexId );
1102 currentVertexId += ( nCurvePoints - 1 );
1109 int currentVertexId = 0;
1110 for (
int j = 0; j < mCurves.size(); ++j )
1112 int nCurvePoints = mCurves.at( j )->numPoints();
1113 if ( ( index - currentVertexId ) < nCurvePoints )
1115 return mCurves.at( j )->zAt( index - currentVertexId );
1117 currentVertexId += ( nCurvePoints - 1 );
1124 int currentVertexId = 0;
1125 for (
int j = 0; j < mCurves.size(); ++j )
1127 int nCurvePoints = mCurves.at( j )->numPoints();
1128 if ( ( index - currentVertexId ) < nCurvePoints )
1130 return mCurves.at( j )->mAt( index - currentVertexId );
1132 currentVertexId += ( nCurvePoints - 1 );
1140 for (
QgsCurve *curve : std::as_const( mCurves ) )
1142 if ( !curve->transform( transformer ) )
1160 for (
QgsCurve *curve : std::as_const( mCurves ) )
1162 curve->filterVertices( filter );
1169 for (
QgsCurve *curve : std::as_const( mCurves ) )
1178 if ( mCurves.empty() )
1179 return std::make_tuple( std::make_unique< QgsCompoundCurve >(), std::make_unique< QgsCompoundCurve >() );
1183 auto curve1 = std::make_unique< QgsCompoundCurve >();
1184 std::unique_ptr< QgsCompoundCurve > curve2;
1186 for (
const QgsCurve *curve : mCurves )
1188 const int curveSize = curve->numPoints();
1189 if ( !curve2 && index < curveStart + curveSize )
1192 auto [ p1, p2 ] = curve->splitCurveAtVertex( index - curveStart );
1193 if ( !p1->isEmpty() )
1194 curve1->addCurve( p1.release() );
1196 curve2 = std::make_unique< QgsCompoundCurve >();
1197 if ( !p2->isEmpty() )
1198 curve2->addCurve( p2.release() );
1203 curve2->addCurve( curve->clone() );
1205 curve1->addCurve( curve->clone() );
1210 curveStart += curve->numPoints() - 1;
1213 return std::make_tuple( std::move( curve1 ), curve2 ? std::move( curve2 ) : std::make_unique< QgsCompoundCurve >() );
1225 for (
const QgsCurve *curve : mCurves )
1242 for (
const QgsCurve *curve : mCurves )
1261 for (
const QgsCurve *curve : mCurves )
1263 if ( curve->hasCurvedSegments() )
1273 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
1274 if ( curveIds.size() == 1 )
1276 QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
1277 return curve->
vertexAngle( curveIds.at( 0 ).second );
1279 else if ( curveIds.size() > 1 )
1281 QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
1282 QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
1283 double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
1284 double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
1295 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
1297 for (
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
1299 length += mCurves.at( it->first )->segmentLength( it->second );
1307 for (
int i = mCurves.count() - 1; i >= 0; --i )
1309 QgsCurve *reversedCurve = mCurves.at( i )->reversed();
1310 clone->addCurve( reversedCurve );
1320 double distanceTraversed = 0;
1321 for (
const QgsCurve *curve : mCurves )
1323 const double thisCurveLength = curve->length();
1324 if ( distanceTraversed + thisCurveLength > distance ||
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
1327 const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
1330 return curve->interpolatePoint( distanceToPoint );
1333 distanceTraversed += thisCurveLength;
1341 if ( startDistance < 0 && endDistance < 0 )
1344 endDistance = std::max( startDistance, endDistance );
1345 auto substring = std::make_unique< QgsCompoundCurve >();
1347 double distanceTraversed = 0;
1348 for (
const QgsCurve *curve : mCurves )
1350 const double thisCurveLength = curve->length();
1351 if ( distanceTraversed + thisCurveLength < startDistance )
1357 std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
1359 substring->addCurve( part.release() );
1362 distanceTraversed += thisCurveLength;
1363 if ( distanceTraversed > endDistance )
1367 return substring.release();
1377 for (
QgsCurve *curve : std::as_const( mCurves ) )
1379 curve->addZValue( zValue );
1392 for (
QgsCurve *curve : std::as_const( mCurves ) )
1394 curve->addMValue( mValue );
1406 for (
QgsCurve *curve : std::as_const( mCurves ) )
1408 curve->dropZValue();
1420 for (
QgsCurve *curve : std::as_const( mCurves ) )
1422 curve->dropMValue();
1430 for (
QgsCurve *curve : std::as_const( mCurves ) )
1446 if ( fromVertex.
part != 0 || fromVertex.
ring != 0 || toVertex.
part != 0 || toVertex.
ring != 0 )
1449 const int fromVertexNumber = fromVertex.
vertex;
1450 const int toVertexNumber = toVertex.
vertex;
1453 if ( fromVertexNumber < 0 || fromVertexNumber >= totalVertices || toVertexNumber < 0 || toVertexNumber >= totalVertices )
1456 if ( fromVertexNumber == toVertexNumber )
1459 double totalDistance = 0.0;
1462 int currentVertexId = 0;
1463 int fromCurve = -1, toCurve = -1;
1464 int fromCurveVertex = -1, toCurveVertex = -1;
1467 for (
int j = 0; j < mCurves.size(); ++j )
1469 int nCurvePoints = mCurves.at( j )->numPoints();
1472 if ( fromCurve == -1 && fromVertexNumber >= currentVertexId && fromVertexNumber < currentVertexId + nCurvePoints )
1475 fromCurveVertex = fromVertexNumber - currentVertexId;
1479 if ( toCurve == -1 && toVertexNumber >= currentVertexId && toVertexNumber < currentVertexId + nCurvePoints )
1482 toCurveVertex = toVertexNumber - currentVertexId;
1486 currentVertexId += ( nCurvePoints - 1 );
1489 if ( fromCurve == -1 || toCurve == -1 )
1492 if ( fromCurve == toCurve )
1497 return mCurves.at( fromCurve )->distanceBetweenVertices( fromId, toId );
1504 if ( fromCurveVertex < mCurves.at( fromCurve )->numPoints() - 1 )
1507 QgsVertexId endId( 0, 0, mCurves.at( fromCurve )->numPoints() - 1 );
1508 totalDistance += mCurves.at( fromCurve )->distanceBetweenVertices( fromId, endId );
1512 for (
int j = fromCurve + 1; j < toCurve; ++j )
1514 totalDistance += mCurves.at( j )->length();
1518 if ( toCurveVertex > 0 )
1522 totalDistance += mCurves.at( toCurve )->distanceBetweenVertices( startId, toId );
1526 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.
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.
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().
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.
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.