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.