28 #include <QPainterPath> 39 bool hasZ = p1.
is3D();
84 if ( mX.count() != otherLine->mX.count() )
87 for (
int i = 0; i < mX.count(); ++i )
105 auto result = qgis::make_unique< QgsCircularString >();
107 return result.release();
112 return QStringLiteral(
"CircularString" );
139 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
143 bbox = segmentBoundingBox(
QgsPoint( mX[i], mY[i] ),
QgsPoint( mX[i + 1], mY[i + 1] ),
QgsPoint( mX[i + 2], mY[i + 2] ) );
152 if ( nPoints > 0 && nPoints % 2 == 0 )
165 double centerX, centerY, radius;
176 QgsPointSequence compassPoints = compassPointsOnSegment( p1Angle, p2Angle, p3Angle, centerX, centerY, radius );
177 QgsPointSequence::const_iterator cpIt = compassPoints.constBegin();
178 for ( ; cpIt != compassPoints.constEnd(); ++cpIt )
180 bbox.combineExtentWith( cpIt->x(), cpIt->y() );
185 QgsPointSequence QgsCircularString::compassPointsOnSegment(
double p1Angle,
double p2Angle,
double p3Angle,
double centerX,
double centerY,
double radius )
189 QgsPoint nPoint( centerX, centerY + radius );
190 QgsPoint ePoint( centerX + radius, centerY );
191 QgsPoint sPoint( centerX, centerY - radius );
192 QgsPoint wPoint( centerX - radius, centerY );
194 if ( p3Angle >= p1Angle )
196 if ( p2Angle > p1Angle && p2Angle < p3Angle )
198 if ( p1Angle <= 90 && p3Angle >= 90 )
200 pointList.append( nPoint );
202 if ( p1Angle <= 180 && p3Angle >= 180 )
204 pointList.append( wPoint );
206 if ( p1Angle <= 270 && p3Angle >= 270 )
208 pointList.append( sPoint );
213 pointList.append( ePoint );
214 if ( p1Angle >= 90 || p3Angle <= 90 )
216 pointList.append( nPoint );
218 if ( p1Angle >= 180 || p3Angle <= 180 )
220 pointList.append( wPoint );
222 if ( p1Angle >= 270 || p3Angle <= 270 )
224 pointList.append( sPoint );
230 if ( p2Angle < p1Angle && p2Angle > p3Angle )
232 if ( p1Angle >= 270 && p3Angle <= 270 )
234 pointList.append( sPoint );
236 if ( p1Angle >= 180 && p3Angle <= 180 )
238 pointList.append( wPoint );
240 if ( p1Angle >= 90 && p3Angle <= 90 )
242 pointList.append( nPoint );
247 pointList.append( ePoint );
248 if ( p1Angle <= 270 || p3Angle >= 270 )
250 pointList.append( sPoint );
252 if ( p1Angle <= 180 || p3Angle >= 180 )
254 pointList.append( wPoint );
256 if ( p1Angle <= 90 || p3Angle >= 90 )
258 pointList.append( nPoint );
283 mX.resize( nVertices );
284 mY.resize( nVertices );
285 hasZ ? mZ.resize( nVertices ) : mZ.clear();
286 hasM ? mM.resize( nVertices ) : mM.clear();
287 for (
int i = 0; i < nVertices; ++i )
320 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
324 wkbArray.resize( binarySize );
327 wkb << static_cast<quint32>(
wkbType() );
346 std::unique_ptr< QgsLineString > line(
curveToLine() );
347 QDomElement gml = line->asGml2( doc, precision, ns, axisOrder );
356 QDomElement elemCurve = doc.createElementNS( ns, QStringLiteral(
"Curve" ) );
361 QDomElement elemSegments = doc.createElementNS( ns, QStringLiteral(
"segments" ) );
362 QDomElement elemArcString = doc.createElementNS( ns, QStringLiteral(
"ArcString" ) );
364 elemSegments.appendChild( elemArcString );
365 elemCurve.appendChild( elemSegments );
372 std::unique_ptr< QgsLineString > line(
curveToLine() );
373 QString json = line->asJson( precision );
387 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
418 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
432 bool res =
snapToGridPrivate( hSpacing, vSpacing, dSpacing, mSpacing, mX, mY, mZ, mM,
433 result->mX, result->mY, result->mZ, result->mM );
435 return result.release();
442 if ( mX.count() <= 3 )
445 double prevX = mX.at( 0 );
446 double prevY = mY.at( 0 );
448 bool useZ = hasZ && useZValues;
449 double prevZ = useZ ? mZ.at( 0 ) : 0;
451 int remaining = mX.count();
454 while ( i + 1 < remaining )
456 double currentCurveX = mX.at( i );
457 double currentCurveY = mY.at( i );
458 double currentX = mX.at( i + 1 );
459 double currentY = mY.at( i + 1 );
460 double currentZ = useZ ? mZ.at( i + 1 ) : 0;
493 return std::min( mX.size(), mY.size() );
498 if ( i < 0 || std::min( mX.size(), mY.size() ) <= i )
503 double x = mX.at( i );
504 double y = mY.at( i );
535 if ( index >= 0 && index < mX.size() )
536 return mX.at( index );
543 if ( index >= 0 && index < mY.size() )
544 return mY.at( index );
553 int size = mX.size();
555 double *srcX = mX.data();
556 double *srcY = mY.data();
557 double *srcM = hasM ? mM.data() :
nullptr;
558 double *srcZ = hasZ ? mZ.data() :
nullptr;
560 double *destX = srcX;
561 double *destY = srcY;
562 double *destM = srcM;
563 double *destZ = srcZ;
565 int filteredPoints = 0;
566 for (
int i = 0; i < size; ++i )
570 double z = hasZ ? *srcZ++ : std::numeric_limits<double>::quiet_NaN();
571 double m = hasM ? *srcM++ : std::numeric_limits<double>::quiet_NaN();
573 if ( filter(
QgsPoint( x, y, z, m ) ) )
585 mX.resize( filteredPoints );
586 mY.resize( filteredPoints );
588 mZ.resize( filteredPoints );
590 mM.resize( filteredPoints );
599 int size = mX.size();
601 double *srcX = mX.data();
602 double *srcY = mY.data();
603 double *srcM = hasM ? mM.data() :
nullptr;
604 double *srcZ = hasZ ? mZ.data() :
nullptr;
606 for (
int i = 0; i < size; ++i )
610 double z = hasZ ? *srcZ : std::numeric_limits<double>::quiet_NaN();
611 double m = hasM ? *srcM : std::numeric_limits<double>::quiet_NaN();
627 for (
int i = 0; i < nPts; ++i )
629 pts.push_back(
pointN( i ) );
637 if ( points.empty() )
648 const QgsPoint &firstPt = points.at( 0 );
649 bool hasZ = firstPt.
is3D();
654 mX.resize( points.size() );
655 mY.resize( points.size() );
658 mZ.resize( points.size() );
666 mM.resize( points.size() );
673 for (
int i = 0; i < points.size(); ++i )
675 mX[i] = points[i].x();
676 mY[i] = points[i].y();
679 double z = points.at( i ).z();
680 mZ[i] = std::isnan( z ) ? 0 : z;
684 double m = points.at( i ).m();
685 mM[i] = std::isnan( m ) ? 0 : m;
701 double *zArray = mZ.data();
705 bool useDummyZ = !hasZ || !transformZ;
708 zArray =
new double[nPoints];
709 for (
int i = 0; i < nPoints; ++i )
728 for (
int i = 0; i < nPoints; ++i )
731 t.map( mX.at( i ), mY.at( i ), &x, &y );
736 mZ[i] = mZ.at( i ) * zScale + zTranslate;
740 mM[i] = mM.at( i ) * mScale + mTranslate;
753 if ( path.isEmpty() || path.currentPosition() != QPointF( mX[0], mY[0] ) )
755 path.moveTo( QPointF( mX[0], mY[0] ) );
758 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
762 for (
int j = 1; j < pt.size(); ++j )
764 path.lineTo( pt.at( j ).x(), pt.at( j ).y() );
772 if ( nPoints % 2 == 0 )
774 path.lineTo( mX[ nPoints - 1 ], mY[ nPoints - 1 ] );
779 void QgsCircularString::arcTo( QPainterPath &path, QPointF pt1, QPointF pt2, QPointF pt3 )
781 double centerX, centerY, radius;
783 radius, centerX, centerY );
788 double diameter = 2 * radius;
789 path.arcTo( centerX - radius, centerY - radius, diameter, diameter, p1Angle, sweepAngle );
800 if ( position.
vertex >= mX.size() || position.
vertex < 1 )
805 mX.insert( position.
vertex, vertex.
x() );
806 mY.insert( position.
vertex, vertex.
y() );
809 mZ.insert( position.
vertex, vertex.
z() );
813 mM.insert( position.
vertex, vertex.
m() );
816 bool vertexNrEven = ( position.
vertex % 2 == 0 );
831 if ( position.
vertex < 0 || position.
vertex >= mX.size() )
836 mX[position.
vertex] = newPos.
x();
837 mY[position.
vertex] = newPos.
y();
840 mZ[position.
vertex] = newPos.
z();
844 mM[position.
vertex] = newPos.
m();
858 if ( position.
vertex < 0 || position.
vertex > ( nVertices - 1 ) )
863 if ( position.
vertex < ( nVertices - 2 ) )
896 double minDist = std::numeric_limits<double>::max();
899 int minDistLeftOf = 0;
901 double currentDist = 0.0;
904 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
906 currentDist = closestPointOnArc( mX[i], mY[i], mX[i + 1], mY[i + 1], mX[i + 2], mY[i + 2], pt, segmentPt, vertexAfter, leftOf, epsilon );
907 if ( currentDist < minDist )
909 minDist = currentDist;
910 minDistSegmentPoint = segmentPt;
919 if ( minDist == std::numeric_limits<double>::max() )
922 segmentPt = minDistSegmentPoint;
923 vertexAfter = minDistVertexAfter;
924 vertexAfter.
part = 0;
925 vertexAfter.
ring = 0;
948 for (
int i = 0; i < maxIndex; i += 2 )
951 QgsPoint p2( mX[i + 1], mY[i + 1] );
952 QgsPoint p3( mX[i + 2], mY[i + 2] );
962 sum += 0.5 * ( mX[i] * mY[i + 2] - mY[i] * mX[i + 2] );
965 double midPointX = ( p1.
x() + p3.
x() ) / 2.0;
966 double midPointY = ( p1.
y() + p3.
y() ) / 2.0;
968 double radius, centerX, centerY;
972 double r2 = radius * radius;
983 double cov = 0.5 - d * std::sqrt( r2 - d * d ) / ( M_PI * r2 ) - M_1_PI * std::asin( d / radius );
984 double circleChordArea = 0;
985 if ( circlePointLeftOfLine == centerPointLeftOfLine )
987 circleChordArea = M_PI * r2 * ( 1 - cov );
991 circleChordArea = M_PI * r2 * cov;
994 if ( !circlePointLeftOfLine )
996 sum += circleChordArea;
1000 sum -= circleChordArea;
1010 double QgsCircularString::closestPointOnArc(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
1013 double radius, centerX, centerY;
1038 segmentPt = ( distPtPt1 <= distPtPt3 ) ? pt1 : pt3;
1039 vertexAfter.
vertex = ( distPtPt1 <= distPtPt3 ) ? 1 : 2;
1046 segmentPt.
setX( pt.
x() );
1047 segmentPt.
setY( pt.
y() );
1053 double sqrDistancePointToCenter = ( pt.
x() - centerX ) * ( pt.
x() - centerX ) + ( pt.
y() - centerY ) * ( pt.
y() - centerY );
1054 *leftOf = clockwise ? ( sqrDistancePointToCenter > radius * radius ? -1 : 1 )
1055 : ( sqrDistancePointToCenter < radius * radius ? -1 : 1 );
1061 void QgsCircularString::insertVertexBetween(
int after,
int before,
int pointOnCircle )
1063 double xAfter = mX.at( after );
1064 double yAfter = mY.at( after );
1065 double xBefore = mX.at( before );
1066 double yBefore = mY.at( before );
1067 double xOnCircle = mX.at( pointOnCircle );
1068 double yOnCircle = mY.at( pointOnCircle );
1070 double radius, centerX, centerY;
1073 double x = ( xAfter + xBefore ) / 2.0;
1074 double y = ( yAfter + yBefore ) / 2.0;
1077 mX.insert( before, newVertex.
x() );
1078 mY.insert( before, newVertex.
y() );
1082 mZ.insert( before, ( mZ[after] + mZ[before] ) / 2.0 );
1086 mM.insert( before, ( mM[after] + mM[before] ) / 2.0 );
1099 int before = vId.
vertex - 1;
1101 int after = vId.
vertex + 1;
1103 if ( vId.
vertex % 2 != 0 )
1133 int vertex1 = vId.
vertex - 2;
1134 int vertex2 = vId.
vertex - 1;
1135 int vertex3 = vId.
vertex;
1137 QgsPoint( mX[vertex1], mY[vertex1] ),
QgsPoint( mX[vertex2], mY[vertex2] ),
QgsPoint( mX[vertex3], mY[vertex3] ) );
1138 int vertex4 = vId.
vertex + 1;
1139 int vertex5 = vId.
vertex + 2;
1141 QgsPoint( mX[vertex3], mY[vertex3] ),
QgsPoint( mX[vertex4], mY[vertex4] ),
QgsPoint( mX[vertex5], mY[vertex5] ) );
1150 if ( startVertex.
vertex < 0 || startVertex.
vertex >= mX.count() - 2 )
1153 if ( startVertex.
vertex % 2 == 1 )
1156 double x1 = mX.at( startVertex.
vertex );
1157 double y1 = mY.at( startVertex.
vertex );
1158 double x2 = mX.at( startVertex.
vertex + 1 );
1159 double y2 = mY.at( startVertex.
vertex + 1 );
1160 double x3 = mX.at( startVertex.
vertex + 2 );
1161 double y3 = mY.at( startVertex.
vertex + 2 );
1168 std::reverse( copy->mX.begin(), copy->mX.end() );
1169 std::reverse( copy->mY.begin(), copy->mY.end() );
1172 std::reverse( copy->mZ.begin(), copy->mZ.end() );
1176 std::reverse( copy->mM.begin(), copy->mM.end() );
1186 double distanceTraversed = 0;
1188 if ( totalPoints == 0 )
1197 const double *x = mX.constData();
1198 const double *y = mY.constData();
1199 const double *z =
is3D() ? mZ.constData() :
nullptr;
1200 const double *m =
isMeasure() ? mM.constData() :
nullptr;
1202 double prevX = *x++;
1203 double prevY = *y++;
1204 double prevZ = z ? *z++ : 0.0;
1205 double prevM = m ? *m++ : 0.0;
1209 return new QgsPoint( pointType, prevX, prevY, prevZ, prevM );
1212 for (
int i = 0; i < ( totalPoints - 2 ) ; i += 2 )
1221 double z2 = z ? *z++ : 0.0;
1222 double m2 = m ? *m++ : 0.0;
1226 double z3 = z ? *z++ : 0.0;
1227 double m3 = m ? *m++ : 0.0;
1230 if ( distance < distanceTraversed + segmentLength ||
qgsDoubleNear( distance, distanceTraversed + segmentLength ) )
1233 const double distanceToPoint = std::min( distance - distanceTraversed, segmentLength );
1235 QgsPoint( pointType, x2, y2, z2, m2 ),
1236 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToPoint ) );
1252 if ( startDistance < 0 && endDistance < 0 )
1255 endDistance = std::max( startDistance, endDistance );
1257 double distanceTraversed = 0;
1259 if ( totalPoints == 0 )
1262 QVector< QgsPoint > substringPoints;
1270 const double *x = mX.constData();
1271 const double *y = mY.constData();
1272 const double *z =
is3D() ? mZ.constData() :
nullptr;
1273 const double *m =
isMeasure() ? mM.constData() :
nullptr;
1275 double prevX = *x++;
1276 double prevY = *y++;
1277 double prevZ = z ? *z++ : 0.0;
1278 double prevM = m ? *m++ : 0.0;
1279 bool foundStart =
false;
1281 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
1283 substringPoints <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM );
1287 substringPoints.reserve( totalPoints );
1289 for (
int i = 0; i < ( totalPoints - 2 ) ; i += 2 )
1298 double z2 = z ? *z++ : 0.0;
1299 double m2 = m ? *m++ : 0.0;
1303 double z3 = z ? *z++ : 0.0;
1304 double m3 = m ? *m++ : 0.0;
1306 bool addedSegmentEnd =
false;
1308 if ( distanceTraversed < startDistance && distanceTraversed + segmentLength > startDistance )
1311 const double distanceToStart = startDistance - distanceTraversed;
1313 QgsPoint( pointType, x2, y2, z2, m2 ),
1314 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToStart );
1317 const bool endPointOnSegment = distanceTraversed + segmentLength > endDistance;
1318 if ( endPointOnSegment )
1320 const double distanceToEnd = endDistance - distanceTraversed;
1321 const double midPointDistance = ( distanceToEnd - distanceToStart ) * 0.5 + distanceToStart;
1322 substringPoints << startPoint
1324 QgsPoint( pointType, x2, y2, z2, m2 ),
1325 QgsPoint( pointType, x3, y3, z3, m3 ), midPointDistance )
1327 QgsPoint( pointType, x2, y2, z2, m2 ),
1328 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd );
1329 addedSegmentEnd =
true;
1333 const double midPointDistance = ( segmentLength - distanceToStart ) * 0.5 + distanceToStart;
1334 substringPoints << startPoint
1336 QgsPoint( pointType, x2, y2, z2, m2 ),
1337 QgsPoint( pointType, x3, y3, z3, m3 ), midPointDistance )
1338 <<
QgsPoint( pointType, x3, y3, z3, m3 );
1339 addedSegmentEnd =
true;
1343 if ( !addedSegmentEnd && foundStart && ( distanceTraversed + segmentLength > endDistance ) )
1346 const double distanceToEnd = endDistance - distanceTraversed;
1349 QgsPoint( pointType, x2, y2, z2, m2 ),
1350 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd / 2.0 )
1353 QgsPoint( pointType, x2, y2, z2, m2 ),
1354 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd );
1356 else if ( !addedSegmentEnd && foundStart )
1358 substringPoints <<
QgsPoint( pointType, x2, y2, z2, m2 )
1359 <<
QgsPoint( pointType, x3, y3, z3, m3 );
1363 if ( distanceTraversed > endDistance )
1372 std::unique_ptr< QgsCircularString > result = qgis::make_unique< QgsCircularString >();
1373 result->setPoints( substringPoints );
1374 return result.release();
1387 mZ.reserve( nPoints );
1388 for (
int i = 0; i < nPoints; ++i )
1405 mM.reserve( nPoints );
1406 for (
int i = 0; i < nPoints; ++i )
1439 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.
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.
QString asJson(int precision=17) const override
Returns a GeoJSON representation of the geometry.
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.