26 #include <QStringList>
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 double length = pointBefore.
distance( pointAfter );
136 double currentDist = 0;
141 if ( vertexId ==
id )
155 double currentDist = 0;
165 nextVertex = previousVertex;
170 while ( currentDist < distance && geometry.
nextVertex( nextVertex, point ) )
172 if ( !first && nextVertex.
part == previousVertex.
part && nextVertex.
ring == previousVertex.
ring )
180 previousVertex = nextVertex;
184 if ( currentDist > distance )
189 previousVertex = nextVertex;
190 previousPoint = point;
200 return ( pt1.
x() - pt2.
x() ) * ( pt1.
x() - pt2.
x() ) + ( pt1.
y() - pt2.
y() ) * ( pt1.
y() - pt2.
y() );
213 double t = ( ( ptX - x1 ) * dx + ( ptY - y1 ) * dy ) / ( dx * dx + dy * dy );
229 double dist = dx * dx + dy * dy;
244 double d = v1.
y() * v2.
x() - v1.
x() * v2.
y();
249 double dx = p2.
x() - p1.
x();
250 double dy = p2.
y() - p1.
y();
251 double k = ( dy * v2.
x() - dx * v2.
y() ) / d;
253 intersection =
QgsPoint( p1.
x() + v1.
x() * k, p1.
y() + v1.
y() * k );
263 isIntersection =
false;
282 isIntersection =
true;
283 if ( acceptImproperIntersection )
285 if ( ( p1 == q1 ) || ( p1 == q2 ) )
287 intersectionPoint = p1;
290 else if ( ( p2 == q1 ) || ( p2 == q2 ) )
292 intersectionPoint = p2;
299 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( p1.
x(), p1.
y(), q1.
x(), q1.
y(), q2.
x(), q2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
301 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( p2.
x(), p2.
y(), q1.
x(), q1.
y(), q2.
x(), q2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
303 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( q1.
x(), q1.
y(), p1.
x(), p1.
y(), p2.
x(), p2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
305 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( q2.
x(), q2.
y(), p1.
x(), p1.
y(), p2.
x(), p2.
y(), x, y, tolerance ), 0.0, tolerance )
312 double lambdav =
QgsVector( intersectionPoint.
x() - p1.
x(), intersectionPoint.
y() - p1.
y() ) * v;
313 if ( lambdav < 0. + tolerance || lambdav > vl - tolerance )
316 double lambdaw =
QgsVector( intersectionPoint.
x() - q1.
x(), intersectionPoint.
y() - q1.
y() ) * w;
317 return !( lambdaw < 0. + tolerance || lambdaw >= wl - tolerance );
327 const double x1 = linePoint1.
x() - center.
x();
328 const double y1 = linePoint1.
y() - center.
y();
329 const double x2 = linePoint2.
x() - center.
x();
330 const double y2 = linePoint2.
y() - center.
y();
331 const double dx = x2 - x1;
332 const double dy = y2 - y1;
334 const double dr2 = std::pow( dx, 2 ) + std::pow( dy, 2 );
335 const double d = x1 * y2 - x2 * y1;
337 const double disc = std::pow( radius, 2 ) * dr2 - std::pow( d, 2 );
347 const int sgnDy = dy < 0 ? -1 : 1;
349 const double sqrDisc = std::sqrt( disc );
351 const double ax = center.
x() + ( d * dy + sgnDy * dx * sqrDisc ) / dr2;
352 const double ay = center.
y() + ( -d * dx + std::fabs( dy ) * sqrDisc ) / dr2;
355 const double bx = center.
x() + ( d * dy - sgnDy * dx * sqrDisc ) / dr2;
356 const double by = center.
y() + ( -d * dx - std::fabs( dy ) * sqrDisc ) / dr2;
363 intersection.
set( p1.
x(), p1.
y() );
367 intersection.
set( p2.
x(), p2.
y() );
378 const double d = center1.
distance( center2 );
381 if ( d > ( r1 + r2 ) )
386 else if ( d < std::fabs( r1 - r2 ) )
403 const double a = ( ( r1 * r1 ) - ( r2 * r2 ) + ( d * d ) ) / ( 2.0 * d ) ;
408 const double dx = center2.
x() - center1.
x();
409 const double dy = center2.
y() - center1.
y();
412 const double x2 = center1.
x() + ( dx * a / d );
413 const double y2 = center1.
y() + ( dy * a / d );
418 const double h = std::sqrt( ( r1 * r1 ) - ( a * a ) );
423 const double rx = dy * ( h / d );
424 const double ry = dx * ( h / d );
427 intersection1 =
QgsPointXY( x2 + rx, y2 - ry );
428 intersection2 =
QgsPointXY( x2 - rx, y2 + ry );
442 const double dx = center.
x() - p.
x();
443 const double dy = center.
y() - p.
y();
444 const double distanceSquared = dx * dx + dy * dy;
445 const double radiusSquared = radius * radius;
446 if ( distanceSquared < radiusSquared )
453 const double distanceToTangent = std::sqrt( distanceSquared - radiusSquared );
465 if ( radius1 > radius2 )
468 const double radius2a = radius2 - radius1;
477 QgsVector v1( -( line1P2.
y() - center1.
y() ), line1P2.
x() - center1.
x() );
478 const double v1Length = v1.
length();
479 v1 = v1 * ( radius1 / v1Length );
482 line1P1 = center1 + v1;
483 line1P2 = line1P2 + v1;
487 QgsVector v2( line2P2.
y() - center1.
y(), -( line2P2.
x() - center1.
x() ) );
488 const double v2Length = v2.
length();
489 v2 = v2 * ( radius1 / v2Length );
492 line2P1 = center1 + v2;
493 line2P2 = line2P2 + v2;
501 if ( radius1 > radius2 )
505 const double d = center1.
distance( center2 );
506 const double radius1a = radius1 + radius2;
523 QgsVector v1( ( line1P2.
y() - center2.
y() ), -( line1P2.
x() - center2.
x() ) );
524 const double v1Length = v1.
length();
525 v1 = v1 * ( radius2 / v1Length );
528 line1P1 = center2 + v1;
529 line1P2 = line1P2 + v1;
533 QgsVector v2( -( line2P2.
y() - center2.
y() ), line2P2.
x() - center2.
x() );
534 const double v2Length = v2.
length();
535 v2 = v2 * ( radius2 / v2Length );
538 line2P1 = center2 + v2;
539 line2P2 = line2P2 + v2;
546 QVector<SelfIntersection> intersections;
552 for (
int i = 0, j = 1; j < n; i = j++ )
560 int end = i == 0 && isClosed ? n - 1 : n;
561 for (
int k = start, l = start + 1; l < end; k = l++ )
567 bool intersection =
false;
578 intersections.append( s );
581 return intersections;
595 double test = ( f1 * f2 - f3 * f4 );
597 return qgsDoubleNear( test, 0.0 ) ? 0 : ( test < 0 ? -1 : 1 );
607 void 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 )
609 const double dx = x2 - x1;
610 const double dy = y2 - y1;
611 const double length = std::sqrt( dx * dx + dy * dy );
624 const double scaleFactor = distance / length;
625 x = x1 + dx * scaleFactor;
626 y = y1 + dy * scaleFactor;
628 *z = *z1 + ( *z2 - *z1 ) * scaleFactor;
630 *m = *m1 + ( *m2 - *m1 ) * scaleFactor;
637 const double mX = x1 + ( x2 - x1 ) * proportion;
638 const double mY = y1 + ( y2 - y1 ) * proportion;
639 const double pX = x1 - x2;
640 const double pY = y1 - y2;
641 double normalX = -pY;
643 const double normalLength = sqrt( ( normalX * normalX ) + ( normalY * normalY ) );
644 normalX /= normalLength;
645 normalY /= normalLength;
647 *x = mX + offset * normalX;
648 *y = mY + offset * normalY;
653 double centerX, centerY, radius;
656 const double theta = distance / radius;
657 const double anglePt1 = std::atan2( pt1.
y() - centerY, pt1.
x() - centerX );
658 const double anglePt2 = std::atan2( pt2.
y() - centerY, pt2.
x() - centerX );
659 const double anglePt3 = std::atan2( pt3.
y() - centerY, pt3.
x() - centerX );
661 const double angleDest = anglePt1 + (
isClockwise ? -theta : theta );
663 const double x = centerX + radius * ( std::cos( angleDest ) );
664 const double y = centerY + radius * ( std::sin( angleDest ) );
666 const double z = pt1.
is3D() ?
678 double angle = std::atan2( dy, dx ) * 180 / M_PI;
683 else if (
angle > 360 )
692 double dx21, dy21, dx31, dy31, h21, h31, d;
697 centerX = ( pt1.
x() + pt2.
x() ) / 2.0;
698 centerY = ( pt1.
y() + pt2.
y() ) / 2.0;
699 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
704 dx21 = pt2.
x() - pt1.
x();
705 dy21 = pt2.
y() - pt1.
y();
706 dx31 = pt3.
x() - pt1.
x();
707 dy31 = pt3.
y() - pt1.
y();
709 h21 = std::pow( dx21, 2.0 ) + std::pow( dy21, 2.0 );
710 h31 = std::pow( dx31, 2.0 ) + std::pow( dy31, 2.0 );
713 d = 2 * ( dx21 * dy31 - dx31 * dy21 );
723 centerX = pt1.
x() + ( h21 * dy31 - h31 * dy21 ) / d;
724 centerY = pt1.
y() - ( h21 * dx31 - h31 * dx21 ) / d;
725 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
730 if ( angle3 >= angle1 )
732 return !( angle2 > angle1 && angle2 < angle3 );
736 return !( angle2 > angle1 || angle2 < angle3 );
744 if ( angle2 < angle1 )
746 return ( angle <= angle1 && angle >= angle2 );
750 return ( angle <= angle1 || angle >= angle2 );
755 if ( angle2 > angle1 )
757 return (
angle >= angle1 &&
angle <= angle2 );
761 return (
angle >= angle1 ||
angle <= angle2 );
774 double centerX, centerY, radius;
776 double length = M_PI / 180.0 * radius *
sweepAngle( centerX, centerY, x1, y1, x2, y2, x3, y3 );
790 if ( p3Angle >= p1Angle )
792 if ( p2Angle > p1Angle && p2Angle < p3Angle )
794 return ( p3Angle - p1Angle );
798 return ( - ( p1Angle + ( 360 - p3Angle ) ) );
803 if ( p2Angle < p1Angle && p2Angle > p3Angle )
805 return ( -( p1Angle - p3Angle ) );
809 return ( p3Angle + ( 360 - p1Angle ) );
816 QgsPoint midPoint( ( p1.
x() + p2.
x() ) / 2.0, ( p1.
y() + p2.
y() ) / 2.0 );
818 if ( radius < midDist )
822 double centerMidDist = std::sqrt( radius * radius - midDist * midDist );
823 double dist = radius - centerMidDist;
825 double midDx = midPoint.
x() - p1.
x();
826 double midDy = midPoint.
y() - p1.
y();
829 QVector<QgsPoint> possibleMidPoints;
836 double minDist = std::numeric_limits<double>::max();
837 int minDistIndex = -1;
838 for (
int i = 0; i < possibleMidPoints.size(); ++i )
840 double currentDist =
sqrDistance2D( mousePos, possibleMidPoints.at( i ) );
841 if ( currentDist < minDist )
844 minDist = currentDist;
848 if ( minDistIndex == -1 )
853 result = possibleMidPoints.at( minDistIndex );
865 if ( !useShortestArc )
866 midPointAngle += M_PI;
867 return center.
project( center.
distance( p1 ), midPointAngle * 180 / M_PI );
874 double mX, mY, radius;
907 double bDistance = std::sqrt( ( b.
x() - centerX ) * ( b.
x() - centerX ) +
908 ( b.
y() - centerY ) * ( b.
y() - centerY ) );
910 double diff = std::fabs( radius - bDistance );
914 double abX = b.
x() - a.
x();
915 double abY = b.
y() - a.
y();
917 double cbX = b.
x() -
c.x();
918 double cbY = b.
y() -
c.y();
920 double dot = ( abX * cbX + abY * cbY );
921 double cross = ( abX * cbY - abY * cbX );
923 double alpha = std::atan2( cross, dot );
929 if ( diff < distanceTolerance )
931 double angle1 = arcAngle( a1, a2, a3 );
932 double angle2 = arcAngle( a2, a3, b );
937 diff = std::fabs( angle1 - angle2 );
938 if ( diff > pointSpacingAngleTolerance )
948 if ( bSide != a2Side )
956 bool reversed =
false;
980 circleCenterRadius( circlePoint1, circlePoint2, circlePoint3, radius, centerX, centerY );
982 if ( circlePoint1 != circlePoint3 && ( radius < 0 ||
qgsDoubleNear( segSide, 0.0 ) ) )
990 double increment = tolerance;
994 tolerance = std::min( tolerance, radius * 2 );
995 double halfAngle = std::acos( -tolerance / radius + 1 );
996 increment = 2 * halfAngle;
1000 double a1 = std::atan2( circlePoint1.
y() - centerY, circlePoint1.
x() - centerX );
1001 double a2 = std::atan2( circlePoint2.
y() - centerY, circlePoint2.
x() - centerX );
1002 double a3 = std::atan2( circlePoint3.
y() - centerY, circlePoint3.
x() - centerX );
1005 const bool symmetric =
true;
1008 double angle = a3 - a1;
1013 int segs = ceil(
angle / increment );
1015 increment =
angle / segs;
1029 QVector<QgsPoint> stringPoints;
1030 stringPoints.insert( 0, circlePoint1 );
1031 if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 )
1045 double tolError = increment / 100;
1046 double stopAngle = a3 - tolError;
1047 for (
double angle = a1 + increment;
angle < stopAngle;
angle += increment )
1049 x = centerX + radius * std::cos(
angle );
1050 y = centerY + radius * std::sin(
angle );
1061 stringPoints.insert( stringPoints.size(),
QgsPoint( pointWkbType, x, y, z, m ) );
1064 stringPoints.insert( stringPoints.size(), circlePoint3 );
1069 std::reverse( stringPoints.begin(), stringPoints.end() );
1071 if ( ! points.empty() && stringPoints.front() == points.back() ) stringPoints.pop_front();
1072 points.append( stringPoints );
1077 double side = ( ( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
1102 return zm1 + ( zm2 - zm1 ) * (
angle - a1 ) / ( a2 - a1 );
1104 return zm2 + ( zm3 - zm2 ) * (
angle - a2 ) / ( a3 - a2 );
1110 return zm1 + ( zm2 - zm1 ) * ( a1 -
angle ) / ( a1 - a2 );
1112 return zm2 + ( zm3 - zm2 ) * ( a2 -
angle ) / ( a2 - a3 );
1118 int dim = 2 + is3D + isMeasure;
1121 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1122 const QStringList coordList = wktCoordinateList.split(
',', QString::SkipEmptyParts );
1124 const QStringList coordList = wktCoordinateList.split(
',', Qt::SkipEmptyParts );
1128 bool foundZ =
false;
1129 bool foundM =
false;
1130 QRegularExpression rx( QStringLiteral(
"\\s" ) );
1131 QRegularExpression rxIsNumber( QStringLiteral(
"^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$" ) );
1132 for (
const QString &pointCoordinates : coordList )
1134 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1135 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1137 QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
1141 if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() )
1144 if ( coordinates.size() == 3 && !foundZ && !foundM && !is3D && !isMeasure )
1150 else if ( coordinates.size() >= 4 && ( !( is3D || foundZ ) || !( isMeasure || foundM ) ) )
1159 for (
const QString &pointCoordinates : coordList )
1161 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1162 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1164 QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
1166 if ( coordinates.size() < dim )
1170 double x = coordinates[idx++].toDouble();
1171 double y = coordinates[idx++].toDouble();
1174 if ( ( is3D || foundZ ) && coordinates.length() > idx )
1175 z = coordinates[idx++].toDouble();
1178 if ( ( isMeasure || foundM ) && coordinates.length() > idx )
1179 m = coordinates[idx++].toDouble();
1182 if ( is3D || foundZ )
1184 if ( isMeasure || foundM )
1191 if ( isMeasure || foundM )
1197 points.append(
QgsPoint( t, x, y, z, m ) );
1205 wkb << static_cast<quint32>( points.size() );
1206 for (
const QgsPoint &point : points )
1208 wkb << point.x() << point.y();
1222 QString wkt = QStringLiteral(
"(" );
1231 wkt += QLatin1String(
", " );
1233 if ( wkt.endsWith( QLatin1String(
", " ) ) )
1241 QDomElement elemCoordinates = doc.createElementNS( ns, QStringLiteral(
"coordinates" ) );
1244 QString cs = QStringLiteral(
"," );
1246 QString ts = QStringLiteral(
" " );
1248 elemCoordinates.setAttribute( QStringLiteral(
"cs" ), cs );
1249 elemCoordinates.setAttribute( QStringLiteral(
"ts" ), ts );
1251 QString strCoordinates;
1254 if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
1259 if ( strCoordinates.endsWith( ts ) )
1260 strCoordinates.chop( 1 );
1262 elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
1263 return elemCoordinates;
1268 QDomElement elemPosList = doc.createElementNS( ns, QStringLiteral(
"posList" ) );
1269 elemPosList.setAttribute( QStringLiteral(
"srsDimension" ), is3D ? 3 : 2 );
1271 QString strCoordinates;
1274 if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
1281 if ( strCoordinates.endsWith(
' ' ) )
1282 strCoordinates.chop( 1 );
1284 elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
1290 QString json = QStringLiteral(
"[ " );
1295 if ( json.endsWith( QLatin1String(
", " ) ) )
1306 json coordinates( json::array() );
1323 double clippedAngle =
angle;
1324 if ( clippedAngle >= M_PI * 2 || clippedAngle <= -2 * M_PI )
1326 clippedAngle = std::fmod( clippedAngle, 2 * M_PI );
1328 if ( clippedAngle < 0.0 )
1330 clippedAngle += 2 * M_PI;
1332 return clippedAngle;
1337 QString wktParsed = wkt;
1339 if ( wkt.contains( QString(
"EMPTY" ), Qt::CaseInsensitive ) )
1341 QRegularExpression wktRegEx( QStringLiteral(
"^\\s*(\\w+)\\s+(\\w+)\\s*$" ) );
1342 wktRegEx.setPatternOptions( QRegularExpression::DotMatchesEverythingOption );
1343 QRegularExpressionMatch match = wktRegEx.match( wkt );
1344 if ( match.hasMatch() )
1346 wktParsed = match.captured( 1 );
1347 contents = match.captured( 2 ).toUpper();
1352 const int openedParenthesisCount = wktParsed.count(
'(' );
1353 const int closedParenthesisCount = wktParsed.count(
')' );
1355 for (
int i = 0 ; i < openedParenthesisCount - closedParenthesisCount; ++i )
1356 wktParsed.push_back(
')' );
1358 wktParsed.truncate( wktParsed.size() - ( closedParenthesisCount - openedParenthesisCount ) );
1360 QRegularExpression cooRegEx( QStringLiteral(
"^[^\\(]*\\((.*)\\)[^\\)]*$" ) );
1361 cooRegEx.setPatternOptions( QRegularExpression::DotMatchesEverythingOption );
1362 QRegularExpressionMatch match = cooRegEx.match( wktParsed );
1363 contents = match.hasMatch() ? match.captured( 1 ) : QString();
1366 return qMakePair( wkbType, contents );
1374 for (
int i = 0, n = wkt.length(); i < n; ++i )
1376 if ( ( wkt[i].isSpace() || wkt[i] ==
'\n' || wkt[i] ==
'\t' ) && level == 0 )
1379 if ( wkt[i] ==
',' && level == 0 )
1381 if ( !block.isEmpty() )
1383 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1384 block.prepend( defaultType +
' ' );
1385 blocks.append( block );
1390 if ( wkt[i] ==
'(' )
1392 else if ( wkt[i] ==
')' )
1396 if ( !block.isEmpty() )
1398 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1399 block.prepend( defaultType +
' ' );
1400 blocks.append( block );
1408 if ( x <= left && y <= bottom )
1410 const double dx = left - x;
1411 const double dy = bottom - y;
1419 else if ( x >= right && y >= top )
1421 const double dx = x - right;
1422 const double dy = y - top;
1430 else if ( x >= right && y <= bottom )
1432 const double dx = x - right;
1433 const double dy = bottom - y;
1441 else if ( x <= left && y >= top )
1443 const double dx = left - x;
1444 const double dy = y - top;
1452 else if ( x <= left )
1454 else if ( x >= right )
1456 else if ( y <= bottom )
1458 else if ( y >= top )
1462 const double smallestX = std::min( right - x, x - left );
1463 const double smallestY = std::min( top - y, y - bottom );
1464 if ( smallestX < smallestY )
1467 if ( right - x < x - left )
1475 if ( top - y < y - bottom )
1487 double x = ( pt1.
x() + pt2.
x() ) / 2.0;
1488 double y = ( pt1.
y() + pt2.
y() ) / 2.0;
1489 double z = std::numeric_limits<double>::quiet_NaN();
1490 double m = std::numeric_limits<double>::quiet_NaN();
1495 z = ( pt1.
z() + pt2.
z() ) / 2.0;
1501 m = ( pt1.
m() + pt2.
m() ) / 2.0;
1504 return QgsPoint( pType, x, y, z, m );
1509 const double _fraction = 1 - fraction;
1511 p1.
x() * _fraction + p2.
x() * fraction,
1512 p1.
y() * _fraction + p2.
y() * fraction,
1513 p1.
is3D() ? p1.
z() * _fraction + p2.
z() * fraction : std::numeric_limits<double>::quiet_NaN(),
1514 p1.
isMeasure() ? p1.
m() * _fraction + p2.
m() * fraction : std::numeric_limits<double>::quiet_NaN() );
1519 const double deltaX = ( x2 - x1 ) * fraction;
1520 const double deltaY = ( y2 - y1 ) * fraction;
1521 return QgsPointXY( x1 + deltaX, y1 + deltaY );
1529 const double fraction = ( value - v1 ) / ( v2 - v1 );
1535 double delta_x = pt2.
x() - pt1.
x();
1536 double delta_y = pt2.
y() - pt1.
y();
1542 return delta_y / delta_x;
1561 a = pt1.
y() - pt2.
y();
1562 b = pt2.
x() - pt1.
x();
1563 c = pt1.
x() * pt2.
y() - pt1.
y() * pt2.
x();
1573 if ( ( p == s1 ) || ( p == s2 ) )
1591 double y = ( -
c - a * p.
x() ) / b;
1593 double d2 = 1 + m * m;
1594 double H = p.
y() - y;
1595 double dx = m * H / d2;
1608 double at = std::atan2( y2 - y1, x2 - x1 );
1609 double a = -at + M_PI_2;
1615 double angle1 = std::atan2( y1 - y2, x1 - x2 );
1616 double angle2 = std::atan2( y3 - y2, x3 - x2 );
1630 double a1 =
lineAngle( x1, y1, x2, y2 );
1631 double a2 =
lineAngle( x2, y2, x3, y3 );
1639 double clockwiseDiff = 0.0;
1642 clockwiseDiff = a2 - a1;
1646 clockwiseDiff = a2 + ( 2 * M_PI - a1 );
1648 double counterClockwiseDiff = 2 * M_PI - clockwiseDiff;
1650 double resultAngle = 0;
1651 if ( clockwiseDiff <= counterClockwiseDiff )
1653 resultAngle = a1 + clockwiseDiff / 2.0;
1657 resultAngle = a1 - counterClockwiseDiff / 2.0;
1668 if ( u3.
length() == 0 )
return 1;
1685 if ( std::fabs( u3.
x() ) <= epsilon &&
1686 std::fabs( u3.
y() ) <= epsilon &&
1687 std::fabs( u3.
z() ) <= epsilon )
1699 if ( !( std::fabs( b1 ) > epsilon ) )
1704 if ( !( a2 != -1 && a2 != 1 ) )
1710 double r1 = ( c2 - b2 * c1 / b1 ) / ( a2 - b2 * a1 / b1 );
1726 bool isIntersection;
1735 intersection.
set( ptInter.
x(), ptInter.
y(), La1.
z() );
1775 if ( !firstIsDone || !secondIsDone )
1781 intersection = ( X1 + X2 ) / 2.0;
1787 return 0.5 * std::abs( ( aX - cX ) * ( bY - aY ) - ( aX - bX ) * ( cY - aY ) );
1791 double weightB,
double weightC,
double &pointX,
double &pointY )
1794 if ( weightB + weightC > 1 )
1796 weightB = 1 - weightB;
1797 weightC = 1 - weightC;
1800 const double rBx = weightB * ( bX - aX );
1801 const double rBy = weightB * ( bY - aY );
1802 const double rCx = weightC * ( cX - aX );
1803 const double rCy = weightC * ( cY - aY );
1805 pointX = rBx + rCx + aX;
1806 pointY = rBy + rCy + aY;
1813 for (
const QgsPoint &pt : points )
1815 if ( pt.isMeasure() )
1818 point.
setM( pt.m() );
1831 for (
const QgsPoint &pt : points )
1836 point.
setZ( pt.z() );
1855 bool intersection =
false;
1861 return intersection;
1873 bool intersection =
false;
1879 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...
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.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
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 QPair< QgsWkbTypes::Type, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
static double circleTangentDirection(const QgsPoint &tangentPoint, const QgsPoint &cp1, const QgsPoint &cp2, const QgsPoint &cp3) SIP_HOLDGIL
Calculates the direction angle of a circle tangent (clockwise from north in radians)
static 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 void pointsToWKB(QgsWkbPtr &wkb, const QgsPointSequence &points, bool is3D, bool isMeasure)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
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 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 double distanceToVertex(const QgsAbstractGeometry &geom, QgsVertexId id)
Returns the distance along a geometry from its first vertex to the specified vertex.
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 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 int circleCircleIntersections(QgsPointXY center1, double radius1, QgsPointXY center2, double radius2, QgsPointXY &intersection1, QgsPointXY &intersection2) SIP_HOLDGIL
Calculates the intersections points between the circle with center center1 and radius radius1 and the...
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 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 ...
bool convertTo(QgsWkbTypes::Type type) override
Converts the geometry to a specified type.
void setZ(double z) SIP_HOLDGIL
Sets the point's z-coordinate.
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.
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 Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Type
The WKB type describes the number of dimensions a geometry has.
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
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.
VertexType type
Vertex type.
bool isValid() const SIP_HOLDGIL
Returns true if the vertex id is valid.