QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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  QString secondWithoutParentheses = parts.second;
183  secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' );
184  if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
185  secondWithoutParentheses.isEmpty() )
186  return true;
187 
188  QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() );
189 
190  const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType );
191  for ( const QString &childWkt : blocks )
192  {
193  QPair<QgsWkbTypes::Type, QString> childParts = QgsGeometryUtils::wktReadBlock( childWkt );
194 
195  if ( QgsWkbTypes::flatType( childParts.first ) == QgsWkbTypes::LineString )
196  mCurves.append( new QgsLineString() );
197  else if ( QgsWkbTypes::flatType( childParts.first ) == QgsWkbTypes::CircularString )
198  mCurves.append( new QgsCircularString() );
199  else
200  {
201  clear();
202  return false;
203  }
204  if ( !mCurves.back()->fromWkt( childWkt ) )
205  {
206  clear();
207  return false;
208  }
209  }
210 
211  //scan through curves and check if dimensionality of curves is different to compound curve.
212  //if so, update the type dimensionality of the compound curve to match
213  bool hasZ = false;
214  bool hasM = false;
215  for ( const QgsCurve *curve : qgis::as_const( mCurves ) )
216  {
217  hasZ = hasZ || curve->is3D();
218  hasM = hasM || curve->isMeasure();
219  if ( hasZ && hasM )
220  break;
221  }
222  if ( hasZ )
223  addZValue( 0 );
224  if ( hasM )
225  addMValue( 0 );
226 
227  return true;
228 }
229 
230 int QgsCompoundCurve::wkbSize( QgsAbstractGeometry::WkbFlags flags ) const
231 {
232  int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
233  for ( const QgsCurve *curve : mCurves )
234  {
235  binarySize += curve->wkbSize( flags );
236  }
237  return binarySize;
238 }
239 
240 QByteArray QgsCompoundCurve::asWkb( WkbFlags flags ) const
241 {
242  QByteArray wkbArray;
243  wkbArray.resize( QgsCompoundCurve::wkbSize( flags ) );
244  QgsWkbPtr wkb( wkbArray );
245  wkb << static_cast<char>( QgsApplication::endian() );
246  wkb << static_cast<quint32>( wkbType() );
247  wkb << static_cast<quint32>( mCurves.size() );
248  for ( const QgsCurve *curve : mCurves )
249  {
250  wkb << curve->asWkb( flags );
251  }
252  return wkbArray;
253 }
254 
255 QString QgsCompoundCurve::asWkt( int precision ) const
256 {
257  QString wkt = wktTypeStr();
258  if ( isEmpty() )
259  wkt += QLatin1String( " EMPTY" );
260  else
261  {
262  wkt += QLatin1String( " (" );
263  for ( const QgsCurve *curve : mCurves )
264  {
265  QString childWkt = curve->asWkt( precision );
266  if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
267  {
268  // Type names of linear geometries are omitted
269  childWkt = childWkt.mid( childWkt.indexOf( '(' ) );
270  }
271  wkt += childWkt + ',';
272  }
273  if ( wkt.endsWith( ',' ) )
274  {
275  wkt.chop( 1 );
276  }
277  wkt += ')';
278  }
279  return wkt;
280 }
281 
282 QDomElement QgsCompoundCurve::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
283 {
284  // GML2 does not support curves
285  std::unique_ptr< QgsLineString > line( curveToLine() );
286  QDomElement gml = line->asGml2( doc, precision, ns, axisOrder );
287  return gml;
288 }
289 
290 QDomElement QgsCompoundCurve::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
291 {
292  QDomElement compoundCurveElem = doc.createElementNS( ns, QStringLiteral( "CompositeCurve" ) );
293 
294  if ( isEmpty() )
295  return compoundCurveElem;
296 
297  for ( const QgsCurve *curve : mCurves )
298  {
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 );
303  }
304 
305  return compoundCurveElem;
306 }
307 
309 {
310  // GeoJSON does not support curves
311  std::unique_ptr< QgsLineString > line( curveToLine() );
312  return line->asJsonObject( precision );
313 }
314 
316 {
317  double length = 0;
318  for ( const QgsCurve *curve : mCurves )
319  {
320  length += curve->length();
321  }
322  return length;
323 }
324 
326 {
327  if ( mCurves.empty() )
328  {
329  return QgsPoint();
330  }
331  return mCurves.at( 0 )->startPoint();
332 }
333 
335 {
336  if ( mCurves.empty() )
337  {
338  return QgsPoint();
339  }
340  return mCurves.at( mCurves.size() - 1 )->endPoint();
341 }
342 
344 {
345  pts.clear();
346  if ( mCurves.empty() )
347  {
348  return;
349  }
350 
351  mCurves[0]->points( pts );
352  for ( int i = 1; i < mCurves.size(); ++i )
353  {
354  QgsPointSequence pList;
355  mCurves[i]->points( pList );
356  pList.removeFirst(); //first vertex already added in previous line
357  pts.append( pList );
358  }
359 }
360 
362 {
363  int nPoints = 0;
364  int nCurves = mCurves.size();
365  if ( nCurves < 1 )
366  {
367  return 0;
368  }
369 
370  for ( int i = 0; i < nCurves; ++i )
371  {
372  nPoints += mCurves.at( i )->numPoints() - 1; //last vertex is equal to first of next section
373  }
374  nPoints += 1; //last vertex was removed above
375  return nPoints;
376 }
377 
379 {
380  if ( mCurves.isEmpty() )
381  return true;
382 
383  for ( QgsCurve *curve : mCurves )
384  {
385  if ( !curve->isEmpty() )
386  return false;
387  }
388  return true;
389 }
390 
392 {
393  QgsLineString *line = new QgsLineString();
394  std::unique_ptr< QgsLineString > currentLine;
395  for ( const QgsCurve *curve : mCurves )
396  {
397  currentLine.reset( curve->curveToLine( tolerance, toleranceType ) );
398  line->append( currentLine.get() );
399  }
400  return line;
401 }
402 
403 QgsCompoundCurve *QgsCompoundCurve::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing ) const
404 {
405  std::unique_ptr<QgsCompoundCurve> result( createEmptyWithSameType() );
406 
407  for ( QgsCurve *curve : mCurves )
408  {
409  std::unique_ptr<QgsCurve> gridified( static_cast< QgsCurve * >( curve->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) );
410  if ( gridified )
411  {
412  result->mCurves.append( gridified.release() );
413  }
414  }
415 
416  if ( result->mCurves.empty() )
417  return nullptr;
418  else
419  return result.release();
420 }
421 
422 bool QgsCompoundCurve::removeDuplicateNodes( double epsilon, bool useZValues )
423 {
424  bool result = false;
425  const QVector< QgsCurve * > curves = mCurves;
426  int i = 0;
427  QgsPoint lastEnd;
428  for ( QgsCurve *curve : curves )
429  {
430  result = result || curve->removeDuplicateNodes( epsilon, useZValues );
431  if ( curve->numPoints() == 0 || qgsDoubleNear( curve->length(), 0.0, epsilon ) )
432  {
433  // empty curve, remove it
434  delete mCurves.takeAt( i );
435  result = true;
436  }
437  else
438  {
439  // ensure this line starts exactly where previous line ended
440  if ( i > 0 )
441  {
442  curve->moveVertex( QgsVertexId( -1, -1, 0 ), lastEnd );
443  }
444  lastEnd = curve->vertexAt( QgsVertexId( -1, -1, curve->numPoints() - 1 ) );
445  }
446  i++;
447  }
448  return result;
449 }
450 
451 const QgsCurve *QgsCompoundCurve::curveAt( int i ) const
452 {
453  if ( i < 0 || i >= mCurves.size() )
454  {
455  return nullptr;
456  }
457  return mCurves.at( i );
458 }
459 
461 {
462  if ( c )
463  {
464  if ( mCurves.empty() )
465  {
467  }
468 
469  mCurves.append( c );
470 
471  if ( QgsWkbTypes::hasZ( mWkbType ) && !QgsWkbTypes::hasZ( c->wkbType() ) )
472  {
473  c->addZValue();
474  }
475  else if ( !QgsWkbTypes::hasZ( mWkbType ) && QgsWkbTypes::hasZ( c->wkbType() ) )
476  {
477  c->dropZValue();
478  }
479  if ( QgsWkbTypes::hasM( mWkbType ) && !QgsWkbTypes::hasM( c->wkbType() ) )
480  {
481  c->addMValue();
482  }
483  else if ( !QgsWkbTypes::hasM( mWkbType ) && QgsWkbTypes::hasM( c->wkbType() ) )
484  {
485  c->dropMValue();
486  }
487  clearCache();
488  }
489 }
490 
492 {
493  if ( i < 0 || i >= mCurves.size() )
494  {
495  return;
496  }
497 
498  delete mCurves.takeAt( i );
499  clearCache();
500 }
501 
503 {
504  if ( mCurves.isEmpty() || mWkbType == QgsWkbTypes::Unknown )
505  {
507  }
508 
509  //is last curve QgsLineString
510  QgsCurve *lastCurve = nullptr;
511  if ( !mCurves.isEmpty() )
512  {
513  lastCurve = mCurves.at( mCurves.size() - 1 );
514  }
515 
516  QgsLineString *line = nullptr;
517  if ( !lastCurve || QgsWkbTypes::flatType( lastCurve->wkbType() ) != QgsWkbTypes::LineString )
518  {
519  line = new QgsLineString();
520  mCurves.append( line );
521  if ( lastCurve )
522  {
523  line->addVertex( lastCurve->endPoint() );
524  }
525  lastCurve = line;
526  }
527  else //create new QgsLineString* with point in it
528  {
529  line = static_cast<QgsLineString *>( lastCurve );
530  }
531  line->addVertex( pt );
532  clearCache();
533 }
534 
535 void QgsCompoundCurve::draw( QPainter &p ) const
536 {
537  for ( const QgsCurve *curve : mCurves )
538  {
539  curve->draw( p );
540  }
541 }
542 
544 {
545  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
546  {
547  curve->transform( ct, d, transformZ );
548  }
549  clearCache();
550 }
551 
552 void QgsCompoundCurve::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
553 {
554  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
555  {
556  curve->transform( t, zTranslate, zScale, mTranslate, mScale );
557  }
558  clearCache();
559 }
560 
561 void QgsCompoundCurve::addToPainterPath( QPainterPath &path ) const
562 {
563  QPainterPath pp;
564  for ( const QgsCurve *curve : mCurves )
565  {
566  curve->addToPainterPath( pp );
567  }
568  path.addPath( pp );
569 }
570 
571 void QgsCompoundCurve::drawAsPolygon( QPainter &p ) const
572 {
573  QPainterPath pp;
574  for ( const QgsCurve *curve : mCurves )
575  {
576  curve->addToPainterPath( pp );
577  }
578  p.drawPath( pp );
579 }
580 
581 bool QgsCompoundCurve::insertVertex( QgsVertexId position, const QgsPoint &vertex )
582 {
583  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
584  if ( curveIds.empty() )
585  {
586  return false;
587  }
588  int curveId = curveIds.at( 0 ).first;
589  if ( curveId >= mCurves.size() )
590  {
591  return false;
592  }
593 
594  bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
595  if ( success )
596  {
597  clearCache(); //bbox changed
598  }
599  return success;
600 }
601 
602 bool QgsCompoundCurve::moveVertex( QgsVertexId position, const QgsPoint &newPos )
603 {
604  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
605  QVector< QPair<int, QgsVertexId> >::const_iterator idIt = curveIds.constBegin();
606  for ( ; idIt != curveIds.constEnd(); ++idIt )
607  {
608  mCurves.at( idIt->first )->moveVertex( idIt->second, newPos );
609  }
610 
611  bool success = !curveIds.isEmpty();
612  if ( success )
613  {
614  clearCache(); //bbox changed
615  }
616  return success;
617 }
618 
620 {
621  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
622  if ( curveIds.size() == 1 )
623  {
624  if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
625  {
626  clearCache(); //bbox may have changed
627  return false;
628  }
629  if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 )
630  {
631  removeCurve( curveIds.at( 0 ).first );
632  }
633  }
634  else if ( curveIds.size() == 2 )
635  {
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 );
639  QgsPoint startPoint = mCurves.at( curveIds.at( 0 ).first ) ->startPoint();
640  QgsPoint endPoint = mCurves.at( curveIds.at( 1 ).first ) ->endPoint();
641  if ( QgsWkbTypes::flatType( mCurves.at( curveIds.at( 0 ).first )->wkbType() ) == QgsWkbTypes::LineString &&
642  QgsWkbTypes::flatType( mCurves.at( curveIds.at( 1 ).first )->wkbType() ) == QgsWkbTypes::CircularString &&
643  mCurves.at( curveIds.at( 1 ).first )->numPoints() > 3 )
644  {
645  QgsPoint intermediatePoint;
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 );
650  }
651  else if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
652  {
653  clearCache(); //bbox may have changed
654  return false;
655  }
656  if ( QgsWkbTypes::flatType( mCurves.at( curveIds.at( 0 ).first )->wkbType() ) == QgsWkbTypes::CircularString &&
657  mCurves.at( curveIds.at( 0 ).first )->numPoints() > 0 &&
658  QgsWkbTypes::flatType( mCurves.at( curveIds.at( 1 ).first )->wkbType() ) == QgsWkbTypes::LineString )
659  {
660  QgsPoint intermediatePoint = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
661  mCurves.at( curveIds.at( 1 ).first )->moveVertex( QgsVertexId( 0, 0, 0 ), intermediatePoint );
662  }
663  else if ( !mCurves.at( curveIds.at( 1 ).first )->deleteVertex( curveIds.at( 1 ).second ) )
664  {
665  clearCache(); //bbox may have changed
666  return false;
667  }
668  if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
669  mCurves.at( curveIds.at( 1 ).first )->numPoints() != 0 )
670  {
671  mCurves.at( curveIds.at( 1 ).first )->moveVertex( QgsVertexId( 0, 0, 0 ), startPoint );
672  removeCurve( curveIds.at( 0 ).first );
673  }
674  else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() != 0 &&
675  mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
676  {
677  mCurves.at( curveIds.at( 0 ).first )->moveVertex(
678  QgsVertexId( 0, 0, mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 ), endPoint );
679  removeCurve( curveIds.at( 1 ).first );
680  }
681  else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
682  mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
683  {
684  removeCurve( curveIds.at( 1 ).first );
685  removeCurve( curveIds.at( 0 ).first );
686  QgsLineString *line = new QgsLineString();
687  line->insertVertex( QgsVertexId( 0, 0, 0 ), startPoint );
688  line->insertVertex( QgsVertexId( 0, 0, 1 ), endPoint );
689  mCurves.insert( curveIds.at( 0 ).first, line );
690  }
691  else
692  {
693  QgsPoint endPointOfFirst = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
694  QgsPoint startPointOfSecond = mCurves.at( curveIds.at( 1 ).first ) ->startPoint();
695  if ( endPointOfFirst != startPointOfSecond )
696  {
697  QgsLineString *line = new QgsLineString();
698  line->insertVertex( QgsVertexId( 0, 0, 0 ), endPointOfFirst );
699  line->insertVertex( QgsVertexId( 0, 0, 1 ), startPointOfSecond );
700  mCurves.insert( curveIds.at( 1 ).first, line );
701  }
702  }
703  }
704 
705  bool success = !curveIds.isEmpty();
706  if ( success )
707  {
708  clearCache(); //bbox changed
709  }
710  return success;
711 }
712 
713 QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId( QgsVertexId id ) const
714 {
715  QVector< QPair<int, QgsVertexId> > curveIds;
716 
717  int currentVertexIndex = 0;
718  for ( int i = 0; i < mCurves.size(); ++i )
719  {
720  int increment = mCurves.at( i )->numPoints() - 1;
721  if ( id.vertex >= currentVertexIndex && id.vertex <= currentVertexIndex + increment )
722  {
723  int curveVertexId = id.vertex - currentVertexIndex;
724  QgsVertexId vid;
725  vid.part = 0;
726  vid.ring = 0;
727  vid.vertex = curveVertexId;
728  curveIds.append( qMakePair( i, vid ) );
729  if ( curveVertexId == increment && i < ( mCurves.size() - 1 ) ) //add first vertex of next curve
730  {
731  vid.vertex = 0;
732  curveIds.append( qMakePair( i + 1, vid ) );
733  }
734  break;
735  }
736  else if ( id.vertex >= currentVertexIndex && id.vertex == currentVertexIndex + increment + 1 && i == ( mCurves.size() - 1 ) )
737  {
738  int curveVertexId = id.vertex - currentVertexIndex;
739  QgsVertexId vid;
740  vid.part = 0;
741  vid.ring = 0;
742  vid.vertex = curveVertexId;
743  curveIds.append( qMakePair( i, vid ) );
744  break;
745  }
746  currentVertexIndex += increment;
747  }
748 
749  return curveIds;
750 }
751 
752 double QgsCompoundCurve::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
753 {
754  return QgsGeometryUtils::closestSegmentFromComponents( mCurves, QgsGeometryUtils::Vertex, pt, segmentPt, vertexAfter, leftOf, epsilon );
755 }
756 
757 bool QgsCompoundCurve::pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const
758 {
759  int currentVertexId = 0;
760  for ( int j = 0; j < mCurves.size(); ++j )
761  {
762  int nCurvePoints = mCurves.at( j )->numPoints();
763  if ( ( node - currentVertexId ) < nCurvePoints )
764  {
765  return ( mCurves.at( j )->pointAt( node - currentVertexId, point, type ) );
766  }
767  currentVertexId += ( nCurvePoints - 1 );
768  }
769  return false;
770 }
771 
772 double QgsCompoundCurve::xAt( int index ) const
773 {
774  int currentVertexId = 0;
775  for ( int j = 0; j < mCurves.size(); ++j )
776  {
777  int nCurvePoints = mCurves.at( j )->numPoints();
778  if ( ( index - currentVertexId ) < nCurvePoints )
779  {
780  return mCurves.at( j )->xAt( index - currentVertexId );
781  }
782  currentVertexId += ( nCurvePoints - 1 );
783  }
784  return 0.0;
785 }
786 
787 double QgsCompoundCurve::yAt( int index ) const
788 {
789  int currentVertexId = 0;
790  for ( int j = 0; j < mCurves.size(); ++j )
791  {
792  int nCurvePoints = mCurves.at( j )->numPoints();
793  if ( ( index - currentVertexId ) < nCurvePoints )
794  {
795  return mCurves.at( j )->yAt( index - currentVertexId );
796  }
797  currentVertexId += ( nCurvePoints - 1 );
798  }
799  return 0.0;
800 }
801 
802 void QgsCompoundCurve::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
803 {
804  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
805  {
806  curve->filterVertices( filter );
807  }
808  clearCache();
809 }
810 
811 void QgsCompoundCurve::transformVertices( const std::function<QgsPoint( const QgsPoint & )> &transform )
812 {
813  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
814  {
815  curve->transformVertices( transform );
816  }
817  clearCache();
818 }
819 
820 void QgsCompoundCurve::sumUpArea( double &sum ) const
821 {
822  for ( const QgsCurve *curve : mCurves )
823  {
824  curve->sumUpArea( sum );
825  }
826 }
827 
829 {
830  if ( numPoints() < 1 || isClosed() )
831  {
832  return;
833  }
834  addVertex( startPoint() );
835 }
836 
838 {
839  for ( const QgsCurve *curve : mCurves )
840  {
841  if ( curve->hasCurvedSegments() )
842  {
843  return true;
844  }
845  }
846  return false;
847 }
848 
850 {
851  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( vertex );
852  if ( curveIds.size() == 1 )
853  {
854  QgsCurve *curve = mCurves[curveIds.at( 0 ).first];
855  return curve->vertexAngle( curveIds.at( 0 ).second );
856  }
857  else if ( curveIds.size() > 1 )
858  {
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 );
863  return QgsGeometryUtils::averageAngle( angle1, angle2 );
864  }
865  else
866  {
867  return 0.0;
868  }
869 }
870 
871 double QgsCompoundCurve::segmentLength( QgsVertexId startVertex ) const
872 {
873  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( startVertex );
874  double length = 0.0;
875  for ( auto it = curveIds.constBegin(); it != curveIds.constEnd(); ++it )
876  {
877  length += mCurves.at( it->first )->segmentLength( it->second );
878  }
879  return length;
880 }
881 
883 {
885  for ( int i = mCurves.count() - 1; i >= 0; --i )
886  {
887  QgsCurve *reversedCurve = mCurves.at( i )->reversed();
888  clone->addCurve( reversedCurve );
889  }
890  return clone;
891 }
892 
893 QgsPoint *QgsCompoundCurve::interpolatePoint( const double distance ) const
894 {
895  if ( distance < 0 )
896  return nullptr;
897 
898  double distanceTraversed = 0;
899  for ( const QgsCurve *curve : mCurves )
900  {
901  const double thisCurveLength = curve->length();
902  if ( distanceTraversed + thisCurveLength > distance || qgsDoubleNear( distanceTraversed + thisCurveLength, distance ) )
903  {
904  // point falls on this segment - truncate to segment length if qgsDoubleNear test was actually > segment length
905  const double distanceToPoint = std::min( distance - distanceTraversed, thisCurveLength );
906 
907  // point falls on this curve
908  return curve->interpolatePoint( distanceToPoint );
909  }
910 
911  distanceTraversed += thisCurveLength;
912  }
913 
914  return nullptr;
915 }
916 
917 QgsCompoundCurve *QgsCompoundCurve::curveSubstring( double startDistance, double endDistance ) const
918 {
919  if ( startDistance < 0 && endDistance < 0 )
920  return createEmptyWithSameType();
921 
922  endDistance = std::max( startDistance, endDistance );
923  std::unique_ptr< QgsCompoundCurve > substring = qgis::make_unique< QgsCompoundCurve >();
924 
925  double distanceTraversed = 0;
926  for ( const QgsCurve *curve : mCurves )
927  {
928  const double thisCurveLength = curve->length();
929  if ( distanceTraversed + thisCurveLength < startDistance )
930  {
931  // keep going - haven't found start yet, so no need to include this curve at all
932  }
933  else
934  {
935  std::unique_ptr< QgsCurve > part( curve->curveSubstring( startDistance - distanceTraversed, endDistance - distanceTraversed ) );
936  if ( part )
937  substring->addCurve( part.release() );
938  }
939 
940  distanceTraversed += thisCurveLength;
941  if ( distanceTraversed > endDistance )
942  break;
943  }
944 
945  return substring.release();
946 }
947 
948 bool QgsCompoundCurve::addZValue( double zValue )
949 {
950  if ( QgsWkbTypes::hasZ( mWkbType ) )
951  return false;
952 
954 
955  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
956  {
957  curve->addZValue( zValue );
958  }
959  clearCache();
960  return true;
961 }
962 
963 bool QgsCompoundCurve::addMValue( double mValue )
964 {
965  if ( QgsWkbTypes::hasM( mWkbType ) )
966  return false;
967 
969 
970  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
971  {
972  curve->addMValue( mValue );
973  }
974  clearCache();
975  return true;
976 }
977 
979 {
980  if ( !QgsWkbTypes::hasZ( mWkbType ) )
981  return false;
982 
984  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
985  {
986  curve->dropZValue();
987  }
988  clearCache();
989  return true;
990 }
991 
993 {
994  if ( !QgsWkbTypes::hasM( mWkbType ) )
995  return false;
996 
998  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
999  {
1000  curve->dropMValue();
1001  }
1002  clearCache();
1003  return true;
1004 }
1005 
1007 {
1008  for ( QgsCurve *curve : qgis::as_const( mCurves ) )
1009  {
1010  curve->swapXy();
1011  }
1012  clearCache();
1013 }
1014 
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:36
QgsVertexId::part
int part
Part number.
Definition: qgsabstractgeometry.h:1131
QgsVertexId::vertex
int vertex
Vertex number.
Definition: qgsabstractgeometry.h:1137
QgsCompoundCurve::length
double length() const override SIP_HOLDGIL
Returns the planar, 2-dimensional length of the geometry.
Definition: qgscompoundcurve.cpp:315
QgsCompoundCurve::addMValue
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
Definition: qgscompoundcurve.cpp:963
QgsWkbTypes::dropM
static Type dropM(Type type) SIP_HOLDGIL
Drops the m dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:1213
QgsCompoundCurve::addZValue
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
Definition: qgscompoundcurve.cpp:948
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
QgsCompoundCurve::wkbSize
int wkbSize(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns the length of the QByteArray returned by asWkb()
Definition: qgscompoundcurve.cpp:230
QgsCompoundCurve::geometryType
QString geometryType() const override SIP_HOLDGIL
Returns a unique string representing the geometry type.
Definition: qgscompoundcurve.cpp:69
qgslinestring.h
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:520
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:38
qgswkbptr.h
QgsCompoundCurve::hasCurvedSegments
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
Definition: qgscompoundcurve.cpp:837
QgsCompoundCurve::calculateBoundingBox
QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
Definition: qgscompoundcurve.cpp:116
QgsCompoundCurve::isEmpty
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
Definition: qgscompoundcurve.cpp:378
QgsCompoundCurve::nCurves
int nCurves() const SIP_HOLDGIL
Returns the number of curves in the geometry.
Definition: qgscompoundcurve.h:78
qgscompoundcurve.h
QgsCompoundCurve::dropZValue
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
Definition: qgscompoundcurve.cpp:978
QgsWkbTypes::flatType
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:702
QgsAbstractGeometry::parts
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
Definition: qgsabstractgeometry.cpp:271
QgsCoordinateTransform::TransformDirection
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
Definition: qgscoordinatetransform.h:59
QgsWkbTypes::LineString
@ LineString
Definition: qgswkbtypes.h:73
QgsCompoundCurve::dropMValue
bool dropMValue() override
Drops any measure values which exist in the geometry.
Definition: qgscompoundcurve.cpp:992
QgsCompoundCurve::addCurve
void addCurve(QgsCurve *c)
Adds a curve to the geometry (takes ownership)
Definition: qgscompoundcurve.cpp:460
QgsCompoundCurve::operator=
QgsCompoundCurve & operator=(const QgsCompoundCurve &curve)
Definition: qgscompoundcurve.cpp:89
QgsWkbTypes::addZ
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1139
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:811
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::yAt
double yAt(int index) const override SIP_HOLDGIL
Returns the y-coordinate of the specified node in the line string.
Definition: qgscompoundcurve.cpp:787
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:391
QgsCompoundCurve::close
void close()
Appends first point if not already closed.
Definition: qgscompoundcurve.cpp:828
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
QgsAbstractGeometry::SegmentationToleranceType
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
Definition: qgsabstractgeometry.h:115
QgsAbstractGeometry::mWkbType
QgsWkbTypes::Type mWkbType
Definition: qgsabstractgeometry.h:1030
QgsCompoundCurve::numPoints
int numPoints() const override SIP_HOLDGIL
Returns the number of points in the curve.
Definition: qgscompoundcurve.cpp:361
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:820
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:581
QgsCompoundCurve::asJsonObject
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
Definition: qgscompoundcurve.cpp:308
QgsLineString
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
QgsCompoundCurve::xAt
double xAt(int index) const override SIP_HOLDGIL
Returns the x-coordinate of the specified node in the line string.
Definition: qgscompoundcurve.cpp:772
QgsCompoundCurve::fromWkt
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
Definition: qgscompoundcurve.cpp:172
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsCompoundCurve::curveAt
const QgsCurve * curveAt(int i) const SIP_HOLDGIL
Returns the curve at the specified index.
Definition: qgscompoundcurve.cpp:451
QgsCompoundCurve::startPoint
QgsPoint startPoint() const override SIP_HOLDGIL
Returns the starting point of the curve.
Definition: qgscompoundcurve.cpp:325
QgsCurve::clearCache
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
Definition: qgscurve.cpp:257
QgsCompoundCurve::fromWkb
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
Definition: qgscompoundcurve.cpp:132
qgsapplication.h
QgsAbstractGeometry::isMeasure
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
Definition: qgsabstractgeometry.h:215
QgsCompoundCurve::segmentLength
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
Definition: qgscompoundcurve.cpp:871
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.
QgsWkbTypes::addM
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1164
precision
int precision
Definition: qgswfsgetfeature.cpp:49
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:35
QgsAbstractGeometry::wkbType
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
Definition: qgsabstractgeometry.h:193
QgsCurve::endPoint
virtual QgsPoint endPoint() const =0
Returns the end point of the curve.
QgsWkbTypes::Unknown
@ Unknown
Definition: qgswkbtypes.h:71
QgsAbstractGeometry::AxisOrder
AxisOrder
Axis order for GML generation.
Definition: qgsabstractgeometry.h:133
QgsLineString::insertVertex
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
Definition: qgslinestring.cpp:1264
QgsCompoundCurve::endPoint
QgsPoint endPoint() const override SIP_HOLDGIL
Returns the end point of the curve.
Definition: qgscompoundcurve.cpp:334
QgsCompoundCurve::addVertex
void addVertex(const QgsPoint &pt)
Adds a vertex to the end of the geometry.
Definition: qgscompoundcurve.cpp:502
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:128
QgsGeometryUtils::averageAngle
static double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3) SIP_HOLDGIL
Calculates the average angle (in radians) between the two linear segments from (x1,...
Definition: qgsgeometryutils.cpp:1521
QgsCompoundCurve::points
void points(QgsPointSequence &pts) const override
Returns a list of points within the curve.
Definition: qgscompoundcurve.cpp:343
QgsWkbTypes::hasM
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1093
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:752
QgsApplication::endian
static endian_t endian()
Returns whether this machine uses big or little endian.
Definition: qgsapplication.cpp:1250
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:290
QgsCompoundCurve::asWkt
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition: qgscompoundcurve.cpp:255
QgsWkbTypes::dropZ
static Type dropZ(Type type) SIP_HOLDGIL
Drops the z dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:1195
QgsWkbPtr
Definition: qgswkbptr.h:43
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:543
QgsCompoundCurve::clear
void clear() override
Clears the geometry, ie reset it to a null geometry.
Definition: qgscompoundcurve.cpp:108
qgsgeometryutils.h
QgsAbstractGeometry::is3D
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
Definition: qgsabstractgeometry.h:206
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:129
QgsCompoundCurve::~QgsCompoundCurve
~QgsCompoundCurve() override
Definition: qgscompoundcurve.cpp:36
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:1340
QgsCompoundCurve::moveVertex
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
Definition: qgscompoundcurve.cpp:602
QgsWkbTypes::CircularString
@ CircularString
Definition: qgswkbtypes.h:80
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:561
QgsLineString::append
void append(const QgsLineString *line)
Appends the contents of another line string to the end of this line string.
Definition: qgslinestring.cpp:868
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:46
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:917
QgsLineString::addVertex
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
Definition: qgslinestring.cpp:1343
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsabstractgeometry.h:1059
QgsVertexId::ring
int ring
Ring number.
Definition: qgsabstractgeometry.h:1134
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:422
QgsVertexId::VertexType
VertexType
Type of vertex.
Definition: qgsabstractgeometry.h:1065
QgsWkbTypes::hasZ
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1043
QgsCompoundCurve::vertexAngle
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
Definition: qgscompoundcurve.cpp:849
QgsCompoundCurve::dimension
int dimension() const override SIP_HOLDGIL
Returns the inherent dimension of the geometry.
Definition: qgscompoundcurve.cpp:74
QgsCompoundCurve::asWkb
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Definition: qgscompoundcurve.cpp:240
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:1306
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:882
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:403
QgsCompoundCurve::deleteVertex
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
Definition: qgscompoundcurve.cpp:619
QgsCurve::isClosed
virtual bool isClosed() const SIP_HOLDGIL
Returns true if the curve is closed.
Definition: qgscurve.cpp:40
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:53
QgsCompoundCurve::swapXy
void swapXy() override
Swaps the x and y coordinates from the geometry.
Definition: qgscompoundcurve.cpp:1006
QgsCompoundCurve::interpolatePoint
QgsPoint * interpolatePoint(double distance) const override
Returns an interpolated point on the curve at the specified distance.
Definition: qgscompoundcurve.cpp:893
QgsCompoundCurve::draw
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
Definition: qgscompoundcurve.cpp:535
QgsCompoundCurve::drawAsPolygon
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
Definition: qgscompoundcurve.cpp:571
QgsCompoundCurve
Compound curve geometry type.
Definition: qgscompoundcurve.h:32
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:282
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:802
QgsCompoundCurve::removeCurve
void removeCurve(int i)
Removes a curve from the geometry.
Definition: qgscompoundcurve.cpp:491
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:757
QgsWkbTypes::CompoundCurve
@ CompoundCurve
Definition: qgswkbtypes.h:81