41  : mGeometry( geometry.constGet() )
 
 
   68  double dx = p2.
x() - p1.
x();
 
   69  double dy = p2.
y() - p1.
y();
 
   70  if ( ( dx == 0.0 ) && ( dy == 0.0 ) )
 
   72  if ( fabs( dx ) >= fabs( dy ) )
 
   74    double dev = fabs( dy ) / fabs( dx );
 
   81    double dev = fabs( dx ) / fabs( dy );
 
 
   99  std::array<Direction, 5> dirs;
 
  106  while ( current != end )
 
  116    else if ( dir != dirs[idx - 1] )
 
  126  ret.first = ( idx == 5 ) ? ( dirs[0] == dirs[4] ) : ( idx == 4 );
 
  127  std::copy( dirs.begin(), dirs.begin() + 4, ret.second.begin() );
 
 
  133  int idx = std::find( oriented.begin(), oriented.end(), dirs[0] ) - oriented.begin();
 
  134  for ( 
int i = 1; i < 4; ++i )
 
  136    if ( dirs[i] != oriented[( idx + i ) % 4] )
 
 
  167  const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( mGeometry );
 
  172  if ( vertexCount < 4 )
 
  174  else if ( simpleRectanglesOnly && ( vertexCount != 5 || !polygon->
exteriorRing()->
isClosed() ) )
 
  178  std::array<Direction, 4> dirs;
 
  179  std::tie( found4Dirs, dirs ) = 
getEdgeDirections( polygon, std::tan( maximumDeviation * M_PI / 180 ) );
 
 
  193  QVector<QgsLineString *> linesToProcess;
 
  195  const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
 
  198    linesToProcess.reserve( multiCurve->
partCount() );
 
  199    for ( 
int i = 0; i < multiCurve->
partCount(); ++i )
 
  201      linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
 
  205  const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
 
  208    linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
 
  211  std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ? 
new QgsMultiPolygon() : nullptr );
 
  214  if ( !linesToProcess.empty() )
 
  216    std::unique_ptr< QgsLineString > secondline;
 
  217    for ( 
QgsLineString *line : std::as_const( linesToProcess ) )
 
  219      QTransform transform = QTransform::fromTranslate( x, y );
 
  221      secondline.reset( line->reversed() );
 
  222      secondline->transform( transform );
 
  224      line->append( secondline.get() );
 
  225      line->addVertex( line->pointN( 0 ) );
 
  228      polygon->setExteriorRing( line );
 
  231        multipolygon->addGeometry( polygon );
 
 
  253    Cell( 
double x, 
double y, 
double h, 
const QgsPolygon *polygon )
 
  257      , d( polygon->pointDistanceToBoundary( x, y ) )
 
  258      , max( d + h * M_SQRT2 )
 
  273struct GreaterThanByMax
 
  275  bool operator()( 
const Cell *lhs, 
const Cell *rhs )
 const 
  277    return rhs->max > lhs->max;
 
  281Cell *getCentroidCell( 
const QgsPolygon *polygon )
 
  289  for ( 
int i = 0, j = len - 1; i < len; j = i++ )
 
  291    double aX = exterior->
xAt( i );
 
  292    double aY = exterior->
yAt( i );
 
  293    double bX = exterior->
xAt( j );
 
  294    double bY = exterior->
yAt( j );
 
  295    double f = aX * bY - bX * aY;
 
  296    x += ( aX + bX ) * f;
 
  297    y += ( aY + bY ) * f;
 
  301    return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
 
  303    return new Cell( x / area, y / area, 0.0, polygon );
 
  308  std::unique_ptr< QgsPolygon > segmentizedPoly;
 
  309  const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( surface );
 
  313    polygon = segmentizedPoly.get();
 
  320  double cellSize = std::min( bounds.
width(), bounds.
height() );
 
  325  double h = cellSize / 2.0;
 
  326  std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
 
  333      cellQueue.push( 
new Cell( x + h, y + h, h, polygon ) );
 
  338  std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
 
  341  std::unique_ptr< Cell > bboxCell( 
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
 
  344  if ( bboxCell->d > bestCell->d )
 
  346    bestCell = std::move( bboxCell );
 
  349  while ( !cellQueue.empty() )
 
  352    std::unique_ptr< Cell > cell( cellQueue.top() );
 
  354    Cell *currentCell = cell.get();
 
  357    if ( currentCell->d > bestCell->d )
 
  359      bestCell = std::move( cell );
 
  363    if ( currentCell->max - bestCell->d <= 
precision )
 
  367    h = currentCell->h / 2.0;
 
  368    cellQueue.push( 
new Cell( currentCell->x - h, currentCell->y - h, h, polygon ) );
 
  369    cellQueue.push( 
new Cell( currentCell->x + h, currentCell->y - h, h, polygon ) );
 
  370    cellQueue.push( 
new Cell( currentCell->x - h, currentCell->y + h, h, polygon ) );
 
  371    cellQueue.push( 
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
 
  374  distanceFromBoundary = bestCell->d;
 
  376  return QgsPoint( bestCell->x, bestCell->y );
 
  384  if ( distanceFromBoundary )
 
  385    *distanceFromBoundary = std::numeric_limits<double>::max();
 
  387  if ( !mGeometry || mGeometry->
isEmpty() )
 
  393  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
  395    int numGeom = gc->numGeometries();
 
  398    for ( 
int i = 0; i < numGeom; ++i )
 
  400      const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( gc->geometryN( i ) );
 
  404      double dist = std::numeric_limits<double>::max();
 
  406      if ( dist > maxDist )
 
  416    if ( distanceFromBoundary )
 
  417      *distanceFromBoundary = maxDist;
 
  422    const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( mGeometry );
 
  426    double dist = std::numeric_limits<double>::max();
 
  431    if ( distanceFromBoundary )
 
  432      *distanceFromBoundary = dist;
 
 
  443  return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
 
 
  469  for ( 
int i = 0; i < numPoints; ++i )
 
  471    if ( !isClosed && i == numPoints - 1 )
 
  473    else if ( !isClosed && i == 0 )
 
  482        a = ring->
pointN( numPoints - 1 );
 
  485      if ( i == numPoints - 1 )
 
  494      sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
 
 
  504                      double lowerThreshold, 
double upperThreshold )
 
  513  double scale = 2.0 * std::min( p.
length(), q.
length() );
 
  517  double dotProduct = p * q;
 
  526  if ( dotProduct < -M_SQRT1_2 )
 
  535  return new_v.
normalized() * ( 0.1 * dotProduct * scale );
 
 
  540  double minScore = std::numeric_limits<double>::max();
 
  545  std::unique_ptr< QgsLineString > best( ring->
clone() );
 
  547  QVector< QgsVector >  motions;
 
  548  motions.reserve( numPoints );
 
  550  for ( 
int it = 0; it < iterations; ++it )
 
  558    for ( 
int i = 0; i < numPoints; ++i )
 
  560      if ( isClosed && i == numPoints - 1 )
 
  561        motions << motions.at( 0 ); 
 
  562      else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
 
  572          a = ring->
pointN( numPoints - 1 );
 
  575        if ( i == numPoints - 1 )
 
  580        motions << 
calcMotion( a, b, 
c, lowerThreshold, upperThreshold );
 
  587    for ( 
int i = 0; i < numPoints; ++i )
 
  589      ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
 
  590      ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
 
  593    double newScore = 
squareness( ring, lowerThreshold, upperThreshold );
 
  594    if ( newScore < minScore )
 
  596      best.reset( ring->
clone() );
 
  600    if ( minScore < tolerance )
 
  606  return best.release();
 
 
  612  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
  616    geom = segmentizedCopy.get();
 
  622                            maxIterations, tolerance, lowerThreshold, upperThreshold );
 
  631                             maxIterations, tolerance, lowerThreshold, upperThreshold ) );
 
  635                               maxIterations, tolerance, lowerThreshold, upperThreshold ) );
 
 
  651  double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
 
  652  double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
 
  654  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
  656    int numGeom = gc->numGeometries();
 
  657    QVector< QgsAbstractGeometry * > geometryList;
 
  658    geometryList.reserve( numGeom );
 
  659    for ( 
int i = 0; i < numGeom; ++i )
 
  661      geometryList << 
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
 
 
  680  QVector< double > outX;
 
  681  QVector< double > outY;
 
  682  QVector< double > outZ;
 
  683  QVector< double > outM;
 
  684  double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
 
  687  outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
 
  688  outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
 
  689  bool withZ = ring->
is3D();
 
  691    outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
 
  694    outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
 
  707  int extraNodesThisSegment = extraNodesPerSegment;
 
  708  for ( 
int i = 0; i < nPoints - 1; ++i )
 
  711    x2 = ring->
xAt( i + 1 );
 
  713    y2 = ring->
yAt( i + 1 );
 
  717      z2 = ring->
zAt( i + 1 );
 
  722      m2 = ring->
mAt( i + 1 );
 
  732    if ( extraNodesPerSegment < 0 )
 
  736      if ( extraNodesThisSegment >= 1 )
 
  737        multiplier = 1.0 / ( extraNodesThisSegment + 1 );
 
  740    for ( 
int j = 0; j < extraNodesThisSegment; ++j )
 
  742      double delta = multiplier * ( j + 1 );
 
  743      xOut = x1 + delta * ( x2 - x1 );
 
  744      yOut = y1 + delta * ( y2 - y1 );
 
  746        zOut = z1 + delta * ( z2 - z1 );
 
  748        mOut = m1 + delta * ( m2 - m1 );
 
  758  outX << ring->
xAt( nPoints - 1 );
 
  759  outY << ring->
yAt( nPoints - 1 );
 
  761    outZ << ring->
zAt( nPoints - 1 );
 
  763    outM << ring->
mAt( nPoints - 1 );
 
 
  771  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
  775    geom = segmentizedCopy.get();
 
  789                                        extraNodesPerSegment, distance ) );
 
  793                                          extraNodesPerSegment, distance ) );
 
 
  813  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
  815    int numGeom = gc->numGeometries();
 
  816    QVector< QgsAbstractGeometry * > geometryList;
 
  817    geometryList.reserve( numGeom );
 
  818    for ( 
int i = 0; i < numGeom; ++i )
 
  820      geometryList << 
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
 
 
  849  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
  851    int numGeom = gc->numGeometries();
 
  852    QVector< QgsAbstractGeometry * > geometryList;
 
  853    geometryList.reserve( numGeom );
 
  854    for ( 
int i = 0; i < numGeom; ++i )
 
 
  881              "line_segment_dist_comparer",
 
  882              "AB must not be collinear with the origin." );
 
  884              "line_segment_dist_comparer",
 
  885              "CD must not be collinear with the origin." );
 
  902    if ( ab.
end() == cd.
end() || oad != oab )
 
  912    if ( cdb == 0 && cda == 0 )
 
  914      return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
 
  916    else if ( cda == cdb || cda == 0 || cdb == 0 )
 
  919      return cdo == cda || cdo == cdb;
 
  935  const bool aIsLeft = a.
x() < mVertex.x();
 
  936  const bool bIsLeft = b.
x() < mVertex.x();
 
  937  if ( aIsLeft != bIsLeft )
 
  942    if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
 
  944      return b.
y() < a.
y();
 
  948      return a.
y() < b.
y();
 
  980    const int abo = 
segment.pointLeftOfLine( origin );
 
  987      const double distA = ao * direction;
 
  988      const double distB = ( origin - 
segment.end() ) * direction;
 
  990      if ( distA > 0 && distB > 0 )
 
  996        if ( ( distA > 0 ) != ( distB > 0 ) )
 
  997          intersectPoint = origin;
 
  998        else if ( distA > distB ) 
 
  999          intersectPoint = 
segment.start(); 
 
 1001          intersectPoint = 
segment.end();
 
 1009    if ( u < 0.0 || 1.0 < u )
 
 1016      intersectPoint = origin + direction * t;
 
 
 1025  if ( radius1 > radius2 )
 
 1032  QVector<QgsPointXY> points;
 
 
 1054  std::vector< std::unique_ptr<QgsLineString > > temporarySegmentizedLines;
 
 1055  std::vector< const QgsLineString * > linesToProcess;
 
 1058  if ( 
const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( simplifiedGeom ) )
 
 1060    for ( 
int i = 0; i < multiCurve->partCount(); ++i )
 
 1062      if ( 
const QgsCurve *curvePart = qgsgeometry_cast< const QgsCurve * >( multiCurve->geometryN( i ) ) )
 
 1068        if ( 
const QgsLineString *lineString = qgsgeometry_cast< const QgsLineString * >( part ) )
 
 1070          linesToProcess.emplace_back( lineString );
 
 1074          std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( part->
segmentize() ) );
 
 1075          linesToProcess.emplace_back( segmentizedCurve.get() );
 
 1076          temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
 
 1081  else if ( 
const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( simplifiedGeom ) )
 
 1083    if ( curve->nCoordinates() > 0 )
 
 1085      if ( 
const QgsLineString *lineString = qgsgeometry_cast< const QgsLineString * >( curve ) )
 
 1087        linesToProcess.emplace_back( lineString );
 
 1091        std::unique_ptr< QgsLineString > segmentizedCurve( qgis::down_cast<QgsLineString *>( curve->segmentize() ) );
 
 1092        linesToProcess.emplace_back( segmentizedCurve.get() );
 
 1093        temporarySegmentizedLines.emplace_back( std::move( segmentizedCurve ) );
 
 1098  if ( linesToProcess.empty() )
 
 1101    g.mLastError = QStringLiteral( 
"Input geometry was not a curve type geometry" );
 
 1105  QVector<QgsGeometry> bufferedLines;
 
 1106  bufferedLines.reserve( linesToProcess.size() );
 
 1110    QVector<QgsGeometry> parts;
 
 1112    double prevRadius = 0;
 
 1115    std::unique_ptr< double[] > widths = widthFunction( line ) ;
 
 1120      double thisRadius = widths[ i ] / 2.0;
 
 1121      if ( thisRadius > 0 )
 
 1125        QgsCircle circ( thisPoint, thisRadius );
 
 1127        parts << thisCircle;
 
 1136        if ( prevRadius > 0 || thisRadius > 0 )
 
 1138          QVector< QgsPointXY > points = 
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
 
 1139          if ( !points.empty() )
 
 1144            int beforeVertex = 0;
 
 1145            int afterVertex = 0;
 
 1147            double sqrDistPrev = 0;
 
 1148            for ( 
int j = 0; j < points.count(); ++j )
 
 1152              points[j] = sqrDistPrev < sqrDist ? pA : pB;
 
 1155            points.append( points.at( 0 ) );
 
 1157            auto poly = std::make_unique< QgsPolygon >();
 
 1159            if ( poly->area() > 0 )
 
 1164      prevPoint = thisPoint;
 
 1165      prevRadius = thisRadius;
 
 1166      prevCircle = thisCircle;
 
 
 1181  start = std::fabs( start );
 
 1182  end = std::fabs( end );
 
 1184  auto interpolateWidths = [ start, end ]( 
const QgsLineString * line )->std::unique_ptr< 
double [] >
 
 1188    std::unique_ptr< double [] > widths( 
new double[ line->nCoordinates() ] );
 
 1190    widths[line->nCoordinates() - 1] = end;
 
 1192    double lineLength = line->length();
 
 1193    double currentLength = 0;
 
 1194    QgsPoint prevPoint = line->pointN( 0 );
 
 1195    for ( 
int i = 1; i < line->nCoordinates() - 1; ++i )
 
 1197      QgsPoint point = line->pointN( i );
 
 1198      double segmentLength = point.
distance( prevPoint );
 
 1199      currentLength += segmentLength;
 
 1200      double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
 
 1201      double delta = lengthFraction * ( end - start );
 
 1202      widths[i] = start + delta;
 
 
 1214  auto widthByM = []( 
const QgsLineString * line )->std::unique_ptr< 
double [] >
 
 1216    std::unique_ptr< double [] > widths( 
new double[ line->nCoordinates() ] );
 
 1217    for ( 
int i = 0; i < line->nCoordinates(); ++i )
 
 1219      widths[ i ] = line->mAt( i );
 
 
 1228    const std::function< 
bool( 
const QgsPointXY & ) > &acceptPoint, 
unsigned long seed, 
QgsFeedback *feedback, 
int maxTriesPerPoint, QString &error )
 
 1235  if ( 
const QgsMultiSurface *ms = qgsgeometry_cast< const QgsMultiSurface * >( geometry ) )
 
 1237    for ( 
int i = 0; i < ms->numGeometries(); ++i )
 
 1240        return QVector< QgsPointXY >();
 
 1242      if ( 
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( ms->geometryN( i ) ) )
 
 1248        std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->geometryN( i )->segmentize() ) );
 
 1255    if ( 
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( geometry ) )
 
 1261      std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( geometry->
segmentize() ) );
 
 1267    return QVector< QgsPointXY >();
 
 1269  if ( !t.
error().isEmpty() )
 
 1272    return QVector< QgsPointXY >();
 
 1275  const QVector<float> triangleData = t.
data();
 
 1276  if ( triangleData.empty() )
 
 1277    return QVector< QgsPointXY >(); 
 
 1280  std::vector< double > cumulativeAreas;
 
 1282  double totalArea = 0;
 
 1283  for ( 
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
 
 1286      return QVector< QgsPointXY >();
 
 1288    const float aX = *it++;
 
 1289    const float aY = *it++;
 
 1291    const float bX = *it++;
 
 1292    const float bY = *it++;
 
 1294    const float cX = *it++;
 
 1295    const float cY = *it++;
 
 1300    cumulativeAreas.emplace_back( totalArea );
 
 1303  std::random_device rd;
 
 1304  std::mt19937 mt( seed == 0 ? rd() : seed );
 
 1305  std::uniform_real_distribution<> uniformDist( 0, 1 );
 
 1308  auto selectRandomTriangle = [&cumulativeAreas, totalArea]( 
double random )->
int 
 1311    const double target = random * totalArea;
 
 1312    for ( 
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
 
 1317    Q_ASSERT_X( 
false, 
"QgsInternalGeometryEngine::randomPointsInPolygon", 
"Invalid random triangle index" );
 
 1322  QVector<QgsPointXY> result;
 
 1323  result.reserve( count );
 
 1325  for ( 
int i = 0; i < count; )
 
 1328      return QVector< QgsPointXY >();
 
 1330    const double triangleIndexRnd = uniformDist( mt );
 
 1332    const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
 
 1335    const double weightB = uniformDist( mt );
 
 1336    const double weightC = uniformDist( mt );
 
 1341    const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
 
 1342    const double aY = triangleData.at( triangleIndex * 9 + 1 ) + bounds.
yMinimum();
 
 1343    const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
 
 1344    const double bY = triangleData.at( triangleIndex * 9 + 4 ) + bounds.
yMinimum();
 
 1345    const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
 
 1346    const double cY = triangleData.at( triangleIndex * 9 + 7 ) + bounds.
yMinimum();
 
 1350    if ( acceptPoint( candidate ) )
 
 1356    else if ( maxTriesPerPoint != 0 )
 
 1360      if ( tries == maxTriesPerPoint )
 
 
 1371    const std::function< 
bool( 
const QgsPointXY & ) > &acceptPoint, 
unsigned long seed, 
QgsFeedback *feedback, 
int maxTriesPerPoint, QString &error )
 
 1375  std::unique_ptr<QgsAbstractGeometry> triangulation = 
geos.constrainedDelaunayTriangulation( &error );
 
 1376  if ( !triangulation || triangulation->isEmpty( ) )
 
 1382  const QgsMultiPolygon *mp = qgsgeometry_cast< const QgsMultiPolygon * >( triangulation.get() );
 
 1387  std::vector< double > cumulativeAreas;
 
 1389  double totalArea = 0;
 
 1390  std::vector< double > vertices( 
static_cast< std::size_t 
>( mp->
numGeometries() ) * 6 );
 
 1391  double *vertexData = vertices.data();
 
 1397    const QgsPolygon *part = qgsgeometry_cast< const QgsPolygon * >( *it );
 
 1405    const double aX = exterior->
xAt( 0 );
 
 1406    const double aY = exterior->
yAt( 0 );
 
 1407    const double bX = exterior->
xAt( 1 );
 
 1408    const double bY = exterior->
yAt( 1 );
 
 1409    const double cX = exterior->
xAt( 2 );
 
 1410    const double cY = exterior->
yAt( 2 );
 
 1420    cumulativeAreas.emplace_back( totalArea );
 
 1423  std::random_device rd;
 
 1424  std::mt19937 mt( seed == 0 ? rd() : seed );
 
 1425  std::uniform_real_distribution<> uniformDist( 0, 1 );
 
 1428  auto selectRandomTriangle = [&cumulativeAreas, totalArea]( 
double random )->
int 
 1431    const double target = random * totalArea;
 
 1432    for ( 
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
 
 1437    Q_ASSERT_X( 
false, 
"QgsInternalGeometryEngine::randomPointsInPolygon", 
"Invalid random triangle index" );
 
 1442  QVector<QgsPointXY> result;
 
 1443  result.reserve( count );
 
 1445  vertexData = vertices.data();
 
 1446  for ( 
int i = 0; i < count; )
 
 1449      return QVector< QgsPointXY >();
 
 1451    const double triangleIndexRnd = uniformDist( mt );
 
 1453    const std::size_t triangleIndex = selectRandomTriangle( triangleIndexRnd );
 
 1456    const double weightB = uniformDist( mt );
 
 1457    const double weightC = uniformDist( mt );
 
 1462    const double aX = vertexData[ triangleIndex * 6 ];
 
 1463    const double aY = vertexData[ triangleIndex * 6 + 1 ];
 
 1464    const double bX = vertexData[ triangleIndex * 6 + 2 ];
 
 1465    const double bY = vertexData[ triangleIndex * 6 + 3 ];
 
 1466    const double cX = vertexData[ triangleIndex * 6 + 4 ];
 
 1467    const double cY = vertexData[ triangleIndex * 6 + 5 ];
 
 1472    if ( acceptPoint( candidate ) )
 
 1478    else if ( maxTriesPerPoint != 0 )
 
 1482      if ( tries == maxTriesPerPoint )
 
 
 1493    const std::function< 
bool( 
const QgsPointXY & ) > &acceptPoint, 
unsigned long seed, 
QgsFeedback *feedback, 
int maxTriesPerPoint )
 
 1496    return QVector< QgsPointXY >();
 
 1499#if (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=11) || GEOS_VERSION_MAJOR>3 
 
 1509    double pointSpacingAngleTolerance )
 
 1515    std::unique_ptr< QgsCircularString > out;
 
 1516    out.reset( qgsgeometry_cast< const QgsCircularString * >( curve )->clone() );
 
 1521    auto out = std::make_unique< QgsCompoundCurve >();
 
 1522    const QgsCompoundCurve *in = qgsgeometry_cast< const QgsCompoundCurve * >( curve );
 
 1523    for ( 
int i = 0; i < in->
nCurves(); i ++ )
 
 1525      std::unique_ptr< QgsCurve > processed = 
lineToCurve( in->
curveAt( i ), distanceTolerance, pointSpacingAngleTolerance );
 
 1528        if ( 
const QgsCompoundCurve *processedCompoundCurve = qgsgeometry_cast< const QgsCompoundCurve *>( processed.get() ) )
 
 1530          for ( 
int i = 0; i < processedCompoundCurve->nCurves(); ++i )
 
 1532            out->addCurve( processedCompoundCurve->curveAt( i )->clone() );
 
 1537          out->addCurve( processed.release() );
 
 1545    const QgsLineString *lineString = qgsgeometry_cast< const QgsLineString * >( curve );
 
 1547    auto out = std::make_unique< QgsCompoundCurve >();
 
 1550    const unsigned int minQuadEdges = 2;
 
 1563      out->addCurve( lineString->
clone() );
 
 1569    QVector< int > edgesInArcs( numEdges + 1, 0 );
 
 1573      double abX = b.x() - a.
x();
 
 1574      double abY = b.y() - a.
y();
 
 1576      double cbX = b.x() - 
c.x();
 
 1577      double cbY = b.y() - 
c.y();
 
 1579      double dot = ( abX * cbX + abY * cbY ); 
 
 1580      double cross = ( abX * cbY - abY * cbX ); 
 
 1582      double alpha = std::atan2( cross, dot );
 
 1597    double centerX = 0.0;
 
 1598    double centerY = 0.0;
 
 1601    while ( i < numEdges - 2 )
 
 1603      unsigned int arcEdges = 0;
 
 1604      double numQuadrants = 0;
 
 1607      bool foundArc = 
false;
 
 1609      a1 = lineString->
pointN( i );
 
 1610      a2 = lineString->
pointN( i + 1 );
 
 1611      a3 = lineString->
pointN( i + 2 );
 
 1614      for ( j = i + 3; j < numEdges + 1; j++ )
 
 1616        b = lineString->
pointN( j );
 
 1623          for ( k = j - 1; k > j - 4; k-- )
 
 1624            edgesInArcs[k] = currentArc;
 
 1644        arcEdges = j - 1 - i;
 
 1645        if ( first.
x() == b.x() && first.
y() == b.y() )
 
 1653          angle = arcAngle( first, 
QgsPoint( centerX, centerY ), b );
 
 1659            angle = 2 * M_PI + angle;
 
 1660          numQuadrants = ( 4 * angle ) / ( 2 * M_PI );
 
 1663        if ( arcEdges < minQuadEdges * numQuadrants )
 
 1666          for ( k = j - 1; k >= i; k-- )
 
 1683    int edgeType = edgesInArcs[0];
 
 1685    auto addPointsToCurve = [ lineString, &out ]( 
int start, 
int end, 
int type )
 
 1690        QVector< QgsPoint > points;
 
 1691        for ( 
int j = start; j < end + 2; ++ j )
 
 1693          points.append( lineString->
pointN( j ) );
 
 1695        std::unique_ptr< QgsCurve > straightSegment = std::make_unique< QgsLineString >( points );
 
 1696        out->addCurve( straightSegment.release() );
 
 1701        QVector< QgsPoint > points;
 
 1702        points.append( lineString->
pointN( start ) );
 
 1703        points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
 
 1704        points.append( lineString->
pointN( end + 1 ) );
 
 1705        auto curvedSegment = std::make_unique< QgsCircularString >();
 
 1706        curvedSegment->setPoints( points );
 
 1707        out->addCurve( curvedSegment.release() );
 
 1711    for ( 
int i = 1; i < numEdges; i++ )
 
 1713      if ( edgeType != edgesInArcs[i] )
 
 1716        addPointsToCurve( start, end, edgeType );
 
 1718        edgeType = edgesInArcs[i];
 
 1724    addPointsToCurve( start, end, edgeType );
 
 1729      std::unique_ptr< QgsCircularString > res;
 
 1730      res.reset( qgsgeometry_cast< const QgsCircularString * >( out->simplifiedTypeRef() )->clone() );
 
 
 1744    return lineToCurve( qgsgeometry_cast< const QgsCurve * >( geom ), distanceTolerance, angleTolerance );
 
 1749    const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( geom );
 
 1750    auto result = std::make_unique< QgsCurvePolygon>();
 
 1753                                          distanceTolerance, angleTolerance ).release() );
 
 1757                                            distanceTolerance, angleTolerance ).release() );
 
 
 1777  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
 1779    int numGeom = gc->numGeometries();
 
 1780    QVector< QgsAbstractGeometry * > geometryList;
 
 1781    geometryList.reserve( numGeom );
 
 1782    for ( 
int i = 0; i < numGeom; ++i )
 
 
 1805  area = std::numeric_limits<double>::max();
 
 1807  width = std::numeric_limits<double>::max();
 
 1808  height = std::numeric_limits<double>::max();
 
 1814  std::unique_ptr< QgsAbstractGeometry > hull( engine->convexHull( &mLastError ) );
 
 1825  double totalRotation = 0;
 
 1826  while ( hull->nextVertex( vertexId, pt2 ) )
 
 1829    double rotateAngle = 180.0 / M_PI * currentAngle;
 
 1830    totalRotation += rotateAngle;
 
 1832    QTransform t = QTransform::fromTranslate( pt0.
x(), pt0.
y() );
 
 1833    t.rotate( rotateAngle );
 
 1834    t.translate( -pt0.
x(), -pt0.
y() );
 
 1836    hull->transform( t );
 
 1839    double currentArea = bounds.
width() * bounds.
height();
 
 1840    if ( currentArea  < area )
 
 1844      angle = totalRotation;
 
 1845      width = bounds.
width();
 
 1846      height = bounds.
height();
 
 1855  if ( width > height )
 
 1857    width = minRect.
height();
 
 1858    height = minRect.
width();
 
 1859    angle = angle + 90.0;
 
 1863  if ( angle > 180.0 )
 
 1864    angle = std::fmod( angle, 180.0 );
 
 
 1871  const int totalPoints = line->
numPoints();
 
 1872  if ( totalPoints < 2 )
 
 1875  const double *x = line->
xData();
 
 1876  const double *y = line->
yData();
 
 1878  double prevX = *x++;
 
 1879  double prevY = *y++;
 
 1881  QVector< double > outX;
 
 1882  QVector< double > outY;
 
 1883  const double totalLength = line->
length();
 
 1885  const int maxRepetitions = std::ceil( totalLength / wavelength );
 
 1886  if ( !strictWavelength )
 
 1887    wavelength = totalLength / maxRepetitions;
 
 1889  const int estimatedPoints = maxRepetitions * 2 + 2;
 
 1890  outX.reserve( estimatedPoints );
 
 1891  outY.reserve( estimatedPoints );
 
 1892  outX.append( prevX );
 
 1893  outY.append( prevY );
 
 1895  double distanceToNextPointFromStartOfSegment = wavelength / 4;
 
 1897  for ( 
int i = 1; i < totalPoints; ++i )
 
 1899    double thisX = *x++;
 
 1900    double thisY = *y++;
 
 1904    while ( distanceToNextPointFromStartOfSegment < segmentLength || 
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
 
 1907      const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
 
 1912      const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
 
 1913      const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
 
 1915      outX.append( outPointX );
 
 1916      outY.append( outPointY );
 
 1918      distanceToNextPointFromStartOfSegment += wavelength / 2;
 
 1924    distanceToNextPointFromStartOfSegment -= segmentLength;
 
 1927  outX.append( prevX );
 
 1928  outY.append( prevY );
 
 1930  return std::make_unique< QgsLineString >( outX, outY );
 
 
 1934    const double minimumWavelength, 
const double maximumWavelength,
 
 1935    const double minimumAmplitude, 
const double maximumAmplitude,
 
 1936    std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
 
 1938  const int totalPoints = line->
numPoints();
 
 1939  if ( totalPoints < 2 )
 
 1942  const double *x = line->
xData();
 
 1943  const double *y = line->
yData();
 
 1945  double prevX = *x++;
 
 1946  double prevY = *y++;
 
 1948  QVector< double > outX;
 
 1949  QVector< double > outY;
 
 1950  const double totalLength = line->
length();
 
 1952  const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
 
 1954  const int estimatedPoints = maxRepetitions * 2 + 2;
 
 1955  outX.reserve( estimatedPoints );
 
 1956  outY.reserve( estimatedPoints );
 
 1957  outX.append( prevX );
 
 1958  outY.append( prevY );
 
 1960  double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
 
 1961  double distanceToNextPointFromStartOfSegment = wavelength / 4;
 
 1962  double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
 
 1965  for ( 
int i = 1; i < totalPoints; ++i )
 
 1967    double thisX = *x++;
 
 1968    double thisY = *y++;
 
 1972    while ( distanceToNextPointFromStartOfSegment < segmentLength || 
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
 
 1975      const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
 
 1980      const double outPointX = pX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
 
 1981      const double outPointY = pY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
 
 1982      outX.append( outPointX );
 
 1983      outY.append( outPointY );
 
 1985      wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
 
 1986      amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
 
 1988      distanceToNextPointFromStartOfSegment += wavelength / 2;
 
 1994    distanceToNextPointFromStartOfSegment -= segmentLength;
 
 1997  outX.append( prevX );
 
 1998  outY.append( prevY );
 
 2000  return std::make_unique< QgsLineString >( outX, outY );
 
 
 2005  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
 2009    geom = segmentizedCopy.get();
 
 2020    auto result = std::make_unique< QgsPolygon >();
 
 2023                             wavelength, amplitude, strictWavelength ).release() );
 
 2027                               wavelength, amplitude, strictWavelength ).release() );
 
 
 2034std::unique_ptr< QgsAbstractGeometry > 
triangularWavesRandomizedPrivate( 
const QgsAbstractGeometry *geom, 
double minimumWavelength, 
double maximumWavelength, 
double minimumAmplitude, 
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
 
 2036  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
 2040    geom = segmentizedCopy.get();
 
 2051    auto result = std::make_unique< QgsPolygon >();
 
 2054                             minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
 
 2058                               minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
 
 
 2081  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
 2083    int numGeom = gc->numGeometries();
 
 2084    QVector< QgsAbstractGeometry * > geometryList;
 
 2085    geometryList.reserve( numGeom );
 
 2086    for ( 
int i = 0; i < numGeom; ++i )
 
 2088      geometryList << 
triangularWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
 
 
 2106  if ( minimumWavelength < 0 || 
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 || 
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
 
 2115  std::random_device rd;
 
 2116  std::mt19937 mt( seed == 0 ? rd() : seed );
 
 2117  std::uniform_real_distribution<> uniformDist( 0, 1 );
 
 2124  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
 2126    int numGeom = gc->numGeometries();
 
 2127    QVector< QgsAbstractGeometry * > geometryList;
 
 2128    geometryList.reserve( numGeom );
 
 2129    for ( 
int i = 0; i < numGeom; ++i )
 
 2131      geometryList << 
triangularWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
 
 
 2149  const int totalPoints = line->
numPoints();
 
 2150  if ( totalPoints < 2 )
 
 2153  const double *x = line->
xData();
 
 2154  const double *y = line->
yData();
 
 2156  double prevX = *x++;
 
 2157  double prevY = *y++;
 
 2159  QVector< double > outX;
 
 2160  QVector< double > outY;
 
 2161  const double totalLength = line->
length();
 
 2163  const int maxRepetitions = std::ceil( totalLength / wavelength );
 
 2164  if ( !strictWavelength )
 
 2165    wavelength = totalLength / maxRepetitions;
 
 2167  const int estimatedPoints = maxRepetitions * 4 + 2;
 
 2168  outX.reserve( estimatedPoints );
 
 2169  outY.reserve( estimatedPoints );
 
 2170  outX.append( prevX );
 
 2171  outY.append( prevY );
 
 2174  outX.append( prevX - amplitude * std::sin( startSegmentAngleRadians + M_PI_2 ) );
 
 2175  outY.append( prevY - amplitude * std::cos( startSegmentAngleRadians + M_PI_2 ) );
 
 2177  double distanceToNextPointFromStartOfSegment = wavelength / 2;
 
 2180  for ( 
int i = 1; i < totalPoints; ++i )
 
 2182    double thisX = *x++;
 
 2183    double thisY = *y++;
 
 2187    while ( distanceToNextPointFromStartOfSegment < segmentLength || 
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
 
 2190      const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
 
 2195      const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
 
 2196      const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
 
 2197      outX.append( pX + side * amplitude * sinAngle );
 
 2198      outY.append( pY + side * amplitude * cosAngle );
 
 2199      outX.append( pX - side * amplitude * sinAngle );
 
 2200      outY.append( pY - side * amplitude * cosAngle );
 
 2202      distanceToNextPointFromStartOfSegment += wavelength / 2;
 
 2208    distanceToNextPointFromStartOfSegment -= segmentLength;
 
 2214  outX.append( prevX );
 
 2215  outY.append( prevY );
 
 2217  return std::make_unique< QgsLineString >( outX, outY );
 
 
 2221    const double minimumWavelength, 
const double maximumWavelength,
 
 2222    const double minimumAmplitude, 
const double maximumAmplitude,
 
 2223    std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
 
 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  QVector< double > outX;
 
 2236  QVector< double > outY;
 
 2237  const double totalLength = line->
length();
 
 2239  const int maxRepetitions = std::ceil( totalLength / minimumWavelength );
 
 2241  const int estimatedPoints = maxRepetitions * 4 + 2;
 
 2242  outX.reserve( estimatedPoints );
 
 2243  outY.reserve( estimatedPoints );
 
 2244  outX.append( prevX );
 
 2245  outY.append( prevY );
 
 2247  double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
 
 2250  outX.append( prevX - amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
 
 2251  outY.append( prevY - amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
 
 2253  double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
 
 2254  double distanceToNextPointFromStartOfSegment = wavelength / 2;
 
 2257  for ( 
int i = 1; i < totalPoints; ++i )
 
 2259    double thisX = *x++;
 
 2260    double thisY = *y++;
 
 2264    while ( distanceToNextPointFromStartOfSegment < segmentLength || 
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
 
 2267      const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
 
 2272      const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
 
 2273      const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
 
 2274      outX.append( pX + side * amplitude * sinAngle );
 
 2275      outY.append( pY + side * amplitude * cosAngle );
 
 2277      amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
 
 2278      outX.append( pX - side * amplitude * sinAngle );
 
 2279      outY.append( pY - side * amplitude * cosAngle );
 
 2281      wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
 
 2282      distanceToNextPointFromStartOfSegment += wavelength / 2;
 
 2288    distanceToNextPointFromStartOfSegment -= segmentLength;
 
 2291  outX.append( prevX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 ) );
 
 2292  outY.append( prevY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 ) );
 
 2293  outX.append( prevX );
 
 2294  outY.append( prevY );
 
 2296  return std::make_unique< QgsLineString >( outX, outY );
 
 
 2301  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
 2305    geom = segmentizedCopy.get();
 
 2316    auto result = std::make_unique< QgsPolygon >();
 
 2319                             wavelength, amplitude, strictWavelength ).release() );
 
 2323                               wavelength, amplitude, strictWavelength ).release() );
 
 
 2330std::unique_ptr< QgsAbstractGeometry > 
squareWavesRandomizedPrivate( 
const QgsAbstractGeometry *geom, 
double minimumWavelength, 
double maximumWavelength, 
double minimumAmplitude, 
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
 
 2332  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
 2336    geom = segmentizedCopy.get();
 
 2347    auto result = std::make_unique< QgsPolygon >();
 
 2350                             minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
 
 2354                               minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
 
 
 2377  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
 2379    int numGeom = gc->numGeometries();
 
 2380    QVector< QgsAbstractGeometry * > geometryList;
 
 2381    geometryList.reserve( numGeom );
 
 2382    for ( 
int i = 0; i < numGeom; ++i )
 
 2384      geometryList << 
squareWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
 
 
 2402  if ( minimumWavelength < 0 || 
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 || 
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
 
 2411  std::random_device rd;
 
 2412  std::mt19937 mt( seed == 0 ? rd() : seed );
 
 2413  std::uniform_real_distribution<> uniformDist( 0, 1 );
 
 2420  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
 2422    int numGeom = gc->numGeometries();
 
 2423    QVector< QgsAbstractGeometry * > geometryList;
 
 2424    geometryList.reserve( numGeom );
 
 2425    for ( 
int i = 0; i < numGeom; ++i )
 
 2427      geometryList << 
squareWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
 
 
 2445  const int totalPoints = line->
numPoints();
 
 2446  if ( totalPoints < 2 )
 
 2449  const double *x = line->
xData();
 
 2450  const double *y = line->
yData();
 
 2452  double prevX = *x++;
 
 2453  double prevY = *y++;
 
 2455  const double totalLength = line->
length();
 
 2457  const int maxRepetitions = std::ceil( totalLength / wavelength );
 
 2458  if ( !strictWavelength )
 
 2459    wavelength = totalLength / maxRepetitions;
 
 2461  const int segments = 10;
 
 2465  double xOutBuffer[4] { prevX, prevX, prevX, prevX };
 
 2466  double yOutBuffer[4] { prevY, prevY, prevY, prevY };
 
 2467  bool isFirstPart = 
true;
 
 2469  double distanceToNextPointFromStartOfSegment = wavelength / 8;
 
 2470  int bufferIndex = 1;
 
 2471  auto out = std::make_unique< QgsLineString >();
 
 2473  double segmentAngleRadians = 0;
 
 2474  double remainingDistance = totalLength;
 
 2475  double totalCoveredDistance = 0;
 
 2477  for ( 
int i = 1; i < totalPoints; ++i )
 
 2479    double thisX = *x++;
 
 2480    double thisY = *y++;
 
 2484    while ( distanceToNextPointFromStartOfSegment < segmentLength || 
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
 
 2487      const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
 
 2490      remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
 
 2492      const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
 
 2493      const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
 
 2495      if ( bufferIndex == 0 )
 
 2497        xOutBuffer[0] = pX + side * amplitude * sinAngle;
 
 2498        yOutBuffer[0] = pY + side * amplitude * cosAngle;
 
 2500        distanceToNextPointFromStartOfSegment += wavelength / 4;
 
 2502      else if ( bufferIndex == 1 && isFirstPart )
 
 2504        xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
 
 2505        yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
 
 2506        xOutBuffer[2] = pX - side * amplitude * sinAngle;
 
 2507        yOutBuffer[2] = pY - side * amplitude * cosAngle;
 
 2509        distanceToNextPointFromStartOfSegment += wavelength / 8;
 
 2511      else if ( bufferIndex == 1 )
 
 2513        xOutBuffer[1] = pX + side * amplitude * sinAngle;
 
 2514        yOutBuffer[1] = pY + side * amplitude * cosAngle;
 
 2515        xOutBuffer[2] = pX - side * amplitude * sinAngle;
 
 2516        yOutBuffer[2] = pY - side * amplitude * cosAngle;
 
 2518        distanceToNextPointFromStartOfSegment += wavelength / 4;
 
 2520      else if ( bufferIndex == 2 )
 
 2522        xOutBuffer[3] = pX - side * amplitude * sinAngle;
 
 2523        yOutBuffer[3] = pY - side * amplitude * cosAngle;
 
 2527          xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
 
 2528          yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
 
 2529          isFirstPart = 
false;
 
 2534            QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
 
 2535            QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
 
 2536            QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
 
 2538        out->append( bezier.get() );
 
 2541        xOutBuffer[0] = xOutBuffer[3];
 
 2542        yOutBuffer[0] = yOutBuffer[3];
 
 2545        distanceToNextPointFromStartOfSegment += wavelength / 4;
 
 2548    totalCoveredDistance += segmentLength;
 
 2551    distanceToNextPointFromStartOfSegment -= segmentLength;
 
 2554  const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
 
 2555  const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
 
 2556  const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
 
 2557  const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
 
 2560      QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
 
 2561      QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
 
 2564  out->append( bezier.get() );
 
 
 2570    const double minimumWavelength, 
const double maximumWavelength,
 
 2571    const double minimumAmplitude, 
const double maximumAmplitude,
 
 2572    std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
 
 2574  const int totalPoints = line->
numPoints();
 
 2575  if ( totalPoints < 2 )
 
 2578  const double *x = line->
xData();
 
 2579  const double *y = line->
yData();
 
 2581  double prevX = *x++;
 
 2582  double prevY = *y++;
 
 2584  const double totalLength = line->
length();
 
 2586  const int segments = 10;
 
 2590  double xOutBuffer[4] { prevX, prevX, prevX, prevX };
 
 2591  double yOutBuffer[4] { prevY, prevY, prevY, prevY };
 
 2592  bool isFirstPart = 
true;
 
 2594  double amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
 
 2595  double wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
 
 2597  double distanceToNextPointFromStartOfSegment = wavelength / 8;
 
 2598  int bufferIndex = 1;
 
 2599  auto out = std::make_unique< QgsLineString >();
 
 2601  double segmentAngleRadians = 0;
 
 2603  double remainingDistance = totalLength;
 
 2604  double totalCoveredDistance = 0;
 
 2606  for ( 
int i = 1; i < totalPoints; ++i )
 
 2608    double thisX = *x++;
 
 2609    double thisY = *y++;
 
 2613    while ( distanceToNextPointFromStartOfSegment < segmentLength || 
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
 
 2616      const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
 
 2619      remainingDistance = totalLength - totalCoveredDistance - distanceToPoint;
 
 2621      const double sinAngle = std::sin( segmentAngleRadians + M_PI_2 );
 
 2622      const double cosAngle = std::cos( segmentAngleRadians + M_PI_2 );
 
 2624      if ( bufferIndex == 0 )
 
 2626        xOutBuffer[0] = pX + side * amplitude * sinAngle;
 
 2627        yOutBuffer[0] = pY + side * amplitude * cosAngle;
 
 2629        distanceToNextPointFromStartOfSegment += wavelength / 4;
 
 2631      else if ( bufferIndex == 1 && isFirstPart )
 
 2633        xOutBuffer[1] = ( xOutBuffer[0] + pX - side * amplitude * sinAngle ) * 0.5;
 
 2634        yOutBuffer[1] = ( yOutBuffer[0] + pY - side * amplitude * cosAngle ) * 0.5;
 
 2635        xOutBuffer[2] = pX - side * amplitude * sinAngle;
 
 2636        yOutBuffer[2] = pY - side * amplitude * cosAngle;
 
 2638        distanceToNextPointFromStartOfSegment += wavelength / 8;
 
 2640      else if ( bufferIndex == 1 )
 
 2642        xOutBuffer[1] = pX + side * amplitude * sinAngle;
 
 2643        yOutBuffer[1] = pY + side * amplitude * cosAngle;
 
 2644        amplitude = uniformDist( mt ) * ( maximumAmplitude - minimumAmplitude ) + minimumAmplitude;
 
 2645        xOutBuffer[2] = pX - side * amplitude * sinAngle;
 
 2647        yOutBuffer[2] = pY - side * amplitude * cosAngle;
 
 2648        distanceToNextPointFromStartOfSegment += wavelength / 4;
 
 2650      else if ( bufferIndex == 2 )
 
 2652        xOutBuffer[3] = pX - side * amplitude * sinAngle;
 
 2653        yOutBuffer[3] = pY - side * amplitude * cosAngle;
 
 2657          xOutBuffer[2] = ( xOutBuffer[2] + xOutBuffer[3] ) * 0.5;
 
 2658          yOutBuffer[2] = ( yOutBuffer[2] + yOutBuffer[3] ) * 0.5;
 
 2659          isFirstPart = 
false;
 
 2664            QgsPoint( xOutBuffer[1], yOutBuffer[1] ),
 
 2665            QgsPoint( xOutBuffer[2], yOutBuffer[2] ),
 
 2666            QgsPoint( xOutBuffer[3], yOutBuffer[3] ),
 
 2668        out->append( bezier.get() );
 
 2671        xOutBuffer[0] = xOutBuffer[3];
 
 2672        yOutBuffer[0] = yOutBuffer[3];
 
 2676        wavelength = uniformDist( mt ) * ( maximumWavelength - minimumWavelength ) + minimumWavelength;
 
 2678        distanceToNextPointFromStartOfSegment += wavelength / 4;
 
 2681    totalCoveredDistance += segmentLength;
 
 2685    distanceToNextPointFromStartOfSegment -= segmentLength;
 
 2688  const double midX = prevX - remainingDistance / 2 * std::sin( segmentAngleRadians );
 
 2689  const double midY = prevY - remainingDistance / 2 * std::cos( segmentAngleRadians );
 
 2690  const double pX = midX + side * amplitude * std::sin( segmentAngleRadians + M_PI_2 );
 
 2691  const double pY = midY + side * amplitude * std::cos( segmentAngleRadians + M_PI_2 );
 
 2693  if ( out->isEmpty() )
 
 2697        QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
 
 2700    out->append( bezier.get() );
 
 2705        QgsPoint( ( out->endPoint().x() + pX ) * 0.5, ( out->endPoint().y() + pY ) * 0.5 ),
 
 2706        QgsPoint( ( prevX + pX ) * 0.5, ( prevY + pY ) * 0.5 ),
 
 2709    out->append( bezier.get() );
 
 
 2717  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
 2721    geom = segmentizedCopy.get();
 
 2732    auto result = std::make_unique< QgsPolygon >();
 
 2735                             wavelength, amplitude, strictWavelength ).release() );
 
 2739                               wavelength, amplitude, strictWavelength ).release() );
 
 
 2746std::unique_ptr< QgsAbstractGeometry > 
roundWavesRandomizedPrivate( 
const QgsAbstractGeometry *geom, 
double minimumWavelength, 
double maximumWavelength, 
double minimumAmplitude, 
double maximumAmplitude, std::uniform_real_distribution<> &uniformDist, std::mt19937 &mt )
 
 2748  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
 2752    geom = segmentizedCopy.get();
 
 2763    auto result = std::make_unique< QgsPolygon >();
 
 2766                             minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
 
 2770                               minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release() );
 
 
 2793  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
 2795    int numGeom = gc->numGeometries();
 
 2796    QVector< QgsAbstractGeometry * > geometryList;
 
 2797    geometryList.reserve( numGeom );
 
 2798    for ( 
int i = 0; i < numGeom; ++i )
 
 2800      geometryList << 
roundWavesPrivate( gc->geometryN( i ), wavelength, amplitude, strictWavelength ).release();
 
 
 2818  if ( minimumWavelength < 0 || 
qgsDoubleNear( minimumWavelength, 0 ) || maximumWavelength < 0 || 
qgsDoubleNear( maximumWavelength, 0 ) || maximumWavelength < minimumWavelength )
 
 2827  std::random_device rd;
 
 2828  std::mt19937 mt( seed == 0 ? rd() : seed );
 
 2829  std::uniform_real_distribution<> uniformDist( 0, 1 );
 
 2836  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
 2838    int numGeom = gc->numGeometries();
 
 2839    QVector< QgsAbstractGeometry * > geometryList;
 
 2840    geometryList.reserve( numGeom );
 
 2841    for ( 
int i = 0; i < numGeom; ++i )
 
 2843      geometryList << 
roundWavesRandomizedPrivate( gc->geometryN( i ), minimumWavelength, maximumWavelength, minimumAmplitude, maximumAmplitude, uniformDist, mt ).release();
 
 
 2860    const QVector< double> &pattern,
 
 2864    double patternOffset )
 
 2866  const int totalPoints = line->
numPoints();
 
 2867  if ( totalPoints < 2 )
 
 2870  const int patternSize = pattern.size();
 
 2872  const double *x = line->
xData();
 
 2873  const double *y = line->
yData();
 
 2875  double prevX = *x++;
 
 2876  double prevY = *y++;
 
 2878  auto result = std::make_unique< QgsMultiLineString >();
 
 2880  QVector< double > outX;
 
 2881  QVector< double > outY;
 
 2882  const double totalLength = line->
length();
 
 2884  double patternLength = 0;
 
 2885  double patternDashLength = 0;
 
 2886  double patternGapLength = 0;
 
 2887  for ( 
int i = 0; i < pattern.size(); ++i )
 
 2889    patternLength += pattern.at( i );
 
 2891      patternDashLength += pattern.at( i );
 
 2893      patternGapLength += pattern.at( i );
 
 2896  double firstPatternLength = 0;
 
 2897  double firstPatternDashLength = 0;
 
 2898  double firstPatternGapLength = 0;
 
 2899  switch ( startRule )
 
 2903      firstPatternLength = patternLength;
 
 2904      firstPatternDashLength = patternDashLength;
 
 2905      firstPatternGapLength = patternGapLength;
 
 2908      firstPatternLength = patternLength - pattern.at( 0 ) * 0.5; 
 
 2909      firstPatternDashLength = patternDashLength - pattern.at( 0 ) * 0.5;
 
 2910      firstPatternGapLength = patternGapLength;
 
 2913      firstPatternLength = pattern.at( patternSize - 1 ); 
 
 2914      firstPatternDashLength = 0;
 
 2915      firstPatternGapLength = pattern.at( patternSize - 1 );
 
 2918      firstPatternLength = pattern.at( patternSize - 1 ) * 0.5; 
 
 2919      firstPatternDashLength = 0;
 
 2920      firstPatternGapLength = pattern.at( patternSize - 1 ) * 0.5;
 
 2924  const bool isSmallEnoughForSinglePattern = ( totalLength - firstPatternLength ) < patternLength * 0.5;
 
 2926  double lastPatternLength = isSmallEnoughForSinglePattern ? firstPatternLength : patternLength;
 
 2927  double lastPatternDashLength = isSmallEnoughForSinglePattern ? firstPatternDashLength : patternDashLength;
 
 2928  double lastPatternGapLength = isSmallEnoughForSinglePattern ? firstPatternGapLength : patternGapLength;
 
 2932      lastPatternLength = 0;
 
 2933      lastPatternDashLength = 0;
 
 2934      lastPatternGapLength = 0;
 
 2937      lastPatternLength -= pattern.at( patternSize - 1 ); 
 
 2938      lastPatternGapLength -= pattern.at( patternSize - 1 );
 
 2941      lastPatternLength -= pattern.at( patternSize - 1 ) + pattern.at( patternSize - 2 ) * 0.5; 
 
 2942      lastPatternDashLength -= pattern.at( patternSize - 2 ) * 0.5;
 
 2943      lastPatternGapLength -= pattern.at( patternSize - 1 );
 
 2946      lastPatternGapLength = patternGapLength;
 
 2949      lastPatternLength -= pattern.at( patternSize - 1 ) * 0.5; 
 
 2950      lastPatternGapLength -= pattern.at( patternSize - 1 ) * 0.5;
 
 2954  const double remainingLengthForCompletePatterns = totalLength - ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) - lastPatternLength;
 
 2955  const int middlePatternRepetitions = std::max( 
static_cast< int >( std::round( remainingLengthForCompletePatterns / patternLength ) ), 0 );
 
 2957  const double totalUnscaledLengthOfPatterns = ( !isSmallEnoughForSinglePattern ? firstPatternLength : 0 ) + middlePatternRepetitions * patternLength + lastPatternLength;
 
 2958  const double totalUnscaledLengthOfDashes = ( !isSmallEnoughForSinglePattern ? firstPatternDashLength : 0 ) + middlePatternRepetitions * patternDashLength + lastPatternDashLength;
 
 2959  const double totalUnscaledLengthOfGaps = ( !isSmallEnoughForSinglePattern ? firstPatternGapLength : 0 ) + middlePatternRepetitions * patternGapLength + lastPatternGapLength;
 
 2961  double dashLengthScalingFactor = 1;
 
 2962  double gapLengthScalingFactor = 1;
 
 2966    const double lengthToShrinkBy = totalUnscaledLengthOfPatterns - totalLength;
 
 2968    switch ( adjustment )
 
 2971        dashLengthScalingFactor = totalLength / totalUnscaledLengthOfPatterns;
 
 2972        gapLengthScalingFactor = dashLengthScalingFactor;
 
 2975        dashLengthScalingFactor = ( totalUnscaledLengthOfDashes - lengthToShrinkBy ) / totalUnscaledLengthOfDashes;
 
 2978        gapLengthScalingFactor = ( totalUnscaledLengthOfGaps - lengthToShrinkBy ) / totalUnscaledLengthOfGaps;
 
 2983  dashLengthScalingFactor = std::max( dashLengthScalingFactor, 0.0 );
 
 2984  gapLengthScalingFactor = std::max( gapLengthScalingFactor, 0.0 );
 
 2986  const int maxPatterns = middlePatternRepetitions + 2;
 
 2987  result->reserve( maxPatterns );
 
 2989  int patternIndex = 0;
 
 2990  double distanceToNextPointFromStartOfSegment = pattern.at( 0 ) * dashLengthScalingFactor;
 
 2992  switch ( startRule )
 
 2998      distanceToNextPointFromStartOfSegment *= 0.5; 
 
 3001      patternIndex = patternSize - 1; 
 
 3003      distanceToNextPointFromStartOfSegment = pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
 
 3006      patternIndex = patternSize - 1; 
 
 3008      distanceToNextPointFromStartOfSegment = 0.5 * pattern.at( patternSize - 1 ) * gapLengthScalingFactor;
 
 3012  const double adjustedOffset = fmod( patternOffset, patternLength );
 
 3013  const double scaledOffset = ( adjustedOffset < 0 ? ( adjustedOffset + patternLength ) : adjustedOffset ) * ( gapLengthScalingFactor + dashLengthScalingFactor ) / 2;
 
 3017    double remainingOffset = scaledOffset;
 
 3018    while ( remainingOffset > 0 )
 
 3020      if ( distanceToNextPointFromStartOfSegment > remainingOffset )
 
 3022        distanceToNextPointFromStartOfSegment -= remainingOffset;
 
 3026      remainingOffset -= distanceToNextPointFromStartOfSegment;
 
 3029      if ( patternIndex == patternSize )
 
 3032      distanceToNextPointFromStartOfSegment = pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
 
 3038    outX.append( prevX );
 
 3039    outY.append( prevY );
 
 3042  for ( 
int i = 1; i < totalPoints; ++i )
 
 3044    double thisX = *x++;
 
 3045    double thisY = *y++;
 
 3048    while ( distanceToNextPointFromStartOfSegment < segmentLength || 
qgsDoubleNear( distanceToNextPointFromStartOfSegment, segmentLength ) )
 
 3051      const double distanceToPoint = std::min( distanceToNextPointFromStartOfSegment, segmentLength );
 
 3066      if ( patternIndex >= patternSize )
 
 3069      distanceToNextPointFromStartOfSegment += pattern.at( patternIndex ) * ( isDash ? dashLengthScalingFactor : gapLengthScalingFactor );
 
 3074      outX.append( thisX );
 
 3075      outY.append( thisY );
 
 3080    distanceToNextPointFromStartOfSegment -= segmentLength;
 
 3085    outX.append( prevX );
 
 3086    outY.append( prevY );
 
 
 3094    const QVector<double> &pattern,
 
 3098    double patternOffset )
 
 3100  std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
 3104    geom = segmentizedCopy.get();
 
 3115    auto result = std::make_unique< QgsMultiLineString >();
 
 3118    for ( 
int i = 0; i < exteriorParts->numGeometries(); ++i )
 
 3119      result->addGeometry( exteriorParts->geometryN( i )->clone() );
 
 3124      for ( 
int j = 0; j < ringParts->numGeometries(); ++j )
 
 3125        result->addGeometry( ringParts->geometryN( j )->clone() );
 
 
 3134  if ( pattern.size() < 2 )
 
 3138  if ( !mGeometry || mGeometry->
isEmpty() )
 
 3148  if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
 3150    int numGeom = gc->numGeometries();
 
 3151    QVector< QgsAbstractGeometry * > geometryList;
 
 3152    geometryList.reserve( numGeom );
 
 3153    for ( 
int i = 0; i < numGeom; ++i )
 
 3155      geometryList << 
applyDashPatternPrivate( gc->geometryN( i ), pattern, startRule, endRule, adjustment, patternOffset ).release();
 
 3163        for ( 
int j = 0; j < collection->numGeometries(); ++j )
 
 3165          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.
 
virtual bool isEmpty() const
Returns true if the geometry is empty.
 
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
 
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
 
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
 
Compound curve geometry type.
 
int nCurves() const
Returns the number of curves in the geometry.
 
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
 
Curve polygon geometry type.
 
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
 
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
 
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
 
Abstract base class for curved geometry type.
 
virtual int numPoints() const =0
Returns the number of points in the curve.
 
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
 
virtual bool isClosed() const
Returns true if the curve is closed.
 
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
 
virtual QgsPolygon * toPolygon(unsigned int segments=36) const
Returns a segmented polygon.
 
Base class for feedback objects to be used for cancellation of something running in a worker thread.
 
bool isCanceled() const
Tells whether the operation has been canceled already.
 
int partCount() const override
Returns count of parts contained in the geometry.
 
int numGeometries() const
Returns the number of geometries within the collection.
 
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
 
static void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...
 
static double distance2D(double x1, double y1, double x2, double y2)
Returns the 2D distance between (x1, y1) and (x2, y2).
 
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
 
static void weightedPointInTriangle(double aX, double aY, double bX, double bY, double cX, double cY, double weightB, double weightC, double &pointX, double &pointY)
Returns a weighted point inside the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
 
static double triangleArea(double aX, double aY, double bX, double bY, double cX, double cY)
Returns the area of the triangle denoted by the points (aX, aY), (bX, bY) and (cX,...
 
static int leftOfLine(const double x, const double y, const double x1, const double y1, const double x2, const double y2)
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> (x2, y2).
 
static void circleCenterRadius(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double &radius, double ¢erX, double ¢erY)
Returns radius and center of the circle through pt1, pt2, pt3.
 
static bool pointContinuesArc(const QgsPoint &a1, const QgsPoint &a2, const QgsPoint &a3, const QgsPoint &b, double distanceTolerance, double pointSpacingAngleTolerance)
Returns true if point b is on the arc formed by points a1, a2, and a3, but not within that arc portio...
 
static int circleCircleOuterTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2)
Calculates the outer tangent points for two circles, centered at center1 and center2 and with radii o...
 
A geometry is the spatial representation of a feature.
 
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
 
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
 
QgsPointXY closestVertex(const QgsPointXY &point, int &closestVertexIndex, int &previousVertexIndex, int &nextVertexIndex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
 
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false)
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
 
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries, const QgsGeometryParameters ¶meters=QgsGeometryParameters())
Compute the unary union on a list of geometries.
 
Qgis::GeometryOperationResult addPartV2(const QVector< QgsPointXY > &points, Qgis::WkbType wkbType=Qgis::WkbType::Unknown)
Adds a new part to a the geometry.
 
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
 
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, 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.
 
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
 
bool isEmpty() const override
Returns true if the geometry is empty.
 
double distance(double x, double y) const
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
 
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
 
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
 
void addInteriorRing(QgsCurve *ring) override
Adds an interior ring to the geometry (takes ownership)
 
bool intersects(const QgsLineSegment2D &segment, QgsPointXY &intersectPoint) const
Finds the closest intersection point of the ray and a line segment.
 
A rectangle specified with double values.
 
Tessellates polygons into triangles.
 
QVector< float > data() const
Returns array of triangle vertex data.
 
void addPolygon(const QgsPolygon &polygon, float extrusionHeight)
Tessellates a triangle and adds its vertex entries to the output data array.
 
QString error() const
Returns a descriptive error string if the tessellation failed.
 
void setOutputZUp(bool zUp)
Sets whether the "up" direction should be the Z axis on output (true), otherwise the "up" direction w...
 
int dataVerticesCount() const
Returns the number of vertices stored in the output data array.
 
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)
 
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.