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;
636 double centerX, centerY, radius;
639 const double theta = distance / radius;
640 const double anglePt1 = std::atan2( pt1.
y() - centerY, pt1.
x() - centerX );
641 const double anglePt2 = std::atan2( pt2.
y() - centerY, pt2.
x() - centerX );
642 const double anglePt3 = std::atan2( pt3.
y() - centerY, pt3.
x() - centerX );
643 const bool isClockwise =
circleClockwise( anglePt1, anglePt2, anglePt3 );
644 const double angleDest = anglePt1 + ( isClockwise ? -theta : theta );
646 const double x = centerX + radius * ( std::cos( angleDest ) );
647 const double y = centerY + radius * ( std::sin( angleDest ) );
649 const double z = pt1.
is3D() ?
661 double angle = std::atan2( dy, dx ) * 180 / M_PI;
666 else if (
angle > 360 )
675 double dx21, dy21, dx31, dy31, h21, h31, d;
680 centerX = ( pt1.
x() + pt2.
x() ) / 2.0;
681 centerY = ( pt1.
y() + pt2.
y() ) / 2.0;
682 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
687 dx21 = pt2.
x() - pt1.
x();
688 dy21 = pt2.
y() - pt1.
y();
689 dx31 = pt3.
x() - pt1.
x();
690 dy31 = pt3.
y() - pt1.
y();
692 h21 = std::pow( dx21, 2.0 ) + std::pow( dy21, 2.0 );
693 h31 = std::pow( dx31, 2.0 ) + std::pow( dy31, 2.0 );
696 d = 2 * ( dx21 * dy31 - dx31 * dy21 );
706 centerX = pt1.
x() + ( h21 * dy31 - h31 * dy21 ) / d;
707 centerY = pt1.
y() - ( h21 * dx31 - h31 * dx21 ) / d;
708 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
713 if ( angle3 >= angle1 )
715 return !( angle2 > angle1 && angle2 < angle3 );
719 return !( angle2 > angle1 || angle2 < angle3 );
727 if ( angle2 < angle1 )
729 return ( angle <= angle1 && angle >= angle2 );
733 return ( angle <= angle1 || angle >= angle2 );
738 if ( angle2 > angle1 )
740 return (
angle >= angle1 &&
angle <= angle2 );
744 return (
angle >= angle1 ||
angle <= angle2 );
757 double centerX, centerY, radius;
759 double length = M_PI / 180.0 * radius *
sweepAngle( centerX, centerY, x1, y1, x2, y2, x3, y3 );
773 if ( p3Angle >= p1Angle )
775 if ( p2Angle > p1Angle && p2Angle < p3Angle )
777 return ( p3Angle - p1Angle );
781 return ( - ( p1Angle + ( 360 - p3Angle ) ) );
786 if ( p2Angle < p1Angle && p2Angle > p3Angle )
788 return ( -( p1Angle - p3Angle ) );
792 return ( p3Angle + ( 360 - p1Angle ) );
799 QgsPoint midPoint( ( p1.
x() + p2.
x() ) / 2.0, ( p1.
y() + p2.
y() ) / 2.0 );
801 if ( radius < midDist )
805 double centerMidDist = std::sqrt( radius * radius - midDist * midDist );
806 double dist = radius - centerMidDist;
808 double midDx = midPoint.
x() - p1.
x();
809 double midDy = midPoint.
y() - p1.
y();
812 QVector<QgsPoint> possibleMidPoints;
819 double minDist = std::numeric_limits<double>::max();
820 int minDistIndex = -1;
821 for (
int i = 0; i < possibleMidPoints.size(); ++i )
823 double currentDist =
sqrDistance2D( mousePos, possibleMidPoints.at( i ) );
824 if ( currentDist < minDist )
827 minDist = currentDist;
831 if ( minDistIndex == -1 )
836 result = possibleMidPoints.at( minDistIndex );
848 if ( !useShortestArc )
849 midPointAngle += M_PI;
850 return center.
project( center.
distance( p1 ), midPointAngle * 180 / M_PI );
857 double mX, mY, radius;
890 double bDistance = std::sqrt( ( b.
x() - centerX ) * ( b.
x() - centerX ) +
891 ( b.
y() - centerY ) * ( b.
y() - centerY ) );
893 double diff = std::fabs( radius - bDistance );
897 double abX = b.
x() - a.
x();
898 double abY = b.
y() - a.
y();
900 double cbX = b.
x() -
c.x();
901 double cbY = b.
y() -
c.y();
903 double dot = ( abX * cbX + abY * cbY );
904 double cross = ( abX * cbY - abY * cbX );
906 double alpha = std::atan2( cross, dot );
912 if ( diff < distanceTolerance )
914 double angle1 = arcAngle( a1, a2, a3 );
915 double angle2 = arcAngle( a2, a3, b );
920 diff = std::fabs( angle1 - angle2 );
921 if ( diff > pointSpacingAngleTolerance )
931 if ( bSide != a2Side )
939 bool reversed =
false;
963 circleCenterRadius( circlePoint1, circlePoint2, circlePoint3, radius, centerX, centerY );
965 if ( circlePoint1 != circlePoint3 && ( radius < 0 ||
qgsDoubleNear( segSide, 0.0 ) ) )
973 double increment = tolerance;
977 tolerance = std::min( tolerance, radius * 2 );
978 double halfAngle = std::acos( -tolerance / radius + 1 );
979 increment = 2 * halfAngle;
983 double a1 = std::atan2( circlePoint1.
y() - centerY, circlePoint1.
x() - centerX );
984 double a2 = std::atan2( circlePoint2.
y() - centerY, circlePoint2.
x() - centerX );
985 double a3 = std::atan2( circlePoint3.
y() - centerY, circlePoint3.
x() - centerX );
988 const bool symmetric =
true;
991 double angle = a3 - a1;
996 int segs = ceil(
angle / increment );
998 increment =
angle / segs;
1012 QVector<QgsPoint> stringPoints;
1013 stringPoints.insert( 0, circlePoint1 );
1014 if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 )
1028 double tolError = increment / 100;
1029 double stopAngle = a3 - tolError;
1030 for (
double angle = a1 + increment;
angle < stopAngle;
angle += increment )
1032 x = centerX + radius * std::cos(
angle );
1033 y = centerY + radius * std::sin(
angle );
1044 stringPoints.insert( stringPoints.size(),
QgsPoint( pointWkbType, x, y, z, m ) );
1047 stringPoints.insert( stringPoints.size(), circlePoint3 );
1052 std::reverse( stringPoints.begin(), stringPoints.end() );
1054 if ( ! points.empty() && stringPoints.front() == points.back() ) stringPoints.pop_front();
1055 points.append( stringPoints );
1060 double side = ( ( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
1085 return zm1 + ( zm2 - zm1 ) * (
angle - a1 ) / ( a2 - a1 );
1087 return zm2 + ( zm3 - zm2 ) * (
angle - a2 ) / ( a3 - a2 );
1093 return zm1 + ( zm2 - zm1 ) * ( a1 -
angle ) / ( a1 - a2 );
1095 return zm2 + ( zm3 - zm2 ) * ( a2 -
angle ) / ( a2 - a3 );
1101 int dim = 2 + is3D + isMeasure;
1104 const QStringList coordList = wktCoordinateList.split(
',', QString::SkipEmptyParts );
1107 bool foundZ =
false;
1108 bool foundM =
false;
1109 QRegularExpression rx( QStringLiteral(
"\\s" ) );
1110 QRegularExpression rxIsNumber( QStringLiteral(
"^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$" ) );
1111 for (
const QString &pointCoordinates : coordList )
1113 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1116 if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() )
1119 if ( coordinates.size() == 3 && !foundZ && !foundM && !is3D && !isMeasure )
1125 else if ( coordinates.size() >= 4 && ( !( is3D || foundZ ) || !( isMeasure || foundM ) ) )
1134 for (
const QString &pointCoordinates : coordList )
1136 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1137 if ( coordinates.size() < dim )
1141 double x = coordinates[idx++].toDouble();
1142 double y = coordinates[idx++].toDouble();
1145 if ( ( is3D || foundZ ) && coordinates.length() > idx )
1146 z = coordinates[idx++].toDouble();
1149 if ( ( isMeasure || foundM ) && coordinates.length() > idx )
1150 m = coordinates[idx++].toDouble();
1153 if ( is3D || foundZ )
1155 if ( isMeasure || foundM )
1162 if ( isMeasure || foundM )
1168 points.append(
QgsPoint( t, x, y, z, m ) );
1176 wkb << static_cast<quint32>( points.size() );
1177 for (
const QgsPoint &point : points )
1179 wkb << point.x() << point.y();
1193 QString wkt = QStringLiteral(
"(" );
1202 wkt += QLatin1String(
", " );
1204 if ( wkt.endsWith( QLatin1String(
", " ) ) )
1212 QDomElement elemCoordinates = doc.createElementNS( ns, QStringLiteral(
"coordinates" ) );
1215 QString cs = QStringLiteral(
"," );
1217 QString ts = QStringLiteral(
" " );
1219 elemCoordinates.setAttribute( QStringLiteral(
"cs" ), cs );
1220 elemCoordinates.setAttribute( QStringLiteral(
"ts" ), ts );
1222 QString strCoordinates;
1225 if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
1230 if ( strCoordinates.endsWith( ts ) )
1231 strCoordinates.chop( 1 );
1233 elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
1234 return elemCoordinates;
1239 QDomElement elemPosList = doc.createElementNS( ns, QStringLiteral(
"posList" ) );
1240 elemPosList.setAttribute( QStringLiteral(
"srsDimension" ), is3D ? 3 : 2 );
1242 QString strCoordinates;
1245 if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
1252 if ( strCoordinates.endsWith(
' ' ) )
1253 strCoordinates.chop( 1 );
1255 elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
1261 QString json = QStringLiteral(
"[ " );
1266 if ( json.endsWith( QLatin1String(
", " ) ) )
1277 json coordinates( json::array() );
1294 double clippedAngle =
angle;
1295 if ( clippedAngle >= M_PI * 2 || clippedAngle <= -2 * M_PI )
1297 clippedAngle = std::fmod( clippedAngle, 2 * M_PI );
1299 if ( clippedAngle < 0.0 )
1301 clippedAngle += 2 * M_PI;
1303 return clippedAngle;
1308 QString wktParsed = wkt;
1310 if ( wkt.contains( QString(
"EMPTY" ), Qt::CaseInsensitive ) )
1312 QRegularExpression wktRegEx( QStringLiteral(
"^\\s*(\\w+)\\s+(\\w+)\\s*$" ) );
1313 wktRegEx.setPatternOptions( QRegularExpression::DotMatchesEverythingOption );
1314 QRegularExpressionMatch match = wktRegEx.match( wkt );
1315 if ( match.hasMatch() )
1317 wktParsed = match.captured( 1 );
1318 contents = match.captured( 2 ).toUpper();
1323 const int openedParenthesisCount = wktParsed.count(
'(' );
1324 const int closedParenthesisCount = wktParsed.count(
')' );
1326 for (
int i = 0 ; i < openedParenthesisCount - closedParenthesisCount; ++i )
1327 wktParsed.push_back(
')' );
1329 wktParsed.truncate( wktParsed.size() - ( closedParenthesisCount - openedParenthesisCount ) );
1331 QRegularExpression cooRegEx( QStringLiteral(
"^[^\\(]*\\((.*)\\)[^\\)]*$" ) );
1332 cooRegEx.setPatternOptions( QRegularExpression::DotMatchesEverythingOption );
1333 QRegularExpressionMatch match = cooRegEx.match( wktParsed );
1334 contents = match.hasMatch() ? match.captured( 1 ) : QString();
1337 return qMakePair( wkbType, contents );
1345 for (
int i = 0, n = wkt.length(); i < n; ++i )
1347 if ( ( wkt[i].isSpace() || wkt[i] ==
'\n' || wkt[i] ==
'\t' ) && level == 0 )
1350 if ( wkt[i] ==
',' && level == 0 )
1352 if ( !block.isEmpty() )
1354 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1355 block.prepend( defaultType +
' ' );
1356 blocks.append( block );
1361 if ( wkt[i] ==
'(' )
1363 else if ( wkt[i] ==
')' )
1367 if ( !block.isEmpty() )
1369 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1370 block.prepend( defaultType +
' ' );
1371 blocks.append( block );
1381 double x = ( pt1.
x() + pt2.
x() ) / 2.0;
1382 double y = ( pt1.
y() + pt2.
y() ) / 2.0;
1383 double z = std::numeric_limits<double>::quiet_NaN();
1384 double m = std::numeric_limits<double>::quiet_NaN();
1389 z = ( pt1.
z() + pt2.
z() ) / 2.0;
1395 m = ( pt1.
m() + pt2.
m() ) / 2.0;
1398 return QgsPoint( pType, x, y, z, m );
1403 const double _fraction = 1 - fraction;
1405 p1.
x() * _fraction + p2.
x() * fraction,
1406 p1.
y() * _fraction + p2.
y() * fraction,
1407 p1.
is3D() ? p1.
z() * _fraction + p2.
z() * fraction : std::numeric_limits<double>::quiet_NaN(),
1408 p1.
isMeasure() ? p1.
m() * _fraction + p2.
m() * fraction : std::numeric_limits<double>::quiet_NaN() );
1413 const double deltaX = ( x2 - x1 ) * fraction;
1414 const double deltaY = ( y2 - y1 ) * fraction;
1415 return QgsPointXY( x1 + deltaX, y1 + deltaY );
1423 const double fraction = ( value - v1 ) / ( v2 - v1 );
1429 double delta_x = pt2.
x() - pt1.
x();
1430 double delta_y = pt2.
y() - pt1.
y();
1436 return delta_y / delta_x;
1455 a = pt1.
y() - pt2.
y();
1456 b = pt2.
x() - pt1.
x();
1457 c = pt1.
x() * pt2.
y() - pt1.
y() * pt2.
x();
1467 if ( ( p == s1 ) || ( p == s2 ) )
1485 double y = ( -
c - a * p.
x() ) / b;
1487 double d2 = 1 + m * m;
1488 double H = p.
y() - y;
1489 double dx = m * H / d2;
1502 double at = std::atan2( y2 - y1, x2 - x1 );
1503 double a = -at + M_PI_2;
1509 double angle1 = std::atan2( y1 - y2, x1 - x2 );
1510 double angle2 = std::atan2( y3 - y2, x3 - x2 );
1524 double a1 =
lineAngle( x1, y1, x2, y2 );
1525 double a2 =
lineAngle( x2, y2, x3, y3 );
1533 double clockwiseDiff = 0.0;
1536 clockwiseDiff = a2 - a1;
1540 clockwiseDiff = a2 + ( 2 * M_PI - a1 );
1542 double counterClockwiseDiff = 2 * M_PI - clockwiseDiff;
1544 double resultAngle = 0;
1545 if ( clockwiseDiff <= counterClockwiseDiff )
1547 resultAngle = a1 + clockwiseDiff / 2.0;
1551 resultAngle = a1 - counterClockwiseDiff / 2.0;
1562 if ( u3.
length() == 0 )
return 1;
1579 if ( std::fabs( u3.
x() ) <= epsilon &&
1580 std::fabs( u3.
y() ) <= epsilon &&
1581 std::fabs( u3.
z() ) <= epsilon )
1593 if ( !( std::fabs( b1 ) > epsilon ) )
1598 if ( !( a2 != -1 && a2 != 1 ) )
1604 double r1 = ( c2 - b2 * c1 / b1 ) / ( a2 - b2 * a1 / b1 );
1620 bool isIntersection;
1629 intersection.
set( ptInter.
x(), ptInter.
y(), La1.
z() );
1669 if ( !firstIsDone || !secondIsDone )
1675 intersection = ( X1 + X2 ) / 2.0;
1681 return 0.5 * std::abs( ( aX - cX ) * ( bY - aY ) - ( aX - bX ) * ( cY - aY ) );
1685 double weightB,
double weightC,
double &pointX,
double &pointY )
1688 if ( weightB + weightC > 1 )
1690 weightB = 1 - weightB;
1691 weightC = 1 - weightC;
1694 const double rBx = weightB * ( bX - aX );
1695 const double rBy = weightB * ( bY - aY );
1696 const double rCx = weightC * ( cX - aX );
1697 const double rCy = weightC * ( cY - aY );
1699 pointX = rBx + rCx + aX;
1700 pointY = rBy + rCy + aY;
1707 for (
const QgsPoint &pt : points )
1712 point.
setZ( pt.z() );
1731 bool intersection =
false;
1737 return intersection;
1749 bool intersection =
false;
1755 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 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 setZValueFromPoints(const QgsPointSequence &points, QgsPoint &point)
A Z dimension is added to point if one of the point in the list points is in 3D.
static bool 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 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 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 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 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,...
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
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.