27#include <QRegularExpression>
28#include <nlohmann/json.hpp>
32 QVector< QgsLineString * > linestrings;
36 QVector< const QgsAbstractGeometry * > geometries;
38 while ( ! geometries.isEmpty() )
41 if (
const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( g ) )
43 linestrings << static_cast< QgsLineString * >( curve->segmentize() );
45 else if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g ) )
47 for (
int i = 0; i < collection->numGeometries(); ++i )
49 geometries.append( collection->geometryN( i ) );
52 else if (
const QgsCurvePolygon *curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( g ) )
54 if ( curvePolygon->exteriorRing() )
55 linestrings << static_cast< QgsLineString * >( curvePolygon->exteriorRing()->segmentize() );
57 for (
int i = 0; i < curvePolygon->numInteriorRings(); ++i )
59 linestrings << static_cast< QgsLineString * >( curvePolygon->interiorRing( i )->segmentize() );
68 double minDist = std::numeric_limits<double>::max();
69 double currentDist = 0;
86 if ( currentDist <= minDist )
88 minDist = currentDist;
89 minDistPoint = vertex;
90 id.part = vertexId.
part;
91 id.ring = vertexId.
ring;
92 id.vertex = vertexId.
vertex;
93 id.type = vertexId.
type;
108 if ( vertexAfter.
vertex > 0 )
113 const double length = pointBefore.
distance( pointAfter );
135 double currentDist = 0;
140 if ( vertexId ==
id )
154 double currentDist = 0;
164 nextVertex = previousVertex;
169 while ( currentDist < distance && geometry.
nextVertex( nextVertex, point ) )
171 if ( !first && nextVertex.
part == previousVertex.
part && nextVertex.
ring == previousVertex.
ring )
179 previousVertex = nextVertex;
183 if ( currentDist > distance )
188 previousVertex = nextVertex;
189 previousPoint = point;
199 return ( pt1.
x() - pt2.
x() ) * ( pt1.
x() - pt2.
x() ) + ( pt1.
y() - pt2.
y() ) * ( pt1.
y() - pt2.
y() );
212 const double t = ( ( ptX - x1 ) * dx + ( ptY - y1 ) * dy ) / ( dx * dx + dy * dy );
228 const double dist = dx * dx + dy * dy;
243 const double area = std::abs(
244 ( linePoint1.
x() - linePoint2.
x() ) * ( point.
y() - linePoint2.
y() ) -
245 ( linePoint1.
y() - linePoint2.
y() ) * ( point.
x() - linePoint2.
x() )
248 const double length = std::sqrt(
249 std::pow( linePoint1.
x() - linePoint2.
x(), 2 ) +
250 std::pow( linePoint1.
y() - linePoint2.
y(), 2 )
253 const double distance = area / length;
254 return qgsDoubleNear( distance, 0.0, epsilon ) ? 0.0 : distance;
259 const double d = v1.
y() * v2.
x() - v1.
x() * v2.
y();
264 const double dx = p2.
x() - p1.
x();
265 const double dy = p2.
y() - p1.
y();
266 const double k = ( dy * v2.
x() - dx * v2.
y() ) / d;
268 intersection =
QgsPoint( p1.
x() + v1.
x() * k, p1.
y() + v1.
y() * k );
278 isIntersection =
false;
282 const double vl = v.
length();
283 const double wl = w.
length();
297 isIntersection =
true;
298 if ( acceptImproperIntersection )
300 if ( ( p1 == q1 ) || ( p1 == q2 ) )
302 intersectionPoint = p1;
305 else if ( ( p2 == q1 ) || ( p2 == q2 ) )
307 intersectionPoint = p2;
314 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( p1.
x(), p1.
y(), q1.
x(), q1.
y(), q2.
x(), q2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
316 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( p2.
x(), p2.
y(), q1.
x(), q1.
y(), q2.
x(), q2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
318 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( q1.
x(), q1.
y(), p1.
x(), p1.
y(), p2.
x(), p2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
320 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( q2.
x(), q2.
y(), p1.
x(), p1.
y(), p2.
x(), p2.
y(), x, y, tolerance ), 0.0, tolerance )
327 const double lambdav =
QgsVector( intersectionPoint.
x() - p1.
x(), intersectionPoint.
y() - p1.
y() ) * v;
328 if ( lambdav < 0. + tolerance || lambdav > vl - tolerance )
331 const double lambdaw =
QgsVector( intersectionPoint.
x() - q1.
x(), intersectionPoint.
y() - q1.
y() ) * w;
332 return !( lambdaw < 0. + tolerance || lambdaw >= wl - tolerance );
342 const double x1 = linePoint1.
x() - center.
x();
343 const double y1 = linePoint1.
y() - center.
y();
344 const double x2 = linePoint2.
x() - center.
x();
345 const double y2 = linePoint2.
y() - center.
y();
346 const double dx = x2 - x1;
347 const double dy = y2 - y1;
349 const double dr2 = std::pow( dx, 2 ) + std::pow( dy, 2 );
350 const double d = x1 * y2 - x2 * y1;
352 const double disc = std::pow( radius, 2 ) * dr2 - std::pow( d, 2 );
362 const int sgnDy = dy < 0 ? -1 : 1;
364 const double sqrDisc = std::sqrt( disc );
366 const double ax = center.
x() + ( d * dy + sgnDy * dx * sqrDisc ) / dr2;
367 const double ay = center.
y() + ( -d * dx + std::fabs( dy ) * sqrDisc ) / dr2;
370 const double bx = center.
x() + ( d * dy - sgnDy * dx * sqrDisc ) / dr2;
371 const double by = center.
y() + ( -d * dx - std::fabs( dy ) * sqrDisc ) / dr2;
378 intersection.
set( p1.
x(), p1.
y() );
382 intersection.
set( p2.
x(), p2.
y() );
393 const double d = center1.
distance( center2 );
396 if ( d > ( r1 + r2 ) )
401 else if ( d < std::fabs( r1 - r2 ) )
418 const double a = ( ( r1 * r1 ) - ( r2 * r2 ) + ( d * d ) ) / ( 2.0 * d ) ;
423 const double dx = center2.
x() - center1.
x();
424 const double dy = center2.
y() - center1.
y();
427 const double x2 = center1.
x() + ( dx * a / d );
428 const double y2 = center1.
y() + ( dy * a / d );
433 const double h = std::sqrt( ( r1 * r1 ) - ( a * a ) );
438 const double rx = dy * ( h / d );
439 const double ry = dx * ( h / d );
442 intersection1 =
QgsPointXY( x2 + rx, y2 - ry );
443 intersection2 =
QgsPointXY( x2 - rx, y2 + ry );
457 const double dx = center.
x() - p.
x();
458 const double dy = center.
y() - p.
y();
459 const double distanceSquared = dx * dx + dy * dy;
460 const double radiusSquared = radius * radius;
461 if ( distanceSquared < radiusSquared )
468 const double distanceToTangent = std::sqrt( distanceSquared - radiusSquared );
480 if ( radius1 > radius2 )
483 const double radius2a = radius2 - radius1;
492 QgsVector v1( -( line1P2.
y() - center1.
y() ), line1P2.
x() - center1.
x() );
493 const double v1Length = v1.
length();
494 v1 = v1 * ( radius1 / v1Length );
497 line1P1 = center1 + v1;
498 line1P2 = line1P2 + v1;
502 QgsVector v2( line2P2.
y() - center1.
y(), -( line2P2.
x() - center1.
x() ) );
503 const double v2Length = v2.
length();
504 v2 = v2 * ( radius1 / v2Length );
507 line2P1 = center1 + v2;
508 line2P2 = line2P2 + v2;
516 if ( radius1 > radius2 )
520 const double d = center1.
distance( center2 );
521 const double radius1a = radius1 + radius2;
538 QgsVector v1( ( line1P2.
y() - center2.
y() ), -( line1P2.
x() - center2.
x() ) );
539 const double v1Length = v1.
length();
540 v1 = v1 * ( radius2 / v1Length );
543 line1P1 = center2 + v1;
544 line1P2 = line1P2 + v1;
548 QgsVector v2( -( line2P2.
y() - center2.
y() ), line2P2.
x() - center2.
x() );
549 const double v2Length = v2.
length();
550 v2 = v2 * ( radius2 / v2Length );
553 line2P1 = center2 + v2;
554 line2P2 = line2P2 + v2;
561 QVector<SelfIntersection> intersections;
567 for (
int i = 0, j = 1; j < n; i = j++ )
574 const int start = j + 1;
575 const int end = i == 0 && isClosed ? n - 1 : n;
576 for (
int k = start, l = start + 1; l < end; k = l++ )
582 bool intersection =
false;
593 intersections.append( s );
596 return intersections;
606 const double f1 = x - x1;
607 const double f2 = y2 - y1;
608 const double f3 = y - y1;
609 const double f4 = x2 - x1;
610 const double test = ( f1 * f2 - f3 * f4 );
612 return qgsDoubleNear( test, 0.0 ) ? 0 : ( test < 0 ? -1 : 1 );
622void 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 )
624 const double dx = x2 - x1;
625 const double dy = y2 - y1;
626 const double length = std::sqrt( dx * dx + dy * dy );
639 const double scaleFactor = distance / length;
640 x = x1 + dx * scaleFactor;
641 y = y1 + dy * scaleFactor;
643 *z = *z1 + ( *z2 - *z1 ) * scaleFactor;
645 *m = *m1 + ( *m2 - *m1 ) * scaleFactor;
652 const double mX = x1 + ( x2 - x1 ) * proportion;
653 const double mY = y1 + ( y2 - y1 ) * proportion;
654 const double pX = x1 - x2;
655 const double pY = y1 - y2;
656 double normalX = -pY;
658 const double normalLength = sqrt( ( normalX * normalX ) + ( normalY * normalY ) );
659 normalX /= normalLength;
660 normalY /= normalLength;
662 *x = mX + offset * normalX;
663 *y = mY + offset * normalY;
668 double centerX, centerY, radius;
671 const double theta = distance / radius;
672 const double anglePt1 = std::atan2( pt1.
y() - centerY, pt1.
x() - centerX );
673 const double anglePt2 = std::atan2( pt2.
y() - centerY, pt2.
x() - centerX );
674 const double anglePt3 = std::atan2( pt3.
y() - centerY, pt3.
x() - centerX );
676 const double angleDest = anglePt1 + (
isClockwise ? -theta : theta );
678 const double x = centerX + radius * ( std::cos( angleDest ) );
679 const double y = centerY + radius * ( std::sin( angleDest ) );
681 const double z = pt1.
is3D() ?
693 const double angle = std::atan2( dy, dx ) * 180 / M_PI;
698 else if (
angle > 360 )
707 double dx21, dy21, dx31, dy31, h21, h31, d;
712 centerX = ( pt1.
x() + pt2.
x() ) / 2.0;
713 centerY = ( pt1.
y() + pt2.
y() ) / 2.0;
714 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
719 dx21 = pt2.
x() - pt1.
x();
720 dy21 = pt2.
y() - pt1.
y();
721 dx31 = pt3.
x() - pt1.
x();
722 dy31 = pt3.
y() - pt1.
y();
724 h21 = std::pow( dx21, 2.0 ) + std::pow( dy21, 2.0 );
725 h31 = std::pow( dx31, 2.0 ) + std::pow( dy31, 2.0 );
728 d = 2 * ( dx21 * dy31 - dx31 * dy21 );
738 centerX = pt1.
x() + ( h21 * dy31 - h31 * dy21 ) / d;
739 centerY = pt1.
y() - ( h21 * dx31 - h31 * dx21 ) / d;
740 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
745 if ( angle3 >= angle1 )
747 return !( angle2 > angle1 && angle2 < angle3 );
751 return !( angle2 > angle1 || angle2 < angle3 );
759 if ( angle2 < angle1 )
761 return ( angle <= angle1 && angle >= angle2 );
765 return ( angle <= angle1 || angle >= angle2 );
770 if ( angle2 > angle1 )
772 return (
angle >= angle1 &&
angle <= angle2 );
776 return (
angle >= angle1 ||
angle <= angle2 );
789 double centerX, centerY, radius;
791 double length = M_PI / 180.0 * radius *
sweepAngle( centerX, centerY, x1, y1, x2, y2, x3, y3 );
805 if ( p3Angle >= p1Angle )
807 if ( p2Angle > p1Angle && p2Angle < p3Angle )
809 return ( p3Angle - p1Angle );
813 return ( - ( p1Angle + ( 360 - p3Angle ) ) );
818 if ( p2Angle < p1Angle && p2Angle > p3Angle )
820 return ( -( p1Angle - p3Angle ) );
824 return ( p3Angle + ( 360 - p1Angle ) );
831 const QgsPoint midPoint( ( p1.
x() + p2.
x() ) / 2.0, ( p1.
y() + p2.
y() ) / 2.0 );
832 const double midDist = std::sqrt(
sqrDistance2D( p1, midPoint ) );
833 if ( radius < midDist )
837 const double centerMidDist = std::sqrt( radius * radius - midDist * midDist );
838 const double dist = radius - centerMidDist;
840 const double midDx = midPoint.
x() - p1.
x();
841 const double midDy = midPoint.
y() - p1.
y();
844 QVector<QgsPoint> possibleMidPoints;
851 double minDist = std::numeric_limits<double>::max();
852 int minDistIndex = -1;
853 for (
int i = 0; i < possibleMidPoints.size(); ++i )
855 const double currentDist =
sqrDistance2D( mousePos, possibleMidPoints.at( i ) );
856 if ( currentDist < minDist )
859 minDist = currentDist;
863 if ( minDistIndex == -1 )
868 result = possibleMidPoints.at( minDistIndex );
880 if ( !useShortestArc )
881 midPointAngle += M_PI;
882 return center.
project( center.
distance( p1 ), midPointAngle * 180 / M_PI );
889 double mX, mY, radius;
922 const double bDistance = std::sqrt( ( b.
x() - centerX ) * ( b.
x() - centerX ) +
923 ( b.
y() - centerY ) * ( b.
y() - centerY ) );
925 double diff = std::fabs( radius - bDistance );
929 const double abX = b.
x() - a.
x();
930 const double abY = b.
y() - a.
y();
932 const double cbX = b.
x() -
c.x();
933 const double cbY = b.
y() -
c.y();
935 const double dot = ( abX * cbX + abY * cbY );
936 const double cross = ( abX * cbY - abY * cbX );
938 const double alpha = std::atan2( cross, dot );
944 if ( diff < distanceTolerance )
946 const double angle1 = arcAngle( a1, a2, a3 );
947 const double angle2 = arcAngle( a2, a3, b );
952 diff = std::fabs( angle1 - angle2 );
953 if ( diff > pointSpacingAngleTolerance )
958 const int a2Side =
leftOfLine( a2.
x(), a2.
y(), a1.
x(), a1.
y(), a3.
x(), a3.
y() );
959 const int bSide =
leftOfLine( b.
x(), b.
y(), a1.
x(), a1.
y(), a3.
x(), a3.
y() );
963 if ( bSide != a2Side )
971 bool reversed =
false;
995 circleCenterRadius( circlePoint1, circlePoint2, circlePoint3, radius, centerX, centerY );
997 if ( circlePoint1 != circlePoint3 && ( radius < 0 ||
qgsDoubleNear( segSide, 0.0 ) ) )
1000 points.append( p2 );
1001 points.append( p3 );
1005 double increment = tolerance;
1009 tolerance = std::min( tolerance, radius * 2 );
1010 const double halfAngle = std::acos( -tolerance / radius + 1 );
1011 increment = 2 * halfAngle;
1015 const double a1 = std::atan2( circlePoint1.
y() - centerY, circlePoint1.
x() - centerX );
1016 double a2 = std::atan2( circlePoint2.
y() - centerY, circlePoint2.
x() - centerX );
1017 double a3 = std::atan2( circlePoint3.
y() - centerY, circlePoint3.
x() - centerX );
1020 const bool symmetric =
true;
1023 double angle = a3 - a1;
1028 const int segs = ceil(
angle / increment );
1030 increment =
angle / segs;
1044 QVector<QgsPoint> stringPoints;
1045 stringPoints.insert( 0, circlePoint1 );
1046 if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 )
1060 const double tolError = increment / 100;
1061 const double stopAngle = a3 - tolError;
1062 for (
double angle = a1 + increment;
angle < stopAngle;
angle += increment )
1064 x = centerX + radius * std::cos(
angle );
1065 y = centerY + radius * std::sin(
angle );
1076 stringPoints.insert( stringPoints.size(),
QgsPoint( pointWkbType, x, y, z, m ) );
1079 stringPoints.insert( stringPoints.size(), circlePoint3 );
1084 std::reverse( stringPoints.begin(), stringPoints.end() );
1086 if ( ! points.empty() && stringPoints.front() == points.back() ) stringPoints.pop_front();
1087 points.append( stringPoints );
1092 const double side = ( ( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
1117 return zm1 + ( zm2 - zm1 ) * (
angle - a1 ) / ( a2 - a1 );
1119 return zm2 + ( zm3 - zm2 ) * (
angle - a2 ) / ( a3 - a2 );
1125 return zm1 + ( zm2 - zm1 ) * ( a1 -
angle ) / ( a1 - a2 );
1127 return zm2 + ( zm3 - zm2 ) * ( a2 -
angle ) / ( a2 - a3 );
1133 const int dim = 2 + is3D + isMeasure;
1136#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1137 const QStringList coordList = wktCoordinateList.split(
',', QString::SkipEmptyParts );
1139 const QStringList coordList = wktCoordinateList.split(
',', Qt::SkipEmptyParts );
1143 bool foundZ =
false;
1144 bool foundM =
false;
1145 const thread_local QRegularExpression rx( QStringLiteral(
"\\s" ) );
1146 const thread_local QRegularExpression rxIsNumber( QStringLiteral(
"^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$" ) );
1147 for (
const QString &pointCoordinates : coordList )
1149#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1150 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1152 const QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
1156 if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() )
1159 if ( coordinates.size() == 3 && !foundZ && !foundM && !is3D && !isMeasure )
1165 else if ( coordinates.size() >= 4 && ( !( is3D || foundZ ) || !( isMeasure || foundM ) ) )
1174 for (
const QString &pointCoordinates : coordList )
1176#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1177 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1179 QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
1181 if ( coordinates.size() < dim )
1185 const double x = coordinates[idx++].toDouble();
1186 const double y = coordinates[idx++].toDouble();
1189 if ( ( is3D || foundZ ) && coordinates.length() > idx )
1190 z = coordinates[idx++].toDouble();
1193 if ( ( isMeasure || foundM ) && coordinates.length() > idx )
1194 m = coordinates[idx++].toDouble();
1197 if ( is3D || foundZ )
1199 if ( isMeasure || foundM )
1206 if ( isMeasure || foundM )
1212 points.append(
QgsPoint( t, x, y, z, m ) );
1220 wkb << static_cast<quint32>( points.size() );
1221 for (
const QgsPoint &point : points )
1223 wkb << point.x() << point.y();
1226 double z = point.z();
1228 && std::isnan( z ) )
1229 z = -std::numeric_limits<double>::max();
1235 double m = point.m();
1237 && std::isnan( m ) )
1238 m = -std::numeric_limits<double>::max();
1247 QString wkt = QStringLiteral(
"(" );
1256 wkt += QLatin1String(
", " );
1258 if ( wkt.endsWith( QLatin1String(
", " ) ) )
1266 QDomElement elemCoordinates = doc.createElementNS( ns, QStringLiteral(
"coordinates" ) );
1269 const QString cs = QStringLiteral(
"," );
1271 const QString ts = QStringLiteral(
" " );
1273 elemCoordinates.setAttribute( QStringLiteral(
"cs" ), cs );
1274 elemCoordinates.setAttribute( QStringLiteral(
"ts" ), ts );
1276 QString strCoordinates;
1279 if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
1284 if ( strCoordinates.endsWith( ts ) )
1285 strCoordinates.chop( 1 );
1287 elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
1288 return elemCoordinates;
1293 QDomElement elemPosList = doc.createElementNS( ns, QStringLiteral(
"posList" ) );
1294 elemPosList.setAttribute( QStringLiteral(
"srsDimension" ), is3D ? 3 : 2 );
1296 QString strCoordinates;
1299 if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
1306 if ( strCoordinates.endsWith(
' ' ) )
1307 strCoordinates.chop( 1 );
1309 elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
1315 QString json = QStringLiteral(
"[ " );
1320 if ( json.endsWith( QLatin1String(
", " ) ) )
1331 json coordinates( json::array() );
1348 double clippedAngle =
angle;
1349 if ( clippedAngle >= M_PI * 2 || clippedAngle <= -2 * M_PI )
1351 clippedAngle = std::fmod( clippedAngle, 2 * M_PI );
1353 if ( clippedAngle < 0.0 )
1355 clippedAngle += 2 * M_PI;
1357 return clippedAngle;
1362 QString wktParsed = wkt;
1364 if ( wkt.contains( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) )
1366 const thread_local QRegularExpression sWktRegEx( QStringLiteral(
"^\\s*(\\w+)\\s+(\\w+)\\s*$" ), QRegularExpression::DotMatchesEverythingOption );
1367 const QRegularExpressionMatch match = sWktRegEx.match( wkt );
1368 if ( match.hasMatch() )
1370 wktParsed = match.captured( 1 );
1371 contents = match.captured( 2 ).toUpper();
1376 const int openedParenthesisCount = wktParsed.count(
'(' );
1377 const int closedParenthesisCount = wktParsed.count(
')' );
1379 for (
int i = 0 ; i < openedParenthesisCount - closedParenthesisCount; ++i )
1380 wktParsed.push_back(
')' );
1382 wktParsed.truncate( wktParsed.size() - ( closedParenthesisCount - openedParenthesisCount ) );
1384 const thread_local QRegularExpression cooRegEx( QStringLiteral(
"^[^\\(]*\\((.*)\\)[^\\)]*$" ), QRegularExpression::DotMatchesEverythingOption );
1385 const QRegularExpressionMatch match = cooRegEx.match( wktParsed );
1386 contents = match.hasMatch() ? match.captured( 1 ) : QString();
1389 return qMakePair( wkbType, contents );
1396 block.reserve( wkt.size() );
1399 const QChar *wktData = wkt.data();
1400 const int wktLength = wkt.length();
1401 for (
int i = 0, n = wktLength; i < n; ++i, ++wktData )
1403 if ( ( wktData->isSpace() || *wktData ==
'\n' || *wktData ==
'\t' ) && level == 0 )
1406 if ( *wktData ==
',' && level == 0 )
1408 if ( !block.isEmpty() )
1410 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1411 block.prepend( defaultType +
' ' );
1412 blocks.append( block );
1417 if ( *wktData ==
'(' )
1419 else if ( *wktData ==
')' )
1423 if ( !block.isEmpty() )
1425 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1426 block.prepend( defaultType +
' ' );
1427 blocks.append( block );
1435 if ( x <= left && y <= bottom )
1437 const double dx = left - x;
1438 const double dy = bottom - y;
1446 else if ( x >= right && y >= top )
1448 const double dx = x - right;
1449 const double dy = y - top;
1457 else if ( x >= right && y <= bottom )
1459 const double dx = x - right;
1460 const double dy = bottom - y;
1468 else if ( x <= left && y >= top )
1470 const double dx = left - x;
1471 const double dy = y - top;
1479 else if ( x <= left )
1481 else if ( x >= right )
1483 else if ( y <= bottom )
1485 else if ( y >= top )
1489 const double smallestX = std::min( right - x, x - left );
1490 const double smallestY = std::min( top - y, y - bottom );
1491 if ( smallestX < smallestY )
1494 if ( right - x < x - left )
1502 if ( top - y < y - bottom )
1514 const double x = ( pt1.
x() + pt2.
x() ) / 2.0;
1515 const double y = ( pt1.
y() + pt2.
y() ) / 2.0;
1516 double z = std::numeric_limits<double>::quiet_NaN();
1517 double m = std::numeric_limits<double>::quiet_NaN();
1522 z = ( pt1.
z() + pt2.
z() ) / 2.0;
1528 m = ( pt1.
m() + pt2.
m() ) / 2.0;
1531 return QgsPoint( pType, x, y, z, m );
1536 const double _fraction = 1 - fraction;
1538 p1.
x() * _fraction + p2.
x() * fraction,
1539 p1.
y() * _fraction + p2.
y() * fraction,
1540 p1.
is3D() ? p1.
z() * _fraction + p2.
z() * fraction : std::numeric_limits<double>::quiet_NaN(),
1541 p1.
isMeasure() ? p1.
m() * _fraction + p2.
m() * fraction : std::numeric_limits<double>::quiet_NaN() );
1546 const double deltaX = ( x2 - x1 ) * fraction;
1547 const double deltaY = ( y2 - y1 ) * fraction;
1548 return QgsPointXY( x1 + deltaX, y1 + deltaY );
1556 const double fraction = ( value - v1 ) / ( v2 - v1 );
1562 const double delta_x = pt2.
x() - pt1.
x();
1563 const double delta_y = pt2.
y() - pt1.
y();
1569 return delta_y / delta_x;
1588 a = pt1.
y() - pt2.
y();
1589 b = pt2.
x() - pt1.
x();
1590 c = pt1.
x() * pt2.
y() - pt1.
y() * pt2.
x();
1600 if ( ( p == s1 ) || ( p == s2 ) )
1618 const double y = ( -
c - a * p.
x() ) / b;
1619 const double m =
gradient( s1, s2 );
1620 const double d2 = 1 + m * m;
1621 const double H = p.
y() - y;
1622 const double dx = m * H / d2;
1623 const double dy = m * dx;
1633void QgsGeometryUtils::perpendicularCenterSegment(
double pointx,
double pointy,
double segmentPoint1x,
double segmentPoint1y,
double segmentPoint2x,
double segmentPoint2y,
double &perpendicularSegmentPoint1x,
double &perpendicularSegmentPoint1y,
double &perpendicularSegmentPoint2x,
double &perpendicularSegmentPoint2y,
double desiredSegmentLength )
1635 QgsVector segmentVector =
QgsVector( segmentPoint2x - segmentPoint1x, segmentPoint2y - segmentPoint1y );
1637 if ( desiredSegmentLength )
1639 if ( desiredSegmentLength != 0 )
1641 perpendicularVector = perpendicularVector.
normalized() * ( desiredSegmentLength ) / 2;
1644 perpendicularSegmentPoint1x = pointx - perpendicularVector.
x();
1645 perpendicularSegmentPoint1y = pointy - perpendicularVector.
y();
1646 perpendicularSegmentPoint2x = pointx + perpendicularVector.
x();
1647 perpendicularSegmentPoint2y = pointy + perpendicularVector.
y();
1652 const double at = std::atan2( y2 - y1, x2 - x1 );
1653 const double a = -at + M_PI_2;
1659 const double angle1 = std::atan2( y1 - y2, x1 - x2 );
1660 const double angle2 = std::atan2( y3 - y2, x3 - x2 );
1674 const double a1 =
lineAngle( x1, y1, x2, y2 );
1675 const double a2 =
lineAngle( x2, y2, x3, y3 );
1683 double clockwiseDiff = 0.0;
1686 clockwiseDiff = a2 - a1;
1690 clockwiseDiff = a2 + ( 2 * M_PI - a1 );
1692 const double counterClockwiseDiff = 2 * M_PI - clockwiseDiff;
1694 double resultAngle = 0;
1695 if ( clockwiseDiff <= counterClockwiseDiff )
1697 resultAngle = a1 + clockwiseDiff / 2.0;
1701 resultAngle = a1 - counterClockwiseDiff / 2.0;
1712 if ( u3.
length() == 0 )
return 1;
1729 if ( std::fabs( u3.
x() ) <= epsilon &&
1730 std::fabs( u3.
y() ) <= epsilon &&
1731 std::fabs( u3.
z() ) <= epsilon )
1743 if ( !( std::fabs( b1 ) > epsilon ) )
1748 if ( !( a2 != -1 && a2 != 1 ) )
1754 const double r1 = ( c2 - b2 * c1 / b1 ) / ( a2 - b2 * a1 / b1 );
1770 bool isIntersection;
1779 intersection.
set( ptInter.
x(), ptInter.
y(), La1.
z() );
1819 if ( !firstIsDone || !secondIsDone )
1825 intersection = ( X1 + X2 ) / 2.0;
1831 return 0.5 * std::abs( ( aX - cX ) * ( bY - aY ) - ( aX - bX ) * ( cY - aY ) );
1835 double weightB,
double weightC,
double &pointX,
double &pointY )
1838 if ( weightB + weightC > 1 )
1840 weightB = 1 - weightB;
1841 weightC = 1 - weightC;
1844 const double rBx = weightB * ( bX - aX );
1845 const double rBy = weightB * ( bY - aY );
1846 const double rCx = weightC * ( cX - aX );
1847 const double rCy = weightC * ( cY - aY );
1849 pointX = rBx + rCx + aX;
1850 pointY = rBy + rCy + aY;
1857 for (
const QgsPoint &pt : points )
1859 if ( pt.isMeasure() )
1862 point.
setM( pt.m() );
1875 for (
const QgsPoint &pt : points )
1880 point.
setZ( pt.z() );
1899 bool intersection =
false;
1905 return intersection;
1917 bool intersection =
false;
1923 return intersection;
WkbType
The WKB type describes the number of dimensions a geometry has.
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...
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
virtual int vertexCount(int part=0, int ring=0) const =0
Returns the number of vertices of which this geometry is built.
AxisOrder
Axis order for GML generation.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual bool isEmpty() const
Returns true if the geometry is empty.
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
@ 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.
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
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 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 QString pointsToJSON(const QgsPointSequence &points, int precision)
Returns a geoJSON coordinates string.
static QgsPoint midpoint(const QgsPoint &pt1, const QgsPoint &pt2) SIP_HOLDGIL
Returns a middle point between points pt1 and pt2.
static bool bisector(double aX, double aY, double bX, double bY, double cX, double cY, double &pointX, double &pointY) SIP_HOLDGIL
Returns the point (pointX, pointY) forming the bisector from point (aX, aY) to the segment (bX,...
static double sqrDistance2D(const QgsPoint &pt1, const QgsPoint &pt2) SIP_HOLDGIL
Returns the squared 2D distance between two points.
static bool skewLinesProjection(const QgsVector3D &P1, const QgsVector3D &P12, const QgsVector3D &P2, const QgsVector3D &P22, QgsVector3D &X1, double epsilon=0.0001) SIP_HOLDGIL
A method to project one skew line onto another.
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 double triangleArea(double aX, double aY, double bX, double bY, double cX, double cY) SIP_HOLDGIL
Returns the area of the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
static bool segmentMidPoint(const QgsPoint &p1, const QgsPoint &p2, QgsPoint &result, double radius, const QgsPoint &mousePos) SIP_HOLDGIL
Calculates midpoint on circle passing through p1 and p2, closest to the given coordinate mousePos.
static json pointsToJson(const QgsPointSequence &points, int precision)
Returns coordinates as json object.
static int circleCircleInnerTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2) SIP_HOLDGIL
Calculates the inner tangent points for two circles, centered at center1 and center2 and with radii o...
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) SIP_HOLDGIL
Computes the intersection between two lines.
static double normalizedAngle(double angle) SIP_HOLDGIL
Ensures that an angle is in the range 0 <= angle < 2 pi.
static QgsPointXY interpolatePointOnLineByValue(double x1, double y1, double v1, double x2, double y2, double v2, double value) SIP_HOLDGIL
Interpolates the position of a point along the line from (x1, y1) to (x2, y2).
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 QgsPoint closestPoint(const QgsAbstractGeometry &geometry, const QgsPoint &point)
Returns the nearest point on a segment of a geometry for the specified point.
static int segmentSide(const QgsPoint &pt1, const QgsPoint &pt3, const QgsPoint &pt2) SIP_HOLDGIL
For line defined by points pt1 and pt3, find out on which side of the line is point 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 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) SIP_HOLDGIL
Create a perpendicular line segment to a given segment [segmentPoint1,segmentPoint2] with its center ...
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 bool lineCircleIntersection(const QgsPointXY ¢er, double radius, const QgsPointXY &linePoint1, const QgsPointXY &linePoint2, QgsPointXY &intersection) SIP_HOLDGIL
Compute the intersection of a line and a circle.
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) SIP_HOLDGIL
Compute the intersection between two segments.
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 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 QPair< Qgis::WkbType, 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 skewLinesDistance(const QgsVector3D &P1, const QgsVector3D &P12, const QgsVector3D &P2, const QgsVector3D &P22) SIP_HOLDGIL
An algorithm to calculate the shortest distance between two skew lines.
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 double lineAngle(double x1, double y1, double x2, double y2) SIP_HOLDGIL
Calculates the direction of line joining two points in radians, clockwise from the north direction.
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 sqrDistToLine(double ptX, double ptY, double x1, double y1, double x2, double y2, double &minDistX, double &minDistY, double epsilon) SIP_HOLDGIL
Returns the squared distance between a point and a line.
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 bool circleClockwise(double angle1, double angle2, double angle3) SIP_HOLDGIL
Returns true if the circle defined by three angles is ordered clockwise.
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) SIP_HOLDGIL
Returns the point (pointX, pointY) forming the bisector from segment (aX aY) (bX bY) and segment (bX,...
static int circleCircleOuterTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2) SIP_HOLDGIL
Calculates the outer tangent points for two circles, centered at center1 and center2 and with radii o...
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 double gradient(const QgsPoint &pt1, const QgsPoint &pt2) SIP_HOLDGIL
Returns the gradient of a line defined by points pt1 and pt2.
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 angleBetweenThreePoints(double x1, double y1, double x2, double y2, double x3, double y3) SIP_HOLDGIL
Calculates the angle between the lines AB and BC, where AB and BC described by points a,...
static QgsPoint closestVertex(const QgsAbstractGeometry &geom, const QgsPoint &pt, QgsVertexId &id)
Returns the closest vertex to a geometry for a specified point.
static double interpolateArcValue(double angle, double a1, double a2, double a3, double zm1, double zm2, double zm3) SIP_HOLDGIL
Interpolate a value at given angle on circular arc given values (zm1, zm2, zm3) at three different an...
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 QgsLineString perpendicularSegment(const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2) SIP_HOLDGIL
Create a perpendicular line segment from p to segment [s1, s2].
static int circleCircleIntersections(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &intersection1, QgsPointXY &intersection2) SIP_HOLDGIL
Calculates the intersections points between the circle with center center1 and radius radius1 and the...
static void coefficients(const QgsPoint &pt1, const QgsPoint &pt2, double &a, double &b, double &c) SIP_HOLDGIL
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) SIP_HOLDGIL
Calculates the perpendicular angle to a line joining two points.
static bool tangentPointAndCircle(const QgsPointXY ¢er, double radius, const QgsPointXY &p, QgsPointXY &pt1, QgsPointXY &pt2) SIP_HOLDGIL
Calculates the tangent points between the circle with the specified center and radius and the point p...
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance) SIP_HOLDGIL
Returns a point a specified distance toward a second point.
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 bool pointContinuesArc(const QgsPoint &a1, const QgsPoint &a2, const QgsPoint &a3, const QgsPoint &b, double distanceTolerance, double pointSpacingAngleTolerance) SIP_HOLDGIL
Returns true if point b is on the arc formed by points a1, a2, and a3, but not within that arc portio...
static void weightedPointInTriangle(double aX, double aY, double bX, double bY, double cX, double cY, double weightB, double weightC, double &pointX, double &pointY) SIP_HOLDGIL
Returns a weighted point inside the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
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 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 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 bool linesIntersection3D(const QgsVector3D &La1, const QgsVector3D &La2, const QgsVector3D &Lb1, const QgsVector3D &Lb2, QgsVector3D &intersection) SIP_HOLDGIL
An algorithm to calculate an (approximate) intersection of two lines in 3D.
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.
static QgsPointXY interpolatePointOnLine(double x1, double y1, double x2, double y2, double fraction) SIP_HOLDGIL
Interpolates the position of a point a fraction of the way along the line from (x1,...
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.
void set(double x, double y) SIP_HOLDGIL
Sets the x and y value of the point.
double sqrDist(double x, double y) const SIP_HOLDGIL
Returns the squared distance between this point a specified x, y coordinate.
double distance(double x, double y) const SIP_HOLDGIL
Returns the distance between this point and a specified x, y coordinate.
Point geometry type, with support for z-dimension and m-values.
double distance(double x, double y) const SIP_HOLDGIL
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const SIP_HOLDGIL
Returns a new point which corresponds to this point projected by a specified distance with specified ...
void setZ(double z) SIP_HOLDGIL
Sets the point's z-coordinate.
bool convertTo(Qgis::WkbType type) override
Converts the geometry to a specified type.
double azimuth(const QgsPoint &other) const SIP_HOLDGIL
Calculates Cartesian azimuth between this point and other one (clockwise in degree,...
void setM(double m) SIP_HOLDGIL
Sets the point's m-value.
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.
QgsVector perpVector() const SIP_HOLDGIL
Returns the perpendicular vector to this vector (rotated 90 degrees counter-clockwise)
QgsVector normalized() const SIP_THROW(QgsException)
Returns the vector's normalized (or "unit") vector (ie same angle but length of 1....
double y() const SIP_HOLDGIL
Returns the vector's y-component.
double x() const SIP_HOLDGIL
Returns the vector's x-component.
double length() const SIP_HOLDGIL
Returns the length of the vector.
static Qgis::WkbType addZ(Qgis::WkbType type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
static Qgis::WkbType addM(Qgis::WkbType type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
static Qgis::WkbType parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
static bool hasZ(Qgis::WkbType type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
static bool hasM(Qgis::WkbType type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
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)
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.
Qgis::VertexType type
Vertex type.
bool isValid() const SIP_HOLDGIL
Returns true if the vertex id is valid.