26 #include <QJsonObject>
28 #include <QPainterPath>
30 #include <nlohmann/json.hpp>
44 const QgsCompoundCurve *otherCurve = qgsgeometry_cast< const QgsCompoundCurve * >( &other );
51 if ( mCurves.size() != otherCurve->mCurves.size() )
54 for (
int i = 0; i < mCurves.size(); ++i )
56 if ( *mCurves.at( i ) != *otherCurve->mCurves.at( i ) )
65 auto result = qgis::make_unique< QgsCompoundCurve >();
67 return result.release();
72 return QStringLiteral(
"CompoundCurve" );
83 mCurves.reserve( curve.mCurves.size() );
86 mCurves.append(
c->clone() );
98 mCurves.append(
c->clone() );
112 qDeleteAll( mCurves );
119 if ( mCurves.empty() )
125 for (
int i = 1; i < mCurves.size(); ++i )
151 for (
int i = 0; i <
nCurves; ++i )
154 wkbPtr -= 1 +
sizeof( int );
167 currentCurve->
fromWkb( wkbPtr );
168 mCurves.append( currentCurve );
183 QString secondWithoutParentheses =
parts.second;
184 secondWithoutParentheses = secondWithoutParentheses.remove(
'(' ).remove(
')' ).simplified().remove(
' ' );
185 if ( (
parts.second.compare( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
186 secondWithoutParentheses.isEmpty() )
189 QString defaultChildWkbType = QStringLiteral(
"LineString%1%2" ).arg(
is3D() ? QStringLiteral(
"Z" ) : QString(),
isMeasure() ? QStringLiteral(
"M" ) : QString() );
192 for (
const QString &childWkt : blocks )
205 if ( !mCurves.back()->fromWkt( childWkt ) )
216 for (
const QgsCurve *curve : qgis::as_const( mCurves ) )
218 hasZ = hasZ || curve->is3D();
219 hasM = hasM || curve->isMeasure();
233 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
234 for (
const QgsCurve *curve : mCurves )
236 binarySize += curve->wkbSize( flags );
247 wkb << static_cast<quint32>(
wkbType() );
248 wkb << static_cast<quint32>( mCurves.size() );
249 for (
const QgsCurve *curve : mCurves )
251 wkb << curve->asWkb( flags );
260 wkt += QLatin1String(
" EMPTY" );
263 wkt += QLatin1String(
" (" );
264 for (
const QgsCurve *curve : mCurves )
266 QString childWkt = curve->asWkt(
precision );
267 if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
270 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
272 wkt += childWkt +
',';
274 if ( wkt.endsWith(
',' ) )
286 std::unique_ptr< QgsLineString > line(
curveToLine() );
287 QDomElement gml = line->asGml2( doc,
precision, ns, axisOrder );
293 QDomElement compoundCurveElem = doc.createElementNS( ns, QStringLiteral(
"CompositeCurve" ) );
296 return compoundCurveElem;
298 for (
const QgsCurve *curve : mCurves )
300 QDomElement curveMemberElem = doc.createElementNS( ns, QStringLiteral(
"curveMember" ) );
301 QDomElement curveElem = curve->asGml3( doc,
precision, ns, axisOrder );
302 curveMemberElem.appendChild( curveElem );
303 compoundCurveElem.appendChild( curveMemberElem );
306 return compoundCurveElem;
312 std::unique_ptr< QgsLineString > line(
curveToLine() );
319 for (
const QgsCurve *curve : mCurves )
321 length += curve->length();
328 if ( mCurves.empty() )
332 return mCurves.at( 0 )->startPoint();
337 if ( mCurves.empty() )
341 return mCurves.at( mCurves.size() - 1 )->endPoint();
347 if ( mCurves.empty() )
352 mCurves[0]->points( pts );
353 for (
int i = 1; i < mCurves.size(); ++i )
356 mCurves[i]->points( pList );
371 for (
int i = 0; i <
nCurves; ++i )
373 nPoints += mCurves.at( i )->numPoints() - 1;
381 if ( mCurves.isEmpty() )
386 if ( !curve->isEmpty() )
394 if ( mCurves.isEmpty() )
397 for (
int i = 0; i < mCurves.size() ; ++i )
399 if ( !mCurves[i]->
isValid( error, flags ) )
401 error = QObject::tr(
"Curve[%1]: %2" ).arg( i + 1 ).arg( error );
411 std::unique_ptr< QgsLineString > currentLine;
412 for (
const QgsCurve *curve : mCurves )
414 currentLine.reset( curve->curveToLine( tolerance, toleranceType ) );
415 line->
append( currentLine.get() );
426 std::unique_ptr<QgsCurve> gridified(
static_cast< QgsCurve *
>( curve->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) );
429 result->mCurves.append( gridified.release() );
433 if ( result->mCurves.empty() )
436 return result.release();
442 const QVector< QgsCurve * > curves = mCurves;
448 if ( curve->numPoints() == 0 ||
qgsDoubleNear( curve->length(), 0.0, epsilon ) )
451 delete mCurves.takeAt( i );
459 curve->moveVertex(
QgsVertexId( -1, -1, 0 ), lastEnd );
470 if ( i < 0 || i >= mCurves.size() )
474 return mCurves.at( i );
481 if ( mCurves.empty() )
510 if ( i < 0 || i >= mCurves.size() )
515 delete mCurves.takeAt( i );
528 if ( !mCurves.isEmpty() )
530 lastCurve = mCurves.at( mCurves.size() - 1 );
537 mCurves.append( line );
554 for (
const QgsCurve *curve : mCurves )
562 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
564 curve->transform( ct, d, transformZ );
571 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
573 curve->transform( t, zTranslate, zScale, mTranslate, mScale );
581 for (
const QgsCurve *curve : mCurves )
583 curve->addToPainterPath( pp );
591 for (
const QgsCurve *curve : mCurves )
593 curve->addToPainterPath( pp );
600 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
601 if ( curveIds.empty() )
605 int curveId = curveIds.at( 0 ).first;
606 if ( curveId >= mCurves.size() )
611 bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
621 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
622 QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
623 for ( ; idIt != curveIds.constEnd(); ++idIt )
625 mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
628 bool success = !curveIds.isEmpty();
638 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
639 if ( curveIds.size() == 1 )
641 if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
646 if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 )
651 else if ( curveIds.size() == 2 )
653 Q_ASSERT( curveIds.at( 1 ).first == curveIds.at( 0 ).first + 1 );
654 Q_ASSERT( curveIds.at( 0 ).second.vertex == mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 );
655 Q_ASSERT( curveIds.at( 1 ).second.vertex == 0 );
660 mCurves.at( curveIds.at( 1 ).first )->numPoints() > 3 )
664 mCurves.at( curveIds.at( 1 ).first ) ->pointAt( 2, intermediatePoint, type );
665 mCurves.at( curveIds.at( 0 ).first )->moveVertex(
666 QgsVertexId( 0, 0, mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 ), intermediatePoint );
668 else if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
674 mCurves.at( curveIds.at( 0 ).first )->numPoints() > 0 &&
677 QgsPoint intermediatePoint = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
678 mCurves.at( curveIds.at( 1 ).first )->moveVertex(
QgsVertexId( 0, 0, 0 ), intermediatePoint );
680 else if ( !mCurves.at( curveIds.at( 1 ).first )->deleteVertex( curveIds.at( 1 ).second ) )
685 if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
686 mCurves.at( curveIds.at( 1 ).first )->numPoints() != 0 )
691 else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() != 0 &&
692 mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
694 mCurves.at( curveIds.at( 0 ).first )->moveVertex(
698 else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
699 mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
706 mCurves.insert( curveIds.at( 0 ).first, line );
710 QgsPoint endPointOfFirst = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
711 QgsPoint startPointOfSecond = mCurves.at( curveIds.at( 1 ).first ) ->startPoint();
712 if ( endPointOfFirst != startPointOfSecond )
717 mCurves.insert( curveIds.at( 1 ).first, line );
722 bool success = !curveIds.isEmpty();
730 QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId(
QgsVertexId id )
const
732 QVector< QPair<int, QgsVertexId> > curveIds;
734 int currentVertexIndex = 0;
735 for (
int i = 0; i < mCurves.size(); ++i )
737 int increment = mCurves.at( i )->numPoints() - 1;
738 if (
id.vertex >= currentVertexIndex &&
id.vertex <= currentVertexIndex + increment )
740 int curveVertexId =
id.vertex - currentVertexIndex;
744 vid.
vertex = curveVertexId;
745 curveIds.append( qMakePair( i, vid ) );
746 if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) )
749 curveIds.append( qMakePair( i + 1, vid ) );
753 else if (
id.vertex >= currentVertexIndex &&
id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
755 int curveVertexId =
id.vertex - currentVertexIndex;
759 vid.
vertex = curveVertexId;
760 curveIds.append( qMakePair( i, vid ) );
763 currentVertexIndex += increment;
776 int currentVertexId = 0;
777 for (
int j = 0; j < mCurves.size(); ++j )
779 int nCurvePoints = mCurves.at( j )->numPoints();
780 if ( ( node - currentVertexId ) < nCurvePoints )
782 return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
784 currentVertexId += ( nCurvePoints - 1 );
791 int currentVertexId = 0;
792 for (
int j = 0; j < mCurves.size(); ++j )
794 int nCurvePoints = mCurves.at( j )->numPoints();
795 if ( ( index - currentVertexId ) < nCurvePoints )
797 return mCurves.at( j )->xAt( index - currentVertexId );
799 currentVertexId += ( nCurvePoints - 1 );
806 int currentVertexId = 0;
807 for (
int j = 0; j < mCurves.size(); ++j )
809 int nCurvePoints = mCurves.at( j )->numPoints();
810 if ( ( index - currentVertexId ) < nCurvePoints )
812 return mCurves.at( j )->yAt( index - currentVertexId );
814 currentVertexId += ( nCurvePoints - 1 );
822 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
824 if ( !curve->transform( transformer ) )
842 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
844 curve->filterVertices( filter );
851 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
860 for (
const QgsCurve *curve : mCurves )
862 curve->sumUpArea( sum );
877 for (
const QgsCurve *curve : mCurves )
879 if ( curve->hasCurvedSegments() )
889 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
890 if ( curveIds.size() == 1 )
892 QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
893 return curve->
vertexAngle( curveIds.at( 0 ).second );
895 else if ( curveIds.size() > 1 )
897 QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
898 QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
899 double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
900 double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
911 QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
913 for (
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
915 length += mCurves.at( it->first )->segmentLength( it->second );
923 for (
int i = mCurves.count() - 1; i >= 0; --i )
925 QgsCurve *reversedCurve = mCurves.at( i )->reversed();
936 double distanceTraversed = 0;
937 for (
const QgsCurve *curve : mCurves )
939 const double thisCurveLength = curve->
length();
940 if ( distanceTraversed + thisCurveLength > distance ||
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
943 const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
946 return curve->interpolatePoint( distanceToPoint );
949 distanceTraversed += thisCurveLength;
957 if ( startDistance < 0 && endDistance < 0 )
960 endDistance = std::max( startDistance, endDistance );
961 std::unique_ptr< QgsCompoundCurve > substring = qgis::make_unique< QgsCompoundCurve >();
963 double distanceTraversed = 0;
964 for (
const QgsCurve *curve : mCurves )
966 const double thisCurveLength = curve->length();
967 if ( distanceTraversed + thisCurveLength < startDistance )
973 std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
975 substring->addCurve( part.release() );
978 distanceTraversed += thisCurveLength;
979 if ( distanceTraversed > endDistance )
983 return substring.release();
993 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
995 curve->addZValue( zValue );
1008 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
1010 curve->addMValue( mValue );
1022 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
1024 curve->dropZValue();
1036 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
1038 curve->dropMValue();
1046 for (
QgsCurve *curve : qgis::as_const( mCurves ) )
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.
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.
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.
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...
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 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.
bool isValid(QString &error, int flags=0) const override
Checks validity of the geometry, and returns true if the geometry is valid.
void addCurve(QgsCurve *c)
Adds a curve to the geometry (takes ownership)
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...
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.
bool pointAt(int node, QgsPoint &point, QgsVertexId::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
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.
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.
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *std::numeric_limits< double >::epsilon()) const override
Searches for the closest segment of the geometry to a given point.
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
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.
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.
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.
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
QgsPoint startPoint() const override SIP_HOLDGIL
Returns the starting point of the curve.
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 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.
QgsWkbTypes::Type readHeader() const
readHeader
Abstract base class for curved geometry type.
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, int flags=0) const override
Checks validity of the geometry, and returns true if the geometry is valid.
virtual QgsPoint endPoint() const =0
Returns the end point of the curve.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
static 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 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.
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.
VertexType
Type of vertex.