18 #ifndef QGSLINESTRING_H
19 #define QGSLINESTRING_H
24 #include "qgis_core.h"
78 QgsLineString( SIP_PYOBJECT points
SIP_TYPEHINT( Sequence[Union[
QgsPoint,
QgsPointXY, Sequence[
float]]] ) )
SIP_HOLDGIL [(
const QVector<double> &x,
const QVector<double> &y,
const QVector<double> &z = QVector<double>(),
const QVector<double> &m = QVector<double>(),
bool is25DType = false )];
80 if ( !PySequence_Check( a0 ) )
82 PyErr_SetString( PyExc_TypeError, QStringLiteral(
"A sequence of QgsPoint, QgsPointXY or array of floats is expected" ).toUtf8().constData() );
88 const int size = PySequence_Size( a0 );
101 for (
int i = 0; i < size; ++i )
103 PyObject *value = PySequence_GetItem( a0, i );
106 PyErr_SetString( PyExc_TypeError, QStringLiteral(
"Invalid type at index %1." ).arg( i ) .toUtf8().constData() );
111 if ( PySequence_Check( value ) )
113 const int elementSize = PySequence_Size( value );
114 if ( elementSize < 2 || elementSize > 4 )
117 PyErr_SetString( PyExc_TypeError, QStringLiteral(
"Invalid sequence size at index %1. Expected an array of 2-4 float values, got %2." ).arg( i ).arg( elementSize ).toUtf8().constData() );
124 for (
int j = 0; j < elementSize; ++j )
126 PyObject *element = PySequence_GetItem( value, j );
129 PyErr_SetString( PyExc_TypeError, QStringLiteral(
"Invalid type at index %1." ).arg( i ) .toUtf8().constData() );
135 double d = PyFloat_AsDouble( element );
136 if ( PyErr_Occurred() )
147 if ( i == 0 && j == 2 )
153 else if ( i > 0 && j == 2 && hasZ )
158 if ( i == 0 && j == 3 )
164 else if ( i > 0 && j == 3 && hasM )
169 Py_DECREF( element );
172 if ( hasZ && elementSize < 3 )
173 zl.append( std::numeric_limits< double >::quiet_NaN() );
174 if ( hasM && elementSize < 4 )
175 ml.append( std::numeric_limits< double >::quiet_NaN() );
186 if ( sipCanConvertToType( value, sipType_QgsPointXY, SIP_NOT_NONE ) )
189 QgsPointXY *p =
reinterpret_cast<QgsPointXY *
>( sipConvertToType( value, sipType_QgsPointXY, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
195 sipReleaseType( p, sipType_QgsPointXY, state );
197 else if ( sipCanConvertToType( value, sipType_QgsPoint, SIP_NOT_NONE ) )
200 QgsPoint *p =
reinterpret_cast<QgsPoint *
>( sipConvertToType( value, sipType_QgsPoint, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
206 if ( i == 0 && p->
is3D() )
212 else if ( i > 0 && hasZ )
223 else if ( i > 0 && hasM )
231 sipReleaseType( p, sipType_QgsPoint, state );
243 PyErr_SetString( PyExc_TypeError, QStringLiteral(
"Invalid type at index %1. Expected QgsPoint, QgsPointXY or array of floats." ).arg( i ) .toUtf8().constData() );
249 sipCpp =
new sipQgsLineString(
QgsLineString( xl, yl, zl, ml, is25D ) );
278 QgsLineString(
const QVector<double> &x,
const QVector<double> &y,
279 const QVector<double> &z = QVector<double>(),
280 const QVector<double> &m = QVector<double>(),
bool is25DType =
false )
SIP_HOLDGIL;
328 const int count = sipCpp->numPoints();
329 if ( a0 < -count || a0 >= count )
331 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
336 std::unique_ptr< QgsPoint > p;
338 p = std::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
340 p = std::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
341 sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
347 double xAt(
int index )
const override;
358 double xAt(
int index )
const override;
360 const int count = sipCpp->numPoints();
361 if ( a0 < -count || a0 >= count )
363 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
369 return PyFloat_FromDouble( sipCpp->xAt( a0 ) );
371 return PyFloat_FromDouble( sipCpp->xAt( count + a0 ) );
377 double yAt(
int index )
const override;
388 double yAt(
int index )
const override;
390 const int count = sipCpp->numPoints();
391 if ( a0 < -count || a0 >= count )
393 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
399 return PyFloat_FromDouble( sipCpp->yAt( a0 ) );
401 return PyFloat_FromDouble( sipCpp->yAt( count + a0 ) );
414 return mX.constData();
425 return mY.constData();
441 return mZ.constData();
457 return mM.constData();
469 double zAt(
int index )
const
471 if ( index >= 0 && index < mZ.size() )
472 return mZ.at( index );
474 return std::numeric_limits<double>::quiet_NaN();
488 double zAt(
int index )
const;
490 const int count = sipCpp->numPoints();
491 if ( a0 < -count || a0 >= count )
493 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
499 return PyFloat_FromDouble( sipCpp->zAt( a0 ) );
501 return PyFloat_FromDouble( sipCpp->zAt( count + a0 ) );
515 double mAt(
int index )
const
517 if ( index >= 0 && index < mM.size() )
518 return mM.at( index );
520 return std::numeric_limits<double>::quiet_NaN();
534 double mAt(
int index )
const;
536 const int count = sipCpp->numPoints();
537 if ( a0 < -count || a0 >= count )
539 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
545 return PyFloat_FromDouble( sipCpp->mAt( a0 ) );
547 return PyFloat_FromDouble( sipCpp->mAt( count + a0 ) );
561 void setXAt(
int index,
double x );
575 void setXAt(
int index,
double x );
577 const int count = sipCpp->numPoints();
578 if ( a0 < -count || a0 >= count )
580 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
586 sipCpp->setXAt( a0, a1 );
588 sipCpp->setXAt( count + a0, a1 );
602 void setYAt(
int index,
double y );
616 void setYAt(
int index,
double y );
618 const int count = sipCpp->numPoints();
619 if ( a0 < -count || a0 >= count )
621 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
627 sipCpp->setYAt( a0, a1 );
629 sipCpp->setYAt( count + a0, a1 );
645 if ( index >= 0 && index < mZ.size() )
660 void setZAt(
int index,
double z );
662 const int count = sipCpp->numPoints();
663 if ( a0 < -count || a0 >= count )
665 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
671 sipCpp->setZAt( a0, a1 );
673 sipCpp->setZAt( count + a0, a1 );
689 if ( index >= 0 && index < mM.size() )
704 void setMAt(
int index,
double m );
706 const int count = sipCpp->numPoints();
707 if ( a0 < -count || a0 >= count )
709 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
715 sipCpp->setMAt( a0, a1 );
717 sipCpp->setMAt( count + a0, a1 );
739 void addVertex(
const QgsPoint &pt );
756 void extend(
double startDistance,
double endDistance );
765 void visitPointsByRegularDistance(
double distance,
const std::function<
bool(
double x,
double y,
double z,
double m,
766 double startSegmentX,
double startSegmentY,
double startSegmentZ,
double startSegmentM,
767 double endSegmentX,
double endSegmentY,
double endSegmentZ,
double endSegmentM
768 ) > &visitPoint )
const;
775 void clear() override;
777 int indexOf( const
QgsPoint &point ) const final;
778 bool isValid( QString &error
SIP_OUT,
Qgis::GeometryValidityFlags flags =
Qgis::GeometryValidityFlags() ) const override;
779 QgsLineString *snappedToGrid(
double hSpacing,
double vSpacing,
double dSpacing = 0,
double mSpacing = 0 ) const override
SIP_FACTORY;
780 bool removeDuplicateNodes(
double epsilon = 4 * std::numeric_limits<
double>::epsilon(),
bool useZValues = false ) override;
792 QVector<
QgsVertexId > collectDuplicateNodes(
double epsilon = 4 * std::numeric_limits<
double>::epsilon(),
bool useZValues = false ) const;
794 QPolygonF asQPolygonF() const override;
797 bool fromWkt( const QString &wkt ) override;
801 QString asWkt(
int precision = 17 ) const override;
805 QString asKml(
int precision = 17 ) const override;
811 std::tuple< std::unique_ptr< QgsCurve >, std::unique_ptr< QgsCurve > >
splitCurveAtVertex(
int index )
const final;
830 QgsLineString *curveToLine(
double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override
SIP_FACTORY;
836 void draw( QPainter &p ) const override;
839 void transform( const QTransform &t,
double zTranslate = 0.0,
double zScale = 1.0,
double mTranslate = 0.0,
double mScale = 1.0 ) override;
841 void addToPainterPath( QPainterPath &path ) const override;
842 void drawAsPolygon( QPainter &p ) const override;
846 bool deleteVertex(
QgsVertexId position ) override;
853 bool pointAt(
int node,
QgsPoint &point,
Qgis::VertexType &type ) const override;
857 void sumUpArea(
double &sum
SIP_OUT ) const override;
858 double vertexAngle(
QgsVertexId vertex ) const override;
859 double segmentLength(
QgsVertexId startVertex ) const override;
860 bool addZValue(
double zValue = 0 ) override;
861 bool addMValue(
double mValue = 0 ) override;
863 bool dropZValue() override;
864 bool dropMValue() override;
865 void swapXy() override;
870 void scroll(
int firstVertexIndex ) final;
894 SIP_PYOBJECT __repr__();
896 QString wkt = sipCpp->asWkt();
897 if ( wkt.length() > 1000 )
898 wkt = wkt.left( 1000 ) + QStringLiteral(
"..." );
899 QString
str = QStringLiteral(
"<QgsLineString: %1>" ).arg( wkt );
900 sipRes = PyUnicode_FromString(
str.toUtf8().constData() );
914 const int count = sipCpp->numPoints();
915 if ( a0 < -count || a0 >= count )
917 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
922 std::unique_ptr< QgsPoint > p;
924 p = std::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
926 p = std::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
927 sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
940 void __setitem__(
int index,
const QgsPoint &point );
942 const int count = sipCpp->numPoints();
943 if ( a0 < -count || a0 >= count )
945 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
952 sipCpp->setXAt( a0, a1->x() );
953 sipCpp->setYAt( a0, a1->y() );
954 if ( sipCpp->isMeasure() )
955 sipCpp->setMAt( a0, a1->m() );
956 if ( sipCpp->is3D() )
957 sipCpp->setZAt( a0, a1->z() );
971 void __delitem__(
int index );
973 const int count = sipCpp->numPoints();
974 if ( a0 >= 0 && a0 < count )
976 else if ( a0 < 0 && a0 >= -count )
977 sipCpp->deleteVertex(
QgsVertexId( -1, -1, count + a0 ) );
980 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
1008 importVerticesFromWkb( wkb );
1013 friend class TestQgsGeometry;
The Qgis class provides global constants for use throughout the application.
Abstract base class for all geometries.
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
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.
virtual int compareToSameClass(const QgsAbstractGeometry *other) const =0
Compares to an other geometry of the same class, and returns a integer for sorting of the two geometr...
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
Compound curve geometry type.
Custom exception class for Coordinate Reference System related exceptions.
Abstract base class for curved geometry type.
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.
virtual double xAt(int index) const =0
Returns the x-coordinate of the specified node in the line string.
virtual std::tuple< std::unique_ptr< QgsCurve >, std::unique_ptr< QgsCurve > > splitCurveAtVertex(int index) const =0
Splits the curve at the specified vertex index, returning two curves which represent the portion of t...
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.
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.
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.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
A rectangle specified with double values.
Handles storage of information regarding WKB types and their properties.
Type
The WKB type describes the number of dimensions a geometry has.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
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 ...
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
#define SIP_TYPEHINT(type)
QVector< QgsPoint > QgsPointSequence
QLineF segment(int index, QRectF rect, double radius)
double closestSegment(const QgsPolylineXY &pl, const QgsPointXY &pt, int &vertexAfter, double epsilon)
Utility class for identifying a unique vertex within a geometry.