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 )
272 struct GreaterThanByMax
274 bool operator()(
const Cell *lhs,
const Cell *rhs )
const
276 return rhs->max > lhs->max;
280 Cell *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 )
530 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
535 double minScore = std::numeric_limits<double>::max();
540 std::unique_ptr< QgsLineString > best( ring->
clone() );
542 QVector< QgsVector > motions;
543 motions.reserve( numPoints );
545 for (
int it = 0; it < iterations; ++it )
553 for (
int i = 0; i < numPoints; ++i )
555 if ( isClosed && i == numPoints - 1 )
556 motions << motions.at( 0 );
557 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
567 a = ring->
pointN( numPoints - 1 );
570 if ( i == numPoints - 1 )
575 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
582 for (
int i = 0; i < numPoints; ++i )
584 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
585 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
588 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
589 if ( newScore < minScore )
591 best.reset( ring->
clone() );
595 if ( minScore < tolerance )
601 return best.release();
607 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
611 geom = segmentizedCopy.get();
617 maxIterations, tolerance, lowerThreshold, upperThreshold );
626 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
630 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
646 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
647 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
649 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
651 int numGeom = gc->numGeometries();
652 QVector< QgsAbstractGeometry * > geometryList;
653 geometryList.reserve( numGeom );
654 for (
int i = 0; i < numGeom; ++i )
656 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
675 QVector< double > outX;
676 QVector< double > outY;
677 QVector< double > outZ;
678 QVector< double > outM;
679 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
682 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
683 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
684 bool withZ = ring->
is3D();
686 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
689 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
702 int extraNodesThisSegment = extraNodesPerSegment;
703 for (
int i = 0; i < nPoints - 1; ++i )
706 x2 = ring->
xAt( i + 1 );
708 y2 = ring->
yAt( i + 1 );
712 z2 = ring->
zAt( i + 1 );
717 m2 = ring->
mAt( i + 1 );
727 if ( extraNodesPerSegment < 0 )
730 extraNodesThisSegment = std::floor( std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) / distance );
731 if ( extraNodesThisSegment >= 1 )
732 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
735 for (
int j = 0; j < extraNodesThisSegment; ++j )
737 double delta = multiplier * ( j + 1 );
738 xOut = x1 + delta * ( x2 - x1 );
739 yOut = y1 + delta * ( y2 - y1 );
741 zOut = z1 + delta * ( z2 - z1 );
743 mOut = m1 + delta * ( m2 - m1 );
753 outX << ring->
xAt( nPoints - 1 );
754 outY << ring->
yAt( nPoints - 1 );
756 outZ << ring->
zAt( nPoints - 1 );
758 outM << ring->
mAt( nPoints - 1 );
766 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
770 geom = segmentizedCopy.get();
784 extraNodesPerSegment, distance ) );
788 extraNodesPerSegment, distance ) );
808 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
810 int numGeom = gc->numGeometries();
811 QVector< QgsAbstractGeometry * > geometryList;
812 geometryList.reserve( numGeom );
813 for (
int i = 0; i < numGeom; ++i )
815 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
844 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
846 int numGeom = gc->numGeometries();
847 QVector< QgsAbstractGeometry * > geometryList;
848 geometryList.reserve( numGeom );
849 for (
int i = 0; i < numGeom; ++i )
876 "line_segment_dist_comparer",
877 "AB must not be collinear with the origin." );
879 "line_segment_dist_comparer",
880 "CD must not be collinear with the origin." );
894 if ( ab.
end() == cd.
end() || oad != oab )
904 if ( cdb == 0 && cda == 0 )
906 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
908 else if ( cda == cdb || cda == 0 || cdb == 0 )
911 return cdo == cda || cdo == cdb;
927 const bool aIsLeft = a.
x() < mVertex.x();
928 const bool bIsLeft = b.
x() < mVertex.x();
929 if ( aIsLeft != bIsLeft )
934 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
936 return b.
y() < a.
y();
940 return a.
y() < b.
y();
972 const int abo =
segment.pointLeftOfLine( origin );
979 const double distA = ao * direction;
980 const double distB = ( origin -
segment.end() ) * direction;
982 if ( distA > 0 && distB > 0 )
988 if ( ( distA > 0 ) != ( distB > 0 ) )
989 intersectPoint = origin;
990 else if ( distA > distB )
991 intersectPoint =
segment.start();
993 intersectPoint =
segment.end();
1001 if ( u < 0.0 || 1.0 < u )
1008 intersectPoint = origin + direction * t;
1017 if ( radius1 > radius2 )
1024 QVector<QgsPointXY> points;
1046 std::vector< std::unique_ptr<QgsLineString > > linesToProcess;
1048 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
1051 for (
int i = 0; i < multiCurve->
partCount(); ++i )
1060 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
1067 if ( linesToProcess.empty() )
1070 g.mLastError = QStringLiteral(
"Input geometry was not a curve type geometry" );
1074 QVector<QgsGeometry> bufferedLines;
1075 bufferedLines.reserve( linesToProcess.size() );
1077 for ( std::unique_ptr< QgsLineString > &line : linesToProcess )
1079 QVector<QgsGeometry> parts;
1081 double prevRadius = 0;
1084 std::unique_ptr< double[] > widths = widthFunction( line.get() ) ;
1089 double thisRadius = widths[ i ] / 2.0;
1090 if ( thisRadius > 0 )
1094 QgsCircle circ( thisPoint, thisRadius );
1096 parts << thisCircle;
1105 if ( prevRadius > 0 || thisRadius > 0 )
1107 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1108 if ( !points.empty() )
1113 int beforeVertex = 0;
1114 int afterVertex = 0;
1116 double sqrDistPrev = 0;
1117 for (
int j = 0; j < points.count(); ++j )
1121 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1124 points.append( points.at( 0 ) );
1126 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
1128 if ( poly->area() > 0 )
1133 prevPoint = thisPoint;
1134 prevRadius = thisRadius;
1135 prevCircle = thisCircle;
1147 start = std::fabs( start );
1148 end = std::fabs( end );
1154 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1156 widths[line->nCoordinates() - 1] = end;
1158 double lineLength = line->length();
1159 double currentLength = 0;
1160 QgsPoint prevPoint = line->pointN( 0 );
1161 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1163 QgsPoint point = line->pointN( i );
1164 double segmentLength = point.
distance( prevPoint );
1165 currentLength += segmentLength;
1166 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1167 double delta = lengthFraction * ( end - start );
1168 widths[i] = start + delta;
1182 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1183 for (
int i = 0; i < line->nCoordinates(); ++i )
1185 widths[ i ] = line->mAt( i );
1194 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1197 return QVector< QgsPointXY >();
1209 return QVector< QgsPointXY >();
1217 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->
geometryN( i )->
segmentize() ) );
1224 if (
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( polygon.
constGet() ) )
1230 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( polygon.
constGet()->
segmentize() ) );
1236 return QVector< QgsPointXY >();
1238 const QVector<float> triangleData = t.
data();
1239 if ( triangleData.empty() )
1240 return QVector< QgsPointXY >();
1243 std::vector< double > cumulativeAreas;
1245 double totalArea = 0;
1246 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1249 return QVector< QgsPointXY >();
1251 const float aX = *it++;
1253 const float aY = -( *it++ );
1254 const float bX = *it++;
1256 const float bY = -( *it++ );
1257 const float cX = *it++;
1259 const float cY = -( *it++ );
1263 cumulativeAreas.emplace_back( totalArea );
1266 std::random_device rd;
1267 std::mt19937 mt( seed == 0 ? rd() : seed );
1268 std::uniform_real_distribution<> uniformDist( 0, 1 );
1271 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1274 const double target = random * totalArea;
1275 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1280 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1285 QVector<QgsPointXY> result;
1286 result.reserve( count );
1288 for (
int i = 0; i < count; )
1291 return QVector< QgsPointXY >();
1293 const double triangleIndexRnd = uniformDist( mt );
1295 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1298 const double weightB = uniformDist( mt );
1299 const double weightC = uniformDist( mt );
1304 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1305 const double aY = -triangleData.at( triangleIndex * 9 + 2 ) + bounds.
yMinimum();
1306 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1307 const double bY = -triangleData.at( triangleIndex * 9 + 5 ) + bounds.
yMinimum();
1308 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1309 const double cY = -triangleData.at( triangleIndex * 9 + 8 ) + bounds.
yMinimum();
1313 if ( acceptPoint( candidate ) )
1319 else if ( maxTriesPerPoint != 0 )
1323 if ( tries == maxTriesPerPoint )
1336 double pointSpacingAngleTolerance )
1342 std::unique_ptr< QgsCircularString > out;
1343 out.reset( qgsgeometry_cast< QgsCircularString * >( curve )->clone() );
1348 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1349 const QgsCompoundCurve *in = qgsgeometry_cast< const QgsCompoundCurve * >( curve );
1350 for (
int i = 0; i < in->
nCurves(); i ++ )
1352 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1360 out->addCurve( qgsgeometry_cast< const QgsLineString * >( processed->simplifiedTypeRef() )->clone() );
1364 out->addCurve( processed.release() );
1372 const QgsLineString *lineString = qgsgeometry_cast< QgsLineString * >( curve );
1374 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1377 const unsigned int minQuadEdges = 2;
1390 out->addCurve( lineString->
clone() );
1396 QVector< int > edgesInArcs( numEdges + 1, 0 );
1400 double abX = b.x() - a.
x();
1401 double abY = b.y() - a.
y();
1403 double cbX = b.x() -
c.x();
1404 double cbY = b.y() -
c.y();
1406 double dot = ( abX * cbX + abY * cbY );
1407 double cross = ( abX * cbY - abY * cbX );
1409 double alpha = std::atan2( cross, dot );
1424 double centerX = 0.0;
1425 double centerY = 0.0;
1428 while ( i < numEdges - 2 )
1430 unsigned int arcEdges = 0;
1431 double numQuadrants = 0;
1434 bool foundArc =
false;
1436 a1 = lineString->
pointN( i );
1437 a2 = lineString->
pointN( i + 1 );
1438 a3 = lineString->
pointN( i + 2 );
1441 for ( j = i + 3; j < numEdges + 1; j++ )
1443 b = lineString->
pointN( j );
1450 for ( k = j - 1; k > j - 4; k-- )
1451 edgesInArcs[k] = currentArc;
1471 arcEdges = j - 1 - i;
1472 if ( first.
x() == b.x() && first.
y() == b.y() )
1487 numQuadrants = ( 4 *
angle ) / ( 2 * M_PI );
1490 if ( arcEdges < minQuadEdges * numQuadrants )
1493 for ( k = j - 1; k >= i; k-- )
1510 int edgeType = edgesInArcs[0];
1512 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1517 QVector< QgsPoint > points;
1518 for (
int j = start; j < end + 2; ++ j )
1520 points.append( lineString->
pointN( j ) );
1522 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1523 out->addCurve( straightSegment.release() );
1528 QVector< QgsPoint > points;
1529 points.append( lineString->
pointN( start ) );
1530 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1531 points.append( lineString->
pointN( end + 1 ) );
1532 std::unique_ptr< QgsCircularString > curvedSegment = std::make_unique< QgsCircularString >();
1533 curvedSegment->setPoints( points );
1534 out->addCurve( curvedSegment.release() );
1538 for (
int i = 1; i < numEdges; i++ )
1540 if ( edgeType != edgesInArcs[i] )
1543 addPointsToCurve( start, end, edgeType );
1545 edgeType = edgesInArcs[i];
1551 addPointsToCurve( start, end, edgeType );
1556 std::unique_ptr< QgsCircularString > res;
1557 res.reset( qgsgeometry_cast< const QgsCircularString * >( out->simplifiedTypeRef() )->clone() );
1571 return lineToCurve( qgsgeometry_cast< const QgsCurve * >( geom ), distanceTolerance, angleTolerance );
1576 const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( geom );
1577 std::unique_ptr< QgsCurvePolygon > result = std::make_unique< QgsCurvePolygon>();
1580 distanceTolerance, angleTolerance ).release() );
1584 distanceTolerance, angleTolerance ).release() );
1604 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1606 int numGeom = gc->numGeometries();
1607 QVector< QgsAbstractGeometry * > geometryList;
1608 geometryList.reserve( numGeom );
1609 for (
int i = 0; i < numGeom; ++i )
1632 area = std::numeric_limits<double>::max();
1634 width = std::numeric_limits<double>::max();
1635 height = std::numeric_limits<double>::max();
1641 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1652 double totalRotation = 0;
1653 while ( hull->nextVertex( vertexId, pt2 ) )
1656 double rotateAngle = 180.0 / M_PI * currentAngle;
1657 totalRotation += rotateAngle;
1659 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1660 t.rotate( rotateAngle );
1661 t.translate( -pt0.
x(), -pt0.
y() );
1663 hull->transform( t );
1666 double currentArea = bounds.
width() * bounds.
height();
1667 if ( currentArea < area )
1671 angle = totalRotation;
1672 width = bounds.
width();
1673 height = bounds.
height();
1682 if ( width > height )
1684 width = minRect.
height();
1685 height = minRect.
width();
1690 if (
angle > 180.0 )
1698 const int totalPoints = line->
numPoints();
1699 if ( totalPoints < 2 )
1702 const double *x = line->
xData();
1703 const double *y = line->
yData();
1705 double prevX = *x++;
1706 double prevY = *y++;
1708 QVector< double > outX;
1709 QVector< double > outY;
1710 const double totalLength = line->
length();
1712 const int maxRepetitions = std::ceil( totalLength / wavelength );
1713 if ( !strictWavelength )
1714 wavelength = totalLength / maxRepetitions;
1716 const int estimatedPoints = maxRepetitions * 2 + 2;
1717 outX.reserve( estimatedPoints );
1718 outY.reserve( estimatedPoints );
1719 outX.append( prevX );
1720 outY.append( prevY );
1722 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1724 for (
int i = 1; i < totalPoints; ++i )
1726 double thisX = *x++;
1727 double thisY = *y++;
1730 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1731 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1734 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1739 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1740 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1742 outX.append( outPointX );
1743 outY.append( outPointY );
1745 distanceToNextPointFromStartOfSegment += wavelength / 2;
1751 distanceToNextPointFromStartOfSegment -= segmentLength;
1754 outX.append( prevX );
1755 outY.append( prevY );
1757 return std::make_unique< QgsLineString >( outX, outY );
1761 const double minimumWavelength,
const double maximumWavelength,
1762 const double minimumAmplitude,
const double maximumAmplitude,
1763 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1765 const int totalPoints = line->
numPoints();
1766 if ( totalPoints < 2 )
1769 const double *x = line->
xData();
1770 const double *y = line->
yData();
1772 double prevX = *x++;
1773 double prevY = *y++;
1775 QVector< double > outX;
1776 QVector< double > outY;
1777 const double totalLength = line->
length();
1779 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1781 const int estimatedPoints = maxRepetitions * 2 + 2;
1782 outX.reserve( estimatedPoints );
1783 outY.reserve( estimatedPoints );
1784 outX.append( prevX );
1785 outY.append( prevY );
1787 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1788 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1789 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1792 for (
int i = 1; i < totalPoints; ++i )
1794 double thisX = *x++;
1795 double thisY = *y++;
1798 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1799 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1802 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1807 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1808 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1809 outX.append( outPointX );
1810 outY.append( outPointY );
1812 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1813 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1815 distanceToNextPointFromStartOfSegment += wavelength / 2;
1821 distanceToNextPointFromStartOfSegment -= segmentLength;
1824 outX.append( prevX );
1825 outY.append( prevY );
1827 return std::make_unique< QgsLineString >( outX, outY );
1832 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1836 geom = segmentizedCopy.get();
1847 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1850 wavelength, amplitude, strictWavelength ).release() );
1854 wavelength, amplitude, strictWavelength ).release() );
1861 std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1863 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1867 geom = segmentizedCopy.get();
1878 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1881 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
1885 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
1908 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1910 int numGeom = gc->numGeometries();
1911 QVector< QgsAbstractGeometry * > geometryList;
1912 geometryList.reserve( numGeom );
1913 for (
int i = 0; i < numGeom; ++i )
1915 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
1933 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
1942 std::random_device rd;
1943 std::mt19937 mt( seed == 0 ? rd() : seed );
1944 std::uniform_real_distribution<> uniformDist( 0, 1 );
1951 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1953 int numGeom = gc->numGeometries();
1954 QVector< QgsAbstractGeometry * > geometryList;
1955 geometryList.reserve( numGeom );
1956 for (
int i = 0; i < numGeom; ++i )
1958 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
1976 const int totalPoints = line->
numPoints();
1977 if ( totalPoints < 2 )
1980 const double *x = line->
xData();
1981 const double *y = line->
yData();
1983 double prevX = *x++;
1984 double prevY = *y++;
1986 QVector< double > outX;
1987 QVector< double > outY;
1988 const double totalLength = line->
length();
1990 const int maxRepetitions = std::ceil( totalLength / wavelength );
1991 if ( !strictWavelength )
1992 wavelength = totalLength / maxRepetitions;
1994 const int estimatedPoints = maxRepetitions * 4 + 2;
1995 outX.reserve( estimatedPoints );
1996 outY.reserve( estimatedPoints );
1997 outX.append( prevX );
1998 outY.append( prevY );
2001 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2002 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2004 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2007 for (
int i = 1; i < totalPoints; ++i )
2009 double thisX = *x++;
2010 double thisY = *y++;
2013 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2014 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2017 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2022 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2023 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2024 outX.append( pX + side * amplitude * sinAngle );
2025 outY.append( pY + side * amplitude * cosAngle );
2026 outX.append( pX - side * amplitude * sinAngle );
2027 outY.append( pY - side * amplitude * cosAngle );
2029 distanceToNextPointFromStartOfSegment += wavelength / 2;
2035 distanceToNextPointFromStartOfSegment -= segmentLength;
2041 outX.append( prevX );
2042 outY.append( prevY );
2044 return std::make_unique< QgsLineString >( outX, outY );
2048 const double minimumWavelength,
const double maximumWavelength,
2049 const double minimumAmplitude,
const double maximumAmplitude,
2050 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2052 const int totalPoints = line->
numPoints();
2053 if ( totalPoints < 2 )
2056 const double *x = line->
xData();
2057 const double *y = line->
yData();
2059 double prevX = *x++;
2060 double prevY = *y++;
2062 QVector< double > outX;
2063 QVector< double > outY;
2064 const double totalLength = line->
length();
2066 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2068 const int estimatedPoints = maxRepetitions * 4 + 2;
2069 outX.reserve( estimatedPoints );
2070 outY.reserve( estimatedPoints );
2071 outX.append( prevX );
2072 outY.append( prevY );
2074 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2077 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2078 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2080 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2081 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2084 for (
int i = 1; i < totalPoints; ++i )
2086 double thisX = *x++;
2087 double thisY = *y++;
2090 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2091 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2094 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2099 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2100 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2101 outX.append( pX + side * amplitude * sinAngle );
2102 outY.append( pY + side * amplitude * cosAngle );
2104 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2105 outX.append( pX - side * amplitude * sinAngle );
2106 outY.append( pY - side * amplitude * cosAngle );
2108 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2109 distanceToNextPointFromStartOfSegment += wavelength / 2;
2115 distanceToNextPointFromStartOfSegment -= segmentLength;
2118 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2119 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2120 outX.append( prevX );
2121 outY.append( prevY );
2123 return std::make_unique< QgsLineString >( outX, outY );
2128 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2132 geom = segmentizedCopy.get();
2143 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2146 wavelength, amplitude, strictWavelength ).release() );
2150 wavelength, amplitude, strictWavelength ).release() );
2157 std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2159 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2163 geom = segmentizedCopy.get();
2174 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2177 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2181 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2204 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2206 int numGeom = gc->numGeometries();
2207 QVector< QgsAbstractGeometry * > geometryList;
2208 geometryList.reserve( numGeom );
2209 for (
int i = 0; i < numGeom; ++i )
2211 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2229 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2238 std::random_device rd;
2239 std::mt19937 mt( seed == 0 ? rd() : seed );
2240 std::uniform_real_distribution<> uniformDist( 0, 1 );
2247 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2249 int numGeom = gc->numGeometries();
2250 QVector< QgsAbstractGeometry * > geometryList;
2251 geometryList.reserve( numGeom );
2252 for (
int i = 0; i < numGeom; ++i )
2254 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2272 const int totalPoints = line->
numPoints();
2273 if ( totalPoints < 2 )
2276 const double *x = line->
xData();
2277 const double *y = line->
yData();
2279 double prevX = *x++;
2280 double prevY = *y++;
2282 const double totalLength = line->
length();
2284 const int maxRepetitions = std::ceil( totalLength / wavelength );
2285 if ( !strictWavelength )
2286 wavelength = totalLength / maxRepetitions;
2288 const int segments = 10;
2292 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2293 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2294 bool isFirstPart =
true;
2296 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2297 int bufferIndex = 1;
2298 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2300 double segmentAngleRadians = 0;
2301 double remainingDistance = totalLength;
2302 double totalCoveredDistance = 0;
2304 for (
int i = 1; i < totalPoints; ++i )
2306 double thisX = *x++;
2307 double thisY = *y++;
2310 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2311 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2314 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2317 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2319 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2320 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2322 if ( bufferIndex == 0 )
2324 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2325 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2327 distanceToNextPointFromStartOfSegment += wavelength / 4;
2329 else if ( bufferIndex == 1 && isFirstPart )
2331 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2332 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2333 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2334 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2336 distanceToNextPointFromStartOfSegment += wavelength / 8;
2338 else if ( bufferIndex == 1 )
2340 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2341 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2342 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2343 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2345 distanceToNextPointFromStartOfSegment += wavelength / 4;
2347 else if ( bufferIndex == 2 )
2349 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2350 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2354 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2355 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2356 isFirstPart =
false;
2361 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2362 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2363 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2365 out->append( bezier.get() );
2368 xOutBuffer[0] = xOutBuffer[3];
2369 yOutBuffer[0] = yOutBuffer[3];
2372 distanceToNextPointFromStartOfSegment += wavelength / 4;
2375 totalCoveredDistance += segmentLength;
2378 distanceToNextPointFromStartOfSegment -= segmentLength;
2381 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2382 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2383 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2384 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2387 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2388 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2391 out->append( bezier.get() );
2397 const double minimumWavelength,
const double maximumWavelength,
2398 const double minimumAmplitude,
const double maximumAmplitude,
2399 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2401 const int totalPoints = line->
numPoints();
2402 if ( totalPoints < 2 )
2405 const double *x = line->
xData();
2406 const double *y = line->
yData();
2408 double prevX = *x++;
2409 double prevY = *y++;
2411 const double totalLength = line->
length();
2413 const int segments = 10;
2417 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2418 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2419 bool isFirstPart =
true;
2421 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2422 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2424 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2425 int bufferIndex = 1;
2426 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2428 double segmentAngleRadians = 0;
2430 double remainingDistance = totalLength;
2431 double totalCoveredDistance = 0;
2433 for (
int i = 1; i < totalPoints; ++i )
2435 double thisX = *x++;
2436 double thisY = *y++;
2439 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2440 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2443 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2446 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2448 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2449 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2451 if ( bufferIndex == 0 )
2453 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2454 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2456 distanceToNextPointFromStartOfSegment += wavelength / 4;
2458 else if ( bufferIndex == 1 && isFirstPart )
2460 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2461 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2462 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2463 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2465 distanceToNextPointFromStartOfSegment += wavelength / 8;
2467 else if ( bufferIndex == 1 )
2469 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2470 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2471 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2472 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2474 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2475 distanceToNextPointFromStartOfSegment += wavelength / 4;
2477 else if ( bufferIndex == 2 )
2479 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2480 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2484 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2485 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2486 isFirstPart =
false;
2491 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2492 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2493 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2495 out->append( bezier.get() );
2498 xOutBuffer[0] = xOutBuffer[3];
2499 yOutBuffer[0] = yOutBuffer[3];
2503 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2505 distanceToNextPointFromStartOfSegment += wavelength / 4;
2508 totalCoveredDistance += segmentLength;
2512 distanceToNextPointFromStartOfSegment -= segmentLength;
2515 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2516 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2517 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2518 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2520 if ( out->isEmpty() )
2524 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2527 out->append( bezier.get() );
2532 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2533 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2536 out->append( bezier.get() );
2544 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2548 geom = segmentizedCopy.get();
2559 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2562 wavelength, amplitude, strictWavelength ).release() );
2566 wavelength, amplitude, strictWavelength ).release() );
2573 std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2575 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2579 geom = segmentizedCopy.get();
2590 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2593 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2597 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2620 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2622 int numGeom = gc->numGeometries();
2623 QVector< QgsAbstractGeometry * > geometryList;
2624 geometryList.reserve( numGeom );
2625 for (
int i = 0; i < numGeom; ++i )
2627 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2645 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2654 std::random_device rd;
2655 std::mt19937 mt( seed == 0 ? rd() : seed );
2656 std::uniform_real_distribution<> uniformDist( 0, 1 );
2663 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2665 int numGeom = gc->numGeometries();
2666 QVector< QgsAbstractGeometry * > geometryList;
2667 geometryList.reserve( numGeom );
2668 for (
int i = 0; i < numGeom; ++i )
2670 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2687 const QVector< double> &pattern,
2691 double patternOffset )
2693 const int totalPoints = line->
numPoints();
2694 if ( totalPoints < 2 )
2697 const int patternSize = pattern.size();
2699 const double *x = line->
xData();
2700 const double *y = line->
yData();
2702 double prevX = *x++;
2703 double prevY = *y++;
2705 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2707 QVector< double > outX;
2708 QVector< double > outY;
2709 const double totalLength = line->
length();
2711 double patternLength = 0;
2712 double patternDashLength = 0;
2713 double patternGapLength = 0;
2714 for (
int i = 0; i < pattern.size(); ++i )
2716 patternLength += pattern.at( i );
2718 patternDashLength += pattern.at( i );
2720 patternGapLength += pattern.at( i );
2723 double firstPatternLength = 0;
2724 double firstPatternDashLength = 0;
2725 double firstPatternGapLength = 0;
2726 switch ( startRule )
2730 firstPatternLength = patternLength;
2731 firstPatternDashLength = patternDashLength;
2732 firstPatternGapLength = patternGapLength;
2735 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2736 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2737 firstPatternGapLength = patternGapLength;
2740 firstPatternLength = pattern.at( patternSize - 1 );
2741 firstPatternDashLength = 0;
2742 firstPatternGapLength = pattern.at( patternSize - 1 );
2745 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2746 firstPatternDashLength = 0;
2747 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2751 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2753 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2754 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2755 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2759 lastPatternLength = 0;
2760 lastPatternDashLength = 0;
2761 lastPatternGapLength = 0;
2764 lastPatternLength -= pattern.at( patternSize - 1 );
2765 lastPatternGapLength -= pattern.at( patternSize - 1 );
2768 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2769 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2770 lastPatternGapLength -= pattern.at( patternSize - 1 );
2773 lastPatternGapLength = patternGapLength;
2776 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2777 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2781 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2782 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2784 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2785 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2786 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2788 double dashLengthScalingFactor = 1;
2789 double gapLengthScalingFactor = 1;
2793 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2795 switch ( adjustment )
2798 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2799 gapLengthScalingFactor = dashLengthScalingFactor;
2802 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2805 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2810 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2811 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2813 const int maxPatterns = middlePatternRepetitions + 2;
2814 result->reserve( maxPatterns );
2816 int patternIndex = 0;
2817 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2819 switch ( startRule )
2825 distanceToNextPointFromStartOfSegment *= 0.5;
2828 patternIndex = patternSize - 1;
2830 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2833 patternIndex = patternSize - 1;
2835 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2839 const double adjustedOffset = fmod( patternOffset, patternLength );
2840 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
2844 double remainingOffset = scaledOffset;
2845 while ( remainingOffset > 0 )
2847 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
2849 distanceToNextPointFromStartOfSegment -= remainingOffset;
2853 remainingOffset -= distanceToNextPointFromStartOfSegment;
2856 if ( patternIndex == patternSize )
2859 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
2865 outX.append( prevX );
2866 outY.append( prevY );
2869 for (
int i = 1; i < totalPoints; ++i )
2871 double thisX = *x++;
2872 double thisY = *y++;
2874 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2875 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2878 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2893 if ( patternIndex >= patternSize )
2896 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
2901 outX.append( thisX );
2902 outY.append( thisY );
2907 distanceToNextPointFromStartOfSegment -= segmentLength;
2912 outX.append( prevX );
2913 outY.append( prevY );
2921 const QVector<double> &pattern,
2925 double patternOffset )
2927 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2931 geom = segmentizedCopy.get();
2942 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2945 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
2946 result->addGeometry( exteriorParts->geometryN( i )->clone() );
2951 for (
int j = 0; j < ringParts->numGeometries(); ++j )
2952 result->addGeometry( ringParts->geometryN( j )->clone() );
2961 if ( pattern.size() < 2 )
2965 if ( !mGeometry || mGeometry->
isEmpty() )
2975 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2977 int numGeom = gc->numGeometries();
2978 QVector< QgsAbstractGeometry * > geometryList;
2979 geometryList.reserve( numGeom );
2980 for (
int i = 0; i < numGeom; ++i )
2982 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
2990 for (
int j = 0; j < collection->numGeometries(); ++j )
2992 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 QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
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.
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.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
int partCount() const override
Returns count of parts contained in the geometry.
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.
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries)
Compute the unary union on a list of geometries.
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.
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.
bool isClosed() const override SIP_HOLDGIL
Returns true if the curve is closed.
const double * yData() const
Returns a const pointer to the y 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.
const double * xData() const
Returns a const pointer to the x vertex data.
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)
QgsAbstractGeometry * densifyGeometry(const QgsAbstractGeometry *geom, int extraNodesPerSegment=1, double distance=1)
std::unique_ptr< QgsLineString > squareWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
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)
Direction getEdgeDirection(const QgsPoint &p1, const QgsPoint &p2, double maxDev)
Determines the direction of an edge from p1 to p2.
QVector< QgsPointXY > generateSegmentCurve(const QgsPoint ¢er1, const double radius1, const QgsPoint ¢er2, const double radius2)
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)
bool dotProductWithinAngleTolerance(double dotProduct, double lowerThreshold, double upperThreshold)
std::pair< bool, std::array< Direction, 4 > > getEdgeDirections(const QgsPolygon *g, double maxDev)
Checks whether the polygon consists of four nearly axis-parallel sides.
double squareness(QgsLineString *ring, double lowerThreshold, double upperThreshold)
QgsAbstractGeometry * orthogonalizeGeom(const QgsAbstractGeometry *geom, int maxIterations, double tolerance, 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.
std::unique_ptr< QgsLineString > roundWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
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)
QgsLineString * doOrthogonalize(QgsLineString *ring, int iterations, double tolerance, double lowerThreshold, double upperThreshold)
std::unique_ptr< QgsLineString > triangularWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
QgsLineString * doDensify(const QgsLineString *ring, int extraNodesPerSegment=-1, double distance=1)
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.