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 )
136 double currentDist = 0;
141 if ( vertexId ==
id )
155 double currentDist = 0;
184 if ( currentDist > distance )
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 )
927 int bSide =
leftOfLine( b.x(), b.y(), a1.
x(), a1.
y(), a3.
x(), a3.
y() );
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 );
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 )
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() );