41 : mGeometry( geometry.constGet() )
68 double dx = p2.
x() - p1.
x();
69 double dy = p2.
y() - p1.
y();
70 if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
72 if ( fabs( dx ) >= fabs( dy ) )
74 double dev = fabs( dy ) / fabs( dx );
81 double dev = fabs( dx ) / fabs( dy );
99 std::array<Direction, 5> dirs;
106 while ( current != end )
116 else if ( dir != dirs[idx - 1] )
126 ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
127 std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
133 int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
134 for (
int i = 1; i < 4; ++i )
136 if ( dirs[i] != oriented[( idx + i ) % 4] )
167 const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( mGeometry );
172 if ( vertexCount < 4 )
174 else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
178 std::array<Direction, 4> dirs;
179 std::tie( found4Dirs, dirs ) =
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
193 QVector<QgsLineString *> linesToProcess;
195 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
198 linesToProcess.reserve( multiCurve->
partCount() );
199 for (
int i = 0; i < multiCurve->
partCount(); ++i )
201 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
205 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
208 linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
211 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() : nullptr );
214 if ( !linesToProcess.empty() )
216 std::unique_ptr< QgsLineString > secondline;
217 for (
QgsLineString *line : std::as_const( linesToProcess ) )
219 QTransform transform = QTransform::fromTranslate( x, y );
221 secondline.reset( line->reversed() );
222 secondline->transform( transform );
224 line->append( secondline.get() );
225 line->addVertex( line->pointN( 0 ) );
228 polygon->setExteriorRing( line );
231 multipolygon->addGeometry( polygon );
253 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
257 , d( polygon->pointDistanceToBoundary( x, y ) )
258 , max( d + h * M_SQRT2 )
273struct GreaterThanByMax
275 bool operator()(
const Cell *lhs,
const Cell *rhs )
const
277 return rhs->max > lhs->max;
281Cell *getCentroidCell(
const QgsPolygon *polygon )
289 for (
int i = 0, j = len - 1; i < len; j = i++ )
291 double aX = exterior->
xAt( i );
292 double aY = exterior->
yAt( i );
293 double bX = exterior->
xAt( j );
294 double bY = exterior->
yAt( j );
295 double f = aX * bY - bX * aY;
296 x += ( aX + bX ) * f;
297 y += ( aY + bY ) * f;
301 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
303 return new Cell( x / area, y / area, 0.0, polygon );
308 std::unique_ptr< QgsPolygon > segmentizedPoly;
309 const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( surface );
313 polygon = segmentizedPoly.get();
320 double cellSize = std::min( bounds.
width(), bounds.
height() );
325 double h = cellSize / 2.0;
326 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
333 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
338 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
341 std::unique_ptr< Cell > bboxCell(
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
344 if ( bboxCell->d > bestCell->d )
346 bestCell = std::move( bboxCell );
349 while ( !cellQueue.empty() )
352 std::unique_ptr< Cell > cell( cellQueue.top() );
354 Cell *currentCell = cell.get();
357 if ( currentCell->d > bestCell->d )
359 bestCell = std::move( cell );
363 if ( currentCell->max - bestCell->d <=
precision )
367 h = currentCell->h / 2.0;
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 ) );
371 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
374 distanceFromBoundary = bestCell->d;
376 return QgsPoint( bestCell->x, bestCell->y );
384 if ( distanceFromBoundary )
385 *distanceFromBoundary = std::numeric_limits<double>::max();
387 if ( !mGeometry || mGeometry->
isEmpty() )
393 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
395 int numGeom = gc->numGeometries();
398 for (
int i = 0; i < numGeom; ++i )
400 const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( gc->geometryN( i ) );
404 double dist = std::numeric_limits<double>::max();
406 if ( dist > maxDist )
416 if ( distanceFromBoundary )
417 *distanceFromBoundary = maxDist;
422 const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( mGeometry );
426 double dist = std::numeric_limits<double>::max();
431 if ( distanceFromBoundary )
432 *distanceFromBoundary = dist;
443 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
469 for (
int i = 0; i < numPoints; ++i )
471 if ( !isClosed && i == numPoints - 1 )
473 else if ( !isClosed && i == 0 )
482 a = ring->
pointN( numPoints - 1 );
485 if ( i == numPoints - 1 )
494 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
504 double lowerThreshold,
double upperThreshold )
513 double scale = 2.0 * std::min( p.
length(), q.
length() );
517 double dotProduct = p * q;
526 if ( dotProduct < -M_SQRT1_2 )
535 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
540 double minScore = std::numeric_limits<double>::max();
545 std::unique_ptr< QgsLineString > best( ring->
clone() );
547 QVector< QgsVector > motions;
548 motions.reserve( numPoints );
550 for (
int it = 0; it < iterations; ++it )
558 for (
int i = 0; i < numPoints; ++i )
560 if ( isClosed && i == numPoints - 1 )
561 motions << motions.at( 0 );
562 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
572 a = ring->
pointN( numPoints - 1 );
575 if ( i == numPoints - 1 )
580 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
587 for (
int i = 0; i < numPoints; ++i )
589 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
590 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
593 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
594 if ( newScore < minScore )
596 best.reset( ring->
clone() );
600 if ( minScore < tolerance )
606 return best.release();
612 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
616 geom = segmentizedCopy.get();
622 maxIterations, tolerance, lowerThreshold, upperThreshold );
631 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
635 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
651 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
652 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
654 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
656 int numGeom = gc->numGeometries();
657 QVector< QgsAbstractGeometry * > geometryList;
658 geometryList.reserve( numGeom );
659 for (
int i = 0; i < numGeom; ++i )
661 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
680 QVector< double > outX;
681 QVector< double > outY;
682 QVector< double > outZ;
683 QVector< double > outM;
684 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
687 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
688 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
689 bool withZ = ring->
is3D();
691 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
694 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
707 int extraNodesThisSegment = extraNodesPerSegment;
708 for (
int i = 0; i < nPoints - 1; ++i )
711 x2 = ring->
xAt( i + 1 );
713 y2 = ring->
yAt( i + 1 );
717 z2 = ring->
zAt( i + 1 );
722 m2 = ring->
mAt( i + 1 );
732 if ( extraNodesPerSegment < 0 )
736 if ( extraNodesThisSegment >= 1 )
737 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
740 for (
int j = 0; j < extraNodesThisSegment; ++j )
742 double delta = multiplier * ( j + 1 );
743 xOut = x1 + delta * ( x2 - x1 );
744 yOut = y1 + delta * ( y2 - y1 );
746 zOut = z1 + delta * ( z2 - z1 );
748 mOut = m1 + delta * ( m2 - m1 );
758 outX << ring->
xAt( nPoints - 1 );
759 outY << ring->
yAt( nPoints - 1 );
761 outZ << ring->
zAt( nPoints - 1 );
763 outM << ring->
mAt( nPoints - 1 );
771 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
775 geom = segmentizedCopy.get();
789 extraNodesPerSegment, distance ) );
793 extraNodesPerSegment, distance ) );
813 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
815 int numGeom = gc->numGeometries();
816 QVector< QgsAbstractGeometry * > geometryList;
817 geometryList.reserve( numGeom );
818 for (
int i = 0; i < numGeom; ++i )
820 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
849 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
851 int numGeom = gc->numGeometries();
852 QVector< QgsAbstractGeometry * > geometryList;
853 geometryList.reserve( numGeom );
854 for (
int i = 0; i < numGeom; ++i )
881 "line_segment_dist_comparer",
882 "AB must not be collinear with the origin." );
884 "line_segment_dist_comparer",
885 "CD must not be collinear with the origin." );
902 if ( ab.
end() == cd.
end() || oad != oab )
912 if ( cdb == 0 && cda == 0 )
914 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
916 else if ( cda == cdb || cda == 0 || cdb == 0 )
919 return cdo == cda || cdo == cdb;
935 const bool aIsLeft = a.
x() < mVertex.x();
936 const bool bIsLeft = b.
x() < mVertex.x();
937 if ( aIsLeft != bIsLeft )
942 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
944 return b.
y() < a.
y();
948 return a.
y() < b.
y();
980 const int abo =
segment.pointLeftOfLine( origin );
987 const double distA = ao * direction;
988 const double distB = ( origin -
segment.end() ) * direction;
990 if ( distA > 0 && distB > 0 )
996 if ( ( distA > 0 ) != ( distB > 0 ) )
997 intersectPoint = origin;
998 else if ( distA > distB )
999 intersectPoint =
segment.start();
1001 intersectPoint =
segment.end();
1009 if ( u < 0.0 || 1.0 < u )
1016 intersectPoint = origin + direction * t;
1025 if ( radius1 > radius2 )
1032 QVector<QgsPointXY> points;
1054 std::vector< std::unique_ptr<QgsLineString > > temporarySegmentizedLines;
1055 std::vector< const QgsLineString * > linesToProcess;
1058 if (
const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( simplifiedGeom ) )
1060 for (
int i = 0; i < multiCurve->partCount(); ++i )
1062 if (
const QgsCurve *curvePart = qgsgeometry_cast< const QgsCurve * >( multiCurve->geometryN( i ) ) )
1068 if (
const QgsLineString *lineString = qgsgeometry_cast< const QgsLineString * >( part ) )
1070 linesToProcess.emplace_back( lineString );
1074 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( part->
segmentize() ) );
1075 linesToProcess.emplace_back( segmentizedCurve.get() );
1076 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1081 else if (
const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( simplifiedGeom ) )
1083 if ( curve->nCoordinates() > 0 )
1085 if (
const QgsLineString *lineString = qgsgeometry_cast< const QgsLineString * >( curve ) )
1087 linesToProcess.emplace_back( lineString );
1091 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( curve->segmentize() ) );
1092 linesToProcess.emplace_back( segmentizedCurve.get() );
1093 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1098 if ( linesToProcess.empty() )
1101 g.mLastError = QStringLiteral(
"Input geometry was not a curve type geometry" );
1105 QVector<QgsGeometry> bufferedLines;
1106 bufferedLines.reserve( linesToProcess.size() );
1110 QVector<QgsGeometry> parts;
1112 double prevRadius = 0;
1115 std::unique_ptr< double[] > widths = widthFunction( line ) ;
1120 double thisRadius = widths[ i ] / 2.0;
1121 if ( thisRadius > 0 )
1125 QgsCircle circ( thisPoint, thisRadius );
1127 parts << thisCircle;
1136 if ( prevRadius > 0 || thisRadius > 0 )
1138 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1139 if ( !points.empty() )
1144 int beforeVertex = 0;
1145 int afterVertex = 0;
1147 double sqrDistPrev = 0;
1148 for (
int j = 0; j < points.count(); ++j )
1152 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1155 points.append( points.at( 0 ) );
1157 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
1159 if ( poly->area() > 0 )
1164 prevPoint = thisPoint;
1165 prevRadius = thisRadius;
1166 prevCircle = thisCircle;
1181 start = std::fabs( start );
1182 end = std::fabs( end );
1184 auto interpolateWidths = [ start, end ](
const QgsLineString * line )->std::unique_ptr<
double [] >
1188 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1190 widths[line->nCoordinates() - 1] = end;
1192 double lineLength = line->length();
1193 double currentLength = 0;
1194 QgsPoint prevPoint = line->pointN( 0 );
1195 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1197 QgsPoint point = line->pointN( i );
1198 double segmentLength = point.
distance( prevPoint );
1199 currentLength += segmentLength;
1200 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1201 double delta = lengthFraction * ( end - start );
1202 widths[i] = start + delta;
1214 auto widthByM = [](
const QgsLineString * line )->std::unique_ptr<
double [] >
1216 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1217 for (
int i = 0; i < line->nCoordinates(); ++i )
1219 widths[ i ] = line->mAt( i );
1228 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1235 if (
const QgsMultiSurface *ms = qgsgeometry_cast< const QgsMultiSurface * >( geometry ) )
1237 for (
int i = 0; i < ms->numGeometries(); ++i )
1240 return QVector< QgsPointXY >();
1242 if (
QgsPolygon *poly = qgsgeometry_cast< QgsPolygon * >( ms->geometryN( i ) ) )
1248 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->geometryN( i )->segmentize() ) );
1255 if (
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( geometry ) )
1261 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( geometry->
segmentize() ) );
1267 return QVector< QgsPointXY >();
1269 if ( !t.
error().isEmpty() )
1272 return QVector< QgsPointXY >();
1275 const QVector<float> triangleData = t.
data();
1276 if ( triangleData.empty() )
1277 return QVector< QgsPointXY >();
1280 std::vector< double > cumulativeAreas;
1282 double totalArea = 0;
1283 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1286 return QVector< QgsPointXY >();
1288 const float aX = *it++;
1289 const float aY = *it++;
1291 const float bX = *it++;
1292 const float bY = *it++;
1294 const float cX = *it++;
1295 const float cY = *it++;
1300 cumulativeAreas.emplace_back( totalArea );
1303 std::random_device rd;
1304 std::mt19937 mt( seed == 0 ? rd() : seed );
1305 std::uniform_real_distribution<> uniformDist( 0, 1 );
1308 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1311 const double target = random * totalArea;
1312 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1317 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1322 QVector<QgsPointXY> result;
1323 result.reserve( count );
1325 for (
int i = 0; i < count; )
1328 return QVector< QgsPointXY >();
1330 const double triangleIndexRnd = uniformDist( mt );
1332 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1335 const double weightB = uniformDist( mt );
1336 const double weightC = uniformDist( mt );
1341 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1342 const double aY = triangleData.at( triangleIndex * 9 + 1 ) + bounds.
yMinimum();
1343 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1344 const double bY = triangleData.at( triangleIndex * 9 + 4 ) + bounds.
yMinimum();
1345 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1346 const double cY = triangleData.at( triangleIndex * 9 + 7 ) + bounds.
yMinimum();
1350 if ( acceptPoint( candidate ) )
1356 else if ( maxTriesPerPoint != 0 )
1360 if ( tries == maxTriesPerPoint )
1371 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1375 std::unique_ptr<QgsAbstractGeometry> triangulation =
geos.constrainedDelaunayTriangulation( &error );
1376 if ( !triangulation || triangulation->isEmpty( ) )
1382 const QgsMultiPolygon *mp = qgsgeometry_cast< const QgsMultiPolygon * >( triangulation.get() );
1387 std::vector< double > cumulativeAreas;
1389 double totalArea = 0;
1390 std::vector< double > vertices(
static_cast< std::size_t
>( mp->
numGeometries() ) * 6 );
1391 double *vertexData = vertices.data();
1397 const QgsPolygon *part = qgsgeometry_cast< const QgsPolygon * >( *it );
1405 const double aX = exterior->
xAt( 0 );
1406 const double aY = exterior->
yAt( 0 );
1407 const double bX = exterior->
xAt( 1 );
1408 const double bY = exterior->
yAt( 1 );
1409 const double cX = exterior->
xAt( 2 );
1410 const double cY = exterior->
yAt( 2 );
1420 cumulativeAreas.emplace_back( totalArea );
1423 std::random_device rd;
1424 std::mt19937 mt( seed == 0 ? rd() : seed );
1425 std::uniform_real_distribution<> uniformDist( 0, 1 );
1428 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1431 const double target = random * totalArea;
1432 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1437 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1442 QVector<QgsPointXY> result;
1443 result.reserve( count );
1445 vertexData = vertices.data();
1446 for (
int i = 0; i < count; )
1449 return QVector< QgsPointXY >();
1451 const double triangleIndexRnd = uniformDist( mt );
1453 const std::size_t triangleIndex = selectRandomTriangle( triangleIndexRnd );
1456 const double weightB = uniformDist( mt );
1457 const double weightC = uniformDist( mt );
1462 const double aX = vertexData[ triangleIndex * 6 ];
1463 const double aY = vertexData[ triangleIndex * 6 + 1 ];
1464 const double bX = vertexData[ triangleIndex * 6 + 2 ];
1465 const double bY = vertexData[ triangleIndex * 6 + 3 ];
1466 const double cX = vertexData[ triangleIndex * 6 + 4 ];
1467 const double cY = vertexData[ triangleIndex * 6 + 5 ];
1472 if ( acceptPoint( candidate ) )
1478 else if ( maxTriesPerPoint != 0 )
1482 if ( tries == maxTriesPerPoint )
1493 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1496 return QVector< QgsPointXY >();
1499#if (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=11) || GEOS_VERSION_MAJOR>3
1509 double pointSpacingAngleTolerance )
1515 std::unique_ptr< QgsCircularString > out;
1516 out.reset( qgsgeometry_cast< QgsCircularString * >( curve )->clone() );
1521 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1522 const QgsCompoundCurve *in = qgsgeometry_cast< const QgsCompoundCurve * >( curve );
1523 for (
int i = 0; i < in->
nCurves(); i ++ )
1525 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1528 if (
const QgsCompoundCurve *processedCompoundCurve = qgsgeometry_cast< const QgsCompoundCurve *>( processed.get() ) )
1530 for (
int i = 0; i < processedCompoundCurve->nCurves(); ++i )
1532 out->addCurve( processedCompoundCurve->curveAt( i )->clone() );
1537 out->addCurve( processed.release() );
1545 const QgsLineString *lineString = qgsgeometry_cast< QgsLineString * >( curve );
1547 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1550 const unsigned int minQuadEdges = 2;
1563 out->addCurve( lineString->
clone() );
1569 QVector< int > edgesInArcs( numEdges + 1, 0 );
1573 double abX = b.x() - a.
x();
1574 double abY = b.y() - a.
y();
1576 double cbX = b.x() -
c.x();
1577 double cbY = b.y() -
c.y();
1579 double dot = ( abX * cbX + abY * cbY );
1580 double cross = ( abX * cbY - abY * cbX );
1582 double alpha = std::atan2( cross, dot );
1597 double centerX = 0.0;
1598 double centerY = 0.0;
1601 while ( i < numEdges - 2 )
1603 unsigned int arcEdges = 0;
1604 double numQuadrants = 0;
1607 bool foundArc =
false;
1609 a1 = lineString->
pointN( i );
1610 a2 = lineString->
pointN( i + 1 );
1611 a3 = lineString->
pointN( i + 2 );
1614 for ( j = i + 3; j < numEdges + 1; j++ )
1616 b = lineString->
pointN( j );
1623 for ( k = j - 1; k > j - 4; k-- )
1624 edgesInArcs[k] = currentArc;
1644 arcEdges = j - 1 - i;
1645 if ( first.
x() == b.x() && first.
y() == b.y() )
1653 angle = arcAngle( first,
QgsPoint( centerX, centerY ), b );
1659 angle = 2 * M_PI + angle;
1660 numQuadrants = ( 4 * angle ) / ( 2 * M_PI );
1663 if ( arcEdges < minQuadEdges * numQuadrants )
1666 for ( k = j - 1; k >= i; k-- )
1683 int edgeType = edgesInArcs[0];
1685 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1690 QVector< QgsPoint > points;
1691 for (
int j = start; j < end + 2; ++ j )
1693 points.append( lineString->
pointN( j ) );
1695 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1696 out->addCurve( straightSegment.release() );
1701 QVector< QgsPoint > points;
1702 points.append( lineString->
pointN( start ) );
1703 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1704 points.append( lineString->
pointN( end + 1 ) );
1705 std::unique_ptr< QgsCircularString > curvedSegment = std::make_unique< QgsCircularString >();
1706 curvedSegment->setPoints( points );
1707 out->addCurve( curvedSegment.release() );
1711 for (
int i = 1; i < numEdges; i++ )
1713 if ( edgeType != edgesInArcs[i] )
1716 addPointsToCurve( start, end, edgeType );
1718 edgeType = edgesInArcs[i];
1724 addPointsToCurve( start, end, edgeType );
1729 std::unique_ptr< QgsCircularString > res;
1730 res.reset( qgsgeometry_cast< const QgsCircularString * >( out->simplifiedTypeRef() )->clone() );
1744 return lineToCurve( qgsgeometry_cast< const QgsCurve * >( geom ), distanceTolerance, angleTolerance );
1749 const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( geom );
1750 std::unique_ptr< QgsCurvePolygon > result = std::make_unique< QgsCurvePolygon>();
1753 distanceTolerance, angleTolerance ).release() );
1757 distanceTolerance, angleTolerance ).release() );
1777 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1779 int numGeom = gc->numGeometries();
1780 QVector< QgsAbstractGeometry * > geometryList;
1781 geometryList.reserve( numGeom );
1782 for (
int i = 0; i < numGeom; ++i )
1805 area = std::numeric_limits<double>::max();
1807 width = std::numeric_limits<double>::max();
1808 height = std::numeric_limits<double>::max();
1814 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1825 double totalRotation = 0;
1826 while ( hull->nextVertex( vertexId, pt2 ) )
1829 double rotateAngle = 180.0 / M_PI * currentAngle;
1830 totalRotation += rotateAngle;
1832 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1833 t.rotate( rotateAngle );
1834 t.translate( -pt0.
x(), -pt0.
y() );
1836 hull->transform( t );
1839 double currentArea = bounds.
width() * bounds.
height();
1840 if ( currentArea < area )
1844 angle = totalRotation;
1845 width = bounds.
width();
1846 height = bounds.
height();
1855 if ( width > height )
1857 width = minRect.
height();
1858 height = minRect.
width();
1859 angle = angle + 90.0;
1863 if ( angle > 180.0 )
1864 angle = std::fmod( angle, 180.0 );
1871 const int totalPoints = line->
numPoints();
1872 if ( totalPoints < 2 )
1875 const double *x = line->
xData();
1876 const double *y = line->
yData();
1878 double prevX = *x++;
1879 double prevY = *y++;
1881 QVector< double > outX;
1882 QVector< double > outY;
1883 const double totalLength = line->
length();
1885 const int maxRepetitions = std::ceil( totalLength / wavelength );
1886 if ( !strictWavelength )
1887 wavelength = totalLength / maxRepetitions;
1889 const int estimatedPoints = maxRepetitions * 2 + 2;
1890 outX.reserve( estimatedPoints );
1891 outY.reserve( estimatedPoints );
1892 outX.append( prevX );
1893 outY.append( prevY );
1895 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1897 for (
int i = 1; i < totalPoints; ++i )
1899 double thisX = *x++;
1900 double thisY = *y++;
1904 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1907 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1912 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1913 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1915 outX.append( outPointX );
1916 outY.append( outPointY );
1918 distanceToNextPointFromStartOfSegment += wavelength / 2;
1924 distanceToNextPointFromStartOfSegment -= segmentLength;
1927 outX.append( prevX );
1928 outY.append( prevY );
1930 return std::make_unique< QgsLineString >( outX, outY );
1934 const double minimumWavelength,
const double maximumWavelength,
1935 const double minimumAmplitude,
const double maximumAmplitude,
1936 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1938 const int totalPoints = line->
numPoints();
1939 if ( totalPoints < 2 )
1942 const double *x = line->
xData();
1943 const double *y = line->
yData();
1945 double prevX = *x++;
1946 double prevY = *y++;
1948 QVector< double > outX;
1949 QVector< double > outY;
1950 const double totalLength = line->
length();
1952 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1954 const int estimatedPoints = maxRepetitions * 2 + 2;
1955 outX.reserve( estimatedPoints );
1956 outY.reserve( estimatedPoints );
1957 outX.append( prevX );
1958 outY.append( prevY );
1960 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1961 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1962 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1965 for (
int i = 1; i < totalPoints; ++i )
1967 double thisX = *x++;
1968 double thisY = *y++;
1972 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1975 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1980 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1981 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1982 outX.append( outPointX );
1983 outY.append( outPointY );
1985 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1986 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1988 distanceToNextPointFromStartOfSegment += wavelength / 2;
1994 distanceToNextPointFromStartOfSegment -= segmentLength;
1997 outX.append( prevX );
1998 outY.append( prevY );
2000 return std::make_unique< QgsLineString >( outX, outY );
2005 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2009 geom = segmentizedCopy.get();
2020 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2023 wavelength, amplitude, strictWavelength ).release() );
2027 wavelength, amplitude, strictWavelength ).release() );
2034std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2036 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2040 geom = segmentizedCopy.get();
2051 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2054 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2058 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2081 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2083 int numGeom = gc->numGeometries();
2084 QVector< QgsAbstractGeometry * > geometryList;
2085 geometryList.reserve( numGeom );
2086 for (
int i = 0; i < numGeom; ++i )
2088 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2106 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2115 std::random_device rd;
2116 std::mt19937 mt( seed == 0 ? rd() : seed );
2117 std::uniform_real_distribution<> uniformDist( 0, 1 );
2124 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2126 int numGeom = gc->numGeometries();
2127 QVector< QgsAbstractGeometry * > geometryList;
2128 geometryList.reserve( numGeom );
2129 for (
int i = 0; i < numGeom; ++i )
2131 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2149 const int totalPoints = line->
numPoints();
2150 if ( totalPoints < 2 )
2153 const double *x = line->
xData();
2154 const double *y = line->
yData();
2156 double prevX = *x++;
2157 double prevY = *y++;
2159 QVector< double > outX;
2160 QVector< double > outY;
2161 const double totalLength = line->
length();
2163 const int maxRepetitions = std::ceil( totalLength / wavelength );
2164 if ( !strictWavelength )
2165 wavelength = totalLength / maxRepetitions;
2167 const int estimatedPoints = maxRepetitions * 4 + 2;
2168 outX.reserve( estimatedPoints );
2169 outY.reserve( estimatedPoints );
2170 outX.append( prevX );
2171 outY.append( prevY );
2174 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2175 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2177 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2180 for (
int i = 1; i < totalPoints; ++i )
2182 double thisX = *x++;
2183 double thisY = *y++;
2187 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2190 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2195 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2196 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2197 outX.append( pX + side * amplitude * sinAngle );
2198 outY.append( pY + side * amplitude * cosAngle );
2199 outX.append( pX - side * amplitude * sinAngle );
2200 outY.append( pY - side * amplitude * cosAngle );
2202 distanceToNextPointFromStartOfSegment += wavelength / 2;
2208 distanceToNextPointFromStartOfSegment -= segmentLength;
2214 outX.append( prevX );
2215 outY.append( prevY );
2217 return std::make_unique< QgsLineString >( outX, outY );
2221 const double minimumWavelength,
const double maximumWavelength,
2222 const double minimumAmplitude,
const double maximumAmplitude,
2223 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2225 const int totalPoints = line->
numPoints();
2226 if ( totalPoints < 2 )
2229 const double *x = line->
xData();
2230 const double *y = line->
yData();
2232 double prevX = *x++;
2233 double prevY = *y++;
2235 QVector< double > outX;
2236 QVector< double > outY;
2237 const double totalLength = line->
length();
2239 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2241 const int estimatedPoints = maxRepetitions * 4 + 2;
2242 outX.reserve( estimatedPoints );
2243 outY.reserve( estimatedPoints );
2244 outX.append( prevX );
2245 outY.append( prevY );
2247 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2250 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2251 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2253 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2254 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2257 for (
int i = 1; i < totalPoints; ++i )
2259 double thisX = *x++;
2260 double thisY = *y++;
2264 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2267 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2272 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2273 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2274 outX.append( pX + side * amplitude * sinAngle );
2275 outY.append( pY + side * amplitude * cosAngle );
2277 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2278 outX.append( pX - side * amplitude * sinAngle );
2279 outY.append( pY - side * amplitude * cosAngle );
2281 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2282 distanceToNextPointFromStartOfSegment += wavelength / 2;
2288 distanceToNextPointFromStartOfSegment -= segmentLength;
2291 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2292 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2293 outX.append( prevX );
2294 outY.append( prevY );
2296 return std::make_unique< QgsLineString >( outX, outY );
2301 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2305 geom = segmentizedCopy.get();
2316 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2319 wavelength, amplitude, strictWavelength ).release() );
2323 wavelength, amplitude, strictWavelength ).release() );
2330std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2332 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2336 geom = segmentizedCopy.get();
2347 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2350 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2354 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2377 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2379 int numGeom = gc->numGeometries();
2380 QVector< QgsAbstractGeometry * > geometryList;
2381 geometryList.reserve( numGeom );
2382 for (
int i = 0; i < numGeom; ++i )
2384 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2402 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2411 std::random_device rd;
2412 std::mt19937 mt( seed == 0 ? rd() : seed );
2413 std::uniform_real_distribution<> uniformDist( 0, 1 );
2420 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2422 int numGeom = gc->numGeometries();
2423 QVector< QgsAbstractGeometry * > geometryList;
2424 geometryList.reserve( numGeom );
2425 for (
int i = 0; i < numGeom; ++i )
2427 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2445 const int totalPoints = line->
numPoints();
2446 if ( totalPoints < 2 )
2449 const double *x = line->
xData();
2450 const double *y = line->
yData();
2452 double prevX = *x++;
2453 double prevY = *y++;
2455 const double totalLength = line->
length();
2457 const int maxRepetitions = std::ceil( totalLength / wavelength );
2458 if ( !strictWavelength )
2459 wavelength = totalLength / maxRepetitions;
2461 const int segments = 10;
2465 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2466 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2467 bool isFirstPart =
true;
2469 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2470 int bufferIndex = 1;
2471 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2473 double segmentAngleRadians = 0;
2474 double remainingDistance = totalLength;
2475 double totalCoveredDistance = 0;
2477 for (
int i = 1; i < totalPoints; ++i )
2479 double thisX = *x++;
2480 double thisY = *y++;
2484 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2487 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2490 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2492 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2493 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2495 if ( bufferIndex == 0 )
2497 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2498 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2500 distanceToNextPointFromStartOfSegment += wavelength / 4;
2502 else if ( bufferIndex == 1 && isFirstPart )
2504 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2505 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2506 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2507 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2509 distanceToNextPointFromStartOfSegment += wavelength / 8;
2511 else if ( bufferIndex == 1 )
2513 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2514 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2515 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2516 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2518 distanceToNextPointFromStartOfSegment += wavelength / 4;
2520 else if ( bufferIndex == 2 )
2522 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2523 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2527 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2528 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2529 isFirstPart =
false;
2534 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2535 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2536 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2538 out->append( bezier.get() );
2541 xOutBuffer[0] = xOutBuffer[3];
2542 yOutBuffer[0] = yOutBuffer[3];
2545 distanceToNextPointFromStartOfSegment += wavelength / 4;
2548 totalCoveredDistance += segmentLength;
2551 distanceToNextPointFromStartOfSegment -= segmentLength;
2554 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2555 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2556 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2557 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2560 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2561 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2564 out->append( bezier.get() );
2570 const double minimumWavelength,
const double maximumWavelength,
2571 const double minimumAmplitude,
const double maximumAmplitude,
2572 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2574 const int totalPoints = line->
numPoints();
2575 if ( totalPoints < 2 )
2578 const double *x = line->
xData();
2579 const double *y = line->
yData();
2581 double prevX = *x++;
2582 double prevY = *y++;
2584 const double totalLength = line->
length();
2586 const int segments = 10;
2590 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2591 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2592 bool isFirstPart =
true;
2594 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2595 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2597 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2598 int bufferIndex = 1;
2599 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2601 double segmentAngleRadians = 0;
2603 double remainingDistance = totalLength;
2604 double totalCoveredDistance = 0;
2606 for (
int i = 1; i < totalPoints; ++i )
2608 double thisX = *x++;
2609 double thisY = *y++;
2613 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2616 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2619 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2621 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2622 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2624 if ( bufferIndex == 0 )
2626 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2627 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2629 distanceToNextPointFromStartOfSegment += wavelength / 4;
2631 else if ( bufferIndex == 1 && isFirstPart )
2633 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2634 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2635 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2636 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2638 distanceToNextPointFromStartOfSegment += wavelength / 8;
2640 else if ( bufferIndex == 1 )
2642 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2643 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2644 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2645 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2647 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2648 distanceToNextPointFromStartOfSegment += wavelength / 4;
2650 else if ( bufferIndex == 2 )
2652 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2653 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2657 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2658 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2659 isFirstPart =
false;
2664 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2665 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2666 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2668 out->append( bezier.get() );
2671 xOutBuffer[0] = xOutBuffer[3];
2672 yOutBuffer[0] = yOutBuffer[3];
2676 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2678 distanceToNextPointFromStartOfSegment += wavelength / 4;
2681 totalCoveredDistance += segmentLength;
2685 distanceToNextPointFromStartOfSegment -= segmentLength;
2688 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2689 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2690 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2691 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2693 if ( out->isEmpty() )
2697 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2700 out->append( bezier.get() );
2705 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2706 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2709 out->append( bezier.get() );
2717 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2721 geom = segmentizedCopy.get();
2732 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2735 wavelength, amplitude, strictWavelength ).release() );
2739 wavelength, amplitude, strictWavelength ).release() );
2746std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2748 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2752 geom = segmentizedCopy.get();
2763 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2766 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2770 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2793 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2795 int numGeom = gc->numGeometries();
2796 QVector< QgsAbstractGeometry * > geometryList;
2797 geometryList.reserve( numGeom );
2798 for (
int i = 0; i < numGeom; ++i )
2800 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2818 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2827 std::random_device rd;
2828 std::mt19937 mt( seed == 0 ? rd() : seed );
2829 std::uniform_real_distribution<> uniformDist( 0, 1 );
2836 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2838 int numGeom = gc->numGeometries();
2839 QVector< QgsAbstractGeometry * > geometryList;
2840 geometryList.reserve( numGeom );
2841 for (
int i = 0; i < numGeom; ++i )
2843 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2860 const QVector< double> &pattern,
2864 double patternOffset )
2866 const int totalPoints = line->
numPoints();
2867 if ( totalPoints < 2 )
2870 const int patternSize = pattern.size();
2872 const double *x = line->
xData();
2873 const double *y = line->
yData();
2875 double prevX = *x++;
2876 double prevY = *y++;
2878 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2880 QVector< double > outX;
2881 QVector< double > outY;
2882 const double totalLength = line->
length();
2884 double patternLength = 0;
2885 double patternDashLength = 0;
2886 double patternGapLength = 0;
2887 for (
int i = 0; i < pattern.size(); ++i )
2889 patternLength += pattern.at( i );
2891 patternDashLength += pattern.at( i );
2893 patternGapLength += pattern.at( i );
2896 double firstPatternLength = 0;
2897 double firstPatternDashLength = 0;
2898 double firstPatternGapLength = 0;
2899 switch ( startRule )
2903 firstPatternLength = patternLength;
2904 firstPatternDashLength = patternDashLength;
2905 firstPatternGapLength = patternGapLength;
2908 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2909 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2910 firstPatternGapLength = patternGapLength;
2913 firstPatternLength = pattern.at( patternSize - 1 );
2914 firstPatternDashLength = 0;
2915 firstPatternGapLength = pattern.at( patternSize - 1 );
2918 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2919 firstPatternDashLength = 0;
2920 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2924 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2926 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2927 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2928 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2932 lastPatternLength = 0;
2933 lastPatternDashLength = 0;
2934 lastPatternGapLength = 0;
2937 lastPatternLength -= pattern.at( patternSize - 1 );
2938 lastPatternGapLength -= pattern.at( patternSize - 1 );
2941 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2942 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2943 lastPatternGapLength -= pattern.at( patternSize - 1 );
2946 lastPatternGapLength = patternGapLength;
2949 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2950 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2954 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2955 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2957 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2958 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2959 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2961 double dashLengthScalingFactor = 1;
2962 double gapLengthScalingFactor = 1;
2966 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2968 switch ( adjustment )
2971 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2972 gapLengthScalingFactor = dashLengthScalingFactor;
2975 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2978 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2983 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2984 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2986 const int maxPatterns = middlePatternRepetitions + 2;
2987 result->reserve( maxPatterns );
2989 int patternIndex = 0;
2990 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2992 switch ( startRule )
2998 distanceToNextPointFromStartOfSegment *= 0.5;
3001 patternIndex = patternSize - 1;
3003 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
3006 patternIndex = patternSize - 1;
3008 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
3012 const double adjustedOffset = fmod( patternOffset, patternLength );
3013 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
3017 double remainingOffset = scaledOffset;
3018 while ( remainingOffset > 0 )
3020 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
3022 distanceToNextPointFromStartOfSegment -= remainingOffset;
3026 remainingOffset -= distanceToNextPointFromStartOfSegment;
3029 if ( patternIndex == patternSize )
3032 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3038 outX.append( prevX );
3039 outY.append( prevY );
3042 for (
int i = 1; i < totalPoints; ++i )
3044 double thisX = *x++;
3045 double thisY = *y++;
3048 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
3051 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
3066 if ( patternIndex >= patternSize )
3069 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3074 outX.append( thisX );
3075 outY.append( thisY );
3080 distanceToNextPointFromStartOfSegment -= segmentLength;
3085 outX.append( prevX );
3086 outY.append( prevY );
3094 const QVector<double> &pattern,
3098 double patternOffset )
3100 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
3104 geom = segmentizedCopy.get();
3115 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
3118 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
3119 result->addGeometry( exteriorParts->geometryN( i )->clone() );
3124 for (
int j = 0; j < ringParts->numGeometries(); ++j )
3125 result->addGeometry( ringParts->geometryN( j )->clone() );
3134 if ( pattern.size() < 2 )
3138 if ( !mGeometry || mGeometry->
isEmpty() )
3148 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
3150 int numGeom = gc->numGeometries();
3151 QVector< QgsAbstractGeometry * > geometryList;
3152 geometryList.reserve( numGeom );
3153 for (
int i = 0; i < numGeom; ++i )
3155 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
3163 for (
int j = 0; j < collection->numGeometries(); ++j )
3165 first.
addPartV2( collection->geometryN( j )->clone() );
DashPatternSizeAdjustment
Dash pattern size adjustment options.
@ ScaleDashOnly
Only dash lengths are adjusted.
@ ScaleBothDashAndGap
Both the dash and gap lengths are adjusted equally.
@ ScaleGapOnly
Only gap lengths are adjusted.
DashPatternLineEndingRule
Dash pattern line ending rules.
@ HalfDash
Start or finish the pattern with a half length dash.
@ HalfGap
Start or finish the pattern with a half length gap.
@ FullGap
Start or finish the pattern with a full gap.
@ FullDash
Start or finish the pattern with a full dash.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CompoundCurve
CompoundCurve.
@ CircularString
CircularString.
The vertex_iterator class provides STL-style iterator for vertices.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
bool isMeasure() const
Returns true if the geometry contains m values.
virtual QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary const part after the last part of the geometry.
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.
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
Compound curve geometry type.
int nCurves() const
Returns the number of curves in the geometry.
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
virtual int numPoints() const =0
Returns the number of points in the curve.
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual bool isClosed() const
Returns true if the curve is closed.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
virtual QgsPolygon * toPolygon(unsigned int segments=36) const
Returns a segmented polygon.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
int partCount() const override
Returns count of parts contained in the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...
static double distance2D(double x1, double y1, double x2, double y2)
Returns the 2D distance between (x1, y1) and (x2, y2).
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
static void weightedPointInTriangle(double aX, double aY, double bX, double bY, double cX, double cY, double weightB, double weightC, double &pointX, double &pointY)
Returns a weighted point inside the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
static double triangleArea(double aX, double aY, double bX, double bY, double cX, double cY)
Returns the area of the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
static int leftOfLine(const double x, const double y, const double x1, const double y1, const double x2, const double y2)
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> (x2, y2).
static void circleCenterRadius(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double &radius, double ¢erX, double ¢erY)
Returns radius and center of the circle through pt1, pt2, pt3.
static bool pointContinuesArc(const QgsPoint &a1, const QgsPoint &a2, const QgsPoint &a3, const QgsPoint &b, double distanceTolerance, double pointSpacingAngleTolerance)
Returns true if point b is on the arc formed by points a1, a2, and a3, but not within that arc portio...
static int circleCircleOuterTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2)
Calculates the outer tangent points for two circles, centered at center1 and center2 and with radii o...
A geometry is the spatial representation of a feature.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
QgsPointXY closestVertex(const QgsPointXY &point, int &closestVertexIndex, int &previousVertexIndex, int &nextVertexIndex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
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.
Qgis::GeometryOperationResult addPartV2(const QVector< QgsPointXY > &points, Qgis::WkbType wkbType=Qgis::WkbType::Unknown)
Adds a new part to a the geometry.
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Does vector analysis using the geos library and handles import, export, exception handling*.
QgsGeometry triangularWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized triangular waves along the boundary of the geometry, with the specified wavelen...
QgsGeometry triangularWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs triangular waves along the boundary of the geometry, with the specified wavelength and amp...
QgsInternalGeometryEngine(const QgsGeometry &geometry)
The caller is responsible that the geometry is available and unchanged for the whole lifetime of this...
QgsGeometry roundWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs rounded (sine-like) waves along the boundary of the geometry, with the specified wavelengt...
QgsGeometry poleOfInaccessibility(double precision, double *distanceFromBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
QgsGeometry squareWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs square waves along the boundary of the geometry, with the specified wavelength and amplitu...
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer using the m-values from a (multi)line geometry.
QgsGeometry extrude(double x, double y) const
Will extrude a line or (segmentized) curve by a given offset and return a polygon representation of i...
QgsGeometry roundWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized rounded (sine-like) waves along the boundary of the geometry,...
QgsGeometry orthogonalize(double tolerance=1.0E-8, int maxIterations=1000, double angleThreshold=15.0) const
Attempts to orthogonalize a line or polygon geometry by shifting vertices to make the geometries angl...
QgsGeometry variableWidthBuffer(int segments, const std::function< std::unique_ptr< double[] >(const QgsLineString *line) > &widthFunction) const
Calculates a variable width buffer for a (multi)curve geometry.
QString lastError() const
Returns an error string referring to the last error encountered.
QgsGeometry orientedMinimumBoundingBox(double &area, double &angle, double &width, double &height) const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a tapered width buffer for a (multi)curve geometry.
QVector< QgsPointXY > randomPointsInPolygon(int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed=0, QgsFeedback *feedback=nullptr, int maxTriesPerPoint=0)
Returns a list of count random points generated inside a polygon geometry (if acceptPoint is specifie...
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Densifies the geometry by adding the specified number of extra nodes within each segment of the geome...
QgsGeometry applyDashPattern(const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternLineEndingRule endRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternSizeAdjustment adjustment=Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap, double patternOffset=0) const
Applies a dash pattern to a geometry, returning a MultiLineString geometry which is the input geometr...
QgsGeometry squareWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized square waves along the boundary of the geometry, with the specified wavelength ...
QgsGeometry convertToCurves(double distanceTolerance, double angleTolerance) const
Attempts to convert a non-curved geometry into a curved geometry type (e.g.
bool isAxisParallelRectangle(double maximumDeviation, bool simpleRectanglesOnly=false) const
Returns true if the geometry is a polygon that is almost an axis-parallel rectangle.
Represents a single 2D line segment, consisting of a 2D start and end vertex only.
int pointLeftOfLine(const QgsPointXY &point) const
Tests if a point is to the left of the line segment.
double endY() const
Returns the segment's end y-coordinate.
QgsPointXY end() const
Returns the segment's end point.
double endX() const
Returns the segment's end x-coordinate.
QgsPointXY start() const
Returns the segment's start point.
double startX() const
Returns the segment's start x-coordinate.
void reverse()
Reverses the line segment, so that the start and end points are flipped.
double startY() const
Returns the segment's start y-coordinate.
Line string geometry type, with support for z-dimension and m-values.
bool isClosed() const override
Returns true if the curve is closed.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
double length() const override
Returns the planar, 2-dimensional length of the geometry.
QgsPoint startPoint() const override
Returns the starting point of the curve.
static QgsLineString * fromBezierCurve(const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments=30)
Returns a new linestring created by segmentizing the bezier curve between start and end,...
int numPoints() const override
Returns the number of points in the curve.
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
void setYAt(int index, double y)
Sets the y-coordinate of the specified node in the line string.
double mAt(int index) const override
Returns the m value of the specified node in the line string.
void setXAt(int index, double x)
Sets the x-coordinate of the specified node in the line string.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
double zAt(int index) const override
Returns the z-coordinate of the specified node in the line string.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
Multi curve geometry collection.
Multi polygon geometry collection.
Multi surface geometry collection.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
bool isEmpty() const override
Returns true if the geometry is empty.
double distance(double x, double y) const
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
void addInteriorRing(QgsCurve *ring) override
Adds an interior ring to the geometry (takes ownership)
bool intersects(const QgsLineSegment2D &segment, QgsPointXY &intersectPoint) const
Finds the closest intersection point of the ray and a line segment.
A rectangle specified with double values.
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.
QString error() const
Returns a descriptive error string if the tessellation failed.
void setOutputZUp(bool zUp)
Sets whether the "up" direction should be the Z axis on output (true), otherwise the "up" direction w...
int dataVerticesCount() const
Returns the number of vertices stored in the output data array.
A class to represent a vector.
double lengthSquared() const
Returns the length of the vector.
double crossProduct(QgsVector v) const
Returns the 2D cross product of this vector and another vector v.
QgsVector normalized() const
Returns the vector's normalized (or "unit") vector (ie same angle but length of 1....
double length() const
Returns the length of the vector.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static bool isCurvedType(Qgis::WkbType type)
Returns true if the WKB type is a curved type or can contain curved geometries.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
Contains geos related utilities and functions.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QVector< QgsPointXY > randomPointsInPolygonGeosBackend(const QgsAbstractGeometry *geometry, int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed, QgsFeedback *feedback, int maxTriesPerPoint, QString &error)
std::unique_ptr< QgsCurve > lineToCurve(const QgsCurve *curve, double distanceTolerance, double pointSpacingAngleTolerance)
bool matchesOrientation(std::array< Direction, 4 > dirs, std::array< Direction, 4 > oriented)
double normalizedDotProduct(const QgsPoint &a, const QgsPoint &b, const QgsPoint &c)
bool isClockwise(std::array< Direction, 4 > dirs)
Checks whether the 4 directions in dirs make up a clockwise rectangle.
std::unique_ptr< QgsLineString > squareWavesRandomizedAlongLine(const QgsLineString *line, const double minimumWavelength, const double maximumWavelength, const double minimumAmplitude, const double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
std::unique_ptr< QgsLineString > squareWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
QgsAbstractGeometry * orthogonalizeGeom(const QgsAbstractGeometry *geom, int maxIterations, double tolerance, double lowerThreshold, double upperThreshold)
QVector< QgsPointXY > randomPointsInPolygonPoly2TriBackend(const QgsAbstractGeometry *geometry, int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed, QgsFeedback *feedback, int maxTriesPerPoint, QString &error)
std::unique_ptr< QgsLineString > triangularWavesRandomizedAlongLine(const QgsLineString *line, const double minimumWavelength, const double maximumWavelength, const double minimumAmplitude, const double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
QgsLineString * doDensify(const QgsLineString *ring, int extraNodesPerSegment=-1, double distance=1)
Direction getEdgeDirection(const QgsPoint &p1, const QgsPoint &p2, double maxDev)
Determines the direction of an edge from p1 to p2.
std::unique_ptr< QgsAbstractGeometry > applyDashPatternPrivate(const QgsAbstractGeometry *geom, const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule, Qgis::DashPatternLineEndingRule endRule, Qgis::DashPatternSizeAdjustment adjustment, double patternOffset)
std::unique_ptr< QgsLineString > roundWavesRandomizedAlongLine(const QgsLineString *line, const double minimumWavelength, const double maximumWavelength, const double minimumAmplitude, const double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
QgsVector calcMotion(const QgsPoint &a, const QgsPoint &b, const QgsPoint &c, double lowerThreshold, double upperThreshold)
QVector< QgsPointXY > generateSegmentCurve(const QgsPoint ¢er1, const double radius1, const QgsPoint ¢er2, const double radius2)
bool dotProductWithinAngleTolerance(double dotProduct, double lowerThreshold, double upperThreshold)
QgsLineString * doOrthogonalize(QgsLineString *ring, int iterations, double tolerance, double lowerThreshold, double upperThreshold)
double squareness(QgsLineString *ring, double lowerThreshold, double upperThreshold)
std::unique_ptr< QgsMultiLineString > dashPatternAlongLine(const QgsLineString *line, const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule, Qgis::DashPatternLineEndingRule endRule, Qgis::DashPatternSizeAdjustment adjustment, double patternOffset)
std::unique_ptr< QgsAbstractGeometry > convertGeometryToCurves(const QgsAbstractGeometry *geom, double distanceTolerance, double angleTolerance)
std::unique_ptr< QgsAbstractGeometry > roundWavesPrivate(const QgsAbstractGeometry *geom, double wavelength, double amplitude, bool strictWavelength)
bool isCounterClockwise(std::array< Direction, 4 > dirs)
Checks whether the 4 directions in dirs make up a counter-clockwise rectangle.
QgsAbstractGeometry * densifyGeometry(const QgsAbstractGeometry *geom, int extraNodesPerSegment=1, double distance=1)
std::unique_ptr< QgsLineString > roundWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
std::pair< bool, std::array< Direction, 4 > > getEdgeDirections(const QgsPolygon *g, double maxDev)
Checks whether the polygon consists of four nearly axis-parallel sides.
std::unique_ptr< QgsAbstractGeometry > squareWavesRandomizedPrivate(const QgsAbstractGeometry *geom, double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
std::unique_ptr< QgsAbstractGeometry > triangularWavesRandomizedPrivate(const QgsAbstractGeometry *geom, double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
std::unique_ptr< QgsAbstractGeometry > triangularWavesPrivate(const QgsAbstractGeometry *geom, double wavelength, double amplitude, bool strictWavelength)
std::unique_ptr< QgsAbstractGeometry > squareWavesPrivate(const QgsAbstractGeometry *geom, double wavelength, double amplitude, bool strictWavelength)
std::unique_ptr< QgsLineString > triangularWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
std::unique_ptr< QgsAbstractGeometry > roundWavesRandomizedPrivate(const QgsAbstractGeometry *geom, double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt)
QLineF segment(int index, QRectF rect, double radius)
Utility class for identifying a unique vertex within a geometry.