QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
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  bool isValid( QString &error SIP_OUT, int flags = 0 ) const override;
590  QgsLineString *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const override SIP_FACTORY;
591  bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
592 
600  QVector< QgsVertexId > collectDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) const;
601 
602  QPolygonF asQPolygonF() const override;
603 
604  bool fromWkb( QgsConstWkbPtr &wkb ) override;
605  bool fromWkt( const QString &wkt ) override;
606 
607  int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
608  QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
609  QString asWkt( int precision = 17 ) const override;
610  QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
611  QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
612  json asJsonObject( int precision = 17 ) const override SIP_SKIP;
613  QString asKml( int precision = 17 ) const override;
614 
615  //curve interface
616  double length() const override SIP_HOLDGIL;
617 
624  double length3D() const SIP_HOLDGIL;
625  QgsPoint startPoint() const override SIP_HOLDGIL;
626  QgsPoint endPoint() const override SIP_HOLDGIL;
627 
634  QgsLineString *curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
635 
636  int numPoints() const override SIP_HOLDGIL;
637  int nCoordinates() const override SIP_HOLDGIL;
638  void points( QgsPointSequence &pt SIP_OUT ) const override;
639 
640  void draw( QPainter &p ) const override;
641 
642  void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) override SIP_THROW( QgsCsException );
643  void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
644 
645  void addToPainterPath( QPainterPath &path ) const override;
646  void drawAsPolygon( QPainter &p ) const override;
647 
648  bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
649  bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
650  bool deleteVertex( QgsVertexId position ) override;
651 
652  QgsLineString *reversed() const override SIP_FACTORY;
653  QgsPoint *interpolatePoint( double distance ) const override SIP_FACTORY;
654  QgsLineString *curveSubstring( double startDistance, double endDistance ) const override SIP_FACTORY;
655 
656  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;
657  bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const override;
658 
659  QgsPoint centroid() const override;
660 
661  void sumUpArea( double &sum SIP_OUT ) const override;
662  double vertexAngle( QgsVertexId vertex ) const override;
663  double segmentLength( QgsVertexId startVertex ) const override;
664  bool addZValue( double zValue = 0 ) override;
665  bool addMValue( double mValue = 0 ) override;
666 
667  bool dropZValue() override;
668  bool dropMValue() override;
669  void swapXy() override;
670 
671  bool convertTo( QgsWkbTypes::Type type ) override;
672 
673  bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) override;
674 
675 #ifndef SIP_RUN
676  void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
677  void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override;
678 
686  inline static const QgsLineString *cast( const QgsAbstractGeometry *geom )
687  {
688  if ( geom && QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::LineString )
689  return static_cast<const QgsLineString *>( geom );
690  return nullptr;
691  }
692 #endif
693 
695 
696 #ifdef SIP_RUN
697  SIP_PYOBJECT __repr__();
698  % MethodCode
699  QString wkt = sipCpp->asWkt();
700  if ( wkt.length() > 1000 )
701  wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
702  QString str = QStringLiteral( "<QgsLineString: %1>" ).arg( wkt );
703  sipRes = PyUnicode_FromString( str.toUtf8().constData() );
704  % End
705 
714  SIP_PYOBJECT __getitem__( int index ) SIP_TYPEHINT( QgsPoint );
715  % MethodCode
716  const int count = sipCpp->numPoints();
717  if ( a0 < -count || a0 >= count )
718  {
719  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
720  sipIsErr = 1;
721  }
722  else
723  {
724  std::unique_ptr< QgsPoint > p;
725  if ( a0 >= 0 )
726  p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
727  else
728  p = qgis::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
729  sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
730  }
731  % End
732 
741  void __setitem__( int index, const QgsPoint &point );
742  % MethodCode
743  const int count = sipCpp->numPoints();
744  if ( a0 < -count || a0 >= count )
745  {
746  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
747  sipIsErr = 1;
748  }
749  else
750  {
751  if ( a0 < 0 )
752  a0 = count + a0;
753  sipCpp->setXAt( a0, a1->x() );
754  sipCpp->setYAt( a0, a1->y() );
755  if ( sipCpp->isMeasure() )
756  sipCpp->setMAt( a0, a1->m() );
757  if ( sipCpp->is3D() )
758  sipCpp->setZAt( a0, a1->z() );
759  }
760  % End
761 
762 
771  void __delitem__( int index );
772  % MethodCode
773  const int count = sipCpp->numPoints();
774  if ( a0 >= 0 && a0 < count )
775  sipCpp->deleteVertex( QgsVertexId( -1, -1, a0 ) );
776  else if ( a0 < 0 && a0 >= -count )
777  sipCpp->deleteVertex( QgsVertexId( -1, -1, count + a0 ) );
778  else
779  {
780  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
781  sipIsErr = 1;
782  }
783  % End
784 
785 #endif
786 
787  protected:
788 
789  QgsRectangle calculateBoundingBox() const override;
790 
791  private:
792  QVector<double> mX;
793  QVector<double> mY;
794  QVector<double> mZ;
795  QVector<double> mM;
796 
797  void importVerticesFromWkb( const QgsConstWkbPtr &wkb );
798 
804  void fromWkbPoints( QgsWkbTypes::Type type, const QgsConstWkbPtr &wkb )
805  {
806  mWkbType = type;
807  importVerticesFromWkb( wkb );
808  }
809 
810  friend class QgsPolygon;
811  friend class QgsTriangle;
812 
813 };
814 
815 // clazy:excludeall=qstring-allocations
816 
817 #endif // QGSLINESTRING_H
An abstract base class for classes which transform geometries by transforming input points to output ...
Abstract base class for all geometries.
virtual QgsRectangle calculateBoundingBox() const
Default calculator for the minimal bounding box for the geometry.
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.
virtual QString geometryType() const =0
Returns a unique string representing the geometry type.
virtual QgsAbstractGeometry * createEmptyWithSameType() const =0
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
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...
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
Compound curve geometry type.
A const WKB pointer.
Definition: qgswkbptr.h:130
Class for doing transforms between two map coordinate systems.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
Abstract base class for curved geometry type.
Definition: qgscurve.h:36
virtual bool equals(const QgsCurve &other) const =0
Checks whether this curve exactly equals another curve.
QgsCurve * toCurveType() const override
Returns the geometry converted to the more generic curve type.
Definition: qgscurve.cpp:197
virtual double xAt(int index) const =0
Returns the x-coordinate of the specified node in the line string.
virtual double yAt(int index) const =0
Returns the y-coordinate of the specified node in the line string.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
Represents a single 2D line segment, consisting of a 2D start and end vertex only.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
const double * yData() const
Returns a const pointer to the y vertex data.
static const QgsLineString * cast(const QgsAbstractGeometry *geom)
Cast the geom to a QgsLineString.
const double * mData() const
Returns a const pointer to the m vertex data, or nullptr if the linestring does not have m values.
void setZAt(int index, double z)
Sets the z-coordinate of the specified node in the line string.
double mAt(int index) const
Returns the m value of the specified node in the line string.
double zAt(int index) const
Returns the z-coordinate of the specified node in the line string.
void setMAt(int index, double m)
Sets the m value of the specified node in the line string.
const double * xData() const
Returns a const pointer to the x vertex data.
const double * zData() const
Returns a const pointer to the z vertex data, or nullptr if the linestring does not have z values.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:38
Polygon geometry type.
Definition: qgspolygon.h:34
A rectangle specified with double values.
Definition: qgsrectangle.h:42
Triangle geometry type.
Definition: qgstriangle.h:34
Handles storage of information regarding WKB types and their properties.
Definition: qgswkbtypes.h:42
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:702
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
#define SIP_THROW(name)
Definition: qgis_sip.h:189
#define SIP_TYPEHINT(type)
Definition: qgis_sip.h:218
#define SIP_SKIP
Definition: qgis_sip.h:126
#define SIP_OUT
Definition: qgis_sip.h:58
#define SIP_HOLDGIL
Definition: qgis_sip.h:157
#define SIP_FACTORY
Definition: qgis_sip.h:76
QVector< QgsPoint > QgsPointSequence
double closestSegment(const QgsPolylineXY &pl, const QgsPointXY &pt, int &vertexAfter, double epsilon)
Definition: qgstracer.cpp:68
int precision
Utility class for identifying a unique vertex within a geometry.