27 #include <QJsonObject>
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() )
157 for (
int i = 1; i < mCurves.size(); ++i )
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( rectangle ) )
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 );
730 for (
const QgsCurve *curve : mCurves )
732 curve->addToPainterPath( pp );
740 for (
const QgsCurve *curve : mCurves )
742 curve->addToPainterPath( pp );
749 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
750 if ( curveIds.empty() )
754 int curveId = curveIds.at( 0 ).first;
755 if ( curveId >= mCurves.size() )
760 bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
770 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
771 QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
772 for ( ; idIt != curveIds.constEnd(); ++idIt )
774 mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
777 bool success = !curveIds.isEmpty();
787 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
788 if ( curveIds.size() == 1 )
790 if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
795 if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 )
800 else if ( curveIds.size() == 2 )
802 Q_ASSERT( curveIds.at( 1 ).first == curveIds.at( 0 ).first + 1 );
803 Q_ASSERT( curveIds.at( 0 ).second.vertex == mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 );
804 Q_ASSERT( curveIds.at( 1 ).second.vertex == 0 );
809 mCurves.at( curveIds.at( 1 ).first )->numPoints() > 3 )
813 mCurves.at( curveIds.at( 1 ).first ) ->pointAt( 2, intermediatePoint, type );
814 mCurves.at( curveIds.at( 0 ).first )->moveVertex(
815 QgsVertexId( 0, 0, mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 ), intermediatePoint );
817 else if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
823 mCurves.at( curveIds.at( 0 ).first )->numPoints() > 0 &&
826 QgsPoint intermediatePoint = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
827 mCurves.at( curveIds.at( 1 ).first )->moveVertex(
QgsVertexId( 0, 0, 0 ), intermediatePoint );
829 else if ( !mCurves.at( curveIds.at( 1 ).first )->deleteVertex( curveIds.at( 1 ).second ) )
834 if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
835 mCurves.at( curveIds.at( 1 ).first )->numPoints() != 0 )
840 else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() != 0 &&
841 mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
843 mCurves.at( curveIds.at( 0 ).first )->moveVertex(
847 else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
848 mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
855 mCurves.insert( curveIds.at( 0 ).first, line );
859 QgsPoint endPointOfFirst = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
860 QgsPoint startPointOfSecond = mCurves.at( curveIds.at( 1 ).first ) ->startPoint();
861 if ( endPointOfFirst != startPointOfSecond )
866 mCurves.insert( curveIds.at( 1 ).first, line );
871 bool success = !curveIds.isEmpty();
879 QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId(
QgsVertexId id )
const
881 QVector< QPair<int, QgsVertexId> > curveIds;
883 int currentVertexIndex = 0;
884 for (
int i = 0; i < mCurves.size(); ++i )
886 int increment = mCurves.at( i )->numPoints() - 1;
887 if (
id.vertex >= currentVertexIndex &&
id.vertex <= currentVertexIndex + increment )
889 int curveVertexId =
id.vertex - currentVertexIndex;
893 vid.
vertex = curveVertexId;
894 curveIds.append( qMakePair( i, vid ) );
895 if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) )
898 curveIds.append( qMakePair( i + 1, vid ) );
902 else if (
id.vertex >= currentVertexIndex &&
id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
904 int curveVertexId =
id.vertex - currentVertexIndex;
908 vid.
vertex = curveVertexId;
909 curveIds.append( qMakePair( i, vid ) );
912 currentVertexIndex += increment;
934 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
937 if ( curveIds.length() != 1 )
940 int curveId = curveIds[0].first;
948 if (
const QgsCircularString *circularString = qgsgeometry_cast<const QgsCircularString *>( curve ) )
953 if ( subVertexId.
vertex % 2 == 0 )
957 circularString->points(
points );
963 std::unique_ptr<QgsCircularString> curveA = std::make_unique<QgsCircularString>();
964 curveA->setPoints( partA );
965 std::unique_ptr<QgsLineString> curveB = std::make_unique<QgsLineString>();
966 curveB->setPoints( partB );
967 std::unique_ptr<QgsCircularString> curveC = std::make_unique<QgsCircularString>();
968 curveC->setPoints( partC );
972 mCurves.insert( curveId, curveC.release() );
973 mCurves.insert( curveId, curveB.release() );
974 if ( subVertexId.
vertex > 1 )
975 mCurves.insert( curveId, curveA.release() );
982 lineString->points(
points );
997 mCurves.insert( curveId, curveC );
998 mCurves.insert( curveId, curveB );
999 if ( subVertexId.
vertex > 1 )
1000 mCurves.insert( curveId, curveA );
1018 int currentVertexId = 0;
1019 for (
int j = 0; j < mCurves.size(); ++j )
1021 int nCurvePoints = mCurves.at( j )->numPoints();
1022 if ( ( node - currentVertexId ) < nCurvePoints )
1024 return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
1026 currentVertexId += ( nCurvePoints - 1 );
1033 int currentVertexId = 0;
1034 for (
int j = 0; j < mCurves.size(); ++j )
1036 int nCurvePoints = mCurves.at( j )->numPoints();
1037 if ( ( index - currentVertexId ) < nCurvePoints )
1039 return mCurves.at( j )->xAt( index - currentVertexId );
1041 currentVertexId += ( nCurvePoints - 1 );
1048 int currentVertexId = 0;
1049 for (
int j = 0; j < mCurves.size(); ++j )
1051 int nCurvePoints = mCurves.at( j )->numPoints();
1052 if ( ( index - currentVertexId ) < nCurvePoints )
1054 return mCurves.at( j )->yAt( index - currentVertexId );
1056 currentVertexId += ( nCurvePoints - 1 );
1064 for (
QgsCurve *curve : std::as_const( mCurves ) )
1066 if ( !curve->transform( transformer ) )
1084 for (
QgsCurve *curve : std::as_const( mCurves ) )
1086 curve->filterVertices( filter );
1093 for (
QgsCurve *curve : std::as_const( mCurves ) )
1102 if ( mCurves.empty() )
1103 return std::make_tuple( std::make_unique< QgsCompoundCurve >(), std::make_unique< QgsCompoundCurve >() );
1107 std::unique_ptr< QgsCompoundCurve > curve1 = std::make_unique< QgsCompoundCurve >();
1108 std::unique_ptr< QgsCompoundCurve > curve2;
1110 for (
const QgsCurve *curve : mCurves )
1112 const int curveSize = curve->numPoints();
1113 if ( !curve2 && index < curveStart + curveSize )
1116 auto [ p1, p2 ] = curve->splitCurveAtVertex( index - curveStart );
1117 if ( !p1->isEmpty() )
1118 curve1->addCurve( p1.release() );
1120 curve2 = std::make_unique< QgsCompoundCurve >();
1121 if ( !p2->isEmpty() )
1122 curve2->addCurve( p2.release() );
1127 curve2->addCurve( curve->clone() );
1129 curve1->addCurve( curve->clone() );
1134 curveStart += curve->numPoints() - 1;
1137 return std::make_tuple( std::move( curve1 ), curve2 ? std::move( curve2 ) : std::make_unique< QgsCompoundCurve >() );
1142 for (
const QgsCurve *curve : mCurves )
1144 curve->sumUpArea( sum );
1159 for (
const QgsCurve *curve : mCurves )
1161 if ( curve->hasCurvedSegments() )
1171 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
1172 if ( curveIds.size() == 1 )
1174 QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
1175 return curve->
vertexAngle( curveIds.at( 0 ).second );
1177 else if ( curveIds.size() > 1 )
1179 QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
1180 QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
1181 double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
1182 double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
1193 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
1195 for (
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
1197 length += mCurves.at( it->first )->segmentLength( it->second );
1205 for (
int i = mCurves.count() - 1; i >= 0; --i )
1207 QgsCurve *reversedCurve = mCurves.at( i )->reversed();
1218 double distanceTraversed = 0;
1219 for (
const QgsCurve *curve : mCurves )
1221 const double thisCurveLength = curve->
length();
1222 if ( distanceTraversed + thisCurveLength > distance ||
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
1225 const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
1228 return curve->interpolatePoint( distanceToPoint );
1231 distanceTraversed += thisCurveLength;
1239 if ( startDistance < 0 && endDistance < 0 )
1242 endDistance = std::max( startDistance, endDistance );
1243 std::unique_ptr< QgsCompoundCurve > substring = std::make_unique< QgsCompoundCurve >();
1245 double distanceTraversed = 0;
1246 for (
const QgsCurve *curve : mCurves )
1248 const double thisCurveLength = curve->length();
1249 if ( distanceTraversed + thisCurveLength < startDistance )
1255 std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
1257 substring->addCurve( part.release() );
1260 distanceTraversed += thisCurveLength;
1261 if ( distanceTraversed > endDistance )
1265 return substring.release();
1275 for (
QgsCurve *curve : std::as_const( mCurves ) )
1277 curve->addZValue( zValue );
1290 for (
QgsCurve *curve : std::as_const( mCurves ) )
1292 curve->addMValue( mValue );
1304 for (
QgsCurve *curve : std::as_const( mCurves ) )
1306 curve->dropZValue();
1318 for (
QgsCurve *curve : std::as_const( mCurves ) )
1320 curve->dropMValue();
1328 for (
QgsCurve *curve : std::as_const( mCurves ) )
VertexType
Types of vertex.
TransformDirection
Indicates the direction (forward or inverse) of a transform.
Abstract base class for all geometries.
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 is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
virtual bool boundingBoxIntersects(const QgsRectangle &rectangle) const SIP_HOLDGIL
Returns true if the bounding box of this geometry intersects with a rectangle.
AxisOrder
Axis order for GML generation.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
QgsAbstractGeometry & operator=(const QgsAbstractGeometry &geom)
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
virtual int compareTo(const QgsAbstractGeometry *other) const
Comparator for sorting of geometry.
QgsWkbTypes::Type mWkbType
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
static endian_t endian()
Returns whether this machine uses big or little endian.
Circular string geometry type.
void setPoints(const QgsPointSequence &points)
Sets the circular string's points.
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...
const QgsAbstractGeometry * simplifiedTypeRef() const override SIP_HOLDGIL
Returns a reference to the simplest lossless representation of this geometry, e.g.
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.
QgsPoint endPoint() const override SIP_HOLDGIL
Returns the end point of the curve.
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...
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
const QgsCurve * curveAt(int i) const SIP_HOLDGIL
Returns the curve at the specified index.
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.
int numPoints() const override SIP_HOLDGIL
Returns the number of points in the curve.
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 dimension() const override SIP_HOLDGIL
Returns the inherent dimension of the geometry.
bool toggleCircularAtVertex(QgsVertexId position)
Converts the vertex at the given position from/to circular.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
int wkbSize(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns the length of the QByteArray returned by asWkb()
QString geometryType() const override SIP_HOLDGIL
Returns a unique string representing the geometry type.
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 boundingBoxIntersects(const QgsRectangle &rectangle) const override SIP_HOLDGIL
Returns true if the bounding box of this geometry intersects with a rectangle.
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
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.
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.
double length() const override SIP_HOLDGIL
Returns the planar, 2-dimensional length of the geometry.
~QgsCompoundCurve() override
double xAt(int index) const override SIP_HOLDGIL
Returns the x-coordinate of the specified node in the line string.
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...
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.
double yAt(int index) const override SIP_HOLDGIL
Returns the y-coordinate of the specified node in the line string.
QgsCompoundCurve * curveSubstring(double startDistance, double endDistance) const override
Returns a new curve representing a substring of this curve.
QgsPoint startPoint() const override SIP_HOLDGIL
Returns the starting point of the curve.
void scroll(int firstVertexIndex) final
Scrolls the curve vertices so that they start with the vertex at the given index.
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.
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
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.
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.
int nCurves() const SIP_HOLDGIL
Returns the number of curves in the geometry.
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.
void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
QgsWkbTypes::Type 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.
virtual bool isClosed() const SIP_HOLDGIL
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.
QgsRectangle mBoundingBox
Cached bounding box.
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 SIP_HOLDGIL
Tells whether the operation has been canceled already.
static QPair< QgsWkbTypes::Type, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
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 double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3) SIP_HOLDGIL
Calculates the average angle (in radians) between the two linear segments from (x1,...
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 setPoints(const QgsPointSequence &points)
Resets the line string to match the specified list of points.
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...
A rectangle specified with double values.
bool intersects(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle intersects with other rectangle.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Type
The WKB type describes the number of dimensions a geometry has.
static Type dropZ(Type type) SIP_HOLDGIL
Drops the z dimension (if present) for a WKB type and returns the new type.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
static Type dropM(Type type) SIP_HOLDGIL
Drops the m dimension (if present) for a WKB type and returns the new type.
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'. Negative values mean left ...
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.