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 QStringLiteral(
"CompoundCurve" );
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( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
221 secondWithoutParentheses.isEmpty() )
224 QString defaultChildWkbType = QStringLiteral(
"LineString%1%2" ).arg(
is3D() ? QStringLiteral(
"Z" ) : QString(),
isMeasure() ? QStringLiteral(
"M" ) : 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 );
295 wkt += QLatin1String(
" EMPTY" );
298 wkt += QLatin1String(
" (" );
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, QStringLiteral(
"CompositeCurve" ) );
331 return compoundCurveElem;
333 for (
const QgsCurve *curve : mCurves )
335 QDomElement curveMemberElem = doc.createElementNS( ns, QStringLiteral(
"curveMember" ) );
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 )
1244 for (
const QgsCurve *curve : mCurves )
1246 if ( curve->hasCurvedSegments() )
1256 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
1257 if ( curveIds.size() == 1 )
1259 QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
1260 return curve->
vertexAngle( curveIds.at( 0 ).second );
1262 else if ( curveIds.size() > 1 )
1264 QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
1265 QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
1266 double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
1267 double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
1278 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
1280 for (
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
1282 length += mCurves.at( it->first )->segmentLength( it->second );
1290 for (
int i = mCurves.count() - 1; i >= 0; --i )
1292 QgsCurve *reversedCurve = mCurves.at( i )->reversed();
1293 clone->addCurve( reversedCurve );
1303 double distanceTraversed = 0;
1304 for (
const QgsCurve *curve : mCurves )
1306 const double thisCurveLength = curve->length();
1307 if ( distanceTraversed + thisCurveLength > distance ||
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
1310 const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
1313 return curve->interpolatePoint( distanceToPoint );
1316 distanceTraversed += thisCurveLength;
1324 if ( startDistance < 0 && endDistance < 0 )
1327 endDistance = std::max( startDistance, endDistance );
1328 auto substring = std::make_unique< QgsCompoundCurve >();
1330 double distanceTraversed = 0;
1331 for (
const QgsCurve *curve : mCurves )
1333 const double thisCurveLength = curve->length();
1334 if ( distanceTraversed + thisCurveLength < startDistance )
1340 std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
1342 substring->addCurve( part.release() );
1345 distanceTraversed += thisCurveLength;
1346 if ( distanceTraversed > endDistance )
1350 return substring.release();
1360 for (
QgsCurve *curve : std::as_const( mCurves ) )
1362 curve->addZValue( zValue );
1375 for (
QgsCurve *curve : std::as_const( mCurves ) )
1377 curve->addMValue( mValue );
1389 for (
QgsCurve *curve : std::as_const( mCurves ) )
1391 curve->dropZValue();
1403 for (
QgsCurve *curve : std::as_const( mCurves ) )
1405 curve->dropMValue();
1413 for (
QgsCurve *curve : std::as_const( mCurves ) )
1429 if ( fromVertex.
part != 0 || fromVertex.
ring != 0 || toVertex.
part != 0 || toVertex.
ring != 0 )
1432 const int fromVertexNumber = fromVertex.
vertex;
1433 const int toVertexNumber = toVertex.
vertex;
1436 if ( fromVertexNumber < 0 || fromVertexNumber >= totalVertices || toVertexNumber < 0 || toVertexNumber >= totalVertices )
1439 if ( fromVertexNumber == toVertexNumber )
1442 double totalDistance = 0.0;
1445 int currentVertexId = 0;
1446 int fromCurve = -1, toCurve = -1;
1447 int fromCurveVertex = -1, toCurveVertex = -1;
1450 for (
int j = 0; j < mCurves.size(); ++j )
1452 int nCurvePoints = mCurves.at( j )->numPoints();
1455 if ( fromCurve == -1 && fromVertexNumber >= currentVertexId && fromVertexNumber < currentVertexId + nCurvePoints )
1458 fromCurveVertex = fromVertexNumber - currentVertexId;
1462 if ( toCurve == -1 && toVertexNumber >= currentVertexId && toVertexNumber < currentVertexId + nCurvePoints )
1465 toCurveVertex = toVertexNumber - currentVertexId;
1469 currentVertexId += ( nCurvePoints - 1 );
1472 if ( fromCurve == -1 || toCurve == -1 )
1475 if ( fromCurve == toCurve )
1480 return mCurves.at( fromCurve )->distanceBetweenVertices( fromId, toId );
1487 if ( fromCurveVertex < mCurves.at( fromCurve )->numPoints() - 1 )
1490 QgsVertexId endId( 0, 0, mCurves.at( fromCurve )->numPoints() - 1 );
1491 totalDistance += mCurves.at( fromCurve )->distanceBetweenVertices( fromId, endId );
1495 for (
int j = fromCurve + 1; j < toCurve; ++j )
1497 totalDistance += mCurves.at( j )->length();
1501 if ( toCurveVertex > 0 )
1505 totalDistance += mCurves.at( toCurve )->distanceBetweenVertices( startId, toId );
1509 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 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
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.