1 /*************************************************************************** 2 qgspointv2.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 QGSPOINT_H 19 #define QGSPOINT_H 20 21 #include "qgis_core.h" 22 #include "qgis_sip.h" 23 #include "qgsabstractgeometry.h" 24 #include "qgsrectangle.h" 25 26 /*************************************************************************** 27 * This class is considered CRITICAL and any change MUST be accompanied with 28 * full unit tests in testqgsgeometry.cpp. 29 * See details in QEP #17 30 ****************************************************************************/ 31 32 /** 33 * \ingroup core 34 * \brief Point geometry type, with support for z-dimension and m-values. 35 * 36 * A QgsPoint represents a 2, 3 or 4-dimensional position, with X and Y and optional 37 * Z or M coordinates. Since it supports these additional dimensions, QgsPoint is 38 * used as the low-level storage of geometry coordinates throughout QGIS. 39 * 40 * In some scenarios it is preferable to use the QgsPointXY class instead, which is 41 * lighter and has smaller memory requirements compared to QgsPoint. See the QgsPointXY 42 * documentation for examples of situations where it is appropriate to use QgsPointXY 43 * instead of QgsPoint. 44 * 45 * \see QgsPointXY 46 * \since QGIS 3.0, (previously QgsPointV2 since QGIS 2.10) 47 */ 48 class CORE_EXPORT QgsPoint: public QgsAbstractGeometry 49 { 50 Q_GADGET 51 52 Q_PROPERTY( double x READ x WRITE setX ) 53 Q_PROPERTY( double y READ y WRITE setY ) 54 Q_PROPERTY( double z READ z WRITE setZ ) 55 Q_PROPERTY( double m READ m WRITE setM ) 56 57 public: 58 59 /** 60 * Construct a point with the provided initial coordinate values. 61 * 62 * If \a wkbType is set to `QgsWkbTypes::Point`, `QgsWkbTypes::PointZ`, `QgsWkbTypes::PointM` or `QgsWkbTypes::PointZM` 63 * the type will be set accordingly. If it is left to the default `QgsWkbTypes::Unknown`, the type will be set 64 * based on the following rules: 65 * 66 * - If only x and y are specified, the type will be a 2D point. 67 * - If any or both of the Z and M are specified, the appropriate type will be created. 68 * 69 * \code{.py} 70 * pt = QgsPoint(43.4, 5.3) 71 * pt.asWkt() # Point(43.4 5.3) 72 * 73 * pt_z = QgsPoint(120, 343, 77) 74 * pt_z.asWkt() # PointZ(120 343 77) 75 * 76 * pt_m = QgsPoint(33, 88, m=5) 77 * pt_m.m() # 5 78 * pt_m.wkbType() # 2001 (QgsWkbTypes.PointM) 79 * 80 * pt = QgsPoint(30, 40, wkbType=QgsWkbTypes.PointZ) 81 * pt.z() # nan 82 * pt.wkbType() # 1001 (QgsWkbTypes.PointZ) 83 * \endcode 84 */ 85 #ifndef SIP_RUN 86 QgsPoint( double x = std::numeric_limits<double>::quiet_NaN(), double y = std::numeric_limits<double>::quiet_NaN(), double z = std::numeric_limits<double>::quiet_NaN(), double m = std::numeric_limits<double>::quiet_NaN(), QgsWkbTypes::Type wkbType = QgsWkbTypes::Unknown ); 87 #else 88 QgsPoint( SIP_PYOBJECT x SIP_TYPEHINT( Optional[Union[QgsPoint, QPointF, float]] ) = Py_None, SIP_PYOBJECT y SIP_TYPEHINT( Optional[float] ) = Py_None, SIP_PYOBJECT z SIP_TYPEHINT( Optional[float] ) = Py_None, SIP_PYOBJECT m SIP_TYPEHINT( Optional[float] ) = Py_None, SIP_PYOBJECT wkbType SIP_TYPEHINT( Optional[int] ) = Py_None ) [( double x = 0.0, double y = 0.0, double z = 0.0, double m = 0.0, QgsWkbTypes::Type wkbType = QgsWkbTypes::Unknown )]; 89 % MethodCode 90 if ( sipCanConvertToType( a0, sipType_QgsPointXY, SIP_NOT_NONE ) && a1 == Py_None && a2 == Py_None && a3 == Py_None && a4 == Py_None ) 91 { 92 int state; 93 sipIsErr = 0; 94 95 QgsPointXY *p = reinterpret_cast<QgsPointXY *>( sipConvertToType( a0, sipType_QgsPointXY, 0, SIP_NOT_NONE, &state, &sipIsErr ) ); 96 if ( sipIsErr ) 97 { 98 sipReleaseType( p, sipType_QgsPointXY, state ); 99 } 100 else 101 { 102 sipCpp = new sipQgsPoint( QgsPoint( *p ) ); 103 } 104 } 105 else if ( sipCanConvertToType( a0, sipType_QPointF, SIP_NOT_NONE ) && a1 == Py_None && a2 == Py_None && a3 == Py_None && a4 == Py_None ) 106 { 107 int state; 108 sipIsErr = 0; 109 110 QPointF *p = reinterpret_cast<QPointF *>( sipConvertToType( a0, sipType_QPointF, 0, SIP_NOT_NONE, &state, &sipIsErr ) ); 111 if ( sipIsErr ) 112 { 113 sipReleaseType( p, sipType_QPointF, state ); 114 } 115 else 116 { 117 sipCpp = new sipQgsPoint( QgsPoint( *p ) ); 118 } 119 } 120 else if ( 121 ( a0 == Py_None || PyFloat_AsDouble( a0 ) != -1.0 || !PyErr_Occurred() ) && 122 ( a1 == Py_None || PyFloat_AsDouble( a1 ) != -1.0 || !PyErr_Occurred() ) && 123 ( a2 == Py_None || PyFloat_AsDouble( a2 ) != -1.0 || !PyErr_Occurred() ) && 124 ( a3 == Py_None || PyFloat_AsDouble( a3 ) != -1.0 || !PyErr_Occurred() ) ) 125 { 126 double x = a0 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a0 ); 127 double y = a1 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a1 ); 128 double z = a2 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a2 ); 129 double m = a3 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a3 ); 130 QgsWkbTypes::Type wkbType = a4 == Py_None ? QgsWkbTypes::Unknown : static_cast<QgsWkbTypes::Type>( sipConvertToEnum( a4, sipType_QgsWkbTypes_Type ) ); 131 sipCpp = new sipQgsPoint( QgsPoint( x, y, z, m, wkbType ) ); 132 } 133 else // Invalid ctor arguments 134 { 135 PyErr_SetString( PyExc_TypeError, QStringLiteral( "Invalid type in constructor arguments." ).toUtf8().constData() ); 136 sipIsErr = 1; 137 } 138 % End 139 #endif 140 141 /** 142 * Construct a QgsPoint from a QgsPointXY object 143 */ 144 explicit QgsPoint( const QgsPointXY &p ) SIP_SKIP; 145 146 /** 147 * Construct a QgsPoint from a QPointF 148 */ 149 explicit QgsPoint( QPointF p ) SIP_SKIP; 150 151 /** 152 * Create a new point with the given wkbtype and values. 153 * 154 * \note Not available in Python bindings 155 */ 156 explicit QgsPoint( QgsWkbTypes::Type wkbType, double x = std::numeric_limits<double>::quiet_NaN(), double y = std::numeric_limits<double>::quiet_NaN(), double z = std::numeric_limits<double>::quiet_NaN(), double m = std::numeric_limits<double>::quiet_NaN() ) SIP_SKIP; 157 158 bool operator==( const QgsAbstractGeometry &other ) const override SIP_HOLDGIL 159 { 160 const QgsPoint *pt = qgsgeometry_cast< const QgsPoint * >( &other ); 161 if ( !pt ) 162 return false; 163 164 const QgsWkbTypes::Type type = wkbType(); 165 166 if ( pt->wkbType() != type ) 167 return false; 168 169 const bool nan1X = std::isnan( mX ); 170 const bool nan2X = std::isnan( pt->x() ); 171 if ( nan1X != nan2X ) 172 return false; 173 if ( !nan1X && !qgsDoubleNear( mX, pt->x(), 1E-8 ) ) 174 return false; 175 176 const bool nan1Y = std::isnan( mY ); 177 const bool nan2Y = std::isnan( pt->y() ); 178 if ( nan1Y != nan2Y ) 179 return false; 180 if ( !nan1Y && !qgsDoubleNear( mY, pt->y(), 1E-8 ) ) 181 return false; 182 183 if ( QgsWkbTypes::hasZ( type ) ) 184 { 185 const bool nan1Z = std::isnan( mZ ); 186 const bool nan2Z = std::isnan( pt->z() ); 187 if ( nan1Z != nan2Z ) 188 return false; 189 if ( !nan1Z && !qgsDoubleNear( mZ, pt->z(), 1E-8 ) ) 190 return false; 191 } 192 193 if ( QgsWkbTypes::hasM( type ) ) 194 { 195 const bool nan1M = std::isnan( mM ); 196 const bool nan2M = std::isnan( pt->m() ); 197 if ( nan1M != nan2M ) 198 return false; 199 if ( !nan1M && !qgsDoubleNear( mM, pt->m(), 1E-8 ) ) 200 return false; 201 } 202 203 return true; 204 } 205 206 bool operator!=( const QgsAbstractGeometry &other ) const override SIP_HOLDGIL 207 { 208 return !operator==( other ); 209 } 210 211 /** 212 * Returns the point's x-coordinate. 213 * \see setX() 214 * \see rx() 215 */ x()216 double x() const SIP_HOLDGIL { return mX; } 217 218 /** 219 * Returns the point's y-coordinate. 220 * \see setY() 221 * \see ry() 222 */ y()223 double y() const SIP_HOLDGIL { return mY; } 224 225 /** 226 * Returns the point's z-coordinate. 227 * \see setZ() 228 * \see rz() 229 */ z()230 double z() const SIP_HOLDGIL { return mZ; } 231 232 /** 233 * Returns the point's m value. 234 * \see setM() 235 * \see rm() 236 */ m()237 double m() const SIP_HOLDGIL { return mM; } 238 239 /** 240 * Returns a reference to the x-coordinate of this point. 241 * Using a reference makes it possible to directly manipulate x in place. 242 * \see x() 243 * \see setX() 244 * \note not available in Python bindings 245 */ rx()246 double &rx() SIP_SKIP { clearCache(); return mX; } 247 248 /** 249 * Returns a reference to the y-coordinate of this point. 250 * Using a reference makes it possible to directly manipulate y in place. 251 * \see y() 252 * \see setY() 253 * \note not available in Python bindings 254 */ ry()255 double &ry() SIP_SKIP { clearCache(); return mY; } 256 257 /** 258 * Returns a reference to the z-coordinate of this point. 259 * Using a reference makes it possible to directly manipulate z in place. 260 * \see z() 261 * \see setZ() 262 * \note not available in Python bindings 263 */ rz()264 double &rz() SIP_SKIP { clearCache(); return mZ; } 265 266 /** 267 * Returns a reference to the m value of this point. 268 * Using a reference makes it possible to directly manipulate m in place. 269 * \see m() 270 * \see setM() 271 * \note not available in Python bindings 272 */ rm()273 double &rm() SIP_SKIP { clearCache(); return mM; } 274 275 /** 276 * Sets the point's x-coordinate. 277 * \see x() 278 * \see rx() 279 */ setX(double x)280 void setX( double x ) SIP_HOLDGIL 281 { 282 clearCache(); 283 mX = x; 284 } 285 286 /** 287 * Sets the point's y-coordinate. 288 * \see y() 289 * \see ry() 290 */ setY(double y)291 void setY( double y ) SIP_HOLDGIL 292 { 293 clearCache(); 294 mY = y; 295 } 296 297 /** 298 * Sets the point's z-coordinate. 299 * \note calling this will have no effect if the point does not contain a z-dimension. Use addZValue() to 300 * add a z value and force the point to have a z dimension. 301 * \see z() 302 * \see rz() 303 */ setZ(double z)304 void setZ( double z ) SIP_HOLDGIL 305 { 306 if ( !is3D() ) 307 return; 308 clearCache(); 309 mZ = z; 310 } 311 312 /** 313 * Sets the point's m-value. 314 * \note calling this will have no effect if the point does not contain a m-dimension. Use addMValue() to 315 * add a m value and force the point to have an m dimension. 316 * \see m() 317 * \see rm() 318 */ setM(double m)319 void setM( double m ) SIP_HOLDGIL 320 { 321 if ( !isMeasure() ) 322 return; 323 clearCache(); 324 mM = m; 325 } 326 327 /** 328 * Returns the point as a QPointF. 329 * \since QGIS 2.14 330 */ toQPointF()331 QPointF toQPointF() const SIP_HOLDGIL 332 { 333 return QPointF( mX, mY ); 334 } 335 336 /** 337 * Returns the Cartesian 2D distance between this point and a specified x, y coordinate. In certain 338 * cases it may be more appropriate to call the faster distanceSquared() method, e.g., 339 * when comparing distances. 340 * \see distanceSquared() 341 * \since QGIS 3.0 342 */ distance(double x,double y)343 double distance( double x, double y ) const SIP_HOLDGIL 344 { 345 return std::sqrt( ( mX - x ) * ( mX - x ) + ( mY - y ) * ( mY - y ) ); 346 } 347 348 /** 349 * Returns the Cartesian 2D distance between this point and another point. In certain 350 * cases it may be more appropriate to call the faster distanceSquared() method, e.g., 351 * when comparing distances. 352 * \see distanceSquared() 353 * \since QGIS 3.0 354 */ distance(const QgsPoint & other)355 double distance( const QgsPoint &other ) const SIP_HOLDGIL 356 { 357 return std::sqrt( ( mX - other.x() ) * ( mX - other.x() ) + ( mY - other.y() ) * ( mY - other.y() ) ); 358 } 359 360 /** 361 * Returns the Cartesian 2D squared distance between this point a specified x, y coordinate. Calling 362 * this is faster than calling distance(), and may be useful in use cases such as comparing 363 * distances where the extra expense of calling distance() is not required. 364 * \see distance() 365 * \since QGIS 3.0 366 */ distanceSquared(double x,double y)367 double distanceSquared( double x, double y ) const SIP_HOLDGIL 368 { 369 return ( mX - x ) * ( mX - x ) + ( mY - y ) * ( mY - y ); 370 } 371 372 /** 373 * Returns the Cartesian 2D squared distance between this point another point. Calling 374 * this is faster than calling distance(), and may be useful in use cases such as comparing 375 * distances where the extra expense of calling distance() is not required. 376 * \see distance() 377 * \since QGIS 3.0 378 */ distanceSquared(const QgsPoint & other)379 double distanceSquared( const QgsPoint &other ) const SIP_HOLDGIL 380 { 381 return ( mX - other.x() ) * ( mX - other.x() ) + ( mY - other.y() ) * ( mY - other.y() ); 382 } 383 384 /** 385 * Returns the Cartesian 3D distance between this point and a specified x, y, z coordinate. In certain 386 * cases it may be more appropriate to call the faster distanceSquared3D() method, e.g., 387 * when comparing distances. 388 * \see distanceSquared3D() 389 * \since QGIS 3.0 390 */ 391 double distance3D( double x, double y, double z ) const SIP_HOLDGIL; 392 393 /** 394 * Returns the Cartesian 3D distance between this point and another point. In certain 395 * cases it may be more appropriate to call the faster distanceSquared3D() method, e.g., 396 * when comparing distances. 397 * \see distanceSquared3D() 398 * \since QGIS 3.0 399 */ 400 double distance3D( const QgsPoint &other ) const SIP_HOLDGIL; 401 402 /** 403 * Returns the Cartesian 3D squared distance between this point and a specified x, y, z coordinate. Calling 404 * this is faster than calling distance3D(), and may be useful in use cases such as comparing 405 * distances where the extra expense of calling distance3D() is not required. 406 * \see distance3D() 407 * \since QGIS 3.0 408 */ 409 double distanceSquared3D( double x, double y, double z ) const SIP_HOLDGIL; 410 411 /** 412 * Returns the Cartesian 3D squared distance between this point and another point. Calling 413 * this is faster than calling distance3D(), and may be useful in use cases such as comparing 414 * distances where the extra expense of calling distance3D() is not required. 415 * \see distance3D() 416 * \since QGIS 3.0 417 */ 418 double distanceSquared3D( const QgsPoint &other ) const SIP_HOLDGIL; 419 420 /** 421 * Calculates Cartesian azimuth between this point and other one (clockwise in degree, starting from north) 422 * \since QGIS 3.0 423 */ 424 double azimuth( const QgsPoint &other ) const SIP_HOLDGIL; 425 426 /** 427 * Calculates Cartesian inclination between this point and other one (starting from zenith = 0 to nadir = 180. Horizon = 90) 428 * Returns 90.0 if the distance between this point and other one is equal to 0 (same point). 429 * \since QGIS 3.0 430 */ 431 double inclination( const QgsPoint &other ) const SIP_HOLDGIL; 432 433 /** 434 * Returns a new point which corresponds to this point projected by a specified distance 435 * with specified angles (azimuth and inclination), using Cartesian mathematics. 436 * M value is preserved. 437 * \param distance distance to project 438 * \param azimuth angle to project in X Y, clockwise in degrees starting from north 439 * \param inclination angle to project in Z (3D). If the point is 2D, the Z value is assumed to be 0. 440 * \returns The point projected. If a 2D point is projected a 3D point will be returned except if 441 * inclination is 90. A 3D point is always returned if a 3D point is projected. 442 * 443 * ### Example 444 * 445 * \code{.py} 446 * p = QgsPoint( 1, 2 ) # 2D point 447 * pr = p.project ( 1, 0 ) 448 * # pr is a 2D point: 'Point (1 3)' 449 * pr = p.project ( 1, 0, 90 ) 450 * # pr is a 2D point: 'Point (1 3)' 451 * pr = p.project (1, 0, 0 ) 452 * # pr is a 3D point: 'PointZ (1 2 nan)' 453 * p = QgsPoint( 1, 2, 2, wkbType=QgsWkbTypes.PointZ ) # 3D point 454 * pr = p.project ( 1, 0 ) 455 * # pr is a 3D point: 'PointZ (1 3 2)' 456 * pr = p.project ( 1, 0, 90 ) 457 * # pr is a 3D point: 'PointZ (1 3 2)' 458 * pr = p.project (1, 0, 0 ) 459 * # pr is a 3D point: 'PointZ (1 2 3)' 460 * \endcode 461 * \since QGIS 3.0 462 */ 463 QgsPoint project( double distance, double azimuth, double inclination = 90.0 ) const SIP_HOLDGIL; 464 465 /** 466 * Calculates the vector obtained by subtracting a point from this point. 467 * \since QGIS 3.0 468 */ 469 QgsVector operator-( const QgsPoint &p ) const SIP_HOLDGIL { return QgsVector( mX - p.mX, mY - p.mY ); } 470 471 /** 472 * Adds a vector to this point in place. 473 * \since QGIS 3.0 474 */ 475 QgsPoint &operator+=( QgsVector v ) SIP_HOLDGIL { mX += v.x(); mY += v.y(); return *this; } 476 477 /** 478 * Subtracts a vector from this point in place. 479 * \since QGIS 3.0 480 */ 481 QgsPoint &operator-=( QgsVector v ) SIP_HOLDGIL { mX -= v.x(); mY -= v.y(); return *this; } 482 483 /** 484 * Adds a vector to this point. 485 * \since QGIS 3.0 486 */ 487 QgsPoint operator+( QgsVector v ) const SIP_HOLDGIL { QgsPoint r = *this; r.rx() += v.x(); r.ry() += v.y(); return r; } 488 489 /** 490 * Subtracts a vector from this point. 491 * \since QGIS 3.0 492 */ 493 QgsPoint operator-( QgsVector v ) const SIP_HOLDGIL { QgsPoint r = *this; r.rx() -= v.x(); r.ry() -= v.y(); return r; } 494 495 //implementation of inherited methods 496 void normalize() final SIP_HOLDGIL; 497 bool isEmpty() const override SIP_HOLDGIL; 498 QgsRectangle boundingBox() const override SIP_HOLDGIL; 499 QString geometryType() const override SIP_HOLDGIL; 500 int dimension() const override SIP_HOLDGIL; 501 QgsPoint *clone() const override SIP_FACTORY; 502 QgsPoint *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const override SIP_FACTORY; 503 bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override; 504 void clear() override; 505 bool fromWkb( QgsConstWkbPtr &wkb ) override; 506 bool fromWkt( const QString &wkt ) override; 507 int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override; 508 QByteArray asWkb( QgsAbstractGeometry::WkbFlags = QgsAbstractGeometry::WkbFlags() ) const override; 509 QString asWkt( int precision = 17 ) const override; 510 QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override; 511 QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override; 512 json asJsonObject( int precision = 17 ) const override SIP_SKIP; 513 QString asKml( int precision = 17 ) const override; 514 void draw( QPainter &p ) const override; 515 QPainterPath asQPainterPath() const override; 516 void transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection d = Qgis::TransformDirection::Forward, bool transformZ = false ) override SIP_THROW( QgsCsException ); 517 void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override; 518 QgsCoordinateSequence coordinateSequence() const override; 519 int nCoordinates() const override SIP_HOLDGIL; 520 int vertexNumberFromVertexId( QgsVertexId id ) const override; 521 QgsAbstractGeometry *boundary() const override SIP_FACTORY; 522 bool isValid( QString &error SIP_OUT, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const override SIP_HOLDGIL; 523 524 //low-level editing 525 bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override; 526 bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override; 527 bool deleteVertex( QgsVertexId position ) override; 528 529 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; 530 bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const override; 531 void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const override; 532 533 /** 534 * Angle undefined. Always returns 0.0 535 * \param vertex the vertex id 536 * \returns 0.0 537 */ 538 double vertexAngle( QgsVertexId vertex ) const override; 539 540 int vertexCount( int /*part*/ = 0, int /*ring*/ = 0 ) const override; 541 int ringCount( int /*part*/ = 0 ) const override; 542 int partCount() const override; 543 QgsPoint vertexAt( QgsVertexId /*id*/ ) const override; 544 QgsPoint *toCurveType() const override SIP_FACTORY; 545 double segmentLength( QgsVertexId startVertex ) const override; 546 bool boundingBoxIntersects( const QgsRectangle &rectangle ) const override SIP_HOLDGIL; 547 548 bool addZValue( double zValue = 0 ) override; 549 bool addMValue( double mValue = 0 ) override; 550 bool dropZValue() override; 551 bool dropMValue() override; 552 void swapXy() override; 553 bool convertTo( QgsWkbTypes::Type type ) override; 554 555 bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) override; 556 557 #ifndef SIP_RUN 558 559 void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override; 560 void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override; 561 562 /** 563 * Cast the \a geom to a QgsPoint. 564 * Should be used by qgsgeometry_cast<QgsPoint *>( geometry ). 565 * 566 * \note Not available in Python. Objects will be automatically be converted to the appropriate target type. 567 * \since QGIS 3.0 568 */ cast(const QgsAbstractGeometry * geom)569 inline static const QgsPoint *cast( const QgsAbstractGeometry *geom ) 570 { 571 if ( geom && QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::Point ) 572 return static_cast<const QgsPoint *>( geom ); 573 return nullptr; 574 } 575 #endif 576 577 QgsPoint *createEmptyWithSameType() const override SIP_FACTORY; 578 579 #ifdef SIP_RUN 580 SIP_PYOBJECT __repr__(); 581 % MethodCode 582 QString str = QStringLiteral( "<QgsPoint: %1>" ).arg( sipCpp->asWkt() ); 583 sipRes = PyUnicode_FromString( str.toUtf8().constData() ); 584 % End 585 #endif 586 587 protected: 588 589 int compareToSameClass( const QgsAbstractGeometry *other ) const final; 590 int childCount() const override; 591 QgsPoint childPoint( int index ) const override; 592 593 private: 594 double mX; 595 double mY; 596 double mZ; 597 double mM; 598 }; 599 600 // clazy:excludeall=qstring-allocations 601 602 #endif // QGSPOINT_H 603