43using namespace Qt::StringLiterals;
46 : mGeometry( geometry.constGet() )
73 double dx = p2.
x() - p1.
x();
74 double dy = p2.
y() - p1.
y();
75 if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
77 if ( fabs( dx ) >= fabs( dy ) )
79 double dev = fabs( dy ) / fabs( dx );
86 double dev = fabs( dx ) / fabs( dy );
104 std::array<Direction, 5> dirs;
111 while ( current != end )
121 else if ( dir != dirs[idx - 1] )
131 ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
132 std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
138 int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
139 for (
int i = 1; i < 4; ++i )
141 if ( dirs[i] != oriented[( idx + i ) % 4] )
177 if ( vertexCount < 4 )
179 else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
183 std::array<Direction, 4> dirs;
184 std::tie( found4Dirs, dirs ) =
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
198 QVector<QgsLineString *> linesToProcess;
203 linesToProcess.reserve( multiCurve->
partCount() );
204 for (
int i = 0; i < multiCurve->
partCount(); ++i )
206 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
213 linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
216 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() :
nullptr );
219 if ( !linesToProcess.empty() )
221 std::unique_ptr< QgsLineString > secondline;
222 for (
QgsLineString *line : std::as_const( linesToProcess ) )
224 QTransform transform = QTransform::fromTranslate( x, y );
226 secondline.reset( line->reversed() );
227 secondline->transform( transform );
229 line->append( secondline.get() );
230 line->addVertex( line->pointN( 0 ) );
236 multipolygon->addGeometry( polygon );
258 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
262 , d( polygon->pointDistanceToBoundary( x, y ) )
263 , max( d + h * M_SQRT2 )
278struct GreaterThanByMax
280 bool operator()(
const Cell *lhs,
const Cell *rhs )
const
282 return rhs->max > lhs->max;
286Cell *getCentroidCell(
const QgsPolygon *polygon )
294 for (
int i = 0, j = len - 1; i < len; j = i++ )
296 double aX = exterior->
xAt( i );
297 double aY = exterior->
yAt( i );
298 double bX = exterior->
xAt( j );
299 double bY = exterior->
yAt( j );
300 double f = aX * bY - bX * aY;
301 x += ( aX + bX ) * f;
302 y += ( aY + bY ) * f;
306 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
308 return new Cell( x / area, y / area, 0.0, polygon );
311QgsPoint surfacePoleOfInaccessibility(
const QgsSurface *surface,
double precision,
double &distanceFromBoundary )
313 std::unique_ptr< QgsPolygon > segmentizedPoly;
318 polygon = segmentizedPoly.get();
325 double cellSize = std::min( bounds.
width(), bounds.
height() );
330 double h = cellSize / 2.0;
331 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
338 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
343 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
346 std::unique_ptr< Cell > bboxCell(
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
349 if ( bboxCell->d > bestCell->d )
351 bestCell = std::move( bboxCell );
354 while ( !cellQueue.empty() )
357 std::unique_ptr< Cell > cell( cellQueue.top() );
359 Cell *currentCell = cell.get();
362 if ( currentCell->d > bestCell->d )
364 bestCell = std::move( cell );
368 if ( currentCell->max - bestCell->d <= precision )
372 h = currentCell->h / 2.0;
373 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y - h, h, polygon ) );
374 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y - h, h, polygon ) );
375 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y + h, h, polygon ) );
376 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
379 distanceFromBoundary = bestCell->d;
381 return QgsPoint( bestCell->x, bestCell->y );
389 if ( distanceFromBoundary )
390 *distanceFromBoundary = std::numeric_limits<double>::max();
392 if ( !mGeometry || mGeometry->isEmpty() )
395 if ( precision <= 0 )
400 int numGeom = gc->numGeometries();
403 for (
int i = 0; i < numGeom; ++i )
409 double dist = std::numeric_limits<double>::max();
410 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
411 if ( dist > maxDist )
421 if ( distanceFromBoundary )
422 *distanceFromBoundary = maxDist;
431 double dist = std::numeric_limits<double>::max();
432 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
436 if ( distanceFromBoundary )
437 *distanceFromBoundary = dist;
448 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
474 for (
int i = 0; i < numPoints; ++i )
476 if ( !isClosed && i == numPoints - 1 )
478 else if ( !isClosed && i == 0 )
487 a = ring->
pointN( numPoints - 1 );
490 if ( i == numPoints - 1 )
499 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
509 double lowerThreshold,
double upperThreshold )
518 double scale = 2.0 * std::min( p.
length(), q.
length() );
522 double dotProduct = p * q;
531 if ( dotProduct < -M_SQRT1_2 )
540 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
545 double minScore = std::numeric_limits<double>::max();
550 std::unique_ptr< QgsLineString > best( ring->
clone() );
552 QVector< QgsVector > motions;
553 motions.reserve( numPoints );
555 for (
int it = 0; it < iterations; ++it )
563 for (
int i = 0; i < numPoints; ++i )
565 if ( isClosed && i == numPoints - 1 )
566 motions << motions.at( 0 );
567 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
577 a = ring->
pointN( numPoints - 1 );
580 if ( i == numPoints - 1 )
585 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
592 for (
int i = 0; i < numPoints; ++i )
594 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
595 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
598 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
599 if ( newScore < minScore )
601 best.reset( ring->
clone() );
605 if ( minScore < tolerance )
611 return best.release();
617 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
621 geom = segmentizedCopy.get();
627 maxIterations, tolerance, lowerThreshold, upperThreshold );
636 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
640 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
656 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
657 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
661 int numGeom = gc->numGeometries();
662 QVector< QgsAbstractGeometry * > geometryList;
663 geometryList.reserve( numGeom );
664 for (
int i = 0; i < numGeom; ++i )
666 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
685 QVector< double > outX;
686 QVector< double > outY;
687 QVector< double > outZ;
688 QVector< double > outM;
689 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
692 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
693 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
694 bool withZ = ring->
is3D();
696 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
699 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
712 int extraNodesThisSegment = extraNodesPerSegment;
713 for (
int i = 0; i < nPoints - 1; ++i )
716 x2 = ring->
xAt( i + 1 );
718 y2 = ring->
yAt( i + 1 );
722 z2 = ring->
zAt( i + 1 );
727 m2 = ring->
mAt( i + 1 );
737 if ( extraNodesPerSegment < 0 )
741 if ( extraNodesThisSegment >= 1 )
742 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
745 for (
int j = 0; j < extraNodesThisSegment; ++j )
747 double delta = multiplier * ( j + 1 );
748 xOut = x1 + delta * ( x2 - x1 );
749 yOut = y1 + delta * ( y2 - y1 );
751 zOut = z1 + delta * ( z2 - z1 );
753 mOut = m1 + delta * ( m2 - m1 );
763 outX << ring->
xAt( nPoints - 1 );
764 outY << ring->
yAt( nPoints - 1 );
766 outZ << ring->
zAt( nPoints - 1 );
768 outM << ring->
mAt( nPoints - 1 );
776 if ( extraNodesPerSegment < 0 &&
qgsDoubleNear( distance, 0 ) )
779 return geom->
clone();
782 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
786 geom = segmentizedCopy.get();
800 extraNodesPerSegment, distance ) );
804 extraNodesPerSegment, distance ) );
826 int numGeom = gc->numGeometries();
827 QVector< QgsAbstractGeometry * > geometryList;
828 geometryList.reserve( numGeom );
829 for (
int i = 0; i < numGeom; ++i )
831 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
862 int numGeom = gc->numGeometries();
863 QVector< QgsAbstractGeometry * > geometryList;
864 geometryList.reserve( numGeom );
865 for (
int i = 0; i < numGeom; ++i )
892 "line_segment_dist_comparer",
893 "AB must not be collinear with the origin." );
895 "line_segment_dist_comparer",
896 "CD must not be collinear with the origin." );
913 if ( ab.
end() == cd.
end() || oad != oab )
923 if ( cdb == 0 && cda == 0 )
925 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
927 else if ( cda == cdb || cda == 0 || cdb == 0 )
930 return cdo == cda || cdo == cdb;
946 const bool aIsLeft = a.
x() < mVertex.x();
947 const bool bIsLeft = b.
x() < mVertex.x();
948 if ( aIsLeft != bIsLeft )
953 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
955 return b.
y() < a.
y();
959 return a.
y() < b.
y();
991 const int abo =
segment.pointLeftOfLine( origin );
998 const double distA = ao * direction;
999 const double distB = ( origin -
segment.end() ) * direction;
1001 if ( distA > 0 && distB > 0 )
1007 if ( ( distA > 0 ) != ( distB > 0 ) )
1008 intersectPoint = origin;
1009 else if ( distA > distB )
1010 intersectPoint =
segment.start();
1012 intersectPoint =
segment.end();
1020 if ( u < 0.0 || 1.0 < u )
1027 intersectPoint = origin + direction * t;
1036 if ( radius1 > radius2 )
1043 QVector<QgsPointXY> points;
1065 std::vector< std::unique_ptr<QgsLineString > > temporarySegmentizedLines;
1066 std::vector< const QgsLineString * > linesToProcess;
1071 for (
int i = 0; i < multiCurve->partCount(); ++i )
1081 linesToProcess.emplace_back( lineString );
1085 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( part->
segmentize() ) );
1086 linesToProcess.emplace_back( segmentizedCurve.get() );
1087 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1094 if ( curve->nCoordinates() > 0 )
1098 linesToProcess.emplace_back( lineString );
1102 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( curve->segmentize() ) );
1103 linesToProcess.emplace_back( segmentizedCurve.get() );
1104 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1109 if ( linesToProcess.empty() )
1112 g.mLastError = u
"Input geometry was not a curve type geometry"_s;
1116 QVector<QgsGeometry> bufferedLines;
1117 bufferedLines.reserve( linesToProcess.size() );
1121 QVector<QgsGeometry> parts;
1123 double prevRadius = 0;
1126 std::unique_ptr< double[] > widths = widthFunction( line ) ;
1131 double thisRadius = widths[ i ] / 2.0;
1132 if ( thisRadius > 0 )
1136 QgsCircle circ( thisPoint, thisRadius );
1138 parts << thisCircle;
1147 if ( prevRadius > 0 || thisRadius > 0 )
1149 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1150 if ( !points.empty() )
1155 int beforeVertex = 0;
1156 int afterVertex = 0;
1158 double sqrDistPrev = 0;
1159 for (
int j = 0; j < points.count(); ++j )
1163 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1166 points.append( points.at( 0 ) );
1168 auto poly = std::make_unique< QgsPolygon >();
1170 if ( poly->area() > 0 )
1175 prevPoint = thisPoint;
1176 prevRadius = thisRadius;
1177 prevCircle = thisCircle;
1192 start = std::fabs( start );
1193 end = std::fabs( end );
1195 auto interpolateWidths = [ start, end ](
const QgsLineString * line )->std::unique_ptr<
double [] >
1199 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1201 widths[line->nCoordinates() - 1] = end;
1203 double lineLength = line->length();
1204 double currentLength = 0;
1205 QgsPoint prevPoint = line->pointN( 0 );
1206 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1208 QgsPoint point = line->pointN( i );
1209 double segmentLength = point.
distance( prevPoint );
1210 currentLength += segmentLength;
1211 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1212 double delta = lengthFraction * ( end - start );
1213 widths[i] = start + delta;
1225 auto widthByM = [](
const QgsLineString * line )->std::unique_ptr<
double [] >
1227 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1228 for (
int i = 0; i < line->nCoordinates(); ++i )
1230 widths[ i ] = line->mAt( i );
1239 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1249 for (
int i = 0; i < ms->numGeometries(); ++i )
1252 return QVector< QgsPointXY >();
1279 return QVector< QgsPointXY >();
1281 if ( !t.
error().isEmpty() )
1284 return QVector< QgsPointXY >();
1287 const QVector<float> triangleData = t.
data();
1288 if ( triangleData.empty() )
1289 return QVector< QgsPointXY >();
1292 std::vector< double > cumulativeAreas;
1294 double totalArea = 0;
1295 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1298 return QVector< QgsPointXY >();
1300 const float aX = *it++;
1301 const float aY = *it++;
1303 const float bX = *it++;
1304 const float bY = *it++;
1306 const float cX = *it++;
1307 const float cY = *it++;
1312 cumulativeAreas.emplace_back( totalArea );
1315 std::random_device rd;
1316 std::mt19937 mt( seed == 0 ? rd() : seed );
1317 std::uniform_real_distribution<> uniformDist( 0, 1 );
1320 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1323 const double target = random * totalArea;
1324 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1329 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1334 QVector<QgsPointXY> result;
1335 result.reserve( count );
1337 for (
int i = 0; i < count; )
1340 return QVector< QgsPointXY >();
1342 const double triangleIndexRnd = uniformDist( mt );
1344 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1347 const double weightB = uniformDist( mt );
1348 const double weightC = uniformDist( mt );
1353 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1354 const double aY = triangleData.at( triangleIndex * 9 + 1 ) + bounds.
yMinimum();
1355 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1356 const double bY = triangleData.at( triangleIndex * 9 + 4 ) + bounds.
yMinimum();
1357 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1358 const double cY = triangleData.at( triangleIndex * 9 + 7 ) + bounds.
yMinimum();
1362 if ( acceptPoint( candidate ) )
1368 else if ( maxTriesPerPoint != 0 )
1372 if ( tries == maxTriesPerPoint )
1383 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1387 std::unique_ptr<QgsAbstractGeometry> triangulation =
geos.constrainedDelaunayTriangulation( &error );
1388 if ( !triangulation || triangulation->isEmpty( ) )
1399 std::vector< double > cumulativeAreas;
1401 double totalArea = 0;
1402 std::vector< double > vertices(
static_cast< std::size_t
>( mp->
numGeometries() ) * 6 );
1403 double *vertexData = vertices.data();
1417 const double aX = exterior->
xAt( 0 );
1418 const double aY = exterior->
yAt( 0 );
1419 const double bX = exterior->
xAt( 1 );
1420 const double bY = exterior->
yAt( 1 );
1421 const double cX = exterior->
xAt( 2 );
1422 const double cY = exterior->
yAt( 2 );
1432 cumulativeAreas.emplace_back( totalArea );
1435 std::random_device rd;
1436 std::mt19937 mt( seed == 0 ? rd() : seed );
1437 std::uniform_real_distribution<> uniformDist( 0, 1 );
1440 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1443 const double target = random * totalArea;
1444 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1449 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1454 QVector<QgsPointXY> result;
1455 result.reserve( count );
1457 vertexData = vertices.data();
1458 for (
int i = 0; i < count; )
1461 return QVector< QgsPointXY >();
1463 const double triangleIndexRnd = uniformDist( mt );
1465 const std::size_t triangleIndex = selectRandomTriangle( triangleIndexRnd );
1468 const double weightB = uniformDist( mt );
1469 const double weightC = uniformDist( mt );
1474 const double aX = vertexData[ triangleIndex * 6 ];
1475 const double aY = vertexData[ triangleIndex * 6 + 1 ];
1476 const double bX = vertexData[ triangleIndex * 6 + 2 ];
1477 const double bY = vertexData[ triangleIndex * 6 + 3 ];
1478 const double cX = vertexData[ triangleIndex * 6 + 4 ];
1479 const double cY = vertexData[ triangleIndex * 6 + 5 ];
1484 if ( acceptPoint( candidate ) )
1490 else if ( maxTriesPerPoint != 0 )
1494 if ( tries == maxTriesPerPoint )
1505 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1508 return QVector< QgsPointXY >();
1511#if (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=11) || GEOS_VERSION_MAJOR>3
1521 double pointSpacingAngleTolerance )
1527 std::unique_ptr< QgsCircularString > out;
1533 auto out = std::make_unique< QgsCompoundCurve >();
1535 for (
int i = 0; i < in->
nCurves(); i ++ )
1537 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1542 for (
int i = 0; i < processedCompoundCurve->nCurves(); ++i )
1544 out->addCurve( processedCompoundCurve->curveAt( i )->clone() );
1549 out->addCurve( processed.release() );
1559 auto out = std::make_unique< QgsCompoundCurve >();
1562 const unsigned int minQuadEdges = 2;
1575 out->addCurve( lineString->
clone() );
1581 QVector< int > edgesInArcs( numEdges + 1, 0 );
1585 double abX = b.x() - a.
x();
1586 double abY = b.y() - a.
y();
1588 double cbX = b.x() -
c.x();
1589 double cbY = b.y() -
c.y();
1591 double dot = ( abX * cbX + abY * cbY );
1592 double cross = ( abX * cbY - abY * cbX );
1594 double alpha = std::atan2( cross, dot );
1609 double centerX = 0.0;
1610 double centerY = 0.0;
1613 while ( i < numEdges - 2 )
1615 unsigned int arcEdges = 0;
1616 double numQuadrants = 0;
1619 bool foundArc =
false;
1621 a1 = lineString->
pointN( i );
1622 a2 = lineString->
pointN( i + 1 );
1623 a3 = lineString->
pointN( i + 2 );
1626 for ( j = i + 3; j < numEdges + 1; j++ )
1628 b = lineString->
pointN( j );
1635 for ( k = j - 1; k > j - 4; k-- )
1636 edgesInArcs[k] = currentArc;
1656 arcEdges = j - 1 - i;
1657 if ( first.
x() == b.x() && first.
y() == b.y() )
1665 angle = arcAngle( first,
QgsPoint( centerX, centerY ), b );
1671 angle = 2 * M_PI + angle;
1672 numQuadrants = ( 4 * angle ) / ( 2 * M_PI );
1675 if ( arcEdges < minQuadEdges * numQuadrants )
1678 for ( k = j - 1; k >= i; k-- )
1695 int edgeType = edgesInArcs[0];
1697 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1702 QVector< QgsPoint > points;
1703 for (
int j = start; j < end + 2; ++ j )
1705 points.append( lineString->
pointN( j ) );
1707 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1708 out->addCurve( straightSegment.release() );
1713 QVector< QgsPoint > points;
1714 points.append( lineString->
pointN( start ) );
1715 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1716 points.append( lineString->
pointN( end + 1 ) );
1717 auto curvedSegment = std::make_unique< QgsCircularString >();
1718 curvedSegment->setPoints( points );
1719 out->addCurve( curvedSegment.release() );
1723 for (
int i = 1; i < numEdges; i++ )
1725 if ( edgeType != edgesInArcs[i] )
1728 addPointsToCurve( start, end, edgeType );
1730 edgeType = edgesInArcs[i];
1736 addPointsToCurve( start, end, edgeType );
1741 std::unique_ptr< QgsCircularString > res;
1762 auto result = std::make_unique< QgsCurvePolygon>();
1765 distanceTolerance, angleTolerance ).release() );
1769 distanceTolerance, angleTolerance ).release() );
1791 int numGeom = gc->numGeometries();
1792 QVector< QgsAbstractGeometry * > geometryList;
1793 geometryList.reserve( numGeom );
1794 for (
int i = 0; i < numGeom; ++i )
1817 area = std::numeric_limits<double>::max();
1819 width = std::numeric_limits<double>::max();
1820 height = std::numeric_limits<double>::max();
1822 if ( !mGeometry || mGeometry->nCoordinates() < 2 )
1826 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1835 if ( !hull->nextVertex( vertexId, pt0 ) )
1841 double totalRotation = 0;
1842 while ( hull->nextVertex( vertexId, pt2 ) )
1845 double rotateAngle = 180.0 / M_PI * currentAngle;
1846 totalRotation += rotateAngle;
1848 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1849 t.rotate( rotateAngle );
1850 t.translate( -pt0.
x(), -pt0.
y() );
1852 hull->transform( t );
1855 double currentArea = bounds.
width() * bounds.
height();
1856 if ( currentArea < area )
1860 angle = totalRotation;
1861 width = bounds.
width();
1862 height = bounds.
height();
1865 pt1 = hull->vertexAt( vertexId );
1871 if ( width > height )
1873 width = minRect.
height();
1874 height = minRect.
width();
1875 angle = angle + 90.0;
1879 if ( angle > 180.0 )
1880 angle = std::fmod( angle, 180.0 );
1887 const int totalPoints = line->
numPoints();
1888 if ( totalPoints < 2 )
1891 const double *x = line->
xData();
1892 const double *y = line->
yData();
1894 double prevX = *x++;
1895 double prevY = *y++;
1897 QVector< double > outX;
1898 QVector< double > outY;
1899 const double totalLength = line->
length();
1901 const int maxRepetitions = std::ceil( totalLength / wavelength );
1902 if ( !strictWavelength )
1903 wavelength = totalLength / maxRepetitions;
1905 const int estimatedPoints = maxRepetitions * 2 + 2;
1906 outX.reserve( estimatedPoints );
1907 outY.reserve( estimatedPoints );
1908 outX.append( prevX );
1909 outY.append( prevY );
1911 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1913 for (
int i = 1; i < totalPoints; ++i )
1915 double thisX = *x++;
1916 double thisY = *y++;
1920 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1923 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1928 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1929 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1931 outX.append( outPointX );
1932 outY.append( outPointY );
1934 distanceToNextPointFromStartOfSegment += wavelength / 2;
1940 distanceToNextPointFromStartOfSegment -= segmentLength;
1943 outX.append( prevX );
1944 outY.append( prevY );
1946 return std::make_unique< QgsLineString >( outX, outY );
1950 const double minimumWavelength,
const double maximumWavelength,
1951 const double minimumAmplitude,
const double maximumAmplitude,
1952 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1954 const int totalPoints = line->
numPoints();
1955 if ( totalPoints < 2 )
1958 const double *x = line->
xData();
1959 const double *y = line->
yData();
1961 double prevX = *x++;
1962 double prevY = *y++;
1964 QVector< double > outX;
1965 QVector< double > outY;
1966 const double totalLength = line->
length();
1968 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1970 const int estimatedPoints = maxRepetitions * 2 + 2;
1971 outX.reserve( estimatedPoints );
1972 outY.reserve( estimatedPoints );
1973 outX.append( prevX );
1974 outY.append( prevY );
1976 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1977 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1978 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1981 for (
int i = 1; i < totalPoints; ++i )
1983 double thisX = *x++;
1984 double thisY = *y++;
1988 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1991 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1996 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1997 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1998 outX.append( outPointX );
1999 outY.append( outPointY );
2001 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2002 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2004 distanceToNextPointFromStartOfSegment += wavelength / 2;
2010 distanceToNextPointFromStartOfSegment -= segmentLength;
2013 outX.append( prevX );
2014 outY.append( prevY );
2016 return std::make_unique< QgsLineString >( outX, outY );
2021 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2025 geom = segmentizedCopy.get();
2036 auto result = std::make_unique< QgsPolygon >();
2039 wavelength, amplitude, strictWavelength ).release() );
2043 wavelength, amplitude, strictWavelength ).release() );
2050std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2052 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2056 geom = segmentizedCopy.get();
2067 auto result = std::make_unique< QgsPolygon >();
2070 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2074 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2099 int numGeom = gc->numGeometries();
2100 QVector< QgsAbstractGeometry * > geometryList;
2101 geometryList.reserve( numGeom );
2102 for (
int i = 0; i < numGeom; ++i )
2104 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2122 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2131 std::random_device rd;
2132 std::mt19937 mt( seed == 0 ? rd() : seed );
2133 std::uniform_real_distribution<> uniformDist( 0, 1 );
2142 int numGeom = gc->numGeometries();
2143 QVector< QgsAbstractGeometry * > geometryList;
2144 geometryList.reserve( numGeom );
2145 for (
int i = 0; i < numGeom; ++i )
2147 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2165 const int totalPoints = line->
numPoints();
2166 if ( totalPoints < 2 )
2169 const double *x = line->
xData();
2170 const double *y = line->
yData();
2172 double prevX = *x++;
2173 double prevY = *y++;
2175 QVector< double > outX;
2176 QVector< double > outY;
2177 const double totalLength = line->
length();
2179 const int maxRepetitions = std::ceil( totalLength / wavelength );
2180 if ( !strictWavelength )
2181 wavelength = totalLength / maxRepetitions;
2183 const int estimatedPoints = maxRepetitions * 4 + 2;
2184 outX.reserve( estimatedPoints );
2185 outY.reserve( estimatedPoints );
2186 outX.append( prevX );
2187 outY.append( prevY );
2190 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2191 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2193 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2196 for (
int i = 1; i < totalPoints; ++i )
2198 double thisX = *x++;
2199 double thisY = *y++;
2203 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2206 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2211 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2212 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2213 outX.append( pX + side * amplitude * sinAngle );
2214 outY.append( pY + side * amplitude * cosAngle );
2215 outX.append( pX - side * amplitude * sinAngle );
2216 outY.append( pY - side * amplitude * cosAngle );
2218 distanceToNextPointFromStartOfSegment += wavelength / 2;
2224 distanceToNextPointFromStartOfSegment -= segmentLength;
2230 outX.append( prevX );
2231 outY.append( prevY );
2233 return std::make_unique< QgsLineString >( outX, outY );
2237 const double minimumWavelength,
const double maximumWavelength,
2238 const double minimumAmplitude,
const double maximumAmplitude,
2239 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2241 const int totalPoints = line->
numPoints();
2242 if ( totalPoints < 2 )
2245 const double *x = line->
xData();
2246 const double *y = line->
yData();
2248 double prevX = *x++;
2249 double prevY = *y++;
2251 QVector< double > outX;
2252 QVector< double > outY;
2253 const double totalLength = line->
length();
2255 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2257 const int estimatedPoints = maxRepetitions * 4 + 2;
2258 outX.reserve( estimatedPoints );
2259 outY.reserve( estimatedPoints );
2260 outX.append( prevX );
2261 outY.append( prevY );
2263 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2266 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2267 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2269 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2270 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2273 for (
int i = 1; i < totalPoints; ++i )
2275 double thisX = *x++;
2276 double thisY = *y++;
2280 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2283 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2288 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2289 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2290 outX.append( pX + side * amplitude * sinAngle );
2291 outY.append( pY + side * amplitude * cosAngle );
2293 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2294 outX.append( pX - side * amplitude * sinAngle );
2295 outY.append( pY - side * amplitude * cosAngle );
2297 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2298 distanceToNextPointFromStartOfSegment += wavelength / 2;
2304 distanceToNextPointFromStartOfSegment -= segmentLength;
2307 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2308 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2309 outX.append( prevX );
2310 outY.append( prevY );
2312 return std::make_unique< QgsLineString >( outX, outY );
2317 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2321 geom = segmentizedCopy.get();
2332 auto result = std::make_unique< QgsPolygon >();
2335 wavelength, amplitude, strictWavelength ).release() );
2339 wavelength, amplitude, strictWavelength ).release() );
2346std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2348 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2352 geom = segmentizedCopy.get();
2363 auto result = std::make_unique< QgsPolygon >();
2366 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2370 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2395 int numGeom = gc->numGeometries();
2396 QVector< QgsAbstractGeometry * > geometryList;
2397 geometryList.reserve( numGeom );
2398 for (
int i = 0; i < numGeom; ++i )
2400 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2418 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2427 std::random_device rd;
2428 std::mt19937 mt( seed == 0 ? rd() : seed );
2429 std::uniform_real_distribution<> uniformDist( 0, 1 );
2438 int numGeom = gc->numGeometries();
2439 QVector< QgsAbstractGeometry * > geometryList;
2440 geometryList.reserve( numGeom );
2441 for (
int i = 0; i < numGeom; ++i )
2443 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2461 const int totalPoints = line->
numPoints();
2462 if ( totalPoints < 2 )
2465 const double *x = line->
xData();
2466 const double *y = line->
yData();
2468 double prevX = *x++;
2469 double prevY = *y++;
2471 const double totalLength = line->
length();
2473 const int maxRepetitions = std::ceil( totalLength / wavelength );
2474 if ( !strictWavelength )
2475 wavelength = totalLength / maxRepetitions;
2477 const int segments = 10;
2481 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2482 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2483 bool isFirstPart =
true;
2485 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2486 int bufferIndex = 1;
2487 auto out = std::make_unique< QgsLineString >();
2489 double segmentAngleRadians = 0;
2490 double remainingDistance = totalLength;
2491 double totalCoveredDistance = 0;
2493 for (
int i = 1; i < totalPoints; ++i )
2495 double thisX = *x++;
2496 double thisY = *y++;
2500 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2503 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2506 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2508 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2509 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2511 if ( bufferIndex == 1 && isFirstPart )
2513 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2514 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2515 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2516 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2518 distanceToNextPointFromStartOfSegment += wavelength / 8;
2520 else if ( bufferIndex == 1 )
2522 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2523 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2524 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2525 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2527 distanceToNextPointFromStartOfSegment += wavelength / 4;
2529 else if ( bufferIndex == 2 )
2531 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2532 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2536 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2537 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2538 isFirstPart =
false;
2543 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2544 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2545 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2547 out->append( bezier.get() );
2550 xOutBuffer[0] = xOutBuffer[3];
2551 yOutBuffer[0] = yOutBuffer[3];
2554 distanceToNextPointFromStartOfSegment += wavelength / 4;
2557 totalCoveredDistance += segmentLength;
2560 distanceToNextPointFromStartOfSegment -= segmentLength;
2563 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2564 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2565 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2566 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2569 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2570 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2573 out->append( bezier.get() );
2579 const double minimumWavelength,
const double maximumWavelength,
2580 const double minimumAmplitude,
const double maximumAmplitude,
2581 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2583 const int totalPoints = line->
numPoints();
2584 if ( totalPoints < 2 )
2587 const double *x = line->
xData();
2588 const double *y = line->
yData();
2590 double prevX = *x++;
2591 double prevY = *y++;
2593 const double totalLength = line->
length();
2595 const int segments = 10;
2599 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2600 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2601 bool isFirstPart =
true;
2603 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2604 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2606 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2607 int bufferIndex = 1;
2608 auto out = std::make_unique< QgsLineString >();
2610 double segmentAngleRadians = 0;
2612 double remainingDistance = totalLength;
2613 double totalCoveredDistance = 0;
2615 for (
int i = 1; i < totalPoints; ++i )
2617 double thisX = *x++;
2618 double thisY = *y++;
2622 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2625 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2628 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2630 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2631 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2633 if ( bufferIndex == 1 && isFirstPart )
2635 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2636 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2637 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2638 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2640 distanceToNextPointFromStartOfSegment += wavelength / 8;
2642 else if ( bufferIndex == 1 )
2644 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2645 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2646 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2647 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2649 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2650 distanceToNextPointFromStartOfSegment += wavelength / 4;
2652 else if ( bufferIndex == 2 )
2654 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2655 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2659 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2660 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2661 isFirstPart =
false;
2666 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2667 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2668 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2670 out->append( bezier.get() );
2673 xOutBuffer[0] = xOutBuffer[3];
2674 yOutBuffer[0] = yOutBuffer[3];
2678 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2680 distanceToNextPointFromStartOfSegment += wavelength / 4;
2683 totalCoveredDistance += segmentLength;
2687 distanceToNextPointFromStartOfSegment -= segmentLength;
2690 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2691 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2692 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2693 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2695 if ( out->isEmpty() )
2699 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2702 out->append( bezier.get() );
2707 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2708 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2711 out->append( bezier.get() );
2719 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2723 geom = segmentizedCopy.get();
2734 auto result = std::make_unique< QgsPolygon >();
2737 wavelength, amplitude, strictWavelength ).release() );
2741 wavelength, amplitude, strictWavelength ).release() );
2748std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2750 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2754 geom = segmentizedCopy.get();
2765 auto result = std::make_unique< QgsPolygon >();
2768 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2772 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2797 int numGeom = gc->numGeometries();
2798 QVector< QgsAbstractGeometry * > geometryList;
2799 geometryList.reserve( numGeom );
2800 for (
int i = 0; i < numGeom; ++i )
2802 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2820 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2829 std::random_device rd;
2830 std::mt19937 mt( seed == 0 ? rd() : seed );
2831 std::uniform_real_distribution<> uniformDist( 0, 1 );
2840 int numGeom = gc->numGeometries();
2841 QVector< QgsAbstractGeometry * > geometryList;
2842 geometryList.reserve( numGeom );
2843 for (
int i = 0; i < numGeom; ++i )
2845 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2862 const QVector< double> &pattern,
2866 double patternOffset )
2868 const int totalPoints = line->
numPoints();
2869 if ( totalPoints < 2 )
2872 const int patternSize = pattern.size();
2874 const double *x = line->
xData();
2875 const double *y = line->
yData();
2877 double prevX = *x++;
2878 double prevY = *y++;
2880 auto result = std::make_unique< QgsMultiLineString >();
2882 QVector< double > outX;
2883 QVector< double > outY;
2884 const double totalLength = line->
length();
2886 double patternLength = 0;
2887 double patternDashLength = 0;
2888 double patternGapLength = 0;
2889 for (
int i = 0; i < pattern.size(); ++i )
2891 patternLength += pattern.at( i );
2893 patternDashLength += pattern.at( i );
2895 patternGapLength += pattern.at( i );
2898 double firstPatternLength = 0;
2899 double firstPatternDashLength = 0;
2900 double firstPatternGapLength = 0;
2901 switch ( startRule )
2905 firstPatternLength = patternLength;
2906 firstPatternDashLength = patternDashLength;
2907 firstPatternGapLength = patternGapLength;
2910 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2911 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2912 firstPatternGapLength = patternGapLength;
2915 firstPatternLength = pattern.at( patternSize - 1 );
2916 firstPatternDashLength = 0;
2917 firstPatternGapLength = pattern.at( patternSize - 1 );
2920 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2921 firstPatternDashLength = 0;
2922 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2926 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2928 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2929 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2930 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2934 lastPatternLength = 0;
2935 lastPatternDashLength = 0;
2936 lastPatternGapLength = 0;
2939 lastPatternLength -= pattern.at( patternSize - 1 );
2940 lastPatternGapLength -= pattern.at( patternSize - 1 );
2943 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2944 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2945 lastPatternGapLength -= pattern.at( patternSize - 1 );
2948 lastPatternGapLength = patternGapLength;
2951 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2952 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2956 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2957 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2959 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2960 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2961 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2963 double dashLengthScalingFactor = 1;
2964 double gapLengthScalingFactor = 1;
2968 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2970 switch ( adjustment )
2973 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2974 gapLengthScalingFactor = dashLengthScalingFactor;
2977 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2980 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2985 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2986 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2988 const int maxPatterns = middlePatternRepetitions + 2;
2989 result->reserve( maxPatterns );
2991 int patternIndex = 0;
2992 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2994 switch ( startRule )
3000 distanceToNextPointFromStartOfSegment *= 0.5;
3003 patternIndex = patternSize - 1;
3005 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
3008 patternIndex = patternSize - 1;
3010 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
3014 const double adjustedOffset = fmod( patternOffset, patternLength );
3015 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
3019 double remainingOffset = scaledOffset;
3020 while ( remainingOffset > 0 )
3022 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
3024 distanceToNextPointFromStartOfSegment -= remainingOffset;
3028 remainingOffset -= distanceToNextPointFromStartOfSegment;
3031 if ( patternIndex == patternSize )
3034 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3040 outX.append( prevX );
3041 outY.append( prevY );
3044 for (
int i = 1; i < totalPoints; ++i )
3046 double thisX = *x++;
3047 double thisY = *y++;
3050 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
3053 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
3068 if ( patternIndex >= patternSize )
3071 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3076 outX.append( thisX );
3077 outY.append( thisY );
3082 distanceToNextPointFromStartOfSegment -= segmentLength;
3087 outX.append( prevX );
3088 outY.append( prevY );
3096 const QVector<double> &pattern,
3100 double patternOffset )
3102 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
3106 geom = segmentizedCopy.get();
3117 auto result = std::make_unique< QgsMultiLineString >();
3120 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
3121 result->addGeometry( exteriorParts->geometryN( i )->clone() );
3126 for (
int j = 0; j < ringParts->numGeometries(); ++j )
3127 result->addGeometry( ringParts->geometryN( j )->clone() );
3136 if ( pattern.size() < 2 )
3140 if ( !mGeometry || mGeometry->isEmpty() )
3152 int numGeom = gc->numGeometries();
3153 QVector< QgsAbstractGeometry * > geometryList;
3154 geometryList.reserve( numGeom );
3155 for (
int i = 0; i < numGeom; ++i )
3157 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
3165 for (
int j = 0; j < collection->numGeometries(); ++j )
3167 first.
addPartV2( collection->geometryN( j )->clone() );
DashPatternSizeAdjustment
Dash pattern size adjustment options.
@ ScaleDashOnly
Only dash lengths are adjusted.
@ ScaleBothDashAndGap
Both the dash and gap lengths are adjusted equally.
@ ScaleGapOnly
Only gap lengths are adjusted.
DashPatternLineEndingRule
Dash pattern line ending rules.
@ HalfDash
Start or finish the pattern with a half length dash.
@ HalfGap
Start or finish the pattern with a half length gap.
@ FullGap
Start or finish the pattern with a full gap.
@ FullDash
Start or finish the pattern with a full dash.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CompoundCurve
CompoundCurve.
@ CircularString
CircularString.
The vertex_iterator class provides an STL-style iterator for vertices.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
bool isMeasure() const
Returns true if the geometry contains m values.
virtual QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary const part after the last part of the geometry.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
Compound curve geometry type.
int nCurves() const
Returns the number of curves in the geometry.
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
virtual int numPoints() const =0
Returns the number of points in the curve.
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual bool isClosed() const
Returns true if the curve is closed.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
virtual QgsPolygon * toPolygon(unsigned int segments=36) const
Returns a segmented polygon.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
int partCount() const override
Returns count of parts contained in the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
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 distance2D(double x1, double y1, double x2, double y2)
Returns the 2D distance between (x1, y1) and (x2, y2).
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 void weightedPointInTriangle(double aX, double aY, double bX, double bY, double cX, double cY, double weightB, double weightC, double &pointX, double &pointY)
Returns a weighted point inside the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
static double triangleArea(double aX, double aY, double bX, double bY, double cX, double cY)
Returns the area of the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
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 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 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 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...
A geometry is the spatial representation of a feature.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
QgsPointXY closestVertex(const QgsPointXY &point, int &closestVertexIndex, int &previousVertexIndex, int &nextVertexIndex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false)
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries, const QgsGeometryParameters ¶meters=QgsGeometryParameters())
Compute the unary union on a list of geometries.
Qgis::GeometryOperationResult addPartV2(const QVector< QgsPointXY > &points, Qgis::WkbType wkbType=Qgis::WkbType::Unknown)
Adds a new part to a the geometry.
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Does vector analysis using the GEOS library and handles import, export, and exception handling.
QgsGeometry triangularWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized triangular waves along the boundary of the geometry, with the specified wavelen...
QgsGeometry triangularWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs triangular waves along the boundary of the geometry, with the specified wavelength and amp...
QgsInternalGeometryEngine(const QgsGeometry &geometry)
The caller is responsible that the geometry is available and unchanged for the whole lifetime of this...
QgsGeometry roundWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs rounded (sine-like) waves along the boundary of the geometry, with the specified wavelengt...
QgsGeometry poleOfInaccessibility(double precision, double *distanceFromBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
QgsGeometry squareWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs square waves along the boundary of the geometry, with the specified wavelength and amplitu...
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer using the m-values from a (multi)line geometry.
QgsGeometry extrude(double x, double y) const
Will extrude a line or (segmentized) curve by a given offset and return a polygon representation of i...
QgsGeometry roundWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized rounded (sine-like) waves along the boundary of the geometry,...
QgsGeometry orthogonalize(double tolerance=1.0E-8, int maxIterations=1000, double angleThreshold=15.0) const
Attempts to orthogonalize a line or polygon geometry by shifting vertices to make the geometries angl...
QgsGeometry variableWidthBuffer(int segments, const std::function< std::unique_ptr< double[] >(const QgsLineString *line) > &widthFunction) const
Calculates a variable width buffer for a (multi)curve geometry.
QString lastError() const
Returns an error string referring to the last error encountered.
QgsGeometry orientedMinimumBoundingBox(double &area, double &angle, double &width, double &height) const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a tapered width buffer for a (multi)curve geometry.
QVector< QgsPointXY > randomPointsInPolygon(int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed=0, QgsFeedback *feedback=nullptr, int maxTriesPerPoint=0)
Returns a list of count random points generated inside a polygon geometry (if acceptPoint is specifie...
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Densifies the geometry by adding the specified number of extra nodes within each segment of the geome...
QgsGeometry applyDashPattern(const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternLineEndingRule endRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternSizeAdjustment adjustment=Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap, double patternOffset=0) const
Applies a dash pattern to a geometry, returning a MultiLineString geometry which is the input geometr...
QgsGeometry squareWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized square waves along the boundary of the geometry, with the specified wavelength ...
QgsGeometry convertToCurves(double distanceTolerance, double angleTolerance) const
Attempts to convert a non-curved geometry into a curved geometry type (e.g.
bool isAxisParallelRectangle(double maximumDeviation, bool simpleRectanglesOnly=false) const
Returns true if the geometry is a polygon that is almost an axis-parallel rectangle.
Represents a single 2D line segment, consisting of a 2D start and end vertex only.
int pointLeftOfLine(const QgsPointXY &point) const
Tests if a point is to the left of the line segment.
double endY() const
Returns the segment's end y-coordinate.
QgsPointXY end() const
Returns the segment's end point.
double endX() const
Returns the segment's end x-coordinate.
QgsPointXY start() const
Returns the segment's start point.
double startX() const
Returns the segment's start x-coordinate.
void reverse()
Reverses the line segment, so that the start and end points are flipped.
double startY() const
Returns the segment's start y-coordinate.
Line string geometry type, with support for z-dimension and m-values.
static std::unique_ptr< QgsLineString > fromBezierCurve(const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments=30)
Returns a new linestring created by segmentizing the bezier curve between start and end,...
bool isClosed() const override
Returns true if the curve is closed.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
double length() const override
Returns the planar, 2-dimensional length of the geometry.
QgsPoint startPoint() const override
Returns the starting point of the curve.
int numPoints() const override
Returns the number of points in the curve.
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
void setYAt(int index, double y)
Sets the y-coordinate of the specified node in the line string.
double mAt(int index) const override
Returns the m value of the specified node in the line string.
void setXAt(int index, double x)
Sets the x-coordinate of the specified node in the line string.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
double zAt(int index) const override
Returns the z-coordinate of the specified node in the line string.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
Multi curve geometry collection.
Multi polygon geometry collection.
Multi surface geometry collection.
Point geometry type, with support for z-dimension and m-values.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
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 setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
void addInteriorRing(QgsCurve *ring) override
Adds an interior ring to the geometry (takes ownership).
bool intersects(const QgsLineSegment2D &segment, QgsPointXY &intersectPoint) const
Finds the closest intersection point of the ray and a line segment.
A rectangle specified with double values.
Tessellates polygons into triangles.
QVector< float > data() const
Returns array of triangle vertex data.
void setBounds(const QgsRectangle &bounds)
Sets scaling and the bounds of the input geometry coordinates.
void addPolygon(const QgsPolygon &polygon, float extrusionHeight)
Tessellates a triangle and adds its vertex entries to the output data array.
QString error() const
Returns a descriptive error string if the tessellation failed.
int dataVerticesCount() const
Returns the number of vertices stored in the output data array.
void setInputZValueIgnored(bool ignore)
Sets whether Z values from the input geometries are ignored (true) or not (false).
Represent a 2-dimensional vector.
double lengthSquared() const
Returns the length of the vector.
double crossProduct(QgsVector v) const
Returns the 2D cross product of this vector and another vector v.
QgsVector normalized() const
Returns the vector's normalized (or "unit") vector (ie same angle but length of 1....
double length() const
Returns the length of the vector.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static Q_INVOKABLE bool isCurvedType(Qgis::WkbType type)
Returns true if the WKB type is a curved type or can contain curved geometries.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
Contains geos related utilities and functions.
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
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< QgsPointXY > randomPointsInPolygonGeosBackend(const QgsAbstractGeometry *geometry, int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed, QgsFeedback *feedback, int maxTriesPerPoint, QString &error)
std::unique_ptr< QgsCurve > lineToCurve(const QgsCurve *curve, double distanceTolerance, double pointSpacingAngleTolerance)
bool matchesOrientation(std::array< Direction, 4 > dirs, std::array< Direction, 4 > oriented)
double normalizedDotProduct(const QgsPoint &a, const QgsPoint &b, const QgsPoint &c)
bool isClockwise(std::array< Direction, 4 > dirs)
Checks whether the 4 directions in dirs make up a clockwise rectangle.
std::unique_ptr< QgsLineString > squareWavesRandomizedAlongLine(const QgsLineString *line, const double minimumWavelength, const double maximumWavelength, const double minimumAmplitude, const double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
std::unique_ptr< QgsLineString > squareWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
QgsAbstractGeometry * orthogonalizeGeom(const QgsAbstractGeometry *geom, int maxIterations, double tolerance, double lowerThreshold, double upperThreshold)
QVector< QgsPointXY > randomPointsInPolygonPoly2TriBackend(const QgsAbstractGeometry *geometry, int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed, QgsFeedback *feedback, int maxTriesPerPoint, QString &error)
std::unique_ptr< QgsLineString > triangularWavesRandomizedAlongLine(const QgsLineString *line, const double minimumWavelength, const double maximumWavelength, const double minimumAmplitude, const double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
QgsLineString * doDensify(const QgsLineString *ring, int extraNodesPerSegment=-1, double distance=1)
Direction getEdgeDirection(const QgsPoint &p1, const QgsPoint &p2, double maxDev)
Determines the direction of an edge from p1 to p2.
std::unique_ptr< QgsAbstractGeometry > applyDashPatternPrivate(const QgsAbstractGeometry *geom, const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule, Qgis::DashPatternLineEndingRule endRule, Qgis::DashPatternSizeAdjustment adjustment, double patternOffset)
std::unique_ptr< QgsLineString > roundWavesRandomizedAlongLine(const QgsLineString *line, const double minimumWavelength, const double maximumWavelength, const double minimumAmplitude, const double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
QgsVector calcMotion(const QgsPoint &a, const QgsPoint &b, const QgsPoint &c, double lowerThreshold, double upperThreshold)
QVector< QgsPointXY > generateSegmentCurve(const QgsPoint ¢er1, const double radius1, const QgsPoint ¢er2, const double radius2)
bool dotProductWithinAngleTolerance(double dotProduct, double lowerThreshold, double upperThreshold)
QgsLineString * doOrthogonalize(QgsLineString *ring, int iterations, double tolerance, double lowerThreshold, double upperThreshold)
double squareness(QgsLineString *ring, double lowerThreshold, double upperThreshold)
std::unique_ptr< QgsMultiLineString > dashPatternAlongLine(const QgsLineString *line, const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule, Qgis::DashPatternLineEndingRule endRule, Qgis::DashPatternSizeAdjustment adjustment, double patternOffset)
std::unique_ptr< QgsAbstractGeometry > convertGeometryToCurves(const QgsAbstractGeometry *geom, double distanceTolerance, double angleTolerance)
std::unique_ptr< QgsAbstractGeometry > roundWavesPrivate(const QgsAbstractGeometry *geom, double wavelength, double amplitude, bool strictWavelength)
bool isCounterClockwise(std::array< Direction, 4 > dirs)
Checks whether the 4 directions in dirs make up a counter-clockwise rectangle.
QgsAbstractGeometry * densifyGeometry(const QgsAbstractGeometry *geom, int extraNodesPerSegment=1, double distance=1)
std::unique_ptr< QgsLineString > roundWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
std::pair< bool, std::array< Direction, 4 > > getEdgeDirections(const QgsPolygon *g, double maxDev)
Checks whether the polygon consists of four nearly axis-parallel sides.
std::unique_ptr< QgsAbstractGeometry > squareWavesRandomizedPrivate(const QgsAbstractGeometry *geom, double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
std::unique_ptr< QgsAbstractGeometry > triangularWavesRandomizedPrivate(const QgsAbstractGeometry *geom, double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
std::unique_ptr< QgsAbstractGeometry > triangularWavesPrivate(const QgsAbstractGeometry *geom, double wavelength, double amplitude, bool strictWavelength)
std::unique_ptr< QgsAbstractGeometry > squareWavesPrivate(const QgsAbstractGeometry *geom, double wavelength, double amplitude, bool strictWavelength)
std::unique_ptr< QgsLineString > triangularWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
std::unique_ptr< QgsAbstractGeometry > roundWavesRandomizedPrivate(const QgsAbstractGeometry *geom, double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
QLineF segment(int index, QRectF rect, double radius)
Utility class for identifying a unique vertex within a geometry.