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(
216 ( linePoint1.
x() - linePoint2.
x() ) * ( point.
y() - linePoint2.
y() ) -
217 ( linePoint1.
y() - linePoint2.
y() ) * ( point.
x() - linePoint2.
x() )
220 const double length = std::sqrt(
221 std::pow( linePoint1.
x() - linePoint2.
x(), 2 ) +
222 std::pow( linePoint1.
y() - linePoint2.
y(), 2 )
225 const double distance = area / length;
226 return qgsDoubleNear( distance, 0.0, epsilon ) ? 0.0 : distance;
235 const double x1 = linePoint1.
x() - center.
x();
236 const double y1 = linePoint1.
y() - center.
y();
237 const double x2 = linePoint2.
x() - center.
x();
238 const double y2 = linePoint2.
y() - center.
y();
239 const double dx = x2 - x1;
240 const double dy = y2 - y1;
242 const double dr2 = std::pow( dx, 2 ) + std::pow( dy, 2 );
243 const double d = x1 * y2 - x2 * y1;
245 const double disc = std::pow( radius, 2 ) * dr2 - std::pow( d, 2 );
255 const int sgnDy = dy < 0 ? -1 : 1;
257 const double sqrDisc = std::sqrt( disc );
259 const double ax = center.
x() + ( d * dy + sgnDy * dx * sqrDisc ) / dr2;
260 const double ay = center.
y() + ( -d * dx + std::fabs( dy ) * sqrDisc ) / dr2;
263 const double bx = center.
x() + ( d * dy - sgnDy * dx * sqrDisc ) / dr2;
264 const double by = center.
y() + ( -d * dx - std::fabs( dy ) * sqrDisc ) / dr2;
271 intersection.
set( p1.
x(), p1.
y() );
275 intersection.
set( p2.
x(), p2.
y() );
286 const double d = center1.
distance( center2 );
290 const bool singleSolutionInt =
qgsDoubleNear( d, std::fabs( r1 - r2 ) );
293 if ( !singleSolutionExt && d > ( r1 + r2 ) )
298 else if ( !singleSolutionInt && d < std::fabs( r1 - r2 ) )
318 const double a = singleSolutionExt ? r1 : ( singleSolutionInt ? ( r1 > r2 ? r1 : -r1 ) : ( ( r1 * r1 ) - ( r2 * r2 ) + ( d * d ) ) / ( 2.0 * d ) );
323 const double dx = center2.
x() - center1.
x();
324 const double dy = center2.
y() - center1.
y();
327 const double x2 = center1.
x() + ( dx * a / d );
328 const double y2 = center1.
y() + ( dy * a / d );
331 if ( singleSolutionExt || singleSolutionInt )
344 const double h = std::sqrt( ( r1 * r1 ) - ( a * a ) );
349 const double rx = dy * ( h / d );
350 const double ry = dx * ( h / d );
353 intersection1 =
QgsPointXY( x2 + rx, y2 - ry );
354 intersection2 =
QgsPointXY( x2 - rx, y2 + ry );
364 const double dx = center.
x() - p.
x();
365 const double dy = center.
y() - p.
y();
366 const double distanceSquared = dx * dx + dy * dy;
367 const double radiusSquared = radius * radius;
368 if ( distanceSquared < radiusSquared )
375 const double distanceToTangent = std::sqrt( distanceSquared - radiusSquared );
387 if ( radius1 > radius2 )
390 const double radius2a = radius2 - radius1;
399 QgsVector v1( -( line1P2.
y() - center1.
y() ), line1P2.
x() - center1.
x() );
400 const double v1Length = v1.
length();
401 v1 = v1 * ( radius1 / v1Length );
404 line1P1 = center1 + v1;
405 line1P2 = line1P2 + v1;
409 QgsVector v2( line2P2.
y() - center1.
y(), -( line2P2.
x() - center1.
x() ) );
410 const double v2Length = v2.
length();
411 v2 = v2 * ( radius1 / v2Length );
414 line2P1 = center1 + v2;
415 line2P2 = line2P2 + v2;
423 if ( radius1 > radius2 )
427 const double d = center1.
distance( center2 );
428 const double radius1a = radius1 + radius2;
445 QgsVector v1( ( line1P2.
y() - center2.
y() ), -( line1P2.
x() - center2.
x() ) );
446 const double v1Length = v1.
length();
447 v1 = v1 * ( radius2 / v1Length );
450 line1P1 = center2 + v1;
451 line1P2 = line1P2 + v1;
455 QgsVector v2( -( line2P2.
y() - center2.
y() ), line2P2.
x() - center2.
x() );
456 const double v2Length = v2.
length();
457 v2 = v2 * ( radius2 / v2Length );
460 line2P1 = center2 + v2;
461 line2P2 = line2P2 + v2;
468 QVector<SelfIntersection> intersections;
474 for (
int i = 0, j = 1; j < n; i = j++ )
481 const int start = j + 1;
482 const int end = i == 0 && isClosed ? n - 1 : n;
483 for (
int k = start, l = start + 1; l < end; k = l++ )
489 bool intersection =
false;
500 intersections.append( s );
503 return intersections;
521 double centerX, centerY, radius;
524 const double theta = distance / radius;
525 const double anglePt1 = std::atan2( pt1.
y() - centerY, pt1.
x() - centerX );
526 const double anglePt2 = std::atan2( pt2.
y() - centerY, pt2.
x() - centerX );
527 const double anglePt3 = std::atan2( pt3.
y() - centerY, pt3.
x() - centerX );
529 const double angleDest = anglePt1 + (
isClockwise ? -theta : theta );
531 const double x = centerX + radius * ( std::cos( angleDest ) );
532 const double y = centerY + radius * ( std::sin( angleDest ) );
534 const double z = pt1.
is3D() ?
550 double z = std::numeric_limits<double>::quiet_NaN();
551 double m = std::numeric_limits<double>::quiet_NaN();
554 p1.
x(), p1.
y(), p1.
z(), p1.
m(),
555 p2.
x(), p2.
y(), p2.
z(), p2.
m(),
556 p3.
x(), p3.
y(), p3.
z(), p3.
m(),
568 return QgsPoint( wkbType, x, y, z, m );
572 double p0x,
double p0y,
double p0z,
double p0m,
573 double p1x,
double p1y,
double p1z,
double p1m,
574 double p2x,
double p2y,
double p2z,
double p2m,
575 double p3x,
double p3y,
double p3z,
double p3m,
576 double t,
bool hasZ,
bool hasM,
577 double &outX,
double &outY,
double &outZ,
double &outM )
580 const double t1 = 1.0 - t;
581 const double t1_2 = t1 * t1;
582 const double t1_3 = t1_2 * t1;
583 const double t_2 = t * t;
584 const double t_3 = t_2 * t;
586 outX = t1_3 * p0x + 3.0 * t1_2 * t * p1x + 3.0 * t1 * t_2 * p2x + t_3 * p3x;
587 outY = t1_3 * p0y + 3.0 * t1_2 * t * p1y + 3.0 * t1 * t_2 * p2y + t_3 * p3y;
591 outZ = t1_3 * p0z + 3.0 * t1_2 * t * p1z + 3.0 * t1 * t_2 * p2z + t_3 * p3z;
596 outM = t1_3 * p0m + 3.0 * t1_2 * t * p1m + 3.0 * t1 * t_2 * p2m + t_3 * p3m;
602 const QgsPoint midPoint( ( p1.
x() + p2.
x() ) / 2.0, ( p1.
y() + p2.
y() ) / 2.0 );
603 const double midDist = std::sqrt(
sqrDistance2D( p1, midPoint ) );
604 if ( radius < midDist )
608 const double centerMidDist = std::sqrt( radius * radius - midDist * midDist );
609 const double dist = radius - centerMidDist;
611 const double midDx = midPoint.
x() - p1.
x();
612 const double midDy = midPoint.
y() - p1.
y();
615 QVector<QgsPoint> possibleMidPoints;
622 double minDist = std::numeric_limits<double>::max();
623 int minDistIndex = -1;
624 for (
int i = 0; i < possibleMidPoints.size(); ++i )
626 const double currentDist =
sqrDistance2D( mousePos, possibleMidPoints.at( i ) );
627 if ( currentDist < minDist )
630 minDist = currentDist;
634 if ( minDistIndex == -1 )
639 result = possibleMidPoints.at( minDistIndex );
651 if ( !useShortestArc )
652 midPointAngle += M_PI;
653 return center.
project( center.
distance( p1 ), midPointAngle * 180 / M_PI );
660 double mX, mY, radius;
693 const double bDistance = std::sqrt( ( b.
x() - centerX ) * ( b.
x() - centerX ) +
694 ( b.
y() - centerY ) * ( b.
y() - centerY ) );
696 double diff = std::fabs( radius - bDistance );
700 const double abX = b.
x() - a.
x();
701 const double abY = b.
y() - a.
y();
703 const double cbX = b.
x() -
c.x();
704 const double cbY = b.
y() -
c.y();
706 const double dot = ( abX * cbX + abY * cbY );
707 const double cross = ( abX * cbY - abY * cbX );
709 const double alpha = std::atan2( cross, dot );
715 if ( diff < distanceTolerance )
717 const double angle1 = arcAngle( a1, a2, a3 );
718 const double angle2 = arcAngle( a2, a3, b );
723 diff = std::fabs( angle1 - angle2 );
724 if ( diff > pointSpacingAngleTolerance )
734 if ( bSide != a2Side )
742 bool reversed =
false;
766 circleCenterRadius( circlePoint1, circlePoint2, circlePoint3, radius, centerX, centerY );
768 if ( circlePoint1 != circlePoint3 && ( radius < 0 ||
qgsDoubleNear( segSide, 0.0 ) ) )
776 double increment = tolerance;
780 tolerance = std::min( tolerance, radius * 2 );
781 const double halfAngle = std::acos( -tolerance / radius + 1 );
782 increment = 2 * halfAngle;
786 const double a1 = std::atan2( circlePoint1.
y() - centerY, circlePoint1.
x() - centerX );
787 double a2 = std::atan2( circlePoint2.
y() - centerY, circlePoint2.
x() - centerX );
788 double a3 = std::atan2( circlePoint3.
y() - centerY, circlePoint3.
x() - centerX );
791 const bool symmetric =
true;
794 double angle = a3 - a1;
796 if ( angle <= 0 ) angle += M_PI * 2;
799 const int segs = ceil( angle / increment );
801 increment = angle / segs;
815 QVector<QgsPoint> stringPoints;
816 stringPoints.insert( 0, circlePoint1 );
817 if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 )
831 const double tolError = increment / 100;
832 const double stopAngle = a3 - tolError;
833 for (
double angle = a1 + increment; angle < stopAngle; angle += increment )
835 x = centerX + radius * std::cos( angle );
836 y = centerY + radius * std::sin( angle );
847 stringPoints.insert( stringPoints.size(),
QgsPoint( pointWkbType, x, y, z, m ) );
850 stringPoints.insert( stringPoints.size(), circlePoint3 );
855 std::reverse( stringPoints.begin(), stringPoints.end() );
857 if ( ! points.empty() && stringPoints.front() == points.back() ) stringPoints.pop_front();
858 points.append( stringPoints );
863 const double side = ( ( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
884 const int dim = 2 + is3D + isMeasure;
887 const QStringList coordList = wktCoordinateList.split(
',', Qt::SkipEmptyParts );
892 const thread_local QRegularExpression rx( u
"\\s"_s );
893 const thread_local QRegularExpression rxIsNumber( u
"^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$"_s );
894 for (
const QString &pointCoordinates : coordList )
896 const QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
899 if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() )
902 if ( coordinates.size() == 3 && !foundZ && !foundM && !is3D && !isMeasure )
908 else if ( coordinates.size() >= 4 && ( !( is3D || foundZ ) || !( isMeasure || foundM ) ) )
917 for (
const QString &pointCoordinates : coordList )
919 QStringList coordinates = pointCoordinates.split( rx, Qt::SkipEmptyParts );
920 if ( coordinates.size() < dim )
924 const double x = coordinates[idx++].toDouble();
925 const double y = coordinates[idx++].toDouble();
928 if ( ( is3D || foundZ ) && coordinates.length() > idx )
929 z = coordinates[idx++].toDouble();
932 if ( ( isMeasure || foundM ) && coordinates.length() > idx )
933 m = coordinates[idx++].toDouble();
936 if ( is3D || foundZ )
938 if ( isMeasure || foundM )
945 if ( isMeasure || foundM )
951 points.append(
QgsPoint( t, x, y, z, m ) );
959 wkb << static_cast<quint32>( points.size() );
960 for (
const QgsPoint &point : points )
962 wkb << point.x() << point.y();
965 double z = point.z();
968 z = -std::numeric_limits<double>::max();
974 double m = point.m();
977 m = -std::numeric_limits<double>::max();
986 QString wkt = u
"("_s;
997 if ( wkt.endsWith(
", "_L1 ) )
1005 QDomElement elemCoordinates = doc.createElementNS( ns, u
"coordinates"_s );
1008 const QString cs = u
","_s;
1010 const QString ts = u
" "_s;
1012 elemCoordinates.setAttribute( u
"cs"_s, cs );
1013 elemCoordinates.setAttribute( u
"ts"_s, ts );
1015 QString strCoordinates;
1023 if ( strCoordinates.endsWith( ts ) )
1024 strCoordinates.chop( 1 );
1026 elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
1027 return elemCoordinates;
1032 QDomElement elemPosList = doc.createElementNS( ns, u
"posList"_s );
1033 elemPosList.setAttribute( u
"srsDimension"_s, is3D ? 3 : 2 );
1035 QString strCoordinates;
1045 if ( strCoordinates.endsWith(
' ' ) )
1046 strCoordinates.chop( 1 );
1048 elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
1054 QString json = u
"[ "_s;
1059 if ( json.endsWith(
", "_L1 ) )
1070 json coordinates( json::array() );
1075 coordinates.push_back( {
qgsRound( p.x(), precision ),
qgsRound( p.y(), precision ),
qgsRound( p.z(), precision ) } );
1079 coordinates.push_back( {
qgsRound( p.x(), precision ),
qgsRound( p.y(), precision ) } );
1087 QString wktParsed = wkt;
1089 bool isEmpty =
false;
1090 const QLatin1String empty {
"EMPTY" };
1091 if ( wkt.contains( empty, Qt::CaseInsensitive ) )
1093 const thread_local QRegularExpression whiteSpaces(
"\\s" );
1094 wktParsed.remove( whiteSpaces );
1095 const int index = wktParsed.indexOf( empty, 0, Qt::CaseInsensitive );
1097 if ( index == wktParsed.length() - empty.size() )
1101 wktParsed = wktParsed.left( index );
1112 const int openedParenthesisCount = wktParsed.count(
'(' );
1113 const int closedParenthesisCount = wktParsed.count(
')' );
1115 for (
int i = 0 ; i < openedParenthesisCount - closedParenthesisCount; ++i )
1116 wktParsed.push_back(
')' );
1118 wktParsed.truncate( wktParsed.size() - ( closedParenthesisCount - openedParenthesisCount ) );
1120 const thread_local QRegularExpression cooRegEx( u
"^[^\\(]*\\((.*)\\)[^\\)]*$"_s, QRegularExpression::DotMatchesEverythingOption );
1121 const QRegularExpressionMatch match = cooRegEx.match( wktParsed );
1122 contents = match.hasMatch() ? match.captured( 1 ) : QString();
1125 return qMakePair( wkbType, contents );
1132 block.reserve( wkt.size() );
1135 const QChar *wktData = wkt.data();
1136 const int wktLength = wkt.length();
1137 for (
int i = 0, n = wktLength; i < n; ++i, ++wktData )
1139 if ( ( wktData->isSpace() || *wktData ==
'\n' || *wktData ==
'\t' ) && level == 0 )
1142 if ( *wktData ==
',' && level == 0 )
1144 if ( !block.isEmpty() )
1146 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1147 block.prepend( defaultType +
' ' );
1148 blocks.append( block );
1153 if ( *wktData ==
'(' )
1155 else if ( *wktData ==
')' )
1159 if ( !block.isEmpty() )
1161 if ( block.startsWith(
'(' ) && !defaultType.isEmpty() )
1162 block.prepend( defaultType +
' ' );
1163 blocks.append( block );
1173 const double x = ( pt1.
x() + pt2.
x() ) / 2.0;
1174 const double y = ( pt1.
y() + pt2.
y() ) / 2.0;
1175 double z = std::numeric_limits<double>::quiet_NaN();
1176 double m = std::numeric_limits<double>::quiet_NaN();
1181 z = ( pt1.
z() + pt2.
z() ) / 2.0;
1187 m = ( pt1.
m() + pt2.
m() ) / 2.0;
1190 return QgsPoint( pType, x, y, z, m );
1195 const double _fraction = 1 - fraction;
1197 p1.
x() * _fraction + p2.
x() * fraction,
1198 p1.
y() * _fraction + p2.
y() * fraction,
1199 p1.
is3D() ? p1.
z() * _fraction + p2.
z() * fraction : std::numeric_limits<double>::quiet_NaN(),
1200 p1.
isMeasure() ? p1.
m() * _fraction + p2.
m() * fraction : std::numeric_limits<double>::quiet_NaN() );
1205 const double deltaX = ( x2 - x1 ) * fraction;
1206 const double deltaY = ( y2 - y1 ) * fraction;
1207 return QgsPointXY( x1 + deltaX, y1 + deltaY );
1215 const double fraction = ( value - v1 ) / ( v2 - v1 );
1221 const double delta_x = pt2.
x() - pt1.
x();
1222 const double delta_y = pt2.
y() - pt1.
y();
1228 return delta_y / delta_x;
1247 a = pt1.
y() - pt2.
y();
1248 b = pt2.
x() - pt1.
x();
1249 c = pt1.
x() * pt2.
y() - pt1.
y() * pt2.
x();
1259 if ( ( p == s1 ) || ( p == s2 ) )
1277 const double y = ( -
c - a * p.
x() ) / b;
1278 const double m =
gradient( s1, s2 );
1279 const double d2 = 1 + m * m;
1280 const double H = p.
y() - y;
1281 const double dx = m * H / d2;
1282 const double dy = m * dx;
1296 for (
const QgsPoint &pt : points )
1298 if ( pt.isMeasure() )
1301 point.
setM( pt.m() );
1314 for (
const QgsPoint &pt : points )
1319 point.
setZ( pt.z() );
1332 else if ( reference.
is3D() )
1346 if ( segmentStart.
is3D() && segmentEnd.
is3D() )
1348 double z1 = segmentStart.
z();
1349 double z2 = segmentEnd.
z();
1350 double interpolatedZ;
1351 double tempX, tempY;
1353 segmentStart.
x(), segmentStart.
y(), segmentEnd.
x(), segmentEnd.
y(),
1354 distanceFromStart, tempX, tempY, &z1, &z2, &interpolatedZ );
1355 result.
setZ( interpolatedZ );
1360 double m1 = segmentStart.
m();
1361 double m2 = segmentEnd.
m();
1362 double interpolatedM;
1363 double tempX, tempY;
1365 segmentStart.
x(), segmentStart.
y(), segmentEnd.
x(), segmentEnd.
y(),
1366 distanceFromStart, tempX, tempY,
nullptr,
nullptr,
nullptr, &m1, &m2, &interpolatedM );
1367 result.
setM( interpolatedM );
1375 double distance1,
double distance2,
1380 double chamferStartX, chamferStartY, chamferEndX, chamferEndY;
1383 segment1Start.
x(), segment1Start.
y(), segment1End.
x(), segment1End.
y(),
1384 segment2Start.
x(), segment2Start.
y(), segment2End.
x(), segment2End.
y(),
1385 distance1, distance2,
1386 chamferStartX, chamferStartY,
1387 chamferEndX, chamferEndY,
1388 nullptr,
nullptr,
nullptr,
nullptr,
1389 nullptr,
nullptr,
nullptr,
nullptr,
1408 double filletPointsX[3], filletPointsY[3];
1411 segment1Start.
x(), segment1Start.
y(), segment1End.
x(), segment1End.
y(),
1412 segment2Start.
x(), segment2Start.
y(), segment2End.
x(), segment2End.
y(),
1414 filletPointsX, filletPointsY,
1415 nullptr,
nullptr,
nullptr,
nullptr,
1416 nullptr,
nullptr,
nullptr,
nullptr,
1425 if ( segment1Start.
is3D() && segment1End.
is3D() && segment2Start.
is3D() && segment2End.
is3D() )
1427 filletMidPoint.
setZ( ( filletPoint1.
z() + filletPoint2.
z() ) / 2.0 );
1431 filletMidPoint.
setM( ( filletPoint1.
m() + filletPoint2.
m() ) / 2.0 );
1444 createFillet( segment1Start, segment1End, segment2Start, segment2End, radius, p1, p2, p3, epsilon );
1445 filletPoints[0] = p1;
1446 filletPoints[1] = p2;
1447 filletPoints[2] = p3;
1454 double distance1,
double distance2 )
1457 createChamfer( segment1Start, segment1End, segment2Start, segment2End, distance1, distance2, chamferStart, chamferEnd );
1459 return std::make_unique<QgsLineString>(
1460 QVector<QgsPoint> { segment1Start, chamferStart, chamferEnd, segment2Start } );
1466 double radius,
int segments )
1469 createFilletArray( segment1Start, segment1End, segment2Start, segment2End, radius, filletPoints );
1472 double intersectionX, intersectionY;
1473 bool isIntersection;
1475 segment1Start.
x(), segment1Start.
y(), segment1End.
x(), segment1End.
y(),
1476 segment2Start.
x(), segment2Start.
y(), segment2End.
x(), segment2End.
y(),
1477 intersectionX, intersectionY, isIntersection, 1e-8,
true );
1479 if ( !isIntersection )
1489 const QgsPoint segment1FarEnd = ( dist1ToStart < dist1ToEnd ) ? segment1End : segment1Start;
1490 const QgsPoint segment2FarEnd = ( dist2ToStart < dist2ToEnd ) ? segment2End : segment2Start;
1492 if ( segments <= 0 )
1495 auto completeCurve = std::make_unique<QgsCompoundCurve>();
1498 auto firstSegment = std::make_unique<QgsLineString>(
1499 QVector<QgsPoint> { segment1FarEnd, filletPoints[0] } );
1500 completeCurve->addCurve( firstSegment.release() );
1503 auto circularString = std::make_unique<QgsCircularString>();
1504 circularString->setPoints( {filletPoints[0], filletPoints[1], filletPoints[2]} );
1505 completeCurve->addCurve( circularString.release() );
1508 auto lastSegment = std::make_unique<QgsLineString>(
1509 QVector<QgsPoint> { filletPoints[2], segment2FarEnd } );
1510 completeCurve->addCurve( lastSegment.release() );
1512 return completeCurve;
1517 QVector<QgsPoint> points;
1518 points.append( segment1FarEnd );
1522 tempArc.
setPoints( {filletPoints[0], filletPoints[1], filletPoints[2]} );
1527 double angleTolerance = M_PI / 180.0;
1530 double radius, centerX, centerY;
1533 filletPoints[0].x(), filletPoints[0].y(),
1534 filletPoints[1].x(), filletPoints[1].y(),
1535 filletPoints[2].x(), filletPoints[2].y() ) ) * M_PI / 180.0;
1537 angleTolerance = arcAngle / segments * ( 1.0 + 1e-10 );
1542 for (
int i = 0; i < segmentizedArc->numPoints(); ++i )
1544 points.append( segmentizedArc->vertexAt(
QgsVertexId( 0, 0, i ) ) );
1547 points.append( segment2FarEnd );
1549 return std::make_unique<QgsLineString>( points );
1561 const QgsCurve *curve,
int vertexIndex,
1562 double distance1,
double distance2 )
1568 const QgsCurve *curve,
int vertexIndex,
1569 double radius,
int segments )
1574std::unique_ptr< QgsAbstractGeometry > QgsGeometryUtils::doChamferFilletOnVertex(
1576 double value1,
double value2,
int segments
1585 if ( vertexIndex < 0 || vertexIndex > curve->
numPoints() - 1 )
1591 throw QgsInvalidArgumentException(
"Opened curve must have at least 3 points." );
1592 if ( vertexIndex <= 0 || vertexIndex >= curve->
numPoints() - 1 )
1593 throw QgsInvalidArgumentException( u
"Vertex index out of range. %1 must be in (0, %2)."_s.arg( vertexIndex ).arg( curve->
numPoints() - 1 ) );
1597 QgsPoint pPrev = curve->
vertexAt( QgsVertexId( 0, 0, vertexIndex - 1 ) );
1598 const QgsPoint p = curve->
vertexAt( QgsVertexId( 0, 0, vertexIndex ) );
1599 QgsPoint pNext = curve->
vertexAt( QgsVertexId( 0, 0, vertexIndex + 1 ) );
1602 if ( vertexIndex - 1 < 0 )
1604 if ( vertexIndex + 1 >= curve->
numPoints() )
1605 pNext = curve->
vertexAt( QgsVertexId( 0, 0, 1 ) );
1608 QgsPoint firstNewPoint, middlePoint, lastNewPoint;
1612 double rad = std::min( value1, pPrev.
distance( p ) * 0.95 );
1613 rad = std::min( rad, pNext.
distance( p ) * 0.95 );
1616 QgsPoint filletPoints[3];
1619 firstNewPoint = filletPoints[0];
1620 middlePoint = filletPoints[1];
1621 lastNewPoint = filletPoints[2];
1626 createChamfer( pPrev, p, p, pNext, value1, value2, firstNewPoint, lastNewPoint );
1629 throw QgsInvalidArgumentException( u
"Operation '%1' is unknown."_s.arg(
qgsEnumValueToKey( operation ) ) );
1634 QVector<QgsPoint> points;
1641 for (
int i = min; i < vertexIndex; ++i )
1643 points.append( curve->
vertexAt( QgsVertexId( 0, 0, i ) ) );
1649 if ( firstNewPoint != pPrev )
1650 points.append( firstNewPoint );
1654 QgsCircularString tempArc;
1655 tempArc.
setPoints( { firstNewPoint, middlePoint, lastNewPoint } );
1659 double radius, centerX, centerY;
1662 firstNewPoint.
x(), firstNewPoint.
y(),
1663 middlePoint.
x(), middlePoint.
y(),
1664 lastNewPoint.
x(), lastNewPoint.
y() ) ) * M_PI / 180.0;
1666 const double angleTolerance = arcAngle / segments * ( 1.0 + 1e-10 );
1669 for (
int i = 1; i < segmentizedArc->numPoints() - 1; ++i )
1671 points.append( segmentizedArc->vertexAt( QgsVertexId( 0, 0, i ) ) );
1676 points.append( middlePoint );
1679 if ( lastNewPoint != pNext )
1680 points.append( lastNewPoint );
1684 if ( firstNewPoint != pPrev )
1685 points.append( firstNewPoint );
1686 if ( lastNewPoint != pNext )
1687 points.append( lastNewPoint );
1691 if ( curve->
isClosed() && vertexIndex == 0 )
1694 for (
int i = vertexIndex + 1; i < max; ++i )
1696 points.append( curve->
vertexAt( QgsVertexId( 0, 0, i ) ) );
1699 return std::make_unique<QgsLineString>( points );
1704 auto newCompound = std::make_unique<QgsCompoundCurve>();
1706 int globalVertexIndex = 0;
1707 int targetCurveIndex = -1;
1708 int vertexInCurve = -1;
1710 for (
int curveIdx = 0; curveIdx < compound->nCurves(); ++curveIdx )
1712 const QgsCurve *subcurve = compound->curveAt( curveIdx );
1713 const int subcurvePoints = subcurve->
numPoints();
1715 if ( globalVertexIndex + subcurvePoints > vertexIndex )
1717 targetCurveIndex = curveIdx;
1718 vertexInCurve = vertexIndex - globalVertexIndex;
1721 globalVertexIndex += subcurvePoints - 1;
1724 if ( targetCurveIndex == -1 )
1726 throw QgsInvalidArgumentException(
"While generating output: unable to find curve within compound." );
1729 const QgsCurve *targetCurve = compound->curveAt( targetCurveIndex );
1732 for (
int i = 0; i < targetCurveIndex; ++i )
1734 std::unique_ptr<QgsCurve> tmpCurv( compound->curveAt( i )->clone() );
1737 tmpCurv->insertVertex( QgsVertexId( 0, 0, 1 ), lastNewPoint );
1738 tmpCurv->deleteVertex( QgsVertexId( 0, 0, 0 ) );
1740 newCompound->addCurve( tmpCurv.release() );
1744 if ( vertexInCurve > 0 )
1746 QVector<QgsPoint> beforePoints;
1747 for (
int j = 0; j < vertexInCurve; ++j )
1749 beforePoints.append( targetCurve->
vertexAt( QgsVertexId( 0, 0, j ) ) );
1751 beforePoints.append( firstNewPoint );
1753 if ( beforePoints.size() > 1 )
1755 auto beforeVertex = std::make_unique<QgsLineString>( beforePoints );
1756 newCompound->addCurve( beforeVertex.release() );
1763 if ( segments <= 0 )
1766 auto filletArc = std::make_unique<QgsCircularString>();
1767 filletArc->setPoints( { firstNewPoint, middlePoint, lastNewPoint } );
1768 newCompound->addCurve( filletArc.release() );
1773 QgsCircularString tempArc;
1774 tempArc.
setPoints( { firstNewPoint, middlePoint, lastNewPoint } );
1776 const double angleTolerance = ( 2.0 * M_PI ) / ( 4.0 * segments );
1779 newCompound->addCurve( segmentizedArc.release() );
1784 auto chamferLine = std::make_unique<QgsLineString>(
1785 QVector<QgsPoint> { firstNewPoint, lastNewPoint }
1787 newCompound->addCurve( chamferLine.release() );
1790 if ( vertexInCurve < targetCurve->numPoints() - 1 )
1792 QVector<QgsPoint> afterPoints;
1793 afterPoints.append( lastNewPoint );
1794 for (
int j = vertexInCurve + 1; j < targetCurve->
numPoints(); ++j )
1796 afterPoints.append( targetCurve->
vertexAt( QgsVertexId( 0, 0, j ) ) );
1799 if ( afterPoints.size() > 1 )
1801 auto afterVertex = std::make_unique<QgsLineString>( afterPoints );
1802 newCompound->addCurve( afterVertex.release() );
1807 for (
int i = targetCurveIndex + 1; i < compound->nCurves(); ++i )
1809 std::unique_ptr<QgsCurve> tmpCurv( compound->curveAt( i )->clone() );
1810 if ( curve->
isClosed() && vertexIndex == 0 )
1812 tmpCurv->insertVertex( QgsVertexId( 0, 0, tmpCurv->numPoints() - 1 ), firstNewPoint );
1813 tmpCurv->deleteVertex( QgsVertexId( 0, 0, tmpCurv->numPoints() - 1 ) );
1815 newCompound->addCurve( tmpCurv.release() );
1821 throw QgsInvalidArgumentException(
"While generating output: curse is not a QgsLineString nor a QgsCompoundCurve." );
1851 ring = curvePolygon->exteriorRing();
1857 pt1 = ringIt.
next();
1862 pt2 = ringIt.
next();
1868 pt3 = ringIt.
next();
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 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.