83 if ( !PySequence_Check( a0 ) )
85 PyErr_SetString( PyExc_TypeError, u
"A sequence of QgsPoint, QgsPointXY or array of floats is expected"_s.toUtf8().constData() );
91 const int size = PySequence_Size( a0 );
104 for (
int i = 0; i < size; ++i )
106 PyObject *value = PySequence_GetItem( a0, i );
109 PyErr_SetString( PyExc_TypeError, u
"Invalid type at index %1."_s.arg( i ) .toUtf8().constData() );
114 if ( PySequence_Check( value ) )
116 const int elementSize = PySequence_Size( value );
117 if ( elementSize < 2 || elementSize > 4 )
120 PyErr_SetString( PyExc_TypeError, u
"Invalid sequence size at index %1. Expected an array of 2-4 float values, got %2."_s.arg( i ).arg( elementSize ).toUtf8().constData() );
127 for (
int j = 0; j < elementSize; ++j )
129 PyObject *element = PySequence_GetItem( value, j );
132 PyErr_SetString( PyExc_TypeError, u
"Invalid type at index %1."_s.arg( i ) .toUtf8().constData() );
138 double d = PyFloat_AsDouble( element );
139 if ( PyErr_Occurred() )
150 if ( i == 0 && j == 2 )
156 else if ( i > 0 && j == 2 && hasZ )
161 if ( i == 0 && j == 3 )
167 else if ( i > 0 && j == 3 && hasM )
172 Py_DECREF( element );
175 if ( hasZ && elementSize < 3 )
176 zl.append( std::numeric_limits< double >::quiet_NaN() );
177 if ( hasM && elementSize < 4 )
178 ml.append( std::numeric_limits< double >::quiet_NaN() );
189 if ( sipCanConvertToType( value, sipType_QgsPointXY, SIP_NOT_NONE ) )
192 QgsPointXY *p =
reinterpret_cast<QgsPointXY *
>( sipConvertToType( value, sipType_QgsPointXY, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
198 sipReleaseType( p, sipType_QgsPointXY, state );
200 else if ( sipCanConvertToType( value, sipType_QgsPoint, SIP_NOT_NONE ) )
203 QgsPoint *p =
reinterpret_cast<QgsPoint *
>( sipConvertToType( value, sipType_QgsPoint, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
209 if ( i == 0 && p->
is3D() )
215 else if ( i > 0 && hasZ )
226 else if ( i > 0 && hasM )
234 sipReleaseType( p, sipType_QgsPoint, state );
246 PyErr_SetString( PyExc_TypeError, u
"Invalid type at index %1. Expected QgsPoint, QgsPointXY or array of floats."_s.arg( i ) .toUtf8().constData() );
252 sipCpp =
new sipQgsLineString(
QgsLineString( xl, yl, zl, ml, is25D ) );
281 QgsLineString(
const QVector<double> &x,
const QVector<double> &y,
282 const QVector<double> &z = QVector<double>(),
283 const QVector<double> &m = QVector<double>(),
bool is25DType =
false )
SIP_HOLDGIL;
308 static std::unique_ptr< QgsLineString >
fromQPolygonF(
const QPolygonF &polygon );
311 bool fuzzyHelper(
double epsilon,
315 std::function<
bool(
double,
double,
double,
double,
double,
double,
double,
double,
double )> comparator3DMeasure,
316 std::function<
bool(
double,
double,
double,
double,
double,
double,
double )> comparator3D,
317 std::function<
bool(
double,
double,
double,
double,
double,
double,
double )> comparatorMeasure,
318 std::function<
bool(
double,
double,
double,
double,
double )> comparator2D )
const
327 const int size = mX.count();
328 if ( size != otherLine->mX.count() )
332 const double *
xData = mX.constData();
333 const double *
yData = mY.constData();
334 const double *
zData = is3DFlag ? mZ.constData() :
nullptr;
335 const double *
mData = isMeasureFlag ? mM.constData() :
nullptr;
336 const double *otherXData = otherLine->mX.constData();
337 const double *otherYData = otherLine->mY.constData();
338 const double *otherZData = is3DFlag ? otherLine->mZ.constData() :
nullptr;
339 const double *otherMData = isMeasureFlag ? otherLine->mM.constData() :
nullptr;
340 for (
int i = 0; i < size; ++i )
342 if ( is3DFlag && isMeasureFlag )
345 *otherXData++, *otherYData++, *otherZData++, *otherMData++ );
350 *otherXData++, *otherYData++, *otherZData++ );
352 else if ( isMeasureFlag )
355 *otherXData++, *otherYData++, *otherMData++ );
359 result &= comparator2D( epsilon, *
xData++, *
yData++,
360 *otherXData++, *otherYData++ );
380 [](
double epsilon,
double x1,
double y1,
double z1,
double m1,
381 double x2,
double y2,
double z2,
double m2 )
385 [](
double epsilon,
double x1,
double y1,
double z1,
386 double x2,
double y2,
double z2 )
390 [](
double epsilon,
double x1,
double y1,
double m1,
391 double x2,
double y2,
double m2 )
395 [](
double epsilon,
double x1,
double y1,
396 double x2,
double y2 )
409 [](
double epsilon,
double x1,
double y1,
double z1,
double m1,
410 double x2,
double y2,
double z2,
double m2 )
414 [](
double epsilon,
double x1,
double y1,
double z1,
415 double x2,
double y2,
double z2 )
419 [](
double epsilon,
double x1,
double y1,
double m1,
420 double x2,
double y2,
double m2 )
424 [](
double epsilon,
double x1,
double y1,
425 double x2,
double y2 )
457 const int count = sipCpp->numPoints();
458 if ( a0 < -count || a0 >= count )
460 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
465 std::unique_ptr< QgsPoint > p;
467 p = std::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
469 p = std::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
470 sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
477 double xAt(
int index )
const override;
489 double xAt(
int index )
const override;
491 const int count = sipCpp->numPoints();
492 if ( a0 < -count || a0 >= count )
494 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
500 return PyFloat_FromDouble( sipCpp->xAt( a0 ) );
502 return PyFloat_FromDouble( sipCpp->xAt( count + a0 ) );
509 double yAt(
int index )
const override;
521 double yAt(
int index )
const override;
523 const int count = sipCpp->numPoints();
524 if ( a0 < -count || a0 >= count )
526 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
532 return PyFloat_FromDouble( sipCpp->yAt( a0 ) );
534 return PyFloat_FromDouble( sipCpp->yAt( count + a0 ) );
548 return mX.constData();
559 return mY.constData();
575 return mZ.constData();
591 return mM.constData();
644 double zAt(
int index )
const override
646 if ( index >= 0 && index < mZ.size() )
647 return mZ.at( index );
649 return std::numeric_limits<double>::quiet_NaN();
664 double zAt(
int index )
const override;
666 const int count = sipCpp->numPoints();
667 if ( a0 < -count || a0 >= count )
669 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
675 return PyFloat_FromDouble( sipCpp->zAt( a0 ) );
677 return PyFloat_FromDouble( sipCpp->zAt( count + a0 ) );
692 double mAt(
int index )
const override
694 if ( index >= 0 && index < mM.size() )
695 return mM.at( index );
697 return std::numeric_limits<double>::quiet_NaN();
712 double mAt(
int index )
const override;
714 const int count = sipCpp->numPoints();
715 if ( a0 < -count || a0 >= count )
717 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
723 return PyFloat_FromDouble( sipCpp->mAt( a0 ) );
725 return PyFloat_FromDouble( sipCpp->mAt( count + a0 ) );
740 void setXAt(
int index,
double x );
755 void setXAt(
int index,
double x );
757 const int count = sipCpp->numPoints();
758 if ( a0 < -count || a0 >= count )
760 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
766 sipCpp->setXAt( a0, a1 );
768 sipCpp->setXAt( count + a0, a1 );
783 void setYAt(
int index,
double y );
798 void setYAt(
int index,
double y );
800 const int count = sipCpp->numPoints();
801 if ( a0 < -count || a0 >= count )
803 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
809 sipCpp->setYAt( a0, a1 );
811 sipCpp->setYAt( count + a0, a1 );
828 if ( index >= 0 && index < mZ.size() )
844 void setZAt(
int index,
double z );
846 const int count = sipCpp->numPoints();
847 if ( a0 < -count || a0 >= count )
849 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
855 sipCpp->setZAt( a0, a1 );
857 sipCpp->setZAt( count + a0, a1 );
874 if ( index >= 0 && index < mM.size() )
890 void setMAt(
int index,
double m );
892 const int count = sipCpp->numPoints();
893 if ( a0 < -count || a0 >= count )
895 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
901 sipCpp->setMAt( a0, a1 );
903 sipCpp->setMAt( count + a0, a1 );
922 void setPoints(
size_t size,
const double *x,
const double *y,
const double *z =
nullptr,
const double *m =
nullptr )
SIP_SKIP;
935 void append( const QgsLineString *line );
941 void addVertex( const QgsPoint &pt );
950 QgsCompoundCurve *toCurveType() const override
SIP_FACTORY;
957 void extend(
double startDistance,
double endDistance );
967 double startSegmentX,
double startSegmentY,
double startSegmentZ,
double startSegmentM,
968 double endSegmentX,
double endSegmentY,
double endSegmentZ,
double endSegmentM
969 ) > &visitPoint )
const;
976 void clear() override;
978 int indexOf( const QgsPoint &point ) const final;
979 bool isValid( QString &error
SIP_OUT, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const override;
980 QgsLineString *snappedToGrid(
double hSpacing,
double vSpacing,
double dSpacing = 0,
double mSpacing = 0,
bool removeRedundantPoints = false ) const override
SIP_FACTORY;
981 bool removeDuplicateNodes(
double epsilon = 4 * std::numeric_limits<
double>::epsilon(),
bool useZValues = false ) override;
984 bool boundingBoxIntersects( const QgsRectangle &rectangle ) const override
SIP_HOLDGIL;
985 bool boundingBoxIntersects( const QgsBox3D &box3d ) const override
SIP_HOLDGIL;
994 QVector< QgsVertexId > collectDuplicateNodes(
double epsilon = 4 * std::numeric_limits<
double>::epsilon(),
bool useZValues = false ) const;
996 QPolygonF asQPolygonF() const override;
998 QgsLineString *simplifyByDistance(
double tolerance ) const override
SIP_FACTORY;
999 bool fromWkb( QgsConstWkbPtr &wkb ) override;
1000 bool fromWkt( const QString &wkt ) override;
1002 int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
1003 QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
1004 QString asWkt(
int precision = 17 ) const override;
1005 QDomElement asGml2( QDomDocument &doc,
int precision = 17, const QString &ns =
"gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
1006 QDomElement asGml3( QDomDocument &doc,
int precision = 17, const QString &ns =
"gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
1007 json asJsonObject(
int precision = 17 ) const override
SIP_SKIP;
1008 QString asKml(
int precision = 17 ) const override;
1014 std::tuple< std::unique_ptr< QgsCurve >, std::unique_ptr< QgsCurve > >
splitCurveAtVertex(
int index )
const final;
1025 QVector<QgsLineString *> splitToDisjointXYParts() const
SIP_FACTORY;
1043 QgsLineString *curveToLine(
double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override
SIP_FACTORY;
1049 void draw( QPainter &p ) const override;
1051 void transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection d = Qgis::TransformDirection::Forward,
bool transformZ = false ) override
SIP_THROW( QgsCsException );
1052 void transform( const QTransform &t,
double zTranslate = 0.0,
double zScale = 1.0,
double mTranslate = 0.0,
double mScale = 1.0 ) override;
1054 void addToPainterPath( QPainterPath &path ) const override;
1055 void drawAsPolygon( QPainter &p ) const override;
1057 bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
1058 bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
1059 bool deleteVertex( QgsVertexId position ) override;
1061 QgsLineString *reversed() const override
SIP_FACTORY;
1062 QgsPoint *interpolatePoint(
double distance ) const override
SIP_FACTORY;
1063 QgsLineString *curveSubstring(
double startDistance,
double endDistance ) const override
SIP_FACTORY;
1065 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;
1066 bool pointAt(
int node, QgsPoint &point, Qgis::VertexType &type ) const override;
1068 QgsPoint centroid() const override;
1080 void sumUpArea(
double &sum
SIP_OUT ) const override;
1092 void sumUpArea3D(
double &sum
SIP_OUT ) const override;
1094 double vertexAngle( QgsVertexId vertex ) const override;
1095 double segmentLength( QgsVertexId startVertex ) const override;
1096 double distanceBetweenVertices( QgsVertexId fromVertex, QgsVertexId toVertex ) const override;
1097 bool addZValue(
double zValue = 0 ) override;
1098 bool addMValue(
double mValue = 0 ) override;
1100 bool dropZValue() override;
1101 bool dropMValue() override;
1102 void swapXy() override;
1104 bool convertTo( Qgis::WkbType type ) override;
1106 bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback =
nullptr ) override;
1107 void scroll(
int firstVertexIndex ) final;
1110 void filterVertices(
const std::function<
bool(
const QgsPoint & ) > &filter )
override;
1111 void transformVertices(
const std::function< QgsPoint(
const QgsPoint & ) > &transform )
override;
1148 SIP_PYOBJECT __repr__();
1150 QString wkt = sipCpp->asWkt();
1151 if ( wkt.length() > 1000 )
1152 wkt = wkt.left( 1000 ) + u
"..."_s;
1153 QString str = u
"<QgsLineString: %1>"_s.arg( wkt );
1154 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
1168 const int count = sipCpp->numPoints();
1169 if ( a0 < -count || a0 >= count )
1171 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
1176 std::unique_ptr< QgsPoint > p;
1178 p = std::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
1180 p = std::make_unique< QgsPoint >( sipCpp->pointN( count + a0 ) );
1181 sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
1194 void __setitem__(
int index,
const QgsPoint &point );
1196 const int count = sipCpp->numPoints();
1197 if ( a0 < -count || a0 >= count )
1199 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
1206 sipCpp->setXAt( a0, a1->x() );
1207 sipCpp->setYAt( a0, a1->y() );
1208 if ( sipCpp->isMeasure() )
1209 sipCpp->setMAt( a0, a1->m() );
1210 if ( sipCpp->is3D() )
1211 sipCpp->setZAt( a0, a1->z() );
1225 void __delitem__(
int index );
1227 const int count = sipCpp->numPoints();
1228 if ( a0 >= 0 && a0 < count )
1229 sipCpp->deleteVertex( QgsVertexId( -1, -1, a0 ) );
1230 else if ( a0 < 0 && a0 >= -count )
1231 sipCpp->deleteVertex( QgsVertexId( -1, -1, count + a0 ) );
1234 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
1248 Q_DECL_DEPRECATED QgsBox3D calculateBoundingBox3d() const
SIP_DEPRECATED;
1255 QgsBox3D calculateBoundingBox3D() const override;
1263 std::unique_ptr< QgsLineString > measuredLine(
double start,
double end ) const;
1278 std::unique_ptr< QgsLineString > interpolateM(
bool use3DDistance = true ) const;
1304 bool lineLocatePointByM(
double m,
double &x
SIP_OUT,
double &y
SIP_OUT,
double &z
SIP_OUT,
double &distanceFromStart
SIP_OUT,
bool use3DDistance = true ) const;
1308 int compareToSameClass( const QgsAbstractGeometry *other ) const final;
1316 void importVerticesFromWkb( const QgsConstWkbPtr &wkb );
1323 void fromWkbPoints( Qgis::WkbType type, const QgsConstWkbPtr &wkb )
1326 importVerticesFromWkb( wkb );
1329 bool lineLocatePointByMPrivate(
double m,
double &x,
double &y,
double &z,
double &distanceFromStart,
bool use3DDistance,
bool haveInterpolatedM )
const;