43using namespace Qt::StringLiterals;
46 : mGeometry( geometry.constGet() )
71 double dx = p2.
x() - p1.
x();
72 double dy = p2.
y() - p1.
y();
73 if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
75 if ( fabs( dx ) >= fabs( dy ) )
77 double dev = fabs( dy ) / fabs( dx );
84 double dev = fabs( dx ) / fabs( dy );
102 std::array<Direction, 5> dirs;
109 while ( current != end )
119 else if ( dir != dirs[idx - 1] )
129 ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
130 std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
136 int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
137 for (
int i = 1; i < 4; ++i )
139 if ( dirs[i] != oriented[( idx + i ) % 4] )
175 if ( vertexCount < 4 )
177 else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
181 std::array<Direction, 4> dirs;
182 std::tie( found4Dirs, dirs ) =
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
196 QVector<QgsLineString *> linesToProcess;
201 linesToProcess.reserve( multiCurve->
partCount() );
202 for (
int i = 0; i < multiCurve->
partCount(); ++i )
204 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
211 linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
214 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() :
nullptr );
217 if ( !linesToProcess.empty() )
219 std::unique_ptr< QgsLineString > secondline;
220 for (
QgsLineString *line : std::as_const( linesToProcess ) )
222 QTransform transform = QTransform::fromTranslate( x, y );
224 secondline.reset( line->reversed() );
225 secondline->transform( transform );
227 line->append( secondline.get() );
228 line->addVertex( line->pointN( 0 ) );
234 multipolygon->addGeometry( polygon );
255 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
259 , d( polygon->pointDistanceToBoundary( x, y ) )
260 , max( d + h * M_SQRT2 )
275struct GreaterThanByMax
277 bool operator()(
const Cell *lhs,
const Cell *rhs )
const {
return rhs->max > lhs->max; }
280Cell *getCentroidCell(
const QgsPolygon *polygon )
288 for (
int i = 0, j = len - 1; i < len; j = i++ )
290 double aX = exterior->
xAt( i );
291 double aY = exterior->
yAt( i );
292 double bX = exterior->
xAt( j );
293 double bY = exterior->
yAt( j );
294 double f = aX * bY - bX * aY;
295 x += ( aX + bX ) * f;
296 y += ( aY + bY ) * f;
300 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
302 return new Cell( x / area, y / area, 0.0, polygon );
305QgsPoint surfacePoleOfInaccessibility(
const QgsSurface *surface,
double precision,
double &distanceFromBoundary )
307 std::unique_ptr< QgsPolygon > segmentizedPoly;
312 polygon = segmentizedPoly.get();
319 double cellSize = std::min( bounds.
width(), bounds.
height() );
324 double h = cellSize / 2.0;
325 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
332 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
337 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
340 auto bboxCell = std::make_unique<Cell>( bounds.
xMinimum() + bounds.
width() / 2.0, bounds.
yMinimum() + bounds.
height() / 2.0, 0, polygon );
341 if ( bboxCell->d > bestCell->d )
343 bestCell = std::move( bboxCell );
346 while ( !cellQueue.empty() )
349 std::unique_ptr< Cell > cell( cellQueue.top() );
351 Cell *currentCell = cell.get();
354 if ( currentCell->d > bestCell->d )
356 bestCell = std::move( cell );
360 if ( currentCell->max - bestCell->d <= precision )
364 h = currentCell->h / 2.0;
365 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y - h, h, polygon ) );
366 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y - h, h, polygon ) );
367 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y + h, h, polygon ) );
368 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
371 distanceFromBoundary = bestCell->d;
373 return QgsPoint( bestCell->x, bestCell->y );
381 if ( distanceFromBoundary )
382 *distanceFromBoundary = std::numeric_limits<double>::max();
384 if ( !mGeometry || mGeometry->isEmpty() )
387 if ( precision <= 0 )
392 int numGeom = gc->numGeometries();
395 for (
int i = 0; i < numGeom; ++i )
401 double dist = std::numeric_limits<double>::max();
402 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
403 if ( dist > maxDist )
413 if ( distanceFromBoundary )
414 *distanceFromBoundary = maxDist;
423 double dist = std::numeric_limits<double>::max();
424 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
428 if ( distanceFromBoundary )
429 *distanceFromBoundary = dist;
440 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
466 for (
int i = 0; i < numPoints; ++i )
468 if ( !isClosed && i == numPoints - 1 )
470 else if ( !isClosed && i == 0 )
479 a = ring->
pointN( numPoints - 1 );
482 if ( i == numPoints - 1 )
491 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
509 double scale = 2.0 * std::min( p.
length(), q.
length() );
513 double dotProduct = p * q;
522 if ( dotProduct < -M_SQRT1_2 )
531 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
536 double minScore = std::numeric_limits<double>::max();
541 std::unique_ptr< QgsLineString > best( ring->
clone() );
543 QVector< QgsVector > motions;
544 motions.reserve( numPoints );
546 for (
int it = 0; it < iterations; ++it )
554 for (
int i = 0; i < numPoints; ++i )
556 if ( isClosed && i == numPoints - 1 )
557 motions << motions.at( 0 );
558 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
568 a = ring->
pointN( numPoints - 1 );
571 if ( i == numPoints - 1 )
576 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
583 for (
int i = 0; i < numPoints; ++i )
585 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
586 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
589 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
590 if ( newScore < minScore )
592 best.reset( ring->
clone() );
596 if ( minScore < tolerance )
602 return best.release();
608 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
612 geom = segmentizedCopy.get();
643 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
644 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
648 int numGeom = gc->numGeometries();
649 QVector< QgsAbstractGeometry * > geometryList;
650 geometryList.reserve( numGeom );
651 for (
int i = 0; i < numGeom; ++i )
653 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
672 QVector< double > outX;
673 QVector< double > outY;
674 QVector< double > outZ;
675 QVector< double > outM;
676 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
679 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
680 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
681 bool withZ = ring->
is3D();
683 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
686 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
699 int extraNodesThisSegment = extraNodesPerSegment;
700 for (
int i = 0; i < nPoints - 1; ++i )
703 x2 = ring->
xAt( i + 1 );
705 y2 = ring->
yAt( i + 1 );
709 z2 = ring->
zAt( i + 1 );
714 m2 = ring->
mAt( i + 1 );
724 if ( extraNodesPerSegment < 0 )
728 if ( extraNodesThisSegment >= 1 )
729 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
732 for (
int j = 0; j < extraNodesThisSegment; ++j )
734 double delta = multiplier * ( j + 1 );
735 xOut = x1 + delta * ( x2 - x1 );
736 yOut = y1 + delta * ( y2 - y1 );
738 zOut = z1 + delta * ( z2 - z1 );
740 mOut = m1 + delta * ( m2 - m1 );
750 outX << ring->
xAt( nPoints - 1 );
751 outY << ring->
yAt( nPoints - 1 );
753 outZ << ring->
zAt( nPoints - 1 );
755 outM << ring->
mAt( nPoints - 1 );
763 if ( extraNodesPerSegment < 0 &&
qgsDoubleNear( distance, 0 ) )
766 return geom->
clone();
769 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
773 geom = segmentizedCopy.get();
811 int numGeom = gc->numGeometries();
812 QVector< QgsAbstractGeometry * > geometryList;
813 geometryList.reserve( numGeom );
814 for (
int i = 0; i < numGeom; ++i )
816 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
847 int numGeom = gc->numGeometries();
848 QVector< QgsAbstractGeometry * > geometryList;
849 geometryList.reserve( numGeom );
850 for (
int i = 0; i < numGeom; ++i )
876 Q_ASSERT_X( ab.
pointLeftOfLine( mOrigin ) != 0,
"line_segment_dist_comparer",
"AB must not be collinear with the origin." );
877 Q_ASSERT_X( cd.
pointLeftOfLine( mOrigin ) != 0,
"line_segment_dist_comparer",
"CD must not be collinear with the origin." );
894 if ( ab.
end() == cd.
end() || oad != oab )
904 if ( cdb == 0 && cda == 0 )
906 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
908 else if ( cda == cdb || cda == 0 || cdb == 0 )
911 return cdo == cda || cdo == cdb;
927 const bool aIsLeft = a.
x() < mVertex.x();
928 const bool bIsLeft = b.
x() < mVertex.x();
929 if ( aIsLeft != bIsLeft )
934 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
936 return b.
y() < a.
y();
940 return a.
y() < b.
y();
972 const int abo =
segment.pointLeftOfLine( origin );
979 const double distA = ao * direction;
980 const double distB = ( origin -
segment.end() ) * direction;
982 if ( distA > 0 && distB > 0 )
988 if ( ( distA > 0 ) != ( distB > 0 ) )
989 intersectPoint = origin;
990 else if ( distA > distB )
991 intersectPoint =
segment.start();
993 intersectPoint =
segment.end();
1001 if ( u < 0.0 || 1.0 < u )
1008 intersectPoint = origin + direction * t;
1017 if ( radius1 > radius2 )
1024 QVector<QgsPointXY> points;
1027 points << t1 << t2 << t4 << t3;
1043 std::vector< std::unique_ptr<QgsLineString > > temporarySegmentizedLines;
1044 std::vector< const QgsLineString * > linesToProcess;
1049 for (
int i = 0; i < multiCurve->partCount(); ++i )
1059 linesToProcess.emplace_back( lineString );
1063 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( part->
segmentize() ) );
1064 linesToProcess.emplace_back( segmentizedCurve.get() );
1065 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1072 if ( curve->nCoordinates() > 0 )
1076 linesToProcess.emplace_back( lineString );
1080 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( curve->segmentize() ) );
1081 linesToProcess.emplace_back( segmentizedCurve.get() );
1082 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1087 if ( linesToProcess.empty() )
1090 g.mLastError = u
"Input geometry was not a curve type geometry"_s;
1094 QVector<QgsGeometry> bufferedLines;
1095 bufferedLines.reserve( linesToProcess.size() );
1099 QVector<QgsGeometry> parts;
1101 double prevRadius = 0;
1104 std::unique_ptr< double[] > widths = widthFunction( line );
1109 double thisRadius = widths[i] / 2.0;
1110 if ( thisRadius > 0 )
1114 QgsCircle circ( thisPoint, thisRadius );
1116 parts << thisCircle;
1125 if ( prevRadius > 0 || thisRadius > 0 )
1127 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1128 if ( !points.empty() )
1133 int beforeVertex = 0;
1134 int afterVertex = 0;
1136 double sqrDistPrev = 0;
1137 for (
int j = 0; j < points.count(); ++j )
1141 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1144 points.append( points.at( 0 ) );
1146 auto poly = std::make_unique< QgsPolygon >();
1148 if ( poly->area() > 0 )
1153 prevPoint = thisPoint;
1154 prevRadius = thisRadius;
1155 prevCircle = thisCircle;
1170 start = std::fabs( start );
1171 end = std::fabs( end );
1173 auto interpolateWidths = [start, end](
const QgsLineString *line ) -> std::unique_ptr<
double[] > {
1176 std::unique_ptr< double[] > widths(
new double[line->nCoordinates()] );
1178 widths[line->nCoordinates() - 1] = end;
1180 double lineLength = line->length();
1181 double currentLength = 0;
1182 QgsPoint prevPoint = line->pointN( 0 );
1183 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1185 QgsPoint point = line->pointN( i );
1186 double segmentLength = point.
distance( prevPoint );
1187 currentLength += segmentLength;
1188 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1189 double delta = lengthFraction * ( end - start );
1190 widths[i] = start + delta;
1202 auto widthByM = [](
const QgsLineString *line ) -> std::unique_ptr<
double[] > {
1203 std::unique_ptr< double[] > widths(
new double[line->nCoordinates()] );
1204 for (
int i = 0; i < line->nCoordinates(); ++i )
1206 widths[i] = line->mAt( i );
1226 for (
int i = 0; i < ms->numGeometries(); ++i )
1229 return QVector< QgsPointXY >();
1256 return QVector< QgsPointXY >();
1258 if ( !t.
error().isEmpty() )
1261 return QVector< QgsPointXY >();
1265 QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
const QVector<float> triangleData = t.
data();
1267 if ( triangleData.empty() )
1268 return QVector< QgsPointXY >();
1271 std::vector< double > cumulativeAreas;
1273 double totalArea = 0;
1274 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1277 return QVector< QgsPointXY >();
1279 const float aX = *it++;
1280 const float aY = *it++;
1282 const float bX = *it++;
1283 const float bY = *it++;
1285 const float cX = *it++;
1286 const float cY = *it++;
1291 cumulativeAreas.emplace_back( totalArea );
1294 std::random_device rd;
1295 std::mt19937 mt( seed == 0 ? rd() : seed );
1296 std::uniform_real_distribution<> uniformDist( 0, 1 );
1299 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random ) ->
int {
1301 const double target = random * totalArea;
1302 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1307 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1312 QVector<QgsPointXY> result;
1313 result.reserve( count );
1315 for (
int i = 0; i < count; )
1318 return QVector< QgsPointXY >();
1320 const double triangleIndexRnd = uniformDist( mt );
1322 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1325 const double weightB = uniformDist( mt );
1326 const double weightC = uniformDist( mt );
1331 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1332 const double aY = triangleData.at( triangleIndex * 9 + 1 ) + bounds.
yMinimum();
1333 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1334 const double bY = triangleData.at( triangleIndex * 9 + 4 ) + bounds.
yMinimum();
1335 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1336 const double cY = triangleData.at( triangleIndex * 9 + 7 ) + bounds.
yMinimum();
1340 if ( acceptPoint( candidate ) )
1346 else if ( maxTriesPerPoint != 0 )
1350 if ( tries == maxTriesPerPoint )
1366 std::unique_ptr<QgsAbstractGeometry> triangulation =
geos.constrainedDelaunayTriangulation( &error );
1367 if ( !triangulation || triangulation->isEmpty() )
1378 std::vector< double > cumulativeAreas;
1380 double totalArea = 0;
1381 std::vector< double > vertices(
static_cast< std::size_t
>( mp->
numGeometries() ) * 6 );
1382 double *vertexData = vertices.data();
1396 const double aX = exterior->
xAt( 0 );
1397 const double aY = exterior->
yAt( 0 );
1398 const double bX = exterior->
xAt( 1 );
1399 const double bY = exterior->
yAt( 1 );
1400 const double cX = exterior->
xAt( 2 );
1401 const double cY = exterior->
yAt( 2 );
1411 cumulativeAreas.emplace_back( totalArea );
1414 std::random_device rd;
1415 std::mt19937 mt( seed == 0 ? rd() : seed );
1416 std::uniform_real_distribution<> uniformDist( 0, 1 );
1419 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random ) ->
int {
1421 const double target = random * totalArea;
1422 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1427 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1432 QVector<QgsPointXY> result;
1433 result.reserve( count );
1435 vertexData = vertices.data();
1436 for (
int i = 0; i < count; )
1439 return QVector< QgsPointXY >();
1441 const double triangleIndexRnd = uniformDist( mt );
1443 const std::size_t triangleIndex = selectRandomTriangle( triangleIndexRnd );
1446 const double weightB = uniformDist( mt );
1447 const double weightC = uniformDist( mt );
1452 const double aX = vertexData[triangleIndex * 6];
1453 const double aY = vertexData[triangleIndex * 6 + 1];
1454 const double bX = vertexData[triangleIndex * 6 + 2];
1455 const double bY = vertexData[triangleIndex * 6 + 3];
1456 const double cX = vertexData[triangleIndex * 6 + 4];
1457 const double cY = vertexData[triangleIndex * 6 + 5];
1462 if ( acceptPoint( candidate ) )
1468 else if ( maxTriesPerPoint != 0 )
1472 if ( tries == maxTriesPerPoint )
1485 return QVector< QgsPointXY >();
1488#if ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 11 ) || GEOS_VERSION_MAJOR > 3
1497std::unique_ptr< QgsCurve >
lineToCurve(
const QgsCurve *curve,
double distanceTolerance,
double pointSpacingAngleTolerance )
1503 std::unique_ptr< QgsCircularString > out;
1509 auto out = std::make_unique< QgsCompoundCurve >();
1511 for (
int i = 0; i < in->
nCurves(); i++ )
1513 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1518 for (
int i = 0; i < processedCompoundCurve->nCurves(); ++i )
1520 out->addCurve( processedCompoundCurve->curveAt( i )->clone() );
1525 out->addCurve( processed.release() );
1535 auto out = std::make_unique< QgsCompoundCurve >();
1538 const unsigned int minQuadEdges = 2;
1551 out->addCurve( lineString->
clone() );
1557 QVector< int > edgesInArcs( numEdges + 1, 0 );
1560 double abX = b.x() - a.
x();
1561 double abY = b.y() - a.
y();
1563 double cbX = b.x() -
c.x();
1564 double cbY = b.y() -
c.y();
1566 double dot = ( abX * cbX + abY * cbY );
1567 double cross = ( abX * cbY - abY * cbX );
1569 double alpha = std::atan2( cross, dot );
1584 double centerX = 0.0;
1585 double centerY = 0.0;
1588 while ( i < numEdges - 2 )
1590 unsigned int arcEdges = 0;
1591 double numQuadrants = 0;
1594 bool foundArc =
false;
1596 a1 = lineString->
pointN( i );
1597 a2 = lineString->
pointN( i + 1 );
1598 a3 = lineString->
pointN( i + 2 );
1601 for ( j = i + 3; j < numEdges + 1; j++ )
1603 b = lineString->
pointN( j );
1610 for ( k = j - 1; k > j - 4; k-- )
1611 edgesInArcs[k] = currentArc;
1631 arcEdges = j - 1 - i;
1632 if ( first.
x() == b.x() && first.
y() == b.y() )
1640 angle = arcAngle( first,
QgsPoint( centerX, centerY ), b );
1646 angle = 2 * M_PI + angle;
1647 numQuadrants = ( 4 * angle ) / ( 2 * M_PI );
1650 if ( arcEdges < minQuadEdges * numQuadrants )
1653 for ( k = j - 1; k >= i; k-- )
1670 int edgeType = edgesInArcs[0];
1672 auto addPointsToCurve = [lineString, &out](
int start,
int end,
int type ) {
1676 QVector< QgsPoint > points;
1677 for (
int j = start; j < end + 2; ++j )
1679 points.append( lineString->
pointN( j ) );
1681 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1682 out->addCurve( straightSegment.release() );
1687 QVector< QgsPoint > points;
1688 points.append( lineString->
pointN( start ) );
1689 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1690 points.append( lineString->
pointN( end + 1 ) );
1691 auto curvedSegment = std::make_unique< QgsCircularString >();
1692 curvedSegment->setPoints( points );
1693 out->addCurve( curvedSegment.release() );
1697 for (
int i = 1; i < numEdges; i++ )
1699 if ( edgeType != edgesInArcs[i] )
1702 addPointsToCurve( start, end, edgeType );
1704 edgeType = edgesInArcs[i];
1710 addPointsToCurve( start, end, edgeType );
1715 std::unique_ptr< QgsCircularString > res;
1736 auto result = std::make_unique< QgsCurvePolygon>();
1738 result->setExteriorRing(
lineToCurve( polygon->
exteriorRing(), distanceTolerance, angleTolerance ).release() );
1741 result->addInteriorRing(
lineToCurve( polygon->
interiorRing( i ), distanceTolerance, angleTolerance ).release() );
1763 int numGeom = gc->numGeometries();
1764 QVector< QgsAbstractGeometry * > geometryList;
1765 geometryList.reserve( numGeom );
1766 for (
int i = 0; i < numGeom; ++i )
1789 area = std::numeric_limits<double>::max();
1791 width = std::numeric_limits<double>::max();
1792 height = std::numeric_limits<double>::max();
1794 if ( !mGeometry || mGeometry->nCoordinates() < 2 )
1798 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1807 if ( !hull->nextVertex( vertexId, pt0 ) )
1813 double totalRotation = 0;
1814 while ( hull->nextVertex( vertexId, pt2 ) )
1817 double rotateAngle = 180.0 / M_PI * currentAngle;
1818 totalRotation += rotateAngle;
1820 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1821 t.rotate( rotateAngle );
1822 t.translate( -pt0.
x(), -pt0.
y() );
1824 hull->transform( t );
1827 double currentArea = bounds.
width() * bounds.
height();
1828 if ( currentArea < area )
1832 angle = totalRotation;
1833 width = bounds.
width();
1834 height = bounds.
height();
1837 pt1 = hull->vertexAt( vertexId );
1843 if ( width > height )
1845 width = minRect.
height();
1846 height = minRect.
width();
1847 angle = angle + 90.0;
1851 if ( angle > 180.0 )
1852 angle = std::fmod( angle, 180.0 );
1859 const int totalPoints = line->
numPoints();
1860 if ( totalPoints < 2 )
1863 const double *x = line->
xData();
1864 const double *y = line->
yData();
1866 double prevX = *x++;
1867 double prevY = *y++;
1869 QVector< double > outX;
1870 QVector< double > outY;
1871 const double totalLength = line->
length();
1873 const int maxRepetitions = std::ceil( totalLength / wavelength );
1874 if ( !strictWavelength )
1875 wavelength = totalLength / maxRepetitions;
1877 const int estimatedPoints = maxRepetitions * 2 + 2;
1878 outX.reserve( estimatedPoints );
1879 outY.reserve( estimatedPoints );
1880 outX.append( prevX );
1881 outY.append( prevY );
1883 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1885 for (
int i = 1; i < totalPoints; ++i )
1887 double thisX = *x++;
1888 double thisY = *y++;
1892 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1895 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1900 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1901 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1903 outX.append( outPointX );
1904 outY.append( outPointY );
1906 distanceToNextPointFromStartOfSegment += wavelength / 2;
1912 distanceToNextPointFromStartOfSegment -= segmentLength;
1915 outX.append( prevX );
1916 outY.append( prevY );
1918 return std::make_unique< QgsLineString >( outX, outY );
1923 const double minimumWavelength,
1924 const double maximumWavelength,
1925 const double minimumAmplitude,
1926 const double maximumAmplitude,
1927 std::uniform_real_distribution<> &uniformDist,
1931 const int totalPoints = line->
numPoints();
1932 if ( totalPoints < 2 )
1935 const double *x = line->
xData();
1936 const double *y = line->
yData();
1938 double prevX = *x++;
1939 double prevY = *y++;
1941 QVector< double > outX;
1942 QVector< double > outY;
1943 const double totalLength = line->
length();
1945 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1947 const int estimatedPoints = maxRepetitions * 2 + 2;
1948 outX.reserve( estimatedPoints );
1949 outY.reserve( estimatedPoints );
1950 outX.append( prevX );
1951 outY.append( prevY );
1953 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1954 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1955 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1958 for (
int i = 1; i < totalPoints; ++i )
1960 double thisX = *x++;
1961 double thisY = *y++;
1965 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1968 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1973 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1974 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1975 outX.append( outPointX );
1976 outY.append( outPointY );
1978 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1979 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1981 distanceToNextPointFromStartOfSegment += wavelength / 2;
1987 distanceToNextPointFromStartOfSegment -= segmentLength;
1990 outX.append( prevX );
1991 outY.append( prevY );
1993 return std::make_unique< QgsLineString >( outX, outY );
1998 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2002 geom = segmentizedCopy.get();
2013 auto result = std::make_unique< QgsPolygon >();
2026 const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt
2029 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2033 geom = segmentizedCopy.get();
2044 auto result = std::make_unique< QgsPolygon >();
2046 result->setExteriorRing(
2051 result->addInteriorRing(
2079 int numGeom = gc->numGeometries();
2080 QVector< QgsAbstractGeometry * > geometryList;
2081 geometryList.reserve( numGeom );
2082 for (
int i = 0; i < numGeom; ++i )
2084 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2102 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2111 std::random_device rd;
2112 std::mt19937 mt( seed == 0 ? rd() : seed );
2113 std::uniform_real_distribution<> uniformDist( 0, 1 );
2122 int numGeom = gc->numGeometries();
2123 QVector< QgsAbstractGeometry * > geometryList;
2124 geometryList.reserve( numGeom );
2125 for (
int i = 0; i < numGeom; ++i )
2127 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2145 const int totalPoints = line->
numPoints();
2146 if ( totalPoints < 2 )
2149 const double *x = line->
xData();
2150 const double *y = line->
yData();
2152 double prevX = *x++;
2153 double prevY = *y++;
2155 QVector< double > outX;
2156 QVector< double > outY;
2157 const double totalLength = line->
length();
2159 const int maxRepetitions = std::ceil( totalLength / wavelength );
2160 if ( !strictWavelength )
2161 wavelength = totalLength / maxRepetitions;
2163 const int estimatedPoints = maxRepetitions * 4 + 2;
2164 outX.reserve( estimatedPoints );
2165 outY.reserve( estimatedPoints );
2166 outX.append( prevX );
2167 outY.append( prevY );
2170 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2171 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2173 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2176 for (
int i = 1; i < totalPoints; ++i )
2178 double thisX = *x++;
2179 double thisY = *y++;
2183 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2186 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2191 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2192 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2193 outX.append( pX + side * amplitude * sinAngle );
2194 outY.append( pY + side * amplitude * cosAngle );
2195 outX.append( pX - side * amplitude * sinAngle );
2196 outY.append( pY - side * amplitude * cosAngle );
2198 distanceToNextPointFromStartOfSegment += wavelength / 2;
2204 distanceToNextPointFromStartOfSegment -= segmentLength;
2210 outX.append( prevX );
2211 outY.append( prevY );
2213 return std::make_unique< QgsLineString >( outX, outY );
2218 const double minimumWavelength,
2219 const double maximumWavelength,
2220 const double minimumAmplitude,
2221 const double maximumAmplitude,
2222 std::uniform_real_distribution<> &uniformDist,
2226 const int totalPoints = line->
numPoints();
2227 if ( totalPoints < 2 )
2230 const double *x = line->
xData();
2231 const double *y = line->
yData();
2233 double prevX = *x++;
2234 double prevY = *y++;
2236 QVector< double > outX;
2237 QVector< double > outY;
2238 const double totalLength = line->
length();
2240 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2242 const int estimatedPoints = maxRepetitions * 4 + 2;
2243 outX.reserve( estimatedPoints );
2244 outY.reserve( estimatedPoints );
2245 outX.append( prevX );
2246 outY.append( prevY );
2248 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2251 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2252 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2254 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2255 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2258 for (
int i = 1; i < totalPoints; ++i )
2260 double thisX = *x++;
2261 double thisY = *y++;
2265 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2268 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2273 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2274 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2275 outX.append( pX + side * amplitude * sinAngle );
2276 outY.append( pY + side * amplitude * cosAngle );
2278 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2279 outX.append( pX - side * amplitude * sinAngle );
2280 outY.append( pY - side * amplitude * cosAngle );
2282 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2283 distanceToNextPointFromStartOfSegment += wavelength / 2;
2289 distanceToNextPointFromStartOfSegment -= segmentLength;
2292 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2293 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2294 outX.append( prevX );
2295 outY.append( prevY );
2297 return std::make_unique< QgsLineString >( outX, outY );
2302 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2306 geom = segmentizedCopy.get();
2317 auto result = std::make_unique< QgsPolygon >();
2330 const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt
2333 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2337 geom = segmentizedCopy.get();
2348 auto result = std::make_unique< QgsPolygon >();
2350 result->setExteriorRing(
2355 result->addInteriorRing(
2382 int numGeom = gc->numGeometries();
2383 QVector< QgsAbstractGeometry * > geometryList;
2384 geometryList.reserve( numGeom );
2385 for (
int i = 0; i < numGeom; ++i )
2387 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2405 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2414 std::random_device rd;
2415 std::mt19937 mt( seed == 0 ? rd() : seed );
2416 std::uniform_real_distribution<> uniformDist( 0, 1 );
2425 int numGeom = gc->numGeometries();
2426 QVector< QgsAbstractGeometry * > geometryList;
2427 geometryList.reserve( numGeom );
2428 for (
int i = 0; i < numGeom; ++i )
2430 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2448 const int totalPoints = line->
numPoints();
2449 if ( totalPoints < 2 )
2452 const double *x = line->
xData();
2453 const double *y = line->
yData();
2455 double prevX = *x++;
2456 double prevY = *y++;
2458 const double totalLength = line->
length();
2460 const int maxRepetitions = std::ceil( totalLength / wavelength );
2461 if ( !strictWavelength )
2462 wavelength = totalLength / maxRepetitions;
2464 const int segments = 10;
2468 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2469 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2470 bool isFirstPart =
true;
2472 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2473 int bufferIndex = 1;
2474 auto out = std::make_unique< QgsLineString >();
2476 double segmentAngleRadians = 0;
2477 double remainingDistance = totalLength;
2478 double totalCoveredDistance = 0;
2480 for (
int i = 1; i < totalPoints; ++i )
2482 double thisX = *x++;
2483 double thisY = *y++;
2487 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2490 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2493 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2495 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2496 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2498 if ( bufferIndex == 1 && isFirstPart )
2500 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2501 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2502 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2503 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2505 distanceToNextPointFromStartOfSegment += wavelength / 8;
2507 else if ( bufferIndex == 1 )
2509 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2510 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2511 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2512 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2514 distanceToNextPointFromStartOfSegment += wavelength / 4;
2516 else if ( bufferIndex == 2 )
2518 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2519 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2523 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2524 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2525 isFirstPart =
false;
2529 std::unique_ptr< QgsLineString > bezier(
2531 fromBezierCurve(
QgsPoint( xOutBuffer[0], yOutBuffer[0] ),
QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
QgsPoint( xOutBuffer[3], yOutBuffer[3] ), segments )
2533 out->append( bezier.get() );
2536 xOutBuffer[0] = xOutBuffer[3];
2537 yOutBuffer[0] = yOutBuffer[3];
2540 distanceToNextPointFromStartOfSegment += wavelength / 4;
2543 totalCoveredDistance += segmentLength;
2546 distanceToNextPointFromStartOfSegment -= segmentLength;
2549 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2550 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2551 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2552 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2554 std::unique_ptr< QgsLineString > bezier(
2556 fromBezierCurve( out->endPoint(),
QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
QgsPoint( prevX, prevY ), segments / 2 )
2558 out->append( bezier.get() );
2565 const double minimumWavelength,
2566 const double maximumWavelength,
2567 const double minimumAmplitude,
2568 const double maximumAmplitude,
2569 std::uniform_real_distribution<> &uniformDist,
2573 const int totalPoints = line->
numPoints();
2574 if ( totalPoints < 2 )
2577 const double *x = line->
xData();
2578 const double *y = line->
yData();
2580 double prevX = *x++;
2581 double prevY = *y++;
2583 const double totalLength = line->
length();
2585 const int segments = 10;
2589 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2590 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2591 bool isFirstPart =
true;
2593 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2594 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2596 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2597 int bufferIndex = 1;
2598 auto out = std::make_unique< QgsLineString >();
2600 double segmentAngleRadians = 0;
2602 double remainingDistance = totalLength;
2603 double totalCoveredDistance = 0;
2605 for (
int i = 1; i < totalPoints; ++i )
2607 double thisX = *x++;
2608 double thisY = *y++;
2612 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2615 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2618 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2620 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2621 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2623 if ( bufferIndex == 1 && isFirstPart )
2625 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2626 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2627 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2628 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2630 distanceToNextPointFromStartOfSegment += wavelength / 8;
2632 else if ( bufferIndex == 1 )
2634 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2635 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2636 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2637 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2639 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2640 distanceToNextPointFromStartOfSegment += wavelength / 4;
2642 else if ( bufferIndex == 2 )
2644 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2645 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2649 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2650 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2651 isFirstPart =
false;
2655 std::unique_ptr< QgsLineString > bezier(
2657 fromBezierCurve(
QgsPoint( xOutBuffer[0], yOutBuffer[0] ),
QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
QgsPoint( xOutBuffer[3], yOutBuffer[3] ), segments )
2659 out->append( bezier.get() );
2662 xOutBuffer[0] = xOutBuffer[3];
2663 yOutBuffer[0] = yOutBuffer[3];
2667 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2669 distanceToNextPointFromStartOfSegment += wavelength / 4;
2672 totalCoveredDistance += segmentLength;
2676 distanceToNextPointFromStartOfSegment -= segmentLength;
2679 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2680 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2681 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2682 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2684 if ( out->isEmpty() )
2686 std::unique_ptr< QgsLineString > bezier(
2690 out->append( bezier.get() );
2694 std::unique_ptr< QgsLineString > bezier(
2696 fromBezierCurve( out->endPoint(),
QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
QgsPoint( prevX, prevY ), segments )
2698 out->append( bezier.get() );
2706 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2710 geom = segmentizedCopy.get();
2721 auto result = std::make_unique< QgsPolygon >();
2734 const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt
2737 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2741 geom = segmentizedCopy.get();
2752 auto result = std::make_unique< QgsPolygon >();
2754 result->setExteriorRing(
2759 result->addInteriorRing(
2786 int numGeom = gc->numGeometries();
2787 QVector< QgsAbstractGeometry * > geometryList;
2788 geometryList.reserve( numGeom );
2789 for (
int i = 0; i < numGeom; ++i )
2791 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2809 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2818 std::random_device rd;
2819 std::mt19937 mt( seed == 0 ? rd() : seed );
2820 std::uniform_real_distribution<> uniformDist( 0, 1 );
2829 int numGeom = gc->numGeometries();
2830 QVector< QgsAbstractGeometry * > geometryList;
2831 geometryList.reserve( numGeom );
2832 for (
int i = 0; i < numGeom; ++i )
2834 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2854 const int totalPoints = line->
numPoints();
2855 if ( totalPoints < 2 )
2858 const int patternSize = pattern.size();
2860 const double *x = line->
xData();
2861 const double *y = line->
yData();
2863 double prevX = *x++;
2864 double prevY = *y++;
2866 auto result = std::make_unique< QgsMultiLineString >();
2868 QVector< double > outX;
2869 QVector< double > outY;
2870 const double totalLength = line->
length();
2872 double patternLength = 0;
2873 double patternDashLength = 0;
2874 double patternGapLength = 0;
2875 for (
int i = 0; i < pattern.size(); ++i )
2877 patternLength += pattern.at( i );
2879 patternDashLength += pattern.at( i );
2881 patternGapLength += pattern.at( i );
2884 double firstPatternLength = 0;
2885 double firstPatternDashLength = 0;
2886 double firstPatternGapLength = 0;
2887 switch ( startRule )
2891 firstPatternLength = patternLength;
2892 firstPatternDashLength = patternDashLength;
2893 firstPatternGapLength = patternGapLength;
2896 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2897 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2898 firstPatternGapLength = patternGapLength;
2901 firstPatternLength = pattern.at( patternSize - 1 );
2902 firstPatternDashLength = 0;
2903 firstPatternGapLength = pattern.at( patternSize - 1 );
2906 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2907 firstPatternDashLength = 0;
2908 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2912 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2914 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2915 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2916 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2920 lastPatternLength = 0;
2921 lastPatternDashLength = 0;
2922 lastPatternGapLength = 0;
2925 lastPatternLength -= pattern.at( patternSize - 1 );
2926 lastPatternGapLength -= pattern.at( patternSize - 1 );
2929 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2930 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2931 lastPatternGapLength -= pattern.at( patternSize - 1 );
2934 lastPatternGapLength = patternGapLength;
2937 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2938 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2942 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2943 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2945 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2946 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2947 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2949 double dashLengthScalingFactor = 1;
2950 double gapLengthScalingFactor = 1;
2954 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2956 switch ( adjustment )
2959 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2960 gapLengthScalingFactor = dashLengthScalingFactor;
2963 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2966 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2971 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2972 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2974 const int maxPatterns = middlePatternRepetitions + 2;
2975 result->reserve( maxPatterns );
2977 int patternIndex = 0;
2978 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2980 switch ( startRule )
2986 distanceToNextPointFromStartOfSegment *= 0.5;
2989 patternIndex = patternSize - 1;
2991 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2994 patternIndex = patternSize - 1;
2996 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
3000 const double adjustedOffset = fmod( patternOffset, patternLength );
3001 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
3005 double remainingOffset = scaledOffset;
3006 while ( remainingOffset > 0 )
3008 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
3010 distanceToNextPointFromStartOfSegment -= remainingOffset;
3014 remainingOffset -= distanceToNextPointFromStartOfSegment;
3017 if ( patternIndex == patternSize )
3020 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3026 outX.append( prevX );
3027 outY.append( prevY );
3030 for (
int i = 1; i < totalPoints; ++i )
3032 double thisX = *x++;
3033 double thisY = *y++;
3036 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
3039 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
3054 if ( patternIndex >= patternSize )
3057 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3062 outX.append( thisX );
3063 outY.append( thisY );
3068 distanceToNextPointFromStartOfSegment -= segmentLength;
3073 outX.append( prevX );
3074 outY.append( prevY );
3085 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
3089 geom = segmentizedCopy.get();
3100 auto result = std::make_unique< QgsMultiLineString >();
3103 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
3104 result->addGeometry( exteriorParts->geometryN( i )->clone() );
3109 for (
int j = 0; j < ringParts->numGeometries(); ++j )
3110 result->addGeometry( ringParts->geometryN( j )->clone() );
3121 if ( pattern.size() < 2 )
3125 if ( !mGeometry || mGeometry->isEmpty() )
3137 int numGeom = gc->numGeometries();
3138 QVector< QgsAbstractGeometry * > geometryList;
3139 geometryList.reserve( numGeom );
3140 for (
int i = 0; i < numGeom; ++i )
3142 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
3150 for (
int j = 0; j < collection->numGeometries(); ++j )
3152 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.
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.
Q_DECL_DEPRECATED 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.