43 : mGeometry( geometry.constGet() )
70 double dx = p2.
x() - p1.
x();
71 double dy = p2.
y() - p1.
y();
72 if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
74 if ( fabs( dx ) >= fabs( dy ) )
76 double dev = fabs( dy ) / fabs( dx );
83 double dev = fabs( dx ) / fabs( dy );
101 std::array<Direction, 5> dirs;
108 while ( current != end )
118 else if ( dir != dirs[idx - 1] )
128 ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
129 std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
135 int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
136 for (
int i = 1; i < 4; ++i )
138 if ( dirs[i] != oriented[( idx + i ) % 4] )
174 if ( vertexCount < 4 )
176 else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
180 std::array<Direction, 4> dirs;
181 std::tie( found4Dirs, dirs ) =
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
195 QVector<QgsLineString *> linesToProcess;
200 linesToProcess.reserve( multiCurve->
partCount() );
201 for (
int i = 0; i < multiCurve->
partCount(); ++i )
203 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
210 linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
213 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() :
nullptr );
216 if ( !linesToProcess.empty() )
218 std::unique_ptr< QgsLineString > secondline;
219 for (
QgsLineString *line : std::as_const( linesToProcess ) )
221 QTransform transform = QTransform::fromTranslate( x, y );
223 secondline.reset( line->reversed() );
224 secondline->transform( transform );
226 line->append( secondline.get() );
227 line->addVertex( line->pointN( 0 ) );
233 multipolygon->addGeometry( polygon );
255 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
259 , d( polygon->pointDistanceToBoundary( x, y ) )
260 , max( d + h * M_SQRT2 )
275struct GreaterThanByMax
277 bool operator()(
const Cell *lhs,
const Cell *rhs )
const
279 return rhs->max > lhs->max;
283Cell *getCentroidCell(
const QgsPolygon *polygon )
291 for (
int i = 0, j = len - 1; i < len; j = i++ )
293 double aX = exterior->
xAt( i );
294 double aY = exterior->
yAt( i );
295 double bX = exterior->
xAt( j );
296 double bY = exterior->
yAt( j );
297 double f = aX * bY - bX * aY;
298 x += ( aX + bX ) * f;
299 y += ( aY + bY ) * f;
303 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
305 return new Cell( x / area, y / area, 0.0, polygon );
308QgsPoint surfacePoleOfInaccessibility(
const QgsSurface *surface,
double precision,
double &distanceFromBoundary )
310 std::unique_ptr< QgsPolygon > segmentizedPoly;
315 polygon = segmentizedPoly.get();
322 double cellSize = std::min( bounds.
width(), bounds.
height() );
327 double h = cellSize / 2.0;
328 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
335 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
340 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
343 std::unique_ptr< Cell > bboxCell(
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
346 if ( bboxCell->d > bestCell->d )
348 bestCell = std::move( bboxCell );
351 while ( !cellQueue.empty() )
354 std::unique_ptr< Cell > cell( cellQueue.top() );
356 Cell *currentCell = cell.get();
359 if ( currentCell->d > bestCell->d )
361 bestCell = std::move( cell );
365 if ( currentCell->max - bestCell->d <= precision )
369 h = currentCell->h / 2.0;
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 ) );
372 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y + h, h, polygon ) );
373 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
376 distanceFromBoundary = bestCell->d;
378 return QgsPoint( bestCell->x, bestCell->y );
386 if ( distanceFromBoundary )
387 *distanceFromBoundary = std::numeric_limits<double>::max();
389 if ( !mGeometry || mGeometry->isEmpty() )
392 if ( precision <= 0 )
397 int numGeom = gc->numGeometries();
400 for (
int i = 0; i < numGeom; ++i )
406 double dist = std::numeric_limits<double>::max();
407 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
408 if ( dist > maxDist )
418 if ( distanceFromBoundary )
419 *distanceFromBoundary = maxDist;
428 double dist = std::numeric_limits<double>::max();
429 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
433 if ( distanceFromBoundary )
434 *distanceFromBoundary = dist;
445 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
471 for (
int i = 0; i < numPoints; ++i )
473 if ( !isClosed && i == numPoints - 1 )
475 else if ( !isClosed && i == 0 )
484 a = ring->
pointN( numPoints - 1 );
487 if ( i == numPoints - 1 )
496 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
506 double lowerThreshold,
double upperThreshold )
515 double scale = 2.0 * std::min( p.
length(), q.
length() );
519 double dotProduct = p * q;
528 if ( dotProduct < -M_SQRT1_2 )
537 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
542 double minScore = std::numeric_limits<double>::max();
547 std::unique_ptr< QgsLineString > best( ring->
clone() );
549 QVector< QgsVector > motions;
550 motions.reserve( numPoints );
552 for (
int it = 0; it < iterations; ++it )
560 for (
int i = 0; i < numPoints; ++i )
562 if ( isClosed && i == numPoints - 1 )
563 motions << motions.at( 0 );
564 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
574 a = ring->
pointN( numPoints - 1 );
577 if ( i == numPoints - 1 )
582 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
589 for (
int i = 0; i < numPoints; ++i )
591 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
592 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
595 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
596 if ( newScore < minScore )
598 best.reset( ring->
clone() );
602 if ( minScore < tolerance )
608 return best.release();
614 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
618 geom = segmentizedCopy.get();
624 maxIterations, tolerance, lowerThreshold, upperThreshold );
633 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
637 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
653 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
654 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
658 int numGeom = gc->numGeometries();
659 QVector< QgsAbstractGeometry * > geometryList;
660 geometryList.reserve( numGeom );
661 for (
int i = 0; i < numGeom; ++i )
663 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
682 QVector< double > outX;
683 QVector< double > outY;
684 QVector< double > outZ;
685 QVector< double > outM;
686 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
689 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
690 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
691 bool withZ = ring->
is3D();
693 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
696 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
709 int extraNodesThisSegment = extraNodesPerSegment;
710 for (
int i = 0; i < nPoints - 1; ++i )
713 x2 = ring->
xAt( i + 1 );
715 y2 = ring->
yAt( i + 1 );
719 z2 = ring->
zAt( i + 1 );
724 m2 = ring->
mAt( i + 1 );
734 if ( extraNodesPerSegment < 0 )
738 if ( extraNodesThisSegment >= 1 )
739 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
742 for (
int j = 0; j < extraNodesThisSegment; ++j )
744 double delta = multiplier * ( j + 1 );
745 xOut = x1 + delta * ( x2 - x1 );
746 yOut = y1 + delta * ( y2 - y1 );
748 zOut = z1 + delta * ( z2 - z1 );
750 mOut = m1 + delta * ( m2 - m1 );
760 outX << ring->
xAt( nPoints - 1 );
761 outY << ring->
yAt( nPoints - 1 );
763 outZ << ring->
zAt( nPoints - 1 );
765 outM << ring->
mAt( nPoints - 1 );
773 if ( extraNodesPerSegment < 0 &&
qgsDoubleNear( distance, 0 ) )
776 return geom->
clone();
779 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
783 geom = segmentizedCopy.get();
797 extraNodesPerSegment, distance ) );
801 extraNodesPerSegment, distance ) );
823 int numGeom = gc->numGeometries();
824 QVector< QgsAbstractGeometry * > geometryList;
825 geometryList.reserve( numGeom );
826 for (
int i = 0; i < numGeom; ++i )
828 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
859 int numGeom = gc->numGeometries();
860 QVector< QgsAbstractGeometry * > geometryList;
861 geometryList.reserve( numGeom );
862 for (
int i = 0; i < numGeom; ++i )
889 "line_segment_dist_comparer",
890 "AB must not be collinear with the origin." );
892 "line_segment_dist_comparer",
893 "CD must not be collinear with the origin." );
910 if ( ab.
end() == cd.
end() || oad != oab )
920 if ( cdb == 0 && cda == 0 )
922 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
924 else if ( cda == cdb || cda == 0 || cdb == 0 )
927 return cdo == cda || cdo == cdb;
943 const bool aIsLeft = a.
x() < mVertex.x();
944 const bool bIsLeft = b.
x() < mVertex.x();
945 if ( aIsLeft != bIsLeft )
950 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
952 return b.
y() < a.
y();
956 return a.
y() < b.
y();
988 const int abo =
segment.pointLeftOfLine( origin );
995 const double distA = ao * direction;
996 const double distB = ( origin -
segment.end() ) * direction;
998 if ( distA > 0 && distB > 0 )
1004 if ( ( distA > 0 ) != ( distB > 0 ) )
1005 intersectPoint = origin;
1006 else if ( distA > distB )
1007 intersectPoint =
segment.start();
1009 intersectPoint =
segment.end();
1017 if ( u < 0.0 || 1.0 < u )
1024 intersectPoint = origin + direction * t;
1033 if ( radius1 > radius2 )
1040 QVector<QgsPointXY> points;
1062 std::vector< std::unique_ptr<QgsLineString > > temporarySegmentizedLines;
1063 std::vector< const QgsLineString * > linesToProcess;
1068 for (
int i = 0; i < multiCurve->partCount(); ++i )
1078 linesToProcess.emplace_back( lineString );
1082 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( part->
segmentize() ) );
1083 linesToProcess.emplace_back( segmentizedCurve.get() );
1084 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1091 if ( curve->nCoordinates() > 0 )
1095 linesToProcess.emplace_back( lineString );
1099 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( curve->segmentize() ) );
1100 linesToProcess.emplace_back( segmentizedCurve.get() );
1101 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1106 if ( linesToProcess.empty() )
1109 g.mLastError = QStringLiteral(
"Input geometry was not a curve type geometry" );
1113 QVector<QgsGeometry> bufferedLines;
1114 bufferedLines.reserve( linesToProcess.size() );
1118 QVector<QgsGeometry> parts;
1120 double prevRadius = 0;
1123 std::unique_ptr< double[] > widths = widthFunction( line ) ;
1128 double thisRadius = widths[ i ] / 2.0;
1129 if ( thisRadius > 0 )
1133 QgsCircle circ( thisPoint, thisRadius );
1135 parts << thisCircle;
1144 if ( prevRadius > 0 || thisRadius > 0 )
1146 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1147 if ( !points.empty() )
1152 int beforeVertex = 0;
1153 int afterVertex = 0;
1155 double sqrDistPrev = 0;
1156 for (
int j = 0; j < points.count(); ++j )
1160 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1163 points.append( points.at( 0 ) );
1165 auto poly = std::make_unique< QgsPolygon >();
1167 if ( poly->area() > 0 )
1172 prevPoint = thisPoint;
1173 prevRadius = thisRadius;
1174 prevCircle = thisCircle;
1189 start = std::fabs( start );
1190 end = std::fabs( end );
1192 auto interpolateWidths = [ start, end ](
const QgsLineString * line )->std::unique_ptr<
double [] >
1196 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1198 widths[line->nCoordinates() - 1] = end;
1200 double lineLength = line->length();
1201 double currentLength = 0;
1202 QgsPoint prevPoint = line->pointN( 0 );
1203 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1205 QgsPoint point = line->pointN( i );
1206 double segmentLength = point.
distance( prevPoint );
1207 currentLength += segmentLength;
1208 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1209 double delta = lengthFraction * ( end - start );
1210 widths[i] = start + delta;
1222 auto widthByM = [](
const QgsLineString * line )->std::unique_ptr<
double [] >
1224 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1225 for (
int i = 0; i < line->nCoordinates(); ++i )
1227 widths[ i ] = line->mAt( i );
1236 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1246 for (
int i = 0; i < ms->numGeometries(); ++i )
1249 return QVector< QgsPointXY >();
1276 return QVector< QgsPointXY >();
1278 if ( !t.
error().isEmpty() )
1281 return QVector< QgsPointXY >();
1284 const QVector<float> triangleData = t.
data();
1285 if ( triangleData.empty() )
1286 return QVector< QgsPointXY >();
1289 std::vector< double > cumulativeAreas;
1291 double totalArea = 0;
1292 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1295 return QVector< QgsPointXY >();
1297 const float aX = *it++;
1298 const float aY = *it++;
1300 const float bX = *it++;
1301 const float bY = *it++;
1303 const float cX = *it++;
1304 const float cY = *it++;
1309 cumulativeAreas.emplace_back( totalArea );
1312 std::random_device rd;
1313 std::mt19937 mt( seed == 0 ? rd() : seed );
1314 std::uniform_real_distribution<> uniformDist( 0, 1 );
1317 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1320 const double target = random * totalArea;
1321 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1326 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1331 QVector<QgsPointXY> result;
1332 result.reserve( count );
1334 for (
int i = 0; i < count; )
1337 return QVector< QgsPointXY >();
1339 const double triangleIndexRnd = uniformDist( mt );
1341 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1344 const double weightB = uniformDist( mt );
1345 const double weightC = uniformDist( mt );
1350 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1351 const double aY = triangleData.at( triangleIndex * 9 + 1 ) + bounds.
yMinimum();
1352 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1353 const double bY = triangleData.at( triangleIndex * 9 + 4 ) + bounds.
yMinimum();
1354 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1355 const double cY = triangleData.at( triangleIndex * 9 + 7 ) + bounds.
yMinimum();
1359 if ( acceptPoint( candidate ) )
1365 else if ( maxTriesPerPoint != 0 )
1369 if ( tries == maxTriesPerPoint )
1380 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1384 std::unique_ptr<QgsAbstractGeometry> triangulation =
geos.constrainedDelaunayTriangulation( &error );
1385 if ( !triangulation || triangulation->isEmpty( ) )
1396 std::vector< double > cumulativeAreas;
1398 double totalArea = 0;
1399 std::vector< double > vertices(
static_cast< std::size_t
>( mp->
numGeometries() ) * 6 );
1400 double *vertexData = vertices.data();
1414 const double aX = exterior->
xAt( 0 );
1415 const double aY = exterior->
yAt( 0 );
1416 const double bX = exterior->
xAt( 1 );
1417 const double bY = exterior->
yAt( 1 );
1418 const double cX = exterior->
xAt( 2 );
1419 const double cY = exterior->
yAt( 2 );
1429 cumulativeAreas.emplace_back( totalArea );
1432 std::random_device rd;
1433 std::mt19937 mt( seed == 0 ? rd() : seed );
1434 std::uniform_real_distribution<> uniformDist( 0, 1 );
1437 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1440 const double target = random * totalArea;
1441 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1446 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1451 QVector<QgsPointXY> result;
1452 result.reserve( count );
1454 vertexData = vertices.data();
1455 for (
int i = 0; i < count; )
1458 return QVector< QgsPointXY >();
1460 const double triangleIndexRnd = uniformDist( mt );
1462 const std::size_t triangleIndex = selectRandomTriangle( triangleIndexRnd );
1465 const double weightB = uniformDist( mt );
1466 const double weightC = uniformDist( mt );
1471 const double aX = vertexData[ triangleIndex * 6 ];
1472 const double aY = vertexData[ triangleIndex * 6 + 1 ];
1473 const double bX = vertexData[ triangleIndex * 6 + 2 ];
1474 const double bY = vertexData[ triangleIndex * 6 + 3 ];
1475 const double cX = vertexData[ triangleIndex * 6 + 4 ];
1476 const double cY = vertexData[ triangleIndex * 6 + 5 ];
1481 if ( acceptPoint( candidate ) )
1487 else if ( maxTriesPerPoint != 0 )
1491 if ( tries == maxTriesPerPoint )
1502 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1505 return QVector< QgsPointXY >();
1508#if (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=11) || GEOS_VERSION_MAJOR>3
1518 double pointSpacingAngleTolerance )
1524 std::unique_ptr< QgsCircularString > out;
1530 auto out = std::make_unique< QgsCompoundCurve >();
1532 for (
int i = 0; i < in->
nCurves(); i ++ )
1534 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1539 for (
int i = 0; i < processedCompoundCurve->nCurves(); ++i )
1541 out->addCurve( processedCompoundCurve->curveAt( i )->clone() );
1546 out->addCurve( processed.release() );
1556 auto out = std::make_unique< QgsCompoundCurve >();
1559 const unsigned int minQuadEdges = 2;
1572 out->addCurve( lineString->
clone() );
1578 QVector< int > edgesInArcs( numEdges + 1, 0 );
1582 double abX = b.x() - a.
x();
1583 double abY = b.y() - a.
y();
1585 double cbX = b.x() -
c.x();
1586 double cbY = b.y() -
c.y();
1588 double dot = ( abX * cbX + abY * cbY );
1589 double cross = ( abX * cbY - abY * cbX );
1591 double alpha = std::atan2( cross, dot );
1606 double centerX = 0.0;
1607 double centerY = 0.0;
1610 while ( i < numEdges - 2 )
1612 unsigned int arcEdges = 0;
1613 double numQuadrants = 0;
1616 bool foundArc =
false;
1618 a1 = lineString->
pointN( i );
1619 a2 = lineString->
pointN( i + 1 );
1620 a3 = lineString->
pointN( i + 2 );
1623 for ( j = i + 3; j < numEdges + 1; j++ )
1625 b = lineString->
pointN( j );
1632 for ( k = j - 1; k > j - 4; k-- )
1633 edgesInArcs[k] = currentArc;
1653 arcEdges = j - 1 - i;
1654 if ( first.
x() == b.x() && first.
y() == b.y() )
1662 angle = arcAngle( first,
QgsPoint( centerX, centerY ), b );
1668 angle = 2 * M_PI + angle;
1669 numQuadrants = ( 4 * angle ) / ( 2 * M_PI );
1672 if ( arcEdges < minQuadEdges * numQuadrants )
1675 for ( k = j - 1; k >= i; k-- )
1692 int edgeType = edgesInArcs[0];
1694 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1699 QVector< QgsPoint > points;
1700 for (
int j = start; j < end + 2; ++ j )
1702 points.append( lineString->
pointN( j ) );
1704 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1705 out->addCurve( straightSegment.release() );
1710 QVector< QgsPoint > points;
1711 points.append( lineString->
pointN( start ) );
1712 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1713 points.append( lineString->
pointN( end + 1 ) );
1714 auto curvedSegment = std::make_unique< QgsCircularString >();
1715 curvedSegment->setPoints( points );
1716 out->addCurve( curvedSegment.release() );
1720 for (
int i = 1; i < numEdges; i++ )
1722 if ( edgeType != edgesInArcs[i] )
1725 addPointsToCurve( start, end, edgeType );
1727 edgeType = edgesInArcs[i];
1733 addPointsToCurve( start, end, edgeType );
1738 std::unique_ptr< QgsCircularString > res;
1759 auto result = std::make_unique< QgsCurvePolygon>();
1762 distanceTolerance, angleTolerance ).release() );
1766 distanceTolerance, angleTolerance ).release() );
1788 int numGeom = gc->numGeometries();
1789 QVector< QgsAbstractGeometry * > geometryList;
1790 geometryList.reserve( numGeom );
1791 for (
int i = 0; i < numGeom; ++i )
1814 area = std::numeric_limits<double>::max();
1816 width = std::numeric_limits<double>::max();
1817 height = std::numeric_limits<double>::max();
1819 if ( !mGeometry || mGeometry->nCoordinates() < 2 )
1823 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1832 if ( !hull->nextVertex( vertexId, pt0 ) )
1838 double totalRotation = 0;
1839 while ( hull->nextVertex( vertexId, pt2 ) )
1842 double rotateAngle = 180.0 / M_PI * currentAngle;
1843 totalRotation += rotateAngle;
1845 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1846 t.rotate( rotateAngle );
1847 t.translate( -pt0.
x(), -pt0.
y() );
1849 hull->transform( t );
1852 double currentArea = bounds.
width() * bounds.
height();
1853 if ( currentArea < area )
1857 angle = totalRotation;
1858 width = bounds.
width();
1859 height = bounds.
height();
1862 pt1 = hull->vertexAt( vertexId );
1868 if ( width > height )
1870 width = minRect.
height();
1871 height = minRect.
width();
1872 angle = angle + 90.0;
1876 if ( angle > 180.0 )
1877 angle = std::fmod( angle, 180.0 );
1884 const int totalPoints = line->
numPoints();
1885 if ( totalPoints < 2 )
1888 const double *x = line->
xData();
1889 const double *y = line->
yData();
1891 double prevX = *x++;
1892 double prevY = *y++;
1894 QVector< double > outX;
1895 QVector< double > outY;
1896 const double totalLength = line->
length();
1898 const int maxRepetitions = std::ceil( totalLength / wavelength );
1899 if ( !strictWavelength )
1900 wavelength = totalLength / maxRepetitions;
1902 const int estimatedPoints = maxRepetitions * 2 + 2;
1903 outX.reserve( estimatedPoints );
1904 outY.reserve( estimatedPoints );
1905 outX.append( prevX );
1906 outY.append( prevY );
1908 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1910 for (
int i = 1; i < totalPoints; ++i )
1912 double thisX = *x++;
1913 double thisY = *y++;
1917 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1920 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1925 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1926 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1928 outX.append( outPointX );
1929 outY.append( outPointY );
1931 distanceToNextPointFromStartOfSegment += wavelength / 2;
1937 distanceToNextPointFromStartOfSegment -= segmentLength;
1940 outX.append( prevX );
1941 outY.append( prevY );
1943 return std::make_unique< QgsLineString >( outX, outY );
1947 const double minimumWavelength,
const double maximumWavelength,
1948 const double minimumAmplitude,
const double maximumAmplitude,
1949 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1951 const int totalPoints = line->
numPoints();
1952 if ( totalPoints < 2 )
1955 const double *x = line->
xData();
1956 const double *y = line->
yData();
1958 double prevX = *x++;
1959 double prevY = *y++;
1961 QVector< double > outX;
1962 QVector< double > outY;
1963 const double totalLength = line->
length();
1965 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1967 const int estimatedPoints = maxRepetitions * 2 + 2;
1968 outX.reserve( estimatedPoints );
1969 outY.reserve( estimatedPoints );
1970 outX.append( prevX );
1971 outY.append( prevY );
1973 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1974 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1975 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1978 for (
int i = 1; i < totalPoints; ++i )
1980 double thisX = *x++;
1981 double thisY = *y++;
1985 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1988 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1993 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1994 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1995 outX.append( outPointX );
1996 outY.append( outPointY );
1998 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1999 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2001 distanceToNextPointFromStartOfSegment += wavelength / 2;
2007 distanceToNextPointFromStartOfSegment -= segmentLength;
2010 outX.append( prevX );
2011 outY.append( prevY );
2013 return std::make_unique< QgsLineString >( outX, outY );
2018 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2022 geom = segmentizedCopy.get();
2033 auto result = std::make_unique< QgsPolygon >();
2036 wavelength, amplitude, strictWavelength ).release() );
2040 wavelength, amplitude, strictWavelength ).release() );
2047std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2049 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2053 geom = segmentizedCopy.get();
2064 auto result = std::make_unique< QgsPolygon >();
2067 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2071 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2096 int numGeom = gc->numGeometries();
2097 QVector< QgsAbstractGeometry * > geometryList;
2098 geometryList.reserve( numGeom );
2099 for (
int i = 0; i < numGeom; ++i )
2101 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2119 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2128 std::random_device rd;
2129 std::mt19937 mt( seed == 0 ? rd() : seed );
2130 std::uniform_real_distribution<> uniformDist( 0, 1 );
2139 int numGeom = gc->numGeometries();
2140 QVector< QgsAbstractGeometry * > geometryList;
2141 geometryList.reserve( numGeom );
2142 for (
int i = 0; i < numGeom; ++i )
2144 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2162 const int totalPoints = line->
numPoints();
2163 if ( totalPoints < 2 )
2166 const double *x = line->
xData();
2167 const double *y = line->
yData();
2169 double prevX = *x++;
2170 double prevY = *y++;
2172 QVector< double > outX;
2173 QVector< double > outY;
2174 const double totalLength = line->
length();
2176 const int maxRepetitions = std::ceil( totalLength / wavelength );
2177 if ( !strictWavelength )
2178 wavelength = totalLength / maxRepetitions;
2180 const int estimatedPoints = maxRepetitions * 4 + 2;
2181 outX.reserve( estimatedPoints );
2182 outY.reserve( estimatedPoints );
2183 outX.append( prevX );
2184 outY.append( prevY );
2187 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2188 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2190 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2193 for (
int i = 1; i < totalPoints; ++i )
2195 double thisX = *x++;
2196 double thisY = *y++;
2200 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2203 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2208 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2209 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2210 outX.append( pX + side * amplitude * sinAngle );
2211 outY.append( pY + side * amplitude * cosAngle );
2212 outX.append( pX - side * amplitude * sinAngle );
2213 outY.append( pY - side * amplitude * cosAngle );
2215 distanceToNextPointFromStartOfSegment += wavelength / 2;
2221 distanceToNextPointFromStartOfSegment -= segmentLength;
2227 outX.append( prevX );
2228 outY.append( prevY );
2230 return std::make_unique< QgsLineString >( outX, outY );
2234 const double minimumWavelength,
const double maximumWavelength,
2235 const double minimumAmplitude,
const double maximumAmplitude,
2236 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2238 const int totalPoints = line->
numPoints();
2239 if ( totalPoints < 2 )
2242 const double *x = line->
xData();
2243 const double *y = line->
yData();
2245 double prevX = *x++;
2246 double prevY = *y++;
2248 QVector< double > outX;
2249 QVector< double > outY;
2250 const double totalLength = line->
length();
2252 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2254 const int estimatedPoints = maxRepetitions * 4 + 2;
2255 outX.reserve( estimatedPoints );
2256 outY.reserve( estimatedPoints );
2257 outX.append( prevX );
2258 outY.append( prevY );
2260 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2263 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2264 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2266 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2267 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2270 for (
int i = 1; i < totalPoints; ++i )
2272 double thisX = *x++;
2273 double thisY = *y++;
2277 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2280 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2285 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2286 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2287 outX.append( pX + side * amplitude * sinAngle );
2288 outY.append( pY + side * amplitude * cosAngle );
2290 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2291 outX.append( pX - side * amplitude * sinAngle );
2292 outY.append( pY - side * amplitude * cosAngle );
2294 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2295 distanceToNextPointFromStartOfSegment += wavelength / 2;
2301 distanceToNextPointFromStartOfSegment -= segmentLength;
2304 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2305 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2306 outX.append( prevX );
2307 outY.append( prevY );
2309 return std::make_unique< QgsLineString >( outX, outY );
2314 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2318 geom = segmentizedCopy.get();
2329 auto result = std::make_unique< QgsPolygon >();
2332 wavelength, amplitude, strictWavelength ).release() );
2336 wavelength, amplitude, strictWavelength ).release() );
2343std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2345 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2349 geom = segmentizedCopy.get();
2360 auto result = std::make_unique< QgsPolygon >();
2363 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2367 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2392 int numGeom = gc->numGeometries();
2393 QVector< QgsAbstractGeometry * > geometryList;
2394 geometryList.reserve( numGeom );
2395 for (
int i = 0; i < numGeom; ++i )
2397 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2415 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2424 std::random_device rd;
2425 std::mt19937 mt( seed == 0 ? rd() : seed );
2426 std::uniform_real_distribution<> uniformDist( 0, 1 );
2435 int numGeom = gc->numGeometries();
2436 QVector< QgsAbstractGeometry * > geometryList;
2437 geometryList.reserve( numGeom );
2438 for (
int i = 0; i < numGeom; ++i )
2440 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2458 const int totalPoints = line->
numPoints();
2459 if ( totalPoints < 2 )
2462 const double *x = line->
xData();
2463 const double *y = line->
yData();
2465 double prevX = *x++;
2466 double prevY = *y++;
2468 const double totalLength = line->
length();
2470 const int maxRepetitions = std::ceil( totalLength / wavelength );
2471 if ( !strictWavelength )
2472 wavelength = totalLength / maxRepetitions;
2474 const int segments = 10;
2478 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2479 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2480 bool isFirstPart =
true;
2482 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2483 int bufferIndex = 1;
2484 auto out = std::make_unique< QgsLineString >();
2486 double segmentAngleRadians = 0;
2487 double remainingDistance = totalLength;
2488 double totalCoveredDistance = 0;
2490 for (
int i = 1; i < totalPoints; ++i )
2492 double thisX = *x++;
2493 double thisY = *y++;
2497 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2500 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2503 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2505 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2506 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2508 if ( bufferIndex == 1 && isFirstPart )
2510 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2511 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2512 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2513 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2515 distanceToNextPointFromStartOfSegment += wavelength / 8;
2517 else if ( bufferIndex == 1 )
2519 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2520 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2521 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2522 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2524 distanceToNextPointFromStartOfSegment += wavelength / 4;
2526 else if ( bufferIndex == 2 )
2528 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2529 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2533 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2534 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2535 isFirstPart =
false;
2540 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2541 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2542 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2544 out->append( bezier.get() );
2547 xOutBuffer[0] = xOutBuffer[3];
2548 yOutBuffer[0] = yOutBuffer[3];
2551 distanceToNextPointFromStartOfSegment += wavelength / 4;
2554 totalCoveredDistance += segmentLength;
2557 distanceToNextPointFromStartOfSegment -= segmentLength;
2560 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2561 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2562 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2563 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2566 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2567 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2570 out->append( bezier.get() );
2576 const double minimumWavelength,
const double maximumWavelength,
2577 const double minimumAmplitude,
const double maximumAmplitude,
2578 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2580 const int totalPoints = line->
numPoints();
2581 if ( totalPoints < 2 )
2584 const double *x = line->
xData();
2585 const double *y = line->
yData();
2587 double prevX = *x++;
2588 double prevY = *y++;
2590 const double totalLength = line->
length();
2592 const int segments = 10;
2596 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2597 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2598 bool isFirstPart =
true;
2600 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2601 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2603 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2604 int bufferIndex = 1;
2605 auto out = std::make_unique< QgsLineString >();
2607 double segmentAngleRadians = 0;
2609 double remainingDistance = totalLength;
2610 double totalCoveredDistance = 0;
2612 for (
int i = 1; i < totalPoints; ++i )
2614 double thisX = *x++;
2615 double thisY = *y++;
2619 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2622 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2625 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2627 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2628 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2630 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 auto 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 auto result = std::make_unique< QgsPolygon >();
2765 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2769 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
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 );
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 auto 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 auto 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() )
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 an 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.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
Compound curve geometry type.
int nCurves() const
Returns the number of curves in the geometry.
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
virtual int numPoints() const =0
Returns the number of points in the curve.
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual bool isClosed() const
Returns true if the curve is closed.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
virtual QgsPolygon * toPolygon(unsigned int segments=36) const
Returns a segmented polygon.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
int partCount() const override
Returns count of parts contained in the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...
static double distance2D(double x1, double y1, double x2, double y2)
Returns the 2D distance between (x1, y1) and (x2, y2).
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
static void weightedPointInTriangle(double aX, double aY, double bX, double bY, double cX, double cY, double weightB, double weightC, double &pointX, double &pointY)
Returns a weighted point inside the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
static double triangleArea(double aX, double aY, double bX, double bY, double cX, double cY)
Returns the area of the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
static int leftOfLine(const double x, const double y, const double x1, const double y1, const double x2, const double y2)
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> (x2, y2).
static void circleCenterRadius(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double &radius, double ¢erX, double ¢erY)
Returns radius and center of the circle through pt1, pt2, pt3.
static bool pointContinuesArc(const QgsPoint &a1, const QgsPoint &a2, const QgsPoint &a3, const QgsPoint &b, double distanceTolerance, double pointSpacingAngleTolerance)
Returns true if point b is on the arc formed by points a1, a2, and a3, but not within that arc portio...
static int circleCircleOuterTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2)
Calculates the outer tangent points for two circles, centered at center1 and center2 and with radii o...
A geometry is the spatial representation of a feature.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
QgsPointXY closestVertex(const QgsPointXY &point, int &closestVertexIndex, int &previousVertexIndex, int &nextVertexIndex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false)
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries, const QgsGeometryParameters ¶meters=QgsGeometryParameters())
Compute the unary union on a list of geometries.
Qgis::GeometryOperationResult addPartV2(const QVector< QgsPointXY > &points, Qgis::WkbType wkbType=Qgis::WkbType::Unknown)
Adds a new part to a the geometry.
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Does vector analysis using the GEOS library and handles import, export, and 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.
static std::unique_ptr< 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,...
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.
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.
Point geometry type, with support for z-dimension and m-values.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
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.
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.
Tessellates polygons into triangles.
QVector< float > data() const
Returns array of triangle vertex data.
void setBounds(const QgsRectangle &bounds)
Sets scaling and the bounds of the input geometry coordinates.
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.
void setInputZValueIgnored(bool ignore)
Sets whether Z values from the input geometries are ignored (true) or not (false).
Represent a 2-dimensional 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 Q_INVOKABLE 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).
T qgsgeometry_cast(QgsAbstractGeometry *geom)
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.