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 const 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 const double t = ( ( ptX - x1 ) * dx + ( ptY - y1 ) * dy ) / ( dx * dx + dy * dy );
229 const double dist = dx * dx + dy * dy;
244 const double area = std::abs(
245 ( linePoint1.
x() - linePoint2.
x() ) * ( point.
y() - linePoint2.
y() ) -
246 ( linePoint1.
y() - linePoint2.
y() ) * ( point.
x() - linePoint2.
x() )
249 const double length = std::sqrt(
250 std::pow( linePoint1.
x() - linePoint2.
x(), 2 ) +
251 std::pow( linePoint1.
y() - linePoint2.
y(), 2 )
254 const double distance = area / length;
255 return qgsDoubleNear( distance, 0.0, epsilon ) ? 0.0 : distance;
260 const double d = v1.
y() * v2.
x() - v1.
x() * v2.
y();
265 const double dx = p2.
x() - p1.
x();
266 const double dy = p2.
y() - p1.
y();
267 const double k = ( dy * v2.
x() - dx * v2.
y() ) / d;
269 intersection =
QgsPoint( p1.
x() + v1.
x() * k, p1.
y() + v1.
y() * k );
279 isIntersection =
false;
283 const double vl = v.
length();
284 const double wl = w.
length();
298 isIntersection =
true;
299 if ( acceptImproperIntersection )
301 if ( ( p1 == q1 ) || ( p1 == q2 ) )
303 intersectionPoint = p1;
306 else if ( ( p2 == q1 ) || ( p2 == q2 ) )
308 intersectionPoint = p2;
315 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( p1.
x(), p1.
y(), q1.
x(), q1.
y(), q2.
x(), q2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
317 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( p2.
x(), p2.
y(), q1.
x(), q1.
y(), q2.
x(), q2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
319 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( q1.
x(), q1.
y(), p1.
x(), p1.
y(), p2.
x(), p2.
y(), x, y, tolerance ), 0.0, tolerance ) ||
321 qgsDoubleNear(
QgsGeometryUtils::sqrDistToLine( q2.
x(), q2.
y(), p1.
x(), p1.
y(), p2.
x(), p2.
y(), x, y, tolerance ), 0.0, tolerance )
328 const double lambdav =
QgsVector( intersectionPoint.
x() - p1.
x(), intersectionPoint.
y() - p1.
y() ) * v;
329 if ( lambdav < 0. + tolerance || lambdav > vl - tolerance )
332 const double lambdaw =
QgsVector( intersectionPoint.
x() - q1.
x(), intersectionPoint.
y() - q1.
y() ) * w;
333 return !( lambdaw < 0. + tolerance || lambdaw >= wl - tolerance );
343 const double x1 = linePoint1.
x() - center.
x();
344 const double y1 = linePoint1.
y() - center.
y();
345 const double x2 = linePoint2.
x() - center.
x();
346 const double y2 = linePoint2.
y() - center.
y();
347 const double dx = x2 - x1;
348 const double dy = y2 - y1;
350 const double dr2 = std::pow( dx, 2 ) + std::pow( dy, 2 );
351 const double d = x1 * y2 - x2 * y1;
353 const double disc = std::pow( radius, 2 ) * dr2 - std::pow( d, 2 );
363 const int sgnDy = dy < 0 ? -1 : 1;
365 const double sqrDisc = std::sqrt( disc );
367 const double ax = center.
x() + ( d * dy + sgnDy * dx * sqrDisc ) / dr2;
368 const double ay = center.
y() + ( -d * dx + std::fabs( dy ) * sqrDisc ) / dr2;
371 const double bx = center.
x() + ( d * dy - sgnDy * dx * sqrDisc ) / dr2;
372 const double by = center.
y() + ( -d * dx - std::fabs( dy ) * sqrDisc ) / dr2;
379 intersection.
set( p1.
x(), p1.
y() );
383 intersection.
set( p2.
x(), p2.
y() );
394 const double d = center1.
distance( center2 );
397 if ( d > ( r1 + r2 ) )
402 else if ( d < std::fabs( r1 - r2 ) )
419 const double a = ( ( r1 * r1 ) - ( r2 * r2 ) + ( d * d ) ) / ( 2.0 * d ) ;
424 const double dx = center2.
x() - center1.
x();
425 const double dy = center2.
y() - center1.
y();
428 const double x2 = center1.
x() + ( dx * a / d );
429 const double y2 = center1.
y() + ( dy * a / d );
434 const double h = std::sqrt( ( r1 * r1 ) - ( a * a ) );
439 const double rx = dy * ( h / d );
440 const double ry = dx * ( h / d );
443 intersection1 =
QgsPointXY( x2 + rx, y2 - ry );
444 intersection2 =
QgsPointXY( x2 - rx, y2 + ry );
458 const double dx = center.
x() - p.
x();
459 const double dy = center.
y() - p.
y();
460 const double distanceSquared = dx * dx + dy * dy;
461 const double radiusSquared = radius * radius;
462 if ( distanceSquared < radiusSquared )
469 const double distanceToTangent = std::sqrt( distanceSquared - radiusSquared );
481 if ( radius1 > radius2 )
484 const double radius2a = radius2 - radius1;
493 QgsVector v1( -( line1P2.
y() - center1.
y() ), line1P2.
x() - center1.
x() );
494 const double v1Length = v1.
length();
495 v1 = v1 * ( radius1 / v1Length );
498 line1P1 = center1 + v1;
499 line1P2 = line1P2 + v1;
503 QgsVector v2( line2P2.
y() - center1.
y(), -( line2P2.
x() - center1.
x() ) );
504 const double v2Length = v2.
length();
505 v2 = v2 * ( radius1 / v2Length );
508 line2P1 = center1 + v2;
509 line2P2 = line2P2 + v2;
517 if ( radius1 > radius2 )
521 const double d = center1.
distance( center2 );
522 const double radius1a = radius1 + radius2;
539 QgsVector v1( ( line1P2.
y() - center2.
y() ), -( line1P2.
x() - center2.
x() ) );
540 const double v1Length = v1.
length();
541 v1 = v1 * ( radius2 / v1Length );
544 line1P1 = center2 + v1;
545 line1P2 = line1P2 + v1;
549 QgsVector v2( -( line2P2.
y() - center2.
y() ), line2P2.
x() - center2.
x() );
550 const double v2Length = v2.
length();
551 v2 = v2 * ( radius2 / v2Length );
554 line2P1 = center2 + v2;
555 line2P2 = line2P2 + v2;
562 QVector<SelfIntersection> intersections;
568 for (
int i = 0, j = 1; j < n; i = j++ )
575 const int start = j + 1;
576 const int end = i == 0 && isClosed ? n - 1 : n;
577 for (
int k = start, l = start + 1; l < end; k = l++ )
583 bool intersection =
false;
594 intersections.append( s );
597 return intersections;
607 const double f1 = x - x1;
608 const double f2 = y2 - y1;
609 const double f3 = y - y1;
610 const double f4 = x2 - x1;
611 const double test = ( f1 * f2 - f3 * f4 );
613 return qgsDoubleNear( test, 0.0 ) ? 0 : ( test < 0 ? -1 : 1 );
623 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 )
625 const double dx = x2 - x1;
626 const double dy = y2 - y1;
627 const double length = std::sqrt( dx * dx + dy * dy );
640 const double scaleFactor = distance / length;
641 x = x1 + dx * scaleFactor;
642 y = y1 + dy * scaleFactor;
644 *z = *z1 + ( *z2 - *z1 ) * scaleFactor;
646 *m = *m1 + ( *m2 - *m1 ) * scaleFactor;
653 const double mX = x1 + ( x2 - x1 ) * proportion;
654 const double mY = y1 + ( y2 - y1 ) * proportion;
655 const double pX = x1 - x2;
656 const double pY = y1 - y2;
657 double normalX = -pY;
659 const double normalLength = sqrt( ( normalX * normalX ) + ( normalY * normalY ) );
660 normalX /= normalLength;
661 normalY /= normalLength;
663 *x = mX + offset * normalX;
664 *y = mY + offset * normalY;
669 double centerX, centerY, radius;
672 const double theta = distance / radius;
673 const double anglePt1 = std::atan2( pt1.
y() - centerY, pt1.
x() - centerX );
674 const double anglePt2 = std::atan2( pt2.
y() - centerY, pt2.
x() - centerX );
675 const double anglePt3 = std::atan2( pt3.
y() - centerY, pt3.
x() - centerX );
677 const double angleDest = anglePt1 + (
isClockwise ? -theta : theta );
679 const double x = centerX + radius * ( std::cos( angleDest ) );
680 const double y = centerY + radius * ( std::sin( angleDest ) );
682 const double z = pt1.
is3D() ?
694 const double angle = std::atan2( dy, dx ) * 180 / M_PI;
699 else if (
angle > 360 )
708 double dx21, dy21, dx31, dy31, h21, h31, d;
713 centerX = ( pt1.
x() + pt2.
x() ) / 2.0;
714 centerY = ( pt1.
y() + pt2.
y() ) / 2.0;
715 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
720 dx21 = pt2.
x() - pt1.
x();
721 dy21 = pt2.
y() - pt1.
y();
722 dx31 = pt3.
x() - pt1.
x();
723 dy31 = pt3.
y() - pt1.
y();
725 h21 = std::pow( dx21, 2.0 ) + std::pow( dy21, 2.0 );
726 h31 = std::pow( dx31, 2.0 ) + std::pow( dy31, 2.0 );
729 d = 2 * ( dx21 * dy31 - dx31 * dy21 );
739 centerX = pt1.
x() + ( h21 * dy31 - h31 * dy21 ) / d;
740 centerY = pt1.
y() - ( h21 * dx31 - h31 * dx21 ) / d;
741 radius = std::sqrt( std::pow( centerX - pt1.
x(), 2.0 ) + std::pow( centerY - pt1.
y(), 2.0 ) );
746 if ( angle3 >= angle1 )
748 return !( angle2 > angle1 && angle2 < angle3 );
752 return !( angle2 > angle1 || angle2 < angle3 );
760 if ( angle2 < angle1 )
762 return ( angle <= angle1 && angle >= angle2 );
766 return ( angle <= angle1 || angle >= angle2 );
771 if ( angle2 > angle1 )
773 return (
angle >= angle1 &&
angle <= angle2 );
777 return (
angle >= angle1 ||
angle <= angle2 );
790 double centerX, centerY, radius;
792 double length = M_PI / 180.0 * radius *
sweepAngle( centerX, centerY, x1, y1, x2, y2, x3, y3 );
806 if ( p3Angle >= p1Angle )
808 if ( p2Angle > p1Angle && p2Angle < p3Angle )
810 return ( p3Angle - p1Angle );
814 return ( - ( p1Angle + ( 360 - p3Angle ) ) );
819 if ( p2Angle < p1Angle && p2Angle > p3Angle )
821 return ( -( p1Angle - p3Angle ) );
825 return ( p3Angle + ( 360 - p1Angle ) );
832 const QgsPoint midPoint( ( p1.
x() + p2.
x() ) / 2.0, ( p1.
y() + p2.
y() ) / 2.0 );
833 const double midDist = std::sqrt(
sqrDistance2D( p1, midPoint ) );
834 if ( radius < midDist )
838 const double centerMidDist = std::sqrt( radius * radius - midDist * midDist );
839 const double dist = radius - centerMidDist;
841 const double midDx = midPoint.
x() - p1.
x();
842 const double midDy = midPoint.
y() - p1.
y();
845 QVector<QgsPoint> possibleMidPoints;
852 double minDist = std::numeric_limits<double>::max();
853 int minDistIndex = -1;
854 for (
int i = 0; i < possibleMidPoints.size(); ++i )
856 const double currentDist =
sqrDistance2D( mousePos, possibleMidPoints.at( i ) );
857 if ( currentDist < minDist )
860 minDist = currentDist;
864 if ( minDistIndex == -1 )
869 result = possibleMidPoints.at( minDistIndex );
881 if ( !useShortestArc )
882 midPointAngle += M_PI;
883 return center.
project( center.
distance( p1 ), midPointAngle * 180 / M_PI );
890 double mX, mY, radius;
923 const double bDistance = std::sqrt( ( b.
x() - centerX ) * ( b.
x() - centerX ) +
924 ( b.
y() - centerY ) * ( b.
y() - centerY ) );
926 double diff = std::fabs( radius - bDistance );
930 const double abX = b.x() - a.
x();
931 const double abY = b.y() - a.
y();
933 const double cbX = b.x() -
c.x();
934 const double cbY = b.y() -
c.y();
936 const double dot = ( abX * cbX + abY * cbY );
937 const double cross = ( abX * cbY - abY * cbX );
939 const double alpha = std::atan2( cross, dot );
945 if ( diff < distanceTolerance )
947 const double angle1 = arcAngle( a1, a2, a3 );
948 const double angle2 = arcAngle( a2, a3, b );
953 diff = std::fabs( angle1 - angle2 );
954 if ( diff > pointSpacingAngleTolerance )
959 const int a2Side =
leftOfLine( a2.
x(), a2.
y(), a1.
x(), a1.
y(), a3.
x(), a3.
y() );
960 const int bSide =
leftOfLine( b.x(), b.y(), a1.
x(), a1.
y(), a3.
x(), a3.
y() );
964 if ( bSide != a2Side )
972 bool reversed =
false;
996 circleCenterRadius( circlePoint1, circlePoint2, circlePoint3, radius, centerX, centerY );
998 if ( circlePoint1 != circlePoint3 && ( radius < 0 ||
qgsDoubleNear( segSide, 0.0 ) ) )
1000 points.append( p1 );
1001 points.append( p2 );
1002 points.append( p3 );
1006 double increment = tolerance;
1010 tolerance = std::min( tolerance, radius * 2 );
1011 const double halfAngle = std::acos( -tolerance / radius + 1 );
1012 increment = 2 * halfAngle;
1016 const double a1 = std::atan2( circlePoint1.
y() - centerY, circlePoint1.
x() - centerX );
1017 double a2 = std::atan2( circlePoint2.
y() - centerY, circlePoint2.
x() - centerX );
1018 double a3 = std::atan2( circlePoint3.
y() - centerY, circlePoint3.
x() - centerX );
1021 const bool symmetric =
true;
1024 double angle = a3 - a1;
1029 const int segs = ceil(
angle / increment );
1031 increment =
angle / segs;
1045 QVector<QgsPoint> stringPoints;
1046 stringPoints.insert( 0, circlePoint1 );
1047 if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 )
1061 const double tolError = increment / 100;
1062 const double stopAngle = a3 - tolError;
1063 for (
double angle = a1 + increment;
angle < stopAngle;
angle += increment )
1065 x = centerX + radius * std::cos(
angle );
1066 y = centerY + radius * std::sin(
angle );
1077 stringPoints.insert( stringPoints.size(),
QgsPoint( pointWkbType, x, y, z, m ) );
1080 stringPoints.insert( stringPoints.size(), circlePoint3 );
1085 std::reverse( stringPoints.begin(), stringPoints.end() );
1087 if ( ! points.empty() && stringPoints.front() == points.back() ) stringPoints.pop_front();
1088 points.append( stringPoints );
1093 const double side = ( ( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
1118 return zm1 + ( zm2 - zm1 ) * (
angle - a1 ) / ( a2 - a1 );
1120 return zm2 + ( zm3 - zm2 ) * (
angle - a2 ) / ( a3 - a2 );
1126 return zm1 + ( zm2 - zm1 ) * ( a1 -
angle ) / ( a1 - a2 );
1128 return zm2 + ( zm3 - zm2 ) * ( a2 -
angle ) / ( a2 - a3 );
1134 const int dim = 2 + is3D + isMeasure;
1137 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1138 const QStringList coordList = wktCoordinateList.split(
',', QString::SkipEmptyParts );
1140 const QStringList coordList = wktCoordinateList.split(
',', Qt::SkipEmptyParts );
1144 bool foundZ =
false;
1145 bool foundM =
false;
1146 const thread_local QRegularExpression rx( QStringLiteral(
"\\s" ) );
1147 const thread_local QRegularExpression rxIsNumber( QStringLiteral(
"^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$" ) );
1148 for (
const QString &pointCoordinates : coordList )
1150 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1151 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1153 const QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
1157 if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() )
1160 if ( coordinates.size() == 3 && !foundZ && !foundM && !is3D && !isMeasure )
1166 else if ( coordinates.size() >= 4 && ( !( is3D || foundZ ) || !( isMeasure || foundM ) ) )
1175 for (
const QString &pointCoordinates : coordList )
1177 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1178 QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
1180 QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
1182 if ( coordinates.size() < dim )
1186 const double x = coordinates[idx++].toDouble();
1187 const double y = coordinates[idx++].toDouble();
1190 if ( ( is3D || foundZ ) && coordinates.length() > idx )
1191 z = coordinates[idx++].toDouble();
1194 if ( ( isMeasure || foundM ) && coordinates.length() > idx )
1195 m = coordinates[idx++].toDouble();
1198 if ( is3D || foundZ )
1200 if ( isMeasure || foundM )
1207 if ( isMeasure || foundM )
1213 points.append(
QgsPoint( t, x, y, z, m ) );
1221 wkb << static_cast<quint32>( points.size() );
1222 for (
const QgsPoint &point : points )
1224 wkb << point.x() << point.y();
1238 QString wkt = QStringLiteral(
"(" );
1247 wkt += QLatin1String(
", " );
1249 if ( wkt.endsWith( QLatin1String(
", " ) ) )
1257 QDomElement elemCoordinates = doc.createElementNS( ns, QStringLiteral(
"coordinates" ) );
1260 const QString cs = QStringLiteral(
"," );
1262 const QString ts = QStringLiteral(
" " );
1264 elemCoordinates.setAttribute( QStringLiteral(
"cs" ), cs );
1265 elemCoordinates.setAttribute( QStringLiteral(
"ts" ), ts );
1267 QString strCoordinates;
1270 if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
1275 if ( strCoordinates.endsWith( ts ) )
1276 strCoordinates.chop( 1 );
1278 elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
1279 return elemCoordinates;
1284 QDomElement elemPosList = doc.createElementNS( ns, QStringLiteral(
"posList" ) );
1285 elemPosList.setAttribute( QStringLiteral(
"srsDimension" ), is3D ? 3 : 2 );
1287 QString strCoordinates;
1290 if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
1297 if ( strCoordinates.endsWith(
' ' ) )
1298 strCoordinates.chop( 1 );
1300 elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
1306 QString json = QStringLiteral(
"[ " );
1311 if ( json.endsWith( QLatin1String(
", " ) ) )
1322 json coordinates( json::array() );
1339 double clippedAngle =
angle;
1340 if ( clippedAngle >= M_PI * 2 || clippedAngle <= -2 * M_PI )
1342 clippedAngle = std::fmod( clippedAngle, 2 * M_PI );
1344 if ( clippedAngle < 0.0 )
1346 clippedAngle += 2 * M_PI;
1348 return clippedAngle;
1353 QString wktParsed = wkt;
1355 if ( wkt.contains( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) )
1357 const thread_local QRegularExpression sWktRegEx( QStringLiteral(
"^\\s*(\\w+)\\s+(\\w+)\\s*$" ), QRegularExpression::DotMatchesEverythingOption );
1358 const QRegularExpressionMatch match = sWktRegEx.match( wkt );
1359 if ( match.hasMatch() )
1361 wktParsed = match.captured( 1 );
1362 contents = match.captured( 2 ).toUpper();
1367 const int openedParenthesisCount = wktParsed.count(
'(' );
1368 const int closedParenthesisCount = wktParsed.count(
')' );
1370 for (
int i = 0 ; i < openedParenthesisCount - closedParenthesisCount; ++i )
1371 wktParsed.push_back(
')' );
1373 wktParsed.truncate( wktParsed.size() - ( closedParenthesisCount - openedParenthesisCount ) );
1375 const thread_local QRegularExpression cooRegEx( QStringLiteral(
"^[^\\(]*\\((.*)\\)[^\\)]*$" ), QRegularExpression::DotMatchesEverythingOption );
1376 const QRegularExpressionMatch match = cooRegEx.match( wktParsed );
1377 contents = match.hasMatch() ? match.captured( 1 ) : QString();
1380 return qMakePair( wkbType, contents );
1387 block.reserve( wkt.size() );
1390 const QChar *wktData = wkt.data();
1391 const int wktLength = wkt.length();
1392 for (
int i = 0, n = wktLength; i < n; ++i, ++wktData )
1394 if ( ( wktData->isSpace() || *wktData ==
'\n' || *wktData ==
'\t' ) && level == 0 )
1397 if ( *wktData ==
',' && level == 0 )
1399 if ( !block.isEmpty() )
1401 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1402 block.prepend( defaultType +
' ' );
1403 blocks.append( block );
1408 if ( *wktData ==
'(' )
1410 else if ( *wktData ==
')' )
1414 if ( !block.isEmpty() )
1416 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1417 block.prepend( defaultType +
' ' );
1418 blocks.append( block );
1426 if ( x <= left && y <= bottom )
1428 const double dx = left - x;
1429 const double dy = bottom - y;
1437 else if ( x >= right && y >= top )
1439 const double dx = x - right;
1440 const double dy = y - top;
1448 else if ( x >= right && y <= bottom )
1450 const double dx = x - right;
1451 const double dy = bottom - y;
1459 else if ( x <= left && y >= top )
1461 const double dx = left - x;
1462 const double dy = y - top;
1470 else if ( x <= left )
1472 else if ( x >= right )
1474 else if ( y <= bottom )
1476 else if ( y >= top )
1480 const double smallestX = std::min( right - x, x - left );
1481 const double smallestY = std::min( top - y, y - bottom );
1482 if ( smallestX < smallestY )
1485 if ( right - x < x - left )
1493 if ( top - y < y - bottom )
1505 const double x = ( pt1.
x() + pt2.
x() ) / 2.0;
1506 const double y = ( pt1.
y() + pt2.
y() ) / 2.0;
1507 double z = std::numeric_limits<double>::quiet_NaN();
1508 double m = std::numeric_limits<double>::quiet_NaN();
1513 z = ( pt1.
z() + pt2.
z() ) / 2.0;
1519 m = ( pt1.
m() + pt2.
m() ) / 2.0;
1522 return QgsPoint( pType, x, y, z, m );
1527 const double _fraction = 1 - fraction;
1529 p1.
x() * _fraction + p2.
x() * fraction,
1530 p1.
y() * _fraction + p2.
y() * fraction,
1531 p1.
is3D() ? p1.
z() * _fraction + p2.
z() * fraction : std::numeric_limits<double>::quiet_NaN(),
1532 p1.
isMeasure() ? p1.
m() * _fraction + p2.
m() * fraction : std::numeric_limits<double>::quiet_NaN() );
1537 const double deltaX = ( x2 - x1 ) * fraction;
1538 const double deltaY = ( y2 - y1 ) * fraction;
1539 return QgsPointXY( x1 + deltaX, y1 + deltaY );
1547 const double fraction = ( value - v1 ) / ( v2 - v1 );
1553 const double delta_x = pt2.
x() - pt1.
x();
1554 const double delta_y = pt2.
y() - pt1.
y();
1560 return delta_y / delta_x;
1579 a = pt1.
y() - pt2.
y();
1580 b = pt2.
x() - pt1.
x();
1581 c = pt1.
x() * pt2.
y() - pt1.
y() * pt2.
x();
1591 if ( ( p == s1 ) || ( p == s2 ) )
1609 const double y = ( -
c - a * p.
x() ) / b;
1610 const double m =
gradient( s1, s2 );
1611 const double d2 = 1 + m * m;
1612 const double H = p.
y() - y;
1613 const double dx = m * H / d2;
1614 const double dy = m * dx;
1624 void QgsGeometryUtils::perpendicularCenterSegment(
double pointx,
double pointy,
double segmentPoint1x,
double segmentPoint1y,
double segmentPoint2x,
double segmentPoint2y,
double &perpendicularSegmentPoint1x,
double &perpendicularSegmentPoint1y,
double &perpendicularSegmentPoint2x,
double &perpendicularSegmentPoint2y,
double desiredSegmentLength )
1626 QgsVector segmentVector =
QgsVector( segmentPoint2x - segmentPoint1x, segmentPoint2y - segmentPoint1y );
1628 if ( desiredSegmentLength )
1630 if ( desiredSegmentLength != 0 )
1632 perpendicularVector = perpendicularVector.
normalized() * ( desiredSegmentLength ) / 2;
1635 perpendicularSegmentPoint1x = pointx - perpendicularVector.
x();
1636 perpendicularSegmentPoint1y = pointy - perpendicularVector.
y();
1637 perpendicularSegmentPoint2x = pointx + perpendicularVector.
x();
1638 perpendicularSegmentPoint2y = pointy + perpendicularVector.
y();
1643 const double at = std::atan2( y2 - y1, x2 - x1 );
1644 const double a = -at + M_PI_2;
1650 const double angle1 = std::atan2( y1 - y2, x1 - x2 );
1651 const double angle2 = std::atan2( y3 - y2, x3 - x2 );
1665 const double a1 =
lineAngle( x1, y1, x2, y2 );
1666 const double a2 =
lineAngle( x2, y2, x3, y3 );
1674 double clockwiseDiff = 0.0;
1677 clockwiseDiff = a2 - a1;
1681 clockwiseDiff = a2 + ( 2 * M_PI - a1 );
1683 const double counterClockwiseDiff = 2 * M_PI - clockwiseDiff;
1685 double resultAngle = 0;
1686 if ( clockwiseDiff <= counterClockwiseDiff )
1688 resultAngle = a1 + clockwiseDiff / 2.0;
1692 resultAngle = a1 - counterClockwiseDiff / 2.0;
1703 if ( u3.
length() == 0 )
return 1;
1720 if ( std::fabs( u3.
x() ) <= epsilon &&
1721 std::fabs( u3.
y() ) <= epsilon &&
1722 std::fabs( u3.
z() ) <= epsilon )
1734 if ( !( std::fabs( b1 ) > epsilon ) )
1739 if ( !( a2 != -1 && a2 != 1 ) )
1745 const double r1 = ( c2 - b2 * c1 / b1 ) / ( a2 - b2 * a1 / b1 );
1761 bool isIntersection;
1770 intersection.
set( ptInter.
x(), ptInter.
y(), La1.
z() );
1810 if ( !firstIsDone || !secondIsDone )
1816 intersection = ( X1 + X2 ) / 2.0;
1822 return 0.5 * std::abs( ( aX - cX ) * ( bY - aY ) - ( aX - bX ) * ( cY - aY ) );
1826 double weightB,
double weightC,
double &pointX,
double &pointY )
1829 if ( weightB + weightC > 1 )
1831 weightB = 1 - weightB;
1832 weightC = 1 - weightC;
1835 const double rBx = weightB * ( bX - aX );
1836 const double rBy = weightB * ( bY - aY );
1837 const double rCx = weightC * ( cX - aX );
1838 const double rCy = weightC * ( cY - aY );
1840 pointX = rBx + rCx + aX;
1841 pointY = rBy + rCy + aY;
1848 for (
const QgsPoint &pt : points )
1850 if ( pt.isMeasure() )
1853 point.
setM( pt.m() );
1866 for (
const QgsPoint &pt : points )
1871 point.
setZ( pt.z() );
1890 bool intersection =
false;
1896 return intersection;
1908 bool intersection =
false;
1914 return intersection;