20#include <nlohmann/json.hpp>
34#include <QRegularExpression>
39using namespace Qt::StringLiterals;
43 QVector< QgsLineString * > linestrings;
47 QVector< const QgsAbstractGeometry * > geometries;
49 while ( !geometries.isEmpty() )
54 linestrings << static_cast< QgsLineString * >( curve->segmentize() );
58 for (
int i = 0; i < collection->numGeometries(); ++i )
60 geometries.append( collection->geometryN( i ) );
65 if ( curvePolygon->exteriorRing() )
66 linestrings << static_cast< QgsLineString * >( curvePolygon->exteriorRing()->segmentize() );
68 for (
int i = 0; i < curvePolygon->numInteriorRings(); ++i )
70 linestrings << static_cast< QgsLineString * >( curvePolygon->interiorRing( i )->segmentize() );
79 double minDist = std::numeric_limits<double>::max();
80 double currentDist = 0;
97 if ( currentDist <= minDist )
99 minDist = currentDist;
100 minDistPoint = vertex;
101 id.part = vertexId.
part;
102 id.ring = vertexId.
ring;
103 id.vertex = vertexId.
vertex;
104 id.type = vertexId.
type;
119 if ( vertexAfter.
vertex > 0 )
124 const double length = pointBefore.
distance( pointAfter );
134 closestPoint.addZValue( pointBefore.
z() + ( pointAfter.
z() - pointBefore.
z() ) * distance / length );
136 closestPoint.addMValue( pointBefore.
m() + ( pointAfter.
m() - pointBefore.
m() ) * distance / length );
146 double currentDist = 0;
151 if ( vertexId ==
id )
165 double currentDist = 0;
180 nextVertex = previousVertex;
185 while ( currentDist < distance && geometry.
nextVertex( nextVertex, point ) )
187 if ( !first && nextVertex.
part == previousVertex.
part && nextVertex.
ring == previousVertex.
ring )
195 previousVertex = nextVertex;
199 if ( currentDist > distance )
204 previousVertex = nextVertex;
205 previousPoint = point;
215 const double area = std::abs( ( linePoint1.
x() - linePoint2.
x() ) * ( point.
y() - linePoint2.
y() ) - ( linePoint1.
y() - linePoint2.
y() ) * ( point.
x() - linePoint2.
x() ) );
217 const double length = std::sqrt( std::pow( linePoint1.
x() - linePoint2.
x(), 2 ) + std::pow( linePoint1.
y() - linePoint2.
y(), 2 ) );
219 const double distance = area / length;
220 return qgsDoubleNear( distance, 0.0, epsilon ) ? 0.0 : distance;
227 const double x1 = linePoint1.
x() - center.
x();
228 const double y1 = linePoint1.
y() - center.
y();
229 const double x2 = linePoint2.
x() - center.
x();
230 const double y2 = linePoint2.
y() - center.
y();
231 const double dx = x2 - x1;
232 const double dy = y2 - y1;
234 const double dr2 = std::pow( dx, 2 ) + std::pow( dy, 2 );
235 const double d = x1 * y2 - x2 * y1;
237 const double disc = std::pow( radius, 2 ) * dr2 - std::pow( d, 2 );
247 const int sgnDy = dy < 0 ? -1 : 1;
249 const double sqrDisc = std::sqrt( disc );
251 const double ax = center.
x() + ( d * dy + sgnDy * dx * sqrDisc ) / dr2;
252 const double ay = center.
y() + ( -d * dx + std::fabs( dy ) * sqrDisc ) / dr2;
255 const double bx = center.
x() + ( d * dy - sgnDy * dx * sqrDisc ) / dr2;
256 const double by = center.
y() + ( -d * dx - std::fabs( dy ) * sqrDisc ) / dr2;
263 intersection.
set( p1.
x(), p1.
y() );
267 intersection.
set( p2.
x(), p2.
y() );
278 const double d = center1.
distance( center2 );
282 const bool singleSolutionInt =
qgsDoubleNear( d, std::fabs( r1 - r2 ) );
285 if ( !singleSolutionExt && d > ( r1 + r2 ) )
290 else if ( !singleSolutionInt && d < std::fabs( r1 - r2 ) )
310 const double a = singleSolutionExt ? r1 : ( singleSolutionInt ? ( r1 > r2 ? r1 : -r1 ) : ( ( r1 * r1 ) - ( r2 * r2 ) + ( d * d ) ) / ( 2.0 * d ) );
315 const double dx = center2.
x() - center1.
x();
316 const double dy = center2.
y() - center1.
y();
319 const double x2 = center1.
x() + ( dx * a / d );
320 const double y2 = center1.
y() + ( dy * a / d );
323 if ( singleSolutionExt || singleSolutionInt )
336 const double h = std::sqrt( ( r1 * r1 ) - ( a * a ) );
341 const double rx = dy * ( h / d );
342 const double ry = dx * ( h / d );
345 intersection1 =
QgsPointXY( x2 + rx, y2 - ry );
346 intersection2 =
QgsPointXY( x2 - rx, y2 + ry );
356 const double dx = center.
x() - p.
x();
357 const double dy = center.
y() - p.
y();
358 const double distanceSquared = dx * dx + dy * dy;
359 const double radiusSquared = radius * radius;
360 if ( distanceSquared < radiusSquared )
367 const double distanceToTangent = std::sqrt( distanceSquared - radiusSquared );
381 if ( radius1 > radius2 )
384 const double radius2a = radius2 - radius1;
393 QgsVector v1( -( line1P2.
y() - center1.
y() ), line1P2.
x() - center1.
x() );
394 const double v1Length = v1.
length();
395 v1 = v1 * ( radius1 / v1Length );
398 line1P1 = center1 + v1;
399 line1P2 = line1P2 + v1;
403 QgsVector v2( line2P2.
y() - center1.
y(), -( line2P2.
x() - center1.
x() ) );
404 const double v2Length = v2.
length();
405 v2 = v2 * ( radius1 / v2Length );
408 line2P1 = center1 + v2;
409 line2P2 = line2P2 + v2;
419 if ( radius1 > radius2 )
423 const double d = center1.
distance( center2 );
424 const double radius1a = radius1 + radius2;
441 QgsVector v1( ( line1P2.
y() - center2.
y() ), -( line1P2.
x() - center2.
x() ) );
442 const double v1Length = v1.
length();
443 v1 = v1 * ( radius2 / v1Length );
446 line1P1 = center2 + v1;
447 line1P2 = line1P2 + v1;
451 QgsVector v2( -( line2P2.
y() - center2.
y() ), line2P2.
x() - center2.
x() );
452 const double v2Length = v2.
length();
453 v2 = v2 * ( radius2 / v2Length );
456 line2P1 = center2 + v2;
457 line2P2 = line2P2 + v2;
464 QVector<SelfIntersection> intersections;
470 for (
int i = 0, j = 1; j < n; i = j++ )
478 const int start = j + 1;
479 const int end = i == 0 && isClosed ? n - 1 : n;
480 for (
int k = start, l = start + 1; l < end; k = l++ )
486 bool intersection =
false;
498 intersections.append( s );
501 return intersections;
519 double centerX, centerY, radius;
522 const double theta = distance / radius;
523 const double anglePt1 = std::atan2( pt1.
y() - centerY, pt1.
x() - centerX );
524 const double anglePt2 = std::atan2( pt2.
y() - centerY, pt2.
x() - centerX );
525 const double anglePt3 = std::atan2( pt3.
y() - centerY, pt3.
x() - centerX );
527 const double angleDest = anglePt1 + (
isClockwise ? -theta : theta );
529 const double x = centerX + radius * ( std::cos( angleDest ) );
530 const double y = centerY + radius * ( std::sin( angleDest ) );
544 double z = std::numeric_limits<double>::quiet_NaN();
545 double m = std::numeric_limits<double>::quiet_NaN();
547 QgsGeometryUtilsBase::interpolatePointOnCubicBezier( p0.
x(), p0.
y(), p0.
z(), p0.
m(), p1.
x(), p1.
y(), p1.
z(), p1.
m(), p2.
x(), p2.
y(), p2.
z(), p2.
m(), p3.
x(), p3.
y(), p3.
z(), p3.
m(), t, hasZ, hasM, x, y, z, m );
557 return QgsPoint( wkbType, x, y, z, m );
587 const double t1 = 1.0 - t;
588 const double t1_2 = t1 * t1;
589 const double t1_3 = t1_2 * t1;
590 const double t_2 = t * t;
591 const double t_3 = t_2 * t;
593 outX = t1_3 * p0x + 3.0 * t1_2 * t * p1x + 3.0 * t1 * t_2 * p2x + t_3 * p3x;
594 outY = t1_3 * p0y + 3.0 * t1_2 * t * p1y + 3.0 * t1 * t_2 * p2y + t_3 * p3y;
598 outZ = t1_3 * p0z + 3.0 * t1_2 * t * p1z + 3.0 * t1 * t_2 * p2z + t_3 * p3z;
603 outM = t1_3 * p0m + 3.0 * t1_2 * t * p1m + 3.0 * t1 * t_2 * p2m + t_3 * p3m;
609 const QgsPoint midPoint( ( p1.
x() + p2.
x() ) / 2.0, ( p1.
y() + p2.
y() ) / 2.0 );
610 const double midDist = std::sqrt(
sqrDistance2D( p1, midPoint ) );
611 if ( radius < midDist )
615 const double centerMidDist = std::sqrt( radius * radius - midDist * midDist );
616 const double dist = radius - centerMidDist;
618 const double midDx = midPoint.
x() - p1.
x();
619 const double midDy = midPoint.
y() - p1.
y();
622 QVector<QgsPoint> possibleMidPoints;
629 double minDist = std::numeric_limits<double>::max();
630 int minDistIndex = -1;
631 for (
int i = 0; i < possibleMidPoints.size(); ++i )
633 const double currentDist =
sqrDistance2D( mousePos, possibleMidPoints.at( i ) );
634 if ( currentDist < minDist )
637 minDist = currentDist;
641 if ( minDistIndex == -1 )
646 result = possibleMidPoints.at( minDistIndex );
658 if ( !useShortestArc )
659 midPointAngle += M_PI;
660 return center.
project( center.
distance( p1 ), midPointAngle * 180 / M_PI );
666 double mX, mY, radius;
699 const double bDistance = std::sqrt( ( b.
x() - centerX ) * ( b.
x() - centerX ) + ( b.
y() - centerY ) * ( b.
y() - centerY ) );
701 double diff = std::fabs( radius - bDistance );
704 const double abX = b.
x() - a.
x();
705 const double abY = b.
y() - a.
y();
707 const double cbX = b.
x() -
c.x();
708 const double cbY = b.
y() -
c.y();
710 const double dot = ( abX * cbX + abY * cbY );
711 const double cross = ( abX * cbY - abY * cbX );
713 const double alpha = std::atan2( cross, dot );
719 if ( diff < distanceTolerance )
721 const double angle1 = arcAngle( a1, a2, a3 );
722 const double angle2 = arcAngle( a2, a3, b );
727 diff = std::fabs( angle1 - angle2 );
728 if ( diff > pointSpacingAngleTolerance )
738 if ( bSide != a2Side )
748 bool reversed =
false;
772 circleCenterRadius( circlePoint1, circlePoint2, circlePoint3, radius, centerX, centerY );
774 if ( circlePoint1 != circlePoint3 && ( radius < 0 ||
qgsDoubleNear( segSide, 0.0 ) ) )
782 double increment = tolerance;
786 tolerance = std::min( tolerance, radius * 2 );
787 const double halfAngle = std::acos( -tolerance / radius + 1 );
788 increment = 2 * halfAngle;
792 const double a1 = std::atan2( circlePoint1.
y() - centerY, circlePoint1.
x() - centerX );
793 double a2 = std::atan2( circlePoint2.
y() - centerY, circlePoint2.
x() - centerX );
794 double a3 = std::atan2( circlePoint3.
y() - centerY, circlePoint3.
x() - centerX );
797 const bool symmetric =
true;
800 double angle = a3 - a1;
806 const int segs = ceil( angle / increment );
808 increment = angle / segs;
822 QVector<QgsPoint> stringPoints;
823 stringPoints.insert( 0, circlePoint1 );
824 if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 )
838 const double tolError = increment / 100;
839 const double stopAngle = a3 - tolError;
840 for (
double angle = a1 + increment; angle < stopAngle; angle += increment )
842 x = centerX + radius * std::cos( angle );
843 y = centerY + radius * std::sin( angle );
854 stringPoints.insert( stringPoints.size(),
QgsPoint( pointWkbType, x, y, z, m ) );
857 stringPoints.insert( stringPoints.size(), circlePoint3 );
862 std::reverse( stringPoints.begin(), stringPoints.end() );
864 if ( !points.empty() && stringPoints.front() == points.back() )
865 stringPoints.pop_front();
866 points.append( stringPoints );
871 const double side = ( ( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
892 const int dim = 2 + is3D + isMeasure;
895 const QStringList coordList = wktCoordinateList.split(
',', Qt::SkipEmptyParts );
900 const thread_local QRegularExpression rx( u
"\\s"_s );
901 const thread_local QRegularExpression rxIsNumber( u
"^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$"_s );
902 for (
const QString &pointCoordinates : coordList )
904 const QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
907 if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() )
910 if ( coordinates.size() == 3 && !foundZ && !foundM && !is3D && !isMeasure )
916 else if ( coordinates.size() >= 4 && ( !( is3D || foundZ ) || !( isMeasure || foundM ) ) )
925 for (
const QString &pointCoordinates : coordList )
927 QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
928 if ( coordinates.size() < dim )
932 const double x = coordinates[idx++].toDouble();
933 const double y = coordinates[idx++].toDouble();
936 if ( ( is3D || foundZ ) && coordinates.length() > idx )
937 z = coordinates[idx++].toDouble();
940 if ( ( isMeasure || foundM ) && coordinates.length() > idx )
941 m = coordinates[idx++].toDouble();
944 if ( is3D || foundZ )
946 if ( isMeasure || foundM )
953 if ( isMeasure || foundM )
959 points.append(
QgsPoint( t, x, y, z, m ) );
967 wkb << static_cast<quint32>( points.size() );
968 for (
const QgsPoint &point : points )
970 wkb << point.x() << point.y();
973 double z = point.z();
975 z = -std::numeric_limits<double>::max();
981 double m = point.m();
983 m = -std::numeric_limits<double>::max();
992 QString wkt = u
"("_s;
1003 if ( wkt.endsWith(
", "_L1 ) )
1011 QDomElement elemCoordinates = doc.createElementNS( ns, u
"coordinates"_s );
1014 const QString cs = u
","_s;
1016 const QString ts = u
" "_s;
1018 elemCoordinates.setAttribute( u
"cs"_s, cs );
1019 elemCoordinates.setAttribute( u
"ts"_s, ts );
1021 QString strCoordinates;
1029 if ( strCoordinates.endsWith( ts ) )
1030 strCoordinates.chop( 1 );
1032 elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
1033 return elemCoordinates;
1038 QDomElement elemPosList = doc.createElementNS( ns, u
"posList"_s );
1039 elemPosList.setAttribute( u
"srsDimension"_s, is3D ? 3 : 2 );
1041 QString strCoordinates;
1051 if ( strCoordinates.endsWith(
' ' ) )
1052 strCoordinates.chop( 1 );
1054 elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
1060 QString json = u
"[ "_s;
1065 if ( json.endsWith(
", "_L1 ) )
1076 json coordinates( json::array() );
1081 coordinates.push_back( {
qgsRound( p.x(), precision ),
qgsRound( p.y(), precision ),
qgsRound( p.z(), precision ) } );
1085 coordinates.push_back( {
qgsRound( p.x(), precision ),
qgsRound( p.y(), precision ) } );
1093 QString wktParsed = wkt;
1095 bool isEmpty =
false;
1096 const QLatin1String empty {
"EMPTY" };
1097 if ( wkt.contains( empty, Qt::CaseInsensitive ) )
1099 const thread_local QRegularExpression whiteSpaces(
"\\s" );
1100 wktParsed.remove( whiteSpaces );
1101 const int index = wktParsed.indexOf( empty, 0, Qt::CaseInsensitive );
1103 if ( index == wktParsed.length() - empty.size() )
1107 wktParsed = wktParsed.left( index );
1118 const int openedParenthesisCount = wktParsed.count(
'(' );
1119 const int closedParenthesisCount = wktParsed.count(
')' );
1121 for (
int i = 0; i < openedParenthesisCount - closedParenthesisCount; ++i )
1122 wktParsed.push_back(
')' );
1124 wktParsed.truncate( wktParsed.size() - ( closedParenthesisCount - openedParenthesisCount ) );
1126 const thread_local QRegularExpression cooRegEx( u
"^[^\\(]*\\((.*)\\)[^\\)]*$"_s, QRegularExpression::DotMatchesEverythingOption );
1127 const QRegularExpressionMatch match = cooRegEx.match( wktParsed );
1128 contents = match.hasMatch() ? match.captured( 1 ) : QString();
1131 return qMakePair( wkbType, contents );
1138 block.reserve( wkt.size() );
1141 const QChar *wktData = wkt.data();
1142 const int wktLength = wkt.length();
1143 for (
int i = 0, n = wktLength; i < n; ++i, ++wktData )
1145 if ( ( wktData->isSpace() || *wktData ==
'\n' || *wktData ==
'\t' ) && level == 0 )
1148 if ( *wktData ==
',' && level == 0 )
1150 if ( !block.isEmpty() )
1152 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1153 block.prepend( defaultType +
' ' );
1154 blocks.append( block );
1159 if ( *wktData ==
'(' )
1161 else if ( *wktData ==
')' )
1165 if ( !block.isEmpty() )
1167 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1168 block.prepend( defaultType +
' ' );
1169 blocks.append( block );
1179 const double x = ( pt1.
x() + pt2.
x() ) / 2.0;
1180 const double y = ( pt1.
y() + pt2.
y() ) / 2.0;
1181 double z = std::numeric_limits<double>::quiet_NaN();
1182 double m = std::numeric_limits<double>::quiet_NaN();
1187 z = ( pt1.
z() + pt2.
z() ) / 2.0;
1193 m = ( pt1.
m() + pt2.
m() ) / 2.0;
1196 return QgsPoint( pType, x, y, z, m );
1201 const double _fraction = 1 - fraction;
1204 p1.
x() * _fraction + p2.
x() * fraction,
1205 p1.
y() * _fraction + p2.
y() * fraction,
1206 p1.
is3D() ? p1.
z() * _fraction + p2.
z() * fraction : std::numeric_limits<double>::quiet_NaN(),
1207 p1.
isMeasure() ? p1.
m() * _fraction + p2.
m() * fraction : std::numeric_limits<double>::quiet_NaN()
1213 const double deltaX = ( x2 - x1 ) * fraction;
1214 const double deltaY = ( y2 - y1 ) * fraction;
1215 return QgsPointXY( x1 + deltaX, y1 + deltaY );
1223 const double fraction = ( value - v1 ) / ( v2 - v1 );
1229 const double delta_x = pt2.
x() - pt1.
x();
1230 const double delta_y = pt2.
y() - pt1.
y();
1236 return delta_y / delta_x;
1255 a = pt1.
y() - pt2.
y();
1256 b = pt2.
x() - pt1.
x();
1257 c = pt1.
x() * pt2.
y() - pt1.
y() * pt2.
x();
1266 if ( ( p == s1 ) || ( p == s2 ) )
1284 const double y = ( -
c - a * p.
x() ) / b;
1285 const double m =
gradient( s1, s2 );
1286 const double d2 = 1 + m * m;
1287 const double H = p.
y() - y;
1288 const double dx = m * H / d2;
1289 const double dy = m * dx;
1303 for (
const QgsPoint &pt : points )
1305 if ( pt.isMeasure() )
1308 point.
setM( pt.m() );
1321 for (
const QgsPoint &pt : points )
1326 point.
setZ( pt.z() );
1339 else if ( reference.
is3D() )
1352 if ( segmentStart.
is3D() && segmentEnd.
is3D() )
1354 double z1 = segmentStart.
z();
1355 double z2 = segmentEnd.
z();
1356 double interpolatedZ;
1357 double tempX, tempY;
1359 result.
setZ( interpolatedZ );
1364 double m1 = segmentStart.
m();
1365 double m2 = segmentEnd.
m();
1366 double interpolatedM;
1367 double tempX, tempY;
1368 QgsGeometryUtilsBase::pointOnLineWithDistance( segmentStart.
x(), segmentStart.
y(), segmentEnd.
x(), segmentEnd.
y(), distanceFromStart, tempX, tempY,
nullptr,
nullptr,
nullptr, &m1, &m2, &interpolatedM );
1369 result.
setM( interpolatedM );
1380 double chamferStartX, chamferStartY, chamferEndX, chamferEndY;
1427 double filletPointsX[3], filletPointsY[3];
1457 if ( segment1Start.
is3D() && segment1End.
is3D() && segment2Start.
is3D() && segment2End.
is3D() )
1459 filletMidPoint.
setZ( ( filletPoint1.
z() + filletPoint2.
z() ) / 2.0 );
1463 filletMidPoint.
setM( ( filletPoint1.
m() + filletPoint2.
m() ) / 2.0 );
1474 createFillet( segment1Start, segment1End, segment2Start, segment2End, radius, p1, p2, p3, epsilon );
1475 filletPoints[0] = p1;
1476 filletPoints[1] = p2;
1477 filletPoints[2] = p3;
1486 createChamfer( segment1Start, segment1End, segment2Start, segment2End, distance1, distance2, chamferStart, chamferEnd );
1488 return std::make_unique<QgsLineString>( QVector<QgsPoint> { segment1Start, chamferStart, chamferEnd, segment2Start } );
1496 createFilletArray( segment1Start, segment1End, segment2Start, segment2End, radius, filletPoints );
1499 double intersectionX, intersectionY;
1500 bool isIntersection;
1502 segmentIntersection( segment1Start.
x(), segment1Start.
y(), segment1End.
x(), segment1End.
y(), segment2Start.
x(), segment2Start.
y(), segment2End.
x(), segment2End.
y(), intersectionX, intersectionY, isIntersection, 1e-8,
true );
1504 if ( !isIntersection )
1514 const QgsPoint segment1FarEnd = ( dist1ToStart < dist1ToEnd ) ? segment1End : segment1Start;
1515 const QgsPoint segment2FarEnd = ( dist2ToStart < dist2ToEnd ) ? segment2End : segment2Start;
1517 if ( segments <= 0 )
1520 auto completeCurve = std::make_unique<QgsCompoundCurve>();
1523 auto firstSegment = std::make_unique<QgsLineString>( QVector<QgsPoint> { segment1FarEnd, filletPoints[0] } );
1524 completeCurve->addCurve( firstSegment.release() );
1527 auto circularString = std::make_unique<QgsCircularString>();
1528 circularString->setPoints( { filletPoints[0], filletPoints[1], filletPoints[2] } );
1529 completeCurve->addCurve( circularString.release() );
1532 auto lastSegment = std::make_unique<QgsLineString>( QVector<QgsPoint> { filletPoints[2], segment2FarEnd } );
1533 completeCurve->addCurve( lastSegment.release() );
1535 return completeCurve;
1540 QVector<QgsPoint> points;
1541 points.append( segment1FarEnd );
1545 tempArc.
setPoints( { filletPoints[0], filletPoints[1], filletPoints[2] } );
1550 double angleTolerance = M_PI / 180.0;
1553 double radius, centerX, centerY;
1555 const double arcAngle
1556 = std::abs(
QgsGeometryUtilsBase::sweepAngle( centerX, centerY, filletPoints[0].x(), filletPoints[0].y(), filletPoints[1].x(), filletPoints[1].y(), filletPoints[2].x(), filletPoints[2].y() ) )
1560 angleTolerance = arcAngle / segments * ( 1.0 + 1e-10 );
1565 for (
int i = 0; i < segmentizedArc->numPoints(); ++i )
1567 points.append( segmentizedArc->vertexAt(
QgsVertexId( 0, 0, i ) ) );
1570 points.append( segment2FarEnd );
1572 return std::make_unique<QgsLineString>( points );
1591std::unique_ptr< QgsAbstractGeometry > QgsGeometryUtils::doChamferFilletOnVertex(
1601 if ( vertexIndex < 0 || vertexIndex > curve->
numPoints() - 1 )
1607 throw QgsInvalidArgumentException(
"Opened curve must have at least 3 points." );
1608 if ( vertexIndex <= 0 || vertexIndex >= curve->
numPoints() - 1 )
1609 throw QgsInvalidArgumentException( u
"Vertex index out of range. %1 must be in (0, %2)."_s.arg( vertexIndex ).arg( curve->
numPoints() - 1 ) );
1613 QgsPoint pPrev = curve->
vertexAt( QgsVertexId( 0, 0, vertexIndex - 1 ) );
1614 const QgsPoint p = curve->
vertexAt( QgsVertexId( 0, 0, vertexIndex ) );
1615 QgsPoint pNext = curve->
vertexAt( QgsVertexId( 0, 0, vertexIndex + 1 ) );
1618 if ( vertexIndex - 1 < 0 )
1620 if ( vertexIndex + 1 >= curve->
numPoints() )
1621 pNext = curve->
vertexAt( QgsVertexId( 0, 0, 1 ) );
1624 QgsPoint firstNewPoint, middlePoint, lastNewPoint;
1628 double rad = std::min( value1, pPrev.
distance( p ) * 0.95 );
1629 rad = std::min( rad, pNext.
distance( p ) * 0.95 );
1632 QgsPoint filletPoints[3];
1635 firstNewPoint = filletPoints[0];
1636 middlePoint = filletPoints[1];
1637 lastNewPoint = filletPoints[2];
1642 createChamfer( pPrev, p, p, pNext, value1, value2, firstNewPoint, lastNewPoint );
1645 throw QgsInvalidArgumentException( u
"Operation '%1' is unknown."_s.arg(
qgsEnumValueToKey( operation ) ) );
1650 QVector<QgsPoint> points;
1657 for (
int i = min; i < vertexIndex; ++i )
1659 points.append( curve->
vertexAt( QgsVertexId( 0, 0, i ) ) );
1665 if ( firstNewPoint != pPrev )
1666 points.append( firstNewPoint );
1670 QgsCircularString tempArc;
1671 tempArc.
setPoints( { firstNewPoint, middlePoint, lastNewPoint } );
1675 double radius, centerX, centerY;
1677 const double arcAngle = std::abs(
QgsGeometryUtilsBase::sweepAngle( centerX, centerY, firstNewPoint.
x(), firstNewPoint.
y(), middlePoint.
x(), middlePoint.
y(), lastNewPoint.
x(), lastNewPoint.
y() ) )
1681 const double angleTolerance = arcAngle / segments * ( 1.0 + 1e-10 );
1684 for (
int i = 1; i < segmentizedArc->numPoints() - 1; ++i )
1686 points.append( segmentizedArc->vertexAt( QgsVertexId( 0, 0, i ) ) );
1691 points.append( middlePoint );
1694 if ( lastNewPoint != pNext )
1695 points.append( lastNewPoint );
1699 if ( firstNewPoint != pPrev )
1700 points.append( firstNewPoint );
1701 if ( lastNewPoint != pNext )
1702 points.append( lastNewPoint );
1706 if ( curve->
isClosed() && vertexIndex == 0 )
1709 for (
int i = vertexIndex + 1; i < max; ++i )
1711 points.append( curve->
vertexAt( QgsVertexId( 0, 0, i ) ) );
1714 return std::make_unique<QgsLineString>( points );
1719 auto newCompound = std::make_unique<QgsCompoundCurve>();
1721 int globalVertexIndex = 0;
1722 int targetCurveIndex = -1;
1723 int vertexInCurve = -1;
1725 for (
int curveIdx = 0; curveIdx < compound->nCurves(); ++curveIdx )
1727 const QgsCurve *subcurve = compound->curveAt( curveIdx );
1728 const int subcurvePoints = subcurve->
numPoints();
1730 if ( globalVertexIndex + subcurvePoints > vertexIndex )
1732 targetCurveIndex = curveIdx;
1733 vertexInCurve = vertexIndex - globalVertexIndex;
1736 globalVertexIndex += subcurvePoints - 1;
1739 if ( targetCurveIndex == -1 )
1741 throw QgsInvalidArgumentException(
"While generating output: unable to find curve within compound." );
1744 const QgsCurve *targetCurve = compound->curveAt( targetCurveIndex );
1747 for (
int i = 0; i < targetCurveIndex; ++i )
1749 std::unique_ptr<QgsCurve> tmpCurv( compound->curveAt( i )->clone() );
1752 tmpCurv->insertVertex( QgsVertexId( 0, 0, 1 ), lastNewPoint );
1753 tmpCurv->deleteVertex( QgsVertexId( 0, 0, 0 ) );
1755 newCompound->addCurve( tmpCurv.release() );
1759 if ( vertexInCurve > 0 )
1761 QVector<QgsPoint> beforePoints;
1762 for (
int j = 0; j < vertexInCurve; ++j )
1764 beforePoints.append( targetCurve->
vertexAt( QgsVertexId( 0, 0, j ) ) );
1766 beforePoints.append( firstNewPoint );
1768 if ( beforePoints.size() > 1 )
1770 auto beforeVertex = std::make_unique<QgsLineString>( beforePoints );
1771 newCompound->addCurve( beforeVertex.release() );
1778 if ( segments <= 0 )
1781 auto filletArc = std::make_unique<QgsCircularString>();
1782 filletArc->setPoints( { firstNewPoint, middlePoint, lastNewPoint } );
1783 newCompound->addCurve( filletArc.release() );
1788 QgsCircularString tempArc;
1789 tempArc.
setPoints( { firstNewPoint, middlePoint, lastNewPoint } );
1791 const double angleTolerance = ( 2.0 * M_PI ) / ( 4.0 * segments );
1794 newCompound->addCurve( segmentizedArc.release() );
1799 auto chamferLine = std::make_unique<QgsLineString>( QVector<QgsPoint> { firstNewPoint, lastNewPoint } );
1800 newCompound->addCurve( chamferLine.release() );
1803 if ( vertexInCurve < targetCurve->numPoints() - 1 )
1805 QVector<QgsPoint> afterPoints;
1806 afterPoints.append( lastNewPoint );
1807 for (
int j = vertexInCurve + 1; j < targetCurve->
numPoints(); ++j )
1809 afterPoints.append( targetCurve->
vertexAt( QgsVertexId( 0, 0, j ) ) );
1812 if ( afterPoints.size() > 1 )
1814 auto afterVertex = std::make_unique<QgsLineString>( afterPoints );
1815 newCompound->addCurve( afterVertex.release() );
1820 for (
int i = targetCurveIndex + 1; i < compound->nCurves(); ++i )
1822 std::unique_ptr<QgsCurve> tmpCurv( compound->curveAt( i )->clone() );
1823 if ( curve->
isClosed() && vertexIndex == 0 )
1825 tmpCurv->insertVertex( QgsVertexId( 0, 0, tmpCurv->numPoints() - 1 ), firstNewPoint );
1826 tmpCurv->deleteVertex( QgsVertexId( 0, 0, tmpCurv->numPoints() - 1 ) );
1828 newCompound->addCurve( tmpCurv.release() );
1834 throw QgsInvalidArgumentException(
"While generating output: curse is not a QgsLineString nor a QgsCompoundCurve." );
1864 ring = curvePolygon->exteriorRing();
1870 pt1 = ringIt.
next();
1875 pt2 = ringIt.
next();
1881 pt3 = ringIt.
next();
1895 const double x1 = a.
x(), y1 = a.
y(), z1 = a.
z();
1896 const double x2 = b.
x(), y2 = b.
y(), z2 = b.
z();
1897 const double x3 =
c.x(), y3 =
c.y(), z3 =
c.z();
1899 const double denom = ( ( y2 - y3 ) * ( x1 - x3 ) + ( x3 - x2 ) * ( y1 - y3 ) );
1901 return std::numeric_limits<double>::quiet_NaN();
1903 const double w1 = ( ( y2 - y3 ) * ( x - x3 ) + ( x3 - x2 ) * ( y - y3 ) ) / denom;
1904 const double w2 = ( ( y3 - y1 ) * ( x - x3 ) + ( x1 - x3 ) * ( y - y3 ) ) / denom;
1905 const double w3 = 1.0 - w1 - w2;
1907 const double eps = 1e-9;
1908 if ( w1 < -eps || w2 < -eps || w3 < -eps )
1909 return std::numeric_limits<double>::quiet_NaN();
1911 return w1 * z1 + w2 * z2 + w3 * z3;
static const double DEFAULT_SEGMENT_EPSILON
Default snapping tolerance for segments.
WkbType
The WKB type describes the number of dimensions a geometry has.
Abstract base class for all geometries.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
@ MaximumDifference
Maximum distance between an arbitrary point on the original curve and closest point on its approximat...
@ MaximumAngle
Maximum angle between generating radii (lines from arc center to output vertices).
QgsVertexIterator vertices() const
Returns a read-only, Java-style iterator for traversal of vertices of all the geometry,...
virtual int vertexCount(int part=0, int ring=0) const =0
Returns the number of vertices of which this geometry is built.
bool isMeasure() const
Returns true if the geometry contains m values.
QFlags< WkbFlag > WkbFlags
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
AxisOrder
Axis order for GML generation.
@ XY
X comes before Y (or lon before lat).
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
virtual bool isEmpty() const
Returns true if the geometry is empty.
@ FlagExportNanAsDoubleMin
Use -DOUBLE_MAX to represent NaN.
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.
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.
Circular string geometry type.
void setPoints(const QgsPointSequence &points)
Sets the circular string's points.
QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a new line string geometry corresponding to a segmentized approximation of the curve.
Curve polygon geometry type.
Abstract base class for curved geometry type.
virtual int numPoints() const =0
Returns the number of points in the curve.
virtual bool isClosed() const
Returns true if the curve is closed.
QgsPoint vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
static void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...
static double maximumFilletRadius(const double segment1StartX, const double segment1StartY, const double segment1EndX, const double segment1EndY, const double segment2StartX, const double segment2StartY, const double segment2EndX, const double segment2EndY, double epsilon=1e-8)
Calculates the maximum allowed fillet radius for the given segment configuration.
static double ccwAngle(double dy, double dx)
Returns the counter clockwise angle between a line with components dx, dy and the line with dx > 0 an...
static bool circleClockwise(double angle1, double angle2, double angle3)
Returns true if the circle defined by three angles is ordered clockwise.
static double distance2D(double x1, double y1, double x2, double y2)
Returns the 2D distance between (x1, y1) and (x2, y2).
static double sweepAngle(double centerX, double centerY, double x1, double y1, double x2, double y2, double x3, double y3)
Calculates angle of a circular string part defined by pt1, pt2, pt3.
static bool createChamfer(const double segment1StartX, const double segment1StartY, const double segment1EndX, const double segment1EndY, const double segment2StartX, const double segment2StartY, const double segment2EndX, const double segment2EndY, const double distance1, const double distance2, double &chamferStartX, double &chamferStartY, double &chamferEndX, double &chamferEndY, double *trim1StartX=nullptr, double *trim1StartY=nullptr, double *trim1EndX=nullptr, double *trim1EndY=nullptr, double *trim2StartX=nullptr, double *trim2StartY=nullptr, double *trim2EndX=nullptr, double *trim2EndY=nullptr, const double epsilon=1e-8)
Creates a chamfer (angled corner) between two line segments.
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
static double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3)
Calculates the average angle (in radians) between the two linear segments from (x1,...
static bool points3DAreCollinear(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, double epsilon)
Given the points (x1, y1, z1), (x2, y2, z2) and (x3, y3, z3) returns true if these points can be cons...
static double interpolateArcValue(double angle, double a1, double a2, double a3, double zm1, double zm2, double zm3)
Interpolate a value at given angle on circular arc given values (zm1, zm2, zm3) at three different an...
static void interpolatePointOnCubicBezier(double p0x, double p0y, double p0z, double p0m, double p1x, double p1y, double p1z, double p1m, double p2x, double p2y, double p2z, double p2m, double p3x, double p3y, double p3z, double p3m, double t, bool hasZ, bool hasM, double &outX, double &outY, double &outZ, double &outM)
Evaluates a point on a cubic Bézier curve defined by four control points.
static bool segmentIntersection(double p1x, double p1y, double p2x, double p2y, double q1x, double q1y, double q2x, double q2y, double &intersectionPointX, double &intersectionPointY, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false)
Compute the intersection between two segments.
static int leftOfLine(const double x, const double y, const double x1, const double y1, const double x2, const double y2)
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> (x2, y2).
static bool pointsAreCollinear(double x1, double y1, double x2, double y2, double x3, double y3, double epsilon)
Given the points (x1, y1), (x2, y2) and (x3, y3) returns true if these points can be considered colli...
static bool createFillet(const double segment1StartX, const double segment1StartY, const double segment1EndX, const double segment1EndY, const double segment2StartX, const double segment2StartY, const double segment2EndX, const double segment2EndY, const double radius, double *filletPointsX, double *filletPointsY, double *trim1StartX=nullptr, double *trim1StartY=nullptr, double *trim1EndX=nullptr, double *trim1EndY=nullptr, double *trim2StartX=nullptr, double *trim2StartY=nullptr, double *trim2EndX=nullptr, double *trim2EndY=nullptr, const double epsilon=1e-8)
Creates a fillet (rounded corner) between two line segments.
static int circleCircleIntersections(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &intersection1, QgsPointXY &intersection2)
Calculates the intersections points between the circle with center center1 and radius radius1 and the...
static std::unique_ptr< QgsLineString > createChamferGeometry(const QgsPoint &segment1Start, const QgsPoint &segment1End, const QgsPoint &segment2Start, const QgsPoint &segment2End, double distance1, double distance2)
Creates a complete chamfer geometry connecting two segments.
static QString pointsToJSON(const QgsPointSequence &points, int precision)
Returns a geoJSON coordinates string.
static QgsPointXY interpolatePointOnLine(double x1, double y1, double x2, double y2, double fraction)
Interpolates the position of a point a fraction of the way along the line from (x1,...
static double circleTangentDirection(const QgsPoint &tangentPoint, const QgsPoint &cp1, const QgsPoint &cp2, const QgsPoint &cp3)
Calculates the direction angle of a circle tangent (clockwise from north in radians).
static int leftOfLine(const QgsPoint &point, const QgsPoint &p1, const QgsPoint &p2)
Returns a value < 0 if the point point is left of the line from p1 -> p2.
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance)
Returns a point a specified distance toward a second point.
static double gradient(const QgsPoint &pt1, const QgsPoint &pt2)
Returns the gradient of a line defined by points pt1 and pt2.
static json pointsToJson(const QgsPointSequence &points, int precision)
Returns coordinates as json object.
static double maxFilletRadius(const QgsPoint &segment1Start, const QgsPoint &segment1End, const QgsPoint &segment2Start, const QgsPoint &segment2End, double epsilon=1e-8)
Calculates the maximum allowed fillet radius for the given segment configuration.
static QgsPoint createPointWithMatchingDimensions(double x, double y, const QgsPoint &reference)
Creates a QgsPoint with dimensions matching a reference point.
static QVector< QgsLineString * > extractLineStrings(const QgsAbstractGeometry *geom)
Returns list of linestrings extracted from the passed geometry.
static std::unique_ptr< QgsAbstractGeometry > createFilletGeometry(const QgsPoint &segment1Start, const QgsPoint &segment1End, const QgsPoint &segment2Start, const QgsPoint &segment2End, double radius, int segments)
Creates a complete fillet geometry connecting two segments.
static QgsPoint interpolatePointOnSegment(double x, double y, const QgsPoint &segmentStart, const QgsPoint &segmentEnd)
Interpolates a point on a segment with proper Z and M value interpolation.
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 bool segmentMidPoint(const QgsPoint &p1, const QgsPoint &p2, QgsPoint &result, double radius, const QgsPoint &mousePos)
Calculates midpoint on circle passing through p1 and p2, closest to the given coordinate mousePos.
static QgsPointXY interpolatePointOnLineByValue(double x1, double y1, double v1, double x2, double y2, double v2, double value)
Interpolates the position of a point along the line from (x1, y1) to (x2, y2).
static QgsPoint closestPoint(const QgsAbstractGeometry &geometry, const QgsPoint &point)
Returns the nearest point on a segment of a geometry for the specified point.
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 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)
Compute the intersection between two segments.
static QgsLineString perpendicularSegment(const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2)
Create a perpendicular line segment from p to segment [s1, s2].
static int segmentSide(const QgsPoint &pt1, const QgsPoint &pt3, const QgsPoint &pt2)
For line defined by points pt1 and pt3, find out on which side of the line is point pt2.
static QgsPoint interpolatePointOnCubicBezier(const QgsPoint &p0, const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, double t)
Evaluates a point on a cubic Bézier curve defined by four control points.
static void pointsToWKB(QgsWkbPtr &wkb, const QgsPointSequence &points, bool is3D, bool isMeasure, QgsAbstractGeometry::WkbFlags flags)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
static bool createChamfer(const QgsPoint &segment1Start, const QgsPoint &segment1End, const QgsPoint &segment2Start, const QgsPoint &segment2End, double distance1, double distance2, QgsPoint &chamferStart, QgsPoint &chamferEnd, double epsilon=1e-8)
Creates a chamfer between two line segments using QgsPoint.
static double distanceToVertex(const QgsAbstractGeometry &geom, QgsVertexId id)
Returns the distance along a geometry from its first vertex to the specified vertex.
static QPair< Qgis::WkbType, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
static bool lineCircleIntersection(const QgsPointXY ¢er, double radius, const QgsPointXY &linePoint1, const QgsPointXY &linePoint2, QgsPointXY &intersection)
Compute the intersection of a line and a circle.
static void circleCenterRadius(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double &radius, double ¢erX, double ¢erY)
Returns radius and center of the circle through pt1, pt2, pt3.
static double distToInfiniteLine(const QgsPoint &point, const QgsPoint &linePoint1, const QgsPoint &linePoint2, double epsilon=1e-7)
Returns the distance between a point and an infinite line.
static void coefficients(const QgsPoint &pt1, const QgsPoint &pt2, double &a, double &b, double &c)
Returns the coefficients (a, b, c for equation "ax + by + c = 0") of a line defined by points pt1 and...
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 QgsPoint midpoint(const QgsPoint &pt1, const QgsPoint &pt2)
Returns a middle point between points pt1 and pt2.
static bool createFillet(const QgsPoint &segment1Start, const QgsPoint &segment1End, const QgsPoint &segment2Start, const QgsPoint &segment2End, double radius, QgsPoint &filletPoint1, QgsPoint &filletMidPoint, QgsPoint &filletPoint2, double epsilon=1e-8)
Creates a fillet (rounded corner) between two line segments using QgsPoint.
static QgsPoint closestVertex(const QgsAbstractGeometry &geom, const QgsPoint &pt, QgsVertexId &id)
Returns the closest vertex to a geometry for a specified point.
static bool pointContinuesArc(const QgsPoint &a1, const QgsPoint &a2, const QgsPoint &a3, const QgsPoint &b, double distanceTolerance, double pointSpacingAngleTolerance)
Returns true if point b is on the arc formed by points a1, a2, and a3, but not within that arc portio...
static QgsPoint interpolatePointOnArc(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double distance)
Interpolates a point on an arc defined by three points, pt1, pt2 and pt3.
static Q_DECL_DEPRECATED bool pointsAreCollinear(double x1, double y1, double x2, double y2, double x3, double y3, double epsilon)
Given the points (x1, y1), (x2, y2) and (x3, y3) returns true if these points can be considered colli...
static bool tangentPointAndCircle(const QgsPointXY ¢er, double radius, const QgsPointXY &p, QgsPointXY &pt1, QgsPointXY &pt2)
Calculates the tangent points between the circle with the specified center and radius and the point p...
static int circleCircleOuterTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2)
Calculates the outer tangent points for two circles, centered at center1 and center2 and with radii o...
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 Q_DECL_DEPRECATED double sqrDistance2D(double x1, double y1, double x2, double y2)
Returns the squared 2D distance between (x1, y1) and (x2, y2).
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 std::unique_ptr< QgsAbstractGeometry > chamferVertex(const QgsCurve *curve, int vertexIndex, double distance1, double distance2)
Applies chamfer to a vertex in a curve geometry.
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 bool checkWeaklyFor3DPlane(const QgsAbstractGeometry *geom, QgsPoint &pt1, QgsPoint &pt2, QgsPoint &pt3, double epsilon=std::numeric_limits< double >::epsilon())
Checks if a 3D geometry has a plane defined by at least 3 non-collinear points.
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 double interpolateZ(const QgsPoint &a, const QgsPoint &b, const QgsPoint &c, double x, double y)
Interpolates the Z value at the given (x, y) location within the triangle defined by points a,...
static int circleCircleInnerTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2)
Calculates the inner tangent points for two circles, centered at center1 and center2 and with radii o...
static bool createFilletArray(const QgsPoint &segment1Start, const QgsPoint &segment1End, const QgsPoint &segment2Start, const QgsPoint &segment2End, double radius, QgsPoint filletPoints[3], double epsilon=1e-8)
Convenient method of createFillet using array output.
static QString pointsToWKT(const QgsPointSequence &points, int precision, bool is3D, bool isMeasure)
Returns a WKT coordinate list.
static QgsPoint segmentMidPointFromCenter(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint ¢er, bool useShortestArc=true)
Calculates the midpoint on the circle passing through p1 and p2, with the specified center coordinate...
static std::unique_ptr< QgsAbstractGeometry > filletVertex(const QgsCurve *curve, int vertexIndex, double radius, int segments)
Applies fillet to a vertex in a curve geometry.
ChamferFilletOperationType
Privatly used in chamfer/fillet functions.
Custom exception class when argument are invalid.
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.
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate.
double distance(double x, double y) const
Returns the distance between this point and a specified x, y coordinate.
void set(double x, double y)
Sets the x and y value of the point.
Point geometry type, with support for z-dimension and m-values.
void setM(double m)
Sets the point's m-value.
bool convertTo(Qgis::WkbType type) override
Converts the geometry to a specified type.
bool fuzzyEqual(const QgsAbstractGeometry &other, double epsilon=1e-8) const override
Performs fuzzy comparison between this geometry and other using an epsilon.
bool isEmpty() const override
Returns true if the geometry is empty.
double distance(double x, double y) const
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
void setZ(double z)
Sets the point's z-coordinate.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
Represent a 2-dimensional vector.
double length() const
Returns the length of the vector.
Java-style iterator for traversal of vertices of a geometry.
bool hasNext() const
Find out whether there are more vertices.
QgsPoint next()
Returns next vertex of the geometry (undefined behavior if hasNext() returns false before calling nex...
static Qgis::WkbType parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
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.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
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).
T qgsgeometry_cast(QgsAbstractGeometry *geom)
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.
bool isValid() const
Returns true if the vertex id is valid.
Qgis::VertexType type
Vertex type.