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 );
731 for (
const QgsCurve *curve : mCurves )
733 if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
735 pp.lineTo( curve->startPoint().toQPointF() );
737 curve->addToPainterPath( pp );
745 for (
const QgsCurve *curve : mCurves )
747 if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
749 pp.lineTo( curve->startPoint().toQPointF() );
751 curve->addToPainterPath( pp );
758 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
759 if ( curveIds.empty() )
763 int curveId = curveIds.at( 0 ).first;
764 if ( curveId >= mCurves.size() )
769 bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
779 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
780 QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
781 for ( ; idIt != curveIds.constEnd(); ++idIt )
783 mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
786 bool success = !curveIds.isEmpty();
796 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
797 if ( curveIds.size() == 1 )
799 if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
804 if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 )
809 else if ( curveIds.size() == 2 )
811 Q_ASSERT( curveIds.at( 1 ).first == curveIds.at( 0 ).first + 1 );
812 Q_ASSERT( curveIds.at( 0 ).second.vertex == mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 );
813 Q_ASSERT( curveIds.at( 1 ).second.vertex == 0 );
818 mCurves.at( curveIds.at( 1 ).first )->numPoints() > 3 )
822 mCurves.at( curveIds.at( 1 ).first ) ->pointAt( 2, intermediatePoint, type );
823 mCurves.at( curveIds.at( 0 ).first )->moveVertex(
824 QgsVertexId( 0, 0, mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 ), intermediatePoint );
826 else if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
832 mCurves.at( curveIds.at( 0 ).first )->numPoints() > 0 &&
835 QgsPoint intermediatePoint = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
836 mCurves.at( curveIds.at( 1 ).first )->moveVertex(
QgsVertexId( 0, 0, 0 ), intermediatePoint );
838 else if ( !mCurves.at( curveIds.at( 1 ).first )->deleteVertex( curveIds.at( 1 ).second ) )
843 if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
844 mCurves.at( curveIds.at( 1 ).first )->numPoints() != 0 )
849 else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() != 0 &&
850 mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
852 mCurves.at( curveIds.at( 0 ).first )->moveVertex(
856 else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
857 mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
864 mCurves.insert( curveIds.at( 0 ).first, line );
868 QgsPoint endPointOfFirst = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
869 QgsPoint startPointOfSecond = mCurves.at( curveIds.at( 1 ).first ) ->startPoint();
870 if ( endPointOfFirst != startPointOfSecond )
875 mCurves.insert( curveIds.at( 1 ).first, line );
880 bool success = !curveIds.isEmpty();
888 QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId(
QgsVertexId id )
const
890 QVector< QPair<int, QgsVertexId> > curveIds;
892 int currentVertexIndex = 0;
893 for (
int i = 0; i < mCurves.size(); ++i )
895 int increment = mCurves.at( i )->numPoints() - 1;
896 if (
id.vertex >= currentVertexIndex &&
id.vertex <= currentVertexIndex + increment )
898 int curveVertexId =
id.vertex - currentVertexIndex;
902 vid.
vertex = curveVertexId;
903 curveIds.append( qMakePair( i, vid ) );
904 if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) )
907 curveIds.append( qMakePair( i + 1, vid ) );
911 else if (
id.vertex >= currentVertexIndex &&
id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
913 int curveVertexId =
id.vertex - currentVertexIndex;
917 vid.
vertex = curveVertexId;
918 curveIds.append( qMakePair( i, vid ) );
921 currentVertexIndex += increment;
943 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
946 if ( curveIds.length() != 1 )
949 int curveId = curveIds[0].first;
957 if (
const QgsCircularString *circularString = qgsgeometry_cast<const QgsCircularString *>( curve ) )
962 if ( subVertexId.
vertex % 2 == 0 )
966 circularString->points(
points );
972 std::unique_ptr<QgsCircularString> curveA = std::make_unique<QgsCircularString>();
973 curveA->setPoints( partA );
974 std::unique_ptr<QgsLineString> curveB = std::make_unique<QgsLineString>();
975 curveB->setPoints( partB );
976 std::unique_ptr<QgsCircularString> curveC = std::make_unique<QgsCircularString>();
977 curveC->setPoints( partC );
981 mCurves.insert( curveId, curveC.release() );
982 mCurves.insert( curveId, curveB.release() );
983 if ( subVertexId.
vertex > 1 )
984 mCurves.insert( curveId, curveA.release() );
991 lineString->points(
points );
1006 mCurves.insert( curveId, curveC );
1007 mCurves.insert( curveId, curveB );
1008 if ( subVertexId.
vertex > 1 )
1009 mCurves.insert( curveId, curveA );
1027 int currentVertexId = 0;
1028 for (
int j = 0; j < mCurves.size(); ++j )
1030 int nCurvePoints = mCurves.at( j )->numPoints();
1031 if ( ( node - currentVertexId ) < nCurvePoints )
1033 return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
1035 currentVertexId += ( nCurvePoints - 1 );
1042 int currentVertexId = 0;
1043 for (
int j = 0; j < mCurves.size(); ++j )
1045 int nCurvePoints = mCurves.at( j )->numPoints();
1046 if ( ( index - currentVertexId ) < nCurvePoints )
1048 return mCurves.at( j )->xAt( index - currentVertexId );
1050 currentVertexId += ( nCurvePoints - 1 );
1057 int currentVertexId = 0;
1058 for (
int j = 0; j < mCurves.size(); ++j )
1060 int nCurvePoints = mCurves.at( j )->numPoints();
1061 if ( ( index - currentVertexId ) < nCurvePoints )
1063 return mCurves.at( j )->yAt( index - currentVertexId );
1065 currentVertexId += ( nCurvePoints - 1 );
1073 for (
QgsCurve *curve : std::as_const( mCurves ) )
1075 if ( !curve->transform( transformer ) )
1093 for (
QgsCurve *curve : std::as_const( mCurves ) )
1095 curve->filterVertices( filter );
1102 for (
QgsCurve *curve : std::as_const( mCurves ) )
1111 if ( mCurves.empty() )
1112 return std::make_tuple( std::make_unique< QgsCompoundCurve >(), std::make_unique< QgsCompoundCurve >() );
1116 std::unique_ptr< QgsCompoundCurve > curve1 = std::make_unique< QgsCompoundCurve >();
1117 std::unique_ptr< QgsCompoundCurve > curve2;
1119 for (
const QgsCurve *curve : mCurves )
1121 const int curveSize = curve->numPoints();
1122 if ( !curve2 && index < curveStart + curveSize )
1125 auto [ p1, p2 ] = curve->splitCurveAtVertex( index - curveStart );
1126 if ( !p1->isEmpty() )
1127 curve1->addCurve( p1.release() );
1129 curve2 = std::make_unique< QgsCompoundCurve >();
1130 if ( !p2->isEmpty() )
1131 curve2->addCurve( p2.release() );
1136 curve2->addCurve( curve->clone() );
1138 curve1->addCurve( curve->clone() );
1143 curveStart += curve->numPoints() - 1;
1146 return std::make_tuple( std::move( curve1 ), curve2 ? std::move( curve2 ) : std::make_unique< QgsCompoundCurve >() );
1151 for (
const QgsCurve *curve : mCurves )
1153 curve->sumUpArea( sum );
1168 for (
const QgsCurve *curve : mCurves )
1170 if ( curve->hasCurvedSegments() )
1180 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
1181 if ( curveIds.size() == 1 )
1183 QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
1184 return curve->
vertexAngle( curveIds.at( 0 ).second );
1186 else if ( curveIds.size() > 1 )
1188 QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
1189 QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
1190 double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
1191 double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
1202 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
1204 for (
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
1206 length += mCurves.at( it->first )->segmentLength( it->second );
1214 for (
int i = mCurves.count() - 1; i >= 0; --i )
1216 QgsCurve *reversedCurve = mCurves.at( i )->reversed();
1227 double distanceTraversed = 0;
1228 for (
const QgsCurve *curve : mCurves )
1230 const double thisCurveLength = curve->
length();
1231 if ( distanceTraversed + thisCurveLength > distance ||
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
1234 const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
1237 return curve->interpolatePoint( distanceToPoint );
1240 distanceTraversed += thisCurveLength;
1248 if ( startDistance < 0 && endDistance < 0 )
1251 endDistance = std::max( startDistance, endDistance );
1252 std::unique_ptr< QgsCompoundCurve > substring = std::make_unique< QgsCompoundCurve >();
1254 double distanceTraversed = 0;
1255 for (
const QgsCurve *curve : mCurves )
1257 const double thisCurveLength = curve->length();
1258 if ( distanceTraversed + thisCurveLength < startDistance )
1264 std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
1266 substring->addCurve( part.release() );
1269 distanceTraversed += thisCurveLength;
1270 if ( distanceTraversed > endDistance )
1274 return substring.release();
1284 for (
QgsCurve *curve : std::as_const( mCurves ) )
1286 curve->addZValue( zValue );
1299 for (
QgsCurve *curve : std::as_const( mCurves ) )
1301 curve->addMValue( mValue );
1313 for (
QgsCurve *curve : std::as_const( mCurves ) )
1315 curve->dropZValue();
1327 for (
QgsCurve *curve : std::as_const( mCurves ) )
1329 curve->dropMValue();
1337 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.