42using namespace Qt::StringLiterals;
45 : mGeometry( geometry.constGet() )
70 double dx = p2.
x() - p1.
x();
71 double dy = p2.
y() - p1.
y();
72 if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
74 if ( fabs( dx ) >= fabs( dy ) )
76 double dev = fabs( dy ) / fabs( dx );
83 double dev = fabs( dx ) / fabs( dy );
101 std::array<Direction, 5> dirs;
108 while ( current != end )
118 else if ( dir != dirs[idx - 1] )
128 ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
129 std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
135 int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
136 for (
int i = 1; i < 4; ++i )
138 if ( dirs[i] != oriented[( idx + i ) % 4] )
174 if ( vertexCount < 4 )
176 else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
180 std::array<Direction, 4> dirs;
181 std::tie( found4Dirs, dirs ) =
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
195 QVector<QgsLineString *> linesToProcess;
200 linesToProcess.reserve( multiCurve->
partCount() );
201 for (
int i = 0; i < multiCurve->
partCount(); ++i )
203 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
210 linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
213 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() :
nullptr );
216 if ( !linesToProcess.empty() )
218 std::unique_ptr< QgsLineString > secondline;
219 for (
QgsLineString *line : std::as_const( linesToProcess ) )
221 QTransform transform = QTransform::fromTranslate( x, y );
223 secondline.reset( line->reversed() );
224 secondline->transform( transform );
226 line->append( secondline.get() );
227 line->addVertex( line->pointN( 0 ) );
233 multipolygon->addGeometry( polygon );
254 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
258 , d( polygon->pointDistanceToBoundary( x, y ) )
259 , max( d + h * M_SQRT2 )
274struct GreaterThanByMax
276 bool operator()(
const Cell *lhs,
const Cell *rhs )
const {
return rhs->max > lhs->max; }
279Cell *getCentroidCell(
const QgsPolygon *polygon )
287 for (
int i = 0, j = len - 1; i < len; j = i++ )
289 double aX = exterior->
xAt( i );
290 double aY = exterior->
yAt( i );
291 double bX = exterior->
xAt( j );
292 double bY = exterior->
yAt( j );
293 double f = aX * bY - bX * aY;
294 x += ( aX + bX ) * f;
295 y += ( aY + bY ) * f;
299 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
301 return new Cell( x / area, y / area, 0.0, polygon );
304QgsPoint surfacePoleOfInaccessibility(
const QgsSurface *surface,
double precision,
double &distanceFromBoundary )
306 std::unique_ptr< QgsPolygon > segmentizedPoly;
311 polygon = segmentizedPoly.get();
318 double cellSize = std::min( bounds.
width(), bounds.
height() );
323 double h = cellSize / 2.0;
324 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
331 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
336 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
339 auto bboxCell = std::make_unique<Cell>( bounds.
xMinimum() + bounds.
width() / 2.0, bounds.
yMinimum() + bounds.
height() / 2.0, 0, polygon );
340 if ( bboxCell->d > bestCell->d )
342 bestCell = std::move( bboxCell );
345 while ( !cellQueue.empty() )
348 std::unique_ptr< Cell > cell( cellQueue.top() );
350 Cell *currentCell = cell.get();
353 if ( currentCell->d > bestCell->d )
355 bestCell = std::move( cell );
359 if ( currentCell->max - bestCell->d <= precision )
363 h = currentCell->h / 2.0;
364 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y - h, h, polygon ) );
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 ) );
370 distanceFromBoundary = bestCell->d;
372 return QgsPoint( bestCell->x, bestCell->y );
380 if ( distanceFromBoundary )
381 *distanceFromBoundary = std::numeric_limits<double>::max();
383 if ( !mGeometry || mGeometry->isEmpty() )
386 if ( precision <= 0 )
391 int numGeom = gc->numGeometries();
394 for (
int i = 0; i < numGeom; ++i )
400 double dist = std::numeric_limits<double>::max();
401 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
402 if ( dist > maxDist )
412 if ( distanceFromBoundary )
413 *distanceFromBoundary = maxDist;
422 double dist = std::numeric_limits<double>::max();
423 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
427 if ( distanceFromBoundary )
428 *distanceFromBoundary = dist;
439 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
465 for (
int i = 0; i < numPoints; ++i )
467 if ( !isClosed && i == numPoints - 1 )
469 else if ( !isClosed && i == 0 )
478 a = ring->
pointN( numPoints - 1 );
481 if ( i == numPoints - 1 )
490 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
508 double scale = 2.0 * std::min( p.
length(), q.
length() );
512 double dotProduct = p * q;
521 if ( dotProduct < -M_SQRT1_2 )
530 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
535 double minScore = std::numeric_limits<double>::max();
540 std::unique_ptr< QgsLineString > best( ring->
clone() );
542 QVector< QgsVector > motions;
543 motions.reserve( numPoints );
545 for (
int it = 0; it < iterations; ++it )
553 for (
int i = 0; i < numPoints; ++i )
555 if ( isClosed && i == numPoints - 1 )
556 motions << motions.at( 0 );
557 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
567 a = ring->
pointN( numPoints - 1 );
570 if ( i == numPoints - 1 )
575 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
582 for (
int i = 0; i < numPoints; ++i )
584 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
585 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
588 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
589 if ( newScore < minScore )
591 best.reset( ring->
clone() );
595 if ( minScore < tolerance )
601 return best.release();
607 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
611 geom = segmentizedCopy.get();
642 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
643 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
647 int numGeom = gc->numGeometries();
648 QVector< QgsAbstractGeometry * > geometryList;
649 geometryList.reserve( numGeom );
650 for (
int i = 0; i < numGeom; ++i )
652 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
671 QVector< double > outX;
672 QVector< double > outY;
673 QVector< double > outZ;
674 QVector< double > outM;
675 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
678 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
679 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
680 bool withZ = ring->
is3D();
682 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
685 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
698 int extraNodesThisSegment = extraNodesPerSegment;
699 for (
int i = 0; i < nPoints - 1; ++i )
702 x2 = ring->
xAt( i + 1 );
704 y2 = ring->
yAt( i + 1 );
708 z2 = ring->
zAt( i + 1 );
713 m2 = ring->
mAt( i + 1 );
723 if ( extraNodesPerSegment < 0 )
727 if ( extraNodesThisSegment >= 1 )
728 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
731 for (
int j = 0; j < extraNodesThisSegment; ++j )
733 double delta = multiplier * ( j + 1 );
734 xOut = x1 + delta * ( x2 - x1 );
735 yOut = y1 + delta * ( y2 - y1 );
737 zOut = z1 + delta * ( z2 - z1 );
739 mOut = m1 + delta * ( m2 - m1 );
749 outX << ring->
xAt( nPoints - 1 );
750 outY << ring->
yAt( nPoints - 1 );
752 outZ << ring->
zAt( nPoints - 1 );
754 outM << ring->
mAt( nPoints - 1 );
762 if ( extraNodesPerSegment < 0 &&
qgsDoubleNear( distance, 0 ) )
765 return geom->
clone();
768 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
772 geom = segmentizedCopy.get();
810 int numGeom = gc->numGeometries();
811 QVector< QgsAbstractGeometry * > geometryList;
812 geometryList.reserve( numGeom );
813 for (
int i = 0; i < numGeom; ++i )
815 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
846 int numGeom = gc->numGeometries();
847 QVector< QgsAbstractGeometry * > geometryList;
848 geometryList.reserve( numGeom );
849 for (
int i = 0; i < numGeom; ++i )
875 Q_ASSERT_X( ab.
pointLeftOfLine( mOrigin ) != 0,
"line_segment_dist_comparer",
"AB must not be collinear with the origin." );
876 Q_ASSERT_X( cd.
pointLeftOfLine( mOrigin ) != 0,
"line_segment_dist_comparer",
"CD must not be collinear with the origin." );
893 if ( ab.
end() == cd.
end() || oad != oab )
903 if ( cdb == 0 && cda == 0 )
905 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
907 else if ( cda == cdb || cda == 0 || cdb == 0 )
910 return cdo == cda || cdo == cdb;
926 const bool aIsLeft = a.
x() < mVertex.x();
927 const bool bIsLeft = b.
x() < mVertex.x();
928 if ( aIsLeft != bIsLeft )
933 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
935 return b.
y() < a.
y();
939 return a.
y() < b.
y();
971 const int abo =
segment.pointLeftOfLine( origin );
978 const double distA = ao * direction;
979 const double distB = ( origin -
segment.end() ) * direction;
981 if ( distA > 0 && distB > 0 )
987 if ( ( distA > 0 ) != ( distB > 0 ) )
988 intersectPoint = origin;
989 else if ( distA > distB )
990 intersectPoint =
segment.start();
992 intersectPoint =
segment.end();
1000 if ( u < 0.0 || 1.0 < u )
1007 intersectPoint = origin + direction * t;
1016 if ( radius1 > radius2 )
1023 QVector<QgsPointXY> points;
1026 points << t1 << t2 << t4 << t3;
1042 std::vector< std::unique_ptr<QgsLineString > > temporarySegmentizedLines;
1043 std::vector< const QgsLineString * > linesToProcess;
1048 for (
int i = 0; i < multiCurve->partCount(); ++i )
1058 linesToProcess.emplace_back( lineString );
1062 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( part->
segmentize() ) );
1063 linesToProcess.emplace_back( segmentizedCurve.get() );
1064 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1071 if ( curve->nCoordinates() > 0 )
1075 linesToProcess.emplace_back( lineString );
1079 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( curve->segmentize() ) );
1080 linesToProcess.emplace_back( segmentizedCurve.get() );
1081 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1086 if ( linesToProcess.empty() )
1089 g.mLastError = u
"Input geometry was not a curve type geometry"_s;
1093 QVector<QgsGeometry> bufferedLines;
1094 bufferedLines.reserve( linesToProcess.size() );
1098 QVector<QgsGeometry> parts;
1100 double prevRadius = 0;
1103 std::unique_ptr< double[] > widths = widthFunction( line );
1108 double thisRadius = widths[i] / 2.0;
1109 if ( thisRadius > 0 )
1113 QgsCircle circ( thisPoint, thisRadius );
1115 parts << thisCircle;
1124 if ( prevRadius > 0 || thisRadius > 0 )
1126 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1127 if ( !points.empty() )
1132 int beforeVertex = 0;
1133 int afterVertex = 0;
1135 double sqrDistPrev = 0;
1136 for (
int j = 0; j < points.count(); ++j )
1140 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1143 points.append( points.at( 0 ) );
1145 auto poly = std::make_unique< QgsPolygon >();
1147 if ( poly->area() > 0 )
1152 prevPoint = thisPoint;
1153 prevRadius = thisRadius;
1154 prevCircle = thisCircle;
1169 start = std::fabs( start );
1170 end = std::fabs( end );
1172 auto interpolateWidths = [start, end](
const QgsLineString *line ) -> std::unique_ptr<
double[] > {
1175 std::unique_ptr< double[] > widths(
new double[line->nCoordinates()] );
1177 widths[line->nCoordinates() - 1] = end;
1179 double lineLength = line->length();
1180 double currentLength = 0;
1181 QgsPoint prevPoint = line->pointN( 0 );
1182 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1184 QgsPoint point = line->pointN( i );
1185 double segmentLength = point.
distance( prevPoint );
1186 currentLength += segmentLength;
1187 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1188 double delta = lengthFraction * ( end - start );
1189 widths[i] = start + delta;
1201 auto widthByM = [](
const QgsLineString *line ) -> std::unique_ptr<
double[] > {
1202 std::unique_ptr< double[] > widths(
new double[line->nCoordinates()] );
1203 for (
int i = 0; i < line->nCoordinates(); ++i )
1205 widths[i] = line->mAt( i );
1225 for (
int i = 0; i < ms->numGeometries(); ++i )
1228 return QVector< QgsPointXY >();
1255 return QVector< QgsPointXY >();
1257 if ( !t.
error().isEmpty() )
1260 return QVector< QgsPointXY >();
1264 QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
const QVector<float> triangleData = t.
data();
1266 if ( triangleData.empty() )
1267 return QVector< QgsPointXY >();
1270 std::vector< double > cumulativeAreas;
1272 double totalArea = 0;
1273 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1276 return QVector< QgsPointXY >();
1278 const float aX = *it++;
1279 const float aY = *it++;
1281 const float bX = *it++;
1282 const float bY = *it++;
1284 const float cX = *it++;
1285 const float cY = *it++;
1290 cumulativeAreas.emplace_back( totalArea );
1293 std::random_device rd;
1294 std::mt19937 mt( seed == 0 ? rd() : seed );
1295 std::uniform_real_distribution<> uniformDist( 0, 1 );
1298 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random ) ->
int {
1300 const double target = random * totalArea;
1301 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1306 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1311 QVector<QgsPointXY> result;
1312 result.reserve( count );
1314 for (
int i = 0; i < count; )
1317 return QVector< QgsPointXY >();
1319 const double triangleIndexRnd = uniformDist( mt );
1321 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1324 const double weightB = uniformDist( mt );
1325 const double weightC = uniformDist( mt );
1330 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1331 const double aY = triangleData.at( triangleIndex * 9 + 1 ) + bounds.
yMinimum();
1332 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1333 const double bY = triangleData.at( triangleIndex * 9 + 4 ) + bounds.
yMinimum();
1334 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1335 const double cY = triangleData.at( triangleIndex * 9 + 7 ) + bounds.
yMinimum();
1339 if ( acceptPoint( candidate ) )
1345 else if ( maxTriesPerPoint != 0 )
1349 if ( tries == maxTriesPerPoint )
1365 std::unique_ptr<QgsAbstractGeometry> triangulation =
geos.constrainedDelaunayTriangulation( &error );
1366 if ( !triangulation || triangulation->isEmpty() )
1377 std::vector< double > cumulativeAreas;
1379 double totalArea = 0;
1380 std::vector< double > vertices(
static_cast< std::size_t
>( mp->
numGeometries() ) * 6 );
1381 double *vertexData = vertices.data();
1395 const double aX = exterior->
xAt( 0 );
1396 const double aY = exterior->
yAt( 0 );
1397 const double bX = exterior->
xAt( 1 );
1398 const double bY = exterior->
yAt( 1 );
1399 const double cX = exterior->
xAt( 2 );
1400 const double cY = exterior->
yAt( 2 );
1410 cumulativeAreas.emplace_back( totalArea );
1413 std::random_device rd;
1414 std::mt19937 mt( seed == 0 ? rd() : seed );
1415 std::uniform_real_distribution<> uniformDist( 0, 1 );
1418 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random ) ->
int {
1420 const double target = random * totalArea;
1421 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1426 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1431 QVector<QgsPointXY> result;
1432 result.reserve( count );
1434 vertexData = vertices.data();
1435 for (
int i = 0; i < count; )
1438 return QVector< QgsPointXY >();
1440 const double triangleIndexRnd = uniformDist( mt );
1442 const std::size_t triangleIndex = selectRandomTriangle( triangleIndexRnd );
1445 const double weightB = uniformDist( mt );
1446 const double weightC = uniformDist( mt );
1451 const double aX = vertexData[triangleIndex * 6];
1452 const double aY = vertexData[triangleIndex * 6 + 1];
1453 const double bX = vertexData[triangleIndex * 6 + 2];
1454 const double bY = vertexData[triangleIndex * 6 + 3];
1455 const double cX = vertexData[triangleIndex * 6 + 4];
1456 const double cY = vertexData[triangleIndex * 6 + 5];
1461 if ( acceptPoint( candidate ) )
1467 else if ( maxTriesPerPoint != 0 )
1471 if ( tries == maxTriesPerPoint )
1484 return QVector< QgsPointXY >();
1487#if GEOS_VERSION_NUM >= GEOS_COMPUTE_VERSION( 3, 11, 0 )
1496std::unique_ptr< QgsCurve >
lineToCurve(
const QgsCurve *curve,
double distanceTolerance,
double pointSpacingAngleTolerance )
1502 std::unique_ptr< QgsCircularString > out;
1508 auto out = std::make_unique< QgsCompoundCurve >();
1510 for (
int i = 0; i < in->
nCurves(); i++ )
1512 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1517 for (
int i = 0; i < processedCompoundCurve->nCurves(); ++i )
1519 out->addCurve( processedCompoundCurve->curveAt( i )->clone() );
1524 out->addCurve( processed.release() );
1534 auto out = std::make_unique< QgsCompoundCurve >();
1537 const unsigned int minQuadEdges = 2;
1550 out->addCurve( lineString->
clone() );
1556 QVector< int > edgesInArcs( numEdges + 1, 0 );
1559 double abX = b.x() - a.
x();
1560 double abY = b.y() - a.
y();
1562 double cbX = b.x() -
c.x();
1563 double cbY = b.y() -
c.y();
1565 double dot = ( abX * cbX + abY * cbY );
1566 double cross = ( abX * cbY - abY * cbX );
1568 double alpha = std::atan2( cross, dot );
1583 double centerX = 0.0;
1584 double centerY = 0.0;
1587 while ( i < numEdges - 2 )
1589 unsigned int arcEdges = 0;
1590 double numQuadrants = 0;
1593 bool foundArc =
false;
1595 a1 = lineString->
pointN( i );
1596 a2 = lineString->
pointN( i + 1 );
1597 a3 = lineString->
pointN( i + 2 );
1600 for ( j = i + 3; j < numEdges + 1; j++ )
1602 b = lineString->
pointN( j );
1609 for ( k = j - 1; k > j - 4; k-- )
1610 edgesInArcs[k] = currentArc;
1630 arcEdges = j - 1 - i;
1631 if ( first.
x() == b.x() && first.
y() == b.y() )
1639 angle = arcAngle( first,
QgsPoint( centerX, centerY ), b );
1645 angle = 2 * M_PI + angle;
1646 numQuadrants = ( 4 * angle ) / ( 2 * M_PI );
1649 if ( arcEdges < minQuadEdges * numQuadrants )
1652 for ( k = j - 1; k >= i; k-- )
1669 int edgeType = edgesInArcs[0];
1671 auto addPointsToCurve = [lineString, &out](
int start,
int end,
int type ) {
1675 QVector< QgsPoint > points;
1676 for (
int j = start; j < end + 2; ++j )
1678 points.append( lineString->
pointN( j ) );
1680 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1681 out->addCurve( straightSegment.release() );
1686 QVector< QgsPoint > points;
1687 points.append( lineString->
pointN( start ) );
1688 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1689 points.append( lineString->
pointN( end + 1 ) );
1690 auto curvedSegment = std::make_unique< QgsCircularString >();
1691 curvedSegment->setPoints( points );
1692 out->addCurve( curvedSegment.release() );
1696 for (
int i = 1; i < numEdges; i++ )
1698 if ( edgeType != edgesInArcs[i] )
1701 addPointsToCurve( start, end, edgeType );
1703 edgeType = edgesInArcs[i];
1709 addPointsToCurve( start, end, edgeType );
1714 std::unique_ptr< QgsCircularString > res;
1735 auto result = std::make_unique< QgsCurvePolygon>();
1737 result->setExteriorRing(
lineToCurve( polygon->
exteriorRing(), distanceTolerance, angleTolerance ).release() );
1740 result->addInteriorRing(
lineToCurve( polygon->
interiorRing( i ), distanceTolerance, angleTolerance ).release() );
1762 int numGeom = gc->numGeometries();
1763 QVector< QgsAbstractGeometry * > geometryList;
1764 geometryList.reserve( numGeom );
1765 for (
int i = 0; i < numGeom; ++i )
1788 area = std::numeric_limits<double>::max();
1790 width = std::numeric_limits<double>::max();
1791 height = std::numeric_limits<double>::max();
1793 if ( !mGeometry || mGeometry->nCoordinates() < 2 )
1797 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1806 if ( !hull->nextVertex( vertexId, pt0 ) )
1812 double totalRotation = 0;
1813 while ( hull->nextVertex( vertexId, pt2 ) )
1816 double rotateAngle = 180.0 / M_PI * currentAngle;
1817 totalRotation += rotateAngle;
1819 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1820 t.rotate( rotateAngle );
1821 t.translate( -pt0.
x(), -pt0.
y() );
1823 hull->transform( t );
1826 double currentArea = bounds.
width() * bounds.
height();
1827 if ( currentArea < area )
1831 angle = totalRotation;
1832 width = bounds.
width();
1833 height = bounds.
height();
1836 pt1 = hull->vertexAt( vertexId );
1842 if ( width > height )
1844 width = minRect.
height();
1845 height = minRect.
width();
1846 angle = angle + 90.0;
1850 if ( angle > 180.0 )
1851 angle = std::fmod( angle, 180.0 );
1858 const int totalPoints = line->
numPoints();
1859 if ( totalPoints < 2 )
1862 const double *x = line->
xData();
1863 const double *y = line->
yData();
1865 double prevX = *x++;
1866 double prevY = *y++;
1868 QVector< double > outX;
1869 QVector< double > outY;
1870 const double totalLength = line->
length();
1872 const int maxRepetitions = std::ceil( totalLength / wavelength );
1873 if ( !strictWavelength )
1874 wavelength = totalLength / maxRepetitions;
1876 const int estimatedPoints = maxRepetitions * 2 + 2;
1877 outX.reserve( estimatedPoints );
1878 outY.reserve( estimatedPoints );
1879 outX.append( prevX );
1880 outY.append( prevY );
1882 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1884 for (
int i = 1; i < totalPoints; ++i )
1886 double thisX = *x++;
1887 double thisY = *y++;
1891 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1894 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1899 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1900 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1902 outX.append( outPointX );
1903 outY.append( outPointY );
1905 distanceToNextPointFromStartOfSegment += wavelength / 2;
1911 distanceToNextPointFromStartOfSegment -= segmentLength;
1914 outX.append( prevX );
1915 outY.append( prevY );
1917 return std::make_unique< QgsLineString >( outX, outY );
1922 const double minimumWavelength,
1923 const double maximumWavelength,
1924 const double minimumAmplitude,
1925 const double maximumAmplitude,
1926 std::uniform_real_distribution<> &uniformDist,
1930 const int totalPoints = line->
numPoints();
1931 if ( totalPoints < 2 )
1934 const double *x = line->
xData();
1935 const double *y = line->
yData();
1937 double prevX = *x++;
1938 double prevY = *y++;
1940 QVector< double > outX;
1941 QVector< double > outY;
1942 const double totalLength = line->
length();
1944 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1946 const int estimatedPoints = maxRepetitions * 2 + 2;
1947 outX.reserve( estimatedPoints );
1948 outY.reserve( estimatedPoints );
1949 outX.append( prevX );
1950 outY.append( prevY );
1952 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1953 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1954 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1957 for (
int i = 1; i < totalPoints; ++i )
1959 double thisX = *x++;
1960 double thisY = *y++;
1964 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1967 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1972 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1973 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1974 outX.append( outPointX );
1975 outY.append( outPointY );
1977 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1978 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1980 distanceToNextPointFromStartOfSegment += wavelength / 2;
1986 distanceToNextPointFromStartOfSegment -= segmentLength;
1989 outX.append( prevX );
1990 outY.append( prevY );
1992 return std::make_unique< QgsLineString >( outX, outY );
1997 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2001 geom = segmentizedCopy.get();
2012 auto result = std::make_unique< QgsPolygon >();
2025 const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt
2028 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2032 geom = segmentizedCopy.get();
2043 auto result = std::make_unique< QgsPolygon >();
2045 result->setExteriorRing(
2050 result->addInteriorRing(
2078 int numGeom = gc->numGeometries();
2079 QVector< QgsAbstractGeometry * > geometryList;
2080 geometryList.reserve( numGeom );
2081 for (
int i = 0; i < numGeom; ++i )
2083 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2101 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2110 std::random_device rd;
2111 std::mt19937 mt( seed == 0 ? rd() : seed );
2112 std::uniform_real_distribution<> uniformDist( 0, 1 );
2121 int numGeom = gc->numGeometries();
2122 QVector< QgsAbstractGeometry * > geometryList;
2123 geometryList.reserve( numGeom );
2124 for (
int i = 0; i < numGeom; ++i )
2126 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2144 const int totalPoints = line->
numPoints();
2145 if ( totalPoints < 2 )
2148 const double *x = line->
xData();
2149 const double *y = line->
yData();
2151 double prevX = *x++;
2152 double prevY = *y++;
2154 QVector< double > outX;
2155 QVector< double > outY;
2156 const double totalLength = line->
length();
2158 const int maxRepetitions = std::ceil( totalLength / wavelength );
2159 if ( !strictWavelength )
2160 wavelength = totalLength / maxRepetitions;
2162 const int estimatedPoints = maxRepetitions * 4 + 2;
2163 outX.reserve( estimatedPoints );
2164 outY.reserve( estimatedPoints );
2165 outX.append( prevX );
2166 outY.append( prevY );
2169 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2170 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2172 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2175 for (
int i = 1; i < totalPoints; ++i )
2177 double thisX = *x++;
2178 double thisY = *y++;
2182 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2185 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2190 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2191 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2192 outX.append( pX + side * amplitude * sinAngle );
2193 outY.append( pY + side * amplitude * cosAngle );
2194 outX.append( pX - side * amplitude * sinAngle );
2195 outY.append( pY - side * amplitude * cosAngle );
2197 distanceToNextPointFromStartOfSegment += wavelength / 2;
2203 distanceToNextPointFromStartOfSegment -= segmentLength;
2209 outX.append( prevX );
2210 outY.append( prevY );
2212 return std::make_unique< QgsLineString >( outX, outY );
2217 const double minimumWavelength,
2218 const double maximumWavelength,
2219 const double minimumAmplitude,
2220 const double maximumAmplitude,
2221 std::uniform_real_distribution<> &uniformDist,
2225 const int totalPoints = line->
numPoints();
2226 if ( totalPoints < 2 )
2229 const double *x = line->
xData();
2230 const double *y = line->
yData();
2232 double prevX = *x++;
2233 double prevY = *y++;
2235 QVector< double > outX;
2236 QVector< double > outY;
2237 const double totalLength = line->
length();
2239 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2241 const int estimatedPoints = maxRepetitions * 4 + 2;
2242 outX.reserve( estimatedPoints );
2243 outY.reserve( estimatedPoints );
2244 outX.append( prevX );
2245 outY.append( prevY );
2247 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2250 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2251 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2253 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2254 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2257 for (
int i = 1; i < totalPoints; ++i )
2259 double thisX = *x++;
2260 double thisY = *y++;
2264 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2267 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2272 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2273 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2274 outX.append( pX + side * amplitude * sinAngle );
2275 outY.append( pY + side * amplitude * cosAngle );
2277 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2278 outX.append( pX - side * amplitude * sinAngle );
2279 outY.append( pY - side * amplitude * cosAngle );
2281 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2282 distanceToNextPointFromStartOfSegment += wavelength / 2;
2288 distanceToNextPointFromStartOfSegment -= segmentLength;
2291 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2292 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2293 outX.append( prevX );
2294 outY.append( prevY );
2296 return std::make_unique< QgsLineString >( outX, outY );
2301 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2305 geom = segmentizedCopy.get();
2316 auto result = std::make_unique< QgsPolygon >();
2329 const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt
2332 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2336 geom = segmentizedCopy.get();
2347 auto result = std::make_unique< QgsPolygon >();
2349 result->setExteriorRing(
2354 result->addInteriorRing(
2381 int numGeom = gc->numGeometries();
2382 QVector< QgsAbstractGeometry * > geometryList;
2383 geometryList.reserve( numGeom );
2384 for (
int i = 0; i < numGeom; ++i )
2386 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2404 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2413 std::random_device rd;
2414 std::mt19937 mt( seed == 0 ? rd() : seed );
2415 std::uniform_real_distribution<> uniformDist( 0, 1 );
2424 int numGeom = gc->numGeometries();
2425 QVector< QgsAbstractGeometry * > geometryList;
2426 geometryList.reserve( numGeom );
2427 for (
int i = 0; i < numGeom; ++i )
2429 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2447 const int totalPoints = line->
numPoints();
2448 if ( totalPoints < 2 )
2451 const double *x = line->
xData();
2452 const double *y = line->
yData();
2454 double prevX = *x++;
2455 double prevY = *y++;
2457 const double totalLength = line->
length();
2459 const int maxRepetitions = std::ceil( totalLength / wavelength );
2460 if ( !strictWavelength )
2461 wavelength = totalLength / maxRepetitions;
2463 const int segments = 10;
2467 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2468 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2469 bool isFirstPart =
true;
2471 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2472 int bufferIndex = 1;
2473 auto out = std::make_unique< QgsLineString >();
2475 double segmentAngleRadians = 0;
2476 double remainingDistance = totalLength;
2477 double totalCoveredDistance = 0;
2479 for (
int i = 1; i < totalPoints; ++i )
2481 double thisX = *x++;
2482 double thisY = *y++;
2486 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2489 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2492 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2494 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2495 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2497 if ( bufferIndex == 1 && isFirstPart )
2499 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2500 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2501 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2502 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2504 distanceToNextPointFromStartOfSegment += wavelength / 8;
2506 else if ( bufferIndex == 1 )
2508 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2509 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2510 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2511 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2513 distanceToNextPointFromStartOfSegment += wavelength / 4;
2515 else if ( bufferIndex == 2 )
2517 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2518 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2522 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2523 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2524 isFirstPart =
false;
2528 std::unique_ptr< QgsLineString > bezier(
2530 fromBezierCurve(
QgsPoint( xOutBuffer[0], yOutBuffer[0] ),
QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
QgsPoint( xOutBuffer[3], yOutBuffer[3] ), segments )
2532 out->append( bezier.get() );
2535 xOutBuffer[0] = xOutBuffer[3];
2536 yOutBuffer[0] = yOutBuffer[3];
2539 distanceToNextPointFromStartOfSegment += wavelength / 4;
2542 totalCoveredDistance += segmentLength;
2545 distanceToNextPointFromStartOfSegment -= segmentLength;
2548 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2549 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2550 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2551 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2553 std::unique_ptr< QgsLineString > bezier(
2555 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 )
2557 out->append( bezier.get() );
2564 const double minimumWavelength,
2565 const double maximumWavelength,
2566 const double minimumAmplitude,
2567 const double maximumAmplitude,
2568 std::uniform_real_distribution<> &uniformDist,
2572 const int totalPoints = line->
numPoints();
2573 if ( totalPoints < 2 )
2576 const double *x = line->
xData();
2577 const double *y = line->
yData();
2579 double prevX = *x++;
2580 double prevY = *y++;
2582 const double totalLength = line->
length();
2584 const int segments = 10;
2588 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2589 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2590 bool isFirstPart =
true;
2592 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2593 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2595 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2596 int bufferIndex = 1;
2597 auto out = std::make_unique< QgsLineString >();
2599 double segmentAngleRadians = 0;
2601 double remainingDistance = totalLength;
2602 double totalCoveredDistance = 0;
2604 for (
int i = 1; i < totalPoints; ++i )
2606 double thisX = *x++;
2607 double thisY = *y++;
2611 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2614 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2617 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2619 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2620 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2622 if ( bufferIndex == 1 && isFirstPart )
2624 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2625 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2626 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2627 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2629 distanceToNextPointFromStartOfSegment += wavelength / 8;
2631 else if ( bufferIndex == 1 )
2633 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2634 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2635 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2636 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2638 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2639 distanceToNextPointFromStartOfSegment += wavelength / 4;
2641 else if ( bufferIndex == 2 )
2643 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2644 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2648 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2649 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2650 isFirstPart =
false;
2654 std::unique_ptr< QgsLineString > bezier(
2656 fromBezierCurve(
QgsPoint( xOutBuffer[0], yOutBuffer[0] ),
QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
QgsPoint( xOutBuffer[3], yOutBuffer[3] ), segments )
2658 out->append( bezier.get() );
2661 xOutBuffer[0] = xOutBuffer[3];
2662 yOutBuffer[0] = yOutBuffer[3];
2666 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2668 distanceToNextPointFromStartOfSegment += wavelength / 4;
2671 totalCoveredDistance += segmentLength;
2675 distanceToNextPointFromStartOfSegment -= segmentLength;
2678 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2679 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2680 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2681 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2683 if ( out->isEmpty() )
2685 std::unique_ptr< QgsLineString > bezier(
2689 out->append( bezier.get() );
2693 std::unique_ptr< QgsLineString > bezier(
2695 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 )
2697 out->append( bezier.get() );
2705 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2709 geom = segmentizedCopy.get();
2720 auto result = std::make_unique< QgsPolygon >();
2733 const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt
2736 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2740 geom = segmentizedCopy.get();
2751 auto result = std::make_unique< QgsPolygon >();
2753 result->setExteriorRing(
2758 result->addInteriorRing(
2785 int numGeom = gc->numGeometries();
2786 QVector< QgsAbstractGeometry * > geometryList;
2787 geometryList.reserve( numGeom );
2788 for (
int i = 0; i < numGeom; ++i )
2790 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2808 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2817 std::random_device rd;
2818 std::mt19937 mt( seed == 0 ? rd() : seed );
2819 std::uniform_real_distribution<> uniformDist( 0, 1 );
2828 int numGeom = gc->numGeometries();
2829 QVector< QgsAbstractGeometry * > geometryList;
2830 geometryList.reserve( numGeom );
2831 for (
int i = 0; i < numGeom; ++i )
2833 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2853 const int totalPoints = line->
numPoints();
2854 if ( totalPoints < 2 )
2857 const int patternSize = pattern.size();
2859 const double *x = line->
xData();
2860 const double *y = line->
yData();
2862 double prevX = *x++;
2863 double prevY = *y++;
2865 auto result = std::make_unique< QgsMultiLineString >();
2867 QVector< double > outX;
2868 QVector< double > outY;
2869 const double totalLength = line->
length();
2871 double patternLength = 0;
2872 double patternDashLength = 0;
2873 double patternGapLength = 0;
2874 for (
int i = 0; i < pattern.size(); ++i )
2876 patternLength += pattern.at( i );
2878 patternDashLength += pattern.at( i );
2880 patternGapLength += pattern.at( i );
2883 double firstPatternLength = 0;
2884 double firstPatternDashLength = 0;
2885 double firstPatternGapLength = 0;
2886 switch ( startRule )
2890 firstPatternLength = patternLength;
2891 firstPatternDashLength = patternDashLength;
2892 firstPatternGapLength = patternGapLength;
2895 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2896 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2897 firstPatternGapLength = patternGapLength;
2900 firstPatternLength = pattern.at( patternSize - 1 );
2901 firstPatternDashLength = 0;
2902 firstPatternGapLength = pattern.at( patternSize - 1 );
2905 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2906 firstPatternDashLength = 0;
2907 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2911 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2913 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2914 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2915 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2919 lastPatternLength = 0;
2920 lastPatternDashLength = 0;
2921 lastPatternGapLength = 0;
2924 lastPatternLength -= pattern.at( patternSize - 1 );
2925 lastPatternGapLength -= pattern.at( patternSize - 1 );
2928 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2929 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2930 lastPatternGapLength -= pattern.at( patternSize - 1 );
2933 lastPatternGapLength = patternGapLength;
2936 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2937 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2941 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2942 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2944 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2945 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2946 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2948 double dashLengthScalingFactor = 1;
2949 double gapLengthScalingFactor = 1;
2953 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2955 switch ( adjustment )
2958 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2959 gapLengthScalingFactor = dashLengthScalingFactor;
2962 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2965 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2970 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2971 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2973 const int maxPatterns = middlePatternRepetitions + 2;
2974 result->reserve( maxPatterns );
2976 int patternIndex = 0;
2977 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2979 switch ( startRule )
2985 distanceToNextPointFromStartOfSegment *= 0.5;
2988 patternIndex = patternSize - 1;
2990 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2993 patternIndex = patternSize - 1;
2995 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2999 const double adjustedOffset = fmod( patternOffset, patternLength );
3000 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
3004 double remainingOffset = scaledOffset;
3005 while ( remainingOffset > 0 )
3007 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
3009 distanceToNextPointFromStartOfSegment -= remainingOffset;
3013 remainingOffset -= distanceToNextPointFromStartOfSegment;
3016 if ( patternIndex == patternSize )
3019 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3025 outX.append( prevX );
3026 outY.append( prevY );
3029 for (
int i = 1; i < totalPoints; ++i )
3031 double thisX = *x++;
3032 double thisY = *y++;
3035 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
3038 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
3053 if ( patternIndex >= patternSize )
3056 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3061 outX.append( thisX );
3062 outY.append( thisY );
3067 distanceToNextPointFromStartOfSegment -= segmentLength;
3072 outX.append( prevX );
3073 outY.append( prevY );
3084 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
3088 geom = segmentizedCopy.get();
3099 auto result = std::make_unique< QgsMultiLineString >();
3102 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
3103 result->addGeometry( exteriorParts->geometryN( i )->clone() );
3108 for (
int j = 0; j < ringParts->numGeometries(); ++j )
3109 result->addGeometry( ringParts->geometryN( j )->clone() );
3120 if ( pattern.size() < 2 )
3124 if ( !mGeometry || mGeometry->isEmpty() )
3136 int numGeom = gc->numGeometries();
3137 QVector< QgsAbstractGeometry * > geometryList;
3138 geometryList.reserve( numGeom );
3139 for (
int i = 0; i < numGeom; ++i )
3141 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
3149 for (
int j = 0; j < collection->numGeometries(); ++j )
3151 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 ...
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries, const QgsGeometryParameters ¶meters=QgsGeometryParameters(), QgsFeedback *feedback=nullptr)
Compute the unary union on a list of geometries.
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...
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.
double length() const override
Returns the planar, 2-dimensional length of the geometry.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
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.
double mAt(int index) const override
Returns the m value of the specified node in the simple curve.
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 simple curve.
int numPoints() const override
Returns the number of points in the curve.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
void setXAt(int index, double x)
Sets the x-coordinate of the specified node in the simple curve.
const double * yData() const
Returns a const pointer to the y vertex data.
double zAt(int index) const override
Returns the z-coordinate of the specified node in the simple curve.
QgsPoint startPoint() const override
Returns the starting point of the curve.
QgsPoint pointN(int i) const
Returns the specified point from inside the simple curve.
const double * xData() const
Returns a const pointer to the x vertex data.
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.