25 #include <QJsonObject> 
   27 #include <QPainterPath> 
   29 #include <nlohmann/json.hpp> 
   43   const QgsCompoundCurve *otherCurve = qgsgeometry_cast< const QgsCompoundCurve * >( &other );
 
   50   if ( mCurves.size() != otherCurve->mCurves.size() )
 
   53   for ( 
int i = 0; i < mCurves.size(); ++i )
 
   55     if ( *mCurves.at( i ) != *otherCurve->mCurves.at( i ) )
 
   64   auto result = qgis::make_unique< QgsCompoundCurve >();
 
   66   return result.release();
 
   71   return QStringLiteral( 
"CompoundCurve" );
 
   82   mCurves.reserve( curve.mCurves.size() );
 
   85     mCurves.append( 
c->clone() );
 
   97       mCurves.append( 
c->clone() );
 
  111   qDeleteAll( mCurves );
 
  118   if ( mCurves.empty() )
 
  124   for ( 
int i = 1; i < mCurves.size(); ++i )
 
  150   for ( 
int i = 0; i < 
nCurves; ++i )
 
  153     wkbPtr -= 1 + 
sizeof( int );
 
  166     currentCurve->
fromWkb( wkbPtr );  
 
  167     mCurves.append( currentCurve );
 
  182   QString secondWithoutParentheses = 
parts.second;
 
  183   secondWithoutParentheses = secondWithoutParentheses.remove( 
'(' ).remove( 
')' ).simplified().remove( 
' ' );
 
  184   if ( ( 
parts.second.compare( QLatin1String( 
"EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
 
  185        secondWithoutParentheses.isEmpty() )
 
  188   QString defaultChildWkbType = QStringLiteral( 
"LineString%1%2" ).arg( 
is3D() ? QStringLiteral( 
"Z" ) : QString(), 
isMeasure() ? QStringLiteral( 
"M" ) : QString() );
 
  191   for ( 
const QString &childWkt : blocks )
 
  204     if ( !mCurves.back()->fromWkt( childWkt ) )
 
  215   for ( 
const QgsCurve *curve : qgis::as_const( mCurves ) )
 
  217     hasZ = hasZ || curve->is3D();
 
  218     hasM = hasM || curve->isMeasure();
 
  232   int binarySize = 
sizeof( char ) + 
sizeof( quint32 ) + 
sizeof( quint32 );
 
  233   for ( 
const QgsCurve *curve : mCurves )
 
  235     binarySize += curve->wkbSize( flags );
 
  246   wkb << static_cast<quint32>( 
wkbType() );
 
  247   wkb << static_cast<quint32>( mCurves.size() );
 
  248   for ( 
const QgsCurve *curve : mCurves )
 
  250     wkb << curve->asWkb( flags );
 
  259     wkt += QLatin1String( 
" EMPTY" );
 
  262     wkt += QLatin1String( 
" (" );
 
  263     for ( 
const QgsCurve *curve : mCurves )
 
  265       QString childWkt = curve->asWkt( 
precision );
 
  266       if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
 
  269         childWkt = childWkt.mid( childWkt.indexOf( 
'(' ) );
 
  271       wkt += childWkt + 
',';
 
  273     if ( wkt.endsWith( 
',' ) )
 
  285   std::unique_ptr< QgsLineString > line( 
curveToLine() );
 
  286   QDomElement gml = line->asGml2( doc, 
precision, ns, axisOrder );
 
  292   QDomElement compoundCurveElem = doc.createElementNS( ns, QStringLiteral( 
"CompositeCurve" ) );
 
  295     return compoundCurveElem;
 
  297   for ( 
const QgsCurve *curve : mCurves )
 
  299     QDomElement curveMemberElem = doc.createElementNS( ns, QStringLiteral( 
"curveMember" ) );
 
  300     QDomElement curveElem = curve->asGml3( doc, 
precision, ns, axisOrder );
 
  301     curveMemberElem.appendChild( curveElem );
 
  302     compoundCurveElem.appendChild( curveMemberElem );
 
  305   return compoundCurveElem;
 
  311   std::unique_ptr< QgsLineString > line( 
curveToLine() );
 
  318   for ( 
const QgsCurve *curve : mCurves )
 
  320     length += curve->length();
 
  327   if ( mCurves.empty() )
 
  331   return mCurves.at( 0 )->startPoint();
 
  336   if ( mCurves.empty() )
 
  340   return mCurves.at( mCurves.size() - 1 )->endPoint();
 
  346   if ( mCurves.empty() )
 
  351   mCurves[0]->points( pts );
 
  352   for ( 
int i = 1; i < mCurves.size(); ++i )
 
  355     mCurves[i]->points( pList );
 
  370   for ( 
int i = 0; i < 
nCurves; ++i )
 
  372     nPoints += mCurves.at( i )->numPoints() - 1; 
 
  380   if ( mCurves.isEmpty() )
 
  385     if ( !curve->isEmpty() )
 
  394   std::unique_ptr< QgsLineString > currentLine;
 
  395   for ( 
const QgsCurve *curve : mCurves )
 
  397     currentLine.reset( curve->curveToLine( tolerance, toleranceType ) );
 
  398     line->
append( currentLine.get() );
 
  409     std::unique_ptr<QgsCurve> gridified( 
static_cast< QgsCurve * 
>( curve->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) );
 
  412       result->mCurves.append( gridified.release() );
 
  416   if ( result->mCurves.empty() )
 
  419     return result.release();
 
  425   const QVector< QgsCurve * > curves = mCurves;
 
  431     if ( curve->numPoints() == 0 || 
qgsDoubleNear( curve->length(), 0.0, epsilon ) )
 
  434       delete mCurves.takeAt( i );
 
  442         curve->moveVertex( 
QgsVertexId( -1, -1, 0 ), lastEnd );
 
  453   if ( i < 0 || i >= mCurves.size() )
 
  457   return mCurves.at( i );
 
  464     if ( mCurves.empty() )
 
  493   if ( i < 0 || i >= mCurves.size() )
 
  498   delete mCurves.takeAt( i );
 
  511   if ( !mCurves.isEmpty() )
 
  513     lastCurve = mCurves.at( mCurves.size() - 1 );
 
  520     mCurves.append( line );
 
  537   for ( 
const QgsCurve *curve : mCurves )
 
  545   for ( 
QgsCurve *curve : qgis::as_const( mCurves ) )
 
  547     curve->transform( ct, d, transformZ );
 
  554   for ( 
QgsCurve *curve : qgis::as_const( mCurves ) )
 
  556     curve->transform( t, zTranslate, zScale, mTranslate, mScale );
 
  564   for ( 
const QgsCurve *curve : mCurves )
 
  566     curve->addToPainterPath( pp );
 
  574   for ( 
const QgsCurve *curve : mCurves )
 
  576     curve->addToPainterPath( pp );
 
  583   QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
 
  584   if ( curveIds.empty() )
 
  588   int curveId = curveIds.at( 0 ).first;
 
  589   if ( curveId >= mCurves.size() )
 
  594   bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
 
  604   QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
 
  605   QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
 
  606   for ( ; idIt != curveIds.constEnd(); ++idIt )
 
  608     mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
 
  611   bool success = !curveIds.isEmpty();
 
  621   QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
 
  622   if ( curveIds.size() == 1 )
 
  624     if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
 
  629     if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 )
 
  634   else if ( curveIds.size() == 2 )
 
  636     Q_ASSERT( curveIds.at( 1 ).first == curveIds.at( 0 ).first + 1 );
 
  637     Q_ASSERT( curveIds.at( 0 ).second.vertex == mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 );
 
  638     Q_ASSERT( curveIds.at( 1 ).second.vertex == 0 );
 
  643          mCurves.at( curveIds.at( 1 ).first )->numPoints() > 3 )
 
  647       mCurves.at( curveIds.at( 1 ).first ) ->pointAt( 2, intermediatePoint, type );
 
  648       mCurves.at( curveIds.at( 0 ).first )->moveVertex(
 
  649         QgsVertexId( 0, 0, mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 ), intermediatePoint );
 
  651     else if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
 
  657          mCurves.at( curveIds.at( 0 ).first )->numPoints() > 0 &&
 
  660       QgsPoint intermediatePoint = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
 
  661       mCurves.at( curveIds.at( 1 ).first )->moveVertex( 
QgsVertexId( 0, 0, 0 ), intermediatePoint );
 
  663     else if ( !mCurves.at( curveIds.at( 1 ).first )->deleteVertex( curveIds.at( 1 ).second ) )
 
  668     if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
 
  669          mCurves.at( curveIds.at( 1 ).first )->numPoints() != 0 )
 
  674     else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() != 0 &&
 
  675               mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
 
  677       mCurves.at( curveIds.at( 0 ).first )->moveVertex(
 
  681     else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
 
  682               mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
 
  689       mCurves.insert( curveIds.at( 0 ).first, line );
 
  693       QgsPoint endPointOfFirst = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
 
  694       QgsPoint startPointOfSecond = mCurves.at( curveIds.at( 1 ).first ) ->startPoint();
 
  695       if ( endPointOfFirst != startPointOfSecond )
 
  700         mCurves.insert( curveIds.at( 1 ).first, line );
 
  705   bool success = !curveIds.isEmpty();
 
  713 QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId( 
QgsVertexId id )
 const 
  715   QVector< QPair<int, QgsVertexId> > curveIds;
 
  717   int currentVertexIndex = 0;
 
  718   for ( 
int i = 0; i < mCurves.size(); ++i )
 
  720     int increment = mCurves.at( i )->numPoints() - 1;
 
  721     if ( 
id.vertex >= currentVertexIndex && 
id.vertex <= currentVertexIndex + increment )
 
  723       int curveVertexId = 
id.vertex - currentVertexIndex;
 
  727       vid.
vertex = curveVertexId;
 
  728       curveIds.append( qMakePair( i, vid ) );
 
  729       if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) ) 
 
  732         curveIds.append( qMakePair( i + 1, vid ) );
 
  736     else if ( 
id.vertex >= currentVertexIndex && 
id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
 
  738       int curveVertexId = 
id.vertex - currentVertexIndex;
 
  742       vid.
vertex = curveVertexId;
 
  743       curveIds.append( qMakePair( i, vid ) );
 
  746     currentVertexIndex += increment;
 
  759   int currentVertexId = 0;
 
  760   for ( 
int j = 0; j < mCurves.size(); ++j )
 
  762     int nCurvePoints = mCurves.at( j )->numPoints();
 
  763     if ( ( node - currentVertexId ) < nCurvePoints )
 
  765       return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
 
  767     currentVertexId += ( nCurvePoints - 1 );
 
  774   int currentVertexId = 0;
 
  775   for ( 
int j = 0; j < mCurves.size(); ++j )
 
  777     int nCurvePoints = mCurves.at( j )->numPoints();
 
  778     if ( ( index - currentVertexId ) < nCurvePoints )
 
  780       return mCurves.at( j )->xAt( index - currentVertexId );
 
  782     currentVertexId += ( nCurvePoints - 1 );
 
  789   int currentVertexId = 0;
 
  790   for ( 
int j = 0; j < mCurves.size(); ++j )
 
  792     int nCurvePoints = mCurves.at( j )->numPoints();
 
  793     if ( ( index - currentVertexId ) < nCurvePoints )
 
  795       return mCurves.at( j )->yAt( index - currentVertexId );
 
  797     currentVertexId += ( nCurvePoints - 1 );
 
  804   for ( 
QgsCurve *curve : qgis::as_const( mCurves ) )
 
  806     curve->filterVertices( filter );
 
  813   for ( 
QgsCurve *curve : qgis::as_const( mCurves ) )
 
  822   for ( 
const QgsCurve *curve : mCurves )
 
  824     curve->sumUpArea( sum );
 
  839   for ( 
const QgsCurve *curve : mCurves )
 
  841     if ( curve->hasCurvedSegments() )
 
  851   QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
 
  852   if ( curveIds.size() == 1 )
 
  854     QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
 
  855     return curve->
vertexAngle( curveIds.at( 0 ).second );
 
  857   else if ( curveIds.size() > 1 )
 
  859     QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
 
  860     QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
 
  861     double angle1 = curve1->
vertexAngle( curveIds.at( 0 ).second );
 
  862     double angle2 = curve2->
vertexAngle( curveIds.at( 1 ).second );
 
  873   QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
 
  875   for ( 
auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
 
  877     length += mCurves.at( it->first )->segmentLength( it->second );
 
  885   for ( 
int i = mCurves.count() - 1; i >= 0; --i )
 
  887     QgsCurve *reversedCurve = mCurves.at( i )->reversed();
 
  898   double distanceTraversed = 0;
 
  899   for ( 
const QgsCurve *curve : mCurves )
 
  901     const double thisCurveLength = curve->
length();
 
  902     if ( distanceTraversed + thisCurveLength > distance || 
qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
 
  905       const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
 
  908       return curve->interpolatePoint( distanceToPoint );
 
  911     distanceTraversed += thisCurveLength;
 
  919   if ( startDistance < 0 && endDistance < 0 )
 
  922   endDistance = std::max( startDistance, endDistance );
 
  923   std::unique_ptr< QgsCompoundCurve > substring = qgis::make_unique< QgsCompoundCurve >();
 
  925   double distanceTraversed = 0;
 
  926   for ( 
const QgsCurve *curve : mCurves )
 
  928     const double thisCurveLength = curve->length();
 
  929     if ( distanceTraversed + thisCurveLength < startDistance )
 
  935       std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
 
  937         substring->addCurve( part.release() );
 
  940     distanceTraversed += thisCurveLength;
 
  941     if ( distanceTraversed > endDistance )
 
  945   return substring.release();
 
  955   for ( 
QgsCurve *curve : qgis::as_const( mCurves ) )
 
  957     curve->addZValue( zValue );
 
  970   for ( 
QgsCurve *curve : qgis::as_const( mCurves ) )
 
  972     curve->addMValue( mValue );
 
  984   for ( 
QgsCurve *curve : qgis::as_const( mCurves ) )
 
  998   for ( 
QgsCurve *curve : qgis::as_const( mCurves ) )
 
 1000     curve->dropMValue();
 
 1008   for ( 
QgsCurve *curve : qgis::as_const( mCurves ) )