28 #include <QJsonObject> 30 #include <QPainterPath> 32 #include <nlohmann/json.hpp> 42 bool hasZ = p1.
is3D();
87 if ( mX.count() != otherLine->mX.count() )
90 for (
int i = 0; i < mX.count(); ++i )
108 auto result = qgis::make_unique< QgsCircularString >();
110 return result.release();
115 return QStringLiteral(
"CircularString" );
142 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
146 bbox = segmentBoundingBox(
QgsPoint( mX[i], mY[i] ),
QgsPoint( mX[i + 1], mY[i + 1] ),
QgsPoint( mX[i + 2], mY[i + 2] ) );
155 if ( nPoints > 0 && nPoints % 2 == 0 )
168 double centerX, centerY, radius;
179 QgsPointSequence compassPoints = compassPointsOnSegment( p1Angle, p2Angle, p3Angle, centerX, centerY, radius );
180 QgsPointSequence::const_iterator cpIt = compassPoints.constBegin();
181 for ( ; cpIt != compassPoints.constEnd(); ++cpIt )
183 bbox.combineExtentWith( cpIt->x(), cpIt->y() );
188 QgsPointSequence QgsCircularString::compassPointsOnSegment(
double p1Angle,
double p2Angle,
double p3Angle,
double centerX,
double centerY,
double radius )
192 QgsPoint nPoint( centerX, centerY + radius );
193 QgsPoint ePoint( centerX + radius, centerY );
194 QgsPoint sPoint( centerX, centerY - radius );
195 QgsPoint wPoint( centerX - radius, centerY );
197 if ( p3Angle >= p1Angle )
199 if ( p2Angle > p1Angle && p2Angle < p3Angle )
201 if ( p1Angle <= 90 && p3Angle >= 90 )
203 pointList.append( nPoint );
205 if ( p1Angle <= 180 && p3Angle >= 180 )
207 pointList.append( wPoint );
209 if ( p1Angle <= 270 && p3Angle >= 270 )
211 pointList.append( sPoint );
216 pointList.append( ePoint );
217 if ( p1Angle >= 90 || p3Angle <= 90 )
219 pointList.append( nPoint );
221 if ( p1Angle >= 180 || p3Angle <= 180 )
223 pointList.append( wPoint );
225 if ( p1Angle >= 270 || p3Angle <= 270 )
227 pointList.append( sPoint );
233 if ( p2Angle < p1Angle && p2Angle > p3Angle )
235 if ( p1Angle >= 270 && p3Angle <= 270 )
237 pointList.append( sPoint );
239 if ( p1Angle >= 180 && p3Angle <= 180 )
241 pointList.append( wPoint );
243 if ( p1Angle >= 90 && p3Angle <= 90 )
245 pointList.append( nPoint );
250 pointList.append( ePoint );
251 if ( p1Angle <= 270 || p3Angle >= 270 )
253 pointList.append( sPoint );
255 if ( p1Angle <= 180 || p3Angle >= 180 )
257 pointList.append( wPoint );
259 if ( p1Angle <= 90 || p3Angle >= 90 )
261 pointList.append( nPoint );
286 mX.resize( nVertices );
287 mY.resize( nVertices );
288 hasZ ? mZ.resize( nVertices ) : mZ.clear();
289 hasM ? mM.resize( nVertices ) : mM.clear();
290 for (
int i = 0; i < nVertices; ++i )
323 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
327 wkbArray.resize( binarySize );
330 wkb << static_cast<quint32>(
wkbType() );
349 std::unique_ptr< QgsLineString > line(
curveToLine() );
350 QDomElement gml = line->asGml2( doc, precision, ns, axisOrder );
359 QDomElement elemCurve = doc.createElementNS( ns, QStringLiteral(
"Curve" ) );
364 QDomElement elemSegments = doc.createElementNS( ns, QStringLiteral(
"segments" ) );
365 QDomElement elemArcString = doc.createElementNS( ns, QStringLiteral(
"ArcString" ) );
367 elemSegments.appendChild( elemArcString );
368 elemCurve.appendChild( elemSegments );
376 std::unique_ptr< QgsLineString > line(
curveToLine() );
377 return line->asJsonObject( precision );
390 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
421 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
435 bool res =
snapToGridPrivate( hSpacing, vSpacing, dSpacing, mSpacing, mX, mY, mZ, mM,
436 result->mX, result->mY, result->mZ, result->mM );
438 return result.release();
445 if ( mX.count() <= 3 )
448 double prevX = mX.at( 0 );
449 double prevY = mY.at( 0 );
451 bool useZ = hasZ && useZValues;
452 double prevZ = useZ ? mZ.at( 0 ) : 0;
454 int remaining = mX.count();
457 while ( i + 1 < remaining )
459 double currentCurveX = mX.at( i );
460 double currentCurveY = mY.at( i );
461 double currentX = mX.at( i + 1 );
462 double currentY = mY.at( i + 1 );
463 double currentZ = useZ ? mZ.at( i + 1 ) : 0;
496 return std::min( mX.size(), mY.size() );
501 if ( i < 0 || std::min( mX.size(), mY.size() ) <= i )
506 double x = mX.at( i );
507 double y = mY.at( i );
538 if ( index >= 0 && index < mX.size() )
539 return mX.at( index );
546 if ( index >= 0 && index < mY.size() )
547 return mY.at( index );
556 int size = mX.size();
558 double *srcX = mX.data();
559 double *srcY = mY.data();
560 double *srcM = hasM ? mM.data() :
nullptr;
561 double *srcZ = hasZ ? mZ.data() :
nullptr;
563 double *destX = srcX;
564 double *destY = srcY;
565 double *destM = srcM;
566 double *destZ = srcZ;
568 int filteredPoints = 0;
569 for (
int i = 0; i < size; ++i )
573 double z = hasZ ? *srcZ++ : std::numeric_limits<double>::quiet_NaN();
574 double m = hasM ? *srcM++ : std::numeric_limits<double>::quiet_NaN();
576 if ( filter(
QgsPoint( x, y, z, m ) ) )
588 mX.resize( filteredPoints );
589 mY.resize( filteredPoints );
591 mZ.resize( filteredPoints );
593 mM.resize( filteredPoints );
602 int size = mX.size();
604 double *srcX = mX.data();
605 double *srcY = mY.data();
606 double *srcM = hasM ? mM.data() :
nullptr;
607 double *srcZ = hasZ ? mZ.data() :
nullptr;
609 for (
int i = 0; i < size; ++i )
613 double z = hasZ ? *srcZ : std::numeric_limits<double>::quiet_NaN();
614 double m = hasM ? *srcM : std::numeric_limits<double>::quiet_NaN();
630 for (
int i = 0; i < nPts; ++i )
632 pts.push_back(
pointN( i ) );
640 if ( points.empty() )
651 const QgsPoint &firstPt = points.at( 0 );
652 bool hasZ = firstPt.
is3D();
657 mX.resize( points.size() );
658 mY.resize( points.size() );
661 mZ.resize( points.size() );
669 mM.resize( points.size() );
676 for (
int i = 0; i < points.size(); ++i )
678 mX[i] = points[i].x();
679 mY[i] = points[i].y();
682 double z = points.at( i ).z();
683 mZ[i] = std::isnan( z ) ? 0 : z;
687 double m = points.at( i ).m();
688 mM[i] = std::isnan( m ) ? 0 : m;
704 double *zArray = mZ.data();
708 bool useDummyZ = !hasZ || !transformZ;
711 zArray =
new double[nPoints];
712 for (
int i = 0; i < nPoints; ++i )
731 for (
int i = 0; i < nPoints; ++i )
734 t.map( mX.at( i ), mY.at( i ), &x, &y );
739 mZ[i] = mZ.at( i ) * zScale + zTranslate;
743 mM[i] = mM.at( i ) * mScale + mTranslate;
756 if ( path.isEmpty() || path.currentPosition() != QPointF( mX[0], mY[0] ) )
758 path.moveTo( QPointF( mX[0], mY[0] ) );
761 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
765 for (
int j = 1; j < pt.size(); ++j )
767 path.lineTo( pt.at( j ).x(), pt.at( j ).y() );
775 if ( nPoints % 2 == 0 )
777 path.lineTo( mX[ nPoints - 1 ], mY[ nPoints - 1 ] );
782 void QgsCircularString::arcTo( QPainterPath &path, QPointF pt1, QPointF pt2, QPointF pt3 )
784 double centerX, centerY, radius;
786 radius, centerX, centerY );
791 double diameter = 2 * radius;
792 path.arcTo( centerX - radius, centerY - radius, diameter, diameter, p1Angle, sweepAngle );
803 if ( position.
vertex >= mX.size() || position.
vertex < 1 )
808 mX.insert( position.
vertex, vertex.
x() );
809 mY.insert( position.
vertex, vertex.
y() );
812 mZ.insert( position.
vertex, vertex.
z() );
816 mM.insert( position.
vertex, vertex.
m() );
819 bool vertexNrEven = ( position.
vertex % 2 == 0 );
834 if ( position.
vertex < 0 || position.
vertex >= mX.size() )
839 mX[position.
vertex] = newPos.
x();
840 mY[position.
vertex] = newPos.
y();
843 mZ[position.
vertex] = newPos.
z();
847 mM[position.
vertex] = newPos.
m();
861 if ( position.
vertex < 0 || position.
vertex > ( nVertices - 1 ) )
866 if ( position.
vertex < ( nVertices - 2 ) )
899 double minDist = std::numeric_limits<double>::max();
902 int minDistLeftOf = 0;
904 double currentDist = 0.0;
907 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
909 currentDist = closestPointOnArc( mX[i], mY[i], mX[i + 1], mY[i + 1], mX[i + 2], mY[i + 2], pt, segmentPt, vertexAfter, leftOf, epsilon );
910 if ( currentDist < minDist )
912 minDist = currentDist;
913 minDistSegmentPoint = segmentPt;
922 if ( minDist == std::numeric_limits<double>::max() )
925 segmentPt = minDistSegmentPoint;
926 vertexAfter = minDistVertexAfter;
927 vertexAfter.
part = 0;
928 vertexAfter.
ring = 0;
951 for (
int i = 0; i < maxIndex; i += 2 )
954 QgsPoint p2( mX[i + 1], mY[i + 1] );
955 QgsPoint p3( mX[i + 2], mY[i + 2] );
965 sum += 0.5 * ( mX[i] * mY[i + 2] - mY[i] * mX[i + 2] );
968 double midPointX = ( p1.
x() + p3.
x() ) / 2.0;
969 double midPointY = ( p1.
y() + p3.
y() ) / 2.0;
971 double radius, centerX, centerY;
975 double r2 = radius * radius;
986 double cov = 0.5 - d * std::sqrt( r2 - d * d ) / ( M_PI * r2 ) - M_1_PI * std::asin( d / radius );
987 double circleChordArea = 0;
988 if ( circlePointLeftOfLine == centerPointLeftOfLine )
990 circleChordArea = M_PI * r2 * ( 1 - cov );
994 circleChordArea = M_PI * r2 * cov;
997 if ( !circlePointLeftOfLine )
999 sum += circleChordArea;
1003 sum -= circleChordArea;
1013 double QgsCircularString::closestPointOnArc(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
1016 double radius, centerX, centerY;
1041 segmentPt = ( distPtPt1 <= distPtPt3 ) ? pt1 : pt3;
1042 vertexAfter.
vertex = ( distPtPt1 <= distPtPt3 ) ? 1 : 2;
1049 segmentPt.
setX( pt.
x() );
1050 segmentPt.
setY( pt.
y() );
1056 double sqrDistancePointToCenter = ( pt.
x() - centerX ) * ( pt.
x() - centerX ) + ( pt.
y() - centerY ) * ( pt.
y() - centerY );
1057 *leftOf = clockwise ? ( sqrDistancePointToCenter > radius * radius ? -1 : 1 )
1058 : ( sqrDistancePointToCenter < radius * radius ? -1 : 1 );
1064 void QgsCircularString::insertVertexBetween(
int after,
int before,
int pointOnCircle )
1066 double xAfter = mX.at( after );
1067 double yAfter = mY.at( after );
1068 double xBefore = mX.at( before );
1069 double yBefore = mY.at( before );
1070 double xOnCircle = mX.at( pointOnCircle );
1071 double yOnCircle = mY.at( pointOnCircle );
1073 double radius, centerX, centerY;
1076 double x = ( xAfter + xBefore ) / 2.0;
1077 double y = ( yAfter + yBefore ) / 2.0;
1080 mX.insert( before, newVertex.
x() );
1081 mY.insert( before, newVertex.
y() );
1085 mZ.insert( before, ( mZ[after] + mZ[before] ) / 2.0 );
1089 mM.insert( before, ( mM[after] + mM[before] ) / 2.0 );
1102 int before = vId.
vertex - 1;
1104 int after = vId.
vertex + 1;
1106 if ( vId.
vertex % 2 != 0 )
1136 int vertex1 = vId.
vertex - 2;
1137 int vertex2 = vId.
vertex - 1;
1138 int vertex3 = vId.
vertex;
1140 QgsPoint( mX[vertex1], mY[vertex1] ),
QgsPoint( mX[vertex2], mY[vertex2] ),
QgsPoint( mX[vertex3], mY[vertex3] ) );
1141 int vertex4 = vId.
vertex + 1;
1142 int vertex5 = vId.
vertex + 2;
1144 QgsPoint( mX[vertex3], mY[vertex3] ),
QgsPoint( mX[vertex4], mY[vertex4] ),
QgsPoint( mX[vertex5], mY[vertex5] ) );
1153 if ( startVertex.
vertex < 0 || startVertex.
vertex >= mX.count() - 2 )
1156 if ( startVertex.
vertex % 2 == 1 )
1159 double x1 = mX.at( startVertex.
vertex );
1160 double y1 = mY.at( startVertex.
vertex );
1161 double x2 = mX.at( startVertex.
vertex + 1 );
1162 double y2 = mY.at( startVertex.
vertex + 1 );
1163 double x3 = mX.at( startVertex.
vertex + 2 );
1164 double y3 = mY.at( startVertex.
vertex + 2 );
1171 std::reverse( copy->mX.begin(), copy->mX.end() );
1172 std::reverse( copy->mY.begin(), copy->mY.end() );
1175 std::reverse( copy->mZ.begin(), copy->mZ.end() );
1179 std::reverse( copy->mM.begin(), copy->mM.end() );
1189 double distanceTraversed = 0;
1191 if ( totalPoints == 0 )
1200 const double *x = mX.constData();
1201 const double *y = mY.constData();
1202 const double *z =
is3D() ? mZ.constData() :
nullptr;
1203 const double *m =
isMeasure() ? mM.constData() :
nullptr;
1205 double prevX = *x++;
1206 double prevY = *y++;
1207 double prevZ = z ? *z++ : 0.0;
1208 double prevM = m ? *m++ : 0.0;
1212 return new QgsPoint( pointType, prevX, prevY, prevZ, prevM );
1215 for (
int i = 0; i < ( totalPoints - 2 ) ; i += 2 )
1224 double z2 = z ? *z++ : 0.0;
1225 double m2 = m ? *m++ : 0.0;
1229 double z3 = z ? *z++ : 0.0;
1230 double m3 = m ? *m++ : 0.0;
1233 if ( distance < distanceTraversed + segmentLength ||
qgsDoubleNear( distance, distanceTraversed + segmentLength ) )
1236 const double distanceToPoint = std::min( distance - distanceTraversed, segmentLength );
1238 QgsPoint( pointType, x2, y2, z2, m2 ),
1239 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToPoint ) );
1255 if ( startDistance < 0 && endDistance < 0 )
1258 endDistance = std::max( startDistance, endDistance );
1260 double distanceTraversed = 0;
1262 if ( totalPoints == 0 )
1265 QVector< QgsPoint > substringPoints;
1273 const double *x = mX.constData();
1274 const double *y = mY.constData();
1275 const double *z =
is3D() ? mZ.constData() :
nullptr;
1276 const double *m =
isMeasure() ? mM.constData() :
nullptr;
1278 double prevX = *x++;
1279 double prevY = *y++;
1280 double prevZ = z ? *z++ : 0.0;
1281 double prevM = m ? *m++ : 0.0;
1282 bool foundStart =
false;
1284 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
1286 substringPoints <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM );
1290 substringPoints.reserve( totalPoints );
1292 for (
int i = 0; i < ( totalPoints - 2 ) ; i += 2 )
1301 double z2 = z ? *z++ : 0.0;
1302 double m2 = m ? *m++ : 0.0;
1306 double z3 = z ? *z++ : 0.0;
1307 double m3 = m ? *m++ : 0.0;
1309 bool addedSegmentEnd =
false;
1311 if ( distanceTraversed < startDistance && distanceTraversed + segmentLength > startDistance )
1314 const double distanceToStart = startDistance - distanceTraversed;
1316 QgsPoint( pointType, x2, y2, z2, m2 ),
1317 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToStart );
1320 const bool endPointOnSegment = distanceTraversed + segmentLength > endDistance;
1321 if ( endPointOnSegment )
1323 const double distanceToEnd = endDistance - distanceTraversed;
1324 const double midPointDistance = ( distanceToEnd - distanceToStart ) * 0.5 + distanceToStart;
1325 substringPoints << startPoint
1327 QgsPoint( pointType, x2, y2, z2, m2 ),
1328 QgsPoint( pointType, x3, y3, z3, m3 ), midPointDistance )
1330 QgsPoint( pointType, x2, y2, z2, m2 ),
1331 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd );
1332 addedSegmentEnd =
true;
1336 const double midPointDistance = ( segmentLength - distanceToStart ) * 0.5 + distanceToStart;
1337 substringPoints << startPoint
1339 QgsPoint( pointType, x2, y2, z2, m2 ),
1340 QgsPoint( pointType, x3, y3, z3, m3 ), midPointDistance )
1341 <<
QgsPoint( pointType, x3, y3, z3, m3 );
1342 addedSegmentEnd =
true;
1346 if ( !addedSegmentEnd && foundStart && ( distanceTraversed + segmentLength > endDistance ) )
1349 const double distanceToEnd = endDistance - distanceTraversed;
1352 QgsPoint( pointType, x2, y2, z2, m2 ),
1353 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd / 2.0 )
1356 QgsPoint( pointType, x2, y2, z2, m2 ),
1357 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd );
1359 else if ( !addedSegmentEnd && foundStart )
1361 substringPoints <<
QgsPoint( pointType, x2, y2, z2, m2 )
1362 <<
QgsPoint( pointType, x3, y3, z3, m3 );
1366 if ( distanceTraversed > endDistance )
1375 std::unique_ptr< QgsCircularString > result = qgis::make_unique< QgsCircularString >();
1376 result->setPoints( substringPoints );
1377 return result.release();
1390 mZ.reserve( nPoints );
1391 for (
int i = 0; i < nPoints; ++i )
1408 mM.reserve( nPoints );
1409 for (
int i = 0; i < nPoints; ++i )
1442 std::swap( mX, mY );
bool isMeasure() const
Returns true if the geometry contains m values.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
A rectangle specified with double values.
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 setPoints(const QgsPointSequence &points)
Resets the line string to match the specified list of points.
int numPoints() const override
Returns the number of points in the curve.
static bool circleAngleBetween(double angle, double angle1, double angle2, bool clockwise)
Returns true if, in a circle, angle is between angle1 and angle2.
static double ccwAngle(double dy, double dx)
Returns the counter clockwise angle between a line with components dx, dy and the line with dx > 0 an...
QgsCircularString()
Constructs an empty circular string.
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 (...
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
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).
bool pointAt(int node, QgsPoint &point, QgsVertexId::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
static QgsPoint segmentMidPointFromCenter(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint ¢er, bool useShortestArc=true)
Calculates the midpoint on the circle passing through p1 and p2, with the specified center coordinate...
static QDomElement pointsToGML3(const QgsPointSequence &points, QDomDocument &doc, int precision, const QString &ns, bool is3D, QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY)
Returns a gml::posList DOM element.
QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
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.
static double circleLength(double x1, double y1, double x2, double y2, double x3, double y3)
Length of a circular string segment defined by pt1, pt2, pt3.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle...
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
static endian_t endian()
Returns whether this machine uses big or little endian.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
QgsPoint pointN(int i) const
Returns the point at index i within the circular string.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
static Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
QgsWkbTypes::Type mWkbType
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
void points(QgsPointSequence &pts) const override
Returns a list of points within the curve.
void clear() override
Clears the geometry, ie reset it to a null geometry.
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
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
QString wktTypeStr() const
Returns the WKT type string of the geometry.
static bool circleClockwise(double angle1, double angle2, double angle3)
Returns true if the circle defined by three angles is ordered clockwise.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
bool equals(const QgsCurve &other) const override
Checks whether this curve exactly equals another curve.
static QString pointsToWKT(const QgsPointSequence &points, int precision, bool is3D, bool isMeasure)
Returns a WKT coordinate list.
QgsCircularString * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership...
Type
The WKB type describes the number of dimensions a geometry has.
static int leftOfLine(const double x, const double y, const double x1, const double y1, const double x2, const double y2)
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> ( x2, y2).
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
Utility class for identifying a unique vertex within a geometry.
QString geometryType() const override
Returns a unique string representing the geometry type.
double length() const override
Returns the length of the geometry.
QgsPoint * interpolatePoint(double distance) const override
Returns an interpolated point on the curve at the specified distance.
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.
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.
static double circleTangentDirection(const QgsPoint &tangentPoint, const QgsPoint &cp1, const QgsPoint &cp2, const QgsPoint &cp3)
Calculates the direction angle of a circle tangent (clockwise from north in radians) ...
QgsCircularString * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
static bool angleOnCircle(double angle, double angle1, double angle2, double angle3)
Returns true if an angle is between angle1 and angle3 on a circle described by angle1, angle2 and angle3.
Abstract base class for curved geometry type.
int dimension() const override
Returns the inherent dimension of the geometry.
void sumUpArea(double &sum) const override
Sums up the area of the curve by iterating over the vertices (shoelace formula).
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Point geometry type, with support for z-dimension and m-values.
QgsPoint endPoint() const override
Returns the end point of the curve.
AxisOrder
Axis order for GML generation.
static QgsCircularString fromTwoPointsAndCenter(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint ¢er, bool useShortestArc=true)
Creates a circular string with a single arc representing the curve from p1 to p2 with the specified c...
void setX(double x)
Sets the point's x-coordinate.
bool snapToGridPrivate(double hSpacing, double vSpacing, double dSpacing, double mSpacing, const QVector< double > &srcX, const QVector< double > &srcY, const QVector< double > &srcZ, const QVector< double > &srcM, QVector< double > &outX, QVector< double > &outY, QVector< double > &outZ, QVector< double > &outM) const
Helper function for QgsCurve subclasses to snap to grids.
void setY(double y)
Sets the point's y-coordinate.
QVector< QgsPoint > QgsPointSequence
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance)
Returns a point a specified distance toward a second point.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
static double sqrDistance2D(const QgsPoint &pt1, const QgsPoint &pt2)
Returns the squared 2D distance between two points.
static Type dropZ(Type type)
Drops the z dimension (if present) for a WKB type and returns the new type.
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
static double sweepAngle(double centerX, double centerY, double x1, double y1, double x2, double y2, double x3, double y3)
Calculates angle of a circular string part defined by pt1, pt2, pt3.
static QgsPointSequence pointsFromWKT(const QString &wktCoordinateList, bool is3D, bool isMeasure)
Returns a list of points contained in a WKT string.
QgsCircularString * clone() const override
Clones the geometry by performing a deep copy.
Line string geometry type, with support for z-dimension and m-values.
static QgsPoint interpolatePointOnArc(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double distance)
Interpolates a point on an arc defined by three points, pt1, pt2 and pt3.
QgsCircularString * 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 setPoints(const QgsPointSequence &points)
Sets the circular string's points.
QByteArray asWkb() const override
Returns a WKB representation of the geometry.
static void circleCenterRadius(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double &radius, double ¢erX, double ¢erY)
Returns radius and center of the circle through pt1, pt2, pt3.
static void pointsToWKB(QgsWkbPtr &wkb, const QgsPointSequence &points, bool is3D, bool isMeasure)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Circular string geometry 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 transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
QgsCircularString * curveSubstring(double startDistance, double endDistance) const override
Returns a new curve representing a substring of this curve.
void swapXy() override
Swaps the x and y coordinates from the geometry.
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
void addToPainterPath(QPainterPath &path) const override
Adds a curve to a painter path.
static Type flatType(Type type)
Returns the flat type for a WKB type.
QgsWkbTypes::Type readHeader() const
readHeader
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...
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...
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
bool isEmpty() const override
Returns true if the geometry is empty.
QgsPoint startPoint() const override
Returns the starting point of the curve.
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.
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 dropMValue() override
Drops any measure values which exist in the geometry.
static void segmentizeArc(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, QgsPointSequence &points, double tolerance=M_PI_2/90, QgsAbstractGeometry::SegmentationToleranceType toleranceType=QgsAbstractGeometry::MaximumAngle, bool hasZ=false, bool hasM=false)
Convert circular arc defined by p1, p2, p3 (p1/p3 being start resp.