43using namespace Qt::StringLiterals;
46 : mGeometry( geometry.constGet() )
73 double dx = p2.
x() - p1.
x();
74 double dy = p2.
y() - p1.
y();
75 if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
77 if ( fabs( dx ) >= fabs( dy ) )
79 double dev = fabs( dy ) / fabs( dx );
86 double dev = fabs( dx ) / fabs( dy );
104 std::array<Direction, 5> dirs;
111 while ( current != end )
121 else if ( dir != dirs[idx - 1] )
131 ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
132 std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
138 int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
139 for (
int i = 1; i < 4; ++i )
141 if ( dirs[i] != oriented[( idx + i ) % 4] )
177 if ( vertexCount < 4 )
179 else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
183 std::array<Direction, 4> dirs;
184 std::tie( found4Dirs, dirs ) =
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
198 QVector<QgsLineString *> linesToProcess;
203 linesToProcess.reserve( multiCurve->
partCount() );
204 for (
int i = 0; i < multiCurve->
partCount(); ++i )
206 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
213 linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
216 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() :
nullptr );
219 if ( !linesToProcess.empty() )
221 std::unique_ptr< QgsLineString > secondline;
222 for (
QgsLineString *line : std::as_const( linesToProcess ) )
224 QTransform transform = QTransform::fromTranslate( x, y );
226 secondline.reset( line->reversed() );
227 secondline->transform( transform );
229 line->append( secondline.get() );
230 line->addVertex( line->pointN( 0 ) );
236 multipolygon->addGeometry( polygon );
258 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
262 , d( polygon->pointDistanceToBoundary( x, y ) )
263 , max( d + h * M_SQRT2 )
278struct GreaterThanByMax
280 bool operator()(
const Cell *lhs,
const Cell *rhs )
const
282 return rhs->max > lhs->max;
286Cell *getCentroidCell(
const QgsPolygon *polygon )
294 for (
int i = 0, j = len - 1; i < len; j = i++ )
296 double aX = exterior->
xAt( i );
297 double aY = exterior->
yAt( i );
298 double bX = exterior->
xAt( j );
299 double bY = exterior->
yAt( j );
300 double f = aX * bY - bX * aY;
301 x += ( aX + bX ) * f;
302 y += ( aY + bY ) * f;
306 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
308 return new Cell( x / area, y / area, 0.0, polygon );
311QgsPoint surfacePoleOfInaccessibility(
const QgsSurface *surface,
double precision,
double &distanceFromBoundary )
313 std::unique_ptr< QgsPolygon > segmentizedPoly;
318 polygon = segmentizedPoly.get();
325 double cellSize = std::min( bounds.
width(), bounds.
height() );
330 double h = cellSize / 2.0;
331 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
338 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
343 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
346 std::unique_ptr< Cell > bboxCell(
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
349 if ( bboxCell->d > bestCell->d )
351 bestCell = std::move( bboxCell );
354 while ( !cellQueue.empty() )
357 std::unique_ptr< Cell > cell( cellQueue.top() );
359 Cell *currentCell = cell.get();
362 if ( currentCell->d > bestCell->d )
364 bestCell = std::move( cell );
368 if ( currentCell->max - bestCell->d <= precision )
372 h = currentCell->h / 2.0;
373 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y - h, h, polygon ) );
374 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y - h, h, polygon ) );
375 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y + h, h, polygon ) );
376 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
379 distanceFromBoundary = bestCell->d;
381 return QgsPoint( bestCell->x, bestCell->y );
389 if ( distanceFromBoundary )
390 *distanceFromBoundary = std::numeric_limits<double>::max();
392 if ( !mGeometry || mGeometry->isEmpty() )
395 if ( precision <= 0 )
400 int numGeom = gc->numGeometries();
403 for (
int i = 0; i < numGeom; ++i )
409 double dist = std::numeric_limits<double>::max();
410 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
411 if ( dist > maxDist )
421 if ( distanceFromBoundary )
422 *distanceFromBoundary = maxDist;
431 double dist = std::numeric_limits<double>::max();
432 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
436 if ( distanceFromBoundary )
437 *distanceFromBoundary = dist;
448 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
474 for (
int i = 0; i < numPoints; ++i )
476 if ( !isClosed && i == numPoints - 1 )
478 else if ( !isClosed && i == 0 )
487 a = ring->
pointN( numPoints - 1 );
490 if ( i == numPoints - 1 )
499 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
509 double lowerThreshold,
double upperThreshold )
518 double scale = 2.0 * std::min( p.
length(), q.
length() );
522 double dotProduct = p * q;
531 if ( dotProduct < -M_SQRT1_2 )
540 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
545 double minScore = std::numeric_limits<double>::max();
550 std::unique_ptr< QgsLineString > best( ring->
clone() );
552 QVector< QgsVector > motions;
553 motions.reserve( numPoints );
555 for (
int it = 0; it < iterations; ++it )
563 for (
int i = 0; i < numPoints; ++i )
565 if ( isClosed && i == numPoints - 1 )
566 motions << motions.at( 0 );
567 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
577 a = ring->
pointN( numPoints - 1 );
580 if ( i == numPoints - 1 )
585 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
592 for (
int i = 0; i < numPoints; ++i )
594 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
595 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
598 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
599 if ( newScore < minScore )
601 best.reset( ring->
clone() );
605 if ( minScore < tolerance )
611 return best.release();
617 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
621 geom = segmentizedCopy.get();
627 maxIterations, tolerance, lowerThreshold, upperThreshold );
636 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
640 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
656 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
657 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
661 int numGeom = gc->numGeometries();
662 QVector< QgsAbstractGeometry * > geometryList;
663 geometryList.reserve( numGeom );
664 for (
int i = 0; i < numGeom; ++i )
666 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
685 QVector< double > outX;
686 QVector< double > outY;
687 QVector< double > outZ;
688 QVector< double > outM;
689 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
692 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
693 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
694 bool withZ = ring->
is3D();
696 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
699 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
712 int extraNodesThisSegment = extraNodesPerSegment;
713 for (
int i = 0; i < nPoints - 1; ++i )
716 x2 = ring->
xAt( i + 1 );
718 y2 = ring->
yAt( i + 1 );
722 z2 = ring->
zAt( i + 1 );
727 m2 = ring->
mAt( i + 1 );
737 if ( extraNodesPerSegment < 0 )
741 if ( extraNodesThisSegment >= 1 )
742 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
745 for (
int j = 0; j < extraNodesThisSegment; ++j )
747 double delta = multiplier * ( j + 1 );
748 xOut = x1 + delta * ( x2 - x1 );
749 yOut = y1 + delta * ( y2 - y1 );
751 zOut = z1 + delta * ( z2 - z1 );
753 mOut = m1 + delta * ( m2 - m1 );
763 outX << ring->
xAt( nPoints - 1 );
764 outY << ring->
yAt( nPoints - 1 );
766 outZ << ring->
zAt( nPoints - 1 );
768 outM << ring->
mAt( nPoints - 1 );
776 if ( extraNodesPerSegment < 0 &&
qgsDoubleNear( distance, 0 ) )
779 return geom->
clone();
782 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
786 geom = segmentizedCopy.get();
800 extraNodesPerSegment, distance ) );
804 extraNodesPerSegment, distance ) );
826 int numGeom = gc->numGeometries();
827 QVector< QgsAbstractGeometry * > geometryList;
828 geometryList.reserve( numGeom );
829 for (
int i = 0; i < numGeom; ++i )
831 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
862 int numGeom = gc->numGeometries();
863 QVector< QgsAbstractGeometry * > geometryList;
864 geometryList.reserve( numGeom );
865 for (
int i = 0; i < numGeom; ++i )
892 "line_segment_dist_comparer",
893 "AB must not be collinear with the origin." );
895 "line_segment_dist_comparer",
896 "CD must not be collinear with the origin." );
913 if ( ab.
end() == cd.
end() || oad != oab )
923 if ( cdb == 0 && cda == 0 )
925 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
927 else if ( cda == cdb || cda == 0 || cdb == 0 )
930 return cdo == cda || cdo == cdb;
946 const bool aIsLeft = a.
x() < mVertex.x();
947 const bool bIsLeft = b.
x() < mVertex.x();
948 if ( aIsLeft != bIsLeft )
953 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
955 return b.
y() < a.
y();
959 return a.
y() < b.
y();
991 const int abo =
segment.pointLeftOfLine( origin );
998 const double distA = ao * direction;
999 const double distB = ( origin -
segment.end() ) * direction;
1001 if ( distA > 0 && distB > 0 )
1007 if ( ( distA > 0 ) != ( distB > 0 ) )
1008 intersectPoint = origin;
1009 else if ( distA > distB )
1010 intersectPoint =
segment.start();
1012 intersectPoint =
segment.end();
1020 if ( u < 0.0 || 1.0 < u )
1027 intersectPoint = origin + direction * t;
1036 if ( radius1 > radius2 )
1043 QVector<QgsPointXY> points;
1065 std::vector< std::unique_ptr<QgsLineString > > temporarySegmentizedLines;
1066 std::vector< const QgsLineString * > linesToProcess;
1071 for (
int i = 0; i < multiCurve->partCount(); ++i )
1081 linesToProcess.emplace_back( lineString );
1085 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( part->
segmentize() ) );
1086 linesToProcess.emplace_back( segmentizedCurve.get() );
1087 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1094 if ( curve->nCoordinates() > 0 )
1098 linesToProcess.emplace_back( lineString );
1102 std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( curve->segmentize() ) );
1103 linesToProcess.emplace_back( segmentizedCurve.get() );
1104 temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
1109 if ( linesToProcess.empty() )
1112 g.mLastError = u
"Input geometry was not a curve type geometry"_s;
1116 QVector<QgsGeometry> bufferedLines;
1117 bufferedLines.reserve( linesToProcess.size() );
1121 QVector<QgsGeometry> parts;
1123 double prevRadius = 0;
1126 std::unique_ptr< double[] > widths = widthFunction( line ) ;
1131 double thisRadius = widths[ i ] / 2.0;
1132 if ( thisRadius > 0 )
1136 QgsCircle circ( thisPoint, thisRadius );
1138 parts << thisCircle;
1147 if ( prevRadius > 0 || thisRadius > 0 )
1149 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1150 if ( !points.empty() )
1155 int beforeVertex = 0;
1156 int afterVertex = 0;
1158 double sqrDistPrev = 0;
1159 for (
int j = 0; j < points.count(); ++j )
1163 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1166 points.append( points.at( 0 ) );
1168 auto poly = std::make_unique< QgsPolygon >();
1170 if ( poly->area() > 0 )
1175 prevPoint = thisPoint;
1176 prevRadius = thisRadius;
1177 prevCircle = thisCircle;
1192 start = std::fabs( start );
1193 end = std::fabs( end );
1195 auto interpolateWidths = [ start, end ](
const QgsLineString * line )->std::unique_ptr<
double [] >
1199 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1201 widths[line->nCoordinates() - 1] = end;
1203 double lineLength = line->length();
1204 double currentLength = 0;
1205 QgsPoint prevPoint = line->pointN( 0 );
1206 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1208 QgsPoint point = line->pointN( i );
1209 double segmentLength = point.
distance( prevPoint );
1210 currentLength += segmentLength;
1211 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1212 double delta = lengthFraction * ( end - start );
1213 widths[i] = start + delta;
1225 auto widthByM = [](
const QgsLineString * line )->std::unique_ptr<
double [] >
1227 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1228 for (
int i = 0; i < line->nCoordinates(); ++i )
1230 widths[ i ] = line->mAt( i );
1239 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1249 for (
int i = 0; i < ms->numGeometries(); ++i )
1252 return QVector< QgsPointXY >();
1279 return QVector< QgsPointXY >();
1281 if ( !t.
error().isEmpty() )
1284 return QVector< QgsPointXY >();
1288 QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
1289 const QVector<float> triangleData = t.
data();
1291 if ( triangleData.empty() )
1292 return QVector< QgsPointXY >();
1295 std::vector< double > cumulativeAreas;
1297 double totalArea = 0;
1298 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1301 return QVector< QgsPointXY >();
1303 const float aX = *it++;
1304 const float aY = *it++;
1306 const float bX = *it++;
1307 const float bY = *it++;
1309 const float cX = *it++;
1310 const float cY = *it++;
1315 cumulativeAreas.emplace_back( totalArea );
1318 std::random_device rd;
1319 std::mt19937 mt( seed == 0 ? rd() : seed );
1320 std::uniform_real_distribution<> uniformDist( 0, 1 );
1323 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1326 const double target = random * totalArea;
1327 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1332 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1337 QVector<QgsPointXY> result;
1338 result.reserve( count );
1340 for (
int i = 0; i < count; )
1343 return QVector< QgsPointXY >();
1345 const double triangleIndexRnd = uniformDist( mt );
1347 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1350 const double weightB = uniformDist( mt );
1351 const double weightC = uniformDist( mt );
1356 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1357 const double aY = triangleData.at( triangleIndex * 9 + 1 ) + bounds.
yMinimum();
1358 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1359 const double bY = triangleData.at( triangleIndex * 9 + 4 ) + bounds.
yMinimum();
1360 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1361 const double cY = triangleData.at( triangleIndex * 9 + 7 ) + bounds.
yMinimum();
1365 if ( acceptPoint( candidate ) )
1371 else if ( maxTriesPerPoint != 0 )
1375 if ( tries == maxTriesPerPoint )
1386 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint, QString &error )
1390 std::unique_ptr<QgsAbstractGeometry> triangulation =
geos.constrainedDelaunayTriangulation( &error );
1391 if ( !triangulation || triangulation->isEmpty( ) )
1402 std::vector< double > cumulativeAreas;
1404 double totalArea = 0;
1405 std::vector< double > vertices(
static_cast< std::size_t
>( mp->
numGeometries() ) * 6 );
1406 double *vertexData = vertices.data();
1420 const double aX = exterior->
xAt( 0 );
1421 const double aY = exterior->
yAt( 0 );
1422 const double bX = exterior->
xAt( 1 );
1423 const double bY = exterior->
yAt( 1 );
1424 const double cX = exterior->
xAt( 2 );
1425 const double cY = exterior->
yAt( 2 );
1435 cumulativeAreas.emplace_back( totalArea );
1438 std::random_device rd;
1439 std::mt19937 mt( seed == 0 ? rd() : seed );
1440 std::uniform_real_distribution<> uniformDist( 0, 1 );
1443 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1446 const double target = random * totalArea;
1447 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1452 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1457 QVector<QgsPointXY> result;
1458 result.reserve( count );
1460 vertexData = vertices.data();
1461 for (
int i = 0; i < count; )
1464 return QVector< QgsPointXY >();
1466 const double triangleIndexRnd = uniformDist( mt );
1468 const std::size_t triangleIndex = selectRandomTriangle( triangleIndexRnd );
1471 const double weightB = uniformDist( mt );
1472 const double weightC = uniformDist( mt );
1477 const double aX = vertexData[ triangleIndex * 6 ];
1478 const double aY = vertexData[ triangleIndex * 6 + 1 ];
1479 const double bX = vertexData[ triangleIndex * 6 + 2 ];
1480 const double bY = vertexData[ triangleIndex * 6 + 3 ];
1481 const double cX = vertexData[ triangleIndex * 6 + 4 ];
1482 const double cY = vertexData[ triangleIndex * 6 + 5 ];
1487 if ( acceptPoint( candidate ) )
1493 else if ( maxTriesPerPoint != 0 )
1497 if ( tries == maxTriesPerPoint )
1508 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1511 return QVector< QgsPointXY >();
1514#if (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=11) || GEOS_VERSION_MAJOR>3
1524 double pointSpacingAngleTolerance )
1530 std::unique_ptr< QgsCircularString > out;
1536 auto out = std::make_unique< QgsCompoundCurve >();
1538 for (
int i = 0; i < in->
nCurves(); i ++ )
1540 std::unique_ptr< QgsCurve > processed =
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
1545 for (
int i = 0; i < processedCompoundCurve->nCurves(); ++i )
1547 out->addCurve( processedCompoundCurve->curveAt( i )->clone() );
1552 out->addCurve( processed.release() );
1562 auto out = std::make_unique< QgsCompoundCurve >();
1565 const unsigned int minQuadEdges = 2;
1578 out->addCurve( lineString->
clone() );
1584 QVector< int > edgesInArcs( numEdges + 1, 0 );
1588 double abX = b.x() - a.
x();
1589 double abY = b.y() - a.
y();
1591 double cbX = b.x() -
c.x();
1592 double cbY = b.y() -
c.y();
1594 double dot = ( abX * cbX + abY * cbY );
1595 double cross = ( abX * cbY - abY * cbX );
1597 double alpha = std::atan2( cross, dot );
1612 double centerX = 0.0;
1613 double centerY = 0.0;
1616 while ( i < numEdges - 2 )
1618 unsigned int arcEdges = 0;
1619 double numQuadrants = 0;
1622 bool foundArc =
false;
1624 a1 = lineString->
pointN( i );
1625 a2 = lineString->
pointN( i + 1 );
1626 a3 = lineString->
pointN( i + 2 );
1629 for ( j = i + 3; j < numEdges + 1; j++ )
1631 b = lineString->
pointN( j );
1638 for ( k = j - 1; k > j - 4; k-- )
1639 edgesInArcs[k] = currentArc;
1659 arcEdges = j - 1 - i;
1660 if ( first.
x() == b.x() && first.
y() == b.y() )
1668 angle = arcAngle( first,
QgsPoint( centerX, centerY ), b );
1674 angle = 2 * M_PI + angle;
1675 numQuadrants = ( 4 * angle ) / ( 2 * M_PI );
1678 if ( arcEdges < minQuadEdges * numQuadrants )
1681 for ( k = j - 1; k >= i; k-- )
1698 int edgeType = edgesInArcs[0];
1700 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1705 QVector< QgsPoint > points;
1706 for (
int j = start; j < end + 2; ++ j )
1708 points.append( lineString->
pointN( j ) );
1710 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1711 out->addCurve( straightSegment.release() );
1716 QVector< QgsPoint > points;
1717 points.append( lineString->
pointN( start ) );
1718 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1719 points.append( lineString->
pointN( end + 1 ) );
1720 auto curvedSegment = std::make_unique< QgsCircularString >();
1721 curvedSegment->setPoints( points );
1722 out->addCurve( curvedSegment.release() );
1726 for (
int i = 1; i < numEdges; i++ )
1728 if ( edgeType != edgesInArcs[i] )
1731 addPointsToCurve( start, end, edgeType );
1733 edgeType = edgesInArcs[i];
1739 addPointsToCurve( start, end, edgeType );
1744 std::unique_ptr< QgsCircularString > res;
1765 auto result = std::make_unique< QgsCurvePolygon>();
1768 distanceTolerance, angleTolerance ).release() );
1772 distanceTolerance, angleTolerance ).release() );
1794 int numGeom = gc->numGeometries();
1795 QVector< QgsAbstractGeometry * > geometryList;
1796 geometryList.reserve( numGeom );
1797 for (
int i = 0; i < numGeom; ++i )
1820 area = std::numeric_limits<double>::max();
1822 width = std::numeric_limits<double>::max();
1823 height = std::numeric_limits<double>::max();
1825 if ( !mGeometry || mGeometry->nCoordinates() < 2 )
1829 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1838 if ( !hull->nextVertex( vertexId, pt0 ) )
1844 double totalRotation = 0;
1845 while ( hull->nextVertex( vertexId, pt2 ) )
1848 double rotateAngle = 180.0 / M_PI * currentAngle;
1849 totalRotation += rotateAngle;
1851 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1852 t.rotate( rotateAngle );
1853 t.translate( -pt0.
x(), -pt0.
y() );
1855 hull->transform( t );
1858 double currentArea = bounds.
width() * bounds.
height();
1859 if ( currentArea < area )
1863 angle = totalRotation;
1864 width = bounds.
width();
1865 height = bounds.
height();
1868 pt1 = hull->vertexAt( vertexId );
1874 if ( width > height )
1876 width = minRect.
height();
1877 height = minRect.
width();
1878 angle = angle + 90.0;
1882 if ( angle > 180.0 )
1883 angle = std::fmod( angle, 180.0 );
1890 const int totalPoints = line->
numPoints();
1891 if ( totalPoints < 2 )
1894 const double *x = line->
xData();
1895 const double *y = line->
yData();
1897 double prevX = *x++;
1898 double prevY = *y++;
1900 QVector< double > outX;
1901 QVector< double > outY;
1902 const double totalLength = line->
length();
1904 const int maxRepetitions = std::ceil( totalLength / wavelength );
1905 if ( !strictWavelength )
1906 wavelength = totalLength / maxRepetitions;
1908 const int estimatedPoints = maxRepetitions * 2 + 2;
1909 outX.reserve( estimatedPoints );
1910 outY.reserve( estimatedPoints );
1911 outX.append( prevX );
1912 outY.append( prevY );
1914 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1916 for (
int i = 1; i < totalPoints; ++i )
1918 double thisX = *x++;
1919 double thisY = *y++;
1923 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1926 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1931 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1932 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1934 outX.append( outPointX );
1935 outY.append( outPointY );
1937 distanceToNextPointFromStartOfSegment += wavelength / 2;
1943 distanceToNextPointFromStartOfSegment -= segmentLength;
1946 outX.append( prevX );
1947 outY.append( prevY );
1949 return std::make_unique< QgsLineString >( outX, outY );
1953 const double minimumWavelength,
const double maximumWavelength,
1954 const double minimumAmplitude,
const double maximumAmplitude,
1955 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1957 const int totalPoints = line->
numPoints();
1958 if ( totalPoints < 2 )
1961 const double *x = line->
xData();
1962 const double *y = line->
yData();
1964 double prevX = *x++;
1965 double prevY = *y++;
1967 QVector< double > outX;
1968 QVector< double > outY;
1969 const double totalLength = line->
length();
1971 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1973 const int estimatedPoints = maxRepetitions * 2 + 2;
1974 outX.reserve( estimatedPoints );
1975 outY.reserve( estimatedPoints );
1976 outX.append( prevX );
1977 outY.append( prevY );
1979 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1980 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1981 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1984 for (
int i = 1; i < totalPoints; ++i )
1986 double thisX = *x++;
1987 double thisY = *y++;
1991 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1994 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1999 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2000 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2001 outX.append( outPointX );
2002 outY.append( outPointY );
2004 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2005 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2007 distanceToNextPointFromStartOfSegment += wavelength / 2;
2013 distanceToNextPointFromStartOfSegment -= segmentLength;
2016 outX.append( prevX );
2017 outY.append( prevY );
2019 return std::make_unique< QgsLineString >( outX, outY );
2024 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2028 geom = segmentizedCopy.get();
2039 auto result = std::make_unique< QgsPolygon >();
2042 wavelength, amplitude, strictWavelength ).release() );
2046 wavelength, amplitude, strictWavelength ).release() );
2053std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2055 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2059 geom = segmentizedCopy.get();
2070 auto result = std::make_unique< QgsPolygon >();
2073 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2077 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2102 int numGeom = gc->numGeometries();
2103 QVector< QgsAbstractGeometry * > geometryList;
2104 geometryList.reserve( numGeom );
2105 for (
int i = 0; i < numGeom; ++i )
2107 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2125 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2134 std::random_device rd;
2135 std::mt19937 mt( seed == 0 ? rd() : seed );
2136 std::uniform_real_distribution<> uniformDist( 0, 1 );
2145 int numGeom = gc->numGeometries();
2146 QVector< QgsAbstractGeometry * > geometryList;
2147 geometryList.reserve( numGeom );
2148 for (
int i = 0; i < numGeom; ++i )
2150 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2168 const int totalPoints = line->
numPoints();
2169 if ( totalPoints < 2 )
2172 const double *x = line->
xData();
2173 const double *y = line->
yData();
2175 double prevX = *x++;
2176 double prevY = *y++;
2178 QVector< double > outX;
2179 QVector< double > outY;
2180 const double totalLength = line->
length();
2182 const int maxRepetitions = std::ceil( totalLength / wavelength );
2183 if ( !strictWavelength )
2184 wavelength = totalLength / maxRepetitions;
2186 const int estimatedPoints = maxRepetitions * 4 + 2;
2187 outX.reserve( estimatedPoints );
2188 outY.reserve( estimatedPoints );
2189 outX.append( prevX );
2190 outY.append( prevY );
2193 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
2194 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
2196 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2199 for (
int i = 1; i < totalPoints; ++i )
2201 double thisX = *x++;
2202 double thisY = *y++;
2206 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2209 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2214 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2215 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2216 outX.append( pX + side * amplitude * sinAngle );
2217 outY.append( pY + side * amplitude * cosAngle );
2218 outX.append( pX - side * amplitude * sinAngle );
2219 outY.append( pY - side * amplitude * cosAngle );
2221 distanceToNextPointFromStartOfSegment += wavelength / 2;
2227 distanceToNextPointFromStartOfSegment -= segmentLength;
2233 outX.append( prevX );
2234 outY.append( prevY );
2236 return std::make_unique< QgsLineString >( outX, outY );
2240 const double minimumWavelength,
const double maximumWavelength,
2241 const double minimumAmplitude,
const double maximumAmplitude,
2242 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2244 const int totalPoints = line->
numPoints();
2245 if ( totalPoints < 2 )
2248 const double *x = line->
xData();
2249 const double *y = line->
yData();
2251 double prevX = *x++;
2252 double prevY = *y++;
2254 QVector< double > outX;
2255 QVector< double > outY;
2256 const double totalLength = line->
length();
2258 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2260 const int estimatedPoints = maxRepetitions * 4 + 2;
2261 outX.reserve( estimatedPoints );
2262 outY.reserve( estimatedPoints );
2263 outX.append( prevX );
2264 outY.append( prevY );
2266 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2269 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2270 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2272 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2273 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2276 for (
int i = 1; i < totalPoints; ++i )
2278 double thisX = *x++;
2279 double thisY = *y++;
2283 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2286 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2291 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2292 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2293 outX.append( pX + side * amplitude * sinAngle );
2294 outY.append( pY + side * amplitude * cosAngle );
2296 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2297 outX.append( pX - side * amplitude * sinAngle );
2298 outY.append( pY - side * amplitude * cosAngle );
2300 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2301 distanceToNextPointFromStartOfSegment += wavelength / 2;
2307 distanceToNextPointFromStartOfSegment -= segmentLength;
2310 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2311 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2312 outX.append( prevX );
2313 outY.append( prevY );
2315 return std::make_unique< QgsLineString >( outX, outY );
2320 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2324 geom = segmentizedCopy.get();
2335 auto result = std::make_unique< QgsPolygon >();
2338 wavelength, amplitude, strictWavelength ).release() );
2342 wavelength, amplitude, strictWavelength ).release() );
2349std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2351 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2355 geom = segmentizedCopy.get();
2366 auto result = std::make_unique< QgsPolygon >();
2369 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2373 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2398 int numGeom = gc->numGeometries();
2399 QVector< QgsAbstractGeometry * > geometryList;
2400 geometryList.reserve( numGeom );
2401 for (
int i = 0; i < numGeom; ++i )
2403 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2421 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2430 std::random_device rd;
2431 std::mt19937 mt( seed == 0 ? rd() : seed );
2432 std::uniform_real_distribution<> uniformDist( 0, 1 );
2441 int numGeom = gc->numGeometries();
2442 QVector< QgsAbstractGeometry * > geometryList;
2443 geometryList.reserve( numGeom );
2444 for (
int i = 0; i < numGeom; ++i )
2446 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2464 const int totalPoints = line->
numPoints();
2465 if ( totalPoints < 2 )
2468 const double *x = line->
xData();
2469 const double *y = line->
yData();
2471 double prevX = *x++;
2472 double prevY = *y++;
2474 const double totalLength = line->
length();
2476 const int maxRepetitions = std::ceil( totalLength / wavelength );
2477 if ( !strictWavelength )
2478 wavelength = totalLength / maxRepetitions;
2480 const int segments = 10;
2484 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2485 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2486 bool isFirstPart =
true;
2488 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2489 int bufferIndex = 1;
2490 auto out = std::make_unique< QgsLineString >();
2492 double segmentAngleRadians = 0;
2493 double remainingDistance = totalLength;
2494 double totalCoveredDistance = 0;
2496 for (
int i = 1; i < totalPoints; ++i )
2498 double thisX = *x++;
2499 double thisY = *y++;
2503 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2506 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2509 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2511 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2512 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2514 if ( bufferIndex == 1 && isFirstPart )
2516 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2517 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2518 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2519 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2521 distanceToNextPointFromStartOfSegment += wavelength / 8;
2523 else if ( bufferIndex == 1 )
2525 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2526 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2527 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2528 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2530 distanceToNextPointFromStartOfSegment += wavelength / 4;
2532 else if ( bufferIndex == 2 )
2534 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2535 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2539 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2540 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2541 isFirstPart =
false;
2546 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2547 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2548 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2550 out->append( bezier.get() );
2553 xOutBuffer[0] = xOutBuffer[3];
2554 yOutBuffer[0] = yOutBuffer[3];
2557 distanceToNextPointFromStartOfSegment += wavelength / 4;
2560 totalCoveredDistance += segmentLength;
2563 distanceToNextPointFromStartOfSegment -= segmentLength;
2566 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2567 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2568 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2569 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2572 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2573 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2576 out->append( bezier.get() );
2582 const double minimumWavelength,
const double maximumWavelength,
2583 const double minimumAmplitude,
const double maximumAmplitude,
2584 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2586 const int totalPoints = line->
numPoints();
2587 if ( totalPoints < 2 )
2590 const double *x = line->
xData();
2591 const double *y = line->
yData();
2593 double prevX = *x++;
2594 double prevY = *y++;
2596 const double totalLength = line->
length();
2598 const int segments = 10;
2602 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2603 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2604 bool isFirstPart =
true;
2606 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2607 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2609 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2610 int bufferIndex = 1;
2611 auto out = std::make_unique< QgsLineString >();
2613 double segmentAngleRadians = 0;
2615 double remainingDistance = totalLength;
2616 double totalCoveredDistance = 0;
2618 for (
int i = 1; i < totalPoints; ++i )
2620 double thisX = *x++;
2621 double thisY = *y++;
2625 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2628 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2631 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2633 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2634 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2636 if ( bufferIndex == 1 && isFirstPart )
2638 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2639 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2640 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2641 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2643 distanceToNextPointFromStartOfSegment += wavelength / 8;
2645 else if ( bufferIndex == 1 )
2647 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2648 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2649 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2650 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2652 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2653 distanceToNextPointFromStartOfSegment += wavelength / 4;
2655 else if ( bufferIndex == 2 )
2657 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2658 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2662 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2663 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2664 isFirstPart =
false;
2669 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2670 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2671 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2673 out->append( bezier.get() );
2676 xOutBuffer[0] = xOutBuffer[3];
2677 yOutBuffer[0] = yOutBuffer[3];
2681 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2683 distanceToNextPointFromStartOfSegment += wavelength / 4;
2686 totalCoveredDistance += segmentLength;
2690 distanceToNextPointFromStartOfSegment -= segmentLength;
2693 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2694 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2695 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2696 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2698 if ( out->isEmpty() )
2702 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2705 out->append( bezier.get() );
2710 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2711 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2714 out->append( bezier.get() );
2722 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2726 geom = segmentizedCopy.get();
2737 auto result = std::make_unique< QgsPolygon >();
2740 wavelength, amplitude, strictWavelength ).release() );
2744 wavelength, amplitude, strictWavelength ).release() );
2751std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2753 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2757 geom = segmentizedCopy.get();
2768 auto result = std::make_unique< QgsPolygon >();
2771 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2775 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2800 int numGeom = gc->numGeometries();
2801 QVector< QgsAbstractGeometry * > geometryList;
2802 geometryList.reserve( numGeom );
2803 for (
int i = 0; i < numGeom; ++i )
2805 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2823 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2832 std::random_device rd;
2833 std::mt19937 mt( seed == 0 ? rd() : seed );
2834 std::uniform_real_distribution<> uniformDist( 0, 1 );
2843 int numGeom = gc->numGeometries();
2844 QVector< QgsAbstractGeometry * > geometryList;
2845 geometryList.reserve( numGeom );
2846 for (
int i = 0; i < numGeom; ++i )
2848 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2865 const QVector< double> &pattern,
2869 double patternOffset )
2871 const int totalPoints = line->
numPoints();
2872 if ( totalPoints < 2 )
2875 const int patternSize = pattern.size();
2877 const double *x = line->
xData();
2878 const double *y = line->
yData();
2880 double prevX = *x++;
2881 double prevY = *y++;
2883 auto result = std::make_unique< QgsMultiLineString >();
2885 QVector< double > outX;
2886 QVector< double > outY;
2887 const double totalLength = line->
length();
2889 double patternLength = 0;
2890 double patternDashLength = 0;
2891 double patternGapLength = 0;
2892 for (
int i = 0; i < pattern.size(); ++i )
2894 patternLength += pattern.at( i );
2896 patternDashLength += pattern.at( i );
2898 patternGapLength += pattern.at( i );
2901 double firstPatternLength = 0;
2902 double firstPatternDashLength = 0;
2903 double firstPatternGapLength = 0;
2904 switch ( startRule )
2908 firstPatternLength = patternLength;
2909 firstPatternDashLength = patternDashLength;
2910 firstPatternGapLength = patternGapLength;
2913 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2914 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2915 firstPatternGapLength = patternGapLength;
2918 firstPatternLength = pattern.at( patternSize - 1 );
2919 firstPatternDashLength = 0;
2920 firstPatternGapLength = pattern.at( patternSize - 1 );
2923 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2924 firstPatternDashLength = 0;
2925 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2929 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2931 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2932 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2933 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2937 lastPatternLength = 0;
2938 lastPatternDashLength = 0;
2939 lastPatternGapLength = 0;
2942 lastPatternLength -= pattern.at( patternSize - 1 );
2943 lastPatternGapLength -= pattern.at( patternSize - 1 );
2946 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2947 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2948 lastPatternGapLength -= pattern.at( patternSize - 1 );
2951 lastPatternGapLength = patternGapLength;
2954 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2955 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2959 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2960 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2962 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2963 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2964 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2966 double dashLengthScalingFactor = 1;
2967 double gapLengthScalingFactor = 1;
2971 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2973 switch ( adjustment )
2976 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2977 gapLengthScalingFactor = dashLengthScalingFactor;
2980 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2983 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2988 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2989 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2991 const int maxPatterns = middlePatternRepetitions + 2;
2992 result->reserve( maxPatterns );
2994 int patternIndex = 0;
2995 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2997 switch ( startRule )
3003 distanceToNextPointFromStartOfSegment *= 0.5;
3006 patternIndex = patternSize - 1;
3008 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
3011 patternIndex = patternSize - 1;
3013 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
3017 const double adjustedOffset = fmod( patternOffset, patternLength );
3018 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
3022 double remainingOffset = scaledOffset;
3023 while ( remainingOffset > 0 )
3025 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
3027 distanceToNextPointFromStartOfSegment -= remainingOffset;
3031 remainingOffset -= distanceToNextPointFromStartOfSegment;
3034 if ( patternIndex == patternSize )
3037 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3043 outX.append( prevX );
3044 outY.append( prevY );
3047 for (
int i = 1; i < totalPoints; ++i )
3049 double thisX = *x++;
3050 double thisY = *y++;
3053 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
3056 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
3071 if ( patternIndex >= patternSize )
3074 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
3079 outX.append( thisX );
3080 outY.append( thisY );
3085 distanceToNextPointFromStartOfSegment -= segmentLength;
3090 outX.append( prevX );
3091 outY.append( prevY );
3099 const QVector<double> &pattern,
3103 double patternOffset )
3105 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
3109 geom = segmentizedCopy.get();
3120 auto result = std::make_unique< QgsMultiLineString >();
3123 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
3124 result->addGeometry( exteriorParts->geometryN( i )->clone() );
3129 for (
int j = 0; j < ringParts->numGeometries(); ++j )
3130 result->addGeometry( ringParts->geometryN( j )->clone() );
3139 if ( pattern.size() < 2 )
3143 if ( !mGeometry || mGeometry->isEmpty() )
3155 int numGeom = gc->numGeometries();
3156 QVector< QgsAbstractGeometry * > geometryList;
3157 geometryList.reserve( numGeom );
3158 for (
int i = 0; i < numGeom; ++i )
3160 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
3168 for (
int j = 0; j < collection->numGeometries(); ++j )
3170 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.
Q_DECL_DEPRECATED 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.