29#include <QPainterPath>
31#include <nlohmann/json.hpp>
45 const QgsCompoundCurve *otherCurve = qgsgeometry_cast< const QgsCompoundCurve * >( &other );
52 if ( mCurves.size() != otherCurve->mCurves.size() )
55 for (
int i = 0; i < mCurves.size(); ++i )
57 if ( *mCurves.at( i ) != *otherCurve->mCurves.at( i ) )
66 auto result = std::make_unique< QgsCompoundCurve >();
68 return result.release();
73 const QgsCompoundCurve *otherCurve = qgsgeometry_cast<const QgsCompoundCurve *>( other );
79 while ( i < mCurves.size() && j < otherCurve->mCurves.size() )
83 const int comparison = aGeom->
compareTo( bGeom );
84 if ( comparison != 0 )
91 if ( i < mCurves.size() )
95 if ( j < otherCurve->mCurves.size() )
104 return QStringLiteral(
"CompoundCurve" );
115 mCurves.reserve( curve.mCurves.size() );
116 for (
const QgsCurve *
c : curve.mCurves )
118 mCurves.append(
c->clone() );
124 if ( &curve !=
this )
128 for (
const QgsCurve *
c : curve.mCurves )
130 mCurves.append(
c->clone() );
144 qDeleteAll( mCurves );
151 if ( mCurves.empty() )
156 QgsBox3D bbox = mCurves.at( 0 )->boundingBox3D();
157 for (
int i = 1; i < mCurves.size(); ++i )
159 QgsBox3D curveBox = mCurves.at( i )->boundingBox3D();
168 if ( index < 1 || index >= size - 1 )
174 if (
QgsCompoundCurve *curve2 = qgsgeometry_cast< QgsCompoundCurve *>( p2.get() ) )
177 mCurves = std::move( curve2->mCurves );
179 if (
QgsCompoundCurve *curve1 = qgsgeometry_cast< QgsCompoundCurve *>( p1.get() ) )
182 mCurves.append( curve1->mCurves );
183 curve1->mCurves.clear();
205 for (
int i = 0; i <
nCurves; ++i )
208 wkbPtr -= 1 +
sizeof( int );
221 currentCurve->
fromWkb( wkbPtr );
222 mCurves.append( currentCurve );
237 QString secondWithoutParentheses =
parts.second;
238 secondWithoutParentheses = secondWithoutParentheses.remove(
'(' ).remove(
')' ).simplified().remove(
' ' );
239 if ( (
parts.second.compare( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
240 secondWithoutParentheses.isEmpty() )
243 QString defaultChildWkbType = QStringLiteral(
"LineString%1%2" ).arg(
is3D() ? QStringLiteral(
"Z" ) : QString(),
isMeasure() ? QStringLiteral(
"M" ) : QString() );
246 for (
const QString &childWkt : blocks )
259 if ( !mCurves.back()->fromWkt( childWkt ) )
270 for (
const QgsCurve *curve : std::as_const( mCurves ) )
272 hasZ = hasZ || curve->is3D();
273 hasM = hasM || curve->isMeasure();
287 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
288 for (
const QgsCurve *curve : mCurves )
290 binarySize += curve->wkbSize( flags );
301 wkb << static_cast<quint32>(
wkbType() );
302 wkb << static_cast<quint32>( mCurves.size() );
303 for (
const QgsCurve *curve : mCurves )
305 wkb << curve->asWkb( flags );
314 wkt += QLatin1String(
" EMPTY" );
317 wkt += QLatin1String(
" (" );
318 for (
const QgsCurve *curve : mCurves )
320 QString childWkt = curve->asWkt(
precision );
321 if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
324 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
326 wkt += childWkt +
',';
328 if ( wkt.endsWith(
',' ) )
340 std::unique_ptr< QgsLineString > line(
curveToLine() );
341 QDomElement gml = line->asGml2( doc,
precision, ns, axisOrder );
347 QDomElement compoundCurveElem = doc.createElementNS( ns, QStringLiteral(
"CompositeCurve" ) );
350 return compoundCurveElem;
352 for (
const QgsCurve *curve : mCurves )
354 QDomElement curveMemberElem = doc.createElementNS( ns, QStringLiteral(
"curveMember" ) );
355 QDomElement curveElem = curve->asGml3( doc,
precision, ns, axisOrder );
356 curveMemberElem.appendChild( curveElem );
357 compoundCurveElem.appendChild( curveMemberElem );
360 return compoundCurveElem;
366 std::unique_ptr< QgsLineString > line(
curveToLine() );
373 for (
const QgsCurve *curve : mCurves )
375 length += curve->length();
382 if ( mCurves.empty() )
386 return mCurves.at( 0 )->startPoint();
391 if ( mCurves.empty() )
395 return mCurves.at( mCurves.size() - 1 )->endPoint();
401 if ( mCurves.empty() )
406 mCurves[0]->points( pts );
407 for (
int i = 1; i < mCurves.size(); ++i )
410 mCurves[i]->points( pList );
425 for (
int i = 0; i <
nCurves; ++i )
427 nPoints += mCurves.at( i )->numPoints() - 1;
435 if ( mCurves.isEmpty() )
440 if ( !curve->isEmpty() )
448 if ( mCurves.isEmpty() )
451 for (
int i = 0; i < mCurves.size() ; ++i )
453 if ( !mCurves[i]->
isValid( error, flags ) )
455 error = QObject::tr(
"Curve[%1]: %2" ).arg( i + 1 ).arg( error );
465 for (
const QgsCurve *curve : mCurves )
467 const int curveIndex = curve->indexOf( point );
468 if ( curveIndex >= 0 )
469 return curveStart + curveIndex;
472 curveStart += curve->numPoints() - 1;
480 std::unique_ptr< QgsLineString > currentLine;
481 for (
const QgsCurve *curve : mCurves )
483 currentLine.reset( curve->curveToLine( tolerance, toleranceType ) );
484 line->
append( currentLine.get() );
495 std::unique_ptr<QgsCurve> gridified(
static_cast< QgsCurve *
>( curve->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) );
498 result->mCurves.append( gridified.release() );
502 if ( result->mCurves.empty() )
505 return result.release();
511 const QVector< QgsCurve * > curves = mCurves;
517 if ( curve->numPoints() == 0 ||
qgsDoubleNear( curve->length(), 0.0, epsilon ) )
520 delete mCurves.takeAt( i );
528 curve->moveVertex(
QgsVertexId( -1, -1, 0 ), lastEnd );
539 if ( mCurves.empty() )
553 for (
const QgsCurve *curve : mCurves )
555 if ( curve->boundingBoxIntersects( box3d ) )
568 if ( mCurves.size() == 1 )
569 return mCurves.at( 0 );
576 if ( i < 0 || i >= mCurves.size() )
580 return mCurves.at( i );
588 if ( mCurves.empty() )
610 QgsLineString *previousLineString = !mCurves.empty() ? qgsgeometry_cast< QgsLineString * >( mCurves.constLast() ) :
nullptr;
611 const QgsLineString *newLineString = qgsgeometry_cast< const QgsLineString * >(
c );
612 const bool canExtendPrevious = extendPrevious && previousLineString && newLineString;
613 if ( canExtendPrevious )
615 previousLineString->
append( newLineString );
630 if ( i < 0 || i >= mCurves.size() )
635 delete mCurves.takeAt( i );
648 if ( !mCurves.isEmpty() )
650 lastCurve = mCurves.at( mCurves.size() - 1 );
657 mCurves.append( line );
675 QVector< QgsCurve * > newCurves;
676 newCurves.reserve( mCurves.size() );
677 for (
QgsCurve *curve : std::as_const( mCurves ) )
679 if ( lastCurve && lastCurve->
wkbType() == curve->wkbType() )
681 if (
QgsLineString *ls = qgsgeometry_cast< QgsLineString * >( lastCurve ) )
683 ls->append( qgsgeometry_cast< QgsLineString * >( curve ) );
686 else if (
QgsCircularString *cs = qgsgeometry_cast< QgsCircularString * >( lastCurve ) )
688 cs->append( qgsgeometry_cast< QgsCircularString * >( curve ) );
703 for (
const QgsCurve *curve : mCurves )
711 for (
QgsCurve *curve : std::as_const( mCurves ) )
713 curve->transform( ct, d, transformZ );
720 for (
QgsCurve *curve : std::as_const( mCurves ) )
722 curve->transform( t, zTranslate, zScale, mTranslate, mScale );
731 for (
const QgsCurve *curve : mCurves )
733 if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
735 pp.lineTo( curve->startPoint().toQPointF() );
737 curve->addToPainterPath( pp );
745 for (
const QgsCurve *curve : mCurves )
747 if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
749 pp.lineTo( curve->startPoint().toQPointF() );
751 curve->addToPainterPath( pp );
758 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
759 if ( curveIds.empty() )
763 int curveId = curveIds.at( 0 ).first;
764 if ( curveId >= mCurves.size() )
769 bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
779 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
780 QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
781 for ( ; idIt != curveIds.constEnd(); ++idIt )
783 mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
786 bool success = !curveIds.isEmpty();
796 const QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
797 if ( curveIds.isEmpty() )
800 const int curveId = curveIds.at( 0 ).first;
801 QgsCurve *curve = mCurves.at( curveId );
802 const QgsVertexId subVertexId = curveIds.at( 0 ).second;
805 if ( curveIds.size() == 1 )
807 const QgsCircularString *circularString = qgsgeometry_cast<const QgsCircularString *>( curve );
810 if ( circularString && subVertexId.
vertex % 2 == 1 )
820 std::unique_ptr<QgsCircularString> curveC = std::make_unique<QgsCircularString>();
821 curveC->setPoints(
points.mid( subVertexId.
vertex + 1 ) );
822 mCurves.insert( curveId, curveC.release() );
826 std::unique_ptr<QgsLineString> curveB = std::make_unique<QgsLineString>();
827 curveB->setPoints( partB );
828 mCurves.insert( curveId, curveB.release() );
829 curve = mCurves.at( curveId );
831 if ( subVertexId.
vertex > 1 )
833 std::unique_ptr<QgsCircularString> curveA = std::make_unique<QgsCircularString>();
834 curveA->setPoints(
points.mid( 0, subVertexId.
vertex ) );
835 mCurves.insert( curveId, curveA.release() );
849 else if ( curveIds.size() == 2 )
851 const int nextCurveId = curveIds.at( 1 ).first;
852 QgsCurve *nextCurve = mCurves.at( nextCurveId );
853 const QgsVertexId nextSubVertexId = curveIds.at( 1 ).second;
855 Q_ASSERT( nextCurveId == curveId + 1 );
857 Q_ASSERT( nextSubVertexId.
vertex == 0 );
868 nextCurve->
pointAt( 2, intermediatePoint, type );
907 mCurves.insert( curveId, line );
913 if ( endPointOfFirst != startPointOfSecond )
918 mCurves.insert( nextCurveId, line );
923 bool success = !curveIds.isEmpty();
929QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId(
QgsVertexId id )
const
931 QVector< QPair<int, QgsVertexId> > curveIds;
933 int currentVertexIndex = 0;
934 for (
int i = 0; i < mCurves.size(); ++i )
936 int increment = mCurves.at( i )->numPoints() - 1;
937 if (
id.vertex >= currentVertexIndex &&
id.vertex <= currentVertexIndex + increment )
939 int curveVertexId =
id.vertex - currentVertexIndex;
943 vid.
vertex = curveVertexId;
944 curveIds.append( qMakePair( i, vid ) );
945 if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) )
948 curveIds.append( qMakePair( i + 1, vid ) );
952 else if (
id.vertex >= currentVertexIndex &&
id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
954 int curveVertexId =
id.vertex - currentVertexIndex;
958 vid.
vertex = curveVertexId;
959 curveIds.append( qMakePair( i, vid ) );
962 currentVertexIndex += increment;
984 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
987 if ( curveIds.length() != 1 )
990 int curveId = curveIds[0].first;
998 if (
const QgsCircularString *circularString = qgsgeometry_cast<const QgsCircularString *>( curve ) )
1003 if ( subVertexId.
vertex % 2 == 0 )
1007 circularString->points(
points );
1013 std::unique_ptr<QgsCircularString> curveA = std::make_unique<QgsCircularString>();
1014 curveA->setPoints( partA );
1015 std::unique_ptr<QgsLineString> curveB = std::make_unique<QgsLineString>();
1016 curveB->setPoints( partB );
1017 std::unique_ptr<QgsCircularString> curveC = std::make_unique<QgsCircularString>();
1018 curveC->setPoints( partC );
1022 mCurves.insert( curveId, curveC.release() );
1023 mCurves.insert( curveId, curveB.release() );
1024 if ( subVertexId.
vertex > 1 )
1025 mCurves.insert( curveId, curveA.release() );
1032 lineString->points(
points );
1038 std::unique_ptr<QgsLineString> curveA = std::make_unique<QgsLineString>();
1039 curveA->setPoints( partA );
1040 std::unique_ptr<QgsCircularString> curveB = std::make_unique<QgsCircularString>();
1041 curveB->setPoints( partB );
1042 std::unique_ptr<QgsLineString> curveC = std::make_unique<QgsLineString>();
1043 curveC->setPoints( partC );
1047 mCurves.insert( curveId, curveC.release() );
1048 mCurves.insert( curveId, curveB.release() );
1049 if ( subVertexId.
vertex > 1 )
1050 mCurves.insert( curveId, curveA.release() );
1068 int currentVertexId = 0;
1069 for (
int j = 0; j < mCurves.size(); ++j )
1071 int nCurvePoints = mCurves.at( j )->numPoints();
1072 if ( ( node - currentVertexId ) < nCurvePoints )
1074 return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
1076 currentVertexId += ( nCurvePoints - 1 );
1083 int currentVertexId = 0;
1084 for (
int j = 0; j < mCurves.size(); ++j )
1086 int nCurvePoints = mCurves.at( j )->numPoints();
1087 if ( ( index - currentVertexId ) < nCurvePoints )
1089 return mCurves.at( j )->xAt( index - currentVertexId );
1091 currentVertexId += ( nCurvePoints - 1 );
1098 int currentVertexId = 0;
1099 for (
int j = 0; j < mCurves.size(); ++j )
1101 int nCurvePoints = mCurves.at( j )->numPoints();
1102 if ( ( index - currentVertexId ) < nCurvePoints )
1104 return mCurves.at( j )->yAt( index - currentVertexId );
1106 currentVertexId += ( nCurvePoints - 1 );
1113 int currentVertexId = 0;
1114 for (
int j = 0; j < mCurves.size(); ++j )
1116 int nCurvePoints = mCurves.at( j )->numPoints();
1117 if ( ( index - currentVertexId ) < nCurvePoints )
1119 return mCurves.at( j )->zAt( index - currentVertexId );
1121 currentVertexId += ( nCurvePoints - 1 );
1128 int currentVertexId = 0;
1129 for (
int j = 0; j < mCurves.size(); ++j )
1131 int nCurvePoints = mCurves.at( j )->numPoints();
1132 if ( ( index - currentVertexId ) < nCurvePoints )
1134 return mCurves.at( j )->mAt( index - currentVertexId );
1136 currentVertexId += ( nCurvePoints - 1 );
1144 for (
QgsCurve *curve : std::as_const( mCurves ) )
1146 if ( !curve->transform( transformer ) )
1164 for (
QgsCurve *curve : std::as_const( mCurves ) )
1166 curve->filterVertices( filter );
1173 for (
QgsCurve *curve : std::as_const( mCurves ) )
1182 if ( mCurves.empty() )
1183 return std::make_tuple( std::make_unique< QgsCompoundCurve >(), std::make_unique< QgsCompoundCurve >() );
1187 std::unique_ptr< QgsCompoundCurve > curve1 = std::make_unique< QgsCompoundCurve >();
1188 std::unique_ptr< QgsCompoundCurve > curve2;
1190 for (
const QgsCurve *curve : mCurves )
1192 const int curveSize = curve->numPoints();
1193 if ( !curve2 && index < curveStart + curveSize )
1196 auto [ p1, p2 ] = curve->splitCurveAtVertex( index - curveStart );
1197 if ( !p1->isEmpty() )
1198 curve1->addCurve( p1.release() );
1200 curve2 = std::make_unique< QgsCompoundCurve >();
1201 if ( !p2->isEmpty() )
1202 curve2->addCurve( p2.release() );
1207 curve2->addCurve( curve->clone() );
1209 curve1->addCurve( curve->clone() );
1214 curveStart += curve->numPoints() - 1;
1217 return std::make_tuple( std::move( curve1 ), curve2 ? std::move( curve2 ) : std::make_unique< QgsCompoundCurve >() );
1229 for (
const QgsCurve *curve : mCurves )
1248 for (
const QgsCurve *curve : mCurves )
1250 if ( curve->hasCurvedSegments() )
1260 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
1261 if ( curveIds.size() == 1 )
1263 QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
1264 return curve->
vertexAngle( curveIds.at( 0 ).second );
1266 else if ( curveIds.size() > 1 )
1268 QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
1269 QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
1270 double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
1271 double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
1282 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
1284 for (
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
1286 length += mCurves.at( it->first )->segmentLength( it->second );
1294 for (
int i = mCurves.count() - 1; i >= 0; --i )
1296 QgsCurve *reversedCurve = mCurves.at( i )->reversed();
1307 double distanceTraversed = 0;
1308 for (
const QgsCurve *curve : mCurves )
1310 const double thisCurveLength = curve->
length();
1311 if ( distanceTraversed + thisCurveLength > distance ||
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
1314 const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
1317 return curve->interpolatePoint( distanceToPoint );
1320 distanceTraversed += thisCurveLength;
1328 if ( startDistance < 0 && endDistance < 0 )
1331 endDistance = std::max( startDistance, endDistance );
1332 std::unique_ptr< QgsCompoundCurve > substring = std::make_unique< QgsCompoundCurve >();
1334 double distanceTraversed = 0;
1335 for (
const QgsCurve *curve : mCurves )
1337 const double thisCurveLength = curve->length();
1338 if ( distanceTraversed + thisCurveLength < startDistance )
1344 std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
1346 substring->addCurve( part.release() );
1349 distanceTraversed += thisCurveLength;
1350 if ( distanceTraversed > endDistance )
1354 return substring.release();
1364 for (
QgsCurve *curve : std::as_const( mCurves ) )
1366 curve->addZValue( zValue );
1379 for (
QgsCurve *curve : std::as_const( mCurves ) )
1381 curve->addMValue( mValue );
1393 for (
QgsCurve *curve : std::as_const( mCurves ) )
1395 curve->dropZValue();
1407 for (
QgsCurve *curve : std::as_const( mCurves ) )
1409 curve->dropMValue();
1417 for (
QgsCurve *curve : std::as_const( mCurves ) )
VertexType
Types of vertex.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CompoundCurve
CompoundCurve.
@ CircularString
CircularString.
TransformDirection
Flags for raster layer temporal capabilities.
Abstract base class for all geometries.
virtual bool fromWkb(QgsConstWkbPtr &wkb)=0
Sets the geometry from a WKB string.
virtual bool moveVertex(QgsVertexId position, const QgsPoint &newPos)=0
Moves a vertex within the geometry.
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.
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 double length() const
Returns the planar, 2-dimensional length of the geometry.
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.
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.
bool intersects(const QgsBox3D &other) const
Returns true if box intersects with another box.
void combineWith(const QgsBox3D &box)
Expands the bbox so that it covers both the original rectangle and the given rectangle.
bool isNull() const
Test if the box is null (holding no spatial information).
Circular string geometry type.
void points(QgsPointSequence &pts) const override
Returns a list of points within the curve.
Compound curve geometry type.
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...
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.
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 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
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 equals(const QgsCurve &other) const override
Checks whether this curve exactly equals another curve.
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) 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
Abstract base class for curved geometry type.
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
virtual bool pointAt(int node, QgsPoint &point, Qgis::VertexType &type) const =0
Returns the point and vertex id of a point within the curve.
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 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)
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,...
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.
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...
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 bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static 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)
QVector< QgsPoint > QgsPointSequence
Utility class for identifying a unique vertex within a geometry.