21#include <nlohmann/json.hpp>
34#include <QPainterPath>
37using namespace Qt::StringLiterals;
47 bool hasZ = p1.
is3D();
80 int pointCount = std::min( x.size(), y.size() );
81 if ( x.size() == pointCount )
87 mX = x.mid( 0, pointCount );
89 if ( y.size() == pointCount )
95 mY = y.mid( 0, pointCount );
97 if ( !z.isEmpty() && z.count() >= pointCount )
100 if ( z.size() == pointCount )
106 mZ = z.mid( 0, pointCount );
109 if ( !m.isEmpty() && m.count() >= pointCount )
112 if ( m.size() == pointCount )
118 mM = m.mid( 0, pointCount );
131 auto result = std::make_unique< QgsCircularString >();
133 return result.release();
138 return u
"CircularString"_s;
156 for (
int i = 0; i < ( nPoints - 2 ); i += 2 )
159 double zMin = std::numeric_limits<double>::quiet_NaN();
160 double zMax = std::numeric_limits<double>::quiet_NaN();
163 zMin = *std::min_element(
mZ.begin() + i,
mZ.begin() + i + 3 );
164 zMax = *std::max_element(
mZ.begin() + i,
mZ.begin() + i + 3 );
168 bbox =
QgsBox3D( box2d, zMin, zMax );
176 if ( nPoints > 0 && nPoints % 2 == 0 )
178 double z = std::numeric_limits<double>::quiet_NaN();
198 double centerX, centerY, radius;
207 bbox.combineExtentWith( pt3.
x(), pt3.
y() );
209 QgsPointSequence compassPoints = compassPointsOnSegment( p1Angle, p2Angle, p3Angle, centerX, centerY, radius );
210 QgsPointSequence::const_iterator cpIt = compassPoints.constBegin();
211 for ( ; cpIt != compassPoints.constEnd(); ++cpIt )
213 bbox.combineExtentWith( cpIt->x(), cpIt->y() );
218QgsPointSequence QgsCircularString::compassPointsOnSegment(
double p1Angle,
double p2Angle,
double p3Angle,
double centerX,
double centerY,
double radius )
222 QgsPoint nPoint( centerX, centerY + radius );
223 QgsPoint ePoint( centerX + radius, centerY );
224 QgsPoint sPoint( centerX, centerY - radius );
225 QgsPoint wPoint( centerX - radius, centerY );
227 if ( p3Angle >= p1Angle )
229 if ( p2Angle > p1Angle && p2Angle < p3Angle )
231 if ( p1Angle <= 90 && p3Angle >= 90 )
233 pointList.append( nPoint );
235 if ( p1Angle <= 180 && p3Angle >= 180 )
237 pointList.append( wPoint );
239 if ( p1Angle <= 270 && p3Angle >= 270 )
241 pointList.append( sPoint );
246 pointList.append( ePoint );
247 if ( p1Angle >= 90 || p3Angle <= 90 )
249 pointList.append( nPoint );
251 if ( p1Angle >= 180 || p3Angle <= 180 )
253 pointList.append( wPoint );
255 if ( p1Angle >= 270 || p3Angle <= 270 )
257 pointList.append( sPoint );
263 if ( p2Angle < p1Angle && p2Angle > p3Angle )
265 if ( p1Angle >= 270 && p3Angle <= 270 )
267 pointList.append( sPoint );
269 if ( p1Angle >= 180 && p3Angle <= 180 )
271 pointList.append( wPoint );
273 if ( p1Angle >= 90 && p3Angle <= 90 )
275 pointList.append( nPoint );
280 pointList.append( ePoint );
281 if ( p1Angle <= 270 || p3Angle >= 270 )
283 pointList.append( sPoint );
285 if ( p1Angle <= 180 || p3Angle >= 180 )
287 pointList.append( wPoint );
289 if ( p1Angle <= 90 || p3Angle >= 90 )
291 pointList.append( nPoint );
301 std::unique_ptr< QgsLineString > line(
curveToLine() );
302 QDomElement gml = line->asGml2( doc, precision, ns, axisOrder );
311 QDomElement elemCurve = doc.createElementNS( ns, u
"Curve"_s );
316 QDomElement elemSegments = doc.createElementNS( ns, u
"segments"_s );
317 QDomElement elemArcString = doc.createElementNS( ns, u
"ArcString"_s );
319 elemSegments.appendChild( elemArcString );
320 elemCurve.appendChild( elemSegments );
332 std::unique_ptr< QgsLineString > line(
curveToLine() );
333 return line->asJsonObject( precision, profile );
341 constexpr int MAX_POINT = 11;
342 if ( pts.size() > MAX_POINT )
344 json geometries = json::array();
345 json subCs = { {
"type",
"CircularString" } };
346 subCs[
"coordinates"] = json::array();
347 for (
int i = 0; i < pts.size(); i++ )
349 const json pointCoords = pts[i].asJsonObject( precision, profile )[
"coordinates"];
350 subCs[
"coordinates"].push_back( pointCoords );
351 if ( subCs[
"coordinates"].size() == MAX_POINT )
353 geometries.push_back( subCs );
355 subCs[
"coordinates"] = json::array();
356 subCs[
"coordinates"].push_back( pointCoords );
360 if ( subCs[
"coordinates"].size() > 1 )
362 geometries.push_back( subCs );
364 return { {
"type",
"CompoundCurve" }, {
"geometries", geometries } };
379 error = QObject::tr(
"CircularString has less than 3 points and is not empty." );
390 for (
int i = 0; i < ( nPoints - 2 ); i += 2 )
403 for (
int i = 0; i < ( nPoints - 2 ); i += 2 )
418 bool res =
snapToGridPrivate( hSpacing, vSpacing, dSpacing, mSpacing,
mX,
mY,
mZ,
mM, result->mX, result->mY, result->mZ, result->mM,
false );
420 return result.release();
427 std::unique_ptr< QgsLineString > line(
curveToLine() );
428 return line->simplifyByDistance( tolerance );
433 if (
mX.count() <= 3 )
436 double prevX =
mX.at( 0 );
437 double prevY =
mY.at( 0 );
439 bool useZ = hasZ && useZValues;
440 double prevZ = useZ ?
mZ.at( 0 ) : 0;
442 int remaining =
mX.count();
445 while ( i + 1 < remaining )
447 double currentCurveX =
mX.at( i );
448 double currentCurveY =
mY.at( i );
449 double currentX =
mX.at( i + 1 );
450 double currentY =
mY.at( i + 1 );
451 double currentZ = useZ ?
mZ.at( i + 1 ) : 0;
484 const int size =
mX.size();
488 const double *x =
mX.constData();
489 const double *y =
mY.constData();
490 const bool useZ =
is3D();
492 const double *z = useZ ?
mZ.constData() :
nullptr;
493 const double *m = useM ?
mM.constData() :
nullptr;
495 for (
int i = 0; i < size; i += 2 )
521 QVector< double > x1, y1, z1, m1;
522 QVector< double > x2, y2, z2, m2;
525 std::unique_ptr< QgsCircularString > first;
526 if ( x1.isEmpty() || ( x1.size() < 2 && x2.size() >= 2 ) )
527 first = std::make_unique< QgsCircularString >();
529 first = std::make_unique< QgsCircularString >( x1, y1, z1, m1 );
531 std::unique_ptr< QgsCircularString > second;
532 if ( x2.isEmpty() || x2.size() < 2 )
533 second = std::make_unique< QgsCircularString >();
535 second = std::make_unique< QgsCircularString >( x2, y2, z2, m2 );
537 return std::make_tuple( std::move( first ), std::move( second ) );
547void arcTo( QPainterPath &path, QPointF pt1, QPointF pt2, QPointF pt3 )
549 double centerX, centerY, radius;
555 double diameter = 2 * radius;
556 path.arcTo( centerX - radius, centerY - radius, diameter, diameter, -p1Angle, -sweepAngle );
567 if ( path.isEmpty() || path.currentPosition() != QPointF(
mX[0],
mY[0] ) )
569 path.moveTo( QPointF(
mX[0],
mY[0] ) );
572 for (
int i = 0; i < ( nPoints - 2 ); i += 2 )
574 arcTo( path, QPointF(
mX[i],
mY[i] ), QPointF(
mX[i + 1],
mY[i + 1] ), QPointF(
mX[i + 2],
mY[i + 2] ) );
578 if ( nPoints % 2 == 0 )
580 path.lineTo(
mX[nPoints - 1],
mY[nPoints - 1] );
596 mX.insert( position.
vertex, vertex.
x() );
597 mY.insert( position.
vertex, vertex.
y() );
600 mZ.insert( position.
vertex, vertex.
z() );
604 mM.insert( position.
vertex, vertex.
m() );
607 bool vertexNrEven = ( position.
vertex % 2 == 0 );
624 if ( position.
vertex < 0 || position.
vertex > ( nVertices - 1 ) )
635 if ( position.
vertex < ( nVertices - 2 ) )
668 if ( positions.empty() )
683 QList<QgsVertexId>
vertices( positions.begin(), positions.end() );
688 for (
size_t i =
vertices.size() - 1; i >= 1; i-- )
691 int prevVertexNr =
vertices[i - 1].vertex;
693 if ( vertexNr - 1 == prevVertexNr )
695 if ( vertexNr < nVertices - 2 )
712 if ( nVertices -
vertices.size() * 2 < 3 )
718 QListIterator<QgsVertexId> positionsIt(
vertices );
719 positionsIt.toBack();
720 while ( positionsIt.hasPrevious() )
722 int currentVertexNr = positionsIt.previous().vertex;
724 if ( currentVertexNr < nVertices - 2 )
742 double minDist = std::numeric_limits<double>::max();
745 int minDistLeftOf = 0;
747 double currentDist = 0.0;
750 for (
int i = 0; i < ( nPoints - 2 ); i += 2 )
752 currentDist = closestPointOnArc(
mX[i],
mY[i],
mX[i + 1],
mY[i + 1],
mX[i + 2],
mY[i + 2], pt, segmentPt, vertexAfter, leftOf, epsilon );
753 if ( currentDist < minDist )
755 minDist = currentDist;
756 minDistSegmentPoint = segmentPt;
760 minDistLeftOf = *leftOf;
765 if ( minDist == std::numeric_limits<double>::max() )
768 segmentPt = minDistSegmentPoint;
769 vertexAfter = minDistVertexAfter;
770 vertexAfter.
part = 0;
771 vertexAfter.
ring = 0;
800 for (
int i = 0; i < maxIndex; i += 2 )
817 double midPointX = ( p1.
x() + p3.
x() ) / 2.0;
818 double midPointY = ( p1.
y() + p3.
y() ) / 2.0;
820 double radius, centerX, centerY;
824 double r2 = radius * radius;
835 double cov = 0.5 - d * std::sqrt( r2 - d * d ) / ( M_PI * r2 ) - M_1_PI * std::asin( d / radius );
836 double circleChordArea = 0;
837 if ( circlePointLeftOfLine == centerPointLeftOfLine )
839 circleChordArea = M_PI * r2 * ( 1 - cov );
843 circleChordArea = M_PI * r2 * cov;
846 if ( !circlePointLeftOfLine )
899 double normalSign = 1.0;
919 QVector<double> projX;
920 QVector<double> projY;
921 projX.reserve( nrPoints );
922 projY.reserve( nrPoints );
923 for (
int i = 0; i < nrPoints; i++ )
925 const double vecAX =
mX[i] - ptA.
x();
926 const double vecAY =
mY[i] - ptA.
y();
927 const double vecAZ =
mZ[i] - ptA.
z();
929 projX.push_back( vecAX * ux.
x() + vecAY * ux.
y() + vecAZ * ux.
z() );
930 projY.push_back( vecAX * uy.
x() + vecAY * uy.
y() + vecAZ * uy.
z() );
947double QgsCircularString::closestPointOnArc(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
const QgsPoint &pt,
QgsPoint &segmentPt,
QgsVertexId &vertexAfter,
int *leftOf,
double epsilon )
949 double radius, centerX, centerY;
974 segmentPt = ( distPtPt1 <= distPtPt3 ) ? pt1 : pt3;
975 vertexAfter.
vertex = ( distPtPt1 <= distPtPt3 ) ? 1 : 2;
982 segmentPt.
setX( pt.
x() );
983 segmentPt.
setY( pt.
y() );
989 double sqrDistancePointToCenter = pt.
distanceSquared( centerX, centerY );
990 *
leftOf = clockwise ? ( sqrDistancePointToCenter > radius * radius ? -1 : 1 ) : ( sqrDistancePointToCenter < radius * radius ? -1 : 1 );
996void QgsCircularString::insertVertexBetween(
int after,
int before,
int pointOnCircle )
998 double xAfter =
mX.at( after );
999 double yAfter =
mY.at( after );
1000 double xBefore =
mX.at( before );
1001 double yBefore =
mY.at( before );
1002 double xOnCircle =
mX.at( pointOnCircle );
1003 double yOnCircle =
mY.at( pointOnCircle );
1005 double radius, centerX, centerY;
1008 double x = ( xAfter + xBefore ) / 2.0;
1009 double y = ( yAfter + yBefore ) / 2.0;
1012 mX.insert( before, newVertex.
x() );
1013 mY.insert( before, newVertex.
y() );
1017 mZ.insert( before, (
mZ[after] +
mZ[before] ) / 2.0 );
1021 mM.insert( before, (
mM[after] +
mM[before] ) / 2.0 );
1034 int before = vId.
vertex - 1;
1036 int after = vId.
vertex + 1;
1038 if ( vId.
vertex % 2 != 0 )
1065 int vertex1 = vId.
vertex - 2;
1066 int vertex2 = vId.
vertex - 1;
1067 int vertex3 = vId.
vertex;
1070 int vertex4 = vId.
vertex + 1;
1071 int vertex5 = vId.
vertex + 2;
1082 if ( startVertex.
vertex % 2 == 1 )
1085 if ( startVertex.
vertex < 0 || startVertex.
vertex >=
mX.count() - 2 )
1088 double x1 =
mX.at( startVertex.
vertex );
1089 double y1 =
mY.at( startVertex.
vertex );
1090 double x2 =
mX.at( startVertex.
vertex + 1 );
1091 double y2 =
mY.at( startVertex.
vertex + 1 );
1092 double x3 =
mX.at( startVertex.
vertex + 2 );
1093 double y3 =
mY.at( startVertex.
vertex + 2 );
1106 if ( fromVertex.
part != 0 || fromVertex.
ring != 0 || toVertex.
part != 0 || toVertex.
ring != 0 )
1109 const int fromVertexNumber = fromVertex.
vertex;
1110 const int toVertexNumber = toVertex.
vertex;
1113 if ( fromVertexNumber < 0 || fromVertexNumber >= nPoints || toVertexNumber < 0 || toVertexNumber >= nPoints )
1116 if ( fromVertexNumber == toVertexNumber )
1119 const double *
xData =
mX.constData();
1120 const double *
yData =
mY.constData();
1121 double totalDistance = 0.0;
1125 const int startArc = ( fromVertexNumber / 2 ) * 2;
1128 for (
int i = startArc; i < nPoints - 2; i += 2 )
1131 double x1 =
xData[i];
1132 double y1 =
yData[i];
1133 double x2 =
xData[i + 1];
1134 double y2 =
yData[i + 1];
1135 double x3 =
xData[i + 2];
1136 double y3 =
yData[i + 2];
1139 if ( fromVertexNumber >= i && toVertexNumber <= i + 2 )
1141 if ( fromVertexNumber == i && toVertexNumber == i + 2 )
1146 else if ( fromVertexNumber == i && toVertexNumber == i + 1 )
1149 double centerX, centerY, radius;
1152 return QgsGeometryUtilsBase::calculateArcLength( centerX, centerY, radius, x1, y1, x2, y2, x3, y3, 0, 1 );
1154 else if ( fromVertexNumber == i + 1 && toVertexNumber == i + 2 )
1157 double centerX, centerY, radius;
1160 return QgsGeometryUtilsBase::calculateArcLength( centerX, centerY, radius, x1, y1, x2, y2, x3, y3, 1, 2 );
1162 else if ( fromVertexNumber == i + 1 && toVertexNumber == i + 1 )
1169 bool startInThisSegment = ( fromVertexNumber >= i && fromVertexNumber <= i + 2 );
1170 bool endInThisSegment = ( toVertexNumber >= i && toVertexNumber <= i + 2 );
1171 bool segmentInRange = ( fromVertexNumber < i && toVertexNumber > i + 2 );
1173 if ( startInThisSegment && !endInThisSegment )
1176 if ( fromVertexNumber == i )
1178 else if ( fromVertexNumber == i + 1 )
1181 double centerX, centerY, radius;
1183 totalDistance +=
QgsGeometryUtilsBase::calculateArcLength( centerX, centerY, radius, x1, y1, x2, y2, x3, y3, 1, 2 );
1186 else if ( !startInThisSegment && endInThisSegment )
1189 if ( toVertexNumber == i + 1 )
1192 double centerX, centerY, radius;
1194 totalDistance +=
QgsGeometryUtilsBase::calculateArcLength( centerX, centerY, radius, x1, y1, x2, y2, x3, y3, 0, 1 );
1196 else if ( toVertexNumber == i + 2 )
1200 else if ( segmentInRange )
1207 return totalDistance;
1221 double distanceTraversed = 0;
1223 if ( totalPoints == 0 )
1232 const double *x =
mX.constData();
1233 const double *y =
mY.constData();
1234 const double *z =
is3D() ?
mZ.constData() :
nullptr;
1235 const double *m =
isMeasure() ?
mM.constData() :
nullptr;
1237 double prevX = *x++;
1238 double prevY = *y++;
1239 double prevZ = z ? *z++ : 0.0;
1240 double prevM = m ? *m++ : 0.0;
1244 return new QgsPoint( pointType, prevX, prevY, prevZ, prevM );
1247 for (
int i = 0; i < ( totalPoints - 2 ); i += 2 )
1256 double z2 = z ? *z++ : 0.0;
1257 double m2 = m ? *m++ : 0.0;
1261 double z3 = z ? *z++ : 0.0;
1262 double m3 = m ? *m++ : 0.0;
1268 const double distanceToPoint = std::min( distance - distanceTraversed,
segmentLength );
1269 return new QgsPoint(
QgsGeometryUtils::interpolatePointOnArc(
QgsPoint( pointType, x1, y1, z1, m1 ),
QgsPoint( pointType, x2, y2, z2, m2 ),
QgsPoint( pointType, x3, y3, z3, m3 ), distanceToPoint ) );
1285 if ( startDistance < 0 && endDistance < 0 )
1288 endDistance = std::max( startDistance, endDistance );
1291 if ( totalPoints == 0 )
1294 QVector< QgsPoint > substringPoints;
1295 substringPoints.reserve( totalPoints );
1303 const double *x =
mX.constData();
1304 const double *y =
mY.constData();
1305 const double *z =
is3D() ?
mZ.constData() :
nullptr;
1306 const double *m =
isMeasure() ?
mM.constData() :
nullptr;
1308 double distanceTraversed = 0;
1309 double prevX = *x++;
1310 double prevY = *y++;
1311 double prevZ = z ? *z++ : 0.0;
1312 double prevM = m ? *m++ : 0.0;
1313 bool foundStart =
false;
1315 if ( startDistance < 0 )
1318 for (
int i = 0; i < ( totalPoints - 2 ); i += 2 )
1327 double z2 = z ? *z++ : 0.0;
1328 double m2 = m ? *m++ : 0.0;
1332 double z3 = z ? *z++ : 0.0;
1333 double m3 = m ? *m++ : 0.0;
1335 bool addedSegmentEnd =
false;
1337 if ( distanceTraversed <= startDistance && startDistance < distanceTraversed +
segmentLength )
1340 const double distanceToStart = startDistance - distanceTraversed;
1342 =
QgsGeometryUtils::interpolatePointOnArc(
QgsPoint( pointType, x1, y1, z1, m1 ),
QgsPoint( pointType, x2, y2, z2, m2 ),
QgsPoint( pointType, x3, y3, z3, m3 ), distanceToStart );
1345 const bool endPointOnSegment = distanceTraversed +
segmentLength > endDistance;
1346 if ( endPointOnSegment )
1348 const double distanceToEnd = endDistance - distanceTraversed;
1349 const double midPointDistance = ( distanceToEnd - distanceToStart ) * 0.5 + distanceToStart;
1352 <<
QgsGeometryUtils::interpolatePointOnArc(
QgsPoint( pointType, x1, y1, z1, m1 ),
QgsPoint( pointType, x2, y2, z2, m2 ),
QgsPoint( pointType, x3, y3, z3, m3 ), midPointDistance )
1353 <<
QgsGeometryUtils::interpolatePointOnArc(
QgsPoint( pointType, x1, y1, z1, m1 ),
QgsPoint( pointType, x2, y2, z2, m2 ),
QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd );
1354 addedSegmentEnd =
true;
1358 const double midPointDistance = (
segmentLength - distanceToStart ) * 0.5 + distanceToStart;
1361 <<
QgsGeometryUtils::interpolatePointOnArc(
QgsPoint( pointType, x1, y1, z1, m1 ),
QgsPoint( pointType, x2, y2, z2, m2 ),
QgsPoint( pointType, x3, y3, z3, m3 ), midPointDistance )
1362 <<
QgsPoint( pointType, x3, y3, z3, m3 );
1363 addedSegmentEnd =
true;
1367 if ( !addedSegmentEnd && foundStart && ( distanceTraversed +
segmentLength > endDistance ) )
1370 const double distanceToEnd = endDistance - distanceTraversed;
1373 <<
QgsGeometryUtils::interpolatePointOnArc(
QgsPoint( pointType, x1, y1, z1, m1 ),
QgsPoint( pointType, x2, y2, z2, m2 ),
QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd / 2.0 )
1375 <<
QgsGeometryUtils::interpolatePointOnArc(
QgsPoint( pointType, x1, y1, z1, m1 ),
QgsPoint( pointType, x2, y2, z2, m2 ),
QgsPoint( pointType, x3, y3, z3, m3 ), distanceToEnd );
1377 else if ( !addedSegmentEnd && foundStart )
1379 substringPoints <<
QgsPoint( pointType, x2, y2, z2, m2 ) <<
QgsPoint( pointType, x3, y3, z3, m3 );
1387 if ( distanceTraversed >= endDistance )
1392 if ( !foundStart &&
qgsDoubleNear( distanceTraversed, startDistance ) )
1394 substringPoints <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM ) <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM ) <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM );
1397 auto result = std::make_unique< QgsCircularString >();
1398 result->setPoints( substringPoints );
1399 return result.release();
QFlags< GeometryValidityFlag > GeometryValidityFlags
Geometry validity flags.
VertexType
Types of vertex.
@ Curve
An intermediate point on a segment defining the curvature of the segment.
@ Segment
The actual start or end point of a segment.
GeoJsonProfile
GeoJson export Profile according to OGC Features and Geometries JSON - Part 1: Core https://docs....
@ Legacy
Legacy GeoJson profile used in QGIS prior to 4.2, which included some non-standard extensions and dev...
@ Rfc7946
GeoJson profile compliant with RFC7946 standard "http://www.opengis.net/def/profile/OGC/0/rfc7946".
@ JsonFg
GeoJson profile from OGC Features and Geometries JSON Part 1: core "http://www.opengis....
@ JsonFgPlus
GeoJson profile from OGC Features and Geometries JSON Part 1: core "http://www.opengis....
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CircularString
CircularString.
@ CircularStringZ
CircularStringZ.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
QgsVertexIterator vertices() const
Returns a read-only, Java-style iterator for traversal of vertices of all the geometry,...
bool isMeasure() const
Returns true if the geometry contains m values.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
AxisOrder
Axis order for GML generation.
QgsAbstractGeometry()=default
A 3-dimensional box composed of x, y, z coordinates.
void combineWith(const QgsBox3D &box)
Expands the bbox so that it covers both the original rectangle and the given rectangle.
QgsCircularString * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0, bool removeRedundantPoints=false) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
double length() const override
Returns the planar, 2-dimensional length of the geometry.
QString geometryType() const override
Returns a unique string representing the geometry type.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
QgsCircularString * clone() const override
Clones the geometry by performing a deep copy.
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.
double distanceBetweenVertices(QgsVertexId fromVertex, QgsVertexId toVertex) const override
Returns the distance along the curve between two vertices.
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...
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
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...
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.
QgsBox3D calculateBoundingBox3D() const override
Calculates the minimal 3D bounding box for the geometry.
bool pointAt(int node, QgsPoint &point, Qgis::VertexType &type) const override
Returns the point and vertex type of a point within the curve.
int indexOf(const QgsPoint &point) const final
Returns the index of the first vertex matching the given point, or -1 if a matching vertex is not fou...
void addToPainterPath(QPainterPath &path) const override
Adds a curve to a painter path.
QgsCircularString * curveSubstring(double startDistance, double endDistance) const override
Returns a new curve representing a substring of this curve.
json asJsonObject(int precision=17, Qgis::GeoJsonProfile profile=Qgis::GeoJsonProfile::Legacy) const override
Returns a json object representation of the geometry with the given precision and profile.
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
bool deleteVertices(const QSet< QgsVertexId > &positions) override
Deletes vertices within the geometry.
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.
void sumUpArea3D(double &sum) const override
Sums up the 3d area of the curve by iterating over the vertices (shoelace formula).
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
QgsAbstractGeometry * simplifyByDistance(double tolerance) const override
Simplifies the geometry by applying the Douglas Peucker simplification by distance algorithm.
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.
void clear() override
Clears the geometry, ie reset it to a null geometry.
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 isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
QgsCircularString()
Constructs an empty circular string.
std::tuple< std::unique_ptr< QgsCurve >, std::unique_ptr< QgsCurve > > splitCurveAtVertex(int index) const final
Splits the curve at the specified vertex index, returning two curves which represent the portion of t...
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
bool mHasCachedSummedUpArea
bool mHasCachedSummedUpArea3D
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
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, bool removeRedundantPoints) const
Helper function for QgsCurve subclasses to snap to grids.
bool hasVertex(QgsVertexId position) const override
Returns true if the geometry contains a vertex matching the given position.
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.
static double calculateArcLength(double centerX, double centerY, double radius, double x1, double y1, double x2, double y2, double x3, double y3, int fromVertex, int toVertex)
Calculates the precise arc length between two vertices on a circular arc.
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...
static bool circleClockwise(double angle1, double angle2, double angle3)
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)
Calculates angle of a circular string part defined by pt1, pt2, pt3.
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,...
static bool circleAngleBetween(double angle, double angle1, double angle2, bool clockwise)
Returns true if, in a circle, angle is between angle1 and angle2.
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,...
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 void circleCenterRadius(double x1, double y1, double x2, double y2, double x3, double y3, double &radius, double ¢erX, double ¢erY)
Returns radius and center of the circle through (x1 y1), (x2 y2), (x3 y3).
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).
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance)
Returns a point a specified distance toward a second point.
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 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.
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 Q_DECL_DEPRECATED double sqrDistance2D(double x1, double y1, double x2, double y2)
Returns the squared 2D distance between (x1, y1) and (x2, y2).
static bool checkWeaklyFor3DPlane(const QgsAbstractGeometry *geom, QgsPoint &pt1, QgsPoint &pt2, QgsPoint &pt3, double epsilon=std::numeric_limits< double >::epsilon())
Checks if a 3D geometry has a plane defined by at least 3 non-collinear points.
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 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 json pointsToJson(const QgsPointSequence &points, int precision, Qgis::GeoJsonProfile profile)
Returns coordinates as json object.
Line string geometry type, with support for z-dimension and m-values.
void setPoints(size_t size, const double *x, const double *y, const double *z=nullptr, const double *m=nullptr)
Resets the line string to match the specified point data.
Point geometry type, with support for z-dimension and m-values.
void setY(double y)
Sets the point's y-coordinate.
void setX(double x)
Sets the point's x-coordinate.
double distanceSquared(double x, double y) const
Returns the Cartesian 2D squared distance between this point a specified x, y coordinate.
A rectangle specified with double values.
int numPoints() const override
Returns the number of points in the curve.
bool isEmpty() const override
Returns true if the geometry is empty.
void splitCurveAtVertexProtected(int index, QVector< double > &x1, QVector< double > &y1, QVector< double > &z1, QVector< double > &m1, QVector< double > &x2, QVector< double > &y2, QVector< double > &z2, QVector< double > &m2) const
Returns coordinate vectors for the split curves.
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.
const double * yData() const
Returns a const pointer to the y vertex data.
QgsPoint startPoint() const override
Returns the starting point of the curve.
QgsPoint pointN(int i) const
Returns the specified point from inside the simple curve.
QgsSimpleCurve * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
const double * xData() const
Returns a const pointer to the x vertex data.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
double x() const
Returns X coordinate.
void normalize()
Normalizes the current vector in place.
static QgsVector3D crossProduct(const QgsVector3D &v1, const QgsVector3D &v2)
Returns the cross product of two vectors.
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'. Negative values mean left ...
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define BUILTIN_UNREACHABLE
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
QVector< QgsPoint > QgsPointSequence
void arcTo(QPainterPath &path, QPointF pt1, QPointF pt2, QPointF pt3)
Utility class for identifying a unique vertex within a geometry.