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;
169 nextVertex = previousVertex;
174 while ( currentDist < distance && geometry.
nextVertex( nextVertex, point ) )
176 if ( !first && nextVertex.
part == previousVertex.
part && nextVertex.
ring == previousVertex.
ring )
184 previousVertex = nextVertex;
188 if ( currentDist > distance )
193 previousVertex = nextVertex;
194 previousPoint = point;
204 return ( pt1.
x() - pt2.
x() ) * ( pt1.
x() - pt2.
x() ) + ( pt1.
y() - pt2.
y() ) * ( pt1.
y() - pt2.
y() );
217 const double t = ( ( ptX - x1 ) * dx + ( ptY - y1 ) * dy ) / ( dx * dx + dy * dy );
233 const double dist = dx * dx + dy * dy;
248 const double area = std::abs(
249 ( linePoint1.
x() - linePoint2.
x() ) * ( point.
y() - linePoint2.
y() ) -
250 ( linePoint1.
y() - linePoint2.
y() ) * ( point.
x() - linePoint2.
x() )
253 const double length = std::sqrt(
254 std::pow( linePoint1.
x() - linePoint2.
x(), 2 ) +
255 std::pow( linePoint1.
y() - linePoint2.
y(), 2 )
258 const double distance = area / length;
259 return qgsDoubleNear( distance, 0.0, epsilon ) ? 0.0 : distance;
264 const double d = v1.
y() * v2.
x() - v1.
x() * v2.
y();
269 const double dx = p2.
x() - p1.
x();
270 const double dy = p2.
y() - p1.
y();
271 const double k = ( dy * v2.
x() - dx * v2.
y() ) / d;
273 intersection =
QgsPoint( p1.
x() + v1.
x() * k, p1.
y() + v1.
y() * k );
283 isIntersection =
false;
287 const double vl = v.
length();
288 const double wl = w.
length();
302 isIntersection =
true;
303 if ( acceptImproperIntersection )
305 if ( ( p1 == q1 ) || ( p1 == q2 ) )
307 intersectionPoint = p1;
310 else if ( ( p2 == q1 ) || ( p2 == q2 ) )
312 intersectionPoint = p2;
319 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( p1.
x(), p1.
y(), q1.
x(), q1.
y(), q2.
x(), q2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
321 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( p2.
x(), p2.
y(), q1.
x(), q1.
y(), q2.
x(), q2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
323 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( q1.
x(), q1.
y(), p1.
x(), p1.
y(), p2.
x(), p2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
325 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( q2.
x(), q2.
y(), p1.
x(), p1.
y(), p2.
x(), p2.
y(), x, y, tolerance ), 0.0, tolerance )
332 const double lambdav =
QgsVector( intersectionPoint.
x() - p1.
x(), intersectionPoint.
y() - p1.
y() ) * v;
333 if ( lambdav < 0. + tolerance || lambdav > vl - tolerance )
336 const double lambdaw =
QgsVector( intersectionPoint.
x() - q1.
x(), intersectionPoint.
y() - q1.
y() ) * w;
337 return !( lambdaw < 0. + tolerance || lambdaw >= wl - tolerance );
347 const double x1 = linePoint1.
x() - center.
x();
348 const double y1 = linePoint1.
y() - center.
y();
349 const double x2 = linePoint2.
x() - center.
x();
350 const double y2 = linePoint2.
y() - center.
y();
351 const double dx = x2 - x1;
352 const double dy = y2 - y1;
354 const double dr2 = std::pow( dx, 2 ) + std::pow( dy, 2 );
355 const double d = x1 * y2 - x2 * y1;
357 const double disc = std::pow( radius, 2 ) * dr2 - std::pow( d, 2 );
367 const int sgnDy = dy < 0 ? -1 : 1;
369 const double sqrDisc = std::sqrt( disc );
371 const double ax = center.
x() + ( d * dy + sgnDy * dx * sqrDisc ) / dr2;
372 const double ay = center.
y() + ( -d * dx + std::fabs( dy ) * sqrDisc ) / dr2;
375 const double bx = center.
x() + ( d * dy - sgnDy * dx * sqrDisc ) / dr2;
376 const double by = center.
y() + ( -d * dx - std::fabs( dy ) * sqrDisc ) / dr2;
383 intersection.
set( p1.
x(), p1.
y() );
387 intersection.
set( p2.
x(), p2.
y() );
398 const double d = center1.
distance( center2 );
401 if ( d > ( r1 + r2 ) )
406 else if ( d < std::fabs( r1 - r2 ) )
423 const double a = ( ( r1 * r1 ) - ( r2 * r2 ) + ( d * d ) ) / ( 2.0 * d ) ;
428 const double dx = center2.
x() - center1.
x();
429 const double dy = center2.
y() - center1.
y();
432 const double x2 = center1.
x() + ( dx * a / d );
433 const double y2 = center1.
y() + ( dy * a / d );
438 const double h = std::sqrt( ( r1 * r1 ) - ( a * a ) );
443 const double rx = dy * ( h / d );
444 const double ry = dx * ( h / d );
447 intersection1 =
QgsPointXY( x2 + rx, y2 - ry );
448 intersection2 =
QgsPointXY( x2 - rx, y2 + ry );
462 const double dx = center.
x() - p.
x();
463 const double dy = center.
y() - p.
y();
464 const double distanceSquared = dx * dx + dy * dy;
465 const double radiusSquared = radius * radius;
466 if ( distanceSquared < radiusSquared )
473 const double distanceToTangent = std::sqrt( distanceSquared - radiusSquared );
485 if ( radius1 > radius2 )
488 const double radius2a = radius2 - radius1;
497 QgsVector v1( -( line1P2.
y() - center1.
y() ), line1P2.
x() - center1.
x() );
498 const double v1Length = v1.
length();
499 v1 = v1 * ( radius1 / v1Length );
502 line1P1 = center1 + v1;
503 line1P2 = line1P2 + v1;
507 QgsVector v2( line2P2.
y() - center1.
y(), -( line2P2.
x() - center1.
x() ) );
508 const double v2Length = v2.
length();
509 v2 = v2 * ( radius1 / v2Length );
512 line2P1 = center1 + v2;
513 line2P2 = line2P2 + v2;
521 if ( radius1 > radius2 )
525 const double d = center1.
distance( center2 );
526 const double radius1a = radius1 + radius2;
543 QgsVector v1( ( line1P2.
y() - center2.
y() ), -( line1P2.
x() - center2.
x() ) );
544 const double v1Length = v1.
length();
545 v1 = v1 * ( radius2 / v1Length );
548 line1P1 = center2 + v1;
549 line1P2 = line1P2 + v1;
553 QgsVector v2( -( line2P2.
y() - center2.
y() ), line2P2.
x() - center2.
x() );
554 const double v2Length = v2.
length();
555 v2 = v2 * ( radius2 / v2Length );
558 line2P1 = center2 + v2;
559 line2P2 = line2P2 + v2;
566 QVector<SelfIntersection> intersections;
572 for (
int i = 0, j = 1; j < n; i = j++ )
579 const int start = j + 1;
580 const int end = i == 0 && isClosed ? n - 1 : n;
581 for (
int k = start, l = start + 1; l < end; k = l++ )
587 bool intersection =
false;
598 intersections.append( s );
601 return intersections;
611 const double f1 = x - x1;
612 const double f2 = y2 - y1;
613 const double f3 = y - y1;
614 const double f4 = x2 - x1;
615 const double test = ( f1 * f2 - f3 * f4 );
617 return qgsDoubleNear( test, 0.0 ) ? 0 : ( test < 0 ? -1 : 1 );
627void 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 )
629 const double dx = x2 - x1;
630 const double dy = y2 - y1;
631 const double length = std::sqrt( dx * dx + dy * dy );
644 const double scaleFactor = distance / length;
645 x = x1 + dx * scaleFactor;
646 y = y1 + dy * scaleFactor;
648 *z = *z1 + ( *z2 - *z1 ) * scaleFactor;
650 *m = *m1 + ( *m2 - *m1 ) * scaleFactor;
657 const double mX = x1 + ( x2 - x1 ) * proportion;
658 const double mY = y1 + ( y2 - y1 ) * proportion;
659 const double pX = x1 - x2;
660 const double pY = y1 - y2;
661 double normalX = -pY;
663 const double normalLength = sqrt( ( normalX * normalX ) + ( normalY * normalY ) );
664 normalX /= normalLength;
665 normalY /= normalLength;
667 *x = mX + offset * normalX;
668 *y = mY + offset * normalY;
673 double centerX, centerY, radius;
676 const double theta = distance / radius;
677 const double anglePt1 = std::atan2( pt1.
y() - centerY, pt1.
x() - centerX );
678 const double anglePt2 = std::atan2( pt2.
y() - centerY, pt2.
x() - centerX );
679 const double anglePt3 = std::atan2( pt3.
y() - centerY, pt3.
x() - centerX );
681 const double angleDest = anglePt1 + (
isClockwise ? -theta : theta );
683 const double x = centerX + radius * ( std::cos( angleDest ) );
684 const double y = centerY + radius * ( std::sin( angleDest ) );
686 const double z = pt1.
is3D() ?
698 const double angle = std::atan2( dy, dx ) * 180 / M_PI;
703 else if (
angle > 360 )
712 double dx21, dy21, dx31, dy31, h21, h31, d;
717 centerX = ( pt1.
x() + pt2.
x() ) / 2.0;
718 centerY = ( pt1.
y() + pt2.
y() ) / 2.0;
719 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
724 dx21 = pt2.
x() - pt1.
x();
725 dy21 = pt2.
y() - pt1.
y();
726 dx31 = pt3.
x() - pt1.
x();
727 dy31 = pt3.
y() - pt1.
y();
729 h21 = std::pow( dx21, 2.0 ) + std::pow( dy21, 2.0 );
730 h31 = std::pow( dx31, 2.0 ) + std::pow( dy31, 2.0 );
733 d = 2 * ( dx21 * dy31 - dx31 * dy21 );
743 centerX = pt1.
x() + ( h21 * dy31 - h31 * dy21 ) / d;
744 centerY = pt1.
y() - ( h21 * dx31 - h31 * dx21 ) / d;
745 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
750 if ( angle3 >= angle1 )
752 return !( angle2 > angle1 && angle2 < angle3 );
756 return !( angle2 > angle1 || angle2 < angle3 );
764 if ( angle2 < angle1 )
766 return ( angle <= angle1 && angle >= angle2 );
770 return ( angle <= angle1 || angle >= angle2 );
775 if ( angle2 > angle1 )
777 return (
angle >= angle1 &&
angle <= angle2 );
781 return (
angle >= angle1 ||
angle <= angle2 );
794 double centerX, centerY, radius;
796 double length = M_PI / 180.0 * radius *
sweepAngle( centerX, centerY, x1, y1, x2, y2, x3, y3 );
810 if ( p3Angle >= p1Angle )
812 if ( p2Angle > p1Angle && p2Angle < p3Angle )
814 return ( p3Angle - p1Angle );
818 return ( - ( p1Angle + ( 360 - p3Angle ) ) );
823 if ( p2Angle < p1Angle && p2Angle > p3Angle )
825 return ( -( p1Angle - p3Angle ) );
829 return ( p3Angle + ( 360 - p1Angle ) );
836 const QgsPoint midPoint( ( p1.
x() + p2.
x() ) / 2.0, ( p1.
y() + p2.
y() ) / 2.0 );
837 const double midDist = std::sqrt(
sqrDistance2D( p1, midPoint ) );
838 if ( radius < midDist )
842 const double centerMidDist = std::sqrt( radius * radius - midDist * midDist );
843 const double dist = radius - centerMidDist;
845 const double midDx = midPoint.
x() - p1.
x();
846 const double midDy = midPoint.
y() - p1.
y();
849 QVector<QgsPoint> possibleMidPoints;
856 double minDist = std::numeric_limits<double>::max();
857 int minDistIndex = -1;
858 for (
int i = 0; i < possibleMidPoints.size(); ++i )
860 const double currentDist =
sqrDistance2D( mousePos, possibleMidPoints.at( i ) );
861 if ( currentDist < minDist )
864 minDist = currentDist;
868 if ( minDistIndex == -1 )
873 result = possibleMidPoints.at( minDistIndex );
885 if ( !useShortestArc )
886 midPointAngle += M_PI;
887 return center.
project( center.
distance( p1 ), midPointAngle * 180 / M_PI );
894 double mX, mY, radius;
927 const double bDistance = std::sqrt( ( b.
x() - centerX ) * ( b.
x() - centerX ) +
928 ( b.
y() - centerY ) * ( b.
y() - centerY ) );
930 double diff = std::fabs( radius - bDistance );
934 const double abX = b.
x() - a.
x();
935 const double abY = b.
y() - a.
y();
937 const double cbX = b.
x() -
c.x();
938 const double cbY = b.
y() -
c.y();
940 const double dot = ( abX * cbX + abY * cbY );
941 const double cross = ( abX * cbY - abY * cbX );
943 const double alpha = std::atan2( cross, dot );
949 if ( diff < distanceTolerance )
951 const double angle1 = arcAngle( a1, a2, a3 );
952 const double angle2 = arcAngle( a2, a3, b );
957 diff = std::fabs( angle1 - angle2 );
958 if ( diff > pointSpacingAngleTolerance )
963 const int a2Side =
leftOfLine( a2.
x(), a2.
y(), a1.
x(), a1.
y(), a3.
x(), a3.
y() );
964 const int bSide =
leftOfLine( b.
x(), b.
y(), a1.
x(), a1.
y(), a3.
x(), a3.
y() );
968 if ( bSide != a2Side )
976 bool reversed =
false;
1000 circleCenterRadius( circlePoint1, circlePoint2, circlePoint3, radius, centerX, centerY );
1002 if ( circlePoint1 != circlePoint3 && ( radius < 0 ||
qgsDoubleNear( segSide, 0.0 ) ) )
1004 points.append( p1 );
1005 points.append( p2 );
1006 points.append( p3 );
1010 double increment = tolerance;
1014 tolerance = std::min( tolerance, radius * 2 );
1015 const double halfAngle = std::acos( -tolerance / radius + 1 );
1016 increment = 2 * halfAngle;
1020 const double a1 = std::atan2( circlePoint1.
y() - centerY, circlePoint1.
x() - centerX );
1021 double a2 = std::atan2( circlePoint2.
y() - centerY, circlePoint2.
x() - centerX );
1022 double a3 = std::atan2( circlePoint3.
y() - centerY, circlePoint3.
x() - centerX );
1025 const bool symmetric =
true;
1028 double angle = a3 - a1;
1033 const int segs = ceil(
angle / increment );
1035 increment =
angle / segs;
1049 QVector<QgsPoint> stringPoints;
1050 stringPoints.insert( 0, circlePoint1 );
1051 if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 )
1065 const double tolError = increment / 100;
1066 const double stopAngle = a3 - tolError;
1067 for (
double angle = a1 + increment;
angle < stopAngle;
angle += increment )
1069 x = centerX + radius * std::cos(
angle );
1070 y = centerY + radius * std::sin(
angle );
1081 stringPoints.insert( stringPoints.size(),
QgsPoint( pointWkbType, x, y, z, m ) );
1084 stringPoints.insert( stringPoints.size(), circlePoint3 );
1089 std::reverse( stringPoints.begin(), stringPoints.end() );
1091 if ( ! points.empty() && stringPoints.front() == points.back() ) stringPoints.pop_front();
1092 points.append( stringPoints );
1097 const double side = ( ( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
1122 return zm1 + ( zm2 - zm1 ) * (
angle - a1 ) / ( a2 - a1 );
1124 return zm2 + ( zm3 - zm2 ) * (
angle - a2 ) / ( a3 - a2 );
1130 return zm1 + ( zm2 - zm1 ) * ( a1 -
angle ) / ( a1 - a2 );
1132 return zm2 + ( zm3 - zm2 ) * ( a2 -
angle ) / ( a2 - a3 );
1138 const int dim = 2 + is3D + isMeasure;
1141#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1142 const QStringList coordList = wktCoordinateList.split(
',', QString::SkipEmptyParts );
1144 const QStringList coordList = wktCoordinateList.split(
',', Qt::SkipEmptyParts );
1148 bool foundZ =
false;
1149 bool foundM =
false;
1150 const thread_local QRegularExpression rx( QStringLiteral(
"\\s" ) );
1151 const thread_local QRegularExpression rxIsNumber( QStringLiteral(
"^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$" ) );
1152 for (
const QString &pointCoordinates : coordList )
1154#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1155 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1157 const QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
1161 if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() )
1164 if ( coordinates.size() == 3 && !foundZ && !foundM && !is3D && !isMeasure )
1170 else if ( coordinates.size() >= 4 && ( !( is3D || foundZ ) || !( isMeasure || foundM ) ) )
1179 for (
const QString &pointCoordinates : coordList )
1181#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1182 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1184 QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
1186 if ( coordinates.size() < dim )
1190 const double x = coordinates[idx++].toDouble();
1191 const double y = coordinates[idx++].toDouble();
1194 if ( ( is3D || foundZ ) && coordinates.length() > idx )
1195 z = coordinates[idx++].toDouble();
1198 if ( ( isMeasure || foundM ) && coordinates.length() > idx )
1199 m = coordinates[idx++].toDouble();
1202 if ( is3D || foundZ )
1204 if ( isMeasure || foundM )
1211 if ( isMeasure || foundM )
1217 points.append(
QgsPoint( t, x, y, z, m ) );
1225 wkb << static_cast<quint32>( points.size() );
1226 for (
const QgsPoint &point : points )
1228 wkb << point.x() << point.y();
1231 double z = point.z();
1233 && std::isnan( z ) )
1234 z = -std::numeric_limits<double>::max();
1240 double m = point.m();
1242 && std::isnan( m ) )
1243 m = -std::numeric_limits<double>::max();
1252 QString wkt = QStringLiteral(
"(" );
1261 wkt += QLatin1String(
", " );
1263 if ( wkt.endsWith( QLatin1String(
", " ) ) )
1271 QDomElement elemCoordinates = doc.createElementNS( ns, QStringLiteral(
"coordinates" ) );
1274 const QString cs = QStringLiteral(
"," );
1276 const QString ts = QStringLiteral(
" " );
1278 elemCoordinates.setAttribute( QStringLiteral(
"cs" ), cs );
1279 elemCoordinates.setAttribute( QStringLiteral(
"ts" ), ts );
1281 QString strCoordinates;
1284 if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
1289 if ( strCoordinates.endsWith( ts ) )
1290 strCoordinates.chop( 1 );
1292 elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
1293 return elemCoordinates;
1298 QDomElement elemPosList = doc.createElementNS( ns, QStringLiteral(
"posList" ) );
1299 elemPosList.setAttribute( QStringLiteral(
"srsDimension" ), is3D ? 3 : 2 );
1301 QString strCoordinates;
1304 if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
1311 if ( strCoordinates.endsWith(
' ' ) )
1312 strCoordinates.chop( 1 );
1314 elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
1320 QString json = QStringLiteral(
"[ " );
1325 if ( json.endsWith( QLatin1String(
", " ) ) )
1336 json coordinates( json::array() );
1353 double clippedAngle =
angle;
1354 if ( clippedAngle >= M_PI * 2 || clippedAngle <= -2 * M_PI )
1356 clippedAngle = std::fmod( clippedAngle, 2 * M_PI );
1358 if ( clippedAngle < 0.0 )
1360 clippedAngle += 2 * M_PI;
1362 return clippedAngle;
1367 QString wktParsed = wkt;
1369 if ( wkt.contains( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) )
1371 const thread_local QRegularExpression sWktRegEx( QStringLiteral(
"^\\s*(\\w+)\\s+(\\w+)\\s*$" ), QRegularExpression::DotMatchesEverythingOption );
1372 const QRegularExpressionMatch match = sWktRegEx.match( wkt );
1373 if ( match.hasMatch() )
1375 wktParsed = match.captured( 1 );
1376 contents = match.captured( 2 ).toUpper();
1381 const int openedParenthesisCount = wktParsed.count(
'(' );
1382 const int closedParenthesisCount = wktParsed.count(
')' );
1384 for (
int i = 0 ; i < openedParenthesisCount - closedParenthesisCount; ++i )
1385 wktParsed.push_back(
')' );
1387 wktParsed.truncate( wktParsed.size() - ( closedParenthesisCount - openedParenthesisCount ) );
1389 const thread_local QRegularExpression cooRegEx( QStringLiteral(
"^[^\\(]*\\((.*)\\)[^\\)]*$" ), QRegularExpression::DotMatchesEverythingOption );
1390 const QRegularExpressionMatch match = cooRegEx.match( wktParsed );
1391 contents = match.hasMatch() ? match.captured( 1 ) : QString();
1394 return qMakePair( wkbType, contents );
1401 block.reserve( wkt.size() );
1404 const QChar *wktData = wkt.data();
1405 const int wktLength = wkt.length();
1406 for (
int i = 0, n = wktLength; i < n; ++i, ++wktData )
1408 if ( ( wktData->isSpace() || *wktData ==
'\n' || *wktData ==
'\t' ) && level == 0 )
1411 if ( *wktData ==
',' && level == 0 )
1413 if ( !block.isEmpty() )
1415 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1416 block.prepend( defaultType +
' ' );
1417 blocks.append( block );
1422 if ( *wktData ==
'(' )
1424 else if ( *wktData ==
')' )
1428 if ( !block.isEmpty() )
1430 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1431 block.prepend( defaultType +
' ' );
1432 blocks.append( block );
1440 if ( x <= left && y <= bottom )
1442 const double dx = left - x;
1443 const double dy = bottom - y;
1451 else if ( x >= right && y >= top )
1453 const double dx = x - right;
1454 const double dy = y - top;
1462 else if ( x >= right && y <= bottom )
1464 const double dx = x - right;
1465 const double dy = bottom - y;
1473 else if ( x <= left && y >= top )
1475 const double dx = left - x;
1476 const double dy = y - top;
1484 else if ( x <= left )
1486 else if ( x >= right )
1488 else if ( y <= bottom )
1490 else if ( y >= top )
1494 const double smallestX = std::min( right - x, x - left );
1495 const double smallestY = std::min( top - y, y - bottom );
1496 if ( smallestX < smallestY )
1499 if ( right - x < x - left )
1507 if ( top - y < y - bottom )
1519 const double x = ( pt1.
x() + pt2.
x() ) / 2.0;
1520 const double y = ( pt1.
y() + pt2.
y() ) / 2.0;
1521 double z = std::numeric_limits<double>::quiet_NaN();
1522 double m = std::numeric_limits<double>::quiet_NaN();
1527 z = ( pt1.
z() + pt2.
z() ) / 2.0;
1533 m = ( pt1.
m() + pt2.
m() ) / 2.0;
1536 return QgsPoint( pType, x, y, z, m );
1541 const double _fraction = 1 - fraction;
1543 p1.
x() * _fraction + p2.
x() * fraction,
1544 p1.
y() * _fraction + p2.
y() * fraction,
1545 p1.
is3D() ? p1.
z() * _fraction + p2.
z() * fraction : std::numeric_limits<double>::quiet_NaN(),
1546 p1.
isMeasure() ? p1.
m() * _fraction + p2.
m() * fraction : std::numeric_limits<double>::quiet_NaN() );
1551 const double deltaX = ( x2 - x1 ) * fraction;
1552 const double deltaY = ( y2 - y1 ) * fraction;
1553 return QgsPointXY( x1 + deltaX, y1 + deltaY );
1561 const double fraction = ( value - v1 ) / ( v2 - v1 );
1567 const double delta_x = pt2.
x() - pt1.
x();
1568 const double delta_y = pt2.
y() - pt1.
y();
1574 return delta_y / delta_x;
1593 a = pt1.
y() - pt2.
y();
1594 b = pt2.
x() - pt1.
x();
1595 c = pt1.
x() * pt2.
y() - pt1.
y() * pt2.
x();
1605 if ( ( p == s1 ) || ( p == s2 ) )
1623 const double y = ( -
c - a * p.
x() ) / b;
1624 const double m =
gradient( s1, s2 );
1625 const double d2 = 1 + m * m;
1626 const double H = p.
y() - y;
1627 const double dx = m * H / d2;
1628 const double dy = m * dx;
1638void QgsGeometryUtils::perpendicularCenterSegment(
double pointx,
double pointy,
double segmentPoint1x,
double segmentPoint1y,
double segmentPoint2x,
double segmentPoint2y,
double &perpendicularSegmentPoint1x,
double &perpendicularSegmentPoint1y,
double &perpendicularSegmentPoint2x,
double &perpendicularSegmentPoint2y,
double desiredSegmentLength )
1640 QgsVector segmentVector =
QgsVector( segmentPoint2x - segmentPoint1x, segmentPoint2y - segmentPoint1y );
1642 if ( desiredSegmentLength != 0 )
1644 perpendicularVector = perpendicularVector.
normalized() * ( desiredSegmentLength ) / 2;
1647 perpendicularSegmentPoint1x = pointx - perpendicularVector.
x();
1648 perpendicularSegmentPoint1y = pointy - perpendicularVector.
y();
1649 perpendicularSegmentPoint2x = pointx + perpendicularVector.
x();
1650 perpendicularSegmentPoint2y = pointy + perpendicularVector.
y();
1655 const double at = std::atan2( y2 - y1, x2 - x1 );
1656 const double a = -at + M_PI_2;
1662 const double angle1 = std::atan2( y1 - y2, x1 - x2 );
1663 const double angle2 = std::atan2( y3 - y2, x3 - x2 );
1677 const double a1 =
lineAngle( x1, y1, x2, y2 );
1678 const double a2 =
lineAngle( x2, y2, x3, y3 );
1686 double clockwiseDiff = 0.0;
1689 clockwiseDiff = a2 - a1;
1693 clockwiseDiff = a2 + ( 2 * M_PI - a1 );
1695 const double counterClockwiseDiff = 2 * M_PI - clockwiseDiff;
1697 double resultAngle = 0;
1698 if ( clockwiseDiff <= counterClockwiseDiff )
1700 resultAngle = a1 + clockwiseDiff / 2.0;
1704 resultAngle = a1 - counterClockwiseDiff / 2.0;
1715 if ( u3.
length() == 0 )
return 1;
1732 if ( std::fabs( u3.
x() ) <= epsilon &&
1733 std::fabs( u3.
y() ) <= epsilon &&
1734 std::fabs( u3.
z() ) <= epsilon )
1746 if ( !( std::fabs( b1 ) > epsilon ) )
1751 if ( !( a2 != -1 && a2 != 1 ) )
1757 const double r1 = ( c2 - b2 * c1 / b1 ) / ( a2 - b2 * a1 / b1 );
1773 bool isIntersection;
1782 intersection.
set( ptInter.
x(), ptInter.
y(), La1.
z() );
1822 if ( !firstIsDone || !secondIsDone )
1828 intersection = ( X1 + X2 ) / 2.0;
1834 return 0.5 * std::abs( ( aX - cX ) * ( bY - aY ) - ( aX - bX ) * ( cY - aY ) );
1838 double weightB,
double weightC,
double &pointX,
double &pointY )
1841 if ( weightB + weightC > 1 )
1843 weightB = 1 - weightB;
1844 weightC = 1 - weightC;
1847 const double rBx = weightB * ( bX - aX );
1848 const double rBy = weightB * ( bY - aY );
1849 const double rCx = weightC * ( cX - aX );
1850 const double rCy = weightC * ( cY - aY );
1852 pointX = rBx + rCx + aX;
1853 pointY = rBy + rCy + aY;
1860 for (
const QgsPoint &pt : points )
1862 if ( pt.isMeasure() )
1865 point.
setM( pt.m() );
1878 for (
const QgsPoint &pt : points )
1883 point.
setZ( pt.z() );
1902 bool intersection =
false;
1908 return intersection;
1920 bool intersection =
false;
1926 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.