39 : mGeometry( geometry.constGet() )
66 double dx = p2.
x() - p1.
x();
67 double dy = p2.
y() - p1.
y();
68 if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
70 if ( fabs( dx ) >= fabs( dy ) )
72 double dev = fabs( dy ) / fabs( dx );
79 double dev = fabs( dx ) / fabs( dy );
97 std::array<Direction, 5> dirs;
104 while ( current != end )
114 else if ( dir != dirs[idx - 1] )
124 ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
125 std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
131 int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
132 for (
int i = 1; i < 4; ++i )
134 if ( dirs[i] != oriented[( idx + i ) % 4] )
165 const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( mGeometry );
170 if ( vertexCount < 4 )
172 else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
176 std::array<Direction, 4> dirs;
177 std::tie( found4Dirs, dirs ) =
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
191 QVector<QgsLineString *> linesToProcess;
193 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
196 linesToProcess.reserve( multiCurve->
partCount() );
197 for (
int i = 0; i < multiCurve->
partCount(); ++i )
199 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
203 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
206 linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
209 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() : nullptr );
212 if ( !linesToProcess.empty() )
214 std::unique_ptr< QgsLineString > secondline;
215 for (
QgsLineString *line : std::as_const( linesToProcess ) )
217 QTransform transform = QTransform::fromTranslate( x, y );
219 secondline.reset( line->reversed() );
220 secondline->transform( transform );
222 line->append( secondline.get() );
223 line->addVertex( line->pointN( 0 ) );
226 polygon->setExteriorRing( line );
229 multipolygon->addGeometry( polygon );
251 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
255 , d( polygon->pointDistanceToBoundary( x, y ) )
256 , max( d + h * M_SQRT2 )
271struct GreaterThanByMax
273 bool operator()(
const Cell *lhs,
const Cell *rhs )
const
275 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 );
306 std::unique_ptr< QgsPolygon > segmentizedPoly;
307 const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( surface );
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 std::unique_ptr< Cell > bboxCell(
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
342 if ( bboxCell->d > bestCell->d )
344 bestCell = std::move( bboxCell );
347 while ( !cellQueue.empty() )
350 std::unique_ptr< Cell > cell( cellQueue.top() );
352 Cell *currentCell = cell.get();
355 if ( currentCell->d > bestCell->d )
357 bestCell = std::move( cell );
361 if ( currentCell->max - bestCell->d <=
precision )
365 h = currentCell->h / 2.0;
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 ) );
369 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
372 distanceFromBoundary = bestCell->d;
374 return QgsPoint( bestCell->x, bestCell->y );
382 if ( distanceFromBoundary )
383 *distanceFromBoundary = std::numeric_limits<double>::max();
385 if ( !mGeometry || mGeometry->
isEmpty() )
391 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
393 int numGeom = gc->numGeometries();
396 for (
int i = 0; i < numGeom; ++i )
398 const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( gc->geometryN( i ) );
402 double dist = std::numeric_limits<double>::max();
404 if ( dist > maxDist )
414 if ( distanceFromBoundary )
415 *distanceFromBoundary = maxDist;
420 const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( mGeometry );
424 double dist = std::numeric_limits<double>::max();
429 if ( distanceFromBoundary )
430 *distanceFromBoundary = dist;
441 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
467 for (
int i = 0; i < numPoints; ++i )
469 if ( !isClosed && i == numPoints - 1 )
471 else if ( !isClosed && i == 0 )
480 a = ring->
pointN( numPoints - 1 );
483 if ( i == numPoints - 1 )
492 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
502 double lowerThreshold,
double upperThreshold )
511 double scale = 2.0 * std::min( p.
length(), q.
length() );
515 double dotProduct = p * q;
524 if ( dotProduct < -M_SQRT1_2 )
533 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
538 double minScore = std::numeric_limits<double>::max();
543 std::unique_ptr< QgsLineString > best( ring->
clone() );
545 QVector< QgsVector > motions;
546 motions.reserve( numPoints );
548 for (
int it = 0; it < iterations; ++it )
556 for (
int i = 0; i < numPoints; ++i )
558 if ( isClosed && i == numPoints - 1 )
559 motions << motions.at( 0 );
560 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
570 a = ring->
pointN( numPoints - 1 );
573 if ( i == numPoints - 1 )
578 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
585 for (
int i = 0; i < numPoints; ++i )
587 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
588 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
591 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
592 if ( newScore < minScore )
594 best.reset( ring->
clone() );
598 if ( minScore < tolerance )
604 return best.release();
610 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
614 geom = segmentizedCopy.get();
620 maxIterations, tolerance, lowerThreshold, upperThreshold );
629 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
633 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
649 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
650 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
652 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
654 int numGeom = gc->numGeometries();
655 QVector< QgsAbstractGeometry * > geometryList;
656 geometryList.reserve( numGeom );
657 for (
int i = 0; i < numGeom; ++i )
659 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
678 QVector< double > outX;
679 QVector< double > outY;
680 QVector< double > outZ;
681 QVector< double > outM;
682 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
685 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
686 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
687 bool withZ = ring->
is3D();
689 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
692 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
705 int extraNodesThisSegment = extraNodesPerSegment;
706 for (
int i = 0; i < nPoints - 1; ++i )
709 x2 = ring->
xAt( i + 1 );
711 y2 = ring->
yAt( i + 1 );
715 z2 = ring->
zAt( i + 1 );
720 m2 = ring->
mAt( i + 1 );
730 if ( extraNodesPerSegment < 0 )
733 extraNodesThisSegment = std::floor( std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) / distance );
734 if ( extraNodesThisSegment >= 1 )
735 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
738 for (
int j = 0; j < extraNodesThisSegment; ++j )
740 double delta = multiplier * ( j + 1 );
741 xOut = x1 + delta * ( x2 - x1 );
742 yOut = y1 + delta * ( y2 - y1 );
744 zOut = z1 + delta * ( z2 - z1 );
746 mOut = m1 + delta * ( m2 - m1 );
756 outX << ring->
xAt( nPoints - 1 );
757 outY << ring->
yAt( nPoints - 1 );
759 outZ << ring->
zAt( nPoints - 1 );
761 outM << ring->
mAt( nPoints - 1 );
769 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
773 geom = segmentizedCopy.get();
787 extraNodesPerSegment, distance ) );
791 extraNodesPerSegment, distance ) );
811 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
813 int numGeom = gc->numGeometries();
814 QVector< QgsAbstractGeometry * > geometryList;
815 geometryList.reserve( numGeom );
816 for (
int i = 0; i < numGeom; ++i )
818 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
847 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
849 int numGeom = gc->numGeometries();
850 QVector< QgsAbstractGeometry * > geometryList;
851 geometryList.reserve( numGeom );
852 for (
int i = 0; i < numGeom; ++i )
879 "line_segment_dist_comparer",
880 "AB must not be collinear with the origin." );
882 "line_segment_dist_comparer",
883 "CD must not be collinear with the origin." );
900 if ( ab.
end() == cd.
end() || oad != oab )
910 if ( cdb == 0 && cda == 0 )
912 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
914 else if ( cda == cdb || cda == 0 || cdb == 0 )
917 return cdo == cda || cdo == cdb;
933 const bool aIsLeft = a.
x() < mVertex.x();
934 const bool bIsLeft = b.
x() < mVertex.x();
935 if ( aIsLeft != bIsLeft )
940 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
942 return b.
y() < a.
y();
946 return a.
y() < b.
y();
978 const int abo =
segment.pointLeftOfLine( origin );
985 const double distA = ao * direction;
986 const double distB = ( origin -
segment.end() ) * direction;
988 if ( distA > 0 && distB > 0 )
994 if ( ( distA > 0 ) != ( distB > 0 ) )
995 intersectPoint = origin;
996 else if ( distA > distB )
997 intersectPoint =
segment.start();
999 intersectPoint =
segment.end();
1007 if ( u < 0.0 || 1.0 < u )
1014 intersectPoint = origin + direction * t;
1023 if ( radius1 > radius2 )
1030 QVector<QgsPointXY> points;
1052 std::vector< std::unique_ptr<QgsLineString > > linesToProcess;
1054 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
1057 for (
int i = 0; i < multiCurve->
partCount(); ++i )
1066 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
1073 if ( linesToProcess.empty() )
1076 g.mLastError = QStringLiteral(
"Input geometry was not a curve type geometry" );
1080 QVector<QgsGeometry> bufferedLines;
1081 bufferedLines.reserve( linesToProcess.size() );
1083 for ( std::unique_ptr< QgsLineString > &line : linesToProcess )
1085 QVector<QgsGeometry> parts;
1087 double prevRadius = 0;
1090 std::unique_ptr< double[] > widths = widthFunction( line.get() ) ;
1095 double thisRadius = widths[ i ] / 2.0;
1096 if ( thisRadius > 0 )
1100 QgsCircle circ( thisPoint, thisRadius );
1102 parts << thisCircle;
1111 if ( prevRadius > 0 || thisRadius > 0 )
1113 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1114 if ( !points.empty() )
1119 int beforeVertex = 0;
1120 int afterVertex = 0;
1122 double sqrDistPrev = 0;
1123 for (
int j = 0; j < points.count(); ++j )
1127 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1130 points.append( points.at( 0 ) );
1132 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
1134 if ( poly->area() > 0 )
1139 prevPoint = thisPoint;
1140 prevRadius = thisRadius;
1141 prevCircle = thisCircle;
1156 start = std::fabs( start );
1157 end = std::fabs( end );
1159 auto interpolateWidths = [ start, end ](
const QgsLineString * line )->std::unique_ptr<
double [] >
1163 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1165 widths[line->nCoordinates() - 1] = end;
1167 double lineLength = line->length();
1168 double currentLength = 0;
1169 QgsPoint prevPoint = line->pointN( 0 );
1170 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1172 QgsPoint point = line->pointN( i );
1173 double segmentLength = point.
distance( prevPoint );
1174 currentLength += segmentLength;
1175 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1176 double delta = lengthFraction * ( end - start );
1177 widths[i] = start + delta;
1189 auto widthByM = [](
const QgsLineString * line )->std::unique_ptr<
double [] >
1191 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1192 for (
int i = 0; i < line->nCoordinates(); ++i )
1194 widths[ i ] = line->mAt( i );
1203 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1206 return QVector< QgsPointXY >();
1218 return QVector< QgsPointXY >();
1226 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->
geometryN( i )->
segmentize() ) );
1233 if (
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( polygon.
constGet() ) )
1239 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( polygon.
constGet()->
segmentize() ) );
1245 return QVector< QgsPointXY >();
1247 const QVector<float> triangleData = t.
data();
1248 if ( triangleData.empty() )
1249 return QVector< QgsPointXY >();
1252 std::vector< double > cumulativeAreas;
1254 double totalArea = 0;
1255 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1258 return QVector< QgsPointXY >();
1260 const float aX = *it++;
1262 const float aY = -( *it++ );
1263 const float bX = *it++;
1265 const float bY = -( *it++ );
1266 const float cX = *it++;
1268 const float cY = -( *it++ );
1272 cumulativeAreas.emplace_back( totalArea );
1275 std::random_device rd;
1276 std::mt19937 mt( seed == 0 ? rd() : seed );
1277 std::uniform_real_distribution<> uniformDist( 0, 1 );
1280 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1283 const double target = random * totalArea;
1284 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1289 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1294 QVector<QgsPointXY> result;
1295 result.reserve( count );
1297 for (
int i = 0; i < count; )
1300 return QVector< QgsPointXY >();
1302 const double triangleIndexRnd = uniformDist( mt );
1304 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1307 const double weightB = uniformDist( mt );
1308 const double weightC = uniformDist( mt );
1313 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1314 const double aY = -triangleData.at( triangleIndex * 9 + 2 ) + bounds.
yMinimum();
1315 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1316 const double bY = -triangleData.at( triangleIndex * 9 + 5 ) + bounds.
yMinimum();
1317 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1318 const double cY = -triangleData.at( triangleIndex * 9 + 8 ) + bounds.
yMinimum();
1322 if ( acceptPoint( candidate ) )
1328 else if ( maxTriesPerPoint != 0 )
1332 if ( tries == maxTriesPerPoint )
1345 double pointSpacingAngleTolerance )
1351 std::unique_ptr< QgsCircularString > out;
1352 out.reset( qgsgeometry_cast< QgsCircularString * >( curve )->clone() );
1357 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1358 const QgsCompoundCurve *in = qgsgeometry_cast< const QgsCompoundCurve * >( curve );
1359 for (
int i = 0; i < in->
nCurves(); i ++ )
1361 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1364 if (
const QgsCompoundCurve *processedCompoundCurve = qgsgeometry_cast< const QgsCompoundCurve *>( processed.get() ) )
1366 for (
int i = 0; i < processedCompoundCurve->nCurves(); ++i )
1368 out->addCurve( processedCompoundCurve->curveAt( i )->clone() );
1373 out->addCurve( processed.release() );
1381 const QgsLineString *lineString = qgsgeometry_cast< QgsLineString * >( curve );
1383 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1386 const unsigned int minQuadEdges = 2;
1399 out->addCurve( lineString->
clone() );
1405 QVector< int > edgesInArcs( numEdges + 1, 0 );
1409 double abX = b.x() - a.
x();
1410 double abY = b.y() - a.
y();
1412 double cbX = b.x() -
c.x();
1413 double cbY = b.y() -
c.y();
1415 double dot = ( abX * cbX + abY * cbY );
1416 double cross = ( abX * cbY - abY * cbX );
1418 double alpha = std::atan2( cross, dot );
1433 double centerX = 0.0;
1434 double centerY = 0.0;
1437 while ( i < numEdges - 2 )
1439 unsigned int arcEdges = 0;
1440 double numQuadrants = 0;
1443 bool foundArc =
false;
1445 a1 = lineString->
pointN( i );
1446 a2 = lineString->
pointN( i + 1 );
1447 a3 = lineString->
pointN( i + 2 );
1450 for ( j = i + 3; j < numEdges + 1; j++ )
1452 b = lineString->
pointN( j );
1459 for ( k = j - 1; k > j - 4; k-- )
1460 edgesInArcs[k] = currentArc;
1480 arcEdges = j - 1 - i;
1481 if ( first.
x() == b.x() && first.
y() == b.y() )
1489 angle = arcAngle( first,
QgsPoint( centerX, centerY ), b );
1495 angle = 2 * M_PI + angle;
1496 numQuadrants = ( 4 * angle ) / ( 2 * M_PI );
1499 if ( arcEdges < minQuadEdges * numQuadrants )
1502 for ( k = j - 1; k >= i; k-- )
1519 int edgeType = edgesInArcs[0];
1521 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1526 QVector< QgsPoint > points;
1527 for (
int j = start; j < end + 2; ++ j )
1529 points.append( lineString->
pointN( j ) );
1531 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1532 out->addCurve( straightSegment.release() );
1537 QVector< QgsPoint > points;
1538 points.append( lineString->
pointN( start ) );
1539 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1540 points.append( lineString->
pointN( end + 1 ) );
1541 std::unique_ptr< QgsCircularString > curvedSegment = std::make_unique< QgsCircularString >();
1542 curvedSegment->setPoints( points );
1543 out->addCurve( curvedSegment.release() );
1547 for (
int i = 1; i < numEdges; i++ )
1549 if ( edgeType != edgesInArcs[i] )
1552 addPointsToCurve( start, end, edgeType );
1554 edgeType = edgesInArcs[i];
1560 addPointsToCurve( start, end, edgeType );
1565 std::unique_ptr< QgsCircularString > res;
1566 res.reset( qgsgeometry_cast< const QgsCircularString * >( out->simplifiedTypeRef() )->clone() );
1580 return lineToCurve( qgsgeometry_cast< const QgsCurve * >( geom ), distanceTolerance, angleTolerance );
1585 const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( geom );
1586 std::unique_ptr< QgsCurvePolygon > result = std::make_unique< QgsCurvePolygon>();
1589 distanceTolerance, angleTolerance ).release() );
1593 distanceTolerance, angleTolerance ).release() );
1613 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1615 int numGeom = gc->numGeometries();
1616 QVector< QgsAbstractGeometry * > geometryList;
1617 geometryList.reserve( numGeom );
1618 for (
int i = 0; i < numGeom; ++i )
1641 area = std::numeric_limits<double>::max();
1643 width = std::numeric_limits<double>::max();
1644 height = std::numeric_limits<double>::max();
1650 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1661 double totalRotation = 0;
1662 while ( hull->nextVertex( vertexId, pt2 ) )
1665 double rotateAngle = 180.0 / M_PI * currentAngle;
1666 totalRotation += rotateAngle;
1668 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1669 t.rotate( rotateAngle );
1670 t.translate( -pt0.
x(), -pt0.
y() );
1672 hull->transform( t );
1675 double currentArea = bounds.
width() * bounds.
height();
1676 if ( currentArea < area )
1680 angle = totalRotation;
1681 width = bounds.
width();
1682 height = bounds.
height();
1691 if ( width > height )
1693 width = minRect.
height();
1694 height = minRect.
width();
1695 angle = angle + 90.0;
1699 if ( angle > 180.0 )
1700 angle = std::fmod( angle, 180.0 );
1707 const int totalPoints = line->
numPoints();
1708 if ( totalPoints < 2 )
1711 const double *x = line->
xData();
1712 const double *y = line->
yData();
1714 double prevX = *x++;
1715 double prevY = *y++;
1717 QVector< double > outX;
1718 QVector< double > outY;
1719 const double totalLength = line->
length();
1721 const int maxRepetitions = std::ceil( totalLength / wavelength );
1722 if ( !strictWavelength )
1723 wavelength = totalLength / maxRepetitions;
1725 const int estimatedPoints = maxRepetitions * 2 + 2;
1726 outX.reserve( estimatedPoints );
1727 outY.reserve( estimatedPoints );
1728 outX.append( prevX );
1729 outY.append( prevY );
1731 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1733 for (
int i = 1; i < totalPoints; ++i )
1735 double thisX = *x++;
1736 double thisY = *y++;
1739 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1740 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1743 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1748 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1749 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1751 outX.append( outPointX );
1752 outY.append( outPointY );
1754 distanceToNextPointFromStartOfSegment += wavelength / 2;
1760 distanceToNextPointFromStartOfSegment -= segmentLength;
1763 outX.append( prevX );
1764 outY.append( prevY );
1766 return std::make_unique< QgsLineString >( outX, outY );
1770 const double minimumWavelength,
const double maximumWavelength,
1771 const double minimumAmplitude,
const double maximumAmplitude,
1772 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1774 const int totalPoints = line->
numPoints();
1775 if ( totalPoints < 2 )
1778 const double *x = line->
xData();
1779 const double *y = line->
yData();
1781 double prevX = *x++;
1782 double prevY = *y++;
1784 QVector< double > outX;
1785 QVector< double > outY;
1786 const double totalLength = line->
length();
1788 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1790 const int estimatedPoints = maxRepetitions * 2 + 2;
1791 outX.reserve( estimatedPoints );
1792 outY.reserve( estimatedPoints );
1793 outX.append( prevX );
1794 outY.append( prevY );
1796 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1797 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1798 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1801 for (
int i = 1; i < totalPoints; ++i )
1803 double thisX = *x++;
1804 double thisY = *y++;
1807 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1808 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1811 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1816 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1817 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1818 outX.append( outPointX );
1819 outY.append( outPointY );
1821 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1822 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1824 distanceToNextPointFromStartOfSegment += wavelength / 2;
1830 distanceToNextPointFromStartOfSegment -= segmentLength;
1833 outX.append( prevX );
1834 outY.append( prevY );
1836 return std::make_unique< QgsLineString >( outX, outY );
1841 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1845 geom = segmentizedCopy.get();
1856 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1859 wavelength, amplitude, strictWavelength ).release() );
1863 wavelength, amplitude, strictWavelength ).release() );
1870std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1872 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1876 geom = segmentizedCopy.get();
1887 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1890 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
1894 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
1917 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1919 int numGeom = gc->numGeometries();
1920 QVector< QgsAbstractGeometry * > geometryList;
1921 geometryList.reserve( numGeom );
1922 for (
int i = 0; i < numGeom; ++i )
1924 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
1942 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
1951 std::random_device rd;
1952 std::mt19937 mt( seed == 0 ? rd() : seed );
1953 std::uniform_real_distribution<> uniformDist( 0, 1 );
1960 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1962 int numGeom = gc->numGeometries();
1963 QVector< QgsAbstractGeometry * > geometryList;
1964 geometryList.reserve( numGeom );
1965 for (
int i = 0; i < numGeom; ++i )
1967 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
1985 const int totalPoints = line->
numPoints();
1986 if ( totalPoints < 2 )
1989 const double *x = line->
xData();
1990 const double *y = line->
yData();
1992 double prevX = *x++;
1993 double prevY = *y++;
1995 QVector< double > outX;
1996 QVector< double > outY;
1997 const double totalLength = line->
length();
1999 const int maxRepetitions = std::ceil( totalLength / wavelength );
2000 if ( !strictWavelength )
2001 wavelength = totalLength / maxRepetitions;
2003 const int estimatedPoints = maxRepetitions * 4 + 2;
2004 outX.reserve( estimatedPoints );
2005 outY.reserve( estimatedPoints );
2006 outX.append( prevX );
2007 outY.append( prevY );
2010 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2011 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2013 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2016 for (
int i = 1; i < totalPoints; ++i )
2018 double thisX = *x++;
2019 double thisY = *y++;
2022 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2023 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2026 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2031 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2032 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2033 outX.append( pX + side * amplitude * sinAngle );
2034 outY.append( pY + side * amplitude * cosAngle );
2035 outX.append( pX - side * amplitude * sinAngle );
2036 outY.append( pY - side * amplitude * cosAngle );
2038 distanceToNextPointFromStartOfSegment += wavelength / 2;
2044 distanceToNextPointFromStartOfSegment -= segmentLength;
2050 outX.append( prevX );
2051 outY.append( prevY );
2053 return std::make_unique< QgsLineString >( outX, outY );
2057 const double minimumWavelength,
const double maximumWavelength,
2058 const double minimumAmplitude,
const double maximumAmplitude,
2059 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2061 const int totalPoints = line->
numPoints();
2062 if ( totalPoints < 2 )
2065 const double *x = line->
xData();
2066 const double *y = line->
yData();
2068 double prevX = *x++;
2069 double prevY = *y++;
2071 QVector< double > outX;
2072 QVector< double > outY;
2073 const double totalLength = line->
length();
2075 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2077 const int estimatedPoints = maxRepetitions * 4 + 2;
2078 outX.reserve( estimatedPoints );
2079 outY.reserve( estimatedPoints );
2080 outX.append( prevX );
2081 outY.append( prevY );
2083 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2086 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2087 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2089 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2090 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2093 for (
int i = 1; i < totalPoints; ++i )
2095 double thisX = *x++;
2096 double thisY = *y++;
2099 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2100 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2103 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2108 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2109 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2110 outX.append( pX + side * amplitude * sinAngle );
2111 outY.append( pY + side * amplitude * cosAngle );
2113 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2114 outX.append( pX - side * amplitude * sinAngle );
2115 outY.append( pY - side * amplitude * cosAngle );
2117 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2118 distanceToNextPointFromStartOfSegment += wavelength / 2;
2124 distanceToNextPointFromStartOfSegment -= segmentLength;
2127 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2128 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2129 outX.append( prevX );
2130 outY.append( prevY );
2132 return std::make_unique< QgsLineString >( outX, outY );
2137 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2141 geom = segmentizedCopy.get();
2152 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2155 wavelength, amplitude, strictWavelength ).release() );
2159 wavelength, amplitude, strictWavelength ).release() );
2166std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2168 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2172 geom = segmentizedCopy.get();
2183 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2186 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2190 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2213 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2215 int numGeom = gc->numGeometries();
2216 QVector< QgsAbstractGeometry * > geometryList;
2217 geometryList.reserve( numGeom );
2218 for (
int i = 0; i < numGeom; ++i )
2220 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2238 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2247 std::random_device rd;
2248 std::mt19937 mt( seed == 0 ? rd() : seed );
2249 std::uniform_real_distribution<> uniformDist( 0, 1 );
2256 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2258 int numGeom = gc->numGeometries();
2259 QVector< QgsAbstractGeometry * > geometryList;
2260 geometryList.reserve( numGeom );
2261 for (
int i = 0; i < numGeom; ++i )
2263 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2281 const int totalPoints = line->
numPoints();
2282 if ( totalPoints < 2 )
2285 const double *x = line->
xData();
2286 const double *y = line->
yData();
2288 double prevX = *x++;
2289 double prevY = *y++;
2291 const double totalLength = line->
length();
2293 const int maxRepetitions = std::ceil( totalLength / wavelength );
2294 if ( !strictWavelength )
2295 wavelength = totalLength / maxRepetitions;
2297 const int segments = 10;
2301 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2302 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2303 bool isFirstPart =
true;
2305 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2306 int bufferIndex = 1;
2307 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2309 double segmentAngleRadians = 0;
2310 double remainingDistance = totalLength;
2311 double totalCoveredDistance = 0;
2313 for (
int i = 1; i < totalPoints; ++i )
2315 double thisX = *x++;
2316 double thisY = *y++;
2319 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2320 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2323 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2326 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2328 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2329 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2331 if ( bufferIndex == 0 )
2333 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2334 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2336 distanceToNextPointFromStartOfSegment += wavelength / 4;
2338 else if ( bufferIndex == 1 && isFirstPart )
2340 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2341 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2342 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2343 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2345 distanceToNextPointFromStartOfSegment += wavelength / 8;
2347 else if ( bufferIndex == 1 )
2349 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2350 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2351 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2352 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2354 distanceToNextPointFromStartOfSegment += wavelength / 4;
2356 else if ( bufferIndex == 2 )
2358 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2359 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2363 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2364 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2365 isFirstPart =
false;
2370 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2371 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2372 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2374 out->append( bezier.get() );
2377 xOutBuffer[0] = xOutBuffer[3];
2378 yOutBuffer[0] = yOutBuffer[3];
2381 distanceToNextPointFromStartOfSegment += wavelength / 4;
2384 totalCoveredDistance += segmentLength;
2387 distanceToNextPointFromStartOfSegment -= segmentLength;
2390 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2391 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2392 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2393 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2396 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2397 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2400 out->append( bezier.get() );
2406 const double minimumWavelength,
const double maximumWavelength,
2407 const double minimumAmplitude,
const double maximumAmplitude,
2408 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2410 const int totalPoints = line->
numPoints();
2411 if ( totalPoints < 2 )
2414 const double *x = line->
xData();
2415 const double *y = line->
yData();
2417 double prevX = *x++;
2418 double prevY = *y++;
2420 const double totalLength = line->
length();
2422 const int segments = 10;
2426 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2427 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2428 bool isFirstPart =
true;
2430 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2431 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2433 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2434 int bufferIndex = 1;
2435 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2437 double segmentAngleRadians = 0;
2439 double remainingDistance = totalLength;
2440 double totalCoveredDistance = 0;
2442 for (
int i = 1; i < totalPoints; ++i )
2444 double thisX = *x++;
2445 double thisY = *y++;
2448 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2449 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2452 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2455 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2457 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2458 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2460 if ( bufferIndex == 0 )
2462 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2463 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2465 distanceToNextPointFromStartOfSegment += wavelength / 4;
2467 else if ( bufferIndex == 1 && isFirstPart )
2469 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2470 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2471 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2472 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2474 distanceToNextPointFromStartOfSegment += wavelength / 8;
2476 else if ( bufferIndex == 1 )
2478 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2479 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2480 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2481 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2483 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2484 distanceToNextPointFromStartOfSegment += wavelength / 4;
2486 else if ( bufferIndex == 2 )
2488 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2489 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2493 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2494 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2495 isFirstPart =
false;
2500 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2501 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2502 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2504 out->append( bezier.get() );
2507 xOutBuffer[0] = xOutBuffer[3];
2508 yOutBuffer[0] = yOutBuffer[3];
2512 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2514 distanceToNextPointFromStartOfSegment += wavelength / 4;
2517 totalCoveredDistance += segmentLength;
2521 distanceToNextPointFromStartOfSegment -= segmentLength;
2524 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2525 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2526 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2527 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2529 if ( out->isEmpty() )
2533 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2536 out->append( bezier.get() );
2541 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2542 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2545 out->append( bezier.get() );
2553 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2557 geom = segmentizedCopy.get();
2568 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2571 wavelength, amplitude, strictWavelength ).release() );
2575 wavelength, amplitude, strictWavelength ).release() );
2582std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2584 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2588 geom = segmentizedCopy.get();
2599 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2602 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2606 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2629 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2631 int numGeom = gc->numGeometries();
2632 QVector< QgsAbstractGeometry * > geometryList;
2633 geometryList.reserve( numGeom );
2634 for (
int i = 0; i < numGeom; ++i )
2636 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2654 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2663 std::random_device rd;
2664 std::mt19937 mt( seed == 0 ? rd() : seed );
2665 std::uniform_real_distribution<> uniformDist( 0, 1 );
2672 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2674 int numGeom = gc->numGeometries();
2675 QVector< QgsAbstractGeometry * > geometryList;
2676 geometryList.reserve( numGeom );
2677 for (
int i = 0; i < numGeom; ++i )
2679 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2696 const QVector< double> &pattern,
2700 double patternOffset )
2702 const int totalPoints = line->
numPoints();
2703 if ( totalPoints < 2 )
2706 const int patternSize = pattern.size();
2708 const double *x = line->
xData();
2709 const double *y = line->
yData();
2711 double prevX = *x++;
2712 double prevY = *y++;
2714 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2716 QVector< double > outX;
2717 QVector< double > outY;
2718 const double totalLength = line->
length();
2720 double patternLength = 0;
2721 double patternDashLength = 0;
2722 double patternGapLength = 0;
2723 for (
int i = 0; i < pattern.size(); ++i )
2725 patternLength += pattern.at( i );
2727 patternDashLength += pattern.at( i );
2729 patternGapLength += pattern.at( i );
2732 double firstPatternLength = 0;
2733 double firstPatternDashLength = 0;
2734 double firstPatternGapLength = 0;
2735 switch ( startRule )
2739 firstPatternLength = patternLength;
2740 firstPatternDashLength = patternDashLength;
2741 firstPatternGapLength = patternGapLength;
2744 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2745 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2746 firstPatternGapLength = patternGapLength;
2749 firstPatternLength = pattern.at( patternSize - 1 );
2750 firstPatternDashLength = 0;
2751 firstPatternGapLength = pattern.at( patternSize - 1 );
2754 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2755 firstPatternDashLength = 0;
2756 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2760 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2762 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2763 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2764 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2768 lastPatternLength = 0;
2769 lastPatternDashLength = 0;
2770 lastPatternGapLength = 0;
2773 lastPatternLength -= pattern.at( patternSize - 1 );
2774 lastPatternGapLength -= pattern.at( patternSize - 1 );
2777 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2778 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2779 lastPatternGapLength -= pattern.at( patternSize - 1 );
2782 lastPatternGapLength = patternGapLength;
2785 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2786 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2790 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2791 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2793 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2794 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2795 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2797 double dashLengthScalingFactor = 1;
2798 double gapLengthScalingFactor = 1;
2802 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2804 switch ( adjustment )
2807 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2808 gapLengthScalingFactor = dashLengthScalingFactor;
2811 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2814 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2819 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2820 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2822 const int maxPatterns = middlePatternRepetitions + 2;
2823 result->reserve( maxPatterns );
2825 int patternIndex = 0;
2826 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2828 switch ( startRule )
2834 distanceToNextPointFromStartOfSegment *= 0.5;
2837 patternIndex = patternSize - 1;
2839 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2842 patternIndex = patternSize - 1;
2844 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2848 const double adjustedOffset = fmod( patternOffset, patternLength );
2849 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
2853 double remainingOffset = scaledOffset;
2854 while ( remainingOffset > 0 )
2856 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
2858 distanceToNextPointFromStartOfSegment -= remainingOffset;
2862 remainingOffset -= distanceToNextPointFromStartOfSegment;
2865 if ( patternIndex == patternSize )
2868 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
2874 outX.append( prevX );
2875 outY.append( prevY );
2878 for (
int i = 1; i < totalPoints; ++i )
2880 double thisX = *x++;
2881 double thisY = *y++;
2883 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2884 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2887 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2902 if ( patternIndex >= patternSize )
2905 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
2910 outX.append( thisX );
2911 outY.append( thisY );
2916 distanceToNextPointFromStartOfSegment -= segmentLength;
2921 outX.append( prevX );
2922 outY.append( prevY );
2930 const QVector<double> &pattern,
2934 double patternOffset )
2936 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2940 geom = segmentizedCopy.get();
2951 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2954 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
2955 result->addGeometry( exteriorParts->geometryN( i )->clone() );
2960 for (
int j = 0; j < ringParts->numGeometries(); ++j )
2961 result->addGeometry( ringParts->geometryN( j )->clone() );
2970 if ( pattern.size() < 2 )
2974 if ( !mGeometry || mGeometry->
isEmpty() )
2984 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2986 int numGeom = gc->numGeometries();
2987 QVector< QgsAbstractGeometry * > geometryList;
2988 geometryList.reserve( numGeom );
2989 for (
int i = 0; i < numGeom; ++i )
2991 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
2999 for (
int j = 0; j < collection->numGeometries(); ++j )
3001 first.
addPart( 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 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 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.
virtual bool isEmpty() const
Returns true if the geometry is empty.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex 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 QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance)
Returns a point a specified distance toward a second point.
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 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 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 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...
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.
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 ...
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
Qgis::GeometryOperationResult addPart(const QVector< QgsPointXY > &points, Qgis::GeometryType geomType=Qgis::GeometryType::Unknown)
Adds a new part to a the geometry.
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.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
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.
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...
static QVector< QgsPointXY > randomPointsInPolygon(const QgsGeometry &polygon, 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 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.
static QgsLineString * fromBezierCurve(const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments=30)
Returns a new linestring created by segmentizing the bezier curve between start and end,...
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.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
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.
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
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 xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
double height() const
Returns the height of the rectangle.
Class that takes care of tessellation of polygons into triangles.
QVector< float > data() const
Returns array of triangle vertex data.
void addPolygon(const QgsPolygon &polygon, float extrusionHeight)
Tessellates a triangle and adds its vertex entries to the output data array.
int dataVerticesCount() const
Returns the number of vertices stored in the output data array.
A class to represent a 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 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.
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)
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)
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.