QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgslinestring.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgslinestring.h
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 #ifndef QGSLINESTRING_H
19 #define QGSLINESTRING_H
20 
21 
22 #include <QPolygonF>
23 
24 #include "qgis_core.h"
25 #include "qgis_sip.h"
26 #include "qgscurve.h"
27 #include "qgscompoundcurve.h"
28 
29 class QgsLineSegment2D;
30 
31 /***************************************************************************
32  * This class is considered CRITICAL and any change MUST be accompanied with
33  * full unit tests in testqgsgeometry.cpp.
34  * See details in QEP #17
35  ****************************************************************************/
36 
43 class CORE_EXPORT QgsLineString: public QgsCurve
44 {
45  public:
46  QgsLineString();
47 
54  QgsLineString( const QVector<QgsPoint> &points );
55 
71  QgsLineString( const QVector<double> &x, const QVector<double> &y,
72  const QVector<double> &z = QVector<double>(),
73  const QVector<double> &m = QVector<double>(), bool is25DType = false );
74 
79  QgsLineString( const QgsPoint &p1, const QgsPoint &p2 );
80 
87  QgsLineString( const QVector<QgsPointXY> &points );
88 
93  explicit QgsLineString( const QgsLineSegment2D &segment );
94 
105  static QgsLineString *fromBezierCurve( const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments = 30 ) SIP_FACTORY;
106 
112  static QgsLineString *fromQPolygonF( const QPolygonF &polygon ) SIP_FACTORY;
113 
114  bool equals( const QgsCurve &other ) const override;
115 
116 #ifndef SIP_RUN
117 
122  QgsPoint pointN( int i ) const;
123 #else
124 
131  SIP_PYOBJECT pointN( int i ) const SIP_TYPEHINT( QgsPoint );
132  % MethodCode
133  const int count = sipCpp->numPoints();
134  if ( a0 < -count || a0 >= count )
135  {
136  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
137  sipIsErr = 1;
138  }
139  else
140  {
141  std::unique_ptr< QgsPoint > p;
142  if ( a0 >= 0 )
143  p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
144  else // negative index, count backwards from end
145  p = qgis::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
146  sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
147  }
148  % End
149 #endif
150 
151 #ifndef SIP_RUN
152  double xAt( int index ) const override;
153 #else
154 
163  double xAt( int index ) const override;
164  % MethodCode
165  const int count = sipCpp->numPoints();
166  if ( a0 < -count || a0 >= count )
167  {
168  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
169  sipIsErr = 1;
170  }
171  else
172  {
173  if ( a0 >= 0 )
174  return PyFloat_FromDouble( sipCpp->xAt( a0 ) );
175  else
176  return PyFloat_FromDouble( sipCpp->xAt( count + a0 ) );
177  }
178  % End
179 #endif
180 
181 #ifndef SIP_RUN
182  double yAt( int index ) const override;
183 #else
184 
193  double yAt( int index ) const override;
194  % MethodCode
195  const int count = sipCpp->numPoints();
196  if ( a0 < -count || a0 >= count )
197  {
198  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
199  sipIsErr = 1;
200  }
201  else
202  {
203  if ( a0 >= 0 )
204  return PyFloat_FromDouble( sipCpp->yAt( a0 ) );
205  else
206  return PyFloat_FromDouble( sipCpp->yAt( count + a0 ) );
207  }
208  % End
209 #endif
210 
217  const double *xData() const SIP_SKIP
218  {
219  return mX.constData();
220  }
221 
228  const double *yData() const SIP_SKIP
229  {
230  return mY.constData();
231  }
232 
241  const double *zData() const SIP_SKIP
242  {
243  if ( mZ.empty() )
244  return nullptr;
245  else
246  return mZ.constData();
247  }
248 
257  const double *mData() const SIP_SKIP
258  {
259  if ( mM.empty() )
260  return nullptr;
261  else
262  return mM.constData();
263  }
264 
265 #ifndef SIP_RUN
266 
274  double zAt( int index ) const
275  {
276  if ( index >= 0 && index < mZ.size() )
277  return mZ.at( index );
278  else
279  return std::numeric_limits<double>::quiet_NaN();
280  }
281 #else
282 
293  double zAt( int index ) const;
294  % MethodCode
295  const int count = sipCpp->numPoints();
296  if ( a0 < -count || a0 >= count )
297  {
298  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
299  sipIsErr = 1;
300  }
301  else
302  {
303  if ( a0 >= 0 )
304  return PyFloat_FromDouble( sipCpp->zAt( a0 ) );
305  else
306  return PyFloat_FromDouble( sipCpp->zAt( count + a0 ) );
307  }
308  % End
309 #endif
310 
311 #ifndef SIP_RUN
312 
320  double mAt( int index ) const
321  {
322  if ( index >= 0 && index < mM.size() )
323  return mM.at( index );
324  else
325  return std::numeric_limits<double>::quiet_NaN();
326  }
327 #else
328 
339  double mAt( int index ) const;
340  % MethodCode
341  const int count = sipCpp->numPoints();
342  if ( a0 < -count || a0 >= count )
343  {
344  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
345  sipIsErr = 1;
346  }
347  else
348  {
349  if ( a0 >= 0 )
350  return PyFloat_FromDouble( sipCpp->mAt( a0 ) );
351  else
352  return PyFloat_FromDouble( sipCpp->mAt( count + a0 ) );
353  }
354  % End
355 #endif
356 
357 #ifndef SIP_RUN
358 
366  void setXAt( int index, double x );
367 #else
368 
380  void setXAt( int index, double x );
381  % MethodCode
382  const int count = sipCpp->numPoints();
383  if ( a0 < -count || a0 >= count )
384  {
385  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
386  sipIsErr = 1;
387  }
388  else
389  {
390  if ( a0 >= 0 )
391  sipCpp->setXAt( a0, a1 );
392  else
393  sipCpp->setXAt( count + a0, a1 );
394  }
395  % End
396 #endif
397 
398 #ifndef SIP_RUN
399 
407  void setYAt( int index, double y );
408 #else
409 
421  void setYAt( int index, double y );
422  % MethodCode
423  const int count = sipCpp->numPoints();
424  if ( a0 < -count || a0 >= count )
425  {
426  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
427  sipIsErr = 1;
428  }
429  else
430  {
431  if ( a0 >= 0 )
432  sipCpp->setYAt( a0, a1 );
433  else
434  sipCpp->setYAt( count + a0, a1 );
435  }
436  % End
437 #endif
438 
439 #ifndef SIP_RUN
440 
448  void setZAt( int index, double z )
449  {
450  if ( index >= 0 && index < mZ.size() )
451  mZ[ index ] = z;
452  }
453 #else
454 
466  void setZAt( int index, double z );
467  % MethodCode
468  const int count = sipCpp->numPoints();
469  if ( a0 < -count || a0 >= count )
470  {
471  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
472  sipIsErr = 1;
473  }
474  else
475  {
476  if ( a0 >= 0 )
477  sipCpp->setZAt( a0, a1 );
478  else
479  sipCpp->setZAt( count + a0, a1 );
480  }
481  % End
482 #endif
483 
484 #ifndef SIP_RUN
485 
493  void setMAt( int index, double m )
494  {
495  if ( index >= 0 && index < mM.size() )
496  mM[ index ] = m;
497  }
498 #else
499 
511  void setMAt( int index, double m );
512  % MethodCode
513  const int count = sipCpp->numPoints();
514  if ( a0 < -count || a0 >= count )
515  {
516  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
517  sipIsErr = 1;
518  }
519  else
520  {
521  if ( a0 >= 0 )
522  sipCpp->setMAt( a0, a1 );
523  else
524  sipCpp->setMAt( count + a0, a1 );
525  }
526  % End
527 #endif
528 
534  void setPoints( const QgsPointSequence &points );
535 
540  void append( const QgsLineString *line );
541 
546  void addVertex( const QgsPoint &pt );
547 
549  void close();
550 
554  QgsCompoundCurve *toCurveType() const override SIP_FACTORY;
555 
562  void extend( double startDistance, double endDistance );
563 
564 #ifndef SIP_RUN
565 
571  void visitPointsByRegularDistance( double distance, const std::function< bool( double x, double y, double z, double m,
572  double startSegmentX, double startSegmentY, double startSegmentZ, double startSegmentM,
573  double endSegmentX, double endSegmentY, double endSegmentZ, double endSegmentM
574  ) > &visitPoint ) const;
575 #endif
576 
577  //reimplemented methods
578 
579  QString geometryType() const override;
580  int dimension() const override;
581  QgsLineString *clone() const override SIP_FACTORY;
582  void clear() override;
583  bool isEmpty() const override;
584  QgsLineString *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const override SIP_FACTORY;
585  bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
586  QPolygonF asQPolygonF() const override;
587 
588  bool fromWkb( QgsConstWkbPtr &wkb ) override;
589  bool fromWkt( const QString &wkt ) override;
590 
591  QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
592  QString asWkt( int precision = 17 ) const override;
593  QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
594  QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
595  json asJsonObject( int precision = 17 ) const override SIP_SKIP;
596  QString asKml( int precision = 17 ) const override;
597 
598  //curve interface
599  double length() const override;
600 
607  double length3D() const;
608  QgsPoint startPoint() const override;
609  QgsPoint endPoint() const override;
610 
616  QgsLineString *curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
617 
618  int numPoints() const override;
619  int nCoordinates() const override;
620  void points( QgsPointSequence &pt SIP_OUT ) const override;
621 
622  void draw( QPainter &p ) const override;
623 
624  void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) override SIP_THROW( QgsCsException );
625  void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
626 
627  void addToPainterPath( QPainterPath &path ) const override;
628  void drawAsPolygon( QPainter &p ) const override;
629 
630  bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
631  bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
632  bool deleteVertex( QgsVertexId position ) override;
633 
634  QgsLineString *reversed() const override SIP_FACTORY;
635  QgsPoint *interpolatePoint( double distance ) const override SIP_FACTORY;
636  QgsLineString *curveSubstring( double startDistance, double endDistance ) const override SIP_FACTORY;
637 
638  double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT, QgsVertexId &vertexAfter SIP_OUT, int *leftOf SIP_OUT = nullptr, double epsilon = 4 * std::numeric_limits<double>::epsilon() ) const override;
639  bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const override;
640 
641  QgsPoint centroid() const override;
642 
643  void sumUpArea( double &sum SIP_OUT ) const override;
644  double vertexAngle( QgsVertexId vertex ) const override;
645  double segmentLength( QgsVertexId startVertex ) const override;
646  bool addZValue( double zValue = 0 ) override;
647  bool addMValue( double mValue = 0 ) override;
648 
649  bool dropZValue() override;
650  bool dropMValue() override;
651  void swapXy() override;
652 
653  bool convertTo( QgsWkbTypes::Type type ) override;
654 
655 #ifndef SIP_RUN
656  void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
657  void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override;
658 
666  inline const QgsLineString *cast( const QgsAbstractGeometry *geom ) const
667  {
668  if ( geom && QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::LineString )
669  return static_cast<const QgsLineString *>( geom );
670  return nullptr;
671  }
672 #endif
673 
675 
676 #ifdef SIP_RUN
677  SIP_PYOBJECT __repr__();
678  % MethodCode
679  QString wkt = sipCpp->asWkt();
680  if ( wkt.length() > 1000 )
681  wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
682  QString str = QStringLiteral( "<QgsLineString: %1>" ).arg( wkt );
683  sipRes = PyUnicode_FromString( str.toUtf8().constData() );
684  % End
685 
694  SIP_PYOBJECT __getitem__( int index ) SIP_TYPEHINT( QgsPoint );
695  % MethodCode
696  const int count = sipCpp->numPoints();
697  if ( a0 < -count || a0 >= count )
698  {
699  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
700  sipIsErr = 1;
701  }
702  else
703  {
704  std::unique_ptr< QgsPoint > p;
705  if ( a0 >= 0 )
706  p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
707  else
708  p = qgis::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
709  sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
710  }
711  % End
712 
721  void __setitem__( int index, const QgsPoint &point );
722  % MethodCode
723  const int count = sipCpp->numPoints();
724  if ( a0 < -count || a0 >= count )
725  {
726  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
727  sipIsErr = 1;
728  }
729  else
730  {
731  if ( a0 < 0 )
732  a0 = count + a0;
733  sipCpp->setXAt( a0, a1->x() );
734  sipCpp->setYAt( a0, a1->y() );
735  if ( sipCpp->isMeasure() )
736  sipCpp->setMAt( a0, a1->m() );
737  if ( sipCpp->is3D() )
738  sipCpp->setZAt( a0, a1->z() );
739  }
740  % End
741 
742 
751  void __delitem__( int index );
752  % MethodCode
753  const int count = sipCpp->numPoints();
754  if ( a0 >= 0 && a0 < count )
755  sipCpp->deleteVertex( QgsVertexId( -1, -1, a0 ) );
756  else if ( a0 < 0 && a0 >= -count )
757  sipCpp->deleteVertex( QgsVertexId( -1, -1, count + a0 ) );
758  else
759  {
760  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
761  sipIsErr = 1;
762  }
763  % End
764 
765 #endif
766 
767  protected:
768 
769  QgsRectangle calculateBoundingBox() const override;
770 
771  private:
772  QVector<double> mX;
773  QVector<double> mY;
774  QVector<double> mZ;
775  QVector<double> mM;
776 
777  void importVerticesFromWkb( const QgsConstWkbPtr &wkb );
778 
784  void fromWkbPoints( QgsWkbTypes::Type type, const QgsConstWkbPtr &wkb )
785  {
786  mWkbType = type;
787  importVerticesFromWkb( wkb );
788  }
789 
790  friend class QgsPolygon;
791  friend class QgsTriangle;
792 
793 };
794 
795 // clazy:excludeall=qstring-allocations
796 
797 #endif // QGSLINESTRING_H
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
QgsLineString::zData
const double * zData() const
Returns a const pointer to the z vertex data, or nullptr if the linestring does not have z values.
Definition: qgslinestring.h:241
QgsAbstractGeometry::wkbType
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Definition: qgsabstractgeometry.h:189
QgsLineString::cast
const QgsLineString * cast(const QgsAbstractGeometry *geom) const
Cast the geom to a QgsLineString.
Definition: qgslinestring.h:666
QgsLineSegment2D
Definition: qgslinesegment.h:31
QgsPolygon
Polygon geometry type.
Definition: qgspolygon.h:33
QgsLineString::mAt
double mAt(int index) const
Returns the m value of the specified node in the line string.
Definition: qgslinestring.h:320
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
SIP_OUT
#define SIP_OUT
Definition: qgis_sip.h:58
qgscompoundcurve.h
QgsLineString::zAt
double zAt(int index) const
Returns the z-coordinate of the specified node in the line string.
Definition: qgslinestring.h:274
QgsAbstractGeometry::filterVertices
virtual void filterVertices(const std::function< bool(const QgsPoint &) > &filter)
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
Definition: qgsabstractgeometry.cpp:250
QgsWkbTypes::LineString
@ LineString
Definition: qgswkbtypes.h:72
QgsLineString::yData
const double * yData() const
Returns a const pointer to the y vertex data.
Definition: qgslinestring.h:228
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
QgsLineString
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:43
closestSegment
double closestSegment(const QgsPolylineXY &pl, const QgsPointXY &pt, int &vertexAfter, double epsilon)
Definition: qgstracer.cpp:68
QgsRectangle
Definition: qgsrectangle.h:41
QgsLineString::xData
const double * xData() const
Returns a const pointer to the x vertex data.
Definition: qgslinestring.h:217
SIP_TYPEHINT
#define SIP_TYPEHINT(type)
Definition: qgis_sip.h:213
SIP_FACTORY
#define SIP_FACTORY
Definition: qgis_sip.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
precision
int precision
Definition: qgswfsgetfeature.cpp:103
QgsAbstractGeometry::dimension
virtual int dimension() const =0
Returns the inherent dimension of the geometry.
QgsCsException
Definition: qgsexception.h:65
SIP_SKIP
#define SIP_SKIP
Definition: qgis_sip.h:126
SIP_THROW
#define SIP_THROW(name)
Definition: qgis_sip.h:184
QgsConstWkbPtr
Definition: qgswkbptr.h:127
QgsCurve::equals
virtual bool equals(const QgsCurve &other) const =0
Checks whether this curve exactly equals another curve.
qgis_sip.h
QgsCurve::yAt
virtual double yAt(int index) const =0
Returns the y-coordinate of the specified node in the line string.
QgsLineString::setMAt
void setMAt(int index, double m)
Sets the m value of the specified node in the line string.
Definition: qgslinestring.h:493
QgsLineString::mData
const double * mData() const
Returns a const pointer to the m vertex data, or nullptr if the linestring does not have m values.
Definition: qgslinestring.h:257
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:71
QgsCurve::xAt
virtual double xAt(int index) const =0
Returns the x-coordinate of the specified node in the line string.
QgsAbstractGeometry::geometryType
virtual QString geometryType() const =0
Returns a unique string representing the geometry type.
QgsCurve::clone
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
QgsAbstractGeometry::createEmptyWithSameType
virtual QgsAbstractGeometry * createEmptyWithSameType() const =0
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
QgsLineString::setZAt
void setZAt(int index, double z)
Sets the z-coordinate of the specified node in the line string.
Definition: qgslinestring.h:448
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:44
qgscurve.h
QgsCurve::toCurveType
QgsCurve * toCurveType() const override
Returns the geometry converted to the more generic curve type.
Definition: qgscurve.cpp:190
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsabstractgeometry.h:1033
QgsAbstractGeometry::transformVertices
virtual void transformVertices(const std::function< QgsPoint(const QgsPoint &) > &transform)
Transforms the vertices from the geometry in place, applying the transform function to every vertex.
Definition: qgsabstractgeometry.cpp:255
QgsWkbTypes
Handles storage of information regarding WKB types and their properties.
Definition: qgswkbtypes.h:40
QgsCoordinateTransform
Definition: qgscoordinatetransform.h:52
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
QgsTriangle
Triangle geometry type.
Definition: qgstriangle.h:33
QgsAbstractGeometry::calculateBoundingBox
virtual QgsRectangle calculateBoundingBox() const
Default calculator for the minimal bounding box for the geometry.
Definition: qgsabstractgeometry.cpp:85