29#include <QPainterPath>
31#include <nlohmann/json.hpp>
45 auto result = std::make_unique< QgsCompoundCurve >();
47 return result.release();
52 const QgsCompoundCurve *otherCurve = qgsgeometry_cast<const QgsCompoundCurve *>( other );
58 while ( i < mCurves.size() && j < otherCurve->mCurves.size() )
62 const int comparison = aGeom->
compareTo( bGeom );
63 if ( comparison != 0 )
70 if ( i < mCurves.size() )
74 if ( j < otherCurve->mCurves.size() )
83 return QStringLiteral(
"CompoundCurve" );
94 mCurves.reserve( curve.mCurves.size() );
97 mCurves.append(
c->clone() );
103 if ( &curve !=
this )
107 for (
const QgsCurve *
c : curve.mCurves )
109 mCurves.append(
c->clone() );
123 qDeleteAll( mCurves );
130 if ( mCurves.empty() )
135 QgsBox3D bbox = mCurves.at( 0 )->boundingBox3D();
136 for (
int i = 1; i < mCurves.size(); ++i )
138 QgsBox3D curveBox = mCurves.at( i )->boundingBox3D();
147 if ( index < 1 || index >= size - 1 )
153 if (
QgsCompoundCurve *curve2 = qgsgeometry_cast< QgsCompoundCurve *>( p2.get() ) )
156 mCurves = std::move( curve2->mCurves );
158 if (
QgsCompoundCurve *curve1 = qgsgeometry_cast< QgsCompoundCurve *>( p1.get() ) )
161 mCurves.append( curve1->mCurves );
162 curve1->mCurves.clear();
184 for (
int i = 0; i <
nCurves; ++i )
187 wkbPtr -= 1 +
sizeof( int );
200 currentCurve->
fromWkb( wkbPtr );
201 mCurves.append( currentCurve );
216 QString secondWithoutParentheses =
parts.second;
217 secondWithoutParentheses = secondWithoutParentheses.remove(
'(' ).remove(
')' ).simplified().remove(
' ' );
218 if ( (
parts.second.compare( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
219 secondWithoutParentheses.isEmpty() )
222 QString defaultChildWkbType = QStringLiteral(
"LineString%1%2" ).arg(
is3D() ? QStringLiteral(
"Z" ) : QString(),
isMeasure() ? QStringLiteral(
"M" ) : QString() );
225 for (
const QString &childWkt : blocks )
238 if ( !mCurves.back()->fromWkt( childWkt ) )
249 for (
const QgsCurve *curve : std::as_const( mCurves ) )
251 hasZ = hasZ || curve->is3D();
252 hasM = hasM || curve->isMeasure();
266 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
267 for (
const QgsCurve *curve : mCurves )
269 binarySize += curve->wkbSize( flags );
280 wkb << static_cast<quint32>(
wkbType() );
281 wkb << static_cast<quint32>( mCurves.size() );
282 for (
const QgsCurve *curve : mCurves )
284 wkb << curve->asWkb( flags );
293 wkt += QLatin1String(
" EMPTY" );
296 wkt += QLatin1String(
" (" );
297 for (
const QgsCurve *curve : mCurves )
299 QString childWkt = curve->asWkt(
precision );
300 if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
303 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
305 wkt += childWkt +
',';
307 if ( wkt.endsWith(
',' ) )
319 std::unique_ptr< QgsLineString > line(
curveToLine() );
320 QDomElement gml = line->asGml2( doc,
precision, ns, axisOrder );
326 QDomElement compoundCurveElem = doc.createElementNS( ns, QStringLiteral(
"CompositeCurve" ) );
329 return compoundCurveElem;
331 for (
const QgsCurve *curve : mCurves )
333 QDomElement curveMemberElem = doc.createElementNS( ns, QStringLiteral(
"curveMember" ) );
334 QDomElement curveElem = curve->asGml3( doc,
precision, ns, axisOrder );
335 curveMemberElem.appendChild( curveElem );
336 compoundCurveElem.appendChild( curveMemberElem );
339 return compoundCurveElem;
345 std::unique_ptr< QgsLineString > line(
curveToLine() );
352 for (
const QgsCurve *curve : mCurves )
354 length += curve->length();
361 if ( mCurves.empty() )
365 return mCurves.at( 0 )->startPoint();
370 if ( mCurves.empty() )
374 return mCurves.at( mCurves.size() - 1 )->endPoint();
380 if ( mCurves.empty() )
385 mCurves[0]->points( pts );
386 for (
int i = 1; i < mCurves.size(); ++i )
389 mCurves[i]->points( pList );
404 for (
int i = 0; i <
nCurves; ++i )
406 nPoints += mCurves.at( i )->numPoints() - 1;
414 if ( mCurves.isEmpty() )
419 if ( !curve->isEmpty() )
427 if ( mCurves.isEmpty() )
430 for (
int i = 0; i < mCurves.size() ; ++i )
432 if ( !mCurves[i]->
isValid( error, flags ) )
434 error = QObject::tr(
"Curve[%1]: %2" ).arg( i + 1 ).arg( error );
444 for (
const QgsCurve *curve : mCurves )
446 const int curveIndex = curve->indexOf( point );
447 if ( curveIndex >= 0 )
448 return curveStart + curveIndex;
451 curveStart += curve->numPoints() - 1;
459 std::unique_ptr< QgsLineString > currentLine;
460 for (
const QgsCurve *curve : mCurves )
462 currentLine.reset( curve->curveToLine( tolerance, toleranceType ) );
463 line->
append( currentLine.get() );
474 std::unique_ptr<QgsCurve> gridified(
static_cast< QgsCurve *
>( curve->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) );
477 result->mCurves.append( gridified.release() );
481 if ( result->mCurves.empty() )
484 return result.release();
490 const QVector< QgsCurve * > curves = mCurves;
496 if ( curve->numPoints() == 0 ||
qgsDoubleNear( curve->length(), 0.0, epsilon ) )
499 delete mCurves.takeAt( i );
507 curve->moveVertex(
QgsVertexId( -1, -1, 0 ), lastEnd );
518 if ( mCurves.empty() )
532 for (
const QgsCurve *curve : mCurves )
534 if ( curve->boundingBoxIntersects( box3d ) )
547 if ( mCurves.size() == 1 )
548 return mCurves.at( 0 );
555 if ( i < 0 || i >= mCurves.size() )
559 return mCurves.at( i );
567 if ( mCurves.empty() )
589 QgsLineString *previousLineString = !mCurves.empty() ? qgsgeometry_cast< QgsLineString * >( mCurves.constLast() ) :
nullptr;
590 const QgsLineString *newLineString = qgsgeometry_cast< const QgsLineString * >(
c );
591 const bool canExtendPrevious = extendPrevious && previousLineString && newLineString;
592 if ( canExtendPrevious )
594 previousLineString->
append( newLineString );
609 if ( i < 0 || i >= mCurves.size() )
614 delete mCurves.takeAt( i );
627 if ( !mCurves.isEmpty() )
629 lastCurve = mCurves.at( mCurves.size() - 1 );
636 mCurves.append( line );
654 QVector< QgsCurve * > newCurves;
655 newCurves.reserve( mCurves.size() );
656 for (
QgsCurve *curve : std::as_const( mCurves ) )
658 if ( lastCurve && lastCurve->
wkbType() == curve->wkbType() )
660 if (
QgsLineString *ls = qgsgeometry_cast< QgsLineString * >( lastCurve ) )
662 ls->append( qgsgeometry_cast< QgsLineString * >( curve ) );
665 else if (
QgsCircularString *cs = qgsgeometry_cast< QgsCircularString * >( lastCurve ) )
667 cs->append( qgsgeometry_cast< QgsCircularString * >( curve ) );
682 for (
const QgsCurve *curve : mCurves )
690 for (
QgsCurve *curve : std::as_const( mCurves ) )
692 curve->transform( ct, d, transformZ );
699 for (
QgsCurve *curve : std::as_const( mCurves ) )
701 curve->transform( t, zTranslate, zScale, mTranslate, mScale );
710 for (
const QgsCurve *curve : mCurves )
712 if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
714 pp.lineTo( curve->startPoint().toQPointF() );
716 curve->addToPainterPath( pp );
724 for (
const QgsCurve *curve : mCurves )
726 if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
728 pp.lineTo( curve->startPoint().toQPointF() );
730 curve->addToPainterPath( pp );
737 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
738 if ( curveIds.empty() )
742 int curveId = curveIds.at( 0 ).first;
743 if ( curveId >= mCurves.size() )
748 bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
758 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
759 QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
760 for ( ; idIt != curveIds.constEnd(); ++idIt )
762 mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
765 bool success = !curveIds.isEmpty();
775 const QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
776 if ( curveIds.isEmpty() )
779 const int curveId = curveIds.at( 0 ).first;
780 QgsCurve *curve = mCurves.at( curveId );
781 const QgsVertexId subVertexId = curveIds.at( 0 ).second;
784 if ( curveIds.size() == 1 )
786 const QgsCircularString *circularString = qgsgeometry_cast<const QgsCircularString *>( curve );
789 if ( circularString && subVertexId.
vertex % 2 == 1 )
799 std::unique_ptr<QgsCircularString> curveC = std::make_unique<QgsCircularString>();
800 curveC->setPoints(
points.mid( subVertexId.
vertex + 1 ) );
801 mCurves.insert( curveId, curveC.release() );
805 std::unique_ptr<QgsLineString> curveB = std::make_unique<QgsLineString>();
806 curveB->setPoints( partB );
807 mCurves.insert( curveId, curveB.release() );
808 curve = mCurves.at( curveId );
810 if ( subVertexId.
vertex > 1 )
812 std::unique_ptr<QgsCircularString> curveA = std::make_unique<QgsCircularString>();
813 curveA->setPoints(
points.mid( 0, subVertexId.
vertex ) );
814 mCurves.insert( curveId, curveA.release() );
828 else if ( curveIds.size() == 2 )
830 const int nextCurveId = curveIds.at( 1 ).first;
831 QgsCurve *nextCurve = mCurves.at( nextCurveId );
832 const QgsVertexId nextSubVertexId = curveIds.at( 1 ).second;
834 Q_ASSERT( nextCurveId == curveId + 1 );
836 Q_ASSERT( nextSubVertexId.
vertex == 0 );
847 nextCurve->
pointAt( 2, intermediatePoint, type );
886 mCurves.insert( curveId, line );
892 if ( endPointOfFirst != startPointOfSecond )
897 mCurves.insert( nextCurveId, line );
902 bool success = !curveIds.isEmpty();
908QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId(
QgsVertexId id )
const
910 QVector< QPair<int, QgsVertexId> > curveIds;
912 int currentVertexIndex = 0;
913 for (
int i = 0; i < mCurves.size(); ++i )
915 int increment = mCurves.at( i )->numPoints() - 1;
916 if (
id.vertex >= currentVertexIndex &&
id.vertex <= currentVertexIndex + increment )
918 int curveVertexId =
id.vertex - currentVertexIndex;
922 vid.
vertex = curveVertexId;
923 curveIds.append( qMakePair( i, vid ) );
924 if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) )
927 curveIds.append( qMakePair( i + 1, vid ) );
931 else if (
id.vertex >= currentVertexIndex &&
id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
933 int curveVertexId =
id.vertex - currentVertexIndex;
937 vid.
vertex = curveVertexId;
938 curveIds.append( qMakePair( i, vid ) );
941 currentVertexIndex += increment;
963 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
966 if ( curveIds.length() != 1 )
969 int curveId = curveIds[0].first;
977 if (
const QgsCircularString *circularString = qgsgeometry_cast<const QgsCircularString *>( curve ) )
982 if ( subVertexId.
vertex % 2 == 0 )
986 circularString->points(
points );
992 std::unique_ptr<QgsCircularString> curveA = std::make_unique<QgsCircularString>();
993 curveA->setPoints( partA );
994 std::unique_ptr<QgsLineString> curveB = std::make_unique<QgsLineString>();
995 curveB->setPoints( partB );
996 std::unique_ptr<QgsCircularString> curveC = std::make_unique<QgsCircularString>();
997 curveC->setPoints( partC );
1001 mCurves.insert( curveId, curveC.release() );
1002 mCurves.insert( curveId, curveB.release() );
1003 if ( subVertexId.
vertex > 1 )
1004 mCurves.insert( curveId, curveA.release() );
1011 lineString->points(
points );
1017 std::unique_ptr<QgsLineString> curveA = std::make_unique<QgsLineString>();
1018 curveA->setPoints( partA );
1019 std::unique_ptr<QgsCircularString> curveB = std::make_unique<QgsCircularString>();
1020 curveB->setPoints( partB );
1021 std::unique_ptr<QgsLineString> curveC = std::make_unique<QgsLineString>();
1022 curveC->setPoints( partC );
1026 mCurves.insert( curveId, curveC.release() );
1027 mCurves.insert( curveId, curveB.release() );
1028 if ( subVertexId.
vertex > 1 )
1029 mCurves.insert( curveId, curveA.release() );
1047 int currentVertexId = 0;
1048 for (
int j = 0; j < mCurves.size(); ++j )
1050 int nCurvePoints = mCurves.at( j )->numPoints();
1051 if ( ( node - currentVertexId ) < nCurvePoints )
1053 return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
1055 currentVertexId += ( nCurvePoints - 1 );
1062 int currentVertexId = 0;
1063 for (
int j = 0; j < mCurves.size(); ++j )
1065 int nCurvePoints = mCurves.at( j )->numPoints();
1066 if ( ( index - currentVertexId ) < nCurvePoints )
1068 return mCurves.at( j )->xAt( index - currentVertexId );
1070 currentVertexId += ( nCurvePoints - 1 );
1077 int currentVertexId = 0;
1078 for (
int j = 0; j < mCurves.size(); ++j )
1080 int nCurvePoints = mCurves.at( j )->numPoints();
1081 if ( ( index - currentVertexId ) < nCurvePoints )
1083 return mCurves.at( j )->yAt( index - currentVertexId );
1085 currentVertexId += ( nCurvePoints - 1 );
1092 int currentVertexId = 0;
1093 for (
int j = 0; j < mCurves.size(); ++j )
1095 int nCurvePoints = mCurves.at( j )->numPoints();
1096 if ( ( index - currentVertexId ) < nCurvePoints )
1098 return mCurves.at( j )->zAt( index - currentVertexId );
1100 currentVertexId += ( nCurvePoints - 1 );
1107 int currentVertexId = 0;
1108 for (
int j = 0; j < mCurves.size(); ++j )
1110 int nCurvePoints = mCurves.at( j )->numPoints();
1111 if ( ( index - currentVertexId ) < nCurvePoints )
1113 return mCurves.at( j )->mAt( index - currentVertexId );
1115 currentVertexId += ( nCurvePoints - 1 );
1123 for (
QgsCurve *curve : std::as_const( mCurves ) )
1125 if ( !curve->transform( transformer ) )
1143 for (
QgsCurve *curve : std::as_const( mCurves ) )
1145 curve->filterVertices( filter );
1152 for (
QgsCurve *curve : std::as_const( mCurves ) )
1161 if ( mCurves.empty() )
1162 return std::make_tuple( std::make_unique< QgsCompoundCurve >(), std::make_unique< QgsCompoundCurve >() );
1166 std::unique_ptr< QgsCompoundCurve > curve1 = std::make_unique< QgsCompoundCurve >();
1167 std::unique_ptr< QgsCompoundCurve > curve2;
1169 for (
const QgsCurve *curve : mCurves )
1171 const int curveSize = curve->numPoints();
1172 if ( !curve2 && index < curveStart + curveSize )
1175 auto [ p1, p2 ] = curve->splitCurveAtVertex( index - curveStart );
1176 if ( !p1->isEmpty() )
1177 curve1->addCurve( p1.release() );
1179 curve2 = std::make_unique< QgsCompoundCurve >();
1180 if ( !p2->isEmpty() )
1181 curve2->addCurve( p2.release() );
1186 curve2->addCurve( curve->clone() );
1188 curve1->addCurve( curve->clone() );
1193 curveStart += curve->numPoints() - 1;
1196 return std::make_tuple( std::move( curve1 ), curve2 ? std::move( curve2 ) : std::make_unique< QgsCompoundCurve >() );
1208 for (
const QgsCurve *curve : mCurves )
1227 for (
const QgsCurve *curve : mCurves )
1229 if ( curve->hasCurvedSegments() )
1239 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
1240 if ( curveIds.size() == 1 )
1242 QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
1243 return curve->
vertexAngle( curveIds.at( 0 ).second );
1245 else if ( curveIds.size() > 1 )
1247 QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
1248 QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
1249 double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
1250 double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
1261 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
1263 for (
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
1265 length += mCurves.at( it->first )->segmentLength( it->second );
1273 for (
int i = mCurves.count() - 1; i >= 0; --i )
1275 QgsCurve *reversedCurve = mCurves.at( i )->reversed();
1286 double distanceTraversed = 0;
1287 for (
const QgsCurve *curve : mCurves )
1289 const double thisCurveLength = curve->
length();
1290 if ( distanceTraversed + thisCurveLength > distance ||
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
1293 const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
1296 return curve->interpolatePoint( distanceToPoint );
1299 distanceTraversed += thisCurveLength;
1307 if ( startDistance < 0 && endDistance < 0 )
1310 endDistance = std::max( startDistance, endDistance );
1311 std::unique_ptr< QgsCompoundCurve > substring = std::make_unique< QgsCompoundCurve >();
1313 double distanceTraversed = 0;
1314 for (
const QgsCurve *curve : mCurves )
1316 const double thisCurveLength = curve->length();
1317 if ( distanceTraversed + thisCurveLength < startDistance )
1323 std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
1325 substring->addCurve( part.release() );
1328 distanceTraversed += thisCurveLength;
1329 if ( distanceTraversed > endDistance )
1333 return substring.release();
1343 for (
QgsCurve *curve : std::as_const( mCurves ) )
1345 curve->addZValue( zValue );
1358 for (
QgsCurve *curve : std::as_const( mCurves ) )
1360 curve->addMValue( mValue );
1372 for (
QgsCurve *curve : std::as_const( mCurves ) )
1374 curve->dropZValue();
1386 for (
QgsCurve *curve : std::as_const( mCurves ) )
1388 curve->dropMValue();
1396 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 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 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.
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.