Branch data Line data Source code
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 : :
37 : : /**
38 : : * \ingroup core
39 : : * \class QgsLineString
40 : : * \brief Line string geometry type, with support for z-dimension and m-values.
41 : : * \since QGIS 2.10
42 : : */
43 : 7089 : class CORE_EXPORT QgsLineString: public QgsCurve
44 : : {
45 : :
46 : : public:
47 : :
48 : : /**
49 : : * Constructor for an empty linestring geometry.
50 : : */
51 : : QgsLineString() SIP_HOLDGIL;
52 : :
53 : : /**
54 : : * Construct a linestring from a vector of points.
55 : : * Z and M type will be set based on the type of the first point
56 : : * in the vector.
57 : : * \since QGIS 3.0
58 : : */
59 : : QgsLineString( const QVector<QgsPoint> &points ) SIP_HOLDGIL;
60 : :
61 : : /**
62 : : * Construct a linestring from arrays of coordinates. If the z or m
63 : : * arrays are non-empty then the resultant linestring will have
64 : : * z and m types accordingly.
65 : : * This constructor is more efficient then calling setPoints()
66 : : * or repeatedly calling addVertex()
67 : : *
68 : : * If the \a z vector is filled, then the geometry type will either
69 : : * be a LineStringZ(M) or LineString25D depending on the \a is25DType
70 : : * argument. If \a is25DType is TRUE (and the \a m vector is unfilled) then
71 : : * the created Linestring will be a LineString25D type. Otherwise, the
72 : : * LineString will be LineStringZ (or LineStringZM) type.
73 : : *
74 : : * \since QGIS 3.0
75 : : */
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 : :
80 : : /**
81 : : * Constructs a linestring with a single segment from \a p1 to \a p2.
82 : : * \since QGIS 3.2
83 : : */
84 : : QgsLineString( const QgsPoint &p1, const QgsPoint &p2 ) SIP_HOLDGIL;
85 : :
86 : : /**
87 : : * Construct a linestring from list of points.
88 : : * This constructor is more efficient then calling setPoints()
89 : : * or repeatedly calling addVertex()
90 : : * \since QGIS 3.0
91 : : */
92 : : QgsLineString( const QVector<QgsPointXY> &points ) SIP_HOLDGIL;
93 : :
94 : : /**
95 : : * Construct a linestring from a single 2d line segment.
96 : : * \since QGIS 3.2
97 : : */
98 : : explicit QgsLineString( const QgsLineSegment2D &segment ) SIP_HOLDGIL;
99 : :
100 : : /**
101 : : * Returns a new linestring created by segmentizing the bezier curve between \a start and \a end, with
102 : : * the specified control points.
103 : : *
104 : : * The \a segments parameter controls how many line segments will be present in the returned linestring.
105 : : *
106 : : * Any z or m values present in the input coordinates will be interpolated along with the x and y values.
107 : : *
108 : : * \since QGIS 3.10
109 : : */
110 : : static QgsLineString *fromBezierCurve( const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments = 30 ) SIP_FACTORY;
111 : :
112 : : /**
113 : : * Returns a new linestring from a QPolygonF \a polygon input.
114 : : *
115 : : * \since QGIS 3.10
116 : : */
117 : : static QgsLineString *fromQPolygonF( const QPolygonF &polygon ) SIP_FACTORY;
118 : :
119 : : bool equals( const QgsCurve &other ) const override;
120 : :
121 : : #ifndef SIP_RUN
122 : :
123 : : /**
124 : : * Returns the specified point from inside the line string.
125 : : * \param i index of point, starting at 0 for the first point
126 : : */
127 : : QgsPoint pointN( int i ) const;
128 : : #else
129 : :
130 : : /**
131 : : * Returns the point at the specified index. An IndexError will be raised if no point with the specified index exists.
132 : : *
133 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
134 : : * corresponds to the last point in the line.
135 : : */
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 : :
160 : : /**
161 : : * Returns the x-coordinate of the specified node in the line string.
162 : : *
163 : : * An IndexError will be raised if no point with the specified index exists.
164 : : *
165 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
166 : : * corresponds to the last point in the line.
167 : : */
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 : :
190 : : /**
191 : : * Returns the y-coordinate of the specified node in the line string.
192 : : *
193 : : * An IndexError will be raised if no point with the specified index exists.
194 : : *
195 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
196 : : * corresponds to the last point in the line.
197 : : */
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 : :
216 : : /**
217 : : * Returns a const pointer to the x vertex data.
218 : : * \note Not available in Python bindings
219 : : * \see yData()
220 : : * \since QGIS 3.2
221 : : */
222 : 101069 : const double *xData() const SIP_SKIP
223 : : {
224 : 101069 : return mX.constData();
225 : : }
226 : :
227 : : /**
228 : : * Returns a const pointer to the y vertex data.
229 : : * \note Not available in Python bindings
230 : : * \see xData()
231 : : * \since QGIS 3.2
232 : : */
233 : 101069 : const double *yData() const SIP_SKIP
234 : : {
235 : 101069 : return mY.constData();
236 : : }
237 : :
238 : : /**
239 : : * Returns a const pointer to the z vertex data, or NULLPTR if the linestring does
240 : : * not have z values.
241 : : * \note Not available in Python bindings
242 : : * \see xData()
243 : : * \see yData()
244 : : * \since QGIS 3.2
245 : : */
246 : 73 : const double *zData() const SIP_SKIP
247 : : {
248 : 73 : if ( mZ.empty() )
249 : 0 : return nullptr;
250 : : else
251 : 73 : return mZ.constData();
252 : 73 : }
253 : :
254 : : /**
255 : : * Returns a const pointer to the m vertex data, or NULLPTR if the linestring does
256 : : * not have m values.
257 : : * \note Not available in Python bindings
258 : : * \see xData()
259 : : * \see yData()
260 : : * \since QGIS 3.2
261 : : */
262 : 3 : const double *mData() const SIP_SKIP
263 : : {
264 : 3 : if ( mM.empty() )
265 : 0 : return nullptr;
266 : : else
267 : 3 : return mM.constData();
268 : 3 : }
269 : :
270 : : #ifndef SIP_RUN
271 : :
272 : : /**
273 : : * Returns the z-coordinate of the specified node in the line string.
274 : : * \param index index of node, where the first node in the line is 0
275 : : * \returns z-coordinate of node, or ``nan`` if index is out of bounds or the line
276 : : * does not have a z dimension
277 : : * \see setZAt()
278 : : */
279 : 31 : double zAt( int index ) const
280 : : {
281 : 31 : if ( index >= 0 && index < mZ.size() )
282 : 27 : return mZ.at( index );
283 : : else
284 : 4 : return std::numeric_limits<double>::quiet_NaN();
285 : 31 : }
286 : : #else
287 : :
288 : : /**
289 : : * Returns the z-coordinate of the specified node in the line string.
290 : : *
291 : : * An IndexError will be raised if no point with the specified index exists.
292 : : *
293 : : * If the LineString does not have a z-dimension then ``nan`` will be returned.
294 : : *
295 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
296 : : * corresponds to the last point in the line.
297 : : */
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 : :
318 : : /**
319 : : * Returns the m value of the specified node in the line string.
320 : : * \param index index of node, where the first node in the line is 0
321 : : * \returns m value of node, or ``nan`` if index is out of bounds or the line
322 : : * does not have m values
323 : : * \see setMAt()
324 : : */
325 : 22 : double mAt( int index ) const
326 : : {
327 : 22 : if ( index >= 0 && index < mM.size() )
328 : 18 : return mM.at( index );
329 : : else
330 : 4 : return std::numeric_limits<double>::quiet_NaN();
331 : 22 : }
332 : : #else
333 : :
334 : : /**
335 : : * Returns the m-coordinate of the specified node in the line string.
336 : : *
337 : : * An IndexError will be raised if no point with the specified index exists.
338 : : *
339 : : * If the LineString does not have a m-dimension then ``nan`` will be returned.
340 : : *
341 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
342 : : * corresponds to the last point in the line.
343 : : */
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 : :
364 : : /**
365 : : * Sets the x-coordinate of the specified node in the line string.
366 : : * \param index index of node, where the first node in the line is 0. Corresponding
367 : : * node must already exist in line string.
368 : : * \param x x-coordinate of node
369 : : * \see xAt()
370 : : */
371 : : void setXAt( int index, double x );
372 : : #else
373 : :
374 : : /**
375 : : * Sets the x-coordinate of the specified node in the line string.
376 : : * The corresponding node must already exist in line string.
377 : : *
378 : : * An IndexError will be raised if no point with the specified index exists.
379 : : *
380 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
381 : : * corresponds to the last point in the line.
382 : : *
383 : : * \see xAt()
384 : : */
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 : :
405 : : /**
406 : : * Sets the y-coordinate of the specified node in the line string.
407 : : * \param index index of node, where the first node in the line is 0. Corresponding
408 : : * node must already exist in line string.
409 : : * \param y y-coordinate of node
410 : : * \see yAt()
411 : : */
412 : : void setYAt( int index, double y );
413 : : #else
414 : :
415 : : /**
416 : : * Sets the y-coordinate of the specified node in the line string.
417 : : * The corresponding node must already exist in line string.
418 : : *
419 : : * An IndexError will be raised if no point with the specified index exists.
420 : : *
421 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
422 : : * corresponds to the last point in the line.
423 : : *
424 : : * \see yAt()
425 : : */
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 : :
446 : : /**
447 : : * Sets the z-coordinate of the specified node in the line string.
448 : : * \param index index of node, where the first node in the line is 0. Corresponding
449 : : * node must already exist in line string, and the line string must have z-dimension.
450 : : * \param z z-coordinate of node
451 : : * \see zAt()
452 : : */
453 : 7 : void setZAt( int index, double z )
454 : : {
455 : 7 : if ( index >= 0 && index < mZ.size() )
456 : 3 : mZ[ index ] = z;
457 : 7 : }
458 : : #else
459 : :
460 : : /**
461 : : * Sets the z-coordinate of the specified node in the line string.
462 : : * The corresponding node must already exist in line string and the line string must have z-dimension.
463 : : *
464 : : * An IndexError will be raised if no point with the specified index exists.
465 : : *
466 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
467 : : * corresponds to the last point in the line.
468 : : *
469 : : * \see zAt()
470 : : */
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 : :
491 : : /**
492 : : * Sets the m value of the specified node in the line string.
493 : : * \param index index of node, where the first node in the line is 0. Corresponding
494 : : * node must already exist in line string, and the line string must have m values.
495 : : * \param m m value of node
496 : : * \see mAt()
497 : : */
498 : 7 : void setMAt( int index, double m )
499 : : {
500 : 7 : if ( index >= 0 && index < mM.size() )
501 : 3 : mM[ index ] = m;
502 : 7 : }
503 : : #else
504 : :
505 : : /**
506 : : * Sets the m-coordinate of the specified node in the line string.
507 : : * The corresponding node must already exist in line string and the line string must have m-dimension.
508 : : *
509 : : * An IndexError will be raised if no point with the specified index exists.
510 : : *
511 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
512 : : * corresponds to the last point in the line.
513 : : *
514 : : * \see mAt()
515 : : */
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 : :
534 : : /**
535 : : * Resets the line string to match the specified list of points. The line string will
536 : : * inherit the dimensionality of the first point in the list.
537 : : * \param points new points for line string. If empty, line string will be cleared.
538 : : */
539 : : void setPoints( const QgsPointSequence &points );
540 : :
541 : : /**
542 : : * Appends the contents of another line string to the end of this line string.
543 : : * \param line line to append. Ownership is not transferred.
544 : : */
545 : : void append( const QgsLineString *line );
546 : :
547 : : /**
548 : : * Adds a new vertex to the end of the line string.
549 : : * \param pt vertex to add
550 : : */
551 : : void addVertex( const QgsPoint &pt );
552 : :
553 : : //! Closes the line string by appending the first point to the end of the line, if it is not already closed.
554 : : void close();
555 : :
556 : : /**
557 : : * Returns the geometry converted to the more generic curve type QgsCompoundCurve
558 : : * \returns the converted geometry. Caller takes ownership
559 : : */
560 : : QgsCompoundCurve *toCurveType() const override SIP_FACTORY;
561 : :
562 : : /**
563 : : * Extends the line geometry by extrapolating out the start or end of the line
564 : : * by a specified distance. Lines are extended using the bearing of the first or last
565 : : * segment in the line.
566 : : * \since QGIS 3.0
567 : : */
568 : : void extend( double startDistance, double endDistance );
569 : :
570 : : #ifndef SIP_RUN
571 : :
572 : : /**
573 : : * Visits regular points along the linestring, spaced by \a distance.
574 : : *
575 : : * The \a visitPoint function should return FALSE to abort further traversal.
576 : : */
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 : :
596 : : /**
597 : : * Returns a list of any duplicate nodes contained in the geometry, within the specified tolerance.
598 : : *
599 : : * If \a useZValues is TRUE then z values will also be considered when testing for duplicates.
600 : : *
601 : : * \since QGIS 3.16
602 : : */
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 : :
621 : : /**
622 : : * Returns the length in 3D world of the line string.
623 : : * If it is not a 3D line string, return its 2D length.
624 : : * \see length()
625 : : * \since QGIS 3.10
626 : : */
627 : : double length3D() const SIP_HOLDGIL;
628 : : QgsPoint startPoint() const override SIP_HOLDGIL;
629 : : QgsPoint endPoint() const override SIP_HOLDGIL;
630 : :
631 : : /**
632 : : * Returns a new line string geometry corresponding to a segmentized approximation
633 : : * of the curve.
634 : : * \param tolerance segmentation tolerance
635 : : * \param toleranceType maximum segmentation angle or maximum difference between approximation and curve
636 : : */
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 : :
682 : : /**
683 : : * Cast the \a geom to a QgsLineString.
684 : : * Should be used by qgsgeometry_cast<QgsLineString *>( geometry ).
685 : : *
686 : : * \note Not available in Python. Objects will be automatically be converted to the appropriate target type.
687 : : * \since QGIS 3.0
688 : : */
689 : 103077 : inline static const QgsLineString *cast( const QgsAbstractGeometry *geom )
690 : : {
691 : 103077 : if ( geom && QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::LineString )
692 : 102844 : return static_cast<const QgsLineString *>( geom );
693 : 233 : return nullptr;
694 : 103077 : }
695 : : #endif
696 : :
697 : : QgsLineString *createEmptyWithSameType() const override SIP_FACTORY;
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 : :
709 : : /**
710 : : * Returns the point at the specified ``index``. An IndexError will be raised if no point with the specified ``index`` exists.
711 : : *
712 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
713 : : * corresponds to the last point in the line.
714 : : *
715 : : * \since QGIS 3.6
716 : : */
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 : :
736 : : /**
737 : : * Sets the point at the specified ``index``. A point at the ``index`` must already exist or an IndexError will be raised.
738 : : *
739 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
740 : : * corresponds to the last point in the line.
741 : : *
742 : : * \since QGIS 3.6
743 : : */
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 : :
766 : : /**
767 : : * Deletes the vertex at the specified ``index``. A point at the ``index`` must already exist or an IndexError will be raised.
768 : : *
769 : : * Indexes can be less than 0, in which case they correspond to positions from the end of the line. E.g. an index of -1
770 : : * corresponds to the last point in the line.
771 : : *
772 : : * \since QGIS 3.6
773 : : */
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 : :
802 : : /**
803 : : * Resets the line string to match the line string in a WKB geometry.
804 : : * \param type WKB type
805 : : * \param wkb WKB representation of line geometry
806 : : */
807 : 22 : void fromWkbPoints( QgsWkbTypes::Type type, const QgsConstWkbPtr &wkb )
808 : : {
809 : 22 : mWkbType = type;
810 : 22 : importVerticesFromWkb( wkb );
811 : 22 : }
812 : :
813 : : friend class QgsPolygon;
814 : : friend class QgsTriangle;
815 : :
816 : : };
817 : :
818 : : // clazy:excludeall=qstring-allocations
819 : :
820 : : #endif // QGSLINESTRING_H
|