39 : mGeometry( geometry.constGet() )
66 double dx = p2.
x() - p1.
x();
67 double dy = p2.
y() - p1.
y();
68 if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
70 if ( fabs( dx ) >= fabs( dy ) )
72 double dev = fabs( dy ) / fabs( dx );
79 double dev = fabs( dx ) / fabs( dy );
97 std::array<Direction, 5> dirs;
104 while ( current != end )
114 else if ( dir != dirs[idx - 1] )
124 ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
125 std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
131 int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
132 for (
int i = 1; i < 4; ++i )
134 if ( dirs[i] != oriented[( idx + i ) % 4] )
165 const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( mGeometry );
170 if ( vertexCount < 4 )
172 else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
176 std::array<Direction, 4> dirs;
177 std::tie( found4Dirs, dirs ) =
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
191 QVector<QgsLineString *> linesToProcess;
193 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
196 linesToProcess.reserve( multiCurve->
partCount() );
197 for (
int i = 0; i < multiCurve->
partCount(); ++i )
199 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
203 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
206 linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
209 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() :
nullptr );
212 if ( !linesToProcess.empty() )
214 std::unique_ptr< QgsLineString > secondline;
215 for (
QgsLineString *line : std::as_const( linesToProcess ) )
217 QTransform transform = QTransform::fromTranslate( x, y );
219 secondline.reset( line->reversed() );
220 secondline->transform( transform );
222 line->append( secondline.get() );
223 line->addVertex( line->pointN( 0 ) );
229 multipolygon->addGeometry( polygon );
251 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
255 , d( polygon->pointDistanceToBoundary( x, y ) )
256 , max( d + h * M_SQRT2 )
271struct GreaterThanByMax
273 bool operator()(
const Cell *lhs,
const Cell *rhs )
const
275 return rhs->max > lhs->max;
279Cell *getCentroidCell(
const QgsPolygon *polygon )
287 for (
int i = 0, j = len - 1; i < len; j = i++ )
289 double aX = exterior->
xAt( i );
290 double aY = exterior->
yAt( i );
291 double bX = exterior->
xAt( j );
292 double bY = exterior->
yAt( j );
293 double f = aX * bY - bX * aY;
294 x += ( aX + bX ) * f;
295 y += ( aY + bY ) * f;
299 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
301 return new Cell( x / area, y / area, 0.0, polygon );
306 std::unique_ptr< QgsPolygon > segmentizedPoly;
307 const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( surface );
311 polygon = segmentizedPoly.get();
318 double cellSize = std::min( bounds.
width(), bounds.
height() );
323 double h = cellSize / 2.0;
324 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
331 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
336 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
339 std::unique_ptr< Cell > bboxCell(
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
342 if ( bboxCell->d > bestCell->d )
344 bestCell = std::move( bboxCell );
347 while ( !cellQueue.empty() )
350 std::unique_ptr< Cell > cell( cellQueue.top() );
352 Cell *currentCell = cell.get();
355 if ( currentCell->d > bestCell->d )
357 bestCell = std::move( cell );
361 if ( currentCell->max - bestCell->d <=
precision )
365 h = currentCell->h / 2.0;
366 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y - h, h, polygon ) );
367 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y - h, h, polygon ) );
368 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y + h, h, polygon ) );
369 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
372 distanceFromBoundary = bestCell->d;
374 return QgsPoint( bestCell->x, bestCell->y );
382 if ( distanceFromBoundary )
383 *distanceFromBoundary = std::numeric_limits<double>::max();
385 if ( !mGeometry || mGeometry->
isEmpty() )
391 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
393 int numGeom = gc->numGeometries();
396 for (
int i = 0; i < numGeom; ++i )
398 const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( gc->geometryN( i ) );
402 double dist = std::numeric_limits<double>::max();
404 if ( dist > maxDist )
414 if ( distanceFromBoundary )
415 *distanceFromBoundary = maxDist;
420 const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( mGeometry );
424 double dist = std::numeric_limits<double>::max();
429 if ( distanceFromBoundary )
430 *distanceFromBoundary = dist;
441 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
467 for (
int i = 0; i < numPoints; ++i )
469 if ( !isClosed && i == numPoints - 1 )
471 else if ( !isClosed && i == 0 )
480 a = ring->
pointN( numPoints - 1 );
483 if ( i == numPoints - 1 )
492 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
502 double lowerThreshold,
double upperThreshold )
511 double scale = 2.0 * std::min( p.
length(), q.
length() );
515 double dotProduct = p * q;
524 if ( dotProduct < -M_SQRT1_2 )
533 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
538 double minScore = std::numeric_limits<double>::max();
543 std::unique_ptr< QgsLineString > best( ring->
clone() );
545 QVector< QgsVector > motions;
546 motions.reserve( numPoints );
548 for (
int it = 0; it < iterations; ++it )
556 for (
int i = 0; i < numPoints; ++i )
558 if ( isClosed && i == numPoints - 1 )
559 motions << motions.at( 0 );
560 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
570 a = ring->
pointN( numPoints - 1 );
573 if ( i == numPoints - 1 )
578 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
585 for (
int i = 0; i < numPoints; ++i )
587 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
588 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
591 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
592 if ( newScore < minScore )
594 best.reset( ring->
clone() );
598 if ( minScore < tolerance )
604 return best.release();
610 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
614 geom = segmentizedCopy.get();
620 maxIterations, tolerance, lowerThreshold, upperThreshold );
629 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
633 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
649 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
650 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
652 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
654 int numGeom = gc->numGeometries();
655 QVector< QgsAbstractGeometry * > geometryList;
656 geometryList.reserve( numGeom );
657 for (
int i = 0; i < numGeom; ++i )
659 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
678 QVector< double > outX;
679 QVector< double > outY;
680 QVector< double > outZ;
681 QVector< double > outM;
682 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
685 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
686 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
687 bool withZ = ring->
is3D();
689 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
692 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
705 int extraNodesThisSegment = extraNodesPerSegment;
706 for (
int i = 0; i < nPoints - 1; ++i )
709 x2 = ring->
xAt( i + 1 );
711 y2 = ring->
yAt( i + 1 );
715 z2 = ring->
zAt( i + 1 );
720 m2 = ring->
mAt( i + 1 );
730 if ( extraNodesPerSegment < 0 )
733 extraNodesThisSegment = std::floor( std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) / distance );
734 if ( extraNodesThisSegment >= 1 )
735 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
738 for (
int j = 0; j < extraNodesThisSegment; ++j )
740 double delta = multiplier * ( j + 1 );
741 xOut = x1 + delta * ( x2 - x1 );
742 yOut = y1 + delta * ( y2 - y1 );
744 zOut = z1 + delta * ( z2 - z1 );
746 mOut = m1 + delta * ( m2 - m1 );
756 outX << ring->
xAt( nPoints - 1 );
757 outY << ring->
yAt( nPoints - 1 );
759 outZ << ring->
zAt( nPoints - 1 );
761 outM << ring->
mAt( nPoints - 1 );
769 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
773 geom = segmentizedCopy.get();
787 extraNodesPerSegment, distance ) );
791 extraNodesPerSegment, distance ) );
811 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
813 int numGeom = gc->numGeometries();
814 QVector< QgsAbstractGeometry * > geometryList;
815 geometryList.reserve( numGeom );
816 for (
int i = 0; i < numGeom; ++i )
818 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
847 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
849 int numGeom = gc->numGeometries();
850 QVector< QgsAbstractGeometry * > geometryList;
851 geometryList.reserve( numGeom );
852 for (
int i = 0; i < numGeom; ++i )
879 "line_segment_dist_comparer",
880 "AB must not be collinear with the origin." );
882 "line_segment_dist_comparer",
883 "CD must not be collinear with the origin." );
897 if ( ab.
end() == cd.
end() || oad != oab )
907 if ( cdb == 0 && cda == 0 )
909 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
911 else if ( cda == cdb || cda == 0 || cdb == 0 )
914 return cdo == cda || cdo == cdb;
930 const bool aIsLeft = a.
x() < mVertex.x();
931 const bool bIsLeft = b.
x() < mVertex.x();
932 if ( aIsLeft != bIsLeft )
937 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
939 return b.
y() < a.
y();
943 return a.
y() < b.
y();
975 const int abo =
segment.pointLeftOfLine( origin );
982 const double distA = ao * direction;
983 const double distB = ( origin -
segment.end() ) * direction;
985 if ( distA > 0 && distB > 0 )
991 if ( ( distA > 0 ) != ( distB > 0 ) )
992 intersectPoint = origin;
993 else if ( distA > distB )
994 intersectPoint =
segment.start();
996 intersectPoint =
segment.end();
1004 if ( u < 0.0 || 1.0 < u )
1011 intersectPoint = origin + direction * t;
1020 if ( radius1 > radius2 )
1027 QVector<QgsPointXY> points;
1049 std::vector< std::unique_ptr<QgsLineString > > linesToProcess;
1051 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
1054 for (
int i = 0; i < multiCurve->
partCount(); ++i )
1063 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
1070 if ( linesToProcess.empty() )
1073 g.mLastError = QStringLiteral(
"Input geometry was not a curve type geometry" );
1077 QVector<QgsGeometry> bufferedLines;
1078 bufferedLines.reserve( linesToProcess.size() );
1080 for ( std::unique_ptr< QgsLineString > &line : linesToProcess )
1082 QVector<QgsGeometry> parts;
1084 double prevRadius = 0;
1087 std::unique_ptr< double[] > widths = widthFunction( line.get() ) ;
1092 double thisRadius = widths[ i ] / 2.0;
1093 if ( thisRadius > 0 )
1097 QgsCircle circ( thisPoint, thisRadius );
1099 parts << thisCircle;
1108 if ( prevRadius > 0 || thisRadius > 0 )
1110 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1111 if ( !points.empty() )
1116 int beforeVertex = 0;
1117 int afterVertex = 0;
1119 double sqrDistPrev = 0;
1120 for (
int j = 0; j < points.count(); ++j )
1124 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1127 points.append( points.at( 0 ) );
1129 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
1131 if ( poly->area() > 0 )
1136 prevPoint = thisPoint;
1137 prevRadius = thisRadius;
1138 prevCircle = thisCircle;
1153 start = std::fabs( start );
1154 end = std::fabs( end );
1160 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1162 widths[line->nCoordinates() - 1] = end;
1164 double lineLength = line->length();
1165 double currentLength = 0;
1166 QgsPoint prevPoint = line->pointN( 0 );
1167 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1169 QgsPoint point = line->pointN( i );
1170 double segmentLength = point.
distance( prevPoint );
1171 currentLength += segmentLength;
1172 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1173 double delta = lengthFraction * ( end - start );
1174 widths[i] = start + delta;
1188 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1189 for (
int i = 0; i < line->nCoordinates(); ++i )
1191 widths[ i ] = line->mAt( i );
1200 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1202 if ( polygon.
type() != Qgis::GeometryType::Polygon || count == 0 )
1203 return QVector< QgsPointXY >();
1215 return QVector< QgsPointXY >();
1223 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->
geometryN( i )->
segmentize() ) );
1230 if (
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( polygon.
constGet() ) )
1236 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( polygon.
constGet()->
segmentize() ) );
1242 return QVector< QgsPointXY >();
1244 const QVector<float> triangleData = t.
data();
1245 if ( triangleData.empty() )
1246 return QVector< QgsPointXY >();
1249 std::vector< double > cumulativeAreas;
1251 double totalArea = 0;
1252 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1255 return QVector< QgsPointXY >();
1257 const float aX = *it++;
1259 const float aY = -( *it++ );
1260 const float bX = *it++;
1262 const float bY = -( *it++ );
1263 const float cX = *it++;
1265 const float cY = -( *it++ );
1269 cumulativeAreas.emplace_back( totalArea );
1272 std::random_device rd;
1273 std::mt19937 mt( seed == 0 ? rd() : seed );
1274 std::uniform_real_distribution<> uniformDist( 0, 1 );
1277 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1280 const double target = random * totalArea;
1281 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1286 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1291 QVector<QgsPointXY> result;
1292 result.reserve( count );
1294 for (
int i = 0; i < count; )
1297 return QVector< QgsPointXY >();
1299 const double triangleIndexRnd = uniformDist( mt );
1301 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1304 const double weightB = uniformDist( mt );
1305 const double weightC = uniformDist( mt );
1310 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1311 const double aY = -triangleData.at( triangleIndex * 9 + 2 ) + bounds.
yMinimum();
1312 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1313 const double bY = -triangleData.at( triangleIndex * 9 + 5 ) + bounds.
yMinimum();
1314 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1315 const double cY = -triangleData.at( triangleIndex * 9 + 8 ) + bounds.
yMinimum();
1319 if ( acceptPoint( candidate ) )
1325 else if ( maxTriesPerPoint != 0 )
1329 if ( tries == maxTriesPerPoint )
1342 double pointSpacingAngleTolerance )
1348 std::unique_ptr< QgsCircularString > out;
1349 out.reset( qgsgeometry_cast< QgsCircularString * >( curve )->clone() );
1354 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1355 const QgsCompoundCurve *in = qgsgeometry_cast< const QgsCompoundCurve * >( curve );
1356 for (
int i = 0; i < in->
nCurves(); i ++ )
1358 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1366 out->addCurve( qgsgeometry_cast< const QgsLineString * >( processed->simplifiedTypeRef() )->clone() );
1370 out->addCurve( processed.release() );
1378 const QgsLineString *lineString = qgsgeometry_cast< QgsLineString * >( curve );
1380 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1383 const unsigned int minQuadEdges = 2;
1396 out->addCurve( lineString->
clone() );
1402 QVector< int > edgesInArcs( numEdges + 1, 0 );
1406 double abX = b.x() - a.
x();
1407 double abY = b.y() - a.
y();
1409 double cbX = b.x() -
c.x();
1410 double cbY = b.y() -
c.y();
1412 double dot = ( abX * cbX + abY * cbY );
1413 double cross = ( abX * cbY - abY * cbX );
1415 double alpha = std::atan2( cross, dot );
1430 double centerX = 0.0;
1431 double centerY = 0.0;
1434 while ( i < numEdges - 2 )
1436 unsigned int arcEdges = 0;
1437 double numQuadrants = 0;
1440 bool foundArc =
false;
1442 a1 = lineString->
pointN( i );
1443 a2 = lineString->
pointN( i + 1 );
1444 a3 = lineString->
pointN( i + 2 );
1447 for ( j = i + 3; j < numEdges + 1; j++ )
1449 b = lineString->
pointN( j );
1456 for ( k = j - 1; k > j - 4; k-- )
1457 edgesInArcs[k] = currentArc;
1477 arcEdges = j - 1 - i;
1478 if ( first.
x() == b.x() && first.
y() == b.y() )
1493 numQuadrants = ( 4 *
angle ) / ( 2 * M_PI );
1496 if ( arcEdges < minQuadEdges * numQuadrants )
1499 for ( k = j - 1; k >= i; k-- )
1516 int edgeType = edgesInArcs[0];
1518 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1523 QVector< QgsPoint > points;
1524 for (
int j = start; j < end + 2; ++ j )
1526 points.append( lineString->
pointN( j ) );
1528 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1529 out->addCurve( straightSegment.release() );
1534 QVector< QgsPoint > points;
1535 points.append( lineString->
pointN( start ) );
1536 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1537 points.append( lineString->
pointN( end + 1 ) );
1538 std::unique_ptr< QgsCircularString > curvedSegment = std::make_unique< QgsCircularString >();
1539 curvedSegment->setPoints( points );
1540 out->addCurve( curvedSegment.release() );
1544 for (
int i = 1; i < numEdges; i++ )
1546 if ( edgeType != edgesInArcs[i] )
1549 addPointsToCurve( start, end, edgeType );
1551 edgeType = edgesInArcs[i];
1557 addPointsToCurve( start, end, edgeType );
1562 std::unique_ptr< QgsCircularString > res;
1563 res.reset( qgsgeometry_cast< const QgsCircularString * >( out->simplifiedTypeRef() )->clone() );
1577 return lineToCurve( qgsgeometry_cast< const QgsCurve * >( geom ), distanceTolerance, angleTolerance );
1582 const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( geom );
1583 std::unique_ptr< QgsCurvePolygon > result = std::make_unique< QgsCurvePolygon>();
1586 distanceTolerance, angleTolerance ).release() );
1590 distanceTolerance, angleTolerance ).release() );
1610 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1612 int numGeom = gc->numGeometries();
1613 QVector< QgsAbstractGeometry * > geometryList;
1614 geometryList.reserve( numGeom );
1615 for (
int i = 0; i < numGeom; ++i )
1638 area = std::numeric_limits<double>::max();
1640 width = std::numeric_limits<double>::max();
1641 height = std::numeric_limits<double>::max();
1647 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1658 double totalRotation = 0;
1659 while ( hull->nextVertex( vertexId, pt2 ) )
1662 double rotateAngle = 180.0 / M_PI * currentAngle;
1663 totalRotation += rotateAngle;
1665 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1666 t.rotate( rotateAngle );
1667 t.translate( -pt0.
x(), -pt0.
y() );
1669 hull->transform( t );
1672 double currentArea = bounds.
width() * bounds.
height();
1673 if ( currentArea < area )
1677 angle = totalRotation;
1678 width = bounds.
width();
1679 height = bounds.
height();
1688 if ( width > height )
1690 width = minRect.
height();
1691 height = minRect.
width();
1696 if (
angle > 180.0 )
1704 const int totalPoints = line->
numPoints();
1705 if ( totalPoints < 2 )
1708 const double *x = line->
xData();
1709 const double *y = line->
yData();
1711 double prevX = *x++;
1712 double prevY = *y++;
1714 QVector< double > outX;
1715 QVector< double > outY;
1716 const double totalLength = line->
length();
1718 const int maxRepetitions = std::ceil( totalLength / wavelength );
1719 if ( !strictWavelength )
1720 wavelength = totalLength / maxRepetitions;
1722 const int estimatedPoints = maxRepetitions * 2 + 2;
1723 outX.reserve( estimatedPoints );
1724 outY.reserve( estimatedPoints );
1725 outX.append( prevX );
1726 outY.append( prevY );
1728 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1730 for (
int i = 1; i < totalPoints; ++i )
1732 double thisX = *x++;
1733 double thisY = *y++;
1736 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1737 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1740 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1745 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1746 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1748 outX.append( outPointX );
1749 outY.append( outPointY );
1751 distanceToNextPointFromStartOfSegment += wavelength / 2;
1757 distanceToNextPointFromStartOfSegment -= segmentLength;
1760 outX.append( prevX );
1761 outY.append( prevY );
1763 return std::make_unique< QgsLineString >( outX, outY );
1767 const double minimumWavelength,
const double maximumWavelength,
1768 const double minimumAmplitude,
const double maximumAmplitude,
1769 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1771 const int totalPoints = line->
numPoints();
1772 if ( totalPoints < 2 )
1775 const double *x = line->
xData();
1776 const double *y = line->
yData();
1778 double prevX = *x++;
1779 double prevY = *y++;
1781 QVector< double > outX;
1782 QVector< double > outY;
1783 const double totalLength = line->
length();
1785 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1787 const int estimatedPoints = maxRepetitions * 2 + 2;
1788 outX.reserve( estimatedPoints );
1789 outY.reserve( estimatedPoints );
1790 outX.append( prevX );
1791 outY.append( prevY );
1793 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1794 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1795 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1798 for (
int i = 1; i < totalPoints; ++i )
1800 double thisX = *x++;
1801 double thisY = *y++;
1804 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1805 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1808 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1813 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1814 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1815 outX.append( outPointX );
1816 outY.append( outPointY );
1818 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1819 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1821 distanceToNextPointFromStartOfSegment += wavelength / 2;
1827 distanceToNextPointFromStartOfSegment -= segmentLength;
1830 outX.append( prevX );
1831 outY.append( prevY );
1833 return std::make_unique< QgsLineString >( outX, outY );
1838 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1842 geom = segmentizedCopy.get();
1853 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1856 wavelength, amplitude, strictWavelength ).release() );
1860 wavelength, amplitude, strictWavelength ).release() );
1867std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1869 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1873 geom = segmentizedCopy.get();
1884 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1887 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
1891 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
1914 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1916 int numGeom = gc->numGeometries();
1917 QVector< QgsAbstractGeometry * > geometryList;
1918 geometryList.reserve( numGeom );
1919 for (
int i = 0; i < numGeom; ++i )
1921 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
1939 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
1948 std::random_device rd;
1949 std::mt19937 mt( seed == 0 ? rd() : seed );
1950 std::uniform_real_distribution<> uniformDist( 0, 1 );
1957 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1959 int numGeom = gc->numGeometries();
1960 QVector< QgsAbstractGeometry * > geometryList;
1961 geometryList.reserve( numGeom );
1962 for (
int i = 0; i < numGeom; ++i )
1964 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
1982 const int totalPoints = line->
numPoints();
1983 if ( totalPoints < 2 )
1986 const double *x = line->
xData();
1987 const double *y = line->
yData();
1989 double prevX = *x++;
1990 double prevY = *y++;
1992 QVector< double > outX;
1993 QVector< double > outY;
1994 const double totalLength = line->
length();
1996 const int maxRepetitions = std::ceil( totalLength / wavelength );
1997 if ( !strictWavelength )
1998 wavelength = totalLength / maxRepetitions;
2000 const int estimatedPoints = maxRepetitions * 4 + 2;
2001 outX.reserve( estimatedPoints );
2002 outY.reserve( estimatedPoints );
2003 outX.append( prevX );
2004 outY.append( prevY );
2007 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2008 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2010 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2013 for (
int i = 1; i < totalPoints; ++i )
2015 double thisX = *x++;
2016 double thisY = *y++;
2019 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2020 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2023 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2028 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2029 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2030 outX.append( pX + side * amplitude * sinAngle );
2031 outY.append( pY + side * amplitude * cosAngle );
2032 outX.append( pX - side * amplitude * sinAngle );
2033 outY.append( pY - side * amplitude * cosAngle );
2035 distanceToNextPointFromStartOfSegment += wavelength / 2;
2041 distanceToNextPointFromStartOfSegment -= segmentLength;
2047 outX.append( prevX );
2048 outY.append( prevY );
2050 return std::make_unique< QgsLineString >( outX, outY );
2054 const double minimumWavelength,
const double maximumWavelength,
2055 const double minimumAmplitude,
const double maximumAmplitude,
2056 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2058 const int totalPoints = line->
numPoints();
2059 if ( totalPoints < 2 )
2062 const double *x = line->
xData();
2063 const double *y = line->
yData();
2065 double prevX = *x++;
2066 double prevY = *y++;
2068 QVector< double > outX;
2069 QVector< double > outY;
2070 const double totalLength = line->
length();
2072 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2074 const int estimatedPoints = maxRepetitions * 4 + 2;
2075 outX.reserve( estimatedPoints );
2076 outY.reserve( estimatedPoints );
2077 outX.append( prevX );
2078 outY.append( prevY );
2080 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2083 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2084 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2086 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2087 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2090 for (
int i = 1; i < totalPoints; ++i )
2092 double thisX = *x++;
2093 double thisY = *y++;
2096 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2097 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2100 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2105 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2106 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2107 outX.append( pX + side * amplitude * sinAngle );
2108 outY.append( pY + side * amplitude * cosAngle );
2110 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2111 outX.append( pX - side * amplitude * sinAngle );
2112 outY.append( pY - side * amplitude * cosAngle );
2114 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2115 distanceToNextPointFromStartOfSegment += wavelength / 2;
2121 distanceToNextPointFromStartOfSegment -= segmentLength;
2124 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2125 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2126 outX.append( prevX );
2127 outY.append( prevY );
2129 return std::make_unique< QgsLineString >( outX, outY );
2134 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2138 geom = segmentizedCopy.get();
2149 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2152 wavelength, amplitude, strictWavelength ).release() );
2156 wavelength, amplitude, strictWavelength ).release() );
2163std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2165 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2169 geom = segmentizedCopy.get();
2180 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2183 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2187 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2210 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2212 int numGeom = gc->numGeometries();
2213 QVector< QgsAbstractGeometry * > geometryList;
2214 geometryList.reserve( numGeom );
2215 for (
int i = 0; i < numGeom; ++i )
2217 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2235 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2244 std::random_device rd;
2245 std::mt19937 mt( seed == 0 ? rd() : seed );
2246 std::uniform_real_distribution<> uniformDist( 0, 1 );
2253 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2255 int numGeom = gc->numGeometries();
2256 QVector< QgsAbstractGeometry * > geometryList;
2257 geometryList.reserve( numGeom );
2258 for (
int i = 0; i < numGeom; ++i )
2260 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2278 const int totalPoints = line->
numPoints();
2279 if ( totalPoints < 2 )
2282 const double *x = line->
xData();
2283 const double *y = line->
yData();
2285 double prevX = *x++;
2286 double prevY = *y++;
2288 const double totalLength = line->
length();
2290 const int maxRepetitions = std::ceil( totalLength / wavelength );
2291 if ( !strictWavelength )
2292 wavelength = totalLength / maxRepetitions;
2294 const int segments = 10;
2298 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2299 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2300 bool isFirstPart =
true;
2302 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2303 int bufferIndex = 1;
2304 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2306 double segmentAngleRadians = 0;
2307 double remainingDistance = totalLength;
2308 double totalCoveredDistance = 0;
2310 for (
int i = 1; i < totalPoints; ++i )
2312 double thisX = *x++;
2313 double thisY = *y++;
2316 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2317 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2320 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2323 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2325 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2326 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2328 if ( bufferIndex == 0 )
2330 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2331 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2333 distanceToNextPointFromStartOfSegment += wavelength / 4;
2335 else if ( bufferIndex == 1 && isFirstPart )
2337 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2338 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2339 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2340 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2342 distanceToNextPointFromStartOfSegment += wavelength / 8;
2344 else if ( bufferIndex == 1 )
2346 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2347 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2348 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2349 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2351 distanceToNextPointFromStartOfSegment += wavelength / 4;
2353 else if ( bufferIndex == 2 )
2355 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2356 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2360 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2361 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2362 isFirstPart =
false;
2367 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2368 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2369 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2371 out->append( bezier.get() );
2374 xOutBuffer[0] = xOutBuffer[3];
2375 yOutBuffer[0] = yOutBuffer[3];
2378 distanceToNextPointFromStartOfSegment += wavelength / 4;
2381 totalCoveredDistance += segmentLength;
2384 distanceToNextPointFromStartOfSegment -= segmentLength;
2387 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2388 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2389 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2390 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2393 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2394 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2397 out->append( bezier.get() );
2403 const double minimumWavelength,
const double maximumWavelength,
2404 const double minimumAmplitude,
const double maximumAmplitude,
2405 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2407 const int totalPoints = line->
numPoints();
2408 if ( totalPoints < 2 )
2411 const double *x = line->
xData();
2412 const double *y = line->
yData();
2414 double prevX = *x++;
2415 double prevY = *y++;
2417 const double totalLength = line->
length();
2419 const int segments = 10;
2423 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2424 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2425 bool isFirstPart =
true;
2427 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2428 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2430 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2431 int bufferIndex = 1;
2432 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2434 double segmentAngleRadians = 0;
2436 double remainingDistance = totalLength;
2437 double totalCoveredDistance = 0;
2439 for (
int i = 1; i < totalPoints; ++i )
2441 double thisX = *x++;
2442 double thisY = *y++;
2445 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2446 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2449 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2452 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2454 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2455 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2457 if ( bufferIndex == 0 )
2459 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2460 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2462 distanceToNextPointFromStartOfSegment += wavelength / 4;
2464 else if ( bufferIndex == 1 && isFirstPart )
2466 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2467 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2468 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2469 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2471 distanceToNextPointFromStartOfSegment += wavelength / 8;
2473 else if ( bufferIndex == 1 )
2475 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2476 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2477 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2478 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2480 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2481 distanceToNextPointFromStartOfSegment += wavelength / 4;
2483 else if ( bufferIndex == 2 )
2485 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2486 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2490 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2491 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2492 isFirstPart =
false;
2497 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2498 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2499 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2501 out->append( bezier.get() );
2504 xOutBuffer[0] = xOutBuffer[3];
2505 yOutBuffer[0] = yOutBuffer[3];
2509 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2511 distanceToNextPointFromStartOfSegment += wavelength / 4;
2514 totalCoveredDistance += segmentLength;
2518 distanceToNextPointFromStartOfSegment -= segmentLength;
2521 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2522 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2523 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2524 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2526 if ( out->isEmpty() )
2530 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2533 out->append( bezier.get() );
2538 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2539 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2542 out->append( bezier.get() );
2550 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2554 geom = segmentizedCopy.get();
2565 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2568 wavelength, amplitude, strictWavelength ).release() );
2572 wavelength, amplitude, strictWavelength ).release() );
2579std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2581 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2585 geom = segmentizedCopy.get();
2596 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2599 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2603 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2626 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2628 int numGeom = gc->numGeometries();
2629 QVector< QgsAbstractGeometry * > geometryList;
2630 geometryList.reserve( numGeom );
2631 for (
int i = 0; i < numGeom; ++i )
2633 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2651 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2660 std::random_device rd;
2661 std::mt19937 mt( seed == 0 ? rd() : seed );
2662 std::uniform_real_distribution<> uniformDist( 0, 1 );
2669 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2671 int numGeom = gc->numGeometries();
2672 QVector< QgsAbstractGeometry * > geometryList;
2673 geometryList.reserve( numGeom );
2674 for (
int i = 0; i < numGeom; ++i )
2676 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2693 const QVector< double> &pattern,
2697 double patternOffset )
2699 const int totalPoints = line->
numPoints();
2700 if ( totalPoints < 2 )
2703 const int patternSize = pattern.size();
2705 const double *x = line->
xData();
2706 const double *y = line->
yData();
2708 double prevX = *x++;
2709 double prevY = *y++;
2711 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2713 QVector< double > outX;
2714 QVector< double > outY;
2715 const double totalLength = line->
length();
2717 double patternLength = 0;
2718 double patternDashLength = 0;
2719 double patternGapLength = 0;
2720 for (
int i = 0; i < pattern.size(); ++i )
2722 patternLength += pattern.at( i );
2724 patternDashLength += pattern.at( i );
2726 patternGapLength += pattern.at( i );
2729 double firstPatternLength = 0;
2730 double firstPatternDashLength = 0;
2731 double firstPatternGapLength = 0;
2732 switch ( startRule )
2736 firstPatternLength = patternLength;
2737 firstPatternDashLength = patternDashLength;
2738 firstPatternGapLength = patternGapLength;
2741 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2742 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2743 firstPatternGapLength = patternGapLength;
2746 firstPatternLength = pattern.at( patternSize - 1 );
2747 firstPatternDashLength = 0;
2748 firstPatternGapLength = pattern.at( patternSize - 1 );
2751 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2752 firstPatternDashLength = 0;
2753 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2757 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2759 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2760 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2761 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2765 lastPatternLength = 0;
2766 lastPatternDashLength = 0;
2767 lastPatternGapLength = 0;
2770 lastPatternLength -= pattern.at( patternSize - 1 );
2771 lastPatternGapLength -= pattern.at( patternSize - 1 );
2774 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2775 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2776 lastPatternGapLength -= pattern.at( patternSize - 1 );
2779 lastPatternGapLength = patternGapLength;
2782 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2783 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2787 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2788 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2790 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2791 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2792 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2794 double dashLengthScalingFactor = 1;
2795 double gapLengthScalingFactor = 1;
2799 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2801 switch ( adjustment )
2804 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2805 gapLengthScalingFactor = dashLengthScalingFactor;
2808 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2811 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2816 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2817 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2819 const int maxPatterns = middlePatternRepetitions + 2;
2820 result->reserve( maxPatterns );
2822 int patternIndex = 0;
2823 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2825 switch ( startRule )
2831 distanceToNextPointFromStartOfSegment *= 0.5;
2834 patternIndex = patternSize - 1;
2836 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2839 patternIndex = patternSize - 1;
2841 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2845 const double adjustedOffset = fmod( patternOffset, patternLength );
2846 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
2850 double remainingOffset = scaledOffset;
2851 while ( remainingOffset > 0 )
2853 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
2855 distanceToNextPointFromStartOfSegment -= remainingOffset;
2859 remainingOffset -= distanceToNextPointFromStartOfSegment;
2862 if ( patternIndex == patternSize )
2865 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
2871 outX.append( prevX );
2872 outY.append( prevY );
2875 for (
int i = 1; i < totalPoints; ++i )
2877 double thisX = *x++;
2878 double thisY = *y++;
2880 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2881 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2884 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2899 if ( patternIndex >= patternSize )
2902 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
2907 outX.append( thisX );
2908 outY.append( thisY );
2913 distanceToNextPointFromStartOfSegment -= segmentLength;
2918 outX.append( prevX );
2919 outY.append( prevY );
2927 const QVector<double> &pattern,
2931 double patternOffset )
2933 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2937 geom = segmentizedCopy.get();
2948 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2951 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
2952 result->addGeometry( exteriorParts->geometryN( i )->clone() );
2957 for (
int j = 0; j < ringParts->numGeometries(); ++j )
2958 result->addGeometry( ringParts->geometryN( j )->clone() );
2967 if ( pattern.size() < 2 )
2971 if ( !mGeometry || mGeometry->
isEmpty() )
2981 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2983 int numGeom = gc->numGeometries();
2984 QVector< QgsAbstractGeometry * > geometryList;
2985 geometryList.reserve( numGeom );
2986 for (
int i = 0; i < numGeom; ++i )
2988 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
2996 for (
int j = 0; j < collection->numGeometries(); ++j )
2998 first.
addPart( collection->geometryN( j )->clone() );
DashPatternSizeAdjustment
Dash pattern size adjustment options.
@ ScaleDashOnly
Only dash lengths are adjusted.
@ ScaleBothDashAndGap
Both the dash and gap lengths are adjusted equally.
@ ScaleGapOnly
Only gap lengths are adjusted.
DashPatternLineEndingRule
Dash pattern line ending rules.
@ HalfDash
Start or finish the pattern with a half length dash.
@ HalfGap
Start or finish the pattern with a half length gap.
@ FullGap
Start or finish the pattern with a full gap.
@ FullDash
Start or finish the pattern with a full dash.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CompoundCurve
CompoundCurve.
@ CircularString
CircularString.
The vertex_iterator class provides STL-style iterator for vertices.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
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.
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex 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 ...
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.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
Qgis::GeometryOperationResult addPart(const QVector< QgsPointXY > &points, Qgis::GeometryType geomType=Qgis::GeometryType::Unknown)
Adds a new part to a the geometry.
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false)
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries, const QgsGeometryParameters ¶meters=QgsGeometryParameters())
Compute the unary union on a list of geometries.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
QgsGeometry triangularWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized triangular waves along the boundary of the geometry, with the specified wavelen...
QgsGeometry triangularWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs triangular waves along the boundary of the geometry, with the specified wavelength and amp...
QgsInternalGeometryEngine(const QgsGeometry &geometry)
The caller is responsible that the geometry is available and unchanged for the whole lifetime of this...
QgsGeometry roundWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs rounded (sine-like) waves along the boundary of the geometry, with the specified wavelengt...
QgsGeometry poleOfInaccessibility(double precision, double *distanceFromBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
QgsGeometry squareWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs square waves along the boundary of the geometry, with the specified wavelength and amplitu...
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer using the m-values from a (multi)line geometry.
QgsGeometry extrude(double x, double y) const
Will extrude a line or (segmentized) curve by a given offset and return a polygon representation of i...
QgsGeometry roundWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized rounded (sine-like) waves along the boundary of the geometry,...
QgsGeometry orthogonalize(double tolerance=1.0E-8, int maxIterations=1000, double angleThreshold=15.0) const
Attempts to orthogonalize a line or polygon geometry by shifting vertices to make the geometries angl...
QgsGeometry variableWidthBuffer(int segments, const std::function< std::unique_ptr< double[] >(const QgsLineString *line) > &widthFunction) const
Calculates a variable width buffer for a (multi)curve geometry.
QString lastError() const
Returns an error string referring to the last error encountered.
QgsGeometry orientedMinimumBoundingBox(double &area, double &angle, double &width, double &height) const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a tapered width buffer for a (multi)curve geometry.
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Densifies the geometry by adding the specified number of extra nodes within each segment of the geome...
QgsGeometry applyDashPattern(const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternLineEndingRule endRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternSizeAdjustment adjustment=Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap, double patternOffset=0) const
Applies a dash pattern to a geometry, returning a MultiLineString geometry which is the input geometr...
static QVector< QgsPointXY > randomPointsInPolygon(const QgsGeometry &polygon, int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed=0, QgsFeedback *feedback=nullptr, int maxTriesPerPoint=0)
Returns a list of count random points generated inside a polygon geometry (if acceptPoint is specifie...
QgsGeometry squareWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized square waves along the boundary of the geometry, with the specified wavelength ...
QgsGeometry convertToCurves(double distanceTolerance, double angleTolerance) const
Attempts to convert a non-curved geometry into a curved geometry type (e.g.
bool isAxisParallelRectangle(double maximumDeviation, bool simpleRectanglesOnly=false) const
Returns true if the geometry is a polygon that is almost an axis-parallel rectangle.
Represents a single 2D line segment, consisting of a 2D start and end vertex only.
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 override
Returns the m value of the specified node in the line string.
void setXAt(int index, double x)
Sets the x-coordinate of the specified node in the line string.
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 override
Returns the z-coordinate of the specified node in the line string.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
Multi curve geometry collection.
Multi polygon geometry collection.
Multi surface geometry collection.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
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 Qgis::GeometryType geometryType(Qgis::WkbType type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static bool isCurvedType(Qgis::WkbType type) SIP_HOLDGIL
Returns true if the WKB type is a curved type or can contain curved geometries.
static Qgis::WkbType flatType(Qgis::WkbType 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.