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 )
1234 if (
const QgsMultiSurface *ms = qgsgeometry_cast< const QgsMultiSurface * >( geometry ) )
1236 for (
int i = 0; i < ms->numGeometries(); ++i )
1239 return QVector< QgsPointXY >();
1241 if (
QgsPolygon *poly = qgsgeometry_cast< QgsPolygon * >( ms->geometryN( i ) ) )
1247 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->geometryN( i )->segmentize() ) );
1254 if (
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( geometry ) )
1260 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( geometry->
segmentize() ) );
1266 return QVector< QgsPointXY >();
1268 if ( !t.
error().isEmpty() )
1271 return QVector< QgsPointXY >();
1274 const QVector<float> triangleData = t.
data();
1275 if ( triangleData.empty() )
1276 return QVector< QgsPointXY >();
1279 std::vector< double > cumulativeAreas;
1281 double totalArea = 0;
1282 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1285 return QVector< QgsPointXY >();
1287 const float aX = *it++;
1289 const float aY = -( *it++ );
1290 const float bX = *it++;
1292 const float bY = -( *it++ );
1293 const float cX = *it++;
1295 const float cY = -( *it++ );
1299 cumulativeAreas.emplace_back( totalArea );
1302 std::random_device rd;
1303 std::mt19937 mt( seed == 0 ? rd() : seed );
1304 std::uniform_real_distribution<> uniformDist( 0, 1 );
1307 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1310 const double target = random * totalArea;
1311 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1316 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1321 QVector<QgsPointXY> result;
1322 result.reserve( count );
1324 for (
int i = 0; i < count; )
1327 return QVector< QgsPointXY >();
1329 const double triangleIndexRnd = uniformDist( mt );
1331 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1334 const double weightB = uniformDist( mt );
1335 const double weightC = uniformDist( mt );
1340 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1341 const double aY = -triangleData.at( triangleIndex * 9 + 2 ) + bounds.
yMinimum();
1342 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1343 const double bY = -triangleData.at( triangleIndex * 9 + 5 ) + bounds.
yMinimum();
1344 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1345 const double cY = -triangleData.at( triangleIndex * 9 + 8 ) + bounds.
yMinimum();
1349 if ( acceptPoint( candidate ) )
1355 else if ( maxTriesPerPoint != 0 )
1359 if ( tries == maxTriesPerPoint )
1370 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1374 std::unique_ptr<QgsAbstractGeometry> triangulation =
geos.constrainedDelaunayTriangulation( &error );
1375 if ( !triangulation || triangulation->isEmpty( ) )
1381 const QgsMultiPolygon *mp = qgsgeometry_cast< const QgsMultiPolygon * >( triangulation.get() );
1386 std::vector< double > cumulativeAreas;
1388 double totalArea = 0;
1389 std::vector< double > vertices(
static_cast< std::size_t
>( mp->
numGeometries() ) * 6 );
1390 double *vertexData = vertices.data();
1396 const QgsPolygon *part = qgsgeometry_cast< const QgsPolygon * >( *it );
1404 const double aX = exterior->
xAt( 0 );
1405 const double aY = exterior->
yAt( 0 );
1406 const double bX = exterior->
xAt( 1 );
1407 const double bY = exterior->
yAt( 1 );
1408 const double cX = exterior->
xAt( 2 );
1409 const double cY = exterior->
yAt( 2 );
1419 cumulativeAreas.emplace_back( totalArea );
1422 std::random_device rd;
1423 std::mt19937 mt( seed == 0 ? rd() : seed );
1424 std::uniform_real_distribution<> uniformDist( 0, 1 );
1427 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1430 const double target = random * totalArea;
1431 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1436 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1441 QVector<QgsPointXY> result;
1442 result.reserve( count );
1444 vertexData = vertices.data();
1445 for (
int i = 0; i < count; )
1448 return QVector< QgsPointXY >();
1450 const double triangleIndexRnd = uniformDist( mt );
1452 const std::size_t triangleIndex = selectRandomTriangle( triangleIndexRnd );
1455 const double weightB = uniformDist( mt );
1456 const double weightC = uniformDist( mt );
1461 const double aX = vertexData[ triangleIndex * 6 ];
1462 const double aY = vertexData[ triangleIndex * 6 + 1 ];
1463 const double bX = vertexData[ triangleIndex * 6 + 2 ];
1464 const double bY = vertexData[ triangleIndex * 6 + 3 ];
1465 const double cX = vertexData[ triangleIndex * 6 + 4 ];
1466 const double cY = vertexData[ triangleIndex * 6 + 5 ];
1471 if ( acceptPoint( candidate ) )
1477 else if ( maxTriesPerPoint != 0 )
1481 if ( tries == maxTriesPerPoint )
1492 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1495 return QVector< QgsPointXY >();
1498#if (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=11) || GEOS_VERSION_MAJOR>3
1508 double pointSpacingAngleTolerance )
1514 std::unique_ptr< QgsCircularString > out;
1515 out.reset( qgsgeometry_cast< QgsCircularString * >( curve )->clone() );
1520 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1521 const QgsCompoundCurve *in = qgsgeometry_cast< const QgsCompoundCurve * >( curve );
1522 for (
int i = 0; i < in->
nCurves(); i ++ )
1524 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1527 if (
const QgsCompoundCurve *processedCompoundCurve = qgsgeometry_cast< const QgsCompoundCurve *>( processed.get() ) )
1529 for (
int i = 0; i < processedCompoundCurve->nCurves(); ++i )
1531 out->addCurve( processedCompoundCurve->curveAt( i )->clone() );
1536 out->addCurve( processed.release() );
1544 const QgsLineString *lineString = qgsgeometry_cast< QgsLineString * >( curve );
1546 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1549 const unsigned int minQuadEdges = 2;
1562 out->addCurve( lineString->
clone() );
1568 QVector< int > edgesInArcs( numEdges + 1, 0 );
1572 double abX = b.x() - a.
x();
1573 double abY = b.y() - a.
y();
1575 double cbX = b.x() -
c.x();
1576 double cbY = b.y() -
c.y();
1578 double dot = ( abX * cbX + abY * cbY );
1579 double cross = ( abX * cbY - abY * cbX );
1581 double alpha = std::atan2( cross, dot );
1596 double centerX = 0.0;
1597 double centerY = 0.0;
1600 while ( i < numEdges - 2 )
1602 unsigned int arcEdges = 0;
1603 double numQuadrants = 0;
1606 bool foundArc =
false;
1608 a1 = lineString->
pointN( i );
1609 a2 = lineString->
pointN( i + 1 );
1610 a3 = lineString->
pointN( i + 2 );
1613 for ( j = i + 3; j < numEdges + 1; j++ )
1615 b = lineString->
pointN( j );
1622 for ( k = j - 1; k > j - 4; k-- )
1623 edgesInArcs[k] = currentArc;
1643 arcEdges = j - 1 - i;
1644 if ( first.
x() == b.x() && first.
y() == b.y() )
1652 angle = arcAngle( first,
QgsPoint( centerX, centerY ), b );
1658 angle = 2 * M_PI + angle;
1659 numQuadrants = ( 4 * angle ) / ( 2 * M_PI );
1662 if ( arcEdges < minQuadEdges * numQuadrants )
1665 for ( k = j - 1; k >= i; k-- )
1682 int edgeType = edgesInArcs[0];
1684 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1689 QVector< QgsPoint > points;
1690 for (
int j = start; j < end + 2; ++ j )
1692 points.append( lineString->
pointN( j ) );
1694 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1695 out->addCurve( straightSegment.release() );
1700 QVector< QgsPoint > points;
1701 points.append( lineString->
pointN( start ) );
1702 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1703 points.append( lineString->
pointN( end + 1 ) );
1704 std::unique_ptr< QgsCircularString > curvedSegment = std::make_unique< QgsCircularString >();
1705 curvedSegment->setPoints( points );
1706 out->addCurve( curvedSegment.release() );
1710 for (
int i = 1; i < numEdges; i++ )
1712 if ( edgeType != edgesInArcs[i] )
1715 addPointsToCurve( start, end, edgeType );
1717 edgeType = edgesInArcs[i];
1723 addPointsToCurve( start, end, edgeType );
1728 std::unique_ptr< QgsCircularString > res;
1729 res.reset( qgsgeometry_cast< const QgsCircularString * >( out->simplifiedTypeRef() )->clone() );
1743 return lineToCurve( qgsgeometry_cast< const QgsCurve * >( geom ), distanceTolerance, angleTolerance );
1748 const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( geom );
1749 std::unique_ptr< QgsCurvePolygon > result = std::make_unique< QgsCurvePolygon>();
1752 distanceTolerance, angleTolerance ).release() );
1756 distanceTolerance, angleTolerance ).release() );
1776 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1778 int numGeom = gc->numGeometries();
1779 QVector< QgsAbstractGeometry * > geometryList;
1780 geometryList.reserve( numGeom );
1781 for (
int i = 0; i < numGeom; ++i )
1804 area = std::numeric_limits<double>::max();
1806 width = std::numeric_limits<double>::max();
1807 height = std::numeric_limits<double>::max();
1813 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1824 double totalRotation = 0;
1825 while ( hull->nextVertex( vertexId, pt2 ) )
1828 double rotateAngle = 180.0 / M_PI * currentAngle;
1829 totalRotation += rotateAngle;
1831 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1832 t.rotate( rotateAngle );
1833 t.translate( -pt0.
x(), -pt0.
y() );
1835 hull->transform( t );
1838 double currentArea = bounds.
width() * bounds.
height();
1839 if ( currentArea < area )
1843 angle = totalRotation;
1844 width = bounds.
width();
1845 height = bounds.
height();
1854 if ( width > height )
1856 width = minRect.
height();
1857 height = minRect.
width();
1858 angle = angle + 90.0;
1862 if ( angle > 180.0 )
1863 angle = std::fmod( angle, 180.0 );
1870 const int totalPoints = line->
numPoints();
1871 if ( totalPoints < 2 )
1874 const double *x = line->
xData();
1875 const double *y = line->
yData();
1877 double prevX = *x++;
1878 double prevY = *y++;
1880 QVector< double > outX;
1881 QVector< double > outY;
1882 const double totalLength = line->
length();
1884 const int maxRepetitions = std::ceil( totalLength / wavelength );
1885 if ( !strictWavelength )
1886 wavelength = totalLength / maxRepetitions;
1888 const int estimatedPoints = maxRepetitions * 2 + 2;
1889 outX.reserve( estimatedPoints );
1890 outY.reserve( estimatedPoints );
1891 outX.append( prevX );
1892 outY.append( prevY );
1894 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1896 for (
int i = 1; i < totalPoints; ++i )
1898 double thisX = *x++;
1899 double thisY = *y++;
1903 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1906 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1911 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1912 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1914 outX.append( outPointX );
1915 outY.append( outPointY );
1917 distanceToNextPointFromStartOfSegment += wavelength / 2;
1923 distanceToNextPointFromStartOfSegment -= segmentLength;
1926 outX.append( prevX );
1927 outY.append( prevY );
1929 return std::make_unique< QgsLineString >( outX, outY );
1933 const double minimumWavelength,
const double maximumWavelength,
1934 const double minimumAmplitude,
const double maximumAmplitude,
1935 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1937 const int totalPoints = line->
numPoints();
1938 if ( totalPoints < 2 )
1941 const double *x = line->
xData();
1942 const double *y = line->
yData();
1944 double prevX = *x++;
1945 double prevY = *y++;
1947 QVector< double > outX;
1948 QVector< double > outY;
1949 const double totalLength = line->
length();
1951 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1953 const int estimatedPoints = maxRepetitions * 2 + 2;
1954 outX.reserve( estimatedPoints );
1955 outY.reserve( estimatedPoints );
1956 outX.append( prevX );
1957 outY.append( prevY );
1959 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1960 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1961 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1964 for (
int i = 1; i < totalPoints; ++i )
1966 double thisX = *x++;
1967 double thisY = *y++;
1971 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1974 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1979 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1980 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1981 outX.append( outPointX );
1982 outY.append( outPointY );
1984 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1985 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1987 distanceToNextPointFromStartOfSegment += wavelength / 2;
1993 distanceToNextPointFromStartOfSegment -= segmentLength;
1996 outX.append( prevX );
1997 outY.append( prevY );
1999 return std::make_unique< QgsLineString >( outX, outY );
2004 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2008 geom = segmentizedCopy.get();
2019 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2022 wavelength, amplitude, strictWavelength ).release() );
2026 wavelength, amplitude, strictWavelength ).release() );
2033std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2035 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2039 geom = segmentizedCopy.get();
2050 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2053 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2057 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2080 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2082 int numGeom = gc->numGeometries();
2083 QVector< QgsAbstractGeometry * > geometryList;
2084 geometryList.reserve( numGeom );
2085 for (
int i = 0; i < numGeom; ++i )
2087 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2105 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2114 std::random_device rd;
2115 std::mt19937 mt( seed == 0 ? rd() : seed );
2116 std::uniform_real_distribution<> uniformDist( 0, 1 );
2123 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2125 int numGeom = gc->numGeometries();
2126 QVector< QgsAbstractGeometry * > geometryList;
2127 geometryList.reserve( numGeom );
2128 for (
int i = 0; i < numGeom; ++i )
2130 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2148 const int totalPoints = line->
numPoints();
2149 if ( totalPoints < 2 )
2152 const double *x = line->
xData();
2153 const double *y = line->
yData();
2155 double prevX = *x++;
2156 double prevY = *y++;
2158 QVector< double > outX;
2159 QVector< double > outY;
2160 const double totalLength = line->
length();
2162 const int maxRepetitions = std::ceil( totalLength / wavelength );
2163 if ( !strictWavelength )
2164 wavelength = totalLength / maxRepetitions;
2166 const int estimatedPoints = maxRepetitions * 4 + 2;
2167 outX.reserve( estimatedPoints );
2168 outY.reserve( estimatedPoints );
2169 outX.append( prevX );
2170 outY.append( prevY );
2173 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2174 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2176 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2179 for (
int i = 1; i < totalPoints; ++i )
2181 double thisX = *x++;
2182 double thisY = *y++;
2186 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2189 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2194 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2195 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2196 outX.append( pX + side * amplitude * sinAngle );
2197 outY.append( pY + side * amplitude * cosAngle );
2198 outX.append( pX - side * amplitude * sinAngle );
2199 outY.append( pY - side * amplitude * cosAngle );
2201 distanceToNextPointFromStartOfSegment += wavelength / 2;
2207 distanceToNextPointFromStartOfSegment -= segmentLength;
2213 outX.append( prevX );
2214 outY.append( prevY );
2216 return std::make_unique< QgsLineString >( outX, outY );
2220 const double minimumWavelength,
const double maximumWavelength,
2221 const double minimumAmplitude,
const double maximumAmplitude,
2222 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2224 const int totalPoints = line->
numPoints();
2225 if ( totalPoints < 2 )
2228 const double *x = line->
xData();
2229 const double *y = line->
yData();
2231 double prevX = *x++;
2232 double prevY = *y++;
2234 QVector< double > outX;
2235 QVector< double > outY;
2236 const double totalLength = line->
length();
2238 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2240 const int estimatedPoints = maxRepetitions * 4 + 2;
2241 outX.reserve( estimatedPoints );
2242 outY.reserve( estimatedPoints );
2243 outX.append( prevX );
2244 outY.append( prevY );
2246 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2249 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2250 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2252 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2253 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2256 for (
int i = 1; i < totalPoints; ++i )
2258 double thisX = *x++;
2259 double thisY = *y++;
2263 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2266 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2271 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2272 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2273 outX.append( pX + side * amplitude * sinAngle );
2274 outY.append( pY + side * amplitude * cosAngle );
2276 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2277 outX.append( pX - side * amplitude * sinAngle );
2278 outY.append( pY - side * amplitude * cosAngle );
2280 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2281 distanceToNextPointFromStartOfSegment += wavelength / 2;
2287 distanceToNextPointFromStartOfSegment -= segmentLength;
2290 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2291 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2292 outX.append( prevX );
2293 outY.append( prevY );
2295 return std::make_unique< QgsLineString >( outX, outY );
2300 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2304 geom = segmentizedCopy.get();
2315 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2318 wavelength, amplitude, strictWavelength ).release() );
2322 wavelength, amplitude, strictWavelength ).release() );
2329std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2331 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2335 geom = segmentizedCopy.get();
2346 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2349 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2353 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2376 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2378 int numGeom = gc->numGeometries();
2379 QVector< QgsAbstractGeometry * > geometryList;
2380 geometryList.reserve( numGeom );
2381 for (
int i = 0; i < numGeom; ++i )
2383 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2401 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2410 std::random_device rd;
2411 std::mt19937 mt( seed == 0 ? rd() : seed );
2412 std::uniform_real_distribution<> uniformDist( 0, 1 );
2419 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2421 int numGeom = gc->numGeometries();
2422 QVector< QgsAbstractGeometry * > geometryList;
2423 geometryList.reserve( numGeom );
2424 for (
int i = 0; i < numGeom; ++i )
2426 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2444 const int totalPoints = line->
numPoints();
2445 if ( totalPoints < 2 )
2448 const double *x = line->
xData();
2449 const double *y = line->
yData();
2451 double prevX = *x++;
2452 double prevY = *y++;
2454 const double totalLength = line->
length();
2456 const int maxRepetitions = std::ceil( totalLength / wavelength );
2457 if ( !strictWavelength )
2458 wavelength = totalLength / maxRepetitions;
2460 const int segments = 10;
2464 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2465 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2466 bool isFirstPart =
true;
2468 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2469 int bufferIndex = 1;
2470 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2472 double segmentAngleRadians = 0;
2473 double remainingDistance = totalLength;
2474 double totalCoveredDistance = 0;
2476 for (
int i = 1; i < totalPoints; ++i )
2478 double thisX = *x++;
2479 double thisY = *y++;
2483 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2486 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2489 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2491 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2492 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2494 if ( bufferIndex == 0 )
2496 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2497 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2499 distanceToNextPointFromStartOfSegment += wavelength / 4;
2501 else if ( bufferIndex == 1 && isFirstPart )
2503 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2504 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2505 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2506 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2508 distanceToNextPointFromStartOfSegment += wavelength / 8;
2510 else if ( bufferIndex == 1 )
2512 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2513 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2514 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2515 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2517 distanceToNextPointFromStartOfSegment += wavelength / 4;
2519 else if ( bufferIndex == 2 )
2521 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2522 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2526 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2527 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2528 isFirstPart =
false;
2533 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2534 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2535 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2537 out->append( bezier.get() );
2540 xOutBuffer[0] = xOutBuffer[3];
2541 yOutBuffer[0] = yOutBuffer[3];
2544 distanceToNextPointFromStartOfSegment += wavelength / 4;
2547 totalCoveredDistance += segmentLength;
2550 distanceToNextPointFromStartOfSegment -= segmentLength;
2553 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2554 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2555 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2556 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2559 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2560 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2563 out->append( bezier.get() );
2569 const double minimumWavelength,
const double maximumWavelength,
2570 const double minimumAmplitude,
const double maximumAmplitude,
2571 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2573 const int totalPoints = line->
numPoints();
2574 if ( totalPoints < 2 )
2577 const double *x = line->
xData();
2578 const double *y = line->
yData();
2580 double prevX = *x++;
2581 double prevY = *y++;
2583 const double totalLength = line->
length();
2585 const int segments = 10;
2589 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2590 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2591 bool isFirstPart =
true;
2593 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2594 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2596 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2597 int bufferIndex = 1;
2598 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2600 double segmentAngleRadians = 0;
2602 double remainingDistance = totalLength;
2603 double totalCoveredDistance = 0;
2605 for (
int i = 1; i < totalPoints; ++i )
2607 double thisX = *x++;
2608 double thisY = *y++;
2612 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2615 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2618 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2620 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2621 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2623 if ( bufferIndex == 0 )
2625 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2626 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2628 distanceToNextPointFromStartOfSegment += wavelength / 4;
2630 else if ( bufferIndex == 1 && isFirstPart )
2632 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2633 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2634 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2635 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2637 distanceToNextPointFromStartOfSegment += wavelength / 8;
2639 else if ( bufferIndex == 1 )
2641 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2642 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2643 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2644 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2646 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2647 distanceToNextPointFromStartOfSegment += wavelength / 4;
2649 else if ( bufferIndex == 2 )
2651 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2652 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2656 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2657 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2658 isFirstPart =
false;
2663 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2664 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2665 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2667 out->append( bezier.get() );
2670 xOutBuffer[0] = xOutBuffer[3];
2671 yOutBuffer[0] = yOutBuffer[3];
2675 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2677 distanceToNextPointFromStartOfSegment += wavelength / 4;
2680 totalCoveredDistance += segmentLength;
2684 distanceToNextPointFromStartOfSegment -= segmentLength;
2687 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2688 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2689 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2690 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2692 if ( out->isEmpty() )
2696 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2699 out->append( bezier.get() );
2704 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2705 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2708 out->append( bezier.get() );
2716 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2720 geom = segmentizedCopy.get();
2731 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2734 wavelength, amplitude, strictWavelength ).release() );
2738 wavelength, amplitude, strictWavelength ).release() );
2745std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2747 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2751 geom = segmentizedCopy.get();
2762 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2765 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2769 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2792 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2794 int numGeom = gc->numGeometries();
2795 QVector< QgsAbstractGeometry * > geometryList;
2796 geometryList.reserve( numGeom );
2797 for (
int i = 0; i < numGeom; ++i )
2799 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2817 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2826 std::random_device rd;
2827 std::mt19937 mt( seed == 0 ? rd() : seed );
2828 std::uniform_real_distribution<> uniformDist( 0, 1 );
2835 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2837 int numGeom = gc->numGeometries();
2838 QVector< QgsAbstractGeometry * > geometryList;
2839 geometryList.reserve( numGeom );
2840 for (
int i = 0; i < numGeom; ++i )
2842 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2859 const QVector< double> &pattern,
2863 double patternOffset )
2865 const int totalPoints = line->
numPoints();
2866 if ( totalPoints < 2 )
2869 const int patternSize = pattern.size();
2871 const double *x = line->
xData();
2872 const double *y = line->
yData();
2874 double prevX = *x++;
2875 double prevY = *y++;
2877 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2879 QVector< double > outX;
2880 QVector< double > outY;
2881 const double totalLength = line->
length();
2883 double patternLength = 0;
2884 double patternDashLength = 0;
2885 double patternGapLength = 0;
2886 for (
int i = 0; i < pattern.size(); ++i )
2888 patternLength += pattern.at( i );
2890 patternDashLength += pattern.at( i );
2892 patternGapLength += pattern.at( i );
2895 double firstPatternLength = 0;
2896 double firstPatternDashLength = 0;
2897 double firstPatternGapLength = 0;
2898 switch ( startRule )
2902 firstPatternLength = patternLength;
2903 firstPatternDashLength = patternDashLength;
2904 firstPatternGapLength = patternGapLength;
2907 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2908 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2909 firstPatternGapLength = patternGapLength;
2912 firstPatternLength = pattern.at( patternSize - 1 );
2913 firstPatternDashLength = 0;
2914 firstPatternGapLength = pattern.at( patternSize - 1 );
2917 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2918 firstPatternDashLength = 0;
2919 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2923 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2925 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2926 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2927 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2931 lastPatternLength = 0;
2932 lastPatternDashLength = 0;
2933 lastPatternGapLength = 0;
2936 lastPatternLength -= pattern.at( patternSize - 1 );
2937 lastPatternGapLength -= pattern.at( patternSize - 1 );
2940 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2941 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2942 lastPatternGapLength -= pattern.at( patternSize - 1 );
2945 lastPatternGapLength = patternGapLength;
2948 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2949 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2953 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2954 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2956 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2957 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2958 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2960 double dashLengthScalingFactor = 1;
2961 double gapLengthScalingFactor = 1;
2965 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2967 switch ( adjustment )
2970 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2971 gapLengthScalingFactor = dashLengthScalingFactor;
2974 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2977 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2982 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2983 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2985 const int maxPatterns = middlePatternRepetitions + 2;
2986 result->reserve( maxPatterns );
2988 int patternIndex = 0;
2989 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2991 switch ( startRule )
2997 distanceToNextPointFromStartOfSegment *= 0.5;
3000 patternIndex = patternSize - 1;
3002 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
3005 patternIndex = patternSize - 1;
3007 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
3011 const double adjustedOffset = fmod( patternOffset, patternLength );
3012 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
3016 double remainingOffset = scaledOffset;
3017 while ( remainingOffset > 0 )
3019 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
3021 distanceToNextPointFromStartOfSegment -= remainingOffset;
3025 remainingOffset -= distanceToNextPointFromStartOfSegment;
3028 if ( patternIndex == patternSize )
3031 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3037 outX.append( prevX );
3038 outY.append( prevY );
3041 for (
int i = 1; i < totalPoints; ++i )
3043 double thisX = *x++;
3044 double thisY = *y++;
3047 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
3050 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
3065 if ( patternIndex >= patternSize )
3068 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3073 outX.append( thisX );
3074 outY.append( thisY );
3079 distanceToNextPointFromStartOfSegment -= segmentLength;
3084 outX.append( prevX );
3085 outY.append( prevY );
3093 const QVector<double> &pattern,
3097 double patternOffset )
3099 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
3103 geom = segmentizedCopy.get();
3114 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
3117 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
3118 result->addGeometry( exteriorParts->geometryN( i )->clone() );
3123 for (
int j = 0; j < ringParts->numGeometries(); ++j )
3124 result->addGeometry( ringParts->geometryN( j )->clone() );
3133 if ( pattern.size() < 2 )
3137 if ( !mGeometry || mGeometry->
isEmpty() )
3147 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
3149 int numGeom = gc->numGeometries();
3150 QVector< QgsAbstractGeometry * > geometryList;
3151 geometryList.reserve( numGeom );
3152 for (
int i = 0; i < numGeom; ++i )
3154 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
3162 for (
int j = 0; j < collection->numGeometries(); ++j )
3164 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)
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.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
double height() const
Returns the height of the rectangle.
Class that takes care of tessellation of polygons into triangles.
QVector< float > data() const
Returns array of triangle vertex data.
void addPolygon(const QgsPolygon &polygon, float extrusionHeight)
Tessellates a triangle and adds its vertex entries to the output data array.
QString error() const
Returns a descriptive error string if the tessellation failed.
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.