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 )
317 if ( parts.second.compare( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) == 0 )
326 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
330 wkbArray.resize( binarySize );
333 wkb << static_cast<quint32>(
wkbType() );
345 wkt += QStringLiteral(
"EMPTY" );
358 std::unique_ptr< QgsLineString > line(
curveToLine() );
359 QDomElement gml = line->asGml2( doc, precision, ns, axisOrder );
368 QDomElement elemCurve = doc.createElementNS( ns, QStringLiteral(
"Curve" ) );
373 QDomElement elemSegments = doc.createElementNS( ns, QStringLiteral(
"segments" ) );
374 QDomElement elemArcString = doc.createElementNS( ns, QStringLiteral(
"ArcString" ) );
376 elemSegments.appendChild( elemArcString );
377 elemCurve.appendChild( elemSegments );
385 std::unique_ptr< QgsLineString > line(
curveToLine() );
386 return line->asJsonObject( precision );
399 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
430 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
444 bool res =
snapToGridPrivate( hSpacing, vSpacing, dSpacing, mSpacing, mX, mY, mZ, mM,
445 result->mX, result->mY, result->mZ, result->mM );
447 return result.release();
454 if ( mX.count() <= 3 )
457 double prevX = mX.at( 0 );
458 double prevY = mY.at( 0 );
460 bool useZ = hasZ && useZValues;
461 double prevZ = useZ ? mZ.at( 0 ) : 0;
463 int remaining = mX.count();
466 while ( i + 1 < remaining )
468 double currentCurveX = mX.at( i );
469 double currentCurveY = mY.at( i );
470 double currentX = mX.at( i + 1 );
471 double currentY = mY.at( i + 1 );
472 double currentZ = useZ ? mZ.at( i + 1 ) : 0;
505 return std::min( mX.size(), mY.size() );
510 if ( i < 0 || std::min( mX.size(), mY.size() ) <= i )
515 double x = mX.at( i );
516 double y = mY.at( i );
547 if ( index >= 0 && index < mX.size() )
548 return mX.at( index );
555 if ( index >= 0 && index < mY.size() )
556 return mY.at( index );
565 int size = mX.size();
567 double *srcX = mX.data();
568 double *srcY = mY.data();
569 double *srcM = hasM ? mM.data() :
nullptr;
570 double *srcZ = hasZ ? mZ.data() :
nullptr;
572 double *destX = srcX;
573 double *destY = srcY;
574 double *destM = srcM;
575 double *destZ = srcZ;
577 int filteredPoints = 0;
578 for (
int i = 0; i < size; ++i )
582 double z = hasZ ? *srcZ++ : std::numeric_limits<double>::quiet_NaN();
583 double m = hasM ? *srcM++ : std::numeric_limits<double>::quiet_NaN();
585 if ( filter(
QgsPoint( x, y, z, m ) ) )
597 mX.resize( filteredPoints );
598 mY.resize( filteredPoints );
600 mZ.resize( filteredPoints );
602 mM.resize( filteredPoints );
611 int size = mX.size();
613 double *srcX = mX.data();
614 double *srcY = mY.data();
615 double *srcM = hasM ? mM.data() :
nullptr;
616 double *srcZ = hasZ ? mZ.data() :
nullptr;
618 for (
int i = 0; i < size; ++i )
622 double z = hasZ ? *srcZ : std::numeric_limits<double>::quiet_NaN();
623 double m = hasM ? *srcM : std::numeric_limits<double>::quiet_NaN();
639 for (
int i = 0; i < nPts; ++i )
641 pts.push_back(
pointN( i ) );
649 if ( points.empty() )
660 const QgsPoint &firstPt = points.at( 0 );
661 bool hasZ = firstPt.
is3D();
666 mX.resize( points.size() );
667 mY.resize( points.size() );
670 mZ.resize( points.size() );
678 mM.resize( points.size() );
685 for (
int i = 0; i < points.size(); ++i )
687 mX[i] = points[i].x();
688 mY[i] = points[i].y();
691 double z = points.at( i ).z();
692 mZ[i] = std::isnan( z ) ? 0 : z;
696 double m = points.at( i ).m();
697 mM[i] = std::isnan( m ) ? 0 : m;
713 double *zArray = mZ.data();
717 bool useDummyZ = !hasZ || !transformZ;
720 zArray =
new double[nPoints];
721 for (
int i = 0; i < nPoints; ++i )
740 for (
int i = 0; i < nPoints; ++i )
743 t.map( mX.at( i ), mY.at( i ), &x, &y );
748 mZ[i] = mZ.at( i ) * zScale + zTranslate;
752 mM[i] = mM.at( i ) * mScale + mTranslate;
765 if ( path.isEmpty() || path.currentPosition() != QPointF( mX[0], mY[0] ) )
767 path.moveTo( QPointF( mX[0], mY[0] ) );
770 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
774 for (
int j = 1; j < pt.size(); ++j )
776 path.lineTo( pt.at( j ).x(), pt.at( j ).y() );
784 if ( nPoints % 2 == 0 )
786 path.lineTo( mX[ nPoints - 1 ], mY[ nPoints - 1 ] );
791 void QgsCircularString::arcTo( QPainterPath &path, QPointF pt1, QPointF pt2, QPointF pt3 )
793 double centerX, centerY, radius;
795 radius, centerX, centerY );
800 double diameter = 2 * radius;
801 path.arcTo( centerX - radius, centerY - radius, diameter, diameter, p1Angle, sweepAngle );
812 if ( position.
vertex >= mX.size() || position.
vertex < 1 )
817 mX.insert( position.
vertex, vertex.
x() );
818 mY.insert( position.
vertex, vertex.
y() );
821 mZ.insert( position.
vertex, vertex.
z() );
825 mM.insert( position.
vertex, vertex.
m() );
828 bool vertexNrEven = ( position.
vertex % 2 == 0 );
843 if ( position.
vertex < 0 || position.
vertex >= mX.size() )
848 mX[position.
vertex] = newPos.
x();
849 mY[position.
vertex] = newPos.
y();
852 mZ[position.
vertex] = newPos.
z();
856 mM[position.
vertex] = newPos.
m();
870 if ( position.
vertex < 0 || position.
vertex > ( nVertices - 1 ) )
875 if ( position.
vertex < ( nVertices - 2 ) )
908 double minDist = std::numeric_limits<double>::max();
911 int minDistLeftOf = 0;
913 double currentDist = 0.0;
916 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
918 currentDist = closestPointOnArc( mX[i], mY[i], mX[i + 1], mY[i + 1], mX[i + 2], mY[i + 2], pt, segmentPt, vertexAfter, leftOf, epsilon );
919 if ( currentDist < minDist )
921 minDist = currentDist;
922 minDistSegmentPoint = segmentPt;
931 if ( minDist == std::numeric_limits<double>::max() )
934 segmentPt = minDistSegmentPoint;
935 vertexAfter = minDistVertexAfter;
936 vertexAfter.
part = 0;
937 vertexAfter.
ring = 0;
960 for (
int i = 0; i < maxIndex; i += 2 )
963 QgsPoint p2( mX[i + 1], mY[i + 1] );
964 QgsPoint p3( mX[i + 2], mY[i + 2] );
974 sum += 0.5 * ( mX[i] * mY[i + 2] - mY[i] * mX[i + 2] );
977 double midPointX = ( p1.
x() + p3.
x() ) / 2.0;
978 double midPointY = ( p1.
y() + p3.
y() ) / 2.0;
980 double radius, centerX, centerY;
984 double r2 = radius * radius;
995 double cov = 0.5 - d * std::sqrt( r2 - d * d ) / ( M_PI * r2 ) - M_1_PI * std::asin( d / radius );
996 double circleChordArea = 0;
997 if ( circlePointLeftOfLine == centerPointLeftOfLine )
999 circleChordArea = M_PI * r2 * ( 1 - cov );
1003 circleChordArea = M_PI * r2 * cov;
1006 if ( !circlePointLeftOfLine )
1008 sum += circleChordArea;
1012 sum -= circleChordArea;
1022 double QgsCircularString::closestPointOnArc(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
1025 double radius, centerX, centerY;
1050 segmentPt = ( distPtPt1 <= distPtPt3 ) ? pt1 : pt3;
1051 vertexAfter.
vertex = ( distPtPt1 <= distPtPt3 ) ? 1 : 2;
1058 segmentPt.
setX( pt.
x() );
1059 segmentPt.
setY( pt.
y() );
1065 double sqrDistancePointToCenter = ( pt.
x() - centerX ) * ( pt.
x() - centerX ) + ( pt.
y() - centerY ) * ( pt.
y() - centerY );
1066 *leftOf = clockwise ? ( sqrDistancePointToCenter > radius * radius ? -1 : 1 )
1067 : ( sqrDistancePointToCenter < radius * radius ? -1 : 1 );
1073 void QgsCircularString::insertVertexBetween(
int after,
int before,
int pointOnCircle )
1075 double xAfter = mX.at( after );
1076 double yAfter = mY.at( after );
1077 double xBefore = mX.at( before );
1078 double yBefore = mY.at( before );
1079 double xOnCircle = mX.at( pointOnCircle );
1080 double yOnCircle = mY.at( pointOnCircle );
1082 double radius, centerX, centerY;
1085 double x = ( xAfter + xBefore ) / 2.0;
1086 double y = ( yAfter + yBefore ) / 2.0;
1089 mX.insert( before, newVertex.
x() );
1090 mY.insert( before, newVertex.
y() );
1094 mZ.insert( before, ( mZ[after] + mZ[before] ) / 2.0 );
1098 mM.insert( before, ( mM[after] + mM[before] ) / 2.0 );
1111 int before = vId.
vertex - 1;
1113 int after = vId.
vertex + 1;
1115 if ( vId.
vertex % 2 != 0 )
1145 int vertex1 = vId.
vertex - 2;
1146 int vertex2 = vId.
vertex - 1;
1147 int vertex3 = vId.
vertex;
1149 QgsPoint( mX[vertex1], mY[vertex1] ),
QgsPoint( mX[vertex2], mY[vertex2] ),
QgsPoint( mX[vertex3], mY[vertex3] ) );
1150 int vertex4 = vId.
vertex + 1;
1151 int vertex5 = vId.
vertex + 2;
1153 QgsPoint( mX[vertex3], mY[vertex3] ),
QgsPoint( mX[vertex4], mY[vertex4] ),
QgsPoint( mX[vertex5], mY[vertex5] ) );
1162 if ( startVertex.
vertex < 0 || startVertex.
vertex >= mX.count() - 2 )
1165 if ( startVertex.
vertex % 2 == 1 )
1168 double x1 = mX.at( startVertex.
vertex );
1169 double y1 = mY.at( startVertex.
vertex );
1170 double x2 = mX.at( startVertex.
vertex + 1 );
1171 double y2 = mY.at( startVertex.
vertex + 1 );
1172 double x3 = mX.at( startVertex.
vertex + 2 );
1173 double y3 = mY.at( startVertex.
vertex + 2 );
1180 std::reverse( copy->mX.begin(), copy->mX.end() );
1181 std::reverse( copy->mY.begin(), copy->mY.end() );
1184 std::reverse( copy->mZ.begin(), copy->mZ.end() );
1188 std::reverse( copy->mM.begin(), copy->mM.end() );
1198 double distanceTraversed = 0;
1200 if ( totalPoints == 0 )
1209 const double *x = mX.constData();
1210 const double *y = mY.constData();
1211 const double *z =
is3D() ? mZ.constData() :
nullptr;
1212 const double *m =
isMeasure() ? mM.constData() :
nullptr;
1214 double prevX = *x++;
1215 double prevY = *y++;
1216 double prevZ = z ? *z++ : 0.0;
1217 double prevM = m ? *m++ : 0.0;
1221 return new QgsPoint( pointType, prevX, prevY, prevZ, prevM );
1224 for (
int i = 0; i < ( totalPoints - 2 ) ; i += 2 )
1233 double z2 = z ? *z++ : 0.0;
1234 double m2 = m ? *m++ : 0.0;
1238 double z3 = z ? *z++ : 0.0;
1239 double m3 = m ? *m++ : 0.0;
1242 if ( distance < distanceTraversed + segmentLength ||
qgsDoubleNear( distance, distanceTraversed + segmentLength ) )
1245 const double distanceToPoint = std::min( distance - distanceTraversed, segmentLength );
1247 QgsPoint( pointType, x2, y2, z2, m2 ),
1248 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToPoint ) );
1264 if ( startDistance < 0 && endDistance < 0 )
1267 endDistance = std::max( startDistance, endDistance );
1269 double distanceTraversed = 0;
1271 if ( totalPoints == 0 )
1274 QVector< QgsPoint > substringPoints;
1282 const double *x = mX.constData();
1283 const double *y = mY.constData();
1284 const double *z =
is3D() ? mZ.constData() :
nullptr;
1285 const double *m =
isMeasure() ? mM.constData() :
nullptr;
1287 double prevX = *x++;
1288 double prevY = *y++;
1289 double prevZ = z ? *z++ : 0.0;
1290 double prevM = m ? *m++ : 0.0;
1291 bool foundStart =
false;
1293 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
1295 substringPoints <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM );
1299 substringPoints.reserve( totalPoints );
1301 for (
int i = 0; i < ( totalPoints - 2 ) ; i += 2 )
1310 double z2 = z ? *z++ : 0.0;
1311 double m2 = m ? *m++ : 0.0;
1315 double z3 = z ? *z++ : 0.0;
1316 double m3 = m ? *m++ : 0.0;
1318 bool addedSegmentEnd =
false;
1320 if ( distanceTraversed < startDistance && distanceTraversed + segmentLength > startDistance )
1323 const double distanceToStart = startDistance - distanceTraversed;
1325 QgsPoint( pointType, x2, y2, z2, m2 ),
1326 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToStart );
1329 const bool endPointOnSegment = distanceTraversed + segmentLength > endDistance;
1330 if ( endPointOnSegment )
1332 const double distanceToEnd = endDistance - distanceTraversed;
1333 const double midPointDistance = ( distanceToEnd - distanceToStart ) * 0.5 + distanceToStart;
1334 substringPoints << startPoint
1336 QgsPoint( pointType, x2, y2, z2, m2 ),
1337 QgsPoint( pointType, x3, y3, z3, m3 ), midPointDistance )
1339 QgsPoint( pointType, x2, y2, z2, m2 ),
1340 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd );
1341 addedSegmentEnd =
true;
1345 const double midPointDistance = ( segmentLength - distanceToStart ) * 0.5 + distanceToStart;
1346 substringPoints << startPoint
1348 QgsPoint( pointType, x2, y2, z2, m2 ),
1349 QgsPoint( pointType, x3, y3, z3, m3 ), midPointDistance )
1350 <<
QgsPoint( pointType, x3, y3, z3, m3 );
1351 addedSegmentEnd =
true;
1355 if ( !addedSegmentEnd && foundStart && ( distanceTraversed + segmentLength > endDistance ) )
1358 const double distanceToEnd = endDistance - distanceTraversed;
1361 QgsPoint( pointType, x2, y2, z2, m2 ),
1362 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd / 2.0 )
1365 QgsPoint( pointType, x2, y2, z2, m2 ),
1366 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd );
1368 else if ( !addedSegmentEnd && foundStart )
1370 substringPoints <<
QgsPoint( pointType, x2, y2, z2, m2 )
1371 <<
QgsPoint( pointType, x3, y3, z3, m3 );
1375 if ( distanceTraversed > endDistance )
1384 std::unique_ptr< QgsCircularString > result = qgis::make_unique< QgsCircularString >();
1385 result->setPoints( substringPoints );
1386 return result.release();
1399 mZ.reserve( nPoints );
1400 for (
int i = 0; i < nPoints; ++i )
1417 mM.reserve( nPoints );
1418 for (
int i = 0; i < nPoints; ++i )
1451 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 planar, 2-dimensional 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.