30 #include <QJsonObject>
32 #include <QPainterPath>
34 #include <nlohmann/json.hpp>
44 bool hasZ = p1.
is3D();
89 if ( mX.count() != otherLine->mX.count() )
92 for (
int i = 0; i < mX.count(); ++i )
110 auto result = qgis::make_unique< QgsCircularString >();
112 return result.release();
117 return QStringLiteral(
"CircularString" );
144 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
148 bbox = segmentBoundingBox(
QgsPoint( mX[i], mY[i] ),
QgsPoint( mX[i + 1], mY[i + 1] ),
QgsPoint( mX[i + 2], mY[i + 2] ) );
157 if ( nPoints > 0 && nPoints % 2 == 0 )
170 double centerX, centerY, radius;
179 bbox.combineExtentWith( pt3.
x(), pt3.
y() );
181 QgsPointSequence compassPoints = compassPointsOnSegment( p1Angle, p2Angle, p3Angle, centerX, centerY, radius );
182 QgsPointSequence::const_iterator cpIt = compassPoints.constBegin();
183 for ( ; cpIt != compassPoints.constEnd(); ++cpIt )
185 bbox.combineExtentWith( cpIt->x(), cpIt->y() );
190 QgsPointSequence QgsCircularString::compassPointsOnSegment(
double p1Angle,
double p2Angle,
double p3Angle,
double centerX,
double centerY,
double radius )
194 QgsPoint nPoint( centerX, centerY + radius );
195 QgsPoint ePoint( centerX + radius, centerY );
196 QgsPoint sPoint( centerX, centerY - radius );
197 QgsPoint wPoint( centerX - radius, centerY );
199 if ( p3Angle >= p1Angle )
201 if ( p2Angle > p1Angle && p2Angle < p3Angle )
203 if ( p1Angle <= 90 && p3Angle >= 90 )
205 pointList.append( nPoint );
207 if ( p1Angle <= 180 && p3Angle >= 180 )
209 pointList.append( wPoint );
211 if ( p1Angle <= 270 && p3Angle >= 270 )
213 pointList.append( sPoint );
218 pointList.append( ePoint );
219 if ( p1Angle >= 90 || p3Angle <= 90 )
221 pointList.append( nPoint );
223 if ( p1Angle >= 180 || p3Angle <= 180 )
225 pointList.append( wPoint );
227 if ( p1Angle >= 270 || p3Angle <= 270 )
229 pointList.append( sPoint );
235 if ( p2Angle < p1Angle && p2Angle > p3Angle )
237 if ( p1Angle >= 270 && p3Angle <= 270 )
239 pointList.append( sPoint );
241 if ( p1Angle >= 180 && p3Angle <= 180 )
243 pointList.append( wPoint );
245 if ( p1Angle >= 90 && p3Angle <= 90 )
247 pointList.append( nPoint );
252 pointList.append( ePoint );
253 if ( p1Angle <= 270 || p3Angle >= 270 )
255 pointList.append( sPoint );
257 if ( p1Angle <= 180 || p3Angle >= 180 )
259 pointList.append( wPoint );
261 if ( p1Angle <= 90 || p3Angle >= 90 )
263 pointList.append( nPoint );
288 mX.resize( nVertices );
289 mY.resize( nVertices );
290 hasZ ? mZ.resize( nVertices ) : mZ.clear();
291 hasM ? mM.resize( nVertices ) : mM.clear();
292 for (
int i = 0; i < nVertices; ++i )
319 parts.second =
parts.second.remove(
'(' ).remove(
')' );
320 QString secondWithoutParentheses =
parts.second;
321 secondWithoutParentheses = secondWithoutParentheses.simplified().remove(
' ' );
322 if ( (
parts.second.compare( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
323 secondWithoutParentheses.isEmpty() )
336 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
347 wkb << static_cast<quint32>(
wkbType() );
359 wkt += QLatin1String(
"EMPTY" );
372 std::unique_ptr< QgsLineString > line(
curveToLine() );
373 QDomElement gml = line->asGml2( doc,
precision, ns, axisOrder );
382 QDomElement elemCurve = doc.createElementNS( ns, QStringLiteral(
"Curve" ) );
387 QDomElement elemSegments = doc.createElementNS( ns, QStringLiteral(
"segments" ) );
388 QDomElement elemArcString = doc.createElementNS( ns, QStringLiteral(
"ArcString" ) );
390 elemSegments.appendChild( elemArcString );
391 elemCurve.appendChild( elemSegments );
399 std::unique_ptr< QgsLineString > line(
curveToLine() );
412 error = QObject::tr(
"CircularString has less than 3 points and is not empty." );
423 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
454 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
468 bool res =
snapToGridPrivate( hSpacing, vSpacing, dSpacing, mSpacing, mX, mY, mZ, mM,
469 result->mX, result->mY, result->mZ, result->mM );
471 return result.release();
478 if ( mX.count() <= 3 )
481 double prevX = mX.at( 0 );
482 double prevY = mY.at( 0 );
484 bool useZ = hasZ && useZValues;
485 double prevZ = useZ ? mZ.at( 0 ) : 0;
487 int remaining = mX.count();
490 while ( i + 1 < remaining )
492 double currentCurveX = mX.at( i );
493 double currentCurveY = mY.at( i );
494 double currentX = mX.at( i + 1 );
495 double currentY = mY.at( i + 1 );
496 double currentZ = useZ ? mZ.at( i + 1 ) : 0;
529 return std::min( mX.size(), mY.size() );
534 if ( i < 0 || std::min( mX.size(), mY.size() ) <= i )
539 double x = mX.at( i );
540 double y = mY.at( i );
571 if ( index >= 0 && index < mX.size() )
572 return mX.at( index );
579 if ( index >= 0 && index < mY.size() )
580 return mY.at( index );
592 int size = mX.size();
594 double *srcX = mX.data();
595 double *srcY = mY.data();
596 double *srcM = hasM ? mM.data() :
nullptr;
597 double *srcZ = hasZ ? mZ.data() :
nullptr;
600 for (
int i = 0; i < size; ++i )
604 double z = hasZ ? *srcZ : std::numeric_limits<double>::quiet_NaN();
605 double m = hasM ? *srcM : std::numeric_limits<double>::quiet_NaN();
633 int size = mX.size();
635 double *srcX = mX.data();
636 double *srcY = mY.data();
637 double *srcM = hasM ? mM.data() :
nullptr;
638 double *srcZ = hasZ ? mZ.data() :
nullptr;
640 double *destX = srcX;
641 double *destY = srcY;
642 double *destM = srcM;
643 double *destZ = srcZ;
645 int filteredPoints = 0;
646 for (
int i = 0; i < size; ++i )
650 double z = hasZ ? *srcZ++ : std::numeric_limits<double>::quiet_NaN();
651 double m = hasM ? *srcM++ : std::numeric_limits<double>::quiet_NaN();
653 if ( filter(
QgsPoint( x, y, z, m ) ) )
665 mX.resize( filteredPoints );
666 mY.resize( filteredPoints );
668 mZ.resize( filteredPoints );
670 mM.resize( filteredPoints );
679 int size = mX.size();
681 double *srcX = mX.data();
682 double *srcY = mY.data();
683 double *srcM = hasM ? mM.data() :
nullptr;
684 double *srcZ = hasZ ? mZ.data() :
nullptr;
686 for (
int i = 0; i < size; ++i )
690 double z = hasZ ? *srcZ : std::numeric_limits<double>::quiet_NaN();
691 double m = hasM ? *srcM : std::numeric_limits<double>::quiet_NaN();
707 for (
int i = 0; i < nPts; ++i )
709 pts.push_back(
pointN( i ) );
729 bool hasZ = firstPt.
is3D();
734 mX.resize(
points.size() );
735 mY.resize(
points.size() );
738 mZ.resize(
points.size() );
746 mM.resize(
points.size() );
753 for (
int i = 0; i <
points.size(); ++i )
759 double z =
points.at( i ).z();
760 mZ[i] = std::isnan( z ) ? 0 : z;
764 double m =
points.at( i ).m();
765 mM[i] = std::isnan( m ) ? 0 : m;
781 double *zArray = mZ.data();
785 bool useDummyZ = !hasZ || !transformZ;
788 zArray =
new double[nPoints];
789 for (
int i = 0; i < nPoints; ++i )
808 for (
int i = 0; i < nPoints; ++i )
811 t.map( mX.at( i ), mY.at( i ), &x, &y );
816 mZ[i] = mZ.at( i ) * zScale + zTranslate;
820 mM[i] = mM.at( i ) * mScale + mTranslate;
833 if ( path.isEmpty() || path.currentPosition() != QPointF( mX[0], mY[0] ) )
835 path.moveTo( QPointF( mX[0], mY[0] ) );
838 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
842 for (
int j = 1; j < pt.size(); ++j )
844 path.lineTo( pt.at( j ).x(), pt.at( j ).y() );
852 if ( nPoints % 2 == 0 )
854 path.lineTo( mX[ nPoints - 1 ], mY[ nPoints - 1 ] );
859 void QgsCircularString::arcTo( QPainterPath &path, QPointF pt1, QPointF pt2, QPointF pt3 )
861 double centerX, centerY, radius;
863 radius, centerX, centerY );
868 double diameter = 2 * radius;
869 path.arcTo( centerX - radius, centerY - radius, diameter, diameter, p1Angle, sweepAngle );
880 if ( position.
vertex >= mX.size() || position.
vertex < 1 )
885 mX.insert( position.
vertex, vertex.
x() );
886 mY.insert( position.
vertex, vertex.
y() );
889 mZ.insert( position.
vertex, vertex.
z() );
893 mM.insert( position.
vertex, vertex.
m() );
896 bool vertexNrEven = ( position.
vertex % 2 == 0 );
911 if ( position.
vertex < 0 || position.
vertex >= mX.size() )
916 mX[position.
vertex] = newPos.
x();
917 mY[position.
vertex] = newPos.
y();
920 mZ[position.
vertex] = newPos.
z();
924 mM[position.
vertex] = newPos.
m();
938 if ( position.
vertex < 0 || position.
vertex > ( nVertices - 1 ) )
943 if ( position.
vertex < ( nVertices - 2 ) )
976 double minDist = std::numeric_limits<double>::max();
979 int minDistLeftOf = 0;
981 double currentDist = 0.0;
984 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
986 currentDist = closestPointOnArc( mX[i], mY[i], mX[i + 1], mY[i + 1], mX[i + 2], mY[i + 2], pt, segmentPt, vertexAfter,
leftOf, epsilon );
987 if ( currentDist < minDist )
989 minDist = currentDist;
990 minDistSegmentPoint = segmentPt;
999 if ( minDist == std::numeric_limits<double>::max() )
1002 segmentPt = minDistSegmentPoint;
1003 vertexAfter = minDistVertexAfter;
1004 vertexAfter.
part = 0;
1005 vertexAfter.
ring = 0;
1028 for (
int i = 0; i < maxIndex; i += 2 )
1031 QgsPoint p2( mX[i + 1], mY[i + 1] );
1032 QgsPoint p3( mX[i + 2], mY[i + 2] );
1042 sum += 0.5 * ( mX[i] * mY[i + 2] - mY[i] * mX[i + 2] );
1045 double midPointX = ( p1.
x() + p3.
x() ) / 2.0;
1046 double midPointY = ( p1.
y() + p3.
y() ) / 2.0;
1048 double radius, centerX, centerY;
1052 double r2 = radius * radius;
1063 double cov = 0.5 - d * std::sqrt( r2 - d * d ) / ( M_PI * r2 ) - M_1_PI * std::asin( d / radius );
1064 double circleChordArea = 0;
1065 if ( circlePointLeftOfLine == centerPointLeftOfLine )
1067 circleChordArea = M_PI * r2 * ( 1 - cov );
1071 circleChordArea = M_PI * r2 * cov;
1074 if ( !circlePointLeftOfLine )
1076 sum += circleChordArea;
1080 sum -= circleChordArea;
1090 double QgsCircularString::closestPointOnArc(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
1093 double radius, centerX, centerY;
1118 segmentPt = ( distPtPt1 <= distPtPt3 ) ? pt1 : pt3;
1119 vertexAfter.
vertex = ( distPtPt1 <= distPtPt3 ) ? 1 : 2;
1126 segmentPt.
setX( pt.
x() );
1127 segmentPt.
setY( pt.
y() );
1133 double sqrDistancePointToCenter = ( pt.
x() - centerX ) * ( pt.
x() - centerX ) + ( pt.
y() - centerY ) * ( pt.
y() - centerY );
1134 *
leftOf = clockwise ? ( sqrDistancePointToCenter > radius * radius ? -1 : 1 )
1135 : ( sqrDistancePointToCenter < radius * radius ? -1 : 1 );
1141 void QgsCircularString::insertVertexBetween(
int after,
int before,
int pointOnCircle )
1143 double xAfter = mX.at( after );
1144 double yAfter = mY.at( after );
1145 double xBefore = mX.at( before );
1146 double yBefore = mY.at( before );
1147 double xOnCircle = mX.at( pointOnCircle );
1148 double yOnCircle = mY.at( pointOnCircle );
1150 double radius, centerX, centerY;
1153 double x = ( xAfter + xBefore ) / 2.0;
1154 double y = ( yAfter + yBefore ) / 2.0;
1157 mX.insert( before, newVertex.
x() );
1158 mY.insert( before, newVertex.
y() );
1162 mZ.insert( before, ( mZ[after] + mZ[before] ) / 2.0 );
1166 mM.insert( before, ( mM[after] + mM[before] ) / 2.0 );
1179 int before = vId.
vertex - 1;
1181 int after = vId.
vertex + 1;
1183 if ( vId.
vertex % 2 != 0 )
1213 int vertex1 = vId.
vertex - 2;
1214 int vertex2 = vId.
vertex - 1;
1215 int vertex3 = vId.
vertex;
1217 QgsPoint( mX[vertex1], mY[vertex1] ),
QgsPoint( mX[vertex2], mY[vertex2] ),
QgsPoint( mX[vertex3], mY[vertex3] ) );
1218 int vertex4 = vId.
vertex + 1;
1219 int vertex5 = vId.
vertex + 2;
1221 QgsPoint( mX[vertex3], mY[vertex3] ),
QgsPoint( mX[vertex4], mY[vertex4] ),
QgsPoint( mX[vertex5], mY[vertex5] ) );
1230 if ( startVertex.
vertex < 0 || startVertex.
vertex >= mX.count() - 2 )
1233 if ( startVertex.
vertex % 2 == 1 )
1236 double x1 = mX.at( startVertex.
vertex );
1237 double y1 = mY.at( startVertex.
vertex );
1238 double x2 = mX.at( startVertex.
vertex + 1 );
1239 double y2 = mY.at( startVertex.
vertex + 1 );
1240 double x3 = mX.at( startVertex.
vertex + 2 );
1241 double y3 = mY.at( startVertex.
vertex + 2 );
1248 std::reverse( copy->mX.begin(), copy->mX.end() );
1249 std::reverse( copy->mY.begin(), copy->mY.end() );
1252 std::reverse( copy->mZ.begin(), copy->mZ.end() );
1256 std::reverse( copy->mM.begin(), copy->mM.end() );
1266 double distanceTraversed = 0;
1268 if ( totalPoints == 0 )
1277 const double *x = mX.constData();
1278 const double *y = mY.constData();
1279 const double *z =
is3D() ? mZ.constData() :
nullptr;
1280 const double *m =
isMeasure() ? mM.constData() :
nullptr;
1282 double prevX = *x++;
1283 double prevY = *y++;
1284 double prevZ = z ? *z++ : 0.0;
1285 double prevM = m ? *m++ : 0.0;
1289 return new QgsPoint( pointType, prevX, prevY, prevZ, prevM );
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;
1313 const double distanceToPoint = std::min( distance - distanceTraversed,
segmentLength );
1315 QgsPoint( pointType, x2, y2, z2, m2 ),
1316 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToPoint ) );
1332 if ( startDistance < 0 && endDistance < 0 )
1335 endDistance = std::max( startDistance, endDistance );
1338 if ( totalPoints == 0 )
1341 QVector< QgsPoint > substringPoints;
1342 substringPoints.reserve( totalPoints );
1350 const double *x = mX.constData();
1351 const double *y = mY.constData();
1352 const double *z =
is3D() ? mZ.constData() :
nullptr;
1353 const double *m =
isMeasure() ? mM.constData() :
nullptr;
1355 double distanceTraversed = 0;
1356 double prevX = *x++;
1357 double prevY = *y++;
1358 double prevZ = z ? *z++ : 0.0;
1359 double prevM = m ? *m++ : 0.0;
1360 bool foundStart =
false;
1362 if ( startDistance < 0 )
1365 for (
int i = 0; i < ( totalPoints - 2 ) ; i += 2 )
1374 double z2 = z ? *z++ : 0.0;
1375 double m2 = m ? *m++ : 0.0;
1379 double z3 = z ? *z++ : 0.0;
1380 double m3 = m ? *m++ : 0.0;
1382 bool addedSegmentEnd =
false;
1384 if ( distanceTraversed <= startDistance && startDistance < distanceTraversed +
segmentLength )
1387 const double distanceToStart = startDistance - distanceTraversed;
1389 QgsPoint( pointType, x2, y2, z2, m2 ),
1390 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToStart );
1393 const bool endPointOnSegment = distanceTraversed +
segmentLength > endDistance;
1394 if ( endPointOnSegment )
1396 const double distanceToEnd = endDistance - distanceTraversed;
1397 const double midPointDistance = ( distanceToEnd - distanceToStart ) * 0.5 + distanceToStart;
1400 QgsPoint( pointType, x2, y2, z2, m2 ),
1401 QgsPoint( pointType, x3, y3, z3, m3 ), midPointDistance )
1403 QgsPoint( pointType, x2, y2, z2, m2 ),
1404 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd );
1405 addedSegmentEnd =
true;
1409 const double midPointDistance = (
segmentLength - distanceToStart ) * 0.5 + distanceToStart;
1412 QgsPoint( pointType, x2, y2, z2, m2 ),
1413 QgsPoint( pointType, x3, y3, z3, m3 ), midPointDistance )
1414 <<
QgsPoint( pointType, x3, y3, z3, m3 );
1415 addedSegmentEnd =
true;
1419 if ( !addedSegmentEnd && foundStart && ( distanceTraversed +
segmentLength > endDistance ) )
1422 const double distanceToEnd = endDistance - distanceTraversed;
1425 QgsPoint( pointType, x2, y2, z2, m2 ),
1426 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd / 2.0 )
1429 QgsPoint( pointType, x2, y2, z2, m2 ),
1430 QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd );
1432 else if ( !addedSegmentEnd && foundStart )
1434 substringPoints <<
QgsPoint( pointType, x2, y2, z2, m2 )
1435 <<
QgsPoint( pointType, x3, y3, z3, m3 );
1443 if ( distanceTraversed >= endDistance )
1448 if ( !foundStart &&
qgsDoubleNear( distanceTraversed, startDistance ) )
1450 substringPoints <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM )
1451 <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM )
1452 <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM );
1455 std::unique_ptr< QgsCircularString > result = qgis::make_unique< QgsCircularString >();
1456 result->setPoints( substringPoints );
1457 return result.release();
1470 mZ.reserve( nPoints );
1471 for (
int i = 0; i < nPoints; ++i )
1488 mM.reserve( nPoints );
1489 for (
int i = 0; i < nPoints; ++i )
1522 std::swap( mX, mY );
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
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.
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.
bool equals(const QgsCurve &other) const override
Checks whether this curve exactly equals another curve.
double length() const override
Returns the planar, 2-dimensional length of the geometry.
QgsPoint pointN(int i) const SIP_HOLDGIL
Returns the point at index i within the circular string.
void points(QgsPointSequence &pts) const override
Returns a list of points within the curve.
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
int numPoints() const override SIP_HOLDGIL
Returns the number of points in the curve.
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.
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.
QgsCircularString * clone() const override
Clones the geometry by performing a deep copy.
QString geometryType() const override SIP_HOLDGIL
Returns a unique string representing the geometry type.
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
int dimension() const override SIP_HOLDGIL
Returns the inherent dimension of the geometry.
bool pointAt(int node, QgsPoint &point, QgsVertexId::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
QgsCircularString * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
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.
void swapXy() override
Swaps the x and y coordinates from the geometry.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
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 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...
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
double xAt(int index) const override SIP_HOLDGIL
Returns the x-coordinate of the specified node in the line string.
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 addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
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 sumUpArea(double &sum) const override
Sums up the area of the curve by iterating over the vertices (shoelace formula).
QgsCircularString * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
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.
double yAt(int index) const override SIP_HOLDGIL
Returns the y-coordinate of the specified node in the line string.
QgsPoint endPoint() const override SIP_HOLDGIL
Returns the end point of the curve.
void addToPainterPath(QPainterPath &path) const override
Adds a curve to a painter path.
int wkbSize(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns the length of the QByteArray returned by asWkb()
QgsCircularString * curveSubstring(double startDistance, double endDistance) const override
Returns a new curve representing a substring of this curve.
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
void setPoints(const QgsPointSequence &points)
Sets the circular string's points.
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.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
bool dropZValue() override
Drops any z-dimensions which exist 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.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
void clear() override
Clears the geometry, ie reset it to a null geometry.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
bool isValid(QString &error, int flags=0) const override
Checks validity of the geometry, and returns true if the geometry is valid.
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
QgsPoint * interpolatePoint(double distance) const override
Returns an interpolated point on the curve at the specified distance.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
QgsPoint startPoint() const override SIP_HOLDGIL
Returns the starting point of the curve.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
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.
QgsCircularString() SIP_HOLDGIL
Constructs an empty circular string.
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.
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.
bool isValid(QString &error, int flags=0) const override
Checks validity of the geometry, and returns true if the geometry is valid.
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 double circleTangentDirection(const QgsPoint &tangentPoint, const QgsPoint &cp1, const QgsPoint &cp2, const QgsPoint &cp3) SIP_HOLDGIL
Calculates the direction angle of a circle tangent (clockwise from north in radians)
static double sqrDistance2D(const QgsPoint &pt1, const QgsPoint &pt2) SIP_HOLDGIL
Returns the squared 2D distance between two points.
static double ccwAngle(double dy, double dx) SIP_HOLDGIL
Returns the counter clockwise angle between a line with components dx, dy and the line with dx > 0 an...
static void pointsToWKB(QgsWkbPtr &wkb, const QgsPointSequence &points, bool is3D, bool isMeasure)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
static QgsPoint segmentMidPointFromCenter(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint ¢er, bool useShortestArc=true) SIP_HOLDGIL
Calculates the midpoint on the circle passing through p1 and p2, with the specified center coordinate...
static void circleCenterRadius(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double &radius, double ¢erX, double ¢erY) SIP_HOLDGIL
Returns radius and center of the circle through pt1, pt2, pt3.
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 bool angleOnCircle(double angle, double angle1, double angle2, double angle3) SIP_HOLDGIL
Returns true if an angle is between angle1 and angle3 on a circle described by angle1,...
static bool circleClockwise(double angle1, double angle2, double angle3) SIP_HOLDGIL
Returns true if the circle defined by three angles is ordered clockwise.
static double sweepAngle(double centerX, double centerY, double x1, double y1, double x2, double y2, double x3, double y3) SIP_HOLDGIL
Calculates angle of a circular string part defined by pt1, pt2, pt3.
static double circleLength(double x1, double y1, double x2, double y2, double x3, double y3) SIP_HOLDGIL
Length of a circular string segment defined by pt1, pt2, pt3.
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance) SIP_HOLDGIL
Returns a point a specified distance toward a second point.
static QgsPointSequence pointsFromWKT(const QString &wktCoordinateList, bool is3D, bool isMeasure)
Returns a list of points contained in a WKT string.
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.
static bool circleAngleBetween(double angle, double angle1, double angle2, bool clockwise) SIP_HOLDGIL
Returns true if, in a circle, angle is between angle1 and angle2.
static QgsPoint interpolatePointOnArc(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double distance) SIP_HOLDGIL
Interpolates a point on an arc defined by three points, pt1, pt2 and pt3.
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.
static int leftOfLine(const double x, const double y, const double x1, const double y1, const double x2, const double y2) SIP_HOLDGIL
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> (x2, y2).
static QString pointsToWKT(const QgsPointSequence &points, int precision, bool is3D, bool isMeasure)
Returns a WKT coordinate list.
Line string geometry type, with support for z-dimension and m-values.
void setPoints(const QgsPointSequence &points)
Resets the line string to match the specified list of points.
Point geometry type, with support for z-dimension and m-values.
void setX(double x) SIP_HOLDGIL
Sets the point's x-coordinate.
void setY(double y) SIP_HOLDGIL
Sets the point's y-coordinate.
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 angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
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.
@ SegmentVertex
The actual start or end point of a segment.
@ CurveVertex
An intermediate point on a segment defining the curvature of the segment.