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 > > linesToProcess;
1056 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
1059 for (
int i = 0; i < multiCurve->
partCount(); ++i )
1068 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
1075 if ( linesToProcess.empty() )
1078 g.mLastError = QStringLiteral(
"Input geometry was not a curve type geometry" );
1082 QVector<QgsGeometry> bufferedLines;
1083 bufferedLines.reserve( linesToProcess.size() );
1085 for ( std::unique_ptr< QgsLineString > &line : linesToProcess )
1087 QVector<QgsGeometry> parts;
1089 double prevRadius = 0;
1092 std::unique_ptr< double[] > widths = widthFunction( line.get() ) ;
1097 double thisRadius = widths[ i ] / 2.0;
1098 if ( thisRadius > 0 )
1102 QgsCircle circ( thisPoint, thisRadius );
1104 parts << thisCircle;
1113 if ( prevRadius > 0 || thisRadius > 0 )
1115 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1116 if ( !points.empty() )
1121 int beforeVertex = 0;
1122 int afterVertex = 0;
1124 double sqrDistPrev = 0;
1125 for (
int j = 0; j < points.count(); ++j )
1129 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1132 points.append( points.at( 0 ) );
1134 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
1136 if ( poly->area() > 0 )
1141 prevPoint = thisPoint;
1142 prevRadius = thisRadius;
1143 prevCircle = thisCircle;
1158 start = std::fabs( start );
1159 end = std::fabs( end );
1161 auto interpolateWidths = [ start, end ](
const QgsLineString * line )->std::unique_ptr<
double [] >
1165 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1167 widths[line->nCoordinates() - 1] = end;
1169 double lineLength = line->length();
1170 double currentLength = 0;
1171 QgsPoint prevPoint = line->pointN( 0 );
1172 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1174 QgsPoint point = line->pointN( i );
1175 double segmentLength = point.
distance( prevPoint );
1176 currentLength += segmentLength;
1177 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1178 double delta = lengthFraction * ( end - start );
1179 widths[i] = start + delta;
1191 auto widthByM = [](
const QgsLineString * line )->std::unique_ptr<
double [] >
1193 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1194 for (
int i = 0; i < line->nCoordinates(); ++i )
1196 widths[ i ] = line->mAt( i );
1205 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1211 if (
const QgsMultiSurface *ms = qgsgeometry_cast< const QgsMultiSurface * >( geometry ) )
1213 for (
int i = 0; i < ms->numGeometries(); ++i )
1216 return QVector< QgsPointXY >();
1218 if (
QgsPolygon *poly = qgsgeometry_cast< QgsPolygon * >( ms->geometryN( i ) ) )
1224 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->geometryN( i )->segmentize() ) );
1231 if (
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( geometry ) )
1237 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( geometry->
segmentize() ) );
1243 return QVector< QgsPointXY >();
1245 if ( !t.
error().isEmpty() )
1248 return QVector< QgsPointXY >();
1251 const QVector<float> triangleData = t.
data();
1252 if ( triangleData.empty() )
1253 return QVector< QgsPointXY >();
1256 std::vector< double > cumulativeAreas;
1258 double totalArea = 0;
1259 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1262 return QVector< QgsPointXY >();
1264 const float aX = *it++;
1266 const float aY = -( *it++ );
1267 const float bX = *it++;
1269 const float bY = -( *it++ );
1270 const float cX = *it++;
1272 const float cY = -( *it++ );
1276 cumulativeAreas.emplace_back( totalArea );
1279 std::random_device rd;
1280 std::mt19937 mt( seed == 0 ? rd() : seed );
1281 std::uniform_real_distribution<> uniformDist( 0, 1 );
1284 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1287 const double target = random * totalArea;
1288 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1293 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1298 QVector<QgsPointXY> result;
1299 result.reserve( count );
1301 for (
int i = 0; i < count; )
1304 return QVector< QgsPointXY >();
1306 const double triangleIndexRnd = uniformDist( mt );
1308 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1311 const double weightB = uniformDist( mt );
1312 const double weightC = uniformDist( mt );
1317 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1318 const double aY = -triangleData.at( triangleIndex * 9 + 2 ) + bounds.
yMinimum();
1319 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1320 const double bY = -triangleData.at( triangleIndex * 9 + 5 ) + bounds.
yMinimum();
1321 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1322 const double cY = -triangleData.at( triangleIndex * 9 + 8 ) + bounds.
yMinimum();
1326 if ( acceptPoint( candidate ) )
1332 else if ( maxTriesPerPoint != 0 )
1336 if ( tries == maxTriesPerPoint )
1347 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1351 std::unique_ptr<QgsAbstractGeometry> triangulation =
geos.constrainedDelaunayTriangulation( &error );
1352 if ( !triangulation || triangulation->isEmpty( ) )
1358 const QgsMultiPolygon *mp = qgsgeometry_cast< const QgsMultiPolygon * >( triangulation.get() );
1363 std::vector< double > cumulativeAreas;
1365 double totalArea = 0;
1366 std::vector< double > vertices(
static_cast< std::size_t
>( mp->
numGeometries() ) * 6 );
1367 double *vertexData = vertices.data();
1373 const QgsPolygon *part = qgsgeometry_cast< const QgsPolygon * >( *it );
1381 const double aX = exterior->
xAt( 0 );
1382 const double aY = exterior->
yAt( 0 );
1383 const double bX = exterior->
xAt( 1 );
1384 const double bY = exterior->
yAt( 1 );
1385 const double cX = exterior->
xAt( 2 );
1386 const double cY = exterior->
yAt( 2 );
1396 cumulativeAreas.emplace_back( totalArea );
1399 std::random_device rd;
1400 std::mt19937 mt( seed == 0 ? rd() : seed );
1401 std::uniform_real_distribution<> uniformDist( 0, 1 );
1404 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1407 const double target = random * totalArea;
1408 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1413 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1418 QVector<QgsPointXY> result;
1419 result.reserve( count );
1421 vertexData = vertices.data();
1422 for (
int i = 0; i < count; )
1425 return QVector< QgsPointXY >();
1427 const double triangleIndexRnd = uniformDist( mt );
1429 const std::size_t triangleIndex = selectRandomTriangle( triangleIndexRnd );
1432 const double weightB = uniformDist( mt );
1433 const double weightC = uniformDist( mt );
1438 const double aX = vertexData[ triangleIndex * 6 ];
1439 const double aY = vertexData[ triangleIndex * 6 + 1 ];
1440 const double bX = vertexData[ triangleIndex * 6 + 2 ];
1441 const double bY = vertexData[ triangleIndex * 6 + 3 ];
1442 const double cX = vertexData[ triangleIndex * 6 + 4 ];
1443 const double cY = vertexData[ triangleIndex * 6 + 5 ];
1448 if ( acceptPoint( candidate ) )
1454 else if ( maxTriesPerPoint != 0 )
1458 if ( tries == maxTriesPerPoint )
1469 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1472 return QVector< QgsPointXY >();
1475#if (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=11) || GEOS_VERSION_MAJOR>3
1485 double pointSpacingAngleTolerance )
1491 std::unique_ptr< QgsCircularString > out;
1492 out.reset( qgsgeometry_cast< QgsCircularString * >( curve )->clone() );
1497 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1498 const QgsCompoundCurve *in = qgsgeometry_cast< const QgsCompoundCurve * >( curve );
1499 for (
int i = 0; i < in->
nCurves(); i ++ )
1501 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1504 if (
const QgsCompoundCurve *processedCompoundCurve = qgsgeometry_cast< const QgsCompoundCurve *>( processed.get() ) )
1506 for (
int i = 0; i < processedCompoundCurve->nCurves(); ++i )
1508 out->addCurve( processedCompoundCurve->curveAt( i )->clone() );
1513 out->addCurve( processed.release() );
1521 const QgsLineString *lineString = qgsgeometry_cast< QgsLineString * >( curve );
1523 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1526 const unsigned int minQuadEdges = 2;
1539 out->addCurve( lineString->
clone() );
1545 QVector< int > edgesInArcs( numEdges + 1, 0 );
1549 double abX = b.x() - a.
x();
1550 double abY = b.y() - a.
y();
1552 double cbX = b.x() -
c.x();
1553 double cbY = b.y() -
c.y();
1555 double dot = ( abX * cbX + abY * cbY );
1556 double cross = ( abX * cbY - abY * cbX );
1558 double alpha = std::atan2( cross, dot );
1573 double centerX = 0.0;
1574 double centerY = 0.0;
1577 while ( i < numEdges - 2 )
1579 unsigned int arcEdges = 0;
1580 double numQuadrants = 0;
1583 bool foundArc =
false;
1585 a1 = lineString->
pointN( i );
1586 a2 = lineString->
pointN( i + 1 );
1587 a3 = lineString->
pointN( i + 2 );
1590 for ( j = i + 3; j < numEdges + 1; j++ )
1592 b = lineString->
pointN( j );
1599 for ( k = j - 1; k > j - 4; k-- )
1600 edgesInArcs[k] = currentArc;
1620 arcEdges = j - 1 - i;
1621 if ( first.
x() == b.x() && first.
y() == b.y() )
1629 angle = arcAngle( first,
QgsPoint( centerX, centerY ), b );
1635 angle = 2 * M_PI + angle;
1636 numQuadrants = ( 4 * angle ) / ( 2 * M_PI );
1639 if ( arcEdges < minQuadEdges * numQuadrants )
1642 for ( k = j - 1; k >= i; k-- )
1659 int edgeType = edgesInArcs[0];
1661 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1666 QVector< QgsPoint > points;
1667 for (
int j = start; j < end + 2; ++ j )
1669 points.append( lineString->
pointN( j ) );
1671 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1672 out->addCurve( straightSegment.release() );
1677 QVector< QgsPoint > points;
1678 points.append( lineString->
pointN( start ) );
1679 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1680 points.append( lineString->
pointN( end + 1 ) );
1681 std::unique_ptr< QgsCircularString > curvedSegment = std::make_unique< QgsCircularString >();
1682 curvedSegment->setPoints( points );
1683 out->addCurve( curvedSegment.release() );
1687 for (
int i = 1; i < numEdges; i++ )
1689 if ( edgeType != edgesInArcs[i] )
1692 addPointsToCurve( start, end, edgeType );
1694 edgeType = edgesInArcs[i];
1700 addPointsToCurve( start, end, edgeType );
1705 std::unique_ptr< QgsCircularString > res;
1706 res.reset( qgsgeometry_cast< const QgsCircularString * >( out->simplifiedTypeRef() )->clone() );
1720 return lineToCurve( qgsgeometry_cast< const QgsCurve * >( geom ), distanceTolerance, angleTolerance );
1725 const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( geom );
1726 std::unique_ptr< QgsCurvePolygon > result = std::make_unique< QgsCurvePolygon>();
1729 distanceTolerance, angleTolerance ).release() );
1733 distanceTolerance, angleTolerance ).release() );
1753 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1755 int numGeom = gc->numGeometries();
1756 QVector< QgsAbstractGeometry * > geometryList;
1757 geometryList.reserve( numGeom );
1758 for (
int i = 0; i < numGeom; ++i )
1781 area = std::numeric_limits<double>::max();
1783 width = std::numeric_limits<double>::max();
1784 height = std::numeric_limits<double>::max();
1790 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1801 double totalRotation = 0;
1802 while ( hull->nextVertex( vertexId, pt2 ) )
1805 double rotateAngle = 180.0 / M_PI * currentAngle;
1806 totalRotation += rotateAngle;
1808 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1809 t.rotate( rotateAngle );
1810 t.translate( -pt0.
x(), -pt0.
y() );
1812 hull->transform( t );
1815 double currentArea = bounds.
width() * bounds.
height();
1816 if ( currentArea < area )
1820 angle = totalRotation;
1821 width = bounds.
width();
1822 height = bounds.
height();
1831 if ( width > height )
1833 width = minRect.
height();
1834 height = minRect.
width();
1835 angle = angle + 90.0;
1839 if ( angle > 180.0 )
1840 angle = std::fmod( angle, 180.0 );
1847 const int totalPoints = line->
numPoints();
1848 if ( totalPoints < 2 )
1851 const double *x = line->
xData();
1852 const double *y = line->
yData();
1854 double prevX = *x++;
1855 double prevY = *y++;
1857 QVector< double > outX;
1858 QVector< double > outY;
1859 const double totalLength = line->
length();
1861 const int maxRepetitions = std::ceil( totalLength / wavelength );
1862 if ( !strictWavelength )
1863 wavelength = totalLength / maxRepetitions;
1865 const int estimatedPoints = maxRepetitions * 2 + 2;
1866 outX.reserve( estimatedPoints );
1867 outY.reserve( estimatedPoints );
1868 outX.append( prevX );
1869 outY.append( prevY );
1871 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1873 for (
int i = 1; i < totalPoints; ++i )
1875 double thisX = *x++;
1876 double thisY = *y++;
1880 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1883 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1888 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1889 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1891 outX.append( outPointX );
1892 outY.append( outPointY );
1894 distanceToNextPointFromStartOfSegment += wavelength / 2;
1900 distanceToNextPointFromStartOfSegment -= segmentLength;
1903 outX.append( prevX );
1904 outY.append( prevY );
1906 return std::make_unique< QgsLineString >( outX, outY );
1910 const double minimumWavelength,
const double maximumWavelength,
1911 const double minimumAmplitude,
const double maximumAmplitude,
1912 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1914 const int totalPoints = line->
numPoints();
1915 if ( totalPoints < 2 )
1918 const double *x = line->
xData();
1919 const double *y = line->
yData();
1921 double prevX = *x++;
1922 double prevY = *y++;
1924 QVector< double > outX;
1925 QVector< double > outY;
1926 const double totalLength = line->
length();
1928 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1930 const int estimatedPoints = maxRepetitions * 2 + 2;
1931 outX.reserve( estimatedPoints );
1932 outY.reserve( estimatedPoints );
1933 outX.append( prevX );
1934 outY.append( prevY );
1936 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1937 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1938 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1941 for (
int i = 1; i < totalPoints; ++i )
1943 double thisX = *x++;
1944 double thisY = *y++;
1948 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1951 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1956 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1957 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1958 outX.append( outPointX );
1959 outY.append( outPointY );
1961 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1962 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1964 distanceToNextPointFromStartOfSegment += wavelength / 2;
1970 distanceToNextPointFromStartOfSegment -= segmentLength;
1973 outX.append( prevX );
1974 outY.append( prevY );
1976 return std::make_unique< QgsLineString >( outX, outY );
1981 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1985 geom = segmentizedCopy.get();
1996 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1999 wavelength, amplitude, strictWavelength ).release() );
2003 wavelength, amplitude, strictWavelength ).release() );
2010std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2012 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2016 geom = segmentizedCopy.get();
2027 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2030 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2034 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2010std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt ) {
…}
2057 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2059 int numGeom = gc->numGeometries();
2060 QVector< QgsAbstractGeometry * > geometryList;
2061 geometryList.reserve( numGeom );
2062 for (
int i = 0; i < numGeom; ++i )
2064 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2082 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2091 std::random_device rd;
2092 std::mt19937 mt( seed == 0 ? rd() : seed );
2093 std::uniform_real_distribution<> uniformDist( 0, 1 );
2100 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2102 int numGeom = gc->numGeometries();
2103 QVector< QgsAbstractGeometry * > geometryList;
2104 geometryList.reserve( numGeom );
2105 for (
int i = 0; i < numGeom; ++i )
2107 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2125 const int totalPoints = line->
numPoints();
2126 if ( totalPoints < 2 )
2129 const double *x = line->
xData();
2130 const double *y = line->
yData();
2132 double prevX = *x++;
2133 double prevY = *y++;
2135 QVector< double > outX;
2136 QVector< double > outY;
2137 const double totalLength = line->
length();
2139 const int maxRepetitions = std::ceil( totalLength / wavelength );
2140 if ( !strictWavelength )
2141 wavelength = totalLength / maxRepetitions;
2143 const int estimatedPoints = maxRepetitions * 4 + 2;
2144 outX.reserve( estimatedPoints );
2145 outY.reserve( estimatedPoints );
2146 outX.append( prevX );
2147 outY.append( prevY );
2150 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2151 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2153 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2156 for (
int i = 1; i < totalPoints; ++i )
2158 double thisX = *x++;
2159 double thisY = *y++;
2163 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2166 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2171 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2172 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2173 outX.append( pX + side * amplitude * sinAngle );
2174 outY.append( pY + side * amplitude * cosAngle );
2175 outX.append( pX - side * amplitude * sinAngle );
2176 outY.append( pY - side * amplitude * cosAngle );
2178 distanceToNextPointFromStartOfSegment += wavelength / 2;
2184 distanceToNextPointFromStartOfSegment -= segmentLength;
2190 outX.append( prevX );
2191 outY.append( prevY );
2193 return std::make_unique< QgsLineString >( outX, outY );
2197 const double minimumWavelength,
const double maximumWavelength,
2198 const double minimumAmplitude,
const double maximumAmplitude,
2199 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2201 const int totalPoints = line->
numPoints();
2202 if ( totalPoints < 2 )
2205 const double *x = line->
xData();
2206 const double *y = line->
yData();
2208 double prevX = *x++;
2209 double prevY = *y++;
2211 QVector< double > outX;
2212 QVector< double > outY;
2213 const double totalLength = line->
length();
2215 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2217 const int estimatedPoints = maxRepetitions * 4 + 2;
2218 outX.reserve( estimatedPoints );
2219 outY.reserve( estimatedPoints );
2220 outX.append( prevX );
2221 outY.append( prevY );
2223 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2226 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2227 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2229 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2230 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2233 for (
int i = 1; i < totalPoints; ++i )
2235 double thisX = *x++;
2236 double thisY = *y++;
2240 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2243 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2248 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2249 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2250 outX.append( pX + side * amplitude * sinAngle );
2251 outY.append( pY + side * amplitude * cosAngle );
2253 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2254 outX.append( pX - side * amplitude * sinAngle );
2255 outY.append( pY - side * amplitude * cosAngle );
2257 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2258 distanceToNextPointFromStartOfSegment += wavelength / 2;
2264 distanceToNextPointFromStartOfSegment -= segmentLength;
2267 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2268 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2269 outX.append( prevX );
2270 outY.append( prevY );
2272 return std::make_unique< QgsLineString >( outX, outY );
2277 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2281 geom = segmentizedCopy.get();
2292 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2295 wavelength, amplitude, strictWavelength ).release() );
2299 wavelength, amplitude, strictWavelength ).release() );
2306std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2308 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2312 geom = segmentizedCopy.get();
2323 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2326 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2330 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2306std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt ) {
…}
2353 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2355 int numGeom = gc->numGeometries();
2356 QVector< QgsAbstractGeometry * > geometryList;
2357 geometryList.reserve( numGeom );
2358 for (
int i = 0; i < numGeom; ++i )
2360 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2378 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2387 std::random_device rd;
2388 std::mt19937 mt( seed == 0 ? rd() : seed );
2389 std::uniform_real_distribution<> uniformDist( 0, 1 );
2396 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2398 int numGeom = gc->numGeometries();
2399 QVector< QgsAbstractGeometry * > geometryList;
2400 geometryList.reserve( numGeom );
2401 for (
int i = 0; i < numGeom; ++i )
2403 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2421 const int totalPoints = line->
numPoints();
2422 if ( totalPoints < 2 )
2425 const double *x = line->
xData();
2426 const double *y = line->
yData();
2428 double prevX = *x++;
2429 double prevY = *y++;
2431 const double totalLength = line->
length();
2433 const int maxRepetitions = std::ceil( totalLength / wavelength );
2434 if ( !strictWavelength )
2435 wavelength = totalLength / maxRepetitions;
2437 const int segments = 10;
2441 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2442 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2443 bool isFirstPart =
true;
2445 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2446 int bufferIndex = 1;
2447 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2449 double segmentAngleRadians = 0;
2450 double remainingDistance = totalLength;
2451 double totalCoveredDistance = 0;
2453 for (
int i = 1; i < totalPoints; ++i )
2455 double thisX = *x++;
2456 double thisY = *y++;
2460 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2463 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2466 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2468 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2469 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2471 if ( bufferIndex == 0 )
2473 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2474 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2476 distanceToNextPointFromStartOfSegment += wavelength / 4;
2478 else if ( bufferIndex == 1 && isFirstPart )
2480 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2481 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2482 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2483 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2485 distanceToNextPointFromStartOfSegment += wavelength / 8;
2487 else if ( bufferIndex == 1 )
2489 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2490 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2491 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2492 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2494 distanceToNextPointFromStartOfSegment += wavelength / 4;
2496 else if ( bufferIndex == 2 )
2498 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2499 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2503 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2504 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2505 isFirstPart =
false;
2510 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2511 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2512 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2514 out->append( bezier.get() );
2517 xOutBuffer[0] = xOutBuffer[3];
2518 yOutBuffer[0] = yOutBuffer[3];
2521 distanceToNextPointFromStartOfSegment += wavelength / 4;
2524 totalCoveredDistance += segmentLength;
2527 distanceToNextPointFromStartOfSegment -= segmentLength;
2530 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2531 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2532 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2533 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2536 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2537 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2540 out->append( bezier.get() );
2546 const double minimumWavelength,
const double maximumWavelength,
2547 const double minimumAmplitude,
const double maximumAmplitude,
2548 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2550 const int totalPoints = line->
numPoints();
2551 if ( totalPoints < 2 )
2554 const double *x = line->
xData();
2555 const double *y = line->
yData();
2557 double prevX = *x++;
2558 double prevY = *y++;
2560 const double totalLength = line->
length();
2562 const int segments = 10;
2566 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2567 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2568 bool isFirstPart =
true;
2570 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2571 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2573 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2574 int bufferIndex = 1;
2575 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2577 double segmentAngleRadians = 0;
2579 double remainingDistance = totalLength;
2580 double totalCoveredDistance = 0;
2582 for (
int i = 1; i < totalPoints; ++i )
2584 double thisX = *x++;
2585 double thisY = *y++;
2589 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2592 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2595 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2597 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2598 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2600 if ( bufferIndex == 0 )
2602 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2603 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2605 distanceToNextPointFromStartOfSegment += wavelength / 4;
2607 else if ( bufferIndex == 1 && isFirstPart )
2609 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2610 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2611 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2612 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2614 distanceToNextPointFromStartOfSegment += wavelength / 8;
2616 else if ( bufferIndex == 1 )
2618 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2619 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2620 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2621 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2623 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2624 distanceToNextPointFromStartOfSegment += wavelength / 4;
2626 else if ( bufferIndex == 2 )
2628 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2629 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2633 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2634 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2635 isFirstPart =
false;
2640 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2641 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2642 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2644 out->append( bezier.get() );
2647 xOutBuffer[0] = xOutBuffer[3];
2648 yOutBuffer[0] = yOutBuffer[3];
2652 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2654 distanceToNextPointFromStartOfSegment += wavelength / 4;
2657 totalCoveredDistance += segmentLength;
2661 distanceToNextPointFromStartOfSegment -= segmentLength;
2664 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2665 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2666 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2667 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2669 if ( out->isEmpty() )
2673 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2676 out->append( bezier.get() );
2681 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2682 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2685 out->append( bezier.get() );
2693 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2697 geom = segmentizedCopy.get();
2708 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2711 wavelength, amplitude, strictWavelength ).release() );
2715 wavelength, amplitude, strictWavelength ).release() );
2722std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2724 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2728 geom = segmentizedCopy.get();
2739 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2742 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2746 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2722std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt ) {
…}
2769 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2771 int numGeom = gc->numGeometries();
2772 QVector< QgsAbstractGeometry * > geometryList;
2773 geometryList.reserve( numGeom );
2774 for (
int i = 0; i < numGeom; ++i )
2776 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2794 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2803 std::random_device rd;
2804 std::mt19937 mt( seed == 0 ? rd() : seed );
2805 std::uniform_real_distribution<> uniformDist( 0, 1 );
2812 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2814 int numGeom = gc->numGeometries();
2815 QVector< QgsAbstractGeometry * > geometryList;
2816 geometryList.reserve( numGeom );
2817 for (
int i = 0; i < numGeom; ++i )
2819 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2836 const QVector< double> &pattern,
2840 double patternOffset )
2842 const int totalPoints = line->
numPoints();
2843 if ( totalPoints < 2 )
2846 const int patternSize = pattern.size();
2848 const double *x = line->
xData();
2849 const double *y = line->
yData();
2851 double prevX = *x++;
2852 double prevY = *y++;
2854 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2856 QVector< double > outX;
2857 QVector< double > outY;
2858 const double totalLength = line->
length();
2860 double patternLength = 0;
2861 double patternDashLength = 0;
2862 double patternGapLength = 0;
2863 for (
int i = 0; i < pattern.size(); ++i )
2865 patternLength += pattern.at( i );
2867 patternDashLength += pattern.at( i );
2869 patternGapLength += pattern.at( i );
2872 double firstPatternLength = 0;
2873 double firstPatternDashLength = 0;
2874 double firstPatternGapLength = 0;
2875 switch ( startRule )
2879 firstPatternLength = patternLength;
2880 firstPatternDashLength = patternDashLength;
2881 firstPatternGapLength = patternGapLength;
2884 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2885 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2886 firstPatternGapLength = patternGapLength;
2889 firstPatternLength = pattern.at( patternSize - 1 );
2890 firstPatternDashLength = 0;
2891 firstPatternGapLength = pattern.at( patternSize - 1 );
2894 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2895 firstPatternDashLength = 0;
2896 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2900 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2902 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2903 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2904 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2908 lastPatternLength = 0;
2909 lastPatternDashLength = 0;
2910 lastPatternGapLength = 0;
2913 lastPatternLength -= pattern.at( patternSize - 1 );
2914 lastPatternGapLength -= pattern.at( patternSize - 1 );
2917 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2918 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2919 lastPatternGapLength -= pattern.at( patternSize - 1 );
2922 lastPatternGapLength = patternGapLength;
2925 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2926 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2930 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2931 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2933 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2934 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2935 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2937 double dashLengthScalingFactor = 1;
2938 double gapLengthScalingFactor = 1;
2942 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2944 switch ( adjustment )
2947 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2948 gapLengthScalingFactor = dashLengthScalingFactor;
2951 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2954 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2959 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2960 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2962 const int maxPatterns = middlePatternRepetitions + 2;
2963 result->reserve( maxPatterns );
2965 int patternIndex = 0;
2966 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2968 switch ( startRule )
2974 distanceToNextPointFromStartOfSegment *= 0.5;
2977 patternIndex = patternSize - 1;
2979 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2982 patternIndex = patternSize - 1;
2984 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2988 const double adjustedOffset = fmod( patternOffset, patternLength );
2989 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
2993 double remainingOffset = scaledOffset;
2994 while ( remainingOffset > 0 )
2996 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
2998 distanceToNextPointFromStartOfSegment -= remainingOffset;
3002 remainingOffset -= distanceToNextPointFromStartOfSegment;
3005 if ( patternIndex == patternSize )
3008 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3014 outX.append( prevX );
3015 outY.append( prevY );
3018 for (
int i = 1; i < totalPoints; ++i )
3020 double thisX = *x++;
3021 double thisY = *y++;
3024 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
3027 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
3042 if ( patternIndex >= patternSize )
3045 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3050 outX.append( thisX );
3051 outY.append( thisY );
3056 distanceToNextPointFromStartOfSegment -= segmentLength;
3061 outX.append( prevX );
3062 outY.append( prevY );
3070 const QVector<double> &pattern,
3074 double patternOffset )
3076 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
3080 geom = segmentizedCopy.get();
3091 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
3094 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
3095 result->addGeometry( exteriorParts->geometryN( i )->clone() );
3100 for (
int j = 0; j < ringParts->numGeometries(); ++j )
3101 result->addGeometry( ringParts->geometryN( j )->clone() );
3110 if ( pattern.size() < 2 )
3114 if ( !mGeometry || mGeometry->
isEmpty() )
3124 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
3126 int numGeom = gc->numGeometries();
3127 QVector< QgsAbstractGeometry * > geometryList;
3128 geometryList.reserve( numGeom );
3129 for (
int i = 0; i < numGeom; ++i )
3131 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
3139 for (
int j = 0; j < collection->numGeometries(); ++j )
3141 first.
addPart( collection->geometryN( j )->clone() );
DashPatternSizeAdjustment
Dash pattern size adjustment options.
@ ScaleDashOnly
Only dash lengths are adjusted.
@ ScaleBothDashAndGap
Both the dash and gap lengths are adjusted equally.
@ ScaleGapOnly
Only gap lengths are adjusted.
DashPatternLineEndingRule
Dash pattern line ending rules.
@ HalfDash
Start or finish the pattern with a half length dash.
@ HalfGap
Start or finish the pattern with a half length gap.
@ FullGap
Start or finish the pattern with a full gap.
@ FullDash
Start or finish the pattern with a full dash.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CompoundCurve
CompoundCurve.
@ CircularString
CircularString.
The vertex_iterator class provides STL-style iterator for vertices.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
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 ...
Qgis::GeometryOperationResult addPart(const QVector< QgsPointXY > &points, Qgis::GeometryType geomType=Qgis::GeometryType::Unknown)
Adds a new part to a the geometry.
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false)
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries, const QgsGeometryParameters ¶meters=QgsGeometryParameters())
Compute the unary union on a list of geometries.
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.