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 currentVertexIndex += increment;
746 int currentVertexId = 0;
747 for (
int j = 0; j < mCurves.size(); ++j )
749 int nCurvePoints = mCurves.at( j )->numPoints();
750 if ( ( node - currentVertexId ) < nCurvePoints )
752 return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
754 currentVertexId += ( nCurvePoints - 1 );
761 int currentVertexId = 0;
762 for (
int j = 0; j < mCurves.size(); ++j )
764 int nCurvePoints = mCurves.at( j )->numPoints();
765 if ( ( index - currentVertexId ) < nCurvePoints )
767 return mCurves.at( j )->xAt( index - currentVertexId );
769 currentVertexId += ( nCurvePoints - 1 );
776 int currentVertexId = 0;
777 for (
int j = 0; j < mCurves.size(); ++j )
779 int nCurvePoints = mCurves.at( j )->numPoints();
780 if ( ( index - currentVertexId ) < nCurvePoints )
782 return mCurves.at( j )->yAt( index - currentVertexId );
784 currentVertexId += ( nCurvePoints - 1 );
791 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
793 curve->filterVertices( filter );
800 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
809 for (
const QgsCurve *curve : mCurves )
811 curve->sumUpArea( sum );
826 for (
const QgsCurve *curve : mCurves )
828 if ( curve->hasCurvedSegments() )
838 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
839 if ( curveIds.size() == 1 )
841 QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
842 return curve->
vertexAngle( curveIds.at( 0 ).second );
844 else if ( curveIds.size() > 1 )
846 QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
847 QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
848 double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
849 double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
860 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
862 for (
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
864 length += mCurves.at( it->first )->segmentLength( it->second );
872 for (
int i = mCurves.count() - 1; i >= 0; --i )
874 QgsCurve *reversedCurve = mCurves.at( i )->reversed();
885 double distanceTraversed = 0;
886 for (
const QgsCurve *curve : mCurves )
888 const double thisCurveLength = curve->
length();
889 if ( distanceTraversed + thisCurveLength > distance ||
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
892 const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
895 return curve->interpolatePoint( distanceToPoint );
898 distanceTraversed += thisCurveLength;
906 if ( startDistance < 0 && endDistance < 0 )
909 endDistance = std::max( startDistance, endDistance );
910 std::unique_ptr< QgsCompoundCurve > substring = qgis::make_unique< QgsCompoundCurve >();
912 double distanceTraversed = 0;
913 for (
const QgsCurve *curve : mCurves )
915 const double thisCurveLength = curve->length();
916 if ( distanceTraversed + thisCurveLength < startDistance )
922 std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
924 substring->addCurve( part.release() );
927 distanceTraversed += thisCurveLength;
928 if ( distanceTraversed > endDistance )
932 return substring.release();
942 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
944 curve->addZValue( zValue );
957 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
959 curve->addMValue( mValue );
971 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
985 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
995 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'. Negativ values mean left a...
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.