38   : mGeometry( geometry.constGet() )
 
   51   QVector<QgsLineString *> linesToProcess;
 
   53   const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
 
   56     linesToProcess.reserve( multiCurve->
partCount() );
 
   57     for ( 
int i = 0; i < multiCurve->
partCount(); ++i )
 
   59       linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
 
   63   const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
 
   66     linesToProcess << static_cast<QgsLineString *>( curve->
segmentize() );
 
   69   std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ? 
new QgsMultiPolygon() : 
nullptr );
 
   72   if ( !linesToProcess.empty() )
 
   74     std::unique_ptr< QgsLineString > secondline;
 
   75     for ( 
QgsLineString *line : qgis::as_const( linesToProcess ) )
 
   77       QTransform transform = QTransform::fromTranslate( x, y );
 
   79       secondline.reset( line->reversed() );
 
   80       secondline->transform( transform );
 
   82       line->append( secondline.get() );
 
   83       line->addVertex( line->pointN( 0 ) );
 
   89         multipolygon->addGeometry( polygon );
 
  111     Cell( 
double x, 
double y, 
double h, 
const QgsPolygon *polygon )
 
  115       , d( polygon->pointDistanceToBoundary( x, y ) )
 
  116       , max( d + h * M_SQRT2 )
 
  131 struct GreaterThanByMax
 
  133   bool operator()( 
const Cell *lhs, 
const Cell *rhs )
 
  135     return rhs->max > lhs->max;
 
  139 Cell *getCentroidCell( 
const QgsPolygon *polygon )
 
  147   for ( 
int i = 0, j = len - 1; i < len; j = i++ )
 
  149     double aX = exterior->
xAt( i );
 
  150     double aY = exterior->
yAt( i );
 
  151     double bX = exterior->
xAt( j );
 
  152     double bY = exterior->
yAt( j );
 
  153     double f = aX * bY - bX * aY;
 
  154     x += ( aX + bX ) * f;
 
  155     y += ( aY + bY ) * f;
 
  159     return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
 
  161     return new Cell( x / area, y / area, 0.0, polygon );
 
  166   std::unique_ptr< QgsPolygon > segmentizedPoly;
 
  167   const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( surface );
 
  171     polygon = segmentizedPoly.get();
 
  178   double cellSize = std::min( bounds.
width(), bounds.
height() );
 
  183   double h = cellSize / 2.0;
 
  184   std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
 
  191       cellQueue.push( 
new Cell( x + h, y + h, h, polygon ) );
 
  196   std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
 
  199   std::unique_ptr< Cell > bboxCell( 
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
 
  202   if ( bboxCell->d > bestCell->d )
 
  204     bestCell = std::move( bboxCell );
 
  207   while ( !cellQueue.empty() )
 
  210     std::unique_ptr< Cell > cell( cellQueue.top() );
 
  212     Cell *currentCell = cell.get();
 
  215     if ( currentCell->d > bestCell->d )
 
  217       bestCell = std::move( cell );
 
  221     if ( currentCell->max - bestCell->d <= 
precision )
 
  225     h = currentCell->h / 2.0;
 
  226     cellQueue.push( 
new Cell( currentCell->x - h, currentCell->y - h, h, polygon ) );
 
  227     cellQueue.push( 
new Cell( currentCell->x + h, currentCell->y - h, h, polygon ) );
 
  228     cellQueue.push( 
new Cell( currentCell->x - h, currentCell->y + h, h, polygon ) );
 
  229     cellQueue.push( 
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
 
  232   distanceFromBoundary = bestCell->d;
 
  234   return QgsPoint( bestCell->x, bestCell->y );
 
  241   if ( distanceFromBoundary )
 
  242     *distanceFromBoundary = std::numeric_limits<double>::max();
 
  244   if ( !mGeometry || mGeometry->
isEmpty() )
 
  250   if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
  252     int numGeom = gc->numGeometries();
 
  256     for ( 
int i = 0; i < numGeom; ++i )
 
  258       const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( gc->geometryN( i ) );
 
  263       double dist = std::numeric_limits<double>::max();
 
  265       if ( dist > maxDist )
 
  275     if ( distanceFromBoundary )
 
  276       *distanceFromBoundary = maxDist;
 
  281     const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( mGeometry );
 
  285     double dist = std::numeric_limits<double>::max();
 
  287     if ( distanceFromBoundary )
 
  288       *distanceFromBoundary = dist;
 
  299   return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
 
  325   for ( 
int i = 0; i < numPoints; ++i )
 
  327     if ( !isClosed && i == numPoints - 1 )
 
  329     else if ( !isClosed && i == 0 )
 
  338         a = ring->
pointN( numPoints - 1 );
 
  341       if ( i == numPoints - 1 )
 
  350       sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
 
  360                       double lowerThreshold, 
double upperThreshold )
 
  369   double scale = 2.0 * std::min( p.
length(), q.
length() );
 
  373   double dotProduct = p * q;
 
  382   if ( dotProduct < -M_SQRT1_2 )
 
  387   return new_v.
normalized() * ( 0.1 * dotProduct * scale );
 
  392   double minScore = std::numeric_limits<double>::max();
 
  397   std::unique_ptr< QgsLineString > best( ring->
clone() );
 
  399   QVector< QgsVector >  motions;
 
  400   motions.reserve( numPoints );
 
  402   for ( 
int it = 0; it < iterations; ++it )
 
  410     for ( 
int i = 0; i < numPoints; ++i )
 
  412       if ( isClosed && i == numPoints - 1 )
 
  413         motions << motions.at( 0 ); 
 
  414       else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
 
  424           a = ring->
pointN( numPoints - 1 );
 
  427         if ( i == numPoints - 1 )
 
  432         motions << 
calcMotion( a, b, 
c, lowerThreshold, upperThreshold );
 
  439     for ( 
int i = 0; i < numPoints; ++i )
 
  441       ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
 
  442       ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
 
  445     double newScore = 
squareness( ring, lowerThreshold, upperThreshold );
 
  446     if ( newScore < minScore )
 
  448       best.reset( ring->
clone() );
 
  452     if ( minScore < tolerance )
 
  458   return best.release();
 
  464   std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
  468     geom = segmentizedCopy.get();
 
  474                             maxIterations, tolerance, lowerThreshold, upperThreshold );
 
  483                              maxIterations, tolerance, lowerThreshold, upperThreshold ) );
 
  487                                maxIterations, tolerance, lowerThreshold, upperThreshold ) );
 
  502   double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
 
  503   double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
 
  505   if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
  507     int numGeom = gc->numGeometries();
 
  508     QVector< QgsAbstractGeometry * > geometryList;
 
  509     geometryList.reserve( numGeom );
 
  510     for ( 
int i = 0; i < numGeom; ++i )
 
  512       geometryList << 
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
 
  531   QVector< double > outX;
 
  532   QVector< double > outY;
 
  533   QVector< double > outZ;
 
  534   QVector< double > outM;
 
  535   double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
 
  538   outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
 
  539   outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
 
  540   bool withZ = ring->
is3D();
 
  542     outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
 
  545     outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
 
  558   int extraNodesThisSegment = extraNodesPerSegment;
 
  559   for ( 
int i = 0; i < nPoints - 1; ++i )
 
  562     x2 = ring->
xAt( i + 1 );
 
  564     y2 = ring->
yAt( i + 1 );
 
  568       z2 = ring->
zAt( i + 1 );
 
  573       m2 = ring->
mAt( i + 1 );
 
  583     if ( extraNodesPerSegment < 0 )
 
  586       extraNodesThisSegment = std::floor( std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) / distance );
 
  587       if ( extraNodesThisSegment >= 1 )
 
  588         multiplier = 1.0 / ( extraNodesThisSegment + 1 );
 
  591     for ( 
int j = 0; j < extraNodesThisSegment; ++j )
 
  593       double delta = multiplier * ( j + 1 );
 
  594       xOut = x1 + delta * ( x2 - x1 );
 
  595       yOut = y1 + delta * ( y2 - y1 );
 
  597         zOut = z1 + delta * ( z2 - z1 );
 
  599         mOut = m1 + delta * ( m2 - m1 );
 
  609   outX << ring->
xAt( nPoints - 1 );
 
  610   outY << ring->
yAt( nPoints - 1 );
 
  612     outZ << ring->
zAt( nPoints - 1 );
 
  614     outM << ring->
mAt( nPoints - 1 );
 
  622   std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
 
  626     geom = segmentizedCopy.get();
 
  640                                         extraNodesPerSegment, distance ) );
 
  644                                           extraNodesPerSegment, distance ) );
 
  663   if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
  665     int numGeom = gc->numGeometries();
 
  666     QVector< QgsAbstractGeometry * > geometryList;
 
  667     geometryList.reserve( numGeom );
 
  668     for ( 
int i = 0; i < numGeom; ++i )
 
  670       geometryList << 
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
 
  698   if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
  700     int numGeom = gc->numGeometries();
 
  701     QVector< QgsAbstractGeometry * > geometryList;
 
  702     geometryList.reserve( numGeom );
 
  703     for ( 
int i = 0; i < numGeom; ++i )
 
  730               "line_segment_dist_comparer",
 
  731               "AB must not be collinear with the origin." );
 
  733               "line_segment_dist_comparer",
 
  734               "CD must not be collinear with the origin." );
 
  748     if ( ab.
end() == cd.
end() || oad != oab )
 
  758     if ( cdb == 0 && cda == 0 )
 
  760       return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
 
  762     else if ( cda == cdb || cda == 0 || cdb == 0 )
 
  765       return cdo == cda || cdo == cdb;
 
  781   const bool aIsLeft = a.
x() < mVertex.x();
 
  782   const bool bIsLeft = b.
x() < mVertex.x();
 
  783   if ( aIsLeft != bIsLeft )
 
  788     if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
 
  790       return b.
y() < a.
y();
 
  794       return a.
y() < b.
y();
 
  833       const double distA = ao * direction;
 
  834       const double distB = ( origin - segment.
end() ) * direction;
 
  836       if ( distA > 0 && distB > 0 )
 
  842         if ( ( distA > 0 ) != ( distB > 0 ) )
 
  843           intersectPoint = origin;
 
  844         else if ( distA > distB ) 
 
  845           intersectPoint = segment.
start(); 
 
  847           intersectPoint = segment.
end();
 
  855     if ( u < 0.0 || 1.0 < u )
 
  862       intersectPoint = origin + direction * t;
 
  871   if ( radius1 > radius2 )
 
  878   QVector<QgsPointXY> points;
 
  899   std::vector< std::unique_ptr<QgsLineString > > linesToProcess;
 
  901   const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
 
  904     for ( 
int i = 0; i < multiCurve->
partCount(); ++i )
 
  913   const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
 
  920   if ( linesToProcess.empty() )
 
  923     g.mLastError = QStringLiteral( 
"Input geometry was not a curve type geometry" );
 
  927   QVector<QgsGeometry> bufferedLines;
 
  928   bufferedLines.reserve( linesToProcess.size() );
 
  930   for ( std::unique_ptr< QgsLineString > &line : linesToProcess )
 
  932     QVector<QgsGeometry> parts;
 
  934     double prevRadius = 0;
 
  937     std::unique_ptr< double[] > widths = widthFunction( line.get() ) ;
 
  942       double thisRadius = widths[ i ] / 2.0;
 
  943       if ( thisRadius > 0 )
 
  958         if ( prevRadius > 0 || thisRadius > 0 )
 
  960           QVector< QgsPointXY > points = 
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
 
  961           if ( !points.empty() )
 
  966             int beforeVertex = 0;
 
  969             double sqrDistPrev = 0;
 
  970             for ( 
int j = 0; j < points.count(); ++j )
 
  974               points[j] = sqrDistPrev < sqrDist ? pA : pB;
 
  977             points.append( points.at( 0 ) );
 
  979             std::unique_ptr< QgsPolygon > poly = qgis::make_unique< QgsPolygon >();
 
  981             if ( poly->area() > 0 )
 
  986       prevPoint = thisPoint;
 
  987       prevRadius = thisRadius;
 
  988       prevCircle = thisCircle;
 
  999   start = std::fabs( start );
 
 1000   end = std::fabs( end );
 
 1006     std::unique_ptr< double [] > widths( 
new double[ line->nCoordinates() ] );
 
 1008     widths[line->nCoordinates() - 1] = end;
 
 1010     double lineLength = line->length();
 
 1011     double currentLength = 0;
 
 1012     QgsPoint prevPoint = line->pointN( 0 );
 
 1013     for ( 
int i = 1; i < line->nCoordinates() - 1; ++i )
 
 1015       QgsPoint point = line->pointN( i );
 
 1016       double segmentLength = point.
distance( prevPoint );
 
 1017       currentLength += segmentLength;
 
 1018       double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
 
 1019       double delta = lengthFraction * ( end - start );
 
 1020       widths[i] = start + delta;
 
 1033     std::unique_ptr< double [] > widths( 
new double[ line->nCoordinates() ] );
 
 1034     for ( 
int i = 0; i < line->nCoordinates(); ++i )
 
 1036       widths[ i ] = line->mAt( i );
 
 1045     const std::function< 
bool( 
const QgsPointXY & ) > &acceptPoint, 
unsigned long seed, 
QgsFeedback *feedback )
 
 1048     return QVector< QgsPointXY >();
 
 1060         return QVector< QgsPointXY >();
 
 1068         std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->
geometryN( i )->
segmentize() ) );
 
 1075     if ( 
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( polygon.
constGet() ) )
 
 1081       std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( polygon.
constGet()->
segmentize() ) );
 
 1087     return QVector< QgsPointXY >();
 
 1089   const QVector<float> triangleData = t.
data();
 
 1090   if ( triangleData.empty() )
 
 1091     return QVector< QgsPointXY >(); 
 
 1094   std::vector< double > cumulativeAreas;
 
 1096   double totalArea = 0;
 
 1097   for ( 
auto it = triangleData.constBegin(); it != triangleData.constEnd(); )
 
 1100       return QVector< QgsPointXY >();
 
 1102     const float aX = *it++;
 
 1104     const float aY = -( *it++ );
 
 1105     const float bX = *it++;
 
 1107     const float bY = -( *it++ );
 
 1108     const float cX = *it++;
 
 1110     const float cY = -( *it++ );
 
 1114     cumulativeAreas.emplace_back( totalArea );
 
 1117   std::random_device rd;
 
 1118   std::mt19937 mt( seed == 0 ? rd() : seed );
 
 1119   std::uniform_real_distribution<> uniformDist( 0, 1 );
 
 1122   auto selectRandomTriangle = [&cumulativeAreas, totalArea]( 
double random )->
int 
 1125     const double target = random * totalArea;
 
 1126     for ( 
auto it = cumulativeAreas.begin(); it != cumulativeAreas.end(); ++it, triangle++ )
 
 1131     Q_ASSERT_X( 
false, 
"QgsInternalGeometryEngine::randomPointsInPolygon", 
"Invalid random triangle index" );
 
 1136   QVector<QgsPointXY> result;
 
 1137   result.reserve( count );
 
 1138   for ( 
int i = 0; i < count; )
 
 1141       return QVector< QgsPointXY >();
 
 1143     const double triangleIndexRnd = uniformDist( mt );
 
 1145     const int triangleIndex = selectRandomTriangle( triangleIndexRnd );
 
 1148     const double weightB = uniformDist( mt );
 
 1149     const double weightC = uniformDist( mt );
 
 1154     const double aX = triangleData.at( triangleIndex * 9 ) + bounds.
xMinimum();
 
 1155     const double aY = -triangleData.at( triangleIndex * 9 + 2 ) + bounds.
yMinimum();
 
 1156     const double bX = triangleData.at( triangleIndex * 9 + 3 ) + bounds.
xMinimum();
 
 1157     const double bY = -triangleData.at( triangleIndex * 9 + 5 ) + bounds.
yMinimum();
 
 1158     const double cX = triangleData.at( triangleIndex * 9 + 6 ) + bounds.
xMinimum();
 
 1159     const double cY = -triangleData.at( triangleIndex * 9 + 8 ) + bounds.
yMinimum();
 
 1163     if ( acceptPoint( candidate ) )
 
 1175     double pointSpacingAngleTolerance )
 
 1177   std::unique_ptr< QgsCompoundCurve > out = qgis::make_unique< QgsCompoundCurve >();
 
 1180   const unsigned int minQuadEdges = 2;
 
 1193     out->addCurve( lineString->
clone() );
 
 1199   QVector< int > edgesInArcs( numEdges + 1, 0 );
 
 1203     double abX = b.x() - a.
x();
 
 1204     double abY = b.y() - a.
y();
 
 1206     double cbX = b.x() - 
c.x();
 
 1207     double cbY = b.y() - 
c.y();
 
 1209     double dot = ( abX * cbX + abY * cbY ); 
 
 1210     double cross = ( abX * cbY - abY * cbX ); 
 
 1212     double alpha = std::atan2( cross, dot );
 
 1227   double centerX = 0.0;
 
 1228   double centerY = 0.0;
 
 1231   while ( i < numEdges - 2 )
 
 1233     unsigned int arcEdges = 0;
 
 1234     double numQuadrants = 0;
 
 1237     bool foundArc = 
false;
 
 1239     a1 = lineString->
pointN( i );
 
 1240     a2 = lineString->
pointN( i + 1 );
 
 1241     a3 = lineString->
pointN( i + 2 );
 
 1244     for ( j = i + 3; j < numEdges + 1; j++ )
 
 1246       b = lineString->
pointN( j );
 
 1253         for ( k = j - 1; k > j - 4; k-- )
 
 1254           edgesInArcs[k] = currentArc;
 
 1274       arcEdges = j - 1 - i;
 
 1275       if ( first.
x() == b.
x() && first.
y() == b.
y() )
 
 1290         numQuadrants = ( 4 * 
angle ) / ( 2 * M_PI );
 
 1293       if ( arcEdges < minQuadEdges * numQuadrants )
 
 1296         for ( k = j - 1; k >= i; k-- )
 
 1313   int edgeType = edgesInArcs[0];
 
 1315   auto addPointsToCurve = [ lineString, &out ]( 
int start, 
int end, 
int type )
 
 1320       QVector< QgsPoint > points;
 
 1321       for ( 
int j = start; j < end + 2; ++ j )
 
 1323         points.append( lineString->
pointN( j ) );
 
 1325       std::unique_ptr< QgsCurve > straightSegment = qgis::make_unique< QgsLineString >( points );
 
 1326       out->addCurve( straightSegment.release() );
 
 1331       QVector< QgsPoint > points;
 
 1332       points.append( lineString->
pointN( start ) );
 
 1333       points.append( lineString->
pointN( ( start + end + 1 ) / 2 ) );
 
 1334       points.append( lineString->
pointN( end + 1 ) );
 
 1335       std::unique_ptr< QgsCircularString > curvedSegment = qgis::make_unique< QgsCircularString >();
 
 1336       curvedSegment->setPoints( points );
 
 1337       out->addCurve( curvedSegment.release() );
 
 1341   for ( 
int i = 1; i < numEdges; i++ )
 
 1343     if ( edgeType != edgesInArcs[i] )
 
 1346       addPointsToCurve( start, end, edgeType );
 
 1348       edgeType = edgesInArcs[i];
 
 1354   addPointsToCurve( start, end, edgeType );
 
 1369     std::unique_ptr< QgsCurvePolygon > result = qgis::make_unique< QgsCurvePolygon>();
 
 1372                                           distanceTolerance, angleTolerance ).release() );
 
 1376                                             distanceTolerance, angleTolerance ).release() );
 
 1402   if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
 
 1404     int numGeom = gc->numGeometries();
 
 1405     QVector< QgsAbstractGeometry * > geometryList;
 
 1406     geometryList.reserve( numGeom );
 
 1407     for ( 
int i = 0; i < numGeom; ++i )