28#include <QRegularExpression>
29#include <nlohmann/json.hpp>
33 QVector< QgsLineString * > linestrings;
37 QVector< const QgsAbstractGeometry * > geometries;
39 while ( ! geometries.isEmpty() )
42 if (
const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( g ) )
44 linestrings << static_cast< QgsLineString * >( curve->segmentize() );
46 else if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g ) )
48 for (
int i = 0; i < collection->numGeometries(); ++i )
50 geometries.append( collection->geometryN( i ) );
53 else if (
const QgsCurvePolygon *curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( g ) )
55 if ( curvePolygon->exteriorRing() )
56 linestrings << static_cast< QgsLineString * >( curvePolygon->exteriorRing()->segmentize() );
58 for (
int i = 0; i < curvePolygon->numInteriorRings(); ++i )
60 linestrings << static_cast< QgsLineString * >( curvePolygon->interiorRing( i )->segmentize() );
69 double minDist = std::numeric_limits<double>::max();
70 double currentDist = 0;
87 if ( currentDist <= minDist )
89 minDist = currentDist;
90 minDistPoint = vertex;
91 id.part = vertexId.
part;
92 id.ring = vertexId.
ring;
93 id.vertex = vertexId.
vertex;
94 id.type = vertexId.
type;
109 if ( vertexAfter.
vertex > 0 )
114 const double length = pointBefore.
distance( pointAfter );
136 double currentDist = 0;
141 if ( vertexId ==
id )
155 double currentDist = 0;
170 nextVertex = previousVertex;
175 while ( currentDist < distance && geometry.
nextVertex( nextVertex, point ) )
177 if ( !first && nextVertex.
part == previousVertex.
part && nextVertex.
ring == previousVertex.
ring )
185 previousVertex = nextVertex;
189 if ( currentDist > distance )
194 previousVertex = nextVertex;
195 previousPoint = point;
205 return ( pt1.
x() - pt2.
x() ) * ( pt1.
x() - pt2.
x() ) + ( pt1.
y() - pt2.
y() ) * ( pt1.
y() - pt2.
y() );
218 const double t = ( ( ptX - x1 ) * dx + ( ptY - y1 ) * dy ) / ( dx * dx + dy * dy );
234 const double dist = dx * dx + dy * dy;
249 const double area = std::abs(
250 ( linePoint1.
x() - linePoint2.
x() ) * ( point.
y() - linePoint2.
y() ) -
251 ( linePoint1.
y() - linePoint2.
y() ) * ( point.
x() - linePoint2.
x() )
254 const double length = std::sqrt(
255 std::pow( linePoint1.
x() - linePoint2.
x(), 2 ) +
256 std::pow( linePoint1.
y() - linePoint2.
y(), 2 )
259 const double distance = area / length;
260 return qgsDoubleNear( distance, 0.0, epsilon ) ? 0.0 : distance;
265 const double d = v1.
y() * v2.
x() - v1.
x() * v2.
y();
270 const double dx = p2.
x() - p1.
x();
271 const double dy = p2.
y() - p1.
y();
272 const double k = ( dy * v2.
x() - dx * v2.
y() ) / d;
274 intersection =
QgsPoint( p1.
x() + v1.
x() * k, p1.
y() + v1.
y() * k );
284 isIntersection =
false;
288 const double vl = v.
length();
289 const double wl = w.
length();
303 isIntersection =
true;
304 if ( acceptImproperIntersection )
306 if ( ( p1 == q1 ) || ( p1 == q2 ) )
308 intersectionPoint = p1;
311 else if ( ( p2 == q1 ) || ( p2 == q2 ) )
313 intersectionPoint = p2;
320 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( p1.
x(), p1.
y(), q1.
x(), q1.
y(), q2.
x(), q2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
322 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( p2.
x(), p2.
y(), q1.
x(), q1.
y(), q2.
x(), q2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
324 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( q1.
x(), q1.
y(), p1.
x(), p1.
y(), p2.
x(), p2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
326 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( q2.
x(), q2.
y(), p1.
x(), p1.
y(), p2.
x(), p2.
y(), x, y, tolerance ), 0.0, tolerance )
333 const double lambdav =
QgsVector( intersectionPoint.
x() - p1.
x(), intersectionPoint.
y() - p1.
y() ) * v;
334 if ( lambdav < 0. + tolerance || lambdav > vl - tolerance )
337 const double lambdaw =
QgsVector( intersectionPoint.
x() - q1.
x(), intersectionPoint.
y() - q1.
y() ) * w;
338 return !( lambdaw < 0. + tolerance || lambdaw >= wl - tolerance );
348 const double x1 = linePoint1.
x() - center.
x();
349 const double y1 = linePoint1.
y() - center.
y();
350 const double x2 = linePoint2.
x() - center.
x();
351 const double y2 = linePoint2.
y() - center.
y();
352 const double dx = x2 - x1;
353 const double dy = y2 - y1;
355 const double dr2 = std::pow( dx, 2 ) + std::pow( dy, 2 );
356 const double d = x1 * y2 - x2 * y1;
358 const double disc = std::pow( radius, 2 ) * dr2 - std::pow( d, 2 );
368 const int sgnDy = dy < 0 ? -1 : 1;
370 const double sqrDisc = std::sqrt( disc );
372 const double ax = center.
x() + ( d * dy + sgnDy * dx * sqrDisc ) / dr2;
373 const double ay = center.
y() + ( -d * dx + std::fabs( dy ) * sqrDisc ) / dr2;
376 const double bx = center.
x() + ( d * dy - sgnDy * dx * sqrDisc ) / dr2;
377 const double by = center.
y() + ( -d * dx - std::fabs( dy ) * sqrDisc ) / dr2;
384 intersection.
set( p1.
x(), p1.
y() );
388 intersection.
set( p2.
x(), p2.
y() );
399 const double d = center1.
distance( center2 );
402 if ( d > ( r1 + r2 ) )
407 else if ( d < std::fabs( r1 - r2 ) )
424 const double a = ( ( r1 * r1 ) - ( r2 * r2 ) + ( d * d ) ) / ( 2.0 * d ) ;
429 const double dx = center2.
x() - center1.
x();
430 const double dy = center2.
y() - center1.
y();
433 const double x2 = center1.
x() + ( dx * a / d );
434 const double y2 = center1.
y() + ( dy * a / d );
439 const double h = std::sqrt( ( r1 * r1 ) - ( a * a ) );
444 const double rx = dy * ( h / d );
445 const double ry = dx * ( h / d );
448 intersection1 =
QgsPointXY( x2 + rx, y2 - ry );
449 intersection2 =
QgsPointXY( x2 - rx, y2 + ry );
463 const double dx = center.
x() - p.
x();
464 const double dy = center.
y() - p.
y();
465 const double distanceSquared = dx * dx + dy * dy;
466 const double radiusSquared = radius * radius;
467 if ( distanceSquared < radiusSquared )
474 const double distanceToTangent = std::sqrt( distanceSquared - radiusSquared );
486 if ( radius1 > radius2 )
489 const double radius2a = radius2 - radius1;
498 QgsVector v1( -( line1P2.
y() - center1.
y() ), line1P2.
x() - center1.
x() );
499 const double v1Length = v1.
length();
500 v1 = v1 * ( radius1 / v1Length );
503 line1P1 = center1 + v1;
504 line1P2 = line1P2 + v1;
508 QgsVector v2( line2P2.
y() - center1.
y(), -( line2P2.
x() - center1.
x() ) );
509 const double v2Length = v2.
length();
510 v2 = v2 * ( radius1 / v2Length );
513 line2P1 = center1 + v2;
514 line2P2 = line2P2 + v2;
522 if ( radius1 > radius2 )
526 const double d = center1.
distance( center2 );
527 const double radius1a = radius1 + radius2;
544 QgsVector v1( ( line1P2.
y() - center2.
y() ), -( line1P2.
x() - center2.
x() ) );
545 const double v1Length = v1.
length();
546 v1 = v1 * ( radius2 / v1Length );
549 line1P1 = center2 + v1;
550 line1P2 = line1P2 + v1;
554 QgsVector v2( -( line2P2.
y() - center2.
y() ), line2P2.
x() - center2.
x() );
555 const double v2Length = v2.
length();
556 v2 = v2 * ( radius2 / v2Length );
559 line2P1 = center2 + v2;
560 line2P2 = line2P2 + v2;
567 QVector<SelfIntersection> intersections;
573 for (
int i = 0, j = 1; j < n; i = j++ )
580 const int start = j + 1;
581 const int end = i == 0 && isClosed ? n - 1 : n;
582 for (
int k = start, l = start + 1; l < end; k = l++ )
588 bool intersection =
false;
599 intersections.append( s );
602 return intersections;
612 const double f1 = x - x1;
613 const double f2 = y2 - y1;
614 const double f3 = y - y1;
615 const double f4 = x2 - x1;
616 const double test = ( f1 * f2 - f3 * f4 );
618 return qgsDoubleNear( test, 0.0 ) ? 0 : ( test < 0 ? -1 : 1 );
628void QgsGeometryUtils::pointOnLineWithDistance(
double x1,
double y1,
double x2,
double y2,
double distance,
double &x,
double &y,
double *z1,
double *z2,
double *z,
double *m1,
double *m2,
double *m )
630 const double dx = x2 - x1;
631 const double dy = y2 - y1;
632 const double length = std::sqrt( dx * dx + dy * dy );
645 const double scaleFactor = distance / length;
646 x = x1 + dx * scaleFactor;
647 y = y1 + dy * scaleFactor;
649 *z = *z1 + ( *z2 - *z1 ) * scaleFactor;
651 *m = *m1 + ( *m2 - *m1 ) * scaleFactor;
658 const double mX = x1 + ( x2 - x1 ) * proportion;
659 const double mY = y1 + ( y2 - y1 ) * proportion;
660 const double pX = x1 - x2;
661 const double pY = y1 - y2;
662 double normalX = -pY;
664 const double normalLength = sqrt( ( normalX * normalX ) + ( normalY * normalY ) );
665 normalX /= normalLength;
666 normalY /= normalLength;
668 *x = mX + offset * normalX;
669 *y = mY + offset * normalY;
674 double centerX, centerY, radius;
677 const double theta = distance / radius;
678 const double anglePt1 = std::atan2( pt1.
y() - centerY, pt1.
x() - centerX );
679 const double anglePt2 = std::atan2( pt2.
y() - centerY, pt2.
x() - centerX );
680 const double anglePt3 = std::atan2( pt3.
y() - centerY, pt3.
x() - centerX );
682 const double angleDest = anglePt1 + (
isClockwise ? -theta : theta );
684 const double x = centerX + radius * ( std::cos( angleDest ) );
685 const double y = centerY + radius * ( std::sin( angleDest ) );
687 const double z = pt1.
is3D() ?
699 const double angle = std::atan2( dy, dx ) * 180 / M_PI;
704 else if ( angle > 360 )
713 double dx21, dy21, dx31, dy31, h21, h31, d;
718 centerX = ( pt1.
x() + pt2.
x() ) / 2.0;
719 centerY = ( pt1.
y() + pt2.
y() ) / 2.0;
720 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
725 dx21 = pt2.
x() - pt1.
x();
726 dy21 = pt2.
y() - pt1.
y();
727 dx31 = pt3.
x() - pt1.
x();
728 dy31 = pt3.
y() - pt1.
y();
730 h21 = std::pow( dx21, 2.0 ) + std::pow( dy21, 2.0 );
731 h31 = std::pow( dx31, 2.0 ) + std::pow( dy31, 2.0 );
734 d = 2 * ( dx21 * dy31 - dx31 * dy21 );
744 centerX = pt1.
x() + ( h21 * dy31 - h31 * dy21 ) / d;
745 centerY = pt1.
y() - ( h21 * dx31 - h31 * dx21 ) / d;
746 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
751 if ( angle3 >= angle1 )
753 return !( angle2 > angle1 && angle2 < angle3 );
757 return !( angle2 > angle1 || angle2 < angle3 );
765 if ( angle2 < angle1 )
767 return ( angle <= angle1 && angle >= angle2 );
771 return ( angle <= angle1 || angle >= angle2 );
776 if ( angle2 > angle1 )
778 return ( angle >= angle1 && angle <= angle2 );
782 return ( angle >= angle1 || angle <= angle2 );
795 double centerX, centerY, radius;
797 double length = M_PI / 180.0 * radius *
sweepAngle( centerX, centerY, x1, y1, x2, y2, x3, y3 );
811 if ( p3Angle >= p1Angle )
813 if ( p2Angle > p1Angle && p2Angle < p3Angle )
815 return ( p3Angle - p1Angle );
819 return ( - ( p1Angle + ( 360 - p3Angle ) ) );
824 if ( p2Angle < p1Angle && p2Angle > p3Angle )
826 return ( -( p1Angle - p3Angle ) );
830 return ( p3Angle + ( 360 - p1Angle ) );
837 const QgsPoint midPoint( ( p1.
x() + p2.
x() ) / 2.0, ( p1.
y() + p2.
y() ) / 2.0 );
838 const double midDist = std::sqrt(
sqrDistance2D( p1, midPoint ) );
839 if ( radius < midDist )
843 const double centerMidDist = std::sqrt( radius * radius - midDist * midDist );
844 const double dist = radius - centerMidDist;
846 const double midDx = midPoint.
x() - p1.
x();
847 const double midDy = midPoint.
y() - p1.
y();
850 QVector<QgsPoint> possibleMidPoints;
857 double minDist = std::numeric_limits<double>::max();
858 int minDistIndex = -1;
859 for (
int i = 0; i < possibleMidPoints.size(); ++i )
861 const double currentDist =
sqrDistance2D( mousePos, possibleMidPoints.at( i ) );
862 if ( currentDist < minDist )
865 minDist = currentDist;
869 if ( minDistIndex == -1 )
874 result = possibleMidPoints.at( minDistIndex );
886 if ( !useShortestArc )
887 midPointAngle += M_PI;
888 return center.
project( center.
distance( p1 ), midPointAngle * 180 / M_PI );
895 double mX, mY, radius;
904 angle =
lineAngle( tangentPoint.
x(), tangentPoint.
y(), mX, mY ) - M_PI_2;
908 angle =
lineAngle( mX, mY, tangentPoint.
x(), tangentPoint.
y() ) - M_PI_2;
928 const double bDistance = std::sqrt( ( b.
x() - centerX ) * ( b.
x() - centerX ) +
929 ( b.
y() - centerY ) * ( b.
y() - centerY ) );
931 double diff = std::fabs( radius - bDistance );
935 const double abX = b.
x() - a.
x();
936 const double abY = b.
y() - a.
y();
938 const double cbX = b.
x() -
c.x();
939 const double cbY = b.
y() -
c.y();
941 const double dot = ( abX * cbX + abY * cbY );
942 const double cross = ( abX * cbY - abY * cbX );
944 const double alpha = std::atan2( cross, dot );
950 if ( diff < distanceTolerance )
952 const double angle1 = arcAngle( a1, a2, a3 );
953 const double angle2 = arcAngle( a2, a3, b );
958 diff = std::fabs( angle1 - angle2 );
959 if ( diff > pointSpacingAngleTolerance )
964 const int a2Side =
leftOfLine( a2.
x(), a2.
y(), a1.
x(), a1.
y(), a3.
x(), a3.
y() );
965 const int bSide =
leftOfLine( b.
x(), b.
y(), a1.
x(), a1.
y(), a3.
x(), a3.
y() );
969 if ( bSide != a2Side )
977 bool reversed =
false;
1001 circleCenterRadius( circlePoint1, circlePoint2, circlePoint3, radius, centerX, centerY );
1003 if ( circlePoint1 != circlePoint3 && ( radius < 0 ||
qgsDoubleNear( segSide, 0.0 ) ) )
1005 points.append( p1 );
1006 points.append( p2 );
1007 points.append( p3 );
1011 double increment = tolerance;
1015 tolerance = std::min( tolerance, radius * 2 );
1016 const double halfAngle = std::acos( -tolerance / radius + 1 );
1017 increment = 2 * halfAngle;
1021 const double a1 = std::atan2( circlePoint1.
y() - centerY, circlePoint1.
x() - centerX );
1022 double a2 = std::atan2( circlePoint2.
y() - centerY, circlePoint2.
x() - centerX );
1023 double a3 = std::atan2( circlePoint3.
y() - centerY, circlePoint3.
x() - centerX );
1026 const bool symmetric =
true;
1029 double angle = a3 - a1;
1031 if ( angle <= 0 ) angle += M_PI * 2;
1034 const int segs = ceil( angle / increment );
1036 increment = angle / segs;
1050 QVector<QgsPoint> stringPoints;
1051 stringPoints.insert( 0, circlePoint1 );
1052 if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 )
1066 const double tolError = increment / 100;
1067 const double stopAngle = a3 - tolError;
1068 for (
double angle = a1 + increment; angle < stopAngle; angle += increment )
1070 x = centerX + radius * std::cos( angle );
1071 y = centerY + radius * std::sin( angle );
1082 stringPoints.insert( stringPoints.size(),
QgsPoint( pointWkbType, x, y, z, m ) );
1085 stringPoints.insert( stringPoints.size(), circlePoint3 );
1090 std::reverse( stringPoints.begin(), stringPoints.end() );
1092 if ( ! points.empty() && stringPoints.front() == points.back() ) stringPoints.pop_front();
1093 points.append( stringPoints );
1098 const double side = ( ( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
1123 return zm1 + ( zm2 - zm1 ) * ( angle - a1 ) / ( a2 - a1 );
1125 return zm2 + ( zm3 - zm2 ) * ( angle - a2 ) / ( a3 - a2 );
1131 return zm1 + ( zm2 - zm1 ) * ( a1 - angle ) / ( a1 - a2 );
1133 return zm2 + ( zm3 - zm2 ) * ( a2 - angle ) / ( a2 - a3 );
1139 const int dim = 2 + is3D + isMeasure;
1142#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1143 const QStringList coordList = wktCoordinateList.split(
',', QString::SkipEmptyParts );
1145 const QStringList coordList = wktCoordinateList.split(
',', Qt::SkipEmptyParts );
1149 bool foundZ =
false;
1150 bool foundM =
false;
1151 const thread_local QRegularExpression rx( QStringLiteral(
"\\s" ) );
1152 const thread_local QRegularExpression rxIsNumber( QStringLiteral(
"^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$" ) );
1153 for (
const QString &pointCoordinates : coordList )
1155#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1156 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1158 const QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
1162 if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() )
1165 if ( coordinates.size() == 3 && !foundZ && !foundM && !is3D && !isMeasure )
1171 else if ( coordinates.size() >= 4 && ( !( is3D || foundZ ) || !( isMeasure || foundM ) ) )
1180 for (
const QString &pointCoordinates : coordList )
1182#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1183 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1185 QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
1187 if ( coordinates.size() < dim )
1191 const double x = coordinates[idx++].toDouble();
1192 const double y = coordinates[idx++].toDouble();
1195 if ( ( is3D || foundZ ) && coordinates.length() > idx )
1196 z = coordinates[idx++].toDouble();
1199 if ( ( isMeasure || foundM ) && coordinates.length() > idx )
1200 m = coordinates[idx++].toDouble();
1203 if ( is3D || foundZ )
1205 if ( isMeasure || foundM )
1212 if ( isMeasure || foundM )
1218 points.append(
QgsPoint( t, x, y, z, m ) );
1226 wkb << static_cast<quint32>( points.size() );
1227 for (
const QgsPoint &point : points )
1229 wkb << point.x() << point.y();
1232 double z = point.z();
1234 && std::isnan( z ) )
1235 z = -std::numeric_limits<double>::max();
1241 double m = point.m();
1243 && std::isnan( m ) )
1244 m = -std::numeric_limits<double>::max();
1253 QString wkt = QStringLiteral(
"(" );
1262 wkt += QLatin1String(
", " );
1264 if ( wkt.endsWith( QLatin1String(
", " ) ) )
1272 QDomElement elemCoordinates = doc.createElementNS( ns, QStringLiteral(
"coordinates" ) );
1275 const QString cs = QStringLiteral(
"," );
1277 const QString ts = QStringLiteral(
" " );
1279 elemCoordinates.setAttribute( QStringLiteral(
"cs" ), cs );
1280 elemCoordinates.setAttribute( QStringLiteral(
"ts" ), ts );
1282 QString strCoordinates;
1290 if ( strCoordinates.endsWith( ts ) )
1291 strCoordinates.chop( 1 );
1293 elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
1294 return elemCoordinates;
1299 QDomElement elemPosList = doc.createElementNS( ns, QStringLiteral(
"posList" ) );
1300 elemPosList.setAttribute( QStringLiteral(
"srsDimension" ), is3D ? 3 : 2 );
1302 QString strCoordinates;
1312 if ( strCoordinates.endsWith(
' ' ) )
1313 strCoordinates.chop( 1 );
1315 elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
1321 QString json = QStringLiteral(
"[ " );
1326 if ( json.endsWith( QLatin1String(
", " ) ) )
1337 json coordinates( json::array() );
1354 double clippedAngle = angle;
1355 if ( clippedAngle >= M_PI * 2 || clippedAngle <= -2 * M_PI )
1357 clippedAngle = std::fmod( clippedAngle, 2 * M_PI );
1359 if ( clippedAngle < 0.0 )
1361 clippedAngle += 2 * M_PI;
1363 return clippedAngle;
1368 QString wktParsed = wkt;
1370 const QLatin1String empty {
"EMPTY" };
1371 if ( wkt.contains( empty, Qt::CaseInsensitive ) )
1373 const thread_local QRegularExpression whiteSpaces(
"\\s" );
1374 wktParsed.remove( whiteSpaces );
1375 const int index = wktParsed.indexOf( empty, 0, Qt::CaseInsensitive );
1377 if ( index == wktParsed.length() - empty.size() )
1381 wktParsed = wktParsed.left( index );
1387 const int openedParenthesisCount = wktParsed.count(
'(' );
1388 const int closedParenthesisCount = wktParsed.count(
')' );
1390 for (
int i = 0 ; i < openedParenthesisCount - closedParenthesisCount; ++i )
1391 wktParsed.push_back(
')' );
1393 wktParsed.truncate( wktParsed.size() - ( closedParenthesisCount - openedParenthesisCount ) );
1395 const thread_local QRegularExpression cooRegEx( QStringLiteral(
"^[^\\(]*\\((.*)\\)[^\\)]*$" ), QRegularExpression::DotMatchesEverythingOption );
1396 const QRegularExpressionMatch match = cooRegEx.match( wktParsed );
1397 contents = match.hasMatch() ? match.captured( 1 ) : QString();
1400 return qMakePair( wkbType, contents );
1407 block.reserve( wkt.size() );
1410 const QChar *wktData = wkt.data();
1411 const int wktLength = wkt.length();
1412 for (
int i = 0, n = wktLength; i < n; ++i, ++wktData )
1414 if ( ( wktData->isSpace() || *wktData ==
'\n' || *wktData ==
'\t' ) && level == 0 )
1417 if ( *wktData ==
',' && level == 0 )
1419 if ( !block.isEmpty() )
1421 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1422 block.prepend( defaultType +
' ' );
1423 blocks.append( block );
1428 if ( *wktData ==
'(' )
1430 else if ( *wktData ==
')' )
1434 if ( !block.isEmpty() )
1436 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1437 block.prepend( defaultType +
' ' );
1438 blocks.append( block );
1446 if ( x <= left && y <= bottom )
1448 const double dx = left - x;
1449 const double dy = bottom - y;
1457 else if ( x >= right && y >= top )
1459 const double dx = x - right;
1460 const double dy = y - top;
1468 else if ( x >= right && y <= bottom )
1470 const double dx = x - right;
1471 const double dy = bottom - y;
1479 else if ( x <= left && y >= top )
1481 const double dx = left - x;
1482 const double dy = y - top;
1490 else if ( x <= left )
1492 else if ( x >= right )
1494 else if ( y <= bottom )
1496 else if ( y >= top )
1500 const double smallestX = std::min( right - x, x - left );
1501 const double smallestY = std::min( top - y, y - bottom );
1502 if ( smallestX < smallestY )
1505 if ( right - x < x - left )
1513 if ( top - y < y - bottom )
1525 const double x = ( pt1.
x() + pt2.
x() ) / 2.0;
1526 const double y = ( pt1.
y() + pt2.
y() ) / 2.0;
1527 double z = std::numeric_limits<double>::quiet_NaN();
1528 double m = std::numeric_limits<double>::quiet_NaN();
1533 z = ( pt1.
z() + pt2.
z() ) / 2.0;
1539 m = ( pt1.
m() + pt2.
m() ) / 2.0;
1542 return QgsPoint( pType, x, y, z, m );
1547 const double _fraction = 1 - fraction;
1549 p1.
x() * _fraction + p2.
x() * fraction,
1550 p1.
y() * _fraction + p2.
y() * fraction,
1551 p1.
is3D() ? p1.
z() * _fraction + p2.
z() * fraction : std::numeric_limits<double>::quiet_NaN(),
1552 p1.
isMeasure() ? p1.
m() * _fraction + p2.
m() * fraction : std::numeric_limits<double>::quiet_NaN() );
1557 const double deltaX = ( x2 - x1 ) * fraction;
1558 const double deltaY = ( y2 - y1 ) * fraction;
1559 return QgsPointXY( x1 + deltaX, y1 + deltaY );
1567 const double fraction = ( value - v1 ) / ( v2 - v1 );
1573 const double delta_x = pt2.
x() - pt1.
x();
1574 const double delta_y = pt2.
y() - pt1.
y();
1580 return delta_y / delta_x;
1599 a = pt1.
y() - pt2.
y();
1600 b = pt2.
x() - pt1.
x();
1601 c = pt1.
x() * pt2.
y() - pt1.
y() * pt2.
x();
1611 if ( ( p == s1 ) || ( p == s2 ) )
1629 const double y = ( -
c - a * p.
x() ) / b;
1630 const double m =
gradient( s1, s2 );
1631 const double d2 = 1 + m * m;
1632 const double H = p.
y() - y;
1633 const double dx = m * H / d2;
1634 const double dy = m * dx;
1644void QgsGeometryUtils::perpendicularCenterSegment(
double pointx,
double pointy,
double segmentPoint1x,
double segmentPoint1y,
double segmentPoint2x,
double segmentPoint2y,
double &perpendicularSegmentPoint1x,
double &perpendicularSegmentPoint1y,
double &perpendicularSegmentPoint2x,
double &perpendicularSegmentPoint2y,
double desiredSegmentLength )
1646 QgsVector segmentVector =
QgsVector( segmentPoint2x - segmentPoint1x, segmentPoint2y - segmentPoint1y );
1648 if ( desiredSegmentLength )
1650 if ( desiredSegmentLength != 0 )
1652 perpendicularVector = perpendicularVector.
normalized() * ( desiredSegmentLength ) / 2;
1655 perpendicularSegmentPoint1x = pointx - perpendicularVector.
x();
1656 perpendicularSegmentPoint1y = pointy - perpendicularVector.
y();
1657 perpendicularSegmentPoint2x = pointx + perpendicularVector.
x();
1658 perpendicularSegmentPoint2y = pointy + perpendicularVector.
y();
1663 const double at = std::atan2( y2 - y1, x2 - x1 );
1664 const double a = -at + M_PI_2;
1670 const double angle1 = std::atan2( y1 - y2, x1 - x2 );
1671 const double angle2 = std::atan2( y3 - y2, x3 - x2 );
1685 const double a1 =
lineAngle( x1, y1, x2, y2 );
1686 const double a2 =
lineAngle( x2, y2, x3, y3 );
1694 double clockwiseDiff = 0.0;
1697 clockwiseDiff = a2 - a1;
1701 clockwiseDiff = a2 + ( 2 * M_PI - a1 );
1703 const double counterClockwiseDiff = 2 * M_PI - clockwiseDiff;
1705 double resultAngle = 0;
1706 if ( clockwiseDiff <= counterClockwiseDiff )
1708 resultAngle = a1 + clockwiseDiff / 2.0;
1712 resultAngle = a1 - counterClockwiseDiff / 2.0;
1723 if ( u3.
length() == 0 )
return 1;
1740 if ( std::fabs( u3.
x() ) <= epsilon &&
1741 std::fabs( u3.
y() ) <= epsilon &&
1742 std::fabs( u3.
z() ) <= epsilon )
1754 if ( !( std::fabs( b1 ) > epsilon ) )
1759 if ( !( a2 != -1 && a2 != 1 ) )
1765 const double r1 = ( c2 - b2 * c1 / b1 ) / ( a2 - b2 * a1 / b1 );
1781 bool isIntersection;
1790 intersection.
set( ptInter.
x(), ptInter.
y(), La1.
z() );
1830 if ( !firstIsDone || !secondIsDone )
1836 intersection = ( X1 + X2 ) / 2.0;
1842 return 0.5 * std::abs( ( aX - cX ) * ( bY - aY ) - ( aX - bX ) * ( cY - aY ) );
1846 double weightB,
double weightC,
double &pointX,
double &pointY )
1849 if ( weightB + weightC > 1 )
1851 weightB = 1 - weightB;
1852 weightC = 1 - weightC;
1855 const double rBx = weightB * ( bX - aX );
1856 const double rBy = weightB * ( bY - aY );
1857 const double rCx = weightC * ( cX - aX );
1858 const double rCy = weightC * ( cY - aY );
1860 pointX = rBx + rCx + aX;
1861 pointY = rBy + rCy + aY;
1868 for (
const QgsPoint &pt : points )
1870 if ( pt.isMeasure() )
1873 point.
setM( pt.m() );
1886 for (
const QgsPoint &pt : points )
1891 point.
setZ( pt.z() );
1910 bool intersection =
false;
1916 return intersection;
1925 const double angle = ( pA.
azimuth( pB ) + pA.
azimuth( pC ) ) / 2.0;
1928 bool intersection =
false;
1934 return intersection;
Abstract base class for all geometries.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
@ MaximumDifference
Maximum distance between an arbitrary point on the original curve and closest point on its approximat...
virtual int vertexCount(int part=0, int ring=0) const =0
Returns the number of vertices of which this geometry is built.
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.
@ XY
X comes before Y (or lon before lat)
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
virtual bool isEmpty() const
Returns true if the geometry is empty.
@ FlagExportNanAsDoubleMin
Use -DOUBLE_MAX to represent NaN (since QGIS 3.30)
virtual double segmentLength(QgsVertexId startVertex) const =0
Returns the length of the segment of the geometry which begins at startVertex.
virtual bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const =0
Returns next vertex id and coordinates.
virtual double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *std::numeric_limits< double >::epsilon()) const =0
Searches for the closest segment of the geometry to a given point.
Curve polygon geometry type.
Abstract base class for curved geometry type.
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 int circleCircleIntersections(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &intersection1, QgsPointXY &intersection2)
Calculates the intersections points between the circle with center center1 and radius radius1 and the...
static bool linesIntersection3D(const QgsVector3D &La1, const QgsVector3D &La2, const QgsVector3D &Lb1, const QgsVector3D &Lb2, QgsVector3D &intersection)
An algorithm to calculate an (approximate) intersection of two lines in 3D.
static QString pointsToJSON(const QgsPointSequence &points, int precision)
Returns a geoJSON coordinates string.
static double sqrDistance2D(const QgsPoint &pt1, const QgsPoint &pt2)
Returns the squared 2D distance between two points.
static QgsPointXY interpolatePointOnLine(double x1, double y1, double x2, double y2, double fraction)
Interpolates the position of a point a fraction of the way along the line from (x1,...
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 double normalizedAngle(double angle)
Ensures that an angle is in the range 0 <= angle < 2 pi.
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance)
Returns a point a specified distance toward a second point.
static double gradient(const QgsPoint &pt1, const QgsPoint &pt2)
Returns the gradient of a line defined by points pt1 and pt2.
static json pointsToJson(const QgsPointSequence &points, int precision)
Returns coordinates as json object.
static double interpolateArcValue(double angle, double a1, double a2, double a3, double zm1, double zm2, double zm3)
Interpolate a value at given angle on circular arc given values (zm1, zm2, zm3) at three different an...
static QVector< QgsLineString * > extractLineStrings(const QgsAbstractGeometry *geom)
Returns list of linestrings extracted from the passed geometry.
static bool lineIntersection(const QgsPoint &p1, QgsVector v1, const QgsPoint &p2, QgsVector v2, QgsPoint &intersection)
Computes the intersection between two lines.
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 QVector< SelfIntersection > selfIntersections(const QgsAbstractGeometry *geom, int part, int ring, double tolerance)
Find self intersections in a polyline.
static bool transferFirstZValueToPoint(const QgsPointSequence &points, QgsPoint &point)
A Z dimension is added to point if one of the point in the list points is in 3D.
static bool segmentMidPoint(const QgsPoint &p1, const QgsPoint &p2, QgsPoint &result, double radius, const QgsPoint &mousePos)
Calculates midpoint on circle passing through p1 and p2, closest to the given coordinate mousePos.
static QgsPointXY interpolatePointOnLineByValue(double x1, double y1, double v1, double x2, double y2, double v2, double value)
Interpolates the position of a point along the line from (x1, y1) to (x2, y2).
static bool segmentIntersection(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false)
Compute the intersection between two segments.
static QgsPoint closestPoint(const QgsAbstractGeometry &geometry, const QgsPoint &point)
Returns the nearest point on a segment of a geometry for the specified point.
static bool circleClockwise(double angle1, double angle2, double angle3)
Returns true if the circle defined by three angles is ordered clockwise.
static double triangleArea(double aX, double aY, double bX, double bY, double cX, double cY)
Returns the area of the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
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 bool verticesAtDistance(const QgsAbstractGeometry &geometry, double distance, QgsVertexId &previousVertex, QgsVertexId &nextVertex)
Retrieves the vertices which are before and after the interpolated point at a specified distance alon...
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType=QString())
Parses a WKT string and returns of list of blocks contained in the WKT.
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 QgsLineString perpendicularSegment(const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2)
Create a perpendicular line segment from p to segment [s1, s2].
static double sqrDistToLine(double ptX, double ptY, double x1, double y1, double x2, double y2, double &minDistX, double &minDistY, double epsilon)
Returns the squared distance between a point and a line.
static int segmentSide(const QgsPoint &pt1, const QgsPoint &pt3, const QgsPoint &pt2)
For line defined by points pt1 and pt3, find out on which side of the line is point pt3.
static void pointsToWKB(QgsWkbPtr &wkb, const QgsPointSequence &points, bool is3D, bool isMeasure, QgsAbstractGeometry::WkbFlags flags)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
static double distanceToVertex(const QgsAbstractGeometry &geom, QgsVertexId id)
Returns the distance along a geometry from its first vertex to the specified vertex.
static void weightedPointInTriangle(double aX, double aY, double bX, double bY, double cX, double cY, double weightB, double weightC, double &pointX, double &pointY)
Returns a weighted point inside the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
static bool lineCircleIntersection(const QgsPointXY ¢er, double radius, const QgsPointXY &linePoint1, const QgsPointXY &linePoint2, QgsPointXY &intersection)
Compute the intersection of a line and a circle.
static double distToInfiniteLine(const QgsPoint &point, const QgsPoint &linePoint1, const QgsPoint &linePoint2, double epsilon=1e-7)
Returns the distance between a point and an infinite line.
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
static void perpendicularOffsetPointAlongSegment(double x1, double y1, double x2, double y2, double proportion, double offset, double *x, double *y)
Calculates a point a certain proportion of the way along the segment from (x1, y1) to (x2,...
static void coefficients(const QgsPoint &pt1, const QgsPoint &pt2, double &a, double &b, double &c)
Returns the coefficients (a, b, c for equation "ax + by + c = 0") of a line defined by points pt1 and...
static double linePerpendicularAngle(double x1, double y1, double x2, double y2)
Calculates the perpendicular angle to a line joining two points.
static bool transferFirstMValueToPoint(const QgsPointSequence &points, QgsPoint &point)
A M dimension is added to point if one of the points in the list points contains an M value.
static QgsPoint midpoint(const QgsPoint &pt1, const QgsPoint &pt2)
Returns a middle point between points pt1 and pt2.
static QgsPoint closestVertex(const QgsAbstractGeometry &geom, const QgsPoint &pt, QgsVertexId &id)
Returns the closest vertex to a geometry for a specified point.
static bool pointContinuesArc(const QgsPoint &a1, const QgsPoint &a2, const QgsPoint &a3, const QgsPoint &b, double distanceTolerance, double pointSpacingAngleTolerance)
Returns true if point b is on the arc formed by points a1, a2, and a3, but not within that arc portio...
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 bool circleAngleBetween(double angle, double angle1, double angle2, bool clockwise)
Returns true if, in a circle, angle is between angle1 and angle2.
static double angleBetweenThreePoints(double x1, double y1, double x2, double y2, double x3, double y3)
Calculates the angle between the lines AB and BC, where AB and BC described by points a,...
static void perpendicularCenterSegment(double centerPointX, double centerPointY, double segmentPoint1x, double segmentPoint1y, double segmentPoint2x, double segmentPoint2y, double &perpendicularSegmentPoint1x, double &perpendicularSegmentPoint1y, double &perpendicularSegmentPoint2x, double &perpendicularSegmentPoint2y, double segmentLength=0)
Create a perpendicular line segment to a given segment [segmentPoint1,segmentPoint2] with its center ...
static bool tangentPointAndCircle(const QgsPointXY ¢er, double radius, const QgsPointXY &p, QgsPointXY &pt1, QgsPointXY &pt2)
Calculates the tangent points between the circle with the specified center and radius and the point p...
static bool bisector(double aX, double aY, double bX, double bY, double cX, double cY, double &pointX, double &pointY)
Returns the point (pointX, pointY) forming the bisector from point (aX, aY) to the segment (bX,...
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 int circleCircleOuterTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2)
Calculates the outer tangent points for two circles, centered at center1 and center2 and with radii o...
static int closestSideOfRectangle(double right, double bottom, double left, double top, double x, double y)
Returns a number representing the closest side of a rectangle defined by /a right,...
static double skewLinesDistance(const QgsVector3D &P1, const QgsVector3D &P12, const QgsVector3D &P2, const QgsVector3D &P22)
An algorithm to calculate the shortest distance between two skew lines.
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 QDomElement pointsToGML2(const QgsPointSequence &points, QDomDocument &doc, int precision, const QString &ns, QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY)
Returns a gml::coordinates DOM element.
static bool transferFirstZOrMValueToPoint(Iterator verticesBegin, Iterator verticesEnd, QgsPoint &point)
A Z or M dimension is added to point if one of the points in the list points contains Z or M value.
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 circleCircleInnerTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2)
Calculates the inner tangent points for two circles, centered at center1 and center2 and with radii o...
static bool angleBisector(double aX, double aY, double bX, double bY, double cX, double cY, double dX, double dY, double &pointX, double &pointY, double &angle)
Returns the point (pointX, pointY) forming the bisector from segment (aX aY) (bX bY) and segment (bX,...
static bool skewLinesProjection(const QgsVector3D &P1, const QgsVector3D &P12, const QgsVector3D &P2, const QgsVector3D &P22, QgsVector3D &X1, double epsilon=0.0001)
A method to project one skew line onto another.
static QString pointsToWKT(const QgsPointSequence &points, int precision, bool is3D, bool isMeasure)
Returns a WKT coordinate list.
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 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 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 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.
Line string geometry type, with support for z-dimension and m-values.
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
A class to represent a 2D point.
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate.
double distance(double x, double y) const
Returns the distance between this point and a specified x, y coordinate.
void set(double x, double y)
Sets the x and y value of the point.
Point geometry type, with support for z-dimension and m-values.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
double azimuth(const QgsPoint &other) const
Calculates Cartesian azimuth between this point and other one (clockwise in degree,...
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
bool convertTo(QgsWkbTypes::Type type) override
Converts the geometry to a specified type.
void setM(double m)
Sets the point's m-value.
bool isEmpty() const override
Returns true if the geometry is empty.
double distance(double x, double y) const
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
void setZ(double z)
Sets the point's z-coordinate.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
static double dotProduct(const QgsVector3D &v1, const QgsVector3D &v2)
Returns the dot product of two vectors.
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.
void set(double x, double y, double z)
Sets vector coordinates.
double length() const
Returns the length of the vector.
A class to represent a vector.
double y() const
Returns the vector's y-component.
QgsVector normalized() const
Returns the vector's normalized (or "unit") vector (ie same angle but length of 1....
QgsVector perpVector() const
Returns the perpendicular vector to this vector (rotated 90 degrees counter-clockwise)
double x() const
Returns the vector's x-component.
double length() const
Returns the length of the vector.
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
Type
The WKB type describes the number of dimensions a geometry has.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
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 qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
const double DEFAULT_SEGMENT_EPSILON
Default snapping tolerance for segments.
QVector< QgsPoint > QgsPointSequence
bool isClockwise(std::array< Direction, 4 > dirs)
Checks whether the 4 directions in dirs make up a clockwise rectangle.
Utility class for identifying a unique vertex within a geometry.
bool isValid() const
Returns true if the vertex id is valid.
Qgis::VertexType type
Vertex type.