25 #include <QJsonObject> 27 #include <QPainterPath> 29 #include <nlohmann/json.hpp> 50 if ( mCurves.size() != otherCurve->mCurves.size() )
53 for (
int i = 0; i < mCurves.size(); ++i )
55 if ( *mCurves.at( i ) != *otherCurve->mCurves.at( i ) )
64 auto result = qgis::make_unique< QgsCompoundCurve >();
66 return result.release();
71 return QStringLiteral(
"CompoundCurve" );
82 mCurves.reserve( curve.mCurves.size() );
85 mCurves.append( c->
clone() );
97 mCurves.append( c->
clone() );
111 qDeleteAll( mCurves );
118 if ( mCurves.empty() )
124 for (
int i = 1; i < mCurves.size(); ++i )
150 for (
int i = 0; i <
nCurves; ++i )
153 wkbPtr -= 1 +
sizeof( int );
166 currentCurve->
fromWkb( wkbPtr );
167 mCurves.append( currentCurve );
182 if ( parts.second.compare( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) == 0 )
185 QString defaultChildWkbType = QStringLiteral(
"LineString%1%2" ).arg(
is3D() ? QStringLiteral(
"Z" ) : QString(),
isMeasure() ? QStringLiteral(
"M" ) : QString() );
188 for (
const QString &childWkt : blocks )
201 if ( !mCurves.back()->fromWkt( childWkt ) )
212 for (
const QgsCurve *curve : qgis::as_const( mCurves ) )
214 hasZ = hasZ || curve->is3D();
215 hasM = hasM || curve->isMeasure();
229 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
230 QVector<QByteArray> wkbForCurves;
231 wkbForCurves.reserve( mCurves.size() );
232 for (
const QgsCurve *curve : mCurves )
234 QByteArray wkbForCurve = curve->asWkb();
235 binarySize += wkbForCurve.length();
236 wkbForCurves << wkbForCurve;
240 wkbArray.resize( binarySize );
243 wkb << static_cast<quint32>(
wkbType() );
244 wkb << static_cast<quint32>( mCurves.size() );
245 for (
const QByteArray &wkbForCurve : qgis::as_const( wkbForCurves ) )
256 wkt += QStringLiteral(
" EMPTY" );
259 wkt += QLatin1String(
" (" );
260 for (
const QgsCurve *curve : mCurves )
262 QString childWkt = curve->asWkt( precision );
263 if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
266 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
268 wkt += childWkt +
',';
270 if ( wkt.endsWith(
',' ) )
282 std::unique_ptr< QgsLineString > line(
curveToLine() );
283 QDomElement gml = line->asGml2( doc, precision, ns, axisOrder );
289 QDomElement compoundCurveElem = doc.createElementNS( ns, QStringLiteral(
"CompositeCurve" ) );
292 return compoundCurveElem;
294 for (
const QgsCurve *curve : mCurves )
296 QDomElement curveMemberElem = doc.createElementNS( ns, QStringLiteral(
"curveMember" ) );
297 QDomElement curveElem = curve->asGml3( doc, precision, ns, axisOrder );
298 curveMemberElem.appendChild( curveElem );
299 compoundCurveElem.appendChild( curveMemberElem );
302 return compoundCurveElem;
308 std::unique_ptr< QgsLineString > line(
curveToLine() );
309 return line->asJsonObject( precision );
315 for (
const QgsCurve *curve : mCurves )
317 length += curve->length();
324 if ( mCurves.empty() )
328 return mCurves.at( 0 )->startPoint();
333 if ( mCurves.empty() )
337 return mCurves.at( mCurves.size() - 1 )->
endPoint();
343 if ( mCurves.empty() )
348 mCurves[0]->points( pts );
349 for (
int i = 1; i < mCurves.size(); ++i )
352 mCurves[i]->points( pList );
367 for (
int i = 0; i <
nCurves; ++i )
369 nPoints += mCurves.at( i )->numPoints() - 1;
377 if ( mCurves.isEmpty() )
382 if ( !curve->isEmpty() )
391 std::unique_ptr< QgsLineString > currentLine;
392 for (
const QgsCurve *curve : mCurves )
394 currentLine.reset( curve->curveToLine( tolerance, toleranceType ) );
395 line->
append( currentLine.get() );
406 std::unique_ptr<QgsCurve> gridified( static_cast< QgsCurve * >( curve->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) );
409 result->mCurves.append( gridified.release() );
413 if ( result->mCurves.empty() )
416 return result.release();
422 const QVector< QgsCurve * > curves = mCurves;
428 if ( curve->numPoints() == 0 ||
qgsDoubleNear( curve->length(), 0.0, epsilon ) )
431 delete mCurves.takeAt( i );
439 curve->moveVertex(
QgsVertexId( -1, -1, 0 ), lastEnd );
450 if ( i < 0 || i >= mCurves.size() )
454 return mCurves.at( i );
461 if ( mCurves.empty() )
490 if ( i < 0 || i >= mCurves.size() )
495 delete mCurves.takeAt( i );
508 if ( !mCurves.isEmpty() )
510 lastCurve = mCurves.at( mCurves.size() - 1 );
517 mCurves.append( line );
534 for (
const QgsCurve *curve : mCurves )
542 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
544 curve->transform( ct, d, transformZ );
551 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
553 curve->transform( t, zTranslate, zScale, mTranslate, mScale );
561 for (
const QgsCurve *curve : mCurves )
563 curve->addToPainterPath( pp );
571 for (
const QgsCurve *curve : mCurves )
573 curve->addToPainterPath( pp );
580 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
581 if ( curveIds.empty() )
585 int curveId = curveIds.at( 0 ).first;
586 if ( curveId >= mCurves.size() )
591 bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
601 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
602 QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
603 for ( ; idIt != curveIds.constEnd(); ++idIt )
605 mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
608 bool success = !curveIds.isEmpty();
618 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
619 if ( curveIds.size() == 1 )
621 if ( !mCurves.at( curveIds.at( 0 ).first )->
deleteVertex( curveIds.at( 0 ).second ) )
626 if ( mCurves.at( curveIds.at( 0 ).first )->
numPoints() == 0 )
631 else if ( curveIds.size() == 2 )
633 Q_ASSERT( curveIds.at( 1 ).first == curveIds.at( 0 ).first + 1 );
634 Q_ASSERT( curveIds.at( 0 ).second.vertex == mCurves.at( curveIds.at( 0 ).first )->
numPoints() - 1 );
635 Q_ASSERT( curveIds.at( 1 ).second.vertex == 0 );
640 mCurves.at( curveIds.at( 1 ).first )->
numPoints() > 3 )
644 mCurves.at( curveIds.at( 1 ).first ) ->
pointAt( 2, intermediatePoint, type );
645 mCurves.at( curveIds.at( 0 ).first )->
moveVertex(
646 QgsVertexId( 0, 0, mCurves.at( curveIds.at( 0 ).first )->
numPoints() - 1 ), intermediatePoint );
648 else if ( !mCurves.at( curveIds.at( 0 ).first )->
deleteVertex( curveIds.at( 0 ).second ) )
654 mCurves.at( curveIds.at( 0 ).first )->
numPoints() > 0 &&
657 QgsPoint intermediatePoint = mCurves.at( curveIds.at( 0 ).first ) ->
endPoint();
660 else if ( !mCurves.at( curveIds.at( 1 ).first )->
deleteVertex( curveIds.at( 1 ).second ) )
665 if ( mCurves.at( curveIds.at( 0 ).first )->
numPoints() == 0 &&
666 mCurves.at( curveIds.at( 1 ).first )->
numPoints() != 0 )
671 else if ( mCurves.at( curveIds.at( 0 ).first )->
numPoints() != 0 &&
672 mCurves.at( curveIds.at( 1 ).first )->
numPoints() == 0 )
674 mCurves.at( curveIds.at( 0 ).first )->
moveVertex(
678 else if ( mCurves.at( curveIds.at( 0 ).first )->
numPoints() == 0 &&
679 mCurves.at( curveIds.at( 1 ).first )->
numPoints() == 0 )
684 line->insertVertex(
QgsVertexId( 0, 0, 0 ), startPoint );
685 line->insertVertex(
QgsVertexId( 0, 0, 1 ), endPoint );
686 mCurves.insert( curveIds.at( 0 ).first, line );
690 QgsPoint endPointOfFirst = mCurves.at( curveIds.at( 0 ).first ) ->
endPoint();
692 if ( endPointOfFirst != startPointOfSecond )
697 mCurves.insert( curveIds.at( 1 ).first, line );
702 bool success = !curveIds.isEmpty();
710 QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId(
QgsVertexId id )
const 712 QVector< QPair<int, QgsVertexId> > curveIds;
714 int currentVertexIndex = 0;
715 for (
int i = 0; i < mCurves.size(); ++i )
717 int increment = mCurves.at( i )->numPoints() - 1;
718 if (
id.vertex >= currentVertexIndex &&
id.vertex <= currentVertexIndex + increment )
720 int curveVertexId =
id.vertex - currentVertexIndex;
724 vid.
vertex = curveVertexId;
725 curveIds.append( qMakePair( i, vid ) );
726 if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) )
729 curveIds.append( qMakePair( i + 1, vid ) );
733 else if (
id.vertex >= currentVertexIndex &&
id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
735 int curveVertexId =
id.vertex - currentVertexIndex;
739 vid.
vertex = curveVertexId;
740 curveIds.append( qMakePair( i, vid ) );
743 currentVertexIndex += increment;
756 int currentVertexId = 0;
757 for (
int j = 0; j < mCurves.size(); ++j )
759 int nCurvePoints = mCurves.at( j )->numPoints();
760 if ( ( node - currentVertexId ) < nCurvePoints )
762 return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
764 currentVertexId += ( nCurvePoints - 1 );
771 int currentVertexId = 0;
772 for (
int j = 0; j < mCurves.size(); ++j )
774 int nCurvePoints = mCurves.at( j )->numPoints();
775 if ( ( index - currentVertexId ) < nCurvePoints )
777 return mCurves.at( j )->xAt( index - currentVertexId );
779 currentVertexId += ( nCurvePoints - 1 );
786 int currentVertexId = 0;
787 for (
int j = 0; j < mCurves.size(); ++j )
789 int nCurvePoints = mCurves.at( j )->numPoints();
790 if ( ( index - currentVertexId ) < nCurvePoints )
792 return mCurves.at( j )->yAt( index - currentVertexId );
794 currentVertexId += ( nCurvePoints - 1 );
801 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
803 curve->filterVertices( filter );
810 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
819 for (
const QgsCurve *curve : mCurves )
821 curve->sumUpArea( sum );
836 for (
const QgsCurve *curve : mCurves )
838 if ( curve->hasCurvedSegments() )
848 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
849 if ( curveIds.size() == 1 )
851 QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
852 return curve->
vertexAngle( curveIds.at( 0 ).second );
854 else if ( curveIds.size() > 1 )
856 QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
857 QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
858 double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
859 double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
870 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
872 for (
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
874 length += mCurves.at( it->first )->segmentLength( it->second );
882 for (
int i = mCurves.count() - 1; i >= 0; --i )
884 QgsCurve *reversedCurve = mCurves.at( i )->reversed();
895 double distanceTraversed = 0;
896 for (
const QgsCurve *curve : mCurves )
898 const double thisCurveLength = curve->
length();
899 if ( distanceTraversed + thisCurveLength > distance ||
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
902 const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
905 return curve->interpolatePoint( distanceToPoint );
908 distanceTraversed += thisCurveLength;
916 if ( startDistance < 0 && endDistance < 0 )
919 endDistance = std::max( startDistance, endDistance );
920 std::unique_ptr< QgsCompoundCurve > substring = qgis::make_unique< QgsCompoundCurve >();
922 double distanceTraversed = 0;
923 for (
const QgsCurve *curve : mCurves )
925 const double thisCurveLength = curve->length();
926 if ( distanceTraversed + thisCurveLength < startDistance )
932 std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
934 substring->addCurve( part.release() );
937 distanceTraversed += thisCurveLength;
938 if ( distanceTraversed > endDistance )
942 return substring.release();
952 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
954 curve->addZValue( zValue );
967 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
969 curve->addMValue( mValue );
981 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
995 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
1005 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
bool isMeasure() const
Returns true if the geometry contains m values.
QgsPoint startPoint() const override
Returns the starting point of the curve.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
void append(const QgsLineString *line)
Appends the contents of another line string to the end of this line string.
QgsCompoundCurve * clone() const override
Clones the geometry by performing a deep copy.
A rectangle specified with double values.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
void addToPainterPath(QPainterPath &path) const override
Adds a curve to a painter path.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
QgsAbstractGeometry & operator=(const QgsAbstractGeometry &geom)
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
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...
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 (...
int dimension() const override
Returns the inherent dimension of the geometry.
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, y1) to (x2, y2) and (x2, y2) to (x3, y3).
void sumUpArea(double &sum) const override
Sums up the area of the curve by iterating over the vertices (shoelace formula).
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
void swapXy() override
Swaps the x and y coordinates from 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.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle...
void clear() override
Clears the geometry, ie reset it to a null geometry.
static endian_t endian()
Returns whether this machine uses big or little endian.
QgsCompoundCurve * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership...
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
QgsCompoundCurve & operator=(const QgsCompoundCurve &curve)
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 Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
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...
void addCurve(QgsCurve *c)
Adds a curve to the geometry (takes ownership)
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
QgsWkbTypes::Type mWkbType
bool pointAt(int node, QgsPoint &point, QgsVertexId::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
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
virtual QgsPoint endPoint() const =0
Returns the end point of the curve.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
Type
The WKB type describes the number of dimensions a geometry has.
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
double length() const override
Returns the planar, 2-dimensional length of the geometry.
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
Utility class for identifying a unique vertex within a 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...
QString geometryType() const override
Returns a unique string representing the geometry type.
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
Abstract base class for curved geometry type.
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
QgsPoint * interpolatePoint(double distance) const override
Returns an interpolated point on the curve at the specified distance.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Point geometry type, with support for z-dimension and m-values.
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
AxisOrder
Axis order for GML generation.
virtual bool isClosed() const
Returns true if the curve is closed.
void removeCurve(int i)
Removes a curve from the geometry.
int nCurves() const
Returns the number of curves in the geometry.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
bool isEmpty() const override
Returns true if the geometry is empty.
QVector< QgsPoint > QgsPointSequence
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
static Type dropZ(Type type)
Drops the z dimension (if present) for a WKB type and returns the new type.
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
void addVertex(const QgsPoint &pt)
Adds a vertex to the end of the geometry.
bool equals(const QgsCurve &other) const override
Checks whether this curve exactly equals another curve.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
QgsCompoundCurve * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
Line string geometry type, with support for z-dimension and m-values.
QgsCompoundCurve * curveSubstring(double startDistance, double endDistance) const override
Returns a new curve representing a substring of this curve.
QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
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.
QByteArray asWkb() const override
Returns a WKB representation of 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.
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Compound curve geometry type.
Circular string geometry type.
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...
void close()
Appends first point if not already closed.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
~QgsCompoundCurve() override
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...
bool dropMValue() override
Drops any measure values which exist in the geometry.
static Type flatType(Type type)
Returns the flat type for a WKB type.
QgsWkbTypes::Type readHeader() const
readHeader
int numPoints() const override
Returns the number of points in the curve.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
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 ...
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 insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
static double closestSegmentFromComponents(T &container, ComponentType ctype, const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon)
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
QgsPoint endPoint() const override
Returns the end point of the curve.
virtual bool fromWkb(QgsConstWkbPtr &wkb)=0
Sets the geometry from a WKB string.