QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgscompoundcurve.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscompoundcurve.cpp
3  ----------------------
4  begin : September 2014
5  copyright : (C) 2014 by Marco Hugentobler
6  email : marco at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgscompoundcurve.h"
19 #include "qgsapplication.h"
20 #include "qgscircularstring.h"
21 #include "qgsgeometryutils.h"
22 #include "qgslinestring.h"
23 #include "qgswkbptr.h"
24 
25 #include <QJsonObject>
26 #include <QPainter>
27 #include <QPainterPath>
28 #include <memory>
29 #include <nlohmann/json.hpp>
30 
32 {
34 }
35 
37 {
38  clear();
39 }
40 
41 bool QgsCompoundCurve::equals( const QgsCurve &other ) const
42 {
43  const QgsCompoundCurve *otherCurve = qgsgeometry_cast< const QgsCompoundCurve * >( &other );
44  if ( !otherCurve )
45  return false;
46 
47  if ( mWkbType != otherCurve->mWkbType )
48  return false;
49 
50  if ( mCurves.size() != otherCurve->mCurves.size() )
51  return false;
52 
53  for ( int i = 0; i < mCurves.size(); ++i )
54  {
55  if ( *mCurves.at( i ) != *otherCurve->mCurves.at( i ) )
56  return false;
57  }
58 
59  return true;
60 }
61 
63 {
64  auto result = qgis::make_unique< QgsCompoundCurve >();
65  result->mWkbType = mWkbType;
66  return result.release();
67 }
68 
70 {
71  return QStringLiteral( "CompoundCurve" );
72 }
73 
75 {
76  return 1;
77 }
78 
80 {
81  mWkbType = curve.wkbType();
82  mCurves.reserve( curve.mCurves.size() );
83  for ( const QgsCurve *c : curve.mCurves )
84  {
85  mCurves.append( c->clone() );
86  }
87 }
88 
90 {
91  if ( &curve != this )
92  {
93  clearCache();
94  QgsCurve::operator=( curve );
95  for ( const QgsCurve *c : curve.mCurves )
96  {
97  mCurves.append( c->clone() );
98  }
99  }
100  return *this;
101 }
102 
104 {
105  return new QgsCompoundCurve( *this );
106 }
107 
109 {
111  qDeleteAll( mCurves );
112  mCurves.clear();
113  clearCache();
114 }
115 
117 {
118  if ( mCurves.empty() )
119  {
120  return QgsRectangle();
121  }
122 
123  QgsRectangle bbox = mCurves.at( 0 )->boundingBox();
124  for ( int i = 1; i < mCurves.size(); ++i )
125  {
126  QgsRectangle curveBox = mCurves.at( i )->boundingBox();
127  bbox.combineExtentWith( curveBox );
128  }
129  return bbox;
130 }
131 
133 {
134  clear();
135  if ( !wkbPtr )
136  {
137  return false;
138  }
139 
140  QgsWkbTypes::Type type = wkbPtr.readHeader();
142  {
143  return false;
144  }
145  mWkbType = type;
146 
147  int nCurves;
148  wkbPtr >> nCurves;
149  QgsCurve *currentCurve = nullptr;
150  for ( int i = 0; i < nCurves; ++i )
151  {
152  QgsWkbTypes::Type curveType = wkbPtr.readHeader();
153  wkbPtr -= 1 + sizeof( int );
154  if ( QgsWkbTypes::flatType( curveType ) == QgsWkbTypes::LineString )
155  {
156  currentCurve = new QgsLineString();
157  }
158  else if ( QgsWkbTypes::flatType( curveType ) == QgsWkbTypes::CircularString )
159  {
160  currentCurve = new QgsCircularString();
161  }
162  else
163  {
164  return false;
165  }
166  currentCurve->fromWkb( wkbPtr ); // also updates wkbPtr
167  mCurves.append( currentCurve );
168  }
169  return true;
170 }
171 
172 bool QgsCompoundCurve::fromWkt( const QString &wkt )
173 {
174  clear();
175 
176  QPair<QgsWkbTypes::Type, QString> parts = QgsGeometryUtils::wktReadBlock( wkt );
177 
179  return false;
180  mWkbType = parts.first;
181 
182  if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 )
183  return true;
184 
185  QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() );
186 
187  const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType );
188  for ( const QString &childWkt : blocks )
189  {
190  QPair<QgsWkbTypes::Type, QString> childParts = QgsGeometryUtils::wktReadBlock( childWkt );
191 
192  if ( QgsWkbTypes::flatType( childParts.first ) == QgsWkbTypes::LineString )
193  mCurves.append( new QgsLineString() );
194  else if ( QgsWkbTypes::flatType( childParts.first ) == QgsWkbTypes::CircularString )
195  mCurves.append( new QgsCircularString() );
196  else
197  {
198  clear();
199  return false;
200  }
201  if ( !mCurves.back()->fromWkt( childWkt ) )
202  {
203  clear();
204  return false;
205  }
206  }
207 
208  //scan through curves and check if dimensionality of curves is different to compound curve.
209  //if so, update the type dimensionality of the compound curve to match
210  bool hasZ = false;
211  bool hasM = false;
212  for ( const QgsCurve *curve : qgis::as_const( mCurves ) )
213  {
214  hasZ = hasZ || curve->is3D();
215  hasM = hasM || curve->isMeasure();
216  if ( hasZ && hasM )
217  break;
218  }
219  if ( hasZ )
220  addZValue( 0 );
221  if ( hasM )
222  addMValue( 0 );
223 
224  return true;
225 }
226 
227 QByteArray QgsCompoundCurve::asWkb( WkbFlags flags ) const
228 {
229  int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
230  QVector<QByteArray> wkbForCurves;
231  wkbForCurves.reserve( mCurves.size() );
232  for ( const QgsCurve *curve : mCurves )
233  {
234  QByteArray wkbForCurve = curve->asWkb( flags );
235  binarySize += wkbForCurve.length();
236  wkbForCurves << wkbForCurve;
237  }
238 
239  QByteArray wkbArray;
240  wkbArray.resize( binarySize );
241  QgsWkbPtr wkb( wkbArray );
242  wkb << static_cast<char>( QgsApplication::endian() );
243  wkb << static_cast<quint32>( wkbType() );
244  wkb << static_cast<quint32>( mCurves.size() );
245  for ( const QByteArray &wkbForCurve : qgis::as_const( wkbForCurves ) )
246  {
247  wkb << wkbForCurve;
248  }
249  return wkbArray;
250 }
251 
252 QString QgsCompoundCurve::asWkt( int precision ) const
253 {
254  QString wkt = wktTypeStr();
255  if ( isEmpty() )
256  wkt += QStringLiteral( " EMPTY" );
257  else
258  {
259  wkt += QLatin1String( " (" );
260  for ( const QgsCurve *curve : mCurves )
261  {
262  QString childWkt = curve->asWkt( precision );
263  if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
264  {
265  // Type names of linear geometries are omitted
266  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
267  }
268  wkt += childWkt + ',';
269  }
270  if ( wkt.endsWith( ',' ) )
271  {
272  wkt.chop( 1 );
273  }
274  wkt += ')';
275  }
276  return wkt;
277 }
278 
279 QDomElement QgsCompoundCurve::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
280 {
281  // GML2 does not support curves
282  std::unique_ptr< QgsLineString > line( curveToLine() );
283  QDomElement gml = line->asGml2( doc, precision, ns, axisOrder );
284  return gml;
285 }
286 
287 QDomElement QgsCompoundCurve::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
288 {
289  QDomElement compoundCurveElem = doc.createElementNS( ns, QStringLiteral( "CompositeCurve" ) );
290 
291  if ( isEmpty() )
292  return compoundCurveElem;
293 
294  for ( const QgsCurve *curve : mCurves )
295  {
296  QDomElement curveMemberElem = doc.createElementNS( ns, QStringLiteral( "curveMember" ) );
297  QDomElement curveElem = curve->asGml3( doc, precision, ns, axisOrder );
298  curveMemberElem.appendChild( curveElem );
299  compoundCurveElem.appendChild( curveMemberElem );
300  }
301 
302  return compoundCurveElem;
303 }
304 
306 {
307  // GeoJSON does not support curves
308  std::unique_ptr< QgsLineString > line( curveToLine() );
309  return line->asJsonObject( precision );
310 }
311 
313 {
314  double length = 0;
315  for ( const QgsCurve *curve : mCurves )
316  {
317  length += curve->length();
318  }
319  return length;
320 }
321 
323 {
324  if ( mCurves.empty() )
325  {
326  return QgsPoint();
327  }
328  return mCurves.at( 0 )->startPoint();
329 }
330 
332 {
333  if ( mCurves.empty() )
334  {
335  return QgsPoint();
336  }
337  return mCurves.at( mCurves.size() - 1 )->endPoint();
338 }
339 
341 {
342  pts.clear();
343  if ( mCurves.empty() )
344  {
345  return;
346  }
347 
348  mCurves[0]->points( pts );
349  for ( int i = 1; i < mCurves.size(); ++i )
350  {
351  QgsPointSequence pList;
352  mCurves[i]->points( pList );
353  pList.removeFirst(); //first vertex already added in previous line
354  pts.append( pList );
355  }
356 }
357 
359 {
360  int nPoints = 0;
361  int nCurves = mCurves.size();
362  if ( nCurves < 1 )
363  {
364  return 0;
365  }
366 
367  for ( int i = 0; i < nCurves; ++i )
368  {
369  nPoints += mCurves.at( i )->numPoints() - 1; //last vertex is equal to first of next section
370  }
371  nPoints += 1; //last vertex was removed above
372  return nPoints;
373 }
374 
376 {
377  if ( mCurves.isEmpty() )
378  return true;
379 
380  for ( QgsCurve *curve : mCurves )
381  {
382  if ( !curve->isEmpty() )
383  return false;
384  }
385  return true;
386 }
387 
389 {
390  QgsLineString *line = new QgsLineString();
391  std::unique_ptr< QgsLineString > currentLine;
392  for ( const QgsCurve *curve : mCurves )
393  {
394  currentLine.reset( curve->curveToLine( tolerance, toleranceType ) );
395  line->append( currentLine.get() );
396  }
397  return line;
398 }
399 
400 QgsCompoundCurve *QgsCompoundCurve::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing ) const
401 {
402  std::unique_ptr<QgsCompoundCurve> result( createEmptyWithSameType() );
403 
404  for ( QgsCurve *curve : mCurves )
405  {
406  std::unique_ptr<QgsCurve> gridified( static_cast< QgsCurve * >( curve->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) );
407  if ( gridified )
408  {
409  result->mCurves.append( gridified.release() );
410  }
411  }
412 
413  if ( result->mCurves.empty() )
414  return nullptr;
415  else
416  return result.release();
417 }
418 
419 bool QgsCompoundCurve::removeDuplicateNodes( double epsilon, bool useZValues )
420 {
421  bool result = false;
422  const QVector< QgsCurve * > curves = mCurves;
423  int i = 0;
424  QgsPoint lastEnd;
425  for ( QgsCurve *curve : curves )
426  {
427  result = result || curve->removeDuplicateNodes( epsilon, useZValues );
428  if ( curve->numPoints() == 0 || qgsDoubleNear( curve->length(), 0.0, epsilon ) )
429  {
430  // empty curve, remove it
431  delete mCurves.takeAt( i );
432  result = true;
433  }
434  else
435  {
436  // ensure this line starts exactly where previous line ended
437  if ( i > 0 )
438  {
439  curve->moveVertex( QgsVertexId( -1, -1, 0 ), lastEnd );
440  }
441  lastEnd = curve->vertexAt( QgsVertexId( -1, -1, curve->numPoints() - 1 ) );
442  }
443  i++;
444  }
445  return result;
446 }
447 
448 const QgsCurve *QgsCompoundCurve::curveAt( int i ) const
449 {
450  if ( i < 0 || i >= mCurves.size() )
451  {
452  return nullptr;
453  }
454  return mCurves.at( i );
455 }
456 
458 {
459  if ( c )
460  {
461  if ( mCurves.empty() )
462  {
464  }
465 
466  mCurves.append( c );
467 
468  if ( QgsWkbTypes::hasZ( mWkbType ) && !QgsWkbTypes::hasZ( c->wkbType() ) )
469  {
470  c->addZValue();
471  }
472  else if ( !QgsWkbTypes::hasZ( mWkbType ) && QgsWkbTypes::hasZ( c->wkbType() ) )
473  {
474  c->dropZValue();
475  }
476  if ( QgsWkbTypes::hasM( mWkbType ) && !QgsWkbTypes::hasM( c->wkbType() ) )
477  {
478  c->addMValue();
479  }
480  else if ( !QgsWkbTypes::hasM( mWkbType ) && QgsWkbTypes::hasM( c->wkbType() ) )
481  {
482  c->dropMValue();
483  }
484  clearCache();
485  }
486 }
487 
489 {
490  if ( i < 0 || i >= mCurves.size() )
491  {
492  return;
493  }
494 
495  delete mCurves.takeAt( i );
496  clearCache();
497 }
498 
500 {
501  if ( mCurves.isEmpty() || mWkbType == QgsWkbTypes::Unknown )
502  {
504  }
505 
506  //is last curve QgsLineString
507  QgsCurve *lastCurve = nullptr;
508  if ( !mCurves.isEmpty() )
509  {
510  lastCurve = mCurves.at( mCurves.size() - 1 );
511  }
512 
513  QgsLineString *line = nullptr;
514  if ( !lastCurve || QgsWkbTypes::flatType( lastCurve->wkbType() ) != QgsWkbTypes::LineString )
515  {
516  line = new QgsLineString();
517  mCurves.append( line );
518  if ( lastCurve )
519  {
520  line->addVertex( lastCurve->endPoint() );
521  }
522  lastCurve = line;
523  }
524  else //create new QgsLineString* with point in it
525  {
526  line = static_cast<QgsLineString *>( lastCurve );
527  }
528  line->addVertex( pt );
529  clearCache();
530 }
531 
532 void QgsCompoundCurve::draw( QPainter &p ) const
533 {
534  for ( const QgsCurve *curve : mCurves )
535  {
536  curve->draw( p );
537  }
538 }
539 
541 {
542  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
543  {
544  curve->transform( ct, d, transformZ );
545  }
546  clearCache();
547 }
548 
549 void QgsCompoundCurve::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
550 {
551  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
552  {
553  curve->transform( t, zTranslate, zScale, mTranslate, mScale );
554  }
555  clearCache();
556 }
557 
558 void QgsCompoundCurve::addToPainterPath( QPainterPath &path ) const
559 {
560  QPainterPath pp;
561  for ( const QgsCurve *curve : mCurves )
562  {
563  curve->addToPainterPath( pp );
564  }
565  path.addPath( pp );
566 }
567 
568 void QgsCompoundCurve::drawAsPolygon( QPainter &p ) const
569 {
570  QPainterPath pp;
571  for ( const QgsCurve *curve : mCurves )
572  {
573  curve->addToPainterPath( pp );
574  }
575  p.drawPath( pp );
576 }
577 
578 bool QgsCompoundCurve::insertVertex( QgsVertexId position, const QgsPoint &vertex )
579 {
580  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
581  if ( curveIds.empty() )
582  {
583  return false;
584  }
585  int curveId = curveIds.at( 0 ).first;
586  if ( curveId >= mCurves.size() )
587  {
588  return false;
589  }
590 
591  bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
592  if ( success )
593  {
594  clearCache(); //bbox changed
595  }
596  return success;
597 }
598 
599 bool QgsCompoundCurve::moveVertex( QgsVertexId position, const QgsPoint &newPos )
600 {
601  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
602  QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
603  for ( ; idIt != curveIds.constEnd(); ++idIt )
604  {
605  mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
606  }
607 
608  bool success = !curveIds.isEmpty();
609  if ( success )
610  {
611  clearCache(); //bbox changed
612  }
613  return success;
614 }
615 
617 {
618  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
619  if ( curveIds.size() == 1 )
620  {
621  if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
622  {
623  clearCache(); //bbox may have changed
624  return false;
625  }
626  if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 )
627  {
628  removeCurve( curveIds.at( 0 ).first );
629  }
630  }
631  else if ( curveIds.size() == 2 )
632  {
633  Q_ASSERT( curveIds.at( 1 ).first == curveIds.at( 0 ).first + 1 );
634  Q_ASSERT( curveIds.at( 0 ).second.vertex == mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 );
635  Q_ASSERT( curveIds.at( 1 ).second.vertex == 0 );
636  QgsPoint startPoint = mCurves.at( curveIds.at( 0 ).first ) ->startPoint();
637  QgsPoint endPoint = mCurves.at( curveIds.at( 1 ).first ) ->endPoint();
638  if ( QgsWkbTypes::flatType( mCurves.at( curveIds.at( 0 ).first )->wkbType() ) == QgsWkbTypes::LineString &&
639  QgsWkbTypes::flatType( mCurves.at( curveIds.at( 1 ).first )->wkbType() ) == QgsWkbTypes::CircularString &&
640  mCurves.at( curveIds.at( 1 ).first )->numPoints() > 3 )
641  {
642  QgsPoint intermediatePoint;
644  mCurves.at( curveIds.at( 1 ).first ) ->pointAt( 2, intermediatePoint, type );
645  mCurves.at( curveIds.at( 0 ).first )->moveVertex(
646  QgsVertexId( 0, 0, mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 ), intermediatePoint );
647  }
648  else if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
649  {
650  clearCache(); //bbox may have changed
651  return false;
652  }
653  if ( QgsWkbTypes::flatType( mCurves.at( curveIds.at( 0 ).first )->wkbType() ) == QgsWkbTypes::CircularString &&
654  mCurves.at( curveIds.at( 0 ).first )->numPoints() > 0 &&
655  QgsWkbTypes::flatType( mCurves.at( curveIds.at( 1 ).first )->wkbType() ) == QgsWkbTypes::LineString )
656  {
657  QgsPoint intermediatePoint = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
658  mCurves.at( curveIds.at( 1 ).first )->moveVertex( QgsVertexId( 0, 0, 0 ), intermediatePoint );
659  }
660  else if ( !mCurves.at( curveIds.at( 1 ).first )->deleteVertex( curveIds.at( 1 ).second ) )
661  {
662  clearCache(); //bbox may have changed
663  return false;
664  }
665  if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
666  mCurves.at( curveIds.at( 1 ).first )->numPoints() != 0 )
667  {
668  mCurves.at( curveIds.at( 1 ).first )->moveVertex( QgsVertexId( 0, 0, 0 ), startPoint );
669  removeCurve( curveIds.at( 0 ).first );
670  }
671  else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() != 0 &&
672  mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
673  {
674  mCurves.at( curveIds.at( 0 ).first )->moveVertex(
675  QgsVertexId( 0, 0, mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 ), endPoint );
676  removeCurve( curveIds.at( 1 ).first );
677  }
678  else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
679  mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
680  {
681  removeCurve( curveIds.at( 1 ).first );
682  removeCurve( curveIds.at( 0 ).first );
683  QgsLineString *line = new QgsLineString();
684  line->insertVertex( QgsVertexId( 0, 0, 0 ), startPoint );
685  line->insertVertex( QgsVertexId( 0, 0, 1 ), endPoint );
686  mCurves.insert( curveIds.at( 0 ).first, line );
687  }
688  else
689  {
690  QgsPoint endPointOfFirst = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
691  QgsPoint startPointOfSecond = mCurves.at( curveIds.at( 1 ).first ) ->startPoint();
692  if ( endPointOfFirst != startPointOfSecond )
693  {
694  QgsLineString *line = new QgsLineString();
695  line->insertVertex( QgsVertexId( 0, 0, 0 ), endPointOfFirst );
696  line->insertVertex( QgsVertexId( 0, 0, 1 ), startPointOfSecond );
697  mCurves.insert( curveIds.at( 1 ).first, line );
698  }
699  }
700  }
701 
702  bool success = !curveIds.isEmpty();
703  if ( success )
704  {
705  clearCache(); //bbox changed
706  }
707  return success;
708 }
709 
710 QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId( QgsVertexId id ) const
711 {
712  QVector< QPair<int, QgsVertexId> > curveIds;
713 
714  int currentVertexIndex = 0;
715  for ( int i = 0; i < mCurves.size(); ++i )
716  {
717  int increment = mCurves.at( i )->numPoints() - 1;
718  if ( id.vertex >= currentVertexIndex && id.vertex <= currentVertexIndex + increment )
719  {
720  int curveVertexId = id.vertex - currentVertexIndex;
721  QgsVertexId vid;
722  vid.part = 0;
723  vid.ring = 0;
724  vid.vertex = curveVertexId;
725  curveIds.append( qMakePair( i, vid ) );
726  if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) ) //add first vertex of next curve
727  {
728  vid.vertex = 0;
729  curveIds.append( qMakePair( i + 1, vid ) );
730  }
731  break;
732  }
733  else if ( id.vertex >= currentVertexIndex && id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
734  {
735  int curveVertexId = id.vertex - currentVertexIndex;
736  QgsVertexId vid;
737  vid.part = 0;
738  vid.ring = 0;
739  vid.vertex = curveVertexId;
740  curveIds.append( qMakePair( i, vid ) );
741  break;
742  }
743  currentVertexIndex += increment;
744  }
745 
746  return curveIds;
747 }
748 
749 double QgsCompoundCurve::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
750 {
751  return QgsGeometryUtils::closestSegmentFromComponents( mCurves, QgsGeometryUtils::Vertex, pt, segmentPt, vertexAfter, leftOf, epsilon );
752 }
753 
754 bool QgsCompoundCurve::pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const
755 {
756  int currentVertexId = 0;
757  for ( int j = 0; j < mCurves.size(); ++j )
758  {
759  int nCurvePoints = mCurves.at( j )->numPoints();
760  if ( ( node - currentVertexId ) < nCurvePoints )
761  {
762  return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
763  }
764  currentVertexId += ( nCurvePoints - 1 );
765  }
766  return false;
767 }
768 
769 double QgsCompoundCurve::xAt( int index ) const
770 {
771  int currentVertexId = 0;
772  for ( int j = 0; j < mCurves.size(); ++j )
773  {
774  int nCurvePoints = mCurves.at( j )->numPoints();
775  if ( ( index - currentVertexId ) < nCurvePoints )
776  {
777  return mCurves.at( j )->xAt( index - currentVertexId );
778  }
779  currentVertexId += ( nCurvePoints - 1 );
780  }
781  return 0.0;
782 }
783 
784 double QgsCompoundCurve::yAt( int index ) const
785 {
786  int currentVertexId = 0;
787  for ( int j = 0; j < mCurves.size(); ++j )
788  {
789  int nCurvePoints = mCurves.at( j )->numPoints();
790  if ( ( index - currentVertexId ) < nCurvePoints )
791  {
792  return mCurves.at( j )->yAt( index - currentVertexId );
793  }
794  currentVertexId += ( nCurvePoints - 1 );
795  }
796  return 0.0;
797 }
798 
799 void QgsCompoundCurve::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
800 {
801  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
802  {
803  curve->filterVertices( filter );
804  }
805  clearCache();
806 }
807 
808 void QgsCompoundCurve::transformVertices( const std::function<QgsPoint( const QgsPoint & )> &transform )
809 {
810  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
811  {
812  curve->transformVertices( transform );
813  }
814  clearCache();
815 }
816 
817 void QgsCompoundCurve::sumUpArea( double &sum ) const
818 {
819  for ( const QgsCurve *curve : mCurves )
820  {
821  curve->sumUpArea( sum );
822  }
823 }
824 
826 {
827  if ( numPoints() < 1 || isClosed() )
828  {
829  return;
830  }
831  addVertex( startPoint() );
832 }
833 
835 {
836  for ( const QgsCurve *curve : mCurves )
837  {
838  if ( curve->hasCurvedSegments() )
839  {
840  return true;
841  }
842  }
843  return false;
844 }
845 
847 {
848  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
849  if ( curveIds.size() == 1 )
850  {
851  QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
852  return curve->vertexAngle( curveIds.at( 0 ).second );
853  }
854  else if ( curveIds.size() > 1 )
855  {
856  QgsCurve *curve1 = mCurves[curveIds.at( 0 ).first];
857  QgsCurve *curve2 = mCurves[curveIds.at( 1 ).first];
858  double angle1 = curve1->vertexAngle( curveIds.at( 0 ).second );
859  double angle2 = curve2->vertexAngle( curveIds.at( 1 ).second );
860  return QgsGeometryUtils::averageAngle( angle1, angle2 );
861  }
862  else
863  {
864  return 0.0;
865  }
866 }
867 
868 double QgsCompoundCurve::segmentLength( QgsVertexId startVertex ) const
869 {
870  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
871  double length = 0.0;
872  for ( auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
873  {
874  length += mCurves.at( it->first )->segmentLength( it->second );
875  }
876  return length;
877 }
878 
880 {
882  for ( int i = mCurves.count() - 1; i >= 0; --i )
883  {
884  QgsCurve *reversedCurve = mCurves.at( i )->reversed();
885  clone->addCurve( reversedCurve );
886  }
887  return clone;
888 }
889 
890 QgsPoint *QgsCompoundCurve::interpolatePoint( const double distance ) const
891 {
892  if ( distance < 0 )
893  return nullptr;
894 
895  double distanceTraversed = 0;
896  for ( const QgsCurve *curve : mCurves )
897  {
898  const double thisCurveLength = curve->length();
899  if ( distanceTraversed + thisCurveLength > distance || qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
900  {
901  // point falls on this segment - truncate to segment length if qgsDoubleNear test was actually > segment length
902  const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
903 
904  // point falls on this curve
905  return curve->interpolatePoint( distanceToPoint );
906  }
907 
908  distanceTraversed += thisCurveLength;
909  }
910 
911  return nullptr;
912 }
913 
914 QgsCompoundCurve *QgsCompoundCurve::curveSubstring( double startDistance, double endDistance ) const
915 {
916  if ( startDistance < 0 && endDistance < 0 )
917  return createEmptyWithSameType();
918 
919  endDistance = std::max( startDistance, endDistance );
920  std::unique_ptr< QgsCompoundCurve > substring = qgis::make_unique< QgsCompoundCurve >();
921 
922  double distanceTraversed = 0;
923  for ( const QgsCurve *curve : mCurves )
924  {
925  const double thisCurveLength = curve->length();
926  if ( distanceTraversed + thisCurveLength < startDistance )
927  {
928  // keep going - haven't found start yet, so no need to include this curve at all
929  }
930  else
931  {
932  std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
933  if ( part )
934  substring->addCurve( part.release() );
935  }
936 
937  distanceTraversed += thisCurveLength;
938  if ( distanceTraversed > endDistance )
939  break;
940  }
941 
942  return substring.release();
943 }
944 
945 bool QgsCompoundCurve::addZValue( double zValue )
946 {
947  if ( QgsWkbTypes::hasZ( mWkbType ) )
948  return false;
949 
951 
952  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
953  {
954  curve->addZValue( zValue );
955  }
956  clearCache();
957  return true;
958 }
959 
960 bool QgsCompoundCurve::addMValue( double mValue )
961 {
962  if ( QgsWkbTypes::hasM( mWkbType ) )
963  return false;
964 
966 
967  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
968  {
969  curve->addMValue( mValue );
970  }
971  clearCache();
972  return true;
973 }
974 
976 {
977  if ( !QgsWkbTypes::hasZ( mWkbType ) )
978  return false;
979 
981  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
982  {
983  curve->dropZValue();
984  }
985  clearCache();
986  return true;
987 }
988 
990 {
991  if ( !QgsWkbTypes::hasM( mWkbType ) )
992  return false;
993 
995  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
996  {
997  curve->dropMValue();
998  }
999  clearCache();
1000  return true;
1001 }
1002 
1004 {
1005  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
1006  {
1007  curve->swapXy();
1008  }
1009  clearCache();
1010 }
1011 
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
QgsVertexId::part
int part
Definition: qgsabstractgeometry.h:1080
QgsVertexId::vertex
int vertex
Definition: qgsabstractgeometry.h:1082
QgsAbstractGeometry::wkbType
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Definition: qgsabstractgeometry.h:189
QgsCompoundCurve::addMValue
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
Definition: qgscompoundcurve.cpp:960
QgsCompoundCurve::addZValue
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
Definition: qgscompoundcurve.cpp:945
QgsRectangle::combineExtentWith
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:359
qgslinestring.h
QgsCompoundCurve::endPoint
QgsPoint endPoint() const override
Returns the end point of the curve.
Definition: qgscompoundcurve.cpp:331
QgsGeometryUtils::Vertex
@ Vertex
Definition: qgsgeometryutils.h:733
QgsPoint::vertexAt
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
Definition: qgspoint.cpp:490
QgsCompoundCurve::xAt
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
Definition: qgscompoundcurve.cpp:769
QgsCompoundCurve::geometryType
QString geometryType() const override
Returns a unique string representing the geometry type.
Definition: qgscompoundcurve.cpp:69
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
qgswkbptr.h
QgsCompoundCurve::hasCurvedSegments
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
Definition: qgscompoundcurve.cpp:834
QgsCompoundCurve::calculateBoundingBox
QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
Definition: qgscompoundcurve.cpp:116
qgscompoundcurve.h
QgsCompoundCurve::dropZValue
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
Definition: qgscompoundcurve.cpp:975
QgsAbstractGeometry::parts
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
Definition: qgsabstractgeometry.cpp:266
QgsCoordinateTransform::TransformDirection
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
Definition: qgscoordinatetransform.h:58
QgsWkbTypes::LineString
@ LineString
Definition: qgswkbtypes.h:72
QgsCompoundCurve::dropMValue
bool dropMValue() override
Drops any measure values which exist in the geometry.
Definition: qgscompoundcurve.cpp:989
QgsCompoundCurve::addCurve
void addCurve(QgsCurve *c)
Adds a curve to the geometry (takes ownership)
Definition: qgscompoundcurve.cpp:457
QgsCompoundCurve::operator=
QgsCompoundCurve & operator=(const QgsCompoundCurve &curve)
Definition: qgscompoundcurve.cpp:89
QgsCompoundCurve::transformVertices
void transformVertices(const std::function< QgsPoint(const QgsPoint &) > &transform) override
Transforms the vertices from the geometry in place, applying the transform function to every vertex.
Definition: qgscompoundcurve.cpp:808
QgsAbstractGeometry::wktTypeStr
QString wktTypeStr() const
Returns the WKT type string of the geometry.
Definition: qgsabstractgeometry.cpp:147
QgsAbstractGeometry::length
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
Definition: qgsabstractgeometry.cpp:132
QgsCompoundCurve::curveToLine
QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a new line string geometry corresponding to a segmentized approximation of the curve.
Definition: qgscompoundcurve.cpp:388
QgsCompoundCurve::close
void close()
Appends first point if not already closed.
Definition: qgscompoundcurve.cpp:825
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
QgsWkbTypes::hasZ
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1042
QgsAbstractGeometry::SegmentationToleranceType
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
Definition: qgsabstractgeometry.h:112
QgsAbstractGeometry::mWkbType
QgsWkbTypes::Type mWkbType
Definition: qgsabstractgeometry.h:1005
QgsCompoundCurve::sumUpArea
void sumUpArea(double &sum) const override
Sums up the area of the curve by iterating over the vertices (shoelace formula).
Definition: qgscompoundcurve.cpp:817
QgsWkbTypes::dropM
static Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:1212
QgsCompoundCurve::createEmptyWithSameType
QgsCompoundCurve * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
Definition: qgscompoundcurve.cpp:62
QgsCompoundCurve::insertVertex
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
Definition: qgscompoundcurve.cpp:578
QgsCompoundCurve::asJsonObject
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
Definition: qgscompoundcurve.cpp:305
QgsLineString
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:43
QgsWkbTypes::addM
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1163
QgsCompoundCurve::fromWkt
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
Definition: qgscompoundcurve.cpp:172
QgsRectangle
Definition: qgsrectangle.h:41
QgsCurve::clearCache
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
Definition: qgscurve.cpp:256
QgsCompoundCurve::fromWkb
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
Definition: qgscompoundcurve.cpp:132
qgsapplication.h
QgsCompoundCurve::segmentLength
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
Definition: qgscompoundcurve.cpp:868
QgsCompoundCurve::nCurves
int nCurves() const
Returns the number of curves in the geometry.
Definition: qgscompoundcurve.h:76
MathUtils::leftOf
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'. Negative values mean left ...
Definition: MathUtils.cpp:292
QgsAbstractGeometry::vertexAngle
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
precision
int precision
Definition: qgswfsgetfeature.cpp:103
QgsGeometryUtils::closestSegmentFromComponents
static double closestSegmentFromComponents(T &container, ComponentType ctype, const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon)
Definition: qgsgeometryutils.h:739
QgsCircularString
Circular string geometry type.
Definition: qgscircularstring.h:34
QgsCurve::endPoint
virtual QgsPoint endPoint() const =0
Returns the end point of the curve.
QgsWkbTypes::Unknown
@ Unknown
Definition: qgswkbtypes.h:70
QgsAbstractGeometry::AxisOrder
AxisOrder
Axis order for GML generation.
Definition: qgsabstractgeometry.h:128
QgsLineString::insertVertex
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
Definition: qgslinestring.cpp:1211
QgsCompoundCurve::addVertex
void addVertex(const QgsPoint &pt)
Adds a vertex to the end of the geometry.
Definition: qgscompoundcurve.cpp:499
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsConstWkbPtr
Definition: qgswkbptr.h:127
QgsGeometryUtils::averageAngle
static double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3)
Calculates the average angle (in radians) between the two linear segments from (x1,...
Definition: qgsgeometryutils.cpp:1506
QgsCompoundCurve::yAt
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
Definition: qgscompoundcurve.cpp:784
QgsCompoundCurve::points
void points(QgsPointSequence &pts) const override
Returns a list of points within the curve.
Definition: qgscompoundcurve.cpp:340
QgsCompoundCurve::closestSegment
double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *std::numeric_limits< double >::epsilon()) const override
Searches for the closest segment of the geometry to a given point.
Definition: qgscompoundcurve.cpp:749
QgsApplication::endian
static endian_t endian()
Returns whether this machine uses big or little endian.
Definition: qgsapplication.cpp:1230
QgsCompoundCurve::asGml3
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
Definition: qgscompoundcurve.cpp:287
QgsCompoundCurve::asWkt
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition: qgscompoundcurve.cpp:252
QgsAbstractGeometry::is3D
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
Definition: qgsabstractgeometry.h:202
QgsCompoundCurve::numPoints
int numPoints() const override
Returns the number of points in the curve.
Definition: qgscompoundcurve.cpp:358
QgsWkbPtr
Definition: qgswkbptr.h:42
qgscircularstring.h
QgsAbstractGeometry::fromWkb
virtual bool fromWkb(QgsConstWkbPtr &wkb)=0
Sets the geometry from a WKB string.
QgsCompoundCurve::transform
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
Definition: qgscompoundcurve.cpp:540
QgsCompoundCurve::clear
void clear() override
Clears the geometry, ie reset it to a null geometry.
Definition: qgscompoundcurve.cpp:108
qgsgeometryutils.h
QgsPoint::removeDuplicateNodes
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
Definition: qgspoint.cpp:128
QgsWkbTypes::addZ
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1138
QgsCompoundCurve::~QgsCompoundCurve
~QgsCompoundCurve() override
Definition: qgscompoundcurve.cpp:36
QgsCompoundCurve::curveAt
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
Definition: qgscompoundcurve.cpp:448
QgsCompoundCurve::startPoint
QgsPoint startPoint() const override
Returns the starting point of the curve.
Definition: qgscompoundcurve.cpp:322
QgsGeometryUtils::wktGetChildBlocks
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType=QString())
Parses a WKT string and returns of list of blocks contained in the WKT.
Definition: qgsgeometryutils.cpp:1325
QgsCompoundCurve::moveVertex
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
Definition: qgscompoundcurve.cpp:599
QgsCompoundCurve::isEmpty
bool isEmpty() const override
Returns true if the geometry is empty.
Definition: qgscompoundcurve.cpp:375
QgsCompoundCurve::length
double length() const override
Returns the planar, 2-dimensional length of the geometry.
Definition: qgscompoundcurve.cpp:312
QgsWkbTypes::hasM
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1092
QgsWkbTypes::CircularString
@ CircularString
Definition: qgswkbtypes.h:79
QgsCompoundCurve::QgsCompoundCurve
QgsCompoundCurve()
Definition: qgscompoundcurve.cpp:31
QgsCompoundCurve::clone
QgsCompoundCurve * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgscompoundcurve.cpp:103
QgsCompoundCurve::addToPainterPath
void addToPainterPath(QPainterPath &path) const override
Adds a curve to a painter path.
Definition: qgscompoundcurve.cpp:558
QgsLineString::append
void append(const QgsLineString *line)
Appends the contents of another line string to the end of this line string.
Definition: qgslinestring.cpp:815
QgsCurve::isClosed
virtual bool isClosed() const
Returns true if the curve is closed.
Definition: qgscurve.cpp:40
QgsCompoundCurve::equals
bool equals(const QgsCurve &other) const override
Checks whether this curve exactly equals another curve.
Definition: qgscompoundcurve.cpp:41
QgsAbstractGeometry::operator=
QgsAbstractGeometry & operator=(const QgsAbstractGeometry &geom)
Definition: qgsabstractgeometry.cpp:33
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:44
c
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
Definition: porting_processing.dox:1
QgsCompoundCurve::curveSubstring
QgsCompoundCurve * curveSubstring(double startDistance, double endDistance) const override
Returns a new curve representing a substring of this curve.
Definition: qgscompoundcurve.cpp:914
QgsLineString::addVertex
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
Definition: qgslinestring.cpp:1290
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsabstractgeometry.h:1033
QgsCompoundCurve::dimension
int dimension() const override
Returns the inherent dimension of the geometry.
Definition: qgscompoundcurve.cpp:74
QgsVertexId::ring
int ring
Definition: qgsabstractgeometry.h:1081
QgsAbstractGeometry::isMeasure
bool isMeasure() const
Returns true if the geometry contains m values.
Definition: qgsabstractgeometry.h:211
QgsCompoundCurve::removeDuplicateNodes
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
Definition: qgscompoundcurve.cpp:419
QgsVertexId::VertexType
VertexType
Definition: qgsabstractgeometry.h:1035
QgsCompoundCurve::vertexAngle
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
Definition: qgscompoundcurve.cpp:846
QgsCompoundCurve::asWkb
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Definition: qgscompoundcurve.cpp:227
QgsWkbTypes::dropZ
static Type dropZ(Type type)
Drops the z dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:1194
QgsConstWkbPtr::readHeader
QgsWkbTypes::Type readHeader() const
readHeader
Definition: qgswkbptr.cpp:54
QgsGeometryUtils::wktReadBlock
static QPair< QgsWkbTypes::Type, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
Definition: qgsgeometryutils.cpp:1299
QgsCompoundCurve::reversed
QgsCompoundCurve * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
Definition: qgscompoundcurve.cpp:879
QgsAbstractGeometry::setZMTypeFromSubGeometry
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
Definition: qgsabstractgeometry.cpp:43
QgsCompoundCurve::snappedToGrid
QgsCompoundCurve * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
Definition: qgscompoundcurve.cpp:400
QgsCompoundCurve::deleteVertex
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
Definition: qgscompoundcurve.cpp:616
QgsCoordinateTransform
Definition: qgscoordinatetransform.h:52
QgsCompoundCurve::swapXy
void swapXy() override
Swaps the x and y coordinates from the geometry.
Definition: qgscompoundcurve.cpp:1003
QgsCompoundCurve::interpolatePoint
QgsPoint * interpolatePoint(double distance) const override
Returns an interpolated point on the curve at the specified distance.
Definition: qgscompoundcurve.cpp:890
QgsCompoundCurve::draw
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
Definition: qgscompoundcurve.cpp:532
QgsCompoundCurve::drawAsPolygon
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
Definition: qgscompoundcurve.cpp:568
QgsWkbTypes::flatType
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:701
QgsCompoundCurve
Compound curve geometry type.
Definition: qgscompoundcurve.h:31
QgsCompoundCurve::asGml2
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
Definition: qgscompoundcurve.cpp:279
QgsCompoundCurve::filterVertices
void filterVertices(const std::function< bool(const QgsPoint &) > &filter) override
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
Definition: qgscompoundcurve.cpp:799
QgsCompoundCurve::removeCurve
void removeCurve(int i)
Removes a curve from the geometry.
Definition: qgscompoundcurve.cpp:488
QgsCompoundCurve::pointAt
bool pointAt(int node, QgsPoint &point, QgsVertexId::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
Definition: qgscompoundcurve.cpp:754
QgsWkbTypes::CompoundCurve
@ CompoundCurve
Definition: qgswkbtypes.h:80