QGIS API Documentation  3.19.0-Master (c9e5875a2b)
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 
46  public:
47 
52 
59  QgsLineString( const QVector<QgsPoint> &points ) SIP_HOLDGIL;
60 
76  QgsLineString( const QVector<double> &x, const QVector<double> &y,
77  const QVector<double> &z = QVector<double>(),
78  const QVector<double> &m = QVector<double>(), bool is25DType = false ) SIP_HOLDGIL;
79 
84  QgsLineString( const QgsPoint &p1, const QgsPoint &p2 ) SIP_HOLDGIL;
85 
92  QgsLineString( const QVector<QgsPointXY> &points ) SIP_HOLDGIL;
93 
99 
110  static QgsLineString *fromBezierCurve( const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments = 30 ) SIP_FACTORY;
111 
117  static QgsLineString *fromQPolygonF( const QPolygonF &polygon ) SIP_FACTORY;
118 
119  bool equals( const QgsCurve &other ) const override;
120 
121 #ifndef SIP_RUN
122 
127  QgsPoint pointN( int i ) const;
128 #else
129 
136  SIP_PYOBJECT pointN( int i ) const SIP_TYPEHINT( QgsPoint );
137  % MethodCode
138  const int count = sipCpp->numPoints();
139  if ( a0 < -count || a0 >= count )
140  {
141  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
142  sipIsErr = 1;
143  }
144  else
145  {
146  std::unique_ptr< QgsPoint > p;
147  if ( a0 >= 0 )
148  p = std::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
149  else // negative index, count backwards from end
150  p = std::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
151  sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
152  }
153  % End
154 #endif
155 
156 #ifndef SIP_RUN
157  double xAt( int index ) const override;
158 #else
159 
168  double xAt( int index ) const override;
169  % MethodCode
170  const int count = sipCpp->numPoints();
171  if ( a0 < -count || a0 >= count )
172  {
173  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
174  sipIsErr = 1;
175  }
176  else
177  {
178  if ( a0 >= 0 )
179  return PyFloat_FromDouble( sipCpp->xAt( a0 ) );
180  else
181  return PyFloat_FromDouble( sipCpp->xAt( count + a0 ) );
182  }
183  % End
184 #endif
185 
186 #ifndef SIP_RUN
187  double yAt( int index ) const override;
188 #else
189 
198  double yAt( int index ) const override;
199  % MethodCode
200  const int count = sipCpp->numPoints();
201  if ( a0 < -count || a0 >= count )
202  {
203  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
204  sipIsErr = 1;
205  }
206  else
207  {
208  if ( a0 >= 0 )
209  return PyFloat_FromDouble( sipCpp->yAt( a0 ) );
210  else
211  return PyFloat_FromDouble( sipCpp->yAt( count + a0 ) );
212  }
213  % End
214 #endif
215 
222  const double *xData() const SIP_SKIP
223  {
224  return mX.constData();
225  }
226 
233  const double *yData() const SIP_SKIP
234  {
235  return mY.constData();
236  }
237 
246  const double *zData() const SIP_SKIP
247  {
248  if ( mZ.empty() )
249  return nullptr;
250  else
251  return mZ.constData();
252  }
253 
262  const double *mData() const SIP_SKIP
263  {
264  if ( mM.empty() )
265  return nullptr;
266  else
267  return mM.constData();
268  }
269 
270 #ifndef SIP_RUN
271 
279  double zAt( int index ) const
280  {
281  if ( index >= 0 && index < mZ.size() )
282  return mZ.at( index );
283  else
284  return std::numeric_limits<double>::quiet_NaN();
285  }
286 #else
287 
298  double zAt( int index ) const;
299  % MethodCode
300  const int count = sipCpp->numPoints();
301  if ( a0 < -count || a0 >= count )
302  {
303  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
304  sipIsErr = 1;
305  }
306  else
307  {
308  if ( a0 >= 0 )
309  return PyFloat_FromDouble( sipCpp->zAt( a0 ) );
310  else
311  return PyFloat_FromDouble( sipCpp->zAt( count + a0 ) );
312  }
313  % End
314 #endif
315 
316 #ifndef SIP_RUN
317 
325  double mAt( int index ) const
326  {
327  if ( index >= 0 && index < mM.size() )
328  return mM.at( index );
329  else
330  return std::numeric_limits<double>::quiet_NaN();
331  }
332 #else
333 
344  double mAt( int index ) const;
345  % MethodCode
346  const int count = sipCpp->numPoints();
347  if ( a0 < -count || a0 >= count )
348  {
349  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
350  sipIsErr = 1;
351  }
352  else
353  {
354  if ( a0 >= 0 )
355  return PyFloat_FromDouble( sipCpp->mAt( a0 ) );
356  else
357  return PyFloat_FromDouble( sipCpp->mAt( count + a0 ) );
358  }
359  % End
360 #endif
361 
362 #ifndef SIP_RUN
363 
371  void setXAt( int index, double x );
372 #else
373 
385  void setXAt( int index, double x );
386  % MethodCode
387  const int count = sipCpp->numPoints();
388  if ( a0 < -count || a0 >= count )
389  {
390  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
391  sipIsErr = 1;
392  }
393  else
394  {
395  if ( a0 >= 0 )
396  sipCpp->setXAt( a0, a1 );
397  else
398  sipCpp->setXAt( count + a0, a1 );
399  }
400  % End
401 #endif
402 
403 #ifndef SIP_RUN
404 
412  void setYAt( int index, double y );
413 #else
414 
426  void setYAt( int index, double y );
427  % MethodCode
428  const int count = sipCpp->numPoints();
429  if ( a0 < -count || a0 >= count )
430  {
431  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
432  sipIsErr = 1;
433  }
434  else
435  {
436  if ( a0 >= 0 )
437  sipCpp->setYAt( a0, a1 );
438  else
439  sipCpp->setYAt( count + a0, a1 );
440  }
441  % End
442 #endif
443 
444 #ifndef SIP_RUN
445 
453  void setZAt( int index, double z )
454  {
455  if ( index >= 0 && index < mZ.size() )
456  mZ[ index ] = z;
457  }
458 #else
459 
471  void setZAt( int index, double z );
472  % MethodCode
473  const int count = sipCpp->numPoints();
474  if ( a0 < -count || a0 >= count )
475  {
476  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
477  sipIsErr = 1;
478  }
479  else
480  {
481  if ( a0 >= 0 )
482  sipCpp->setZAt( a0, a1 );
483  else
484  sipCpp->setZAt( count + a0, a1 );
485  }
486  % End
487 #endif
488 
489 #ifndef SIP_RUN
490 
498  void setMAt( int index, double m )
499  {
500  if ( index >= 0 && index < mM.size() )
501  mM[ index ] = m;
502  }
503 #else
504 
516  void setMAt( int index, double m );
517  % MethodCode
518  const int count = sipCpp->numPoints();
519  if ( a0 < -count || a0 >= count )
520  {
521  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
522  sipIsErr = 1;
523  }
524  else
525  {
526  if ( a0 >= 0 )
527  sipCpp->setMAt( a0, a1 );
528  else
529  sipCpp->setMAt( count + a0, a1 );
530  }
531  % End
532 #endif
533 
539  void setPoints( const QgsPointSequence &points );
540 
545  void append( const QgsLineString *line );
546 
551  void addVertex( const QgsPoint &pt );
552 
554  void close();
555 
560  QgsCompoundCurve *toCurveType() const override SIP_FACTORY;
561 
568  void extend( double startDistance, double endDistance );
569 
570 #ifndef SIP_RUN
571 
577  void visitPointsByRegularDistance( double distance, const std::function< bool( double x, double y, double z, double m,
578  double startSegmentX, double startSegmentY, double startSegmentZ, double startSegmentM,
579  double endSegmentX, double endSegmentY, double endSegmentZ, double endSegmentM
580  ) > &visitPoint ) const;
581 #endif
582 
583  //reimplemented methods
584 
585  QString geometryType() const override SIP_HOLDGIL;
586  int dimension() const override SIP_HOLDGIL;
587  QgsLineString *clone() const override SIP_FACTORY;
588  void clear() override;
589  bool isEmpty() const override SIP_HOLDGIL;
590  bool isValid( QString &error SIP_OUT, int flags = 0 ) const override;
591  QgsLineString *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const override SIP_FACTORY;
592  bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
593  bool isClosed() const override SIP_HOLDGIL;
594  bool boundingBoxIntersects( const QgsRectangle &rectangle ) const override SIP_HOLDGIL;
595 
603  QVector< QgsVertexId > collectDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) const;
604 
605  QPolygonF asQPolygonF() const override;
606 
607  bool fromWkb( QgsConstWkbPtr &wkb ) override;
608  bool fromWkt( const QString &wkt ) override;
609 
610  int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
611  QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
612  QString asWkt( int precision = 17 ) const override;
613  QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
614  QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
615  json asJsonObject( int precision = 17 ) const override SIP_SKIP;
616  QString asKml( int precision = 17 ) const override;
617 
618  //curve interface
619  double length() const override SIP_HOLDGIL;
620 
627  double length3D() const SIP_HOLDGIL;
628  QgsPoint startPoint() const override SIP_HOLDGIL;
629  QgsPoint endPoint() const override SIP_HOLDGIL;
630 
637  QgsLineString *curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
638 
639  int numPoints() const override SIP_HOLDGIL;
640  int nCoordinates() const override SIP_HOLDGIL;
641  void points( QgsPointSequence &pt SIP_OUT ) const override;
642 
643  void draw( QPainter &p ) const override;
644 
645  void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) override SIP_THROW( QgsCsException );
646  void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
647 
648  void addToPainterPath( QPainterPath &path ) const override;
649  void drawAsPolygon( QPainter &p ) const override;
650 
651  bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
652  bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
653  bool deleteVertex( QgsVertexId position ) override;
654 
655  QgsLineString *reversed() const override SIP_FACTORY;
656  QgsPoint *interpolatePoint( double distance ) const override SIP_FACTORY;
657  QgsLineString *curveSubstring( double startDistance, double endDistance ) const override SIP_FACTORY;
658 
659  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;
660  bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const override;
661 
662  QgsPoint centroid() const override;
663 
664  void sumUpArea( double &sum SIP_OUT ) const override;
665  double vertexAngle( QgsVertexId vertex ) const override;
666  double segmentLength( QgsVertexId startVertex ) const override;
667  bool addZValue( double zValue = 0 ) override;
668  bool addMValue( double mValue = 0 ) override;
669 
670  bool dropZValue() override;
671  bool dropMValue() override;
672  void swapXy() override;
673 
674  bool convertTo( QgsWkbTypes::Type type ) override;
675 
676  bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) override;
677 
678 #ifndef SIP_RUN
679  void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
680  void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override;
681 
689  inline static const QgsLineString *cast( const QgsAbstractGeometry *geom )
690  {
691  if ( geom && QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::LineString )
692  return static_cast<const QgsLineString *>( geom );
693  return nullptr;
694  }
695 #endif
696 
698 
699 #ifdef SIP_RUN
700  SIP_PYOBJECT __repr__();
701  % MethodCode
702  QString wkt = sipCpp->asWkt();
703  if ( wkt.length() > 1000 )
704  wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
705  QString str = QStringLiteral( "<QgsLineString: %1>" ).arg( wkt );
706  sipRes = PyUnicode_FromString( str.toUtf8().constData() );
707  % End
708 
717  SIP_PYOBJECT __getitem__( int index ) SIP_TYPEHINT( QgsPoint );
718  % MethodCode
719  const int count = sipCpp->numPoints();
720  if ( a0 < -count || a0 >= count )
721  {
722  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
723  sipIsErr = 1;
724  }
725  else
726  {
727  std::unique_ptr< QgsPoint > p;
728  if ( a0 >= 0 )
729  p = std::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
730  else
731  p = std::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
732  sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
733  }
734  % End
735 
744  void __setitem__( int index, const QgsPoint &point );
745  % MethodCode
746  const int count = sipCpp->numPoints();
747  if ( a0 < -count || a0 >= count )
748  {
749  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
750  sipIsErr = 1;
751  }
752  else
753  {
754  if ( a0 < 0 )
755  a0 = count + a0;
756  sipCpp->setXAt( a0, a1->x() );
757  sipCpp->setYAt( a0, a1->y() );
758  if ( sipCpp->isMeasure() )
759  sipCpp->setMAt( a0, a1->m() );
760  if ( sipCpp->is3D() )
761  sipCpp->setZAt( a0, a1->z() );
762  }
763  % End
764 
765 
774  void __delitem__( int index );
775  % MethodCode
776  const int count = sipCpp->numPoints();
777  if ( a0 >= 0 && a0 < count )
778  sipCpp->deleteVertex( QgsVertexId( -1, -1, a0 ) );
779  else if ( a0 < 0 && a0 >= -count )
780  sipCpp->deleteVertex( QgsVertexId( -1, -1, count + a0 ) );
781  else
782  {
783  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
784  sipIsErr = 1;
785  }
786  % End
787 
788 #endif
789 
790  protected:
791 
792  QgsRectangle calculateBoundingBox() const override;
793 
794  private:
795  QVector<double> mX;
796  QVector<double> mY;
797  QVector<double> mZ;
798  QVector<double> mM;
799 
800  void importVerticesFromWkb( const QgsConstWkbPtr &wkb );
801 
807  void fromWkbPoints( QgsWkbTypes::Type type, const QgsConstWkbPtr &wkb )
808  {
809  mWkbType = type;
810  importVerticesFromWkb( wkb );
811  }
812 
813  friend class QgsPolygon;
814  friend class QgsTriangle;
815 
816 };
817 
818 // clazy:excludeall=qstring-allocations
819 
820 #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:138
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
QLineF segment(int index, QRectF rect, double radius)
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.