QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 
51 
58  QgsLineString( const QVector<QgsPoint> &points ) SIP_HOLDGIL;
59 
75  QgsLineString( const QVector<double> &x, const QVector<double> &y,
76  const QVector<double> &z = QVector<double>(),
77  const QVector<double> &m = QVector<double>(), bool is25DType = false ) SIP_HOLDGIL;
78 
83  QgsLineString( const QgsPoint &p1, const QgsPoint &p2 ) SIP_HOLDGIL;
84 
91  QgsLineString( const QVector<QgsPointXY> &points ) SIP_HOLDGIL;
92 
97  explicit QgsLineString( const QgsLineSegment2D &segment ) SIP_HOLDGIL;
98 
109  static QgsLineString *fromBezierCurve( const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments = 30 ) SIP_FACTORY;
110 
116  static QgsLineString *fromQPolygonF( const QPolygonF &polygon ) SIP_FACTORY;
117 
118  bool equals( const QgsCurve &other ) const override;
119 
120 #ifndef SIP_RUN
121 
126  QgsPoint pointN( int i ) const;
127 #else
128 
135  SIP_PYOBJECT pointN( int i ) const SIP_TYPEHINT( QgsPoint );
136  % MethodCode
137  const int count = sipCpp->numPoints();
138  if ( a0 < -count || a0 >= count )
139  {
140  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
141  sipIsErr = 1;
142  }
143  else
144  {
145  std::unique_ptr< QgsPoint > p;
146  if ( a0 >= 0 )
147  p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
148  else // negative index, count backwards from end
149  p = qgis::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
150  sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
151  }
152  % End
153 #endif
154 
155 #ifndef SIP_RUN
156  double xAt( int index ) const override;
157 #else
158 
167  double xAt( int index ) const override;
168  % MethodCode
169  const int count = sipCpp->numPoints();
170  if ( a0 < -count || a0 >= count )
171  {
172  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
173  sipIsErr = 1;
174  }
175  else
176  {
177  if ( a0 >= 0 )
178  return PyFloat_FromDouble( sipCpp->xAt( a0 ) );
179  else
180  return PyFloat_FromDouble( sipCpp->xAt( count + a0 ) );
181  }
182  % End
183 #endif
184 
185 #ifndef SIP_RUN
186  double yAt( int index ) const override;
187 #else
188 
197  double yAt( int index ) const override;
198  % MethodCode
199  const int count = sipCpp->numPoints();
200  if ( a0 < -count || a0 >= count )
201  {
202  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
203  sipIsErr = 1;
204  }
205  else
206  {
207  if ( a0 >= 0 )
208  return PyFloat_FromDouble( sipCpp->yAt( a0 ) );
209  else
210  return PyFloat_FromDouble( sipCpp->yAt( count + a0 ) );
211  }
212  % End
213 #endif
214 
221  const double *xData() const SIP_SKIP
222  {
223  return mX.constData();
224  }
225 
232  const double *yData() const SIP_SKIP
233  {
234  return mY.constData();
235  }
236 
245  const double *zData() const SIP_SKIP
246  {
247  if ( mZ.empty() )
248  return nullptr;
249  else
250  return mZ.constData();
251  }
252 
261  const double *mData() const SIP_SKIP
262  {
263  if ( mM.empty() )
264  return nullptr;
265  else
266  return mM.constData();
267  }
268 
269 #ifndef SIP_RUN
270 
278  double zAt( int index ) const
279  {
280  if ( index >= 0 && index < mZ.size() )
281  return mZ.at( index );
282  else
283  return std::numeric_limits<double>::quiet_NaN();
284  }
285 #else
286 
297  double zAt( int index ) const;
298  % MethodCode
299  const int count = sipCpp->numPoints();
300  if ( a0 < -count || a0 >= count )
301  {
302  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
303  sipIsErr = 1;
304  }
305  else
306  {
307  if ( a0 >= 0 )
308  return PyFloat_FromDouble( sipCpp->zAt( a0 ) );
309  else
310  return PyFloat_FromDouble( sipCpp->zAt( count + a0 ) );
311  }
312  % End
313 #endif
314 
315 #ifndef SIP_RUN
316 
324  double mAt( int index ) const
325  {
326  if ( index >= 0 && index < mM.size() )
327  return mM.at( index );
328  else
329  return std::numeric_limits<double>::quiet_NaN();
330  }
331 #else
332 
343  double mAt( int index ) const;
344  % MethodCode
345  const int count = sipCpp->numPoints();
346  if ( a0 < -count || a0 >= count )
347  {
348  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
349  sipIsErr = 1;
350  }
351  else
352  {
353  if ( a0 >= 0 )
354  return PyFloat_FromDouble( sipCpp->mAt( a0 ) );
355  else
356  return PyFloat_FromDouble( sipCpp->mAt( count + a0 ) );
357  }
358  % End
359 #endif
360 
361 #ifndef SIP_RUN
362 
370  void setXAt( int index, double x );
371 #else
372 
384  void setXAt( int index, double x );
385  % MethodCode
386  const int count = sipCpp->numPoints();
387  if ( a0 < -count || a0 >= count )
388  {
389  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
390  sipIsErr = 1;
391  }
392  else
393  {
394  if ( a0 >= 0 )
395  sipCpp->setXAt( a0, a1 );
396  else
397  sipCpp->setXAt( count + a0, a1 );
398  }
399  % End
400 #endif
401 
402 #ifndef SIP_RUN
403 
411  void setYAt( int index, double y );
412 #else
413 
425  void setYAt( int index, double y );
426  % MethodCode
427  const int count = sipCpp->numPoints();
428  if ( a0 < -count || a0 >= count )
429  {
430  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
431  sipIsErr = 1;
432  }
433  else
434  {
435  if ( a0 >= 0 )
436  sipCpp->setYAt( a0, a1 );
437  else
438  sipCpp->setYAt( count + a0, a1 );
439  }
440  % End
441 #endif
442 
443 #ifndef SIP_RUN
444 
452  void setZAt( int index, double z )
453  {
454  if ( index >= 0 && index < mZ.size() )
455  mZ[ index ] = z;
456  }
457 #else
458 
470  void setZAt( int index, double z );
471  % MethodCode
472  const int count = sipCpp->numPoints();
473  if ( a0 < -count || a0 >= count )
474  {
475  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
476  sipIsErr = 1;
477  }
478  else
479  {
480  if ( a0 >= 0 )
481  sipCpp->setZAt( a0, a1 );
482  else
483  sipCpp->setZAt( count + a0, a1 );
484  }
485  % End
486 #endif
487 
488 #ifndef SIP_RUN
489 
497  void setMAt( int index, double m )
498  {
499  if ( index >= 0 && index < mM.size() )
500  mM[ index ] = m;
501  }
502 #else
503 
515  void setMAt( int index, double m );
516  % MethodCode
517  const int count = sipCpp->numPoints();
518  if ( a0 < -count || a0 >= count )
519  {
520  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
521  sipIsErr = 1;
522  }
523  else
524  {
525  if ( a0 >= 0 )
526  sipCpp->setMAt( a0, a1 );
527  else
528  sipCpp->setMAt( count + a0, a1 );
529  }
530  % End
531 #endif
532 
538  void setPoints( const QgsPointSequence &points );
539 
544  void append( const QgsLineString *line );
545 
550  void addVertex( const QgsPoint &pt );
551 
553  void close();
554 
559  QgsCompoundCurve *toCurveType() const override SIP_FACTORY;
560 
567  void extend( double startDistance, double endDistance );
568 
569 #ifndef SIP_RUN
570 
576  void visitPointsByRegularDistance( double distance, const std::function< bool( double x, double y, double z, double m,
577  double startSegmentX, double startSegmentY, double startSegmentZ, double startSegmentM,
578  double endSegmentX, double endSegmentY, double endSegmentZ, double endSegmentM
579  ) > &visitPoint ) const;
580 #endif
581 
582  //reimplemented methods
583 
584  QString geometryType() const override SIP_HOLDGIL;
585  int dimension() const override SIP_HOLDGIL;
586  QgsLineString *clone() const override SIP_FACTORY;
587  void clear() override;
588  bool isEmpty() const override SIP_HOLDGIL;
589  QgsLineString *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const override SIP_FACTORY;
590  bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
591 
599  QVector< QgsVertexId > collectDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) const;
600 
601  QPolygonF asQPolygonF() const override;
602 
603  bool fromWkb( QgsConstWkbPtr &wkb ) override;
604  bool fromWkt( const QString &wkt ) override;
605 
606  int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
607  QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
608  QString asWkt( int precision = 17 ) const override;
609  QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
610  QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
611  json asJsonObject( int precision = 17 ) const override SIP_SKIP;
612  QString asKml( int precision = 17 ) const override;
613 
614  //curve interface
615  double length() const override SIP_HOLDGIL;
616 
623  double length3D() const SIP_HOLDGIL;
624  QgsPoint startPoint() const override SIP_HOLDGIL;
625  QgsPoint endPoint() const override SIP_HOLDGIL;
626 
633  QgsLineString *curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
634 
635  int numPoints() const override SIP_HOLDGIL;
636  int nCoordinates() const override SIP_HOLDGIL;
637  void points( QgsPointSequence &pt SIP_OUT ) const override;
638 
639  void draw( QPainter &p ) const override;
640 
641  void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) override SIP_THROW( QgsCsException );
642  void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
643 
644  void addToPainterPath( QPainterPath &path ) const override;
645  void drawAsPolygon( QPainter &p ) const override;
646 
647  bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
648  bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
649  bool deleteVertex( QgsVertexId position ) override;
650 
651  QgsLineString *reversed() const override SIP_FACTORY;
652  QgsPoint *interpolatePoint( double distance ) const override SIP_FACTORY;
653  QgsLineString *curveSubstring( double startDistance, double endDistance ) const override SIP_FACTORY;
654 
655  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;
656  bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const override;
657 
658  QgsPoint centroid() const override;
659 
660  void sumUpArea( double &sum SIP_OUT ) const override;
661  double vertexAngle( QgsVertexId vertex ) const override;
662  double segmentLength( QgsVertexId startVertex ) const override;
663  bool addZValue( double zValue = 0 ) override;
664  bool addMValue( double mValue = 0 ) override;
665 
666  bool dropZValue() override;
667  bool dropMValue() override;
668  void swapXy() override;
669 
670  bool convertTo( QgsWkbTypes::Type type ) override;
671 
672 #ifndef SIP_RUN
673  void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
674  void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override;
675 
683  inline const QgsLineString *cast( const QgsAbstractGeometry *geom ) const
684  {
685  if ( geom && QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::LineString )
686  return static_cast<const QgsLineString *>( geom );
687  return nullptr;
688  }
689 #endif
690 
692 
693 #ifdef SIP_RUN
694  SIP_PYOBJECT __repr__();
695  % MethodCode
696  QString wkt = sipCpp->asWkt();
697  if ( wkt.length() > 1000 )
698  wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
699  QString str = QStringLiteral( "<QgsLineString: %1>" ).arg( wkt );
700  sipRes = PyUnicode_FromString( str.toUtf8().constData() );
701  % End
702 
711  SIP_PYOBJECT __getitem__( int index ) SIP_TYPEHINT( QgsPoint );
712  % MethodCode
713  const int count = sipCpp->numPoints();
714  if ( a0 < -count || a0 >= count )
715  {
716  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
717  sipIsErr = 1;
718  }
719  else
720  {
721  std::unique_ptr< QgsPoint > p;
722  if ( a0 >= 0 )
723  p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
724  else
725  p = qgis::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
726  sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
727  }
728  % End
729 
738  void __setitem__( int index, const QgsPoint &point );
739  % MethodCode
740  const int count = sipCpp->numPoints();
741  if ( a0 < -count || a0 >= count )
742  {
743  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
744  sipIsErr = 1;
745  }
746  else
747  {
748  if ( a0 < 0 )
749  a0 = count + a0;
750  sipCpp->setXAt( a0, a1->x() );
751  sipCpp->setYAt( a0, a1->y() );
752  if ( sipCpp->isMeasure() )
753  sipCpp->setMAt( a0, a1->m() );
754  if ( sipCpp->is3D() )
755  sipCpp->setZAt( a0, a1->z() );
756  }
757  % End
758 
759 
768  void __delitem__( int index );
769  % MethodCode
770  const int count = sipCpp->numPoints();
771  if ( a0 >= 0 && a0 < count )
772  sipCpp->deleteVertex( QgsVertexId( -1, -1, a0 ) );
773  else if ( a0 < 0 && a0 >= -count )
774  sipCpp->deleteVertex( QgsVertexId( -1, -1, count + a0 ) );
775  else
776  {
777  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
778  sipIsErr = 1;
779  }
780  % End
781 
782 #endif
783 
784  protected:
785 
786  QgsRectangle calculateBoundingBox() const override;
787 
788  private:
789  QVector<double> mX;
790  QVector<double> mY;
791  QVector<double> mZ;
792  QVector<double> mM;
793 
794  void importVerticesFromWkb( const QgsConstWkbPtr &wkb );
795 
801  void fromWkbPoints( QgsWkbTypes::Type type, const QgsConstWkbPtr &wkb )
802  {
803  mWkbType = type;
804  importVerticesFromWkb( wkb );
805  }
806 
807  friend class QgsPolygon;
808  friend class QgsTriangle;
809 
810 };
811 
812 // clazy:excludeall=qstring-allocations
813 
814 #endif // QGSLINESTRING_H
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:36
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:245
QgsLineString::cast
const QgsLineString * cast(const QgsAbstractGeometry *geom) const
Cast the geom to a QgsLineString.
Definition: qgslinestring.h:683
QgsLineSegment2D
Represents a single 2D line segment, consisting of a 2D start and end vertex only.
Definition: qgslinesegment.h:32
QgsPolygon
Polygon geometry type.
Definition: qgspolygon.h:34
QgsLineString::mAt
double mAt(int index) const
Returns the m value of the specified node in the line string.
Definition: qgslinestring.h:324
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:38
SIP_OUT
#define SIP_OUT
Definition: qgis_sip.h:58
qgscompoundcurve.h
QgsWkbTypes::flatType
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:702
QgsLineString::zAt
double zAt(int index) const
Returns the z-coordinate of the specified node in the line string.
Definition: qgslinestring.h:278
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:73
QgsLineString::yData
const double * yData() const
Returns a const pointer to the y vertex data.
Definition: qgslinestring.h:232
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
QgsLineString
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
closestSegment
double closestSegment(const QgsPolylineXY &pl, const QgsPointXY &pt, int &vertexAfter, double epsilon)
Definition: qgstracer.cpp:68
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsLineString::xData
const double * xData() const
Returns a const pointer to the x vertex data.
Definition: qgslinestring.h:221
SIP_TYPEHINT
#define SIP_TYPEHINT(type)
Definition: qgis_sip.h:218
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:49
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
SIP_SKIP
#define SIP_SKIP
Definition: qgis_sip.h:126
SIP_HOLDGIL
#define SIP_HOLDGIL
Definition: qgis_sip.h:157
SIP_THROW
#define SIP_THROW(name)
Definition: qgis_sip.h:189
QgsAbstractGeometry::wkbType
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
Definition: qgsabstractgeometry.h:193
QgsConstWkbPtr
Definition: qgswkbptr.h:128
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:497
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:261
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:74
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.
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:452
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:46
qgscurve.h
QgsCurve::toCurveType
QgsCurve * toCurveType() const override
Returns the geometry converted to the more generic curve type.
Definition: qgscurve.cpp:197
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsabstractgeometry.h:1059
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:42
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:53
QgsCompoundCurve
Compound curve geometry type.
Definition: qgscompoundcurve.h:32
QgsTriangle
Triangle geometry type.
Definition: qgstriangle.h:34
QgsAbstractGeometry::calculateBoundingBox
virtual QgsRectangle calculateBoundingBox() const
Default calculator for the minimal bounding box for the geometry.
Definition: qgsabstractgeometry.cpp:85