40 : mGeometry( geometry.constGet() )
67 double dx = p2.
x() - p1.
x();
68 double dy = p2.
y() - p1.
y();
69 if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
71 if ( fabs( dx ) >= fabs( dy ) )
73 double dev = fabs( dy ) / fabs( dx );
80 double dev = fabs( dx ) / fabs( dy );
98 std::array<Direction, 5> dirs;
105 while ( current != end )
115 else if ( dir != dirs[idx - 1] )
125 ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
126 std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
132 int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
133 for (
int i = 1; i < 4; ++i )
135 if ( dirs[i] != oriented[( idx + i ) % 4] )
166 const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( mGeometry );
171 if ( vertexCount < 4 )
173 else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
177 std::array<Direction, 4> dirs;
178 std::tie( found4Dirs, dirs ) =
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
192 QVector<QgsLineString *> linesToProcess;
194 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
197 linesToProcess.reserve( multiCurve->
partCount() );
198 for (
int i = 0; i < multiCurve->
partCount(); ++i )
200 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
204 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
207 linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
210 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() :
nullptr );
213 if ( !linesToProcess.empty() )
215 std::unique_ptr< QgsLineString > secondline;
216 for (
QgsLineString *line : std::as_const( linesToProcess ) )
218 QTransform transform = QTransform::fromTranslate( x, y );
220 secondline.reset( line->reversed() );
221 secondline->transform( transform );
223 line->append( secondline.get() );
224 line->addVertex( line->pointN( 0 ) );
230 multipolygon->addGeometry( polygon );
252 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
256 , d( polygon->pointDistanceToBoundary( x, y ) )
257 , max( d + h * M_SQRT2 )
272 struct GreaterThanByMax
274 bool operator()(
const Cell *lhs,
const Cell *rhs )
276 return rhs->max > lhs->max;
280 Cell *getCentroidCell(
const QgsPolygon *polygon )
288 for (
int i = 0, j = len - 1; i < len; j = i++ )
290 double aX = exterior->
xAt( i );
291 double aY = exterior->
yAt( i );
292 double bX = exterior->
xAt( j );
293 double bY = exterior->
yAt( j );
294 double f = aX * bY - bX * aY;
295 x += ( aX + bX ) * f;
296 y += ( aY + bY ) * f;
300 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
302 return new Cell( x / area, y / area, 0.0, polygon );
307 std::unique_ptr< QgsPolygon > segmentizedPoly;
308 const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( surface );
312 polygon = segmentizedPoly.get();
319 double cellSize = std::min( bounds.
width(), bounds.
height() );
324 double h = cellSize / 2.0;
325 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
332 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
337 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
340 std::unique_ptr< Cell > bboxCell(
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
343 if ( bboxCell->d > bestCell->d )
345 bestCell = std::move( bboxCell );
348 while ( !cellQueue.empty() )
351 std::unique_ptr< Cell > cell( cellQueue.top() );
353 Cell *currentCell = cell.get();
356 if ( currentCell->d > bestCell->d )
358 bestCell = std::move( cell );
362 if ( currentCell->max - bestCell->d <=
precision )
366 h = currentCell->h / 2.0;
367 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y - h, h, polygon ) );
368 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y - h, h, polygon ) );
369 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y + h, h, polygon ) );
370 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
373 distanceFromBoundary = bestCell->d;
375 return QgsPoint( bestCell->x, bestCell->y );
383 if ( distanceFromBoundary )
384 *distanceFromBoundary = std::numeric_limits<double>::max();
386 if ( !mGeometry || mGeometry->
isEmpty() )
392 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
394 int numGeom = gc->numGeometries();
397 for (
int i = 0; i < numGeom; ++i )
399 const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( gc->geometryN( i ) );
403 double dist = std::numeric_limits<double>::max();
405 if ( dist > maxDist )
415 if ( distanceFromBoundary )
416 *distanceFromBoundary = maxDist;
421 const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( mGeometry );
425 double dist = std::numeric_limits<double>::max();
430 if ( distanceFromBoundary )
431 *distanceFromBoundary = dist;
442 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
468 for (
int i = 0; i < numPoints; ++i )
470 if ( !isClosed && i == numPoints - 1 )
472 else if ( !isClosed && i == 0 )
481 a = ring->
pointN( numPoints - 1 );
484 if ( i == numPoints - 1 )
493 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
503 double lowerThreshold,
double upperThreshold )
512 double scale = 2.0 * std::min( p.
length(), q.
length() );
516 double dotProduct = p * q;
525 if ( dotProduct < -M_SQRT1_2 )
530 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
535 double minScore = std::numeric_limits<double>::max();
540 std::unique_ptr< QgsLineString > best( ring->
clone() );
542 QVector< QgsVector > motions;
543 motions.reserve( numPoints );
545 for (
int it = 0; it < iterations; ++it )
553 for (
int i = 0; i < numPoints; ++i )
555 if ( isClosed && i == numPoints - 1 )
556 motions << motions.at( 0 );
557 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
567 a = ring->
pointN( numPoints - 1 );
570 if ( i == numPoints - 1 )
575 motions <<
calcMotion( a, b,
c, lowerThreshold, upperThreshold );
582 for (
int i = 0; i < numPoints; ++i )
584 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
585 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
588 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
589 if ( newScore < minScore )
591 best.reset( ring->
clone() );
595 if ( minScore < tolerance )
601 return best.release();
607 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
611 geom = segmentizedCopy.get();
617 maxIterations, tolerance, lowerThreshold, upperThreshold );
626 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
630 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
646 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
647 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
649 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
651 int numGeom = gc->numGeometries();
652 QVector< QgsAbstractGeometry * > geometryList;
653 geometryList.reserve( numGeom );
654 for (
int i = 0; i < numGeom; ++i )
656 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
675 QVector< double > outX;
676 QVector< double > outY;
677 QVector< double > outZ;
678 QVector< double > outM;
679 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
682 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
683 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
684 bool withZ = ring->
is3D();
686 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
689 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
702 int extraNodesThisSegment = extraNodesPerSegment;
703 for (
int i = 0; i < nPoints - 1; ++i )
706 x2 = ring->
xAt( i + 1 );
708 y2 = ring->
yAt( i + 1 );
712 z2 = ring->
zAt( i + 1 );
717 m2 = ring->
mAt( i + 1 );
727 if ( extraNodesPerSegment < 0 )
730 extraNodesThisSegment = std::floor( std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) / distance );
731 if ( extraNodesThisSegment >= 1 )
732 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
735 for (
int j = 0; j < extraNodesThisSegment; ++j )
737 double delta = multiplier * ( j + 1 );
738 xOut = x1 + delta * ( x2 - x1 );
739 yOut = y1 + delta * ( y2 - y1 );
741 zOut = z1 + delta * ( z2 - z1 );
743 mOut = m1 + delta * ( m2 - m1 );
753 outX << ring->
xAt( nPoints - 1 );
754 outY << ring->
yAt( nPoints - 1 );
756 outZ << ring->
zAt( nPoints - 1 );
758 outM << ring->
mAt( nPoints - 1 );
766 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
770 geom = segmentizedCopy.get();
784 extraNodesPerSegment, distance ) );
788 extraNodesPerSegment, distance ) );
808 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
810 int numGeom = gc->numGeometries();
811 QVector< QgsAbstractGeometry * > geometryList;
812 geometryList.reserve( numGeom );
813 for (
int i = 0; i < numGeom; ++i )
815 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
844 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
846 int numGeom = gc->numGeometries();
847 QVector< QgsAbstractGeometry * > geometryList;
848 geometryList.reserve( numGeom );
849 for (
int i = 0; i < numGeom; ++i )
876 "line_segment_dist_comparer",
877 "AB must not be collinear with the origin." );
879 "line_segment_dist_comparer",
880 "CD must not be collinear with the origin." );
894 if ( ab.
end() == cd.
end() || oad != oab )
904 if ( cdb == 0 && cda == 0 )
906 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
908 else if ( cda == cdb || cda == 0 || cdb == 0 )
911 return cdo == cda || cdo == cdb;
927 const bool aIsLeft = a.
x() < mVertex.x();
928 const bool bIsLeft = b.
x() < mVertex.x();
929 if ( aIsLeft != bIsLeft )
934 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
936 return b.
y() < a.
y();
940 return a.
y() < b.
y();
972 const int abo =
segment.pointLeftOfLine( origin );
979 const double distA = ao * direction;
980 const double distB = ( origin -
segment.end() ) * direction;
982 if ( distA > 0 && distB > 0 )
988 if ( ( distA > 0 ) != ( distB > 0 ) )
989 intersectPoint = origin;
990 else if ( distA > distB )
991 intersectPoint =
segment.start();
993 intersectPoint =
segment.end();
1001 if ( u < 0.0 || 1.0 < u )
1008 intersectPoint = origin + direction * t;
1017 if ( radius1 > radius2 )
1024 QVector<QgsPointXY> points;
1046 std::vector< std::unique_ptr<QgsLineString > > linesToProcess;
1048 const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
1051 for (
int i = 0; i < multiCurve->
partCount(); ++i )
1060 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
1067 if ( linesToProcess.empty() )
1070 g.mLastError = QStringLiteral(
"Input geometry was not a curve type geometry" );
1074 QVector<QgsGeometry> bufferedLines;
1075 bufferedLines.reserve( linesToProcess.size() );
1077 for ( std::unique_ptr< QgsLineString > &line : linesToProcess )
1079 QVector<QgsGeometry> parts;
1081 double prevRadius = 0;
1084 std::unique_ptr< double[] > widths = widthFunction( line.get() ) ;
1089 double thisRadius = widths[ i ] / 2.0;
1090 if ( thisRadius > 0 )
1094 QgsCircle circ( thisPoint, thisRadius );
1096 parts << thisCircle;
1105 if ( prevRadius > 0 || thisRadius > 0 )
1107 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
1108 if ( !points.empty() )
1113 int beforeVertex = 0;
1114 int afterVertex = 0;
1116 double sqrDistPrev = 0;
1117 for (
int j = 0; j < points.count(); ++j )
1121 points[j] = sqrDistPrev < sqrDist ? pA : pB;
1124 points.append( points.at( 0 ) );
1126 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
1128 if ( poly->area() > 0 )
1133 prevPoint = thisPoint;
1134 prevRadius = thisRadius;
1135 prevCircle = thisCircle;
1147 start = std::fabs( start );
1148 end = std::fabs( end );
1154 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1156 widths[line->nCoordinates() - 1] = end;
1158 double lineLength = line->length();
1159 double currentLength = 0;
1160 QgsPoint prevPoint = line->pointN( 0 );
1161 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1163 QgsPoint point = line->pointN( i );
1164 double segmentLength = point.
distance( prevPoint );
1165 currentLength += segmentLength;
1166 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1167 double delta = lengthFraction * ( end - start );
1168 widths[i] = start + delta;
1182 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1183 for (
int i = 0; i < line->nCoordinates(); ++i )
1185 widths[ i ] = line->mAt( i );
1194 const std::function<
bool(
const QgsPointXY & ) > &acceptPoint,
unsigned long seed,
QgsFeedback *feedback,
int maxTriesPerPoint )
1197 return QVector< QgsPointXY >();
1209 return QVector< QgsPointXY >();
1217 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->
geometryN( i )->
segmentize() ) );
1224 if (
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( polygon.
constGet() ) )
1230 std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( polygon.
constGet()->
segmentize() ) );
1236 return QVector< QgsPointXY >();
1238 const QVector<float> triangleData = t.
data();
1239 if ( triangleData.empty() )
1240 return QVector< QgsPointXY >();
1243 std::vector< double > cumulativeAreas;
1245 double totalArea = 0;
1246 for (
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
1249 return QVector< QgsPointXY >();
1251 const float aX = *it++;
1253 const float aY = -( *it++ );
1254 const float bX = *it++;
1256 const float bY = -( *it++ );
1257 const float cX = *it++;
1259 const float cY = -( *it++ );
1263 cumulativeAreas.emplace_back( totalArea );
1266 std::random_device rd;
1267 std::mt19937 mt( seed == 0 ? rd() : seed );
1268 std::uniform_real_distribution<> uniformDist( 0, 1 );
1271 auto selectRandomTriangle = [&cumulativeAreas, totalArea](
double random )->
int
1274 const double target = random * totalArea;
1275 for (
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
1280 Q_ASSERT_X(
false,
"QgsInternalGeometryEngine::randomPointsInPolygon",
"Invalid random triangle index" );
1285 QVector<QgsPointXY> result;
1286 result.reserve( count );
1288 for (
int i = 0; i < count; )
1291 return QVector< QgsPointXY >();
1293 const double triangleIndexRnd = uniformDist( mt );
1295 const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
1298 const double weightB = uniformDist( mt );
1299 const double weightC = uniformDist( mt );
1304 const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
1305 const double aY = -triangleData.at( triangleIndex * 9 + 2 ) + bounds.
yMinimum();
1306 const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
1307 const double bY = -triangleData.at( triangleIndex * 9 + 5 ) + bounds.
yMinimum();
1308 const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
1309 const double cY = -triangleData.at( triangleIndex * 9 + 8 ) + bounds.
yMinimum();
1313 if ( acceptPoint( candidate ) )
1319 else if ( maxTriesPerPoint != 0 )
1323 if ( tries == maxTriesPerPoint )
1336 double pointSpacingAngleTolerance )
1338 std::unique_ptr< QgsCompoundCurve > out = std::make_unique< QgsCompoundCurve >();
1341 const unsigned int minQuadEdges = 2;
1354 out->addCurve( lineString->
clone() );
1360 QVector< int > edgesInArcs( numEdges + 1, 0 );
1364 double abX = b.x() - a.
x();
1365 double abY = b.y() - a.
y();
1367 double cbX = b.x() -
c.x();
1368 double cbY = b.y() -
c.y();
1370 double dot = ( abX * cbX + abY * cbY );
1371 double cross = ( abX * cbY - abY * cbX );
1373 double alpha = std::atan2( cross, dot );
1388 double centerX = 0.0;
1389 double centerY = 0.0;
1392 while ( i < numEdges - 2 )
1394 unsigned int arcEdges = 0;
1395 double numQuadrants = 0;
1398 bool foundArc =
false;
1400 a1 = lineString->
pointN( i );
1401 a2 = lineString->
pointN( i + 1 );
1402 a3 = lineString->
pointN( i + 2 );
1405 for ( j = i + 3; j < numEdges + 1; j++ )
1407 b = lineString->
pointN( j );
1414 for ( k = j - 1; k > j - 4; k-- )
1415 edgesInArcs[k] = currentArc;
1435 arcEdges = j - 1 - i;
1436 if ( first.
x() == b.x() && first.
y() == b.y() )
1451 numQuadrants = ( 4 *
angle ) / ( 2 * M_PI );
1454 if ( arcEdges < minQuadEdges * numQuadrants )
1457 for ( k = j - 1; k >= i; k-- )
1474 int edgeType = edgesInArcs[0];
1476 auto addPointsToCurve = [ lineString, &out ](
int start,
int end,
int type )
1481 QVector< QgsPoint > points;
1482 for (
int j = start; j < end + 2; ++ j )
1484 points.append( lineString->
pointN( j ) );
1486 std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
1487 out->addCurve( straightSegment.release() );
1492 QVector< QgsPoint > points;
1493 points.append( lineString->
pointN( start ) );
1494 points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
1495 points.append( lineString->
pointN( end + 1 ) );
1496 std::unique_ptr< QgsCircularString > curvedSegment = std::make_unique< QgsCircularString >();
1497 curvedSegment->setPoints( points );
1498 out->addCurve( curvedSegment.release() );
1502 for (
int i = 1; i < numEdges; i++ )
1504 if ( edgeType != edgesInArcs[i] )
1507 addPointsToCurve( start, end, edgeType );
1509 edgeType = edgesInArcs[i];
1515 addPointsToCurve( start, end, edgeType );
1530 std::unique_ptr< QgsCurvePolygon > result = std::make_unique< QgsCurvePolygon>();
1533 distanceTolerance, angleTolerance ).release() );
1537 distanceTolerance, angleTolerance ).release() );
1557 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1559 int numGeom = gc->numGeometries();
1560 QVector< QgsAbstractGeometry * > geometryList;
1561 geometryList.reserve( numGeom );
1562 for (
int i = 0; i < numGeom; ++i )
1585 area = std::numeric_limits<double>::max();
1587 width = std::numeric_limits<double>::max();
1588 height = std::numeric_limits<double>::max();
1594 std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
1605 double totalRotation = 0;
1606 while ( hull->nextVertex( vertexId, pt2 ) )
1609 double rotateAngle = 180.0 / M_PI * currentAngle;
1610 totalRotation += rotateAngle;
1612 QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
1613 t.rotate( rotateAngle );
1614 t.translate( -pt0.
x(), -pt0.
y() );
1616 hull->transform( t );
1619 double currentArea = bounds.
width() * bounds.
height();
1620 if ( currentArea < area )
1624 angle = totalRotation;
1625 width = bounds.
width();
1626 height = bounds.
height();
1635 if ( width > height )
1637 width = minRect.
height();
1638 height = minRect.
width();
1643 if (
angle > 180.0 )
1651 const int totalPoints = line->
numPoints();
1652 if ( totalPoints < 2 )
1655 const double *x = line->
xData();
1656 const double *y = line->
yData();
1658 double prevX = *x++;
1659 double prevY = *y++;
1661 QVector< double > outX;
1662 QVector< double > outY;
1663 const double totalLength = line->
length();
1665 const int maxRepetitions = std::ceil( totalLength / wavelength );
1666 if ( !strictWavelength )
1667 wavelength = totalLength / maxRepetitions;
1669 const int estimatedPoints = maxRepetitions * 2 + 2;
1670 outX.reserve( estimatedPoints );
1671 outY.reserve( estimatedPoints );
1672 outX.append( prevX );
1673 outY.append( prevY );
1675 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1677 for (
int i = 1; i < totalPoints; ++i )
1679 double thisX = *x++;
1680 double thisY = *y++;
1683 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1684 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1687 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1692 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1693 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1695 outX.append( outPointX );
1696 outY.append( outPointY );
1698 distanceToNextPointFromStartOfSegment += wavelength / 2;
1704 distanceToNextPointFromStartOfSegment -= segmentLength;
1707 outX.append( prevX );
1708 outY.append( prevY );
1710 return std::make_unique< QgsLineString >( outX, outY );
1714 const double minimumWavelength,
const double maximumWavelength,
1715 const double minimumAmplitude,
const double maximumAmplitude,
1716 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1718 const int totalPoints = line->
numPoints();
1719 if ( totalPoints < 2 )
1722 const double *x = line->
xData();
1723 const double *y = line->
yData();
1725 double prevX = *x++;
1726 double prevY = *y++;
1728 QVector< double > outX;
1729 QVector< double > outY;
1730 const double totalLength = line->
length();
1732 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
1734 const int estimatedPoints = maxRepetitions * 2 + 2;
1735 outX.reserve( estimatedPoints );
1736 outY.reserve( estimatedPoints );
1737 outX.append( prevX );
1738 outY.append( prevY );
1740 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1741 double distanceToNextPointFromStartOfSegment = wavelength / 4;
1742 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1745 for (
int i = 1; i < totalPoints; ++i )
1747 double thisX = *x++;
1748 double thisY = *y++;
1751 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1752 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1755 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1760 const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
1761 const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
1762 outX.append( outPointX );
1763 outY.append( outPointY );
1765 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
1766 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
1768 distanceToNextPointFromStartOfSegment += wavelength / 2;
1774 distanceToNextPointFromStartOfSegment -= segmentLength;
1777 outX.append( prevX );
1778 outY.append( prevY );
1780 return std::make_unique< QgsLineString >( outX, outY );
1785 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1789 geom = segmentizedCopy.get();
1800 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1803 wavelength, amplitude, strictWavelength ).release() );
1807 wavelength, amplitude, strictWavelength ).release() );
1814 std::unique_ptr< QgsAbstractGeometry >
triangularWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
1816 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
1820 geom = segmentizedCopy.get();
1831 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
1834 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
1838 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
1861 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1863 int numGeom = gc->numGeometries();
1864 QVector< QgsAbstractGeometry * > geometryList;
1865 geometryList.reserve( numGeom );
1866 for (
int i = 0; i < numGeom; ++i )
1868 geometryList <<
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
1886 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
1895 std::random_device rd;
1896 std::mt19937 mt( seed == 0 ? rd() : seed );
1897 std::uniform_real_distribution<> uniformDist( 0, 1 );
1904 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
1906 int numGeom = gc->numGeometries();
1907 QVector< QgsAbstractGeometry * > geometryList;
1908 geometryList.reserve( numGeom );
1909 for (
int i = 0; i < numGeom; ++i )
1911 geometryList <<
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
1929 const int totalPoints = line->
numPoints();
1930 if ( totalPoints < 2 )
1933 const double *x = line->
xData();
1934 const double *y = line->
yData();
1936 double prevX = *x++;
1937 double prevY = *y++;
1939 QVector< double > outX;
1940 QVector< double > outY;
1941 const double totalLength = line->
length();
1943 const int maxRepetitions = std::ceil( totalLength / wavelength );
1944 if ( !strictWavelength )
1945 wavelength = totalLength / maxRepetitions;
1947 const int estimatedPoints = maxRepetitions * 4 + 2;
1948 outX.reserve( estimatedPoints );
1949 outY.reserve( estimatedPoints );
1950 outX.append( prevX );
1951 outY.append( prevY );
1954 outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
1955 outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
1957 double distanceToNextPointFromStartOfSegment = wavelength / 2;
1960 for (
int i = 1; i < totalPoints; ++i )
1962 double thisX = *x++;
1963 double thisY = *y++;
1966 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1967 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
1970 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
1975 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
1976 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
1977 outX.append( pX + side * amplitude * sinAngle );
1978 outY.append( pY + side * amplitude * cosAngle );
1979 outX.append( pX - side * amplitude * sinAngle );
1980 outY.append( pY - side * amplitude * cosAngle );
1982 distanceToNextPointFromStartOfSegment += wavelength / 2;
1988 distanceToNextPointFromStartOfSegment -= segmentLength;
1994 outX.append( prevX );
1995 outY.append( prevY );
1997 return std::make_unique< QgsLineString >( outX, outY );
2001 const double minimumWavelength,
const double maximumWavelength,
2002 const double minimumAmplitude,
const double maximumAmplitude,
2003 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2005 const int totalPoints = line->
numPoints();
2006 if ( totalPoints < 2 )
2009 const double *x = line->
xData();
2010 const double *y = line->
yData();
2012 double prevX = *x++;
2013 double prevY = *y++;
2015 QVector< double > outX;
2016 QVector< double > outY;
2017 const double totalLength = line->
length();
2019 const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
2021 const int estimatedPoints = maxRepetitions * 4 + 2;
2022 outX.reserve( estimatedPoints );
2023 outY.reserve( estimatedPoints );
2024 outX.append( prevX );
2025 outY.append( prevY );
2027 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2030 outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2031 outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2033 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2034 double distanceToNextPointFromStartOfSegment = wavelength / 2;
2037 for (
int i = 1; i < totalPoints; ++i )
2039 double thisX = *x++;
2040 double thisY = *y++;
2043 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2044 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2047 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2052 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2053 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2054 outX.append( pX + side * amplitude * sinAngle );
2055 outY.append( pY + side * amplitude * cosAngle );
2057 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2058 outX.append( pX - side * amplitude * sinAngle );
2059 outY.append( pY - side * amplitude * cosAngle );
2061 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2062 distanceToNextPointFromStartOfSegment += wavelength / 2;
2068 distanceToNextPointFromStartOfSegment -= segmentLength;
2071 outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
2072 outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
2073 outX.append( prevX );
2074 outY.append( prevY );
2076 return std::make_unique< QgsLineString >( outX, outY );
2081 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2085 geom = segmentizedCopy.get();
2096 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2099 wavelength, amplitude, strictWavelength ).release() );
2103 wavelength, amplitude, strictWavelength ).release() );
2110 std::unique_ptr< QgsAbstractGeometry >
squareWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2112 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2116 geom = segmentizedCopy.get();
2127 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2130 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2134 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2157 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2159 int numGeom = gc->numGeometries();
2160 QVector< QgsAbstractGeometry * > geometryList;
2161 geometryList.reserve( numGeom );
2162 for (
int i = 0; i < numGeom; ++i )
2164 geometryList <<
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2182 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2191 std::random_device rd;
2192 std::mt19937 mt( seed == 0 ? rd() : seed );
2193 std::uniform_real_distribution<> uniformDist( 0, 1 );
2200 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2202 int numGeom = gc->numGeometries();
2203 QVector< QgsAbstractGeometry * > geometryList;
2204 geometryList.reserve( numGeom );
2205 for (
int i = 0; i < numGeom; ++i )
2207 geometryList <<
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2225 const int totalPoints = line->
numPoints();
2226 if ( totalPoints < 2 )
2229 const double *x = line->
xData();
2230 const double *y = line->
yData();
2232 double prevX = *x++;
2233 double prevY = *y++;
2235 const double totalLength = line->
length();
2237 const int maxRepetitions = std::ceil( totalLength / wavelength );
2238 if ( !strictWavelength )
2239 wavelength = totalLength / maxRepetitions;
2241 const int segments = 10;
2245 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2246 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2247 bool isFirstPart =
true;
2249 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2250 int bufferIndex = 1;
2251 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2253 double segmentAngleRadians = 0;
2254 double remainingDistance = totalLength;
2255 double totalCoveredDistance = 0;
2257 for (
int i = 1; i < totalPoints; ++i )
2259 double thisX = *x++;
2260 double thisY = *y++;
2263 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2264 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2267 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2270 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2272 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2273 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2275 if ( bufferIndex == 0 )
2277 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2278 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2280 distanceToNextPointFromStartOfSegment += wavelength / 4;
2282 else if ( bufferIndex == 1 && isFirstPart )
2284 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2285 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2286 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2287 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2289 distanceToNextPointFromStartOfSegment += wavelength / 8;
2291 else if ( bufferIndex == 1 )
2293 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2294 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2295 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2296 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2298 distanceToNextPointFromStartOfSegment += wavelength / 4;
2300 else if ( bufferIndex == 2 )
2302 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2303 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2307 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2308 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2309 isFirstPart =
false;
2314 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2315 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2316 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2318 out->append( bezier.get() );
2321 xOutBuffer[0] = xOutBuffer[3];
2322 yOutBuffer[0] = yOutBuffer[3];
2325 distanceToNextPointFromStartOfSegment += wavelength / 4;
2328 totalCoveredDistance += segmentLength;
2331 distanceToNextPointFromStartOfSegment -= segmentLength;
2334 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2335 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2336 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2337 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2340 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2341 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2344 out->append( bezier.get() );
2350 const double minimumWavelength,
const double maximumWavelength,
2351 const double minimumAmplitude,
const double maximumAmplitude,
2352 std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2354 const int totalPoints = line->
numPoints();
2355 if ( totalPoints < 2 )
2358 const double *x = line->
xData();
2359 const double *y = line->
yData();
2361 double prevX = *x++;
2362 double prevY = *y++;
2364 const double totalLength = line->
length();
2366 const int segments = 10;
2370 double xOutBuffer[4] { prevX, prevX, prevX, prevX };
2371 double yOutBuffer[4] { prevY, prevY, prevY, prevY };
2372 bool isFirstPart =
true;
2374 double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2375 double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2377 double distanceToNextPointFromStartOfSegment = wavelength / 8;
2378 int bufferIndex = 1;
2379 std::unique_ptr< QgsLineString > out = std::make_unique< QgsLineString >();
2381 double segmentAngleRadians = 0;
2383 double remainingDistance = totalLength;
2384 double totalCoveredDistance = 0;
2386 for (
int i = 1; i < totalPoints; ++i )
2388 double thisX = *x++;
2389 double thisY = *y++;
2392 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2393 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2396 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2399 remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
2401 const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
2402 const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
2404 if ( bufferIndex == 0 )
2406 xOutBuffer[0] = pX + side * amplitude * sinAngle;
2407 yOutBuffer[0] = pY + side * amplitude * cosAngle;
2409 distanceToNextPointFromStartOfSegment += wavelength / 4;
2411 else if ( bufferIndex == 1 && isFirstPart )
2413 xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
2414 yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
2415 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2416 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2418 distanceToNextPointFromStartOfSegment += wavelength / 8;
2420 else if ( bufferIndex == 1 )
2422 xOutBuffer[1] = pX + side * amplitude * sinAngle;
2423 yOutBuffer[1] = pY + side * amplitude * cosAngle;
2424 amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
2425 xOutBuffer[2] = pX - side * amplitude * sinAngle;
2427 yOutBuffer[2] = pY - side * amplitude * cosAngle;
2428 distanceToNextPointFromStartOfSegment += wavelength / 4;
2430 else if ( bufferIndex == 2 )
2432 xOutBuffer[3] = pX - side * amplitude * sinAngle;
2433 yOutBuffer[3] = pY - side * amplitude * cosAngle;
2437 xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
2438 yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
2439 isFirstPart =
false;
2444 QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
2445 QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
2446 QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
2448 out->append( bezier.get() );
2451 xOutBuffer[0] = xOutBuffer[3];
2452 yOutBuffer[0] = yOutBuffer[3];
2456 wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
2458 distanceToNextPointFromStartOfSegment += wavelength / 4;
2461 totalCoveredDistance += segmentLength;
2465 distanceToNextPointFromStartOfSegment -= segmentLength;
2468 const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
2469 const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
2470 const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
2471 const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
2473 if ( out->isEmpty() )
2477 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2480 out->append( bezier.get() );
2485 QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
2486 QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
2489 out->append( bezier.get() );
2497 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2501 geom = segmentizedCopy.get();
2512 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2515 wavelength, amplitude, strictWavelength ).release() );
2519 wavelength, amplitude, strictWavelength ).release() );
2526 std::unique_ptr< QgsAbstractGeometry >
roundWavesRandomizedPrivate(
const QgsAbstractGeometry *geom,
double minimumWavelength,
double maximumWavelength,
double minimumAmplitude,
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
2528 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2532 geom = segmentizedCopy.get();
2543 std::unique_ptr< QgsPolygon > result = std::make_unique< QgsPolygon >();
2546 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2550 minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
2573 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2575 int numGeom = gc->numGeometries();
2576 QVector< QgsAbstractGeometry * > geometryList;
2577 geometryList.reserve( numGeom );
2578 for (
int i = 0; i < numGeom; ++i )
2580 geometryList <<
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
2598 if ( minimumWavelength < 0 ||
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 ||
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
2607 std::random_device rd;
2608 std::mt19937 mt( seed == 0 ? rd() : seed );
2609 std::uniform_real_distribution<> uniformDist( 0, 1 );
2616 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2618 int numGeom = gc->numGeometries();
2619 QVector< QgsAbstractGeometry * > geometryList;
2620 geometryList.reserve( numGeom );
2621 for (
int i = 0; i < numGeom; ++i )
2623 geometryList <<
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
2640 const QVector< double> &pattern,
2644 double patternOffset )
2646 const int totalPoints = line->
numPoints();
2647 if ( totalPoints < 2 )
2650 const int patternSize = pattern.size();
2652 const double *x = line->
xData();
2653 const double *y = line->
yData();
2655 double prevX = *x++;
2656 double prevY = *y++;
2658 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2660 QVector< double > outX;
2661 QVector< double > outY;
2662 const double totalLength = line->
length();
2664 double patternLength = 0;
2665 double patternDashLength = 0;
2666 double patternGapLength = 0;
2667 for (
int i = 0; i < pattern.size(); ++i )
2669 patternLength += pattern.at( i );
2671 patternDashLength += pattern.at( i );
2673 patternGapLength += pattern.at( i );
2676 double firstPatternLength = 0;
2677 double firstPatternDashLength = 0;
2678 double firstPatternGapLength = 0;
2679 switch ( startRule )
2683 firstPatternLength = patternLength;
2684 firstPatternDashLength = patternDashLength;
2685 firstPatternGapLength = patternGapLength;
2688 firstPatternLength = patternLength - pattern.at( 0 ) * 0.5;
2689 firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
2690 firstPatternGapLength = patternGapLength;
2693 firstPatternLength = pattern.at( patternSize - 1 );
2694 firstPatternDashLength = 0;
2695 firstPatternGapLength = pattern.at( patternSize - 1 );
2698 firstPatternLength = pattern.at( patternSize - 1 ) * 0.5;
2699 firstPatternDashLength = 0;
2700 firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
2704 const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
2706 double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
2707 double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
2708 double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
2712 lastPatternLength = 0;
2713 lastPatternDashLength = 0;
2714 lastPatternGapLength = 0;
2717 lastPatternLength -= pattern.at( patternSize - 1 );
2718 lastPatternGapLength -= pattern.at( patternSize - 1 );
2721 lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5;
2722 lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
2723 lastPatternGapLength -= pattern.at( patternSize - 1 );
2726 lastPatternGapLength = patternGapLength;
2729 lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5;
2730 lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
2734 const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
2735 const int middlePatternRepetitions = std::max(
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
2737 const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
2738 const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
2739 const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
2741 double dashLengthScalingFactor = 1;
2742 double gapLengthScalingFactor = 1;
2746 const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
2748 switch ( adjustment )
2751 dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
2752 gapLengthScalingFactor = dashLengthScalingFactor;
2755 dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
2758 gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
2763 dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
2764 gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
2766 const int maxPatterns = middlePatternRepetitions + 2;
2767 result->reserve( maxPatterns );
2769 int patternIndex = 0;
2770 double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
2772 switch ( startRule )
2778 distanceToNextPointFromStartOfSegment *= 0.5;
2781 patternIndex = patternSize - 1;
2783 distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2786 patternIndex = patternSize - 1;
2788 distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
2792 const double adjustedOffset = fmod( patternOffset, patternLength );
2793 const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
2797 double remainingOffset = scaledOffset;
2798 while ( remainingOffset > 0 )
2800 if ( distanceToNextPointFromStartOfSegment > remainingOffset )
2802 distanceToNextPointFromStartOfSegment -= remainingOffset;
2806 remainingOffset -= distanceToNextPointFromStartOfSegment;
2809 if ( patternIndex == patternSize )
2812 distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
2818 outX.append( prevX );
2819 outY.append( prevY );
2822 for (
int i = 1; i < totalPoints; ++i )
2824 double thisX = *x++;
2825 double thisY = *y++;
2827 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
2828 while ( distanceToNextPointFromStartOfSegment < segmentLength ||
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
2831 const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
2846 if ( patternIndex >= patternSize )
2849 distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
2854 outX.append( thisX );
2855 outY.append( thisY );
2860 distanceToNextPointFromStartOfSegment -= segmentLength;
2865 outX.append( prevX );
2866 outY.append( prevY );
2874 const QVector<double> &pattern,
2878 double patternOffset )
2880 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
2884 geom = segmentizedCopy.get();
2895 std::unique_ptr< QgsMultiLineString > result = std::make_unique< QgsMultiLineString >();
2898 for (
int i = 0; i < exteriorParts->numGeometries(); ++i )
2899 result->addGeometry( exteriorParts->geometryN( i )->clone() );
2904 for (
int j = 0; j < ringParts->numGeometries(); ++j )
2905 result->addGeometry( ringParts->geometryN( j )->clone() );
2914 if ( pattern.size() < 2 )
2918 if ( !mGeometry || mGeometry->
isEmpty() )
2928 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
2930 int numGeom = gc->numGeometries();
2931 QVector< QgsAbstractGeometry * > geometryList;
2932 geometryList.reserve( numGeom );
2933 for (
int i = 0; i < numGeom; ++i )
2935 geometryList <<
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
2943 for (
int j = 0; j < collection->numGeometries(); ++j )
2945 first.
addPart( collection->geometryN( j )->clone() );
DashPatternSizeAdjustment
Dash pattern size adjustment options.
@ ScaleDashOnly
Only dash lengths are adjusted.
@ ScaleBothDashAndGap
Both the dash and gap lengths are adjusted equally.
@ ScaleGapOnly
Only gap lengths are adjusted.
DashPatternLineEndingRule
Dash pattern line ending rules.
@ HalfDash
Start or finish the pattern with a half length dash.
@ HalfGap
Start or finish the pattern with a half length gap.
@ FullGap
Start or finish the pattern with a full gap.
@ FullDash
Start or finish the pattern with a full dash.
The vertex_iterator class provides STL-style iterator for vertices.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
virtual bool isEmpty() const
Returns true if the geometry is empty.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
const QgsCurve * interiorRing(int i) const SIP_HOLDGIL
Retrieves an interior ring from the curve polygon.
const QgsCurve * exteriorRing() const SIP_HOLDGIL
Returns the curve polygon's exterior ring.
int numInteriorRings() const SIP_HOLDGIL
Returns the number of interior rings contained with 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 SIP_HOLDGIL
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 SIP_HOLDGIL
Tells whether the operation has been canceled already.
int numGeometries() const SIP_HOLDGIL
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.
int partCount() const override
Returns count of parts contained in the geometry.
static double triangleArea(double aX, double aY, double bX, double bY, double cX, double cY) SIP_HOLDGIL
Returns the area of the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
static void circleCenterRadius(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double &radius, double ¢erX, double ¢erY) SIP_HOLDGIL
Returns radius and center of the circle through pt1, pt2, pt3.
static double lineAngle(double x1, double y1, double x2, double y2) SIP_HOLDGIL
Calculates the direction of line joining two points in radians, clockwise from the north direction.
static int circleCircleOuterTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2) SIP_HOLDGIL
Calculates the outer tangent points for two circles, centered at center1 and center2 and with radii o...
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance) SIP_HOLDGIL
Returns a point a specified distance toward a second point.
static bool pointContinuesArc(const QgsPoint &a1, const QgsPoint &a2, const QgsPoint &a3, const QgsPoint &b, double distanceTolerance, double pointSpacingAngleTolerance) SIP_HOLDGIL
Returns true if point b is on the arc formed by points a1, a2, and a3, but not within that arc portio...
static void weightedPointInTriangle(double aX, double aY, double bX, double bY, double cX, double cY, double weightB, double weightC, double &pointX, double &pointY) SIP_HOLDGIL
Returns a weighted point inside 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) SIP_HOLDGIL
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> (x2, y2).
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries)
Compute the unary union on a list of geometries.
QgsPointXY closestVertex(const QgsPointXY &point, int &closestVertexIndex, int &previousVertexIndex, int &nextVertexIndex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
Qgis::GeometryOperationResult addPart(const QVector< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
bool isMultipart() const SIP_HOLDGIL
Returns true if WKB of the geometry is of WKBMulti* type.
QgsWkbTypes::GeometryType type
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
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.
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...
static QVector< QgsPointXY > randomPointsInPolygon(const QgsGeometry &polygon, 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 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.
QgsPointXY end() const SIP_HOLDGIL
Returns the segment's end point.
int pointLeftOfLine(const QgsPointXY &point) const SIP_HOLDGIL
Tests if a point is to the left of the line segment.
double endX() const SIP_HOLDGIL
Returns the segment's end x-coordinate.
double endY() const SIP_HOLDGIL
Returns the segment's end y-coordinate.
double startX() const SIP_HOLDGIL
Returns the segment's start x-coordinate.
QgsPointXY start() const SIP_HOLDGIL
Returns the segment's start point.
void reverse() SIP_HOLDGIL
Reverses the line segment, so that the start and end points are flipped.
double startY() const SIP_HOLDGIL
Returns the segment's start y-coordinate.
Line string geometry type, with support for z-dimension and m-values.
QgsPoint startPoint() const override SIP_HOLDGIL
Returns the starting point of the curve.
bool isClosed() const override SIP_HOLDGIL
Returns true if the curve is closed.
const double * yData() const
Returns a const pointer to the y vertex data.
double length() const override SIP_HOLDGIL
Returns the planar, 2-dimensional length of the geometry.
int numPoints() const override SIP_HOLDGIL
Returns the number of points in the curve.
static QgsLineString * fromBezierCurve(const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments=30)
Returns a new linestring created by segmentizing the bezier curve between start and end,...
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
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
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.
int nCoordinates() const override SIP_HOLDGIL
Returns the number of nodes contained in the geometry.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
double zAt(int index) const
Returns the z-coordinate of the specified node in the line string.
const double * xData() const
Returns a const pointer to the x vertex data.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
Multi curve geometry collection.
Multi polygon geometry collection.
Multi surface geometry collection.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
double distance(double x, double y) const SIP_HOLDGIL
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
void addInteriorRing(QgsCurve *ring) override
Adds an interior ring to the geometry (takes ownership)
bool intersects(const QgsLineSegment2D &segment, QgsPointXY &intersectPoint) const
Finds the closest intersection point of the ray and a line segment.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Class that takes care of tessellation of polygons into triangles.
QVector< float > data() const
Returns array of triangle vertex data.
void addPolygon(const QgsPolygon &polygon, float extrusionHeight)
Tessellates a triangle and adds its vertex entries to the output data array.
int dataVerticesCount() const
Returns the number of vertices stored in the output data array.
A class to represent a vector.
QgsVector normalized() const SIP_THROW(QgsException)
Returns the vector's normalized (or "unit") vector (ie same angle but length of 1....
double lengthSquared() const SIP_HOLDGIL
Returns the length of the vector.
double crossProduct(QgsVector v) const SIP_HOLDGIL
Returns the 2D cross product of this vector and another vector v.
double length() const SIP_HOLDGIL
Returns the length of the vector.
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static bool isCurvedType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a curved type or can contain curved geometries.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
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)
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)
QgsAbstractGeometry * densifyGeometry(const QgsAbstractGeometry *geom, int extraNodesPerSegment=1, double distance=1)
std::unique_ptr< QgsLineString > squareWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
std::unique_ptr< QgsCompoundCurve > lineToCurve(const QgsLineString *lineString, double distanceTolerance, double pointSpacingAngleTolerance)
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)
Direction getEdgeDirection(const QgsPoint &p1, const QgsPoint &p2, double maxDev)
Determines the direction of an edge from p1 to p2.
QVector< QgsPointXY > generateSegmentCurve(const QgsPoint ¢er1, const double radius1, const QgsPoint ¢er2, const double radius2)
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)
bool dotProductWithinAngleTolerance(double dotProduct, double lowerThreshold, double upperThreshold)
std::pair< bool, std::array< Direction, 4 > > getEdgeDirections(const QgsPolygon *g, double maxDev)
Checks whether the polygon consists of four nearly axis-parallel sides.
double squareness(QgsLineString *ring, double lowerThreshold, double upperThreshold)
QgsAbstractGeometry * orthogonalizeGeom(const QgsAbstractGeometry *geom, int maxIterations, double tolerance, 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.
std::unique_ptr< QgsLineString > roundWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
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)
QgsLineString * doOrthogonalize(QgsLineString *ring, int iterations, double tolerance, double lowerThreshold, double upperThreshold)
std::unique_ptr< QgsLineString > triangularWavesAlongLine(const QgsLineString *line, double wavelength, const double amplitude, const bool strictWavelength)
QgsLineString * doDensify(const QgsLineString *ring, int extraNodesPerSegment=-1, double distance=1)
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.