40 : mGeometry( geometry.constGet() )
67 double dx = p2.
x() - p1.
x();
68 double dy = p2.
y() - p1.
y();
69 if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
71 if ( fabs( dx ) >= fabs( dy ) )
73 double dev = fabs( dy ) / fabs( dx );
80 double dev = fabs( dx ) / fabs( dy );
98 std::array<Direction, 5> dirs;
105 while ( current != end )
115 else if ( dir != dirs[idx - 1] )
125 ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
126 std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
132 int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
133 for (
int i = 1; i < 4; ++i )
135 if ( dirs[i] != oriented[( idx + i ) % 4] )
166 const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( mGeometry );
171 if ( vertexCount < 4 )
173 else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
177 std::array<Direction, 4> dirs;
178 std::tie( found4Dirs, dirs ) =
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
192 QVector<QgsLineString *> linesToProcess;
194 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
197 linesToProcess.reserve( multiCurve->
partCount() );
198 for (
int i = 0; i < multiCurve->
partCount(); ++i )
200 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
204 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
207 linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
210 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() :
nullptr );
213 if ( !linesToProcess.empty() )
215 std::unique_ptr< QgsLineString > secondline;
216 for (
QgsLineString *line : std::as_const( linesToProcess ) )
218 QTransform transform = QTransform::fromTranslate( x, y );
220 secondline.reset( line->reversed() );
221 secondline->transform( transform );
223 line->append( secondline.get() );
224 line->addVertex( line->pointN( 0 ) );
230 multipolygon->addGeometry( polygon );
252 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
256 , d( polygon->pointDistanceToBoundary( x, y ) )
257 , max( d + h * M_SQRT2 )
272struct GreaterThanByMax
274 bool operator()(
const Cell *lhs,
const Cell *rhs )
const
276 return rhs->max > lhs->max;
280Cell *getCentroidCell(
const QgsPolygon *polygon )
288 for (
int i = 0, j = len - 1; i < len; j = i++ )
290 double aX = exterior->
xAt( i );
291 double aY = exterior->
yAt( i );
292 double bX = exterior->
xAt( j );
293 double bY = exterior->
yAt( j );
294 double f = aX * bY - bX * aY;
295 x += ( aX + bX ) * f;
296 y += ( aY + bY ) * f;
300 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
302 return new Cell( x / area, y / area, 0.0, polygon );
307 std::unique_ptr< QgsPolygon > segmentizedPoly;
308 const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( surface );
312 polygon = segmentizedPoly.get();
319 double cellSize = std::min( bounds.
width(), bounds.
height() );
324 double h = cellSize / 2.0;
325 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
332 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
337 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
340 std::unique_ptr< Cell > bboxCell(
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
343 if ( bboxCell->d > bestCell->d )
345 bestCell = std::move( bboxCell );
348 while ( !cellQueue.empty() )
351 std::unique_ptr< Cell > cell( cellQueue.top() );
353 Cell *currentCell = cell.get();
356 if ( currentCell->d > bestCell->d )
358 bestCell = std::move( cell );
362 if ( currentCell->max - bestCell->d <=
precision )
366 h = currentCell->h / 2.0;
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 ) );
370 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
373 distanceFromBoundary = bestCell->d;
375 return QgsPoint( bestCell->x, bestCell->y );
383 if ( distanceFromBoundary )
384 *distanceFromBoundary = std::numeric_limits<double>::max();
386 if ( !mGeometry || mGeometry->
isEmpty() )
392 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
394 int numGeom = gc->numGeometries();
397 for (
int i = 0; i < numGeom; ++i )
399 const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( gc->geometryN( i ) );
403 double dist = std::numeric_limits<double>::max();
405 if ( dist > maxDist )
415 if ( distanceFromBoundary )
416 *distanceFromBoundary = maxDist;
421 const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( mGeometry );
425 double dist = std::numeric_limits<double>::max();
430 if ( distanceFromBoundary )
431 *distanceFromBoundary = dist;
442 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
468 for (
int i = 0; i < numPoints; ++i )
470 if ( !isClosed && i == numPoints - 1 )
472 else if ( !isClosed && i == 0 )
481 a = ring->
pointN( numPoints - 1 );
484 if ( i == numPoints - 1 )
493 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
503 double lowerThreshold,
double upperThreshold )
512 double scale = 2.0 * std::min( p.
length(), q.
length() );
516 double dotProduct = p * q;
525 if ( dotProduct < -M_SQRT1_2 )
534 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
539 double minScore = std::numeric_limits<double>::max();
544 std::unique_ptr< QgsLineString > best( ring->
clone() );
546 QVector< QgsVector > motions;
547 motions.reserve( numPoints );
549 for (
int it = 0; it < iterations; ++it )
557 for (
int i = 0; i < numPoints; ++i )
559 if ( isClosed && i == numPoints - 1 )
560 motions << motions.at( 0 );
561 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
571 a = ring->
pointN( numPoints - 1 );
574 if ( i == numPoints - 1 )
579 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
586 for (
int i = 0; i < numPoints; ++i )
588 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
589 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
592 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
593 if ( newScore < minScore )
595 best.reset( ring->
clone() );
599 if ( minScore < tolerance )
605 return best.release();
611 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
615 geom = segmentizedCopy.get();
621 maxIterations, tolerance, lowerThreshold, upperThreshold );
630 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
634 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
650 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
651 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
653 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
655 int numGeom = gc->numGeometries();
656 QVector< QgsAbstractGeometry * > geometryList;
657 geometryList.reserve( numGeom );
658 for (
int i = 0; i < numGeom; ++i )
660 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
679 QVector< double > outX;
680 QVector< double > outY;
681 QVector< double > outZ;
682 QVector< double > outM;
683 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
686 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
687 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
688 bool withZ = ring->
is3D();
690 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
693 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
706 int extraNodesThisSegment = extraNodesPerSegment;
707 for (
int i = 0; i < nPoints - 1; ++i )
710 x2 = ring->
xAt( i + 1 );
712 y2 = ring->
yAt( i + 1 );
716 z2 = ring->
zAt( i + 1 );
721 m2 = ring->
mAt( i + 1 );
731 if ( extraNodesPerSegment < 0 )
734 extraNodesThisSegment = std::floor( std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) / distance );
735 if ( extraNodesThisSegment >= 1 )
736 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
739 for (
int j = 0; j < extraNodesThisSegment; ++j )
741 double delta = multiplier * ( j + 1 );
742 xOut = x1 + delta * ( x2 - x1 );
743 yOut = y1 + delta * ( y2 - y1 );
745 zOut = z1 + delta * ( z2 - z1 );
747 mOut = m1 + delta * ( m2 - m1 );
757 outX << ring->
xAt( nPoints - 1 );
758 outY << ring->
yAt( nPoints - 1 );
760 outZ << ring->
zAt( nPoints - 1 );
762 outM << ring->
mAt( nPoints - 1 );
770 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
774 geom = segmentizedCopy.get();
788 extraNodesPerSegment, distance ) );
792 extraNodesPerSegment, distance ) );
812 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
814 int numGeom = gc->numGeometries();
815 QVector< QgsAbstractGeometry * > geometryList;
816 geometryList.reserve( numGeom );
817 for (
int i = 0; i < numGeom; ++i )
819 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
848 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
850 int numGeom = gc->numGeometries();
851 QVector< QgsAbstractGeometry * > geometryList;
852 geometryList.reserve( numGeom );
853 for (
int i = 0; i < numGeom; ++i )
880 "line_segment_dist_comparer",
881 "AB must not be collinear with the origin." );
883 "line_segment_dist_comparer",
884 "CD must not be collinear with the origin." );
898 if ( ab.
end() == cd.
end() || oad != oab )
908 if ( cdb == 0 && cda == 0 )
910 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
912 else if ( cda == cdb || cda == 0 || cdb == 0 )
915 return cdo == cda || cdo == cdb;
931 const bool aIsLeft = a.
x() < mVertex.x();
932 const bool bIsLeft = b.
x() < mVertex.x();
933 if ( aIsLeft != bIsLeft )
938 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
940 return b.
y() < a.
y();
944 return a.
y() < b.
y();
976 const int abo =
segment.pointLeftOfLine( origin );
983 const double distA = ao * direction;
984 const double distB = ( origin -
segment.end() ) * direction;
986 if ( distA > 0 && distB > 0 )
992 if ( ( distA > 0 ) != ( distB > 0 ) )
993 intersectPoint = origin;
994 else if ( distA > distB )
995 intersectPoint =
segment.start();
997 intersectPoint =
segment.end();
1005 if ( u < 0.0 || 1.0 < u )
1012 intersectPoint = origin + direction * t;
1021 if ( radius1 > radius2 )
1028 QVector<QgsPointXY> points;
1050 std::vector< std::unique_ptr<QgsLineString > > linesToProcess;
1052 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
1055 for (
int i = 0; i < multiCurve->
partCount(); ++i )
1064 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
1071 if ( linesToProcess.empty() )
1074 g.mLastError = QStringLiteral(
"Input geometry was not a curve type geometry" );
1078 QVector<QgsGeometry> bufferedLines;
1079 bufferedLines.reserve( linesToProcess.size() );
1081 for ( std::unique_ptr< QgsLineString > &line : linesToProcess )
1083 QVector<QgsGeometry> parts;
1085 double prevRadius = 0;
1088 std::unique_ptr< double[] > widths = widthFunction( line.get() ) ;
1093 double thisRadius = widths[ i ] / 2.0;
1094 if ( thisRadius > 0 )
1098 QgsCircle circ( thisPoint, thisRadius );
1100 parts << thisCircle;
1109 if ( prevRadius > 0 || thisRadius > 0 )
1111 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1112 if ( !points.empty() )
1117 int beforeVertex = 0;
1118 int afterVertex = 0;
1120 double sqrDistPrev = 0;
1121 for (
int j = 0; j < points.count(); ++j )
1125 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1128 points.append( points.at( 0 ) );
1130 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
1132 if ( poly->area() > 0 )
1137 prevPoint = thisPoint;
1138 prevRadius = thisRadius;
1139 prevCircle = thisCircle;
1154 start = std::fabs( start );
1155 end = std::fabs( end );
1161 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1163 widths[line->nCoordinates() - 1] = end;
1165 double lineLength = line->length();
1166 double currentLength = 0;
1167 QgsPoint prevPoint = line->pointN( 0 );
1168 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1170 QgsPoint point = line->pointN( i );
1171 double segmentLength = point.
distance( prevPoint );
1172 currentLength += segmentLength;
1173 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1174 double delta = lengthFraction * ( end - start );
1175 widths[i] = start + delta;
1189 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1190 for (
int i = 0; i < line->nCoordinates(); ++i )
1192 widths[ i ] = line->mAt( i );
1201 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1204 return QVector< QgsPointXY >();
1216 return QVector< QgsPointXY >();
1224 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->
geometryN( i )->
segmentize() ) );
1231 if (
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( polygon.
constGet() ) )
1237 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( polygon.
constGet()->
segmentize() ) );
1243 return QVector< QgsPointXY >();
1245 const QVector<float> triangleData = t.
data();
1246 if ( triangleData.empty() )
1247 return QVector< QgsPointXY >();
1250 std::vector< double > cumulativeAreas;
1252 double totalArea = 0;
1253 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1256 return QVector< QgsPointXY >();
1258 const float aX = *it++;
1260 const float aY = -( *it++ );
1261 const float bX = *it++;
1263 const float bY = -( *it++ );
1264 const float cX = *it++;
1266 const float cY = -( *it++ );
1270 cumulativeAreas.emplace_back( totalArea );
1273 std::random_device rd;
1274 std::mt19937 mt( seed == 0 ? rd() : seed );
1275 std::uniform_real_distribution<> uniformDist( 0, 1 );
1278 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1281 const double target = random * totalArea;
1282 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1287 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1292 QVector<QgsPointXY> result;
1293 result.reserve( count );
1295 for (
int i = 0; i < count; )
1298 return QVector< QgsPointXY >();
1300 const double triangleIndexRnd = uniformDist( mt );
1302 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1305 const double weightB = uniformDist( mt );
1306 const double weightC = uniformDist( mt );
1311 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1312 const double aY = -triangleData.at( triangleIndex * 9 + 2 ) + bounds.
yMinimum();
1313 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1314 const double bY = -triangleData.at( triangleIndex * 9 + 5 ) + bounds.
yMinimum();
1315 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1316 const double cY = -triangleData.at( triangleIndex * 9 + 8 ) + bounds.
yMinimum();
1320 if ( acceptPoint( candidate ) )
1326 else if ( maxTriesPerPoint != 0 )
1330 if ( tries == maxTriesPerPoint )
1343 double pointSpacingAngleTolerance )
1349 std::unique_ptr< QgsCircularString > out;
1350 out.reset( qgsgeometry_cast< QgsCircularString * >( curve )->clone() );
1355 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1356 const QgsCompoundCurve *in = qgsgeometry_cast< const QgsCompoundCurve * >( curve );
1357 for (
int i = 0; i < in->
nCurves(); i ++ )
1359 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1367 out->addCurve( qgsgeometry_cast< const QgsLineString * >( processed->simplifiedTypeRef() )->clone() );
1371 out->addCurve( processed.release() );
1379 const QgsLineString *lineString = qgsgeometry_cast< QgsLineString * >( curve );
1381 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1384 const unsigned int minQuadEdges = 2;
1397 out->addCurve( lineString->
clone() );
1403 QVector< int > edgesInArcs( numEdges + 1, 0 );
1407 double abX = b.x() - a.
x();
1408 double abY = b.y() - a.
y();
1410 double cbX = b.x() -
c.x();
1411 double cbY = b.y() -
c.y();
1413 double dot = ( abX * cbX + abY * cbY );
1414 double cross = ( abX * cbY - abY * cbX );
1416 double alpha = std::atan2( cross, dot );
1431 double centerX = 0.0;
1432 double centerY = 0.0;
1435 while ( i < numEdges - 2 )
1437 unsigned int arcEdges = 0;
1438 double numQuadrants = 0;
1441 bool foundArc =
false;
1443 a1 = lineString->
pointN( i );
1444 a2 = lineString->
pointN( i + 1 );
1445 a3 = lineString->
pointN( i + 2 );
1448 for ( j = i + 3; j < numEdges + 1; j++ )
1450 b = lineString->
pointN( j );
1457 for ( k = j - 1; k > j - 4; k-- )
1458 edgesInArcs[k] = currentArc;
1478 arcEdges = j - 1 - i;
1479 if ( first.
x() == b.x() && first.
y() == b.y() )
1494 numQuadrants = ( 4 *
angle ) / ( 2 * M_PI );
1497 if ( arcEdges < minQuadEdges * numQuadrants )
1500 for ( k = j - 1; k >= i; k-- )
1517 int edgeType = edgesInArcs[0];
1519 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1524 QVector< QgsPoint > points;
1525 for (
int j = start; j < end + 2; ++ j )
1527 points.append( lineString->
pointN( j ) );
1529 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1530 out->addCurve( straightSegment.release() );
1535 QVector< QgsPoint > points;
1536 points.append( lineString->
pointN( start ) );
1537 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1538 points.append( lineString->
pointN( end + 1 ) );
1539 std::unique_ptr< QgsCircularString > curvedSegment = std::make_unique< QgsCircularString >();
1540 curvedSegment->setPoints( points );
1541 out->addCurve( curvedSegment.release() );
1545 for (
int i = 1; i < numEdges; i++ )
1547 if ( edgeType != edgesInArcs[i] )
1550 addPointsToCurve( start, end, edgeType );
1552 edgeType = edgesInArcs[i];
1558 addPointsToCurve( start, end, edgeType );
1563 std::unique_ptr< QgsCircularString > res;
1564 res.reset( qgsgeometry_cast< const QgsCircularString * >( out->simplifiedTypeRef() )->clone() );
1578 return lineToCurve( qgsgeometry_cast< const QgsCurve * >( geom ), distanceTolerance, angleTolerance );
1583 const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( geom );
1584 std::unique_ptr< QgsCurvePolygon > result = std::make_unique< QgsCurvePolygon>();
1587 distanceTolerance, angleTolerance ).release() );
1591 distanceTolerance, angleTolerance ).release() );
1611 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1613 int numGeom = gc->numGeometries();
1614 QVector< QgsAbstractGeometry * > geometryList;
1615 geometryList.reserve( numGeom );
1616 for (
int i = 0; i < numGeom; ++i )
1639 area = std::numeric_limits<double>::max();
1641 width = std::numeric_limits<double>::max();
1642 height = std::numeric_limits<double>::max();
1648 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1659 double totalRotation = 0;
1660 while ( hull->nextVertex( vertexId, pt2 ) )
1663 double rotateAngle = 180.0 / M_PI * currentAngle;
1664 totalRotation += rotateAngle;
1666 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1667 t.rotate( rotateAngle );
1668 t.translate( -pt0.
x(), -pt0.
y() );
1670 hull->transform( t );
1673 double currentArea = bounds.
width() * bounds.
height();
1674 if ( currentArea < area )
1678 angle = totalRotation;
1679 width = bounds.
width();
1680 height = bounds.
height();
1689 if ( width > height )
1691 width = minRect.
height();
1692 height = minRect.
width();
1697 if (
angle > 180.0 )
1705 const int totalPoints = line->
numPoints();
1706 if ( totalPoints < 2 )
1709 const double *x = line->
xData();
1710 const double *y = line->
yData();
1712 double prevX = *x++;
1713 double prevY = *y++;
1715 QVector< double > outX;
1716 QVector< double > outY;
1717 const double totalLength = line->
length();
1719 const int maxRepetitions = std::ceil( totalLength / wavelength );
1720 if ( !strictWavelength )
1721 wavelength = totalLength / maxRepetitions;
1723 const int estimatedPoints = maxRepetitions * 2 + 2;
1724 outX.reserve( estimatedPoints );
1725 outY.reserve( estimatedPoints );
1726 outX.append( prevX );
1727 outY.append( prevY );
1729 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1731 for (
int i = 1; i < totalPoints; ++i )
1733 double thisX = *x++;
1734 double thisY = *y++;
1737 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1738 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1741 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1746 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1747 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1749 outX.append( outPointX );
1750 outY.append( outPointY );
1752 distanceToNextPointFromStartOfSegment += wavelength / 2;
1758 distanceToNextPointFromStartOfSegment -= segmentLength;
1761 outX.append( prevX );
1762 outY.append( prevY );
1764 return std::make_unique< QgsLineString >( outX, outY );
1768 const double minimumWavelength,
const double maximumWavelength,
1769 const double minimumAmplitude,
const double maximumAmplitude,
1770 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1772 const int totalPoints = line->
numPoints();
1773 if ( totalPoints < 2 )
1776 const double *x = line->
xData();
1777 const double *y = line->
yData();
1779 double prevX = *x++;
1780 double prevY = *y++;
1782 QVector< double > outX;
1783 QVector< double > outY;
1784 const double totalLength = line->
length();
1786 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1788 const int estimatedPoints = maxRepetitions * 2 + 2;
1789 outX.reserve( estimatedPoints );
1790 outY.reserve( estimatedPoints );
1791 outX.append( prevX );
1792 outY.append( prevY );
1794 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1795 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1796 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1799 for (
int i = 1; i < totalPoints; ++i )
1801 double thisX = *x++;
1802 double thisY = *y++;
1805 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1806 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1809 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1814 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1815 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1816 outX.append( outPointX );
1817 outY.append( outPointY );
1819 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1820 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1822 distanceToNextPointFromStartOfSegment += wavelength / 2;
1828 distanceToNextPointFromStartOfSegment -= segmentLength;
1831 outX.append( prevX );
1832 outY.append( prevY );
1834 return std::make_unique< QgsLineString >( outX, outY );
1839 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1843 geom = segmentizedCopy.get();
1854 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1857 wavelength, amplitude, strictWavelength ).release() );
1861 wavelength, amplitude, strictWavelength ).release() );
1868std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1870 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1874 geom = segmentizedCopy.get();
1885 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1888 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
1892 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
1915 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1917 int numGeom = gc->numGeometries();
1918 QVector< QgsAbstractGeometry * > geometryList;
1919 geometryList.reserve( numGeom );
1920 for (
int i = 0; i < numGeom; ++i )
1922 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
1940 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
1949 std::random_device rd;
1950 std::mt19937 mt( seed == 0 ? rd() : seed );
1951 std::uniform_real_distribution<> uniformDist( 0, 1 );
1958 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1960 int numGeom = gc->numGeometries();
1961 QVector< QgsAbstractGeometry * > geometryList;
1962 geometryList.reserve( numGeom );
1963 for (
int i = 0; i < numGeom; ++i )
1965 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
1983 const int totalPoints = line->
numPoints();
1984 if ( totalPoints < 2 )
1987 const double *x = line->
xData();
1988 const double *y = line->
yData();
1990 double prevX = *x++;
1991 double prevY = *y++;
1993 QVector< double > outX;
1994 QVector< double > outY;
1995 const double totalLength = line->
length();
1997 const int maxRepetitions = std::ceil( totalLength / wavelength );
1998 if ( !strictWavelength )
1999 wavelength = totalLength / maxRepetitions;
2001 const int estimatedPoints = maxRepetitions * 4 + 2;
2002 outX.reserve( estimatedPoints );
2003 outY.reserve( estimatedPoints );
2004 outX.append( prevX );
2005 outY.append( prevY );
2008 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2009 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2011 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2014 for (
int i = 1; i < totalPoints; ++i )
2016 double thisX = *x++;
2017 double thisY = *y++;
2020 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2021 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2024 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2029 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2030 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2031 outX.append( pX + side * amplitude * sinAngle );
2032 outY.append( pY + side * amplitude * cosAngle );
2033 outX.append( pX - side * amplitude * sinAngle );
2034 outY.append( pY - side * amplitude * cosAngle );
2036 distanceToNextPointFromStartOfSegment += wavelength / 2;
2042 distanceToNextPointFromStartOfSegment -= segmentLength;
2048 outX.append( prevX );
2049 outY.append( prevY );
2051 return std::make_unique< QgsLineString >( outX, outY );
2055 const double minimumWavelength,
const double maximumWavelength,
2056 const double minimumAmplitude,
const double maximumAmplitude,
2057 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2059 const int totalPoints = line->
numPoints();
2060 if ( totalPoints < 2 )
2063 const double *x = line->
xData();
2064 const double *y = line->
yData();
2066 double prevX = *x++;
2067 double prevY = *y++;
2069 QVector< double > outX;
2070 QVector< double > outY;
2071 const double totalLength = line->
length();
2073 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2075 const int estimatedPoints = maxRepetitions * 4 + 2;
2076 outX.reserve( estimatedPoints );
2077 outY.reserve( estimatedPoints );
2078 outX.append( prevX );
2079 outY.append( prevY );
2081 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2084 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2085 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2087 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2088 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2091 for (
int i = 1; i < totalPoints; ++i )
2093 double thisX = *x++;
2094 double thisY = *y++;
2097 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2098 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2101 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2106 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2107 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2108 outX.append( pX + side * amplitude * sinAngle );
2109 outY.append( pY + side * amplitude * cosAngle );
2111 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2112 outX.append( pX - side * amplitude * sinAngle );
2113 outY.append( pY - side * amplitude * cosAngle );
2115 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2116 distanceToNextPointFromStartOfSegment += wavelength / 2;
2122 distanceToNextPointFromStartOfSegment -= segmentLength;
2125 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2126 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2127 outX.append( prevX );
2128 outY.append( prevY );
2130 return std::make_unique< QgsLineString >( outX, outY );
2135 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2139 geom = segmentizedCopy.get();
2150 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2153 wavelength, amplitude, strictWavelength ).release() );
2157 wavelength, amplitude, strictWavelength ).release() );
2164std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2166 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2170 geom = segmentizedCopy.get();
2181 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2184 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2188 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2211 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2213 int numGeom = gc->numGeometries();
2214 QVector< QgsAbstractGeometry * > geometryList;
2215 geometryList.reserve( numGeom );
2216 for (
int i = 0; i < numGeom; ++i )
2218 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2236 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2245 std::random_device rd;
2246 std::mt19937 mt( seed == 0 ? rd() : seed );
2247 std::uniform_real_distribution<> uniformDist( 0, 1 );
2254 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2256 int numGeom = gc->numGeometries();
2257 QVector< QgsAbstractGeometry * > geometryList;
2258 geometryList.reserve( numGeom );
2259 for (
int i = 0; i < numGeom; ++i )
2261 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2279 const int totalPoints = line->
numPoints();
2280 if ( totalPoints < 2 )
2283 const double *x = line->
xData();
2284 const double *y = line->
yData();
2286 double prevX = *x++;
2287 double prevY = *y++;
2289 const double totalLength = line->
length();
2291 const int maxRepetitions = std::ceil( totalLength / wavelength );
2292 if ( !strictWavelength )
2293 wavelength = totalLength / maxRepetitions;
2295 const int segments = 10;
2299 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2300 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2301 bool isFirstPart =
true;
2303 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2304 int bufferIndex = 1;
2305 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2307 double segmentAngleRadians = 0;
2308 double remainingDistance = totalLength;
2309 double totalCoveredDistance = 0;
2311 for (
int i = 1; i < totalPoints; ++i )
2313 double thisX = *x++;
2314 double thisY = *y++;
2317 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2318 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2321 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2324 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2326 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2327 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2329 if ( bufferIndex == 0 )
2331 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2332 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2334 distanceToNextPointFromStartOfSegment += wavelength / 4;
2336 else if ( bufferIndex == 1 && isFirstPart )
2338 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2339 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2340 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2341 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2343 distanceToNextPointFromStartOfSegment += wavelength / 8;
2345 else if ( bufferIndex == 1 )
2347 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2348 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2349 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2350 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2352 distanceToNextPointFromStartOfSegment += wavelength / 4;
2354 else if ( bufferIndex == 2 )
2356 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2357 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2361 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2362 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2363 isFirstPart =
false;
2368 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2369 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2370 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2372 out->append( bezier.get() );
2375 xOutBuffer[0] = xOutBuffer[3];
2376 yOutBuffer[0] = yOutBuffer[3];
2379 distanceToNextPointFromStartOfSegment += wavelength / 4;
2382 totalCoveredDistance += segmentLength;
2385 distanceToNextPointFromStartOfSegment -= segmentLength;
2388 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2389 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2390 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2391 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2394 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2395 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2398 out->append( bezier.get() );
2404 const double minimumWavelength,
const double maximumWavelength,
2405 const double minimumAmplitude,
const double maximumAmplitude,
2406 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2408 const int totalPoints = line->
numPoints();
2409 if ( totalPoints < 2 )
2412 const double *x = line->
xData();
2413 const double *y = line->
yData();
2415 double prevX = *x++;
2416 double prevY = *y++;
2418 const double totalLength = line->
length();
2420 const int segments = 10;
2424 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2425 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2426 bool isFirstPart =
true;
2428 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2429 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2431 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2432 int bufferIndex = 1;
2433 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2435 double segmentAngleRadians = 0;
2437 double remainingDistance = totalLength;
2438 double totalCoveredDistance = 0;
2440 for (
int i = 1; i < totalPoints; ++i )
2442 double thisX = *x++;
2443 double thisY = *y++;
2446 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2447 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2450 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2453 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2455 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2456 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2458 if ( bufferIndex == 0 )
2460 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2461 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2463 distanceToNextPointFromStartOfSegment += wavelength / 4;
2465 else if ( bufferIndex == 1 && isFirstPart )
2467 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2468 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2469 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2470 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2472 distanceToNextPointFromStartOfSegment += wavelength / 8;
2474 else if ( bufferIndex == 1 )
2476 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2477 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2478 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2479 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2481 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2482 distanceToNextPointFromStartOfSegment += wavelength / 4;
2484 else if ( bufferIndex == 2 )
2486 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2487 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2491 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2492 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2493 isFirstPart =
false;
2498 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2499 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2500 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2502 out->append( bezier.get() );
2505 xOutBuffer[0] = xOutBuffer[3];
2506 yOutBuffer[0] = yOutBuffer[3];
2510 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2512 distanceToNextPointFromStartOfSegment += wavelength / 4;
2515 totalCoveredDistance += segmentLength;
2519 distanceToNextPointFromStartOfSegment -= segmentLength;
2522 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2523 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2524 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2525 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2527 if ( out->isEmpty() )
2531 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2534 out->append( bezier.get() );
2539 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2540 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2543 out->append( bezier.get() );
2551 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2555 geom = segmentizedCopy.get();
2566 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2569 wavelength, amplitude, strictWavelength ).release() );
2573 wavelength, amplitude, strictWavelength ).release() );
2580std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2582 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2586 geom = segmentizedCopy.get();
2597 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2600 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2604 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2627 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2629 int numGeom = gc->numGeometries();
2630 QVector< QgsAbstractGeometry * > geometryList;
2631 geometryList.reserve( numGeom );
2632 for (
int i = 0; i < numGeom; ++i )
2634 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2652 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2661 std::random_device rd;
2662 std::mt19937 mt( seed == 0 ? rd() : seed );
2663 std::uniform_real_distribution<> uniformDist( 0, 1 );
2670 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2672 int numGeom = gc->numGeometries();
2673 QVector< QgsAbstractGeometry * > geometryList;
2674 geometryList.reserve( numGeom );
2675 for (
int i = 0; i < numGeom; ++i )
2677 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2694 const QVector< double> &pattern,
2698 double patternOffset )
2700 const int totalPoints = line->
numPoints();
2701 if ( totalPoints < 2 )
2704 const int patternSize = pattern.size();
2706 const double *x = line->
xData();
2707 const double *y = line->
yData();
2709 double prevX = *x++;
2710 double prevY = *y++;
2712 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2714 QVector< double > outX;
2715 QVector< double > outY;
2716 const double totalLength = line->
length();
2718 double patternLength = 0;
2719 double patternDashLength = 0;
2720 double patternGapLength = 0;
2721 for (
int i = 0; i < pattern.size(); ++i )
2723 patternLength += pattern.at( i );
2725 patternDashLength += pattern.at( i );
2727 patternGapLength += pattern.at( i );
2730 double firstPatternLength = 0;
2731 double firstPatternDashLength = 0;
2732 double firstPatternGapLength = 0;
2733 switch ( startRule )
2737 firstPatternLength = patternLength;
2738 firstPatternDashLength = patternDashLength;
2739 firstPatternGapLength = patternGapLength;
2742 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2743 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2744 firstPatternGapLength = patternGapLength;
2747 firstPatternLength = pattern.at( patternSize - 1 );
2748 firstPatternDashLength = 0;
2749 firstPatternGapLength = pattern.at( patternSize - 1 );
2752 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2753 firstPatternDashLength = 0;
2754 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2758 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2760 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2761 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2762 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2766 lastPatternLength = 0;
2767 lastPatternDashLength = 0;
2768 lastPatternGapLength = 0;
2771 lastPatternLength -= pattern.at( patternSize - 1 );
2772 lastPatternGapLength -= pattern.at( patternSize - 1 );
2775 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2776 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2777 lastPatternGapLength -= pattern.at( patternSize - 1 );
2780 lastPatternGapLength = patternGapLength;
2783 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2784 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2788 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2789 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2791 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2792 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2793 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2795 double dashLengthScalingFactor = 1;
2796 double gapLengthScalingFactor = 1;
2800 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2802 switch ( adjustment )
2805 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2806 gapLengthScalingFactor = dashLengthScalingFactor;
2809 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2812 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2817 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2818 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2820 const int maxPatterns = middlePatternRepetitions + 2;
2821 result->reserve( maxPatterns );
2823 int patternIndex = 0;
2824 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2826 switch ( startRule )
2832 distanceToNextPointFromStartOfSegment *= 0.5;
2835 patternIndex = patternSize - 1;
2837 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2840 patternIndex = patternSize - 1;
2842 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2846 const double adjustedOffset = fmod( patternOffset, patternLength );
2847 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
2851 double remainingOffset = scaledOffset;
2852 while ( remainingOffset > 0 )
2854 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
2856 distanceToNextPointFromStartOfSegment -= remainingOffset;
2860 remainingOffset -= distanceToNextPointFromStartOfSegment;
2863 if ( patternIndex == patternSize )
2866 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
2872 outX.append( prevX );
2873 outY.append( prevY );
2876 for (
int i = 1; i < totalPoints; ++i )
2878 double thisX = *x++;
2879 double thisY = *y++;
2881 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2882 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2885 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2900 if ( patternIndex >= patternSize )
2903 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
2908 outX.append( thisX );
2909 outY.append( thisY );
2914 distanceToNextPointFromStartOfSegment -= segmentLength;
2919 outX.append( prevX );
2920 outY.append( prevY );
2928 const QVector<double> &pattern,
2932 double patternOffset )
2934 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2938 geom = segmentizedCopy.get();
2949 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2952 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
2953 result->addGeometry( exteriorParts->geometryN( i )->clone() );
2958 for (
int j = 0; j < ringParts->numGeometries(); ++j )
2959 result->addGeometry( ringParts->geometryN( j )->clone() );
2968 if ( pattern.size() < 2 )
2972 if ( !mGeometry || mGeometry->
isEmpty() )
2982 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2984 int numGeom = gc->numGeometries();
2985 QVector< QgsAbstractGeometry * > geometryList;
2986 geometryList.reserve( numGeom );
2987 for (
int i = 0; i < numGeom; ++i )
2989 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
2997 for (
int j = 0; j < collection->numGeometries(); ++j )
2999 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.
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.
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
virtual int nCoordinates() const
Returns the number of nodes contained in 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.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
Compound curve geometry type.
const QgsCurve * curveAt(int i) const SIP_HOLDGIL
Returns the curve at the specified index.
int nCurves() const SIP_HOLDGIL
Returns the number of curves in the geometry.
Curve polygon geometry type.
const QgsCurve * interiorRing(int i) const SIP_HOLDGIL
Retrieves an interior ring from the curve polygon.
const QgsCurve * exteriorRing() const SIP_HOLDGIL
Returns the curve polygon's exterior ring.
int numInteriorRings() const SIP_HOLDGIL
Returns the number of interior rings contained with 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 SIP_HOLDGIL
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 SIP_HOLDGIL
Tells whether the operation has been canceled already.
int numGeometries() const SIP_HOLDGIL
Returns the number of geometries within the collection.
int partCount() const override
Returns count of parts contained in the geometry.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static double triangleArea(double aX, double aY, double bX, double bY, double cX, double cY) SIP_HOLDGIL
Returns the area of the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
static void circleCenterRadius(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double &radius, double ¢erX, double ¢erY) SIP_HOLDGIL
Returns radius and center of the circle through pt1, pt2, pt3.
static double lineAngle(double x1, double y1, double x2, double y2) SIP_HOLDGIL
Calculates the direction of line joining two points in radians, clockwise from the north direction.
static int circleCircleOuterTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2) SIP_HOLDGIL
Calculates the outer tangent points for two circles, centered at center1 and center2 and with radii o...
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance) SIP_HOLDGIL
Returns a point a specified distance toward a second point.
static bool pointContinuesArc(const QgsPoint &a1, const QgsPoint &a2, const QgsPoint &a3, const QgsPoint &b, double distanceTolerance, double pointSpacingAngleTolerance) SIP_HOLDGIL
Returns true if point b is on the arc formed by points a1, a2, and a3, but not within that arc portio...
static void weightedPointInTriangle(double aX, double aY, double bX, double bY, double cX, double cY, double weightB, double weightC, double &pointX, double &pointY) SIP_HOLDGIL
Returns a weighted point inside 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) SIP_HOLDGIL
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> (x2, y2).
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
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 ...
Qgis::GeometryOperationResult addPart(const QVector< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
bool isMultipart() const SIP_HOLDGIL
Returns true if WKB of the geometry is of WKBMulti* type.
QgsWkbTypes::GeometryType type
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified 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.
QgsPointXY end() const SIP_HOLDGIL
Returns the segment's end point.
int pointLeftOfLine(const QgsPointXY &point) const SIP_HOLDGIL
Tests if a point is to the left of the line segment.
double endX() const SIP_HOLDGIL
Returns the segment's end x-coordinate.
double endY() const SIP_HOLDGIL
Returns the segment's end y-coordinate.
double startX() const SIP_HOLDGIL
Returns the segment's start x-coordinate.
QgsPointXY start() const SIP_HOLDGIL
Returns the segment's start point.
void reverse() SIP_HOLDGIL
Reverses the line segment, so that the start and end points are flipped.
double startY() const SIP_HOLDGIL
Returns the segment's start y-coordinate.
Line string geometry type, with support for z-dimension and m-values.
QgsPoint startPoint() const override SIP_HOLDGIL
Returns the starting point of the curve.
const double * yData() const
Returns a const pointer to the y vertex data.
bool isClosed() const override SIP_HOLDGIL
Returns true if the curve is closed.
const double * xData() const
Returns a const pointer to the x vertex data.
double length() const override SIP_HOLDGIL
Returns the planar, 2-dimensional length of the geometry.
int numPoints() const override SIP_HOLDGIL
Returns the number of points in 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,...
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
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
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.
int nCoordinates() const override SIP_HOLDGIL
Returns the number of nodes contained in the geometry.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
double zAt(int index) const
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.
double distance(double x, double y) const SIP_HOLDGIL
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
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 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 yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
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.
QgsVector normalized() const SIP_THROW(QgsException)
Returns the vector's normalized (or "unit") vector (ie same angle but length of 1....
double lengthSquared() const SIP_HOLDGIL
Returns the length of the vector.
double crossProduct(QgsVector v) const SIP_HOLDGIL
Returns the 2D cross product of this vector and another vector v.
double length() const SIP_HOLDGIL
Returns the length of the vector.
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Type
The WKB type describes the number of dimensions a geometry has.
static bool isCurvedType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a curved type or can contain curved geometries.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
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.