QGIS API Documentation  3.21.0-Master (56b4176581)
qgspoint.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointv2.cpp
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 
19 #include "qgspoint.h"
20 #include "qgsapplication.h"
21 #include "qgscoordinatetransform.h"
22 #include "qgsgeometryutils.h"
23 #include "qgsmaptopixel.h"
24 #include "qgswkbptr.h"
25 #include "qgsgeometrytransformer.h"
26 
27 #include <cmath>
28 #include <QPainter>
29 #include <QPainterPath>
30 #include <QRegularExpression>
31 #include <QJsonObject>
32 #include <QJsonArray>
33 #include <nlohmann/json.hpp>
34 
35 /***************************************************************************
36  * This class is considered CRITICAL and any change MUST be accompanied with
37  * full unit tests.
38  * See details in QEP #17
39  ****************************************************************************/
40 
41 QgsPoint::QgsPoint( double x, double y, double z, double m, QgsWkbTypes::Type wkbType )
42  : mX( x )
43  , mY( y )
44  , mZ( z )
45  , mM( m )
46 {
48  {
50  mWkbType = wkbType;
51  }
52  else if ( std::isnan( z ) )
53  {
54  if ( std::isnan( m ) )
56  else
58  }
59  else if ( std::isnan( m ) )
61  else
63 }
64 
66  : mX( p.x() )
67  , mY( p.y() )
68  , mZ( std::numeric_limits<double>::quiet_NaN() )
69  , mM( std::numeric_limits<double>::quiet_NaN() )
70 {
72  if ( p.isEmpty() )
73  {
74  mX = std::numeric_limits<double>::quiet_NaN();
75  mY = std::numeric_limits<double>::quiet_NaN();
76  }
77 }
78 
79 QgsPoint::QgsPoint( QPointF p )
80  : mX( p.x() )
81  , mY( p.y() )
82  , mZ( std::numeric_limits<double>::quiet_NaN() )
83  , mM( std::numeric_limits<double>::quiet_NaN() )
84 {
86 }
87 
88 QgsPoint::QgsPoint( QgsWkbTypes::Type wkbType, double x, double y, double z, double m )
89  : mX( x )
90  , mY( y )
91  , mZ( QgsWkbTypes::hasZ( wkbType ) ? z : std::numeric_limits<double>::quiet_NaN() )
92  , mM( QgsWkbTypes::hasM( wkbType ) ? m : std::numeric_limits<double>::quiet_NaN() )
93 {
95  mWkbType = wkbType;
96 }
97 
98 /***************************************************************************
99  * This class is considered CRITICAL and any change MUST be accompanied with
100  * full unit tests.
101  * See details in QEP #17
102  ****************************************************************************/
103 
105 {
106  return new QgsPoint( *this );
107 }
108 
109 QgsPoint *QgsPoint::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing ) const
110 {
111  // helper function
112  auto gridifyValue = []( double value, double spacing, bool extraCondition = true ) -> double
113  {
114  if ( spacing > 0 && extraCondition )
115  return std::round( value / spacing ) * spacing;
116  else
117  return value;
118  };
119 
120  // Get the new values
121  const auto x = gridifyValue( mX, hSpacing );
122  const auto y = gridifyValue( mY, vSpacing );
123  const auto z = gridifyValue( mZ, dSpacing, QgsWkbTypes::hasZ( mWkbType ) );
124  const auto m = gridifyValue( mM, mSpacing, QgsWkbTypes::hasM( mWkbType ) );
125 
126  // return the new object
127  return new QgsPoint( mWkbType, x, y, z, m );
128 }
129 
130 bool QgsPoint::removeDuplicateNodes( double, bool )
131 {
132  return false;
133 }
134 
136 {
137  const QgsWkbTypes::Type type = wkbPtr.readHeader();
138  if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::Point )
139  {
140  clear();
141  return false;
142  }
143  mWkbType = type;
144 
145  wkbPtr >> mX;
146  wkbPtr >> mY;
147  if ( is3D() )
148  wkbPtr >> mZ;
149  if ( isMeasure() )
150  wkbPtr >> mM;
151 
152  clearCache();
153 
154  return true;
155 }
156 
157 /***************************************************************************
158  * This class is considered CRITICAL and any change MUST be accompanied with
159  * full unit tests.
160  * See details in QEP #17
161  ****************************************************************************/
162 
163 bool QgsPoint::fromWkt( const QString &wkt )
164 {
165  clear();
166 
167  QPair<QgsWkbTypes::Type, QString> parts = QgsGeometryUtils::wktReadBlock( wkt );
168 
170  return false;
171  mWkbType = parts.first;
172 
173  QString secondWithoutParentheses = parts.second;
174  secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' );
175  parts.second = parts.second.remove( '(' ).remove( ')' );
176  if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
177  secondWithoutParentheses.isEmpty() )
178  return true;
179 
180  const QRegularExpression rx( QStringLiteral( "\\s" ) );
181 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
182  QStringList coordinates = parts.second.split( rx, QString::SkipEmptyParts );
183 #else
184  QStringList coordinates = parts.second.split( rx, Qt::SkipEmptyParts );
185 #endif
186 
187  // So far the parser hasn't looked at the coordinates. We'll avoid having anything but numbers and return NULL instead of 0 as a coordinate.
188  // Without this check, "POINT (a, b)" or "POINT (( 4, 3 ))" returned "POINT (0 ,0)"
189  // And some strange conversion...
190  // .. python:
191  // p = QgsPoint()
192  // p.fromWkt("POINT (-3.12, -4.2")
193  // False
194  // p.fromWkt( "POINT (-5.1234, -1.4321)" )
195  // True
196  // p.asWkt()
197  // 'Point (0 -1.43209999999999993)'
198  const QRegularExpression rxIsNumber( QStringLiteral( "^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$" ) );
199  if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() )
200  return false;
201 
202  if ( coordinates.size() < 2 )
203  {
204  clear();
205  return false;
206  }
207  else if ( coordinates.size() == 3 && !is3D() && !isMeasure() )
208  {
209  // 3 dimensional coordinates, but not specifically marked as such. We allow this
210  // anyway and upgrade geometry to have Z dimension
212  }
213  else if ( coordinates.size() >= 4 && ( !is3D() || !isMeasure() ) )
214  {
215  // 4 (or more) dimensional coordinates, but not specifically marked as such. We allow this
216  // anyway and upgrade geometry to have Z&M dimensions
219  }
220 
221  int idx = 0;
222  mX = coordinates[idx++].toDouble();
223  mY = coordinates[idx++].toDouble();
224  if ( is3D() && coordinates.length() > 2 )
225  mZ = coordinates[idx++].toDouble();
226  if ( isMeasure() && coordinates.length() > 2 + is3D() )
227  mM = coordinates[idx++].toDouble();
228 
229  return true;
230 }
231 
232 /***************************************************************************
233  * This class is considered CRITICAL and any change MUST be accompanied with
234  * full unit tests.
235  * See details in QEP #17
236  ****************************************************************************/
237 
238 int QgsPoint::wkbSize( WkbFlags ) const
239 {
240  int binarySize = sizeof( char ) + sizeof( quint32 );
241  binarySize += ( 2 + is3D() + isMeasure() ) * sizeof( double );
242  return binarySize;
243 }
244 
245 QByteArray QgsPoint::asWkb( WkbFlags flags ) const
246 {
247  QByteArray wkbArray;
248  wkbArray.resize( QgsPoint::wkbSize( flags ) );
249  QgsWkbPtr wkb( wkbArray );
250  wkb << static_cast<char>( QgsApplication::endian() );
251  wkb << static_cast<quint32>( wkbType() );
252  wkb << mX << mY;
253  if ( is3D() )
254  {
255  wkb << mZ;
256  }
257  if ( isMeasure() )
258  {
259  wkb << mM;
260  }
261  return wkbArray;
262 }
263 
264 QString QgsPoint::asWkt( int precision ) const
265 {
266  QString wkt = wktTypeStr();
267 
268  if ( isEmpty() )
269  wkt += QLatin1String( " EMPTY" );
270  else
271  {
272  wkt += QLatin1String( " (" );
273  wkt += qgsDoubleToString( mX, precision ) + ' ' + qgsDoubleToString( mY, precision );
274  if ( is3D() )
275  wkt += ' ' + qgsDoubleToString( mZ, precision );
276  if ( isMeasure() )
277  wkt += ' ' + qgsDoubleToString( mM, precision );
278  wkt += ')';
279  }
280  return wkt;
281 }
282 
283 QDomElement QgsPoint::asGml2( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
284 {
285  QDomElement elemPoint = doc.createElementNS( ns, QStringLiteral( "Point" ) );
286  QDomElement elemCoordinates = doc.createElementNS( ns, QStringLiteral( "coordinates" ) );
287 
288  // coordinate separator
289  const QString cs = QStringLiteral( "," );
290  // tuple separator
291  const QString ts = QStringLiteral( " " );
292 
293  elemCoordinates.setAttribute( QStringLiteral( "cs" ), cs );
294  elemCoordinates.setAttribute( QStringLiteral( "ts" ), ts );
295 
296  QString strCoordinates;
297  if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
298  strCoordinates = qgsDoubleToString( mX, precision ) + cs + qgsDoubleToString( mY, precision );
299  else
300  strCoordinates = qgsDoubleToString( mY, precision ) + cs + qgsDoubleToString( mX, precision );
301  elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
302  elemPoint.appendChild( elemCoordinates );
303  return elemPoint;
304 }
305 
306 QDomElement QgsPoint::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
307 {
308  QDomElement elemPoint = doc.createElementNS( ns, QStringLiteral( "Point" ) );
309  QDomElement elemPosList = doc.createElementNS( ns, QStringLiteral( "pos" ) );
310  elemPosList.setAttribute( QStringLiteral( "srsDimension" ), is3D() ? 3 : 2 );
311  QString strCoordinates;
312  if ( axisOrder == QgsAbstractGeometry::AxisOrder::XY )
313  strCoordinates = qgsDoubleToString( mX, precision ) + ' ' + qgsDoubleToString( mY, precision );
314  else
315  strCoordinates = qgsDoubleToString( mY, precision ) + ' ' + qgsDoubleToString( mX, precision );
316  if ( is3D() )
317  strCoordinates += ' ' + qgsDoubleToString( mZ, precision );
318 
319  elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
320  elemPoint.appendChild( elemPosList );
321  return elemPoint;
322 }
323 
324 
326 {
327  json j
328  {
329  { "type", "Point" },
330  { "coordinates", json::array() },
331  };
332  if ( ! isEmpty() )
333  {
334  j["coordinates"].push_back( qgsRound( mX, precision ) );
335  j["coordinates"].push_back( qgsRound( mY, precision ) );
336  if ( is3D() )
337  {
338  j["coordinates"].push_back( qgsRound( mZ, precision ) );
339  }
340  }
341  return j;
342 }
343 
344 QString QgsPoint::asKml( int precision ) const
345 {
346  return QStringLiteral( "<Point><coordinates>%1,%2</coordinates></Point>" ).arg( qgsDoubleToString( mX, precision ), qgsDoubleToString( mY, precision ) );
347 }
348 
349 void QgsPoint::draw( QPainter &p ) const
350 {
351  p.drawRect( QRectF( mX - 2, mY - 2, 4, 4 ) );
352 }
353 
354 QPainterPath QgsPoint::asQPainterPath() const
355 {
356  return QPainterPath();
357 }
358 
360 {
361  mX = mY = std::numeric_limits<double>::quiet_NaN();
362  if ( is3D() )
363  mZ = 0.;
364  else
365  mZ = std::numeric_limits<double>::quiet_NaN();
366 
367  if ( isMeasure() )
368  mM = 0.;
369  else
370  mM = std::numeric_limits<double>::quiet_NaN();
371 
372  clearCache();
373 }
374 
375 
376 /***************************************************************************
377  * This class is considered CRITICAL and any change MUST be accompanied with
378  * full unit tests.
379  * See details in QEP #17
380  ****************************************************************************/
381 
383 {
384  clearCache();
385  if ( transformZ )
386  {
387  ct.transformInPlace( mX, mY, mZ, d );
388  }
389  else
390  {
391  double z = 0.0;
392  ct.transformInPlace( mX, mY, z, d );
393  }
394 }
395 
397 {
399 
400  cs.append( QgsRingSequence() );
401  cs.back().append( QgsPointSequence() << QgsPoint( *this ) );
402 
403  return cs;
404 }
405 
407 {
408  return 1;
409 }
410 
412 {
413  if ( id.vertex != 0 )
414  return -1;
415  else
416  return 0;
417 }
418 
420 {
421  return nullptr;
422 }
423 
424 bool QgsPoint::isValid( QString &, Qgis::GeometryValidityFlags ) const
425 {
426  return true;
427 }
428 
429 bool QgsPoint::insertVertex( QgsVertexId position, const QgsPoint &vertex )
430 {
431  Q_UNUSED( position )
432  Q_UNUSED( vertex )
433  return false;
434 }
435 
436 /***************************************************************************
437  * This class is considered CRITICAL and any change MUST be accompanied with
438  * full unit tests.
439  * See details in QEP #17
440  ****************************************************************************/
441 
442 bool QgsPoint::moveVertex( QgsVertexId position, const QgsPoint &newPos )
443 {
444  Q_UNUSED( position )
445  clearCache();
446  mX = newPos.mX;
447  mY = newPos.mY;
448  if ( is3D() && newPos.is3D() )
449  {
450  mZ = newPos.mZ;
451  }
452  if ( isMeasure() && newPos.isMeasure() )
453  {
454  mM = newPos.mM;
455  }
456  return true;
457 }
458 
460 {
461  Q_UNUSED( position )
462  return false;
463 }
464 
465 double QgsPoint::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
466 {
467  Q_UNUSED( pt )
468  Q_UNUSED( segmentPt )
469  Q_UNUSED( vertexAfter )
470  if ( leftOf )
471  *leftOf = 0;
472  Q_UNUSED( epsilon )
473  return -1; // no segments - return error
474 }
475 
476 bool QgsPoint::nextVertex( QgsVertexId &id, QgsPoint &vertex ) const
477 {
478  if ( id.vertex < 0 )
479  {
480  id.vertex = 0;
481  if ( id.part < 0 )
482  {
483  id.part = 0;
484  }
485  if ( id.ring < 0 )
486  {
487  id.ring = 0;
488  }
489  vertex = *this;
490  return true;
491  }
492  else
493  {
494  return false;
495  }
496 }
497 
498 void QgsPoint::adjacentVertices( QgsVertexId, QgsVertexId &previousVertex, QgsVertexId &nextVertex ) const
499 {
500  previousVertex = QgsVertexId();
502 }
503 
504 double QgsPoint::vertexAngle( QgsVertexId vertex ) const
505 {
506  Q_UNUSED( vertex )
507  return 0.0;
508 }
509 
510 int QgsPoint::vertexCount( int, int ) const
511 {
512  return 1;
513 }
514 
515 int QgsPoint::ringCount( int ) const
516 {
517  return 1;
518 }
519 
521 {
522  return 1;
523 }
524 
526 {
527  return *this;
528 }
529 
531 {
532  return clone();
533 }
534 
536 {
537  return 0.0;
538 }
539 
540 bool QgsPoint::boundingBoxIntersects( const QgsRectangle &rectangle ) const
541 {
542  return rectangle.contains( mX, mY );
543 }
544 
545 /***************************************************************************
546  * This class is considered CRITICAL and any change MUST be accompanied with
547  * full unit tests.
548  * See details in QEP #17
549  ****************************************************************************/
550 
551 bool QgsPoint::addZValue( double zValue )
552 {
553  if ( QgsWkbTypes::hasZ( mWkbType ) )
554  return false;
555 
557  mZ = zValue;
558  clearCache();
559  return true;
560 }
561 
562 bool QgsPoint::addMValue( double mValue )
563 {
564  if ( QgsWkbTypes::hasM( mWkbType ) )
565  return false;
566 
568  mM = mValue;
569  clearCache();
570  return true;
571 }
572 
573 void QgsPoint::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
574 {
575  clearCache();
576  qreal x, y;
577  t.map( mX, mY, &x, &y );
578  mX = x;
579  mY = y;
580 
581  if ( is3D() )
582  {
583  mZ = mZ * zScale + zTranslate;
584  }
585  if ( isMeasure() )
586  {
587  mM = mM * mScale + mTranslate;
588  }
589 }
590 
591 
593 {
594  if ( !is3D() )
595  return false;
596 
598  mZ = std::numeric_limits<double>::quiet_NaN();
599  clearCache();
600  return true;
601 }
602 
604 {
605  if ( !isMeasure() )
606  return false;
607 
609  mM = std::numeric_limits<double>::quiet_NaN();
610  clearCache();
611  return true;
612 }
613 
615 {
616  std::swap( mX, mY );
617  clearCache();
618 }
619 
621 {
622  if ( type == mWkbType )
623  return true;
624 
625  clearCache();
626 
627  switch ( type )
628  {
629  case QgsWkbTypes::Point:
630  mZ = std::numeric_limits<double>::quiet_NaN();
631  mM = std::numeric_limits<double>::quiet_NaN();
632  mWkbType = type;
633  return true;
634  case QgsWkbTypes::PointZ:
636  mM = std::numeric_limits<double>::quiet_NaN();
637  mWkbType = type;
638  return true;
639  case QgsWkbTypes::PointM:
640  mZ = std::numeric_limits<double>::quiet_NaN();
641  mWkbType = type;
642  return true;
644  mWkbType = type;
645  return true;
646  default:
647  break;
648  }
649 
650  return false;
651 }
652 
654 {
655  if ( !transformer )
656  return false;
657 
658  const bool res = transformer->transformPoint( mX, mY, mZ, mM );
659  clearCache();
660  return res;
661 }
662 
663 void QgsPoint::filterVertices( const std::function<bool ( const QgsPoint & )> & )
664 {
665  // no meaning for points
666 }
667 
668 void QgsPoint::transformVertices( const std::function<QgsPoint( const QgsPoint & )> &transform )
669 {
670  const QgsPoint res = transform( *this );
671  mX = res.x();
672  mY = res.y();
673  if ( is3D() )
674  mZ = res.z();
675  if ( isMeasure() )
676  mM = res.m();
677  clearCache();
678 }
679 
680 double QgsPoint::distance3D( double x, double y, double z ) const
681 {
682  double zDistSquared = 0.0;
683  if ( is3D() || !std::isnan( z ) )
684  zDistSquared = ( mZ - z ) * ( mZ - z );
685 
686  return std::sqrt( ( mX - x ) * ( mX - x ) + ( mY - y ) * ( mY - y ) + zDistSquared );
687 }
688 
689 double QgsPoint::distance3D( const QgsPoint &other ) const
690 {
691  double zDistSquared = 0.0;
692  if ( is3D() || other.is3D() )
693  zDistSquared = ( mZ - other.z() ) * ( mZ - other.z() );
694 
695  return std::sqrt( ( mX - other.x() ) * ( mX - other.x() ) + ( mY - other.y() ) * ( mY - other.y() ) + zDistSquared );
696 }
697 
698 double QgsPoint::distanceSquared3D( double x, double y, double z ) const
699 {
700  double zDistSquared = 0.0;
701  if ( is3D() || !std::isnan( z ) )
702  zDistSquared = ( mZ - z ) * ( mZ - z );
703 
704  return ( mX - x ) * ( mX - x ) + ( mY - y ) * ( mY - y ) + zDistSquared;
705 }
706 
707 double QgsPoint::distanceSquared3D( const QgsPoint &other ) const
708 {
709  double zDistSquared = 0.0;
710  if ( is3D() || other.is3D() )
711  zDistSquared = ( mZ - other.z() ) * ( mZ - other.z() );
712 
713  return ( mX - other.x() ) * ( mX - other.x() ) + ( mY - other.y() ) * ( mY - other.y() ) + zDistSquared;
714 }
715 
716 double QgsPoint::azimuth( const QgsPoint &other ) const
717 {
718  const double dx = other.x() - mX;
719  const double dy = other.y() - mY;
720  return ( std::atan2( dx, dy ) * 180.0 / M_PI );
721 }
722 
723 double QgsPoint::inclination( const QgsPoint &other ) const
724 {
725  const double distance = distance3D( other );
726  if ( qgsDoubleNear( distance, 0.0 ) )
727  {
728  return 90.0;
729  }
730  const double dz = other.z() - mZ;
731 
732  return ( std::acos( dz / distance ) * 180.0 / M_PI );
733 }
734 
735 QgsPoint QgsPoint::project( double distance, double azimuth, double inclination ) const
736 {
737  QgsWkbTypes::Type pType = mWkbType;
738  const double radsXy = azimuth * M_PI / 180.0;
739  double dx = 0.0, dy = 0.0, dz = 0.0;
740 
741  inclination = std::fmod( inclination, 360.0 );
742 
743  if ( !qgsDoubleNear( inclination, 90.0 ) )
744  pType = QgsWkbTypes::addZ( pType );
745 
746  if ( !is3D() && qgsDoubleNear( inclination, 90.0 ) )
747  {
748  dx = distance * std::sin( radsXy );
749  dy = distance * std::cos( radsXy );
750  }
751  else
752  {
753  const double radsZ = inclination * M_PI / 180.0;
754  dx = distance * std::sin( radsZ ) * std::sin( radsXy );
755  dy = distance * std::sin( radsZ ) * std::cos( radsXy );
756  dz = distance * std::cos( radsZ );
757  }
758 
759  return QgsPoint( mX + dx, mY + dy, mZ + dz, mM, pType );
760 }
761 
763 {
764  // nothing to do
765 }
766 
767 bool QgsPoint::isEmpty() const
768 {
769  return std::isnan( mX ) || std::isnan( mY );
770 }
771 
773 {
774  return QgsRectangle( mX, mY, mX, mY );
775 }
776 
777 QString QgsPoint::geometryType() const
778 {
779  return QStringLiteral( "Point" );
780 }
781 
783 {
784  return 0;
785 }
786 
788 {
789  return 1;
790 }
791 
792 QgsPoint QgsPoint::childPoint( int index ) const
793 {
794  Q_ASSERT( index == 0 );
795  return *this;
796 }
797 
799 {
800  const double nan = std::numeric_limits<double>::quiet_NaN();
801  return new QgsPoint( nan, nan, nan, nan, mWkbType );
802 }
803 
805 {
806  const QgsPoint *otherPoint = qgsgeometry_cast< const QgsPoint * >( other );
807  if ( !otherPoint )
808  return -1;
809 
810  if ( mX < otherPoint->mX )
811  {
812  return -1;
813  }
814  else if ( mX > otherPoint->mX )
815  {
816  return 1;
817  }
818 
819  if ( mY < otherPoint->mY )
820  {
821  return -1;
822  }
823  else if ( mY > otherPoint->mY )
824  {
825  return 1;
826  }
827 
828  if ( is3D() && !otherPoint->is3D() )
829  return 1;
830  else if ( !is3D() && otherPoint->is3D() )
831  return -1;
832  else if ( is3D() && otherPoint->is3D() )
833  {
834  if ( mZ < otherPoint->mZ )
835  {
836  return -1;
837  }
838  else if ( mZ > otherPoint->mZ )
839  {
840  return 1;
841  }
842  }
843 
844  if ( isMeasure() && !otherPoint->isMeasure() )
845  return 1;
846  else if ( !isMeasure() && otherPoint->isMeasure() )
847  return -1;
848  else if ( isMeasure() && otherPoint->isMeasure() )
849  {
850  if ( mM < otherPoint->mM )
851  {
852  return -1;
853  }
854  else if ( mM > otherPoint->mM )
855  {
856  return 1;
857  }
858  }
859 
860  return 0;
861 }
TransformDirection
Indicates the direction (forward or inverse) of a transform.
Definition: qgis.h:880
An abstract base class for classes which transform geometries by transforming input points to output ...
virtual bool transformPoint(double &x, double &y, double &z, double &m)=0
Transforms the point defined by the coordinates (x, y, z) and the specified m value.
Abstract base class for all geometries.
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
AxisOrder
Axis order for GML generation.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
virtual void clearCache() const
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
QgsWkbTypes::Type mWkbType
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
static endian_t endian()
Returns whether this machine uses big or little endian.
A const WKB pointer.
Definition: qgswkbptr.h:138
QgsWkbTypes::Type readHeader() const
readHeader
Definition: qgswkbptr.cpp:54
Class for doing transforms between two map coordinate systems.
void transformInPlace(double &x, double &y, double &z, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transforms an array of x, y and z double coordinates in place, from the source CRS to the destination...
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
static QPair< QgsWkbTypes::Type, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
A class to represent a 2D point.
Definition: qgspointxy.h:59
bool isEmpty() const SIP_HOLDGIL
Returns true if the geometry is empty.
Definition: qgspointxy.h:249
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
int wkbSize(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns the length of the QByteArray returned by asWkb()
Definition: qgspoint.cpp:238
double distance(double x, double y) const SIP_HOLDGIL
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
Definition: qgspoint.h:343
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
Definition: qgspoint.cpp:135
void filterVertices(const std::function< bool(const QgsPoint &) > &filter) override
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
Definition: qgspoint.cpp:663
QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
Definition: qgspoint.cpp:396
double vertexAngle(QgsVertexId vertex) const override
Angle undefined.
Definition: qgspoint.cpp:504
void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
Definition: qgspoint.cpp:382
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
Definition: qgspoint.cpp:306
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
Definition: qgspoint.cpp:562
QPainterPath asQPainterPath() const override
Returns the geometry represented as a QPainterPath.
Definition: qgspoint.cpp:354
QByteArray asWkb(QgsAbstractGeometry::WkbFlags=QgsAbstractGeometry::WkbFlags()) const override
Definition: qgspoint.cpp:245
void clear() override
Clears the geometry, ie reset it to a null geometry.
Definition: qgspoint.cpp:359
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
Definition: qgspoint.cpp:163
bool dropMValue() override
Drops any measure values which exist in the geometry.
Definition: qgspoint.cpp:603
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
Definition: qgspoint.cpp:429
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
Definition: qgspoint.cpp:767
void adjacentVertices(QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex) const override
Returns the vertices adjacent to a specified vertex within a geometry.
Definition: qgspoint.cpp:498
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override SIP_HOLDGIL
Checks validity of the geometry, and returns true if the geometry is valid.
Definition: qgspoint.cpp:424
int dimension() const override SIP_HOLDGIL
Returns the inherent dimension of the geometry.
Definition: qgspoint.cpp:782
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
Definition: qgspoint.cpp:551
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
Definition: qgspoint.cpp:419
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
Definition: qgspoint.cpp:349
QgsPoint * toCurveType() const override
Returns the geometry converted to the more generic curve type.
Definition: qgspoint.cpp:530
QgsPoint project(double distance, double azimuth, double inclination=90.0) const SIP_HOLDGIL
Returns a new point which corresponds to this point projected by a specified distance with specified ...
Definition: qgspoint.cpp:735
double distance3D(double x, double y, double z) const SIP_HOLDGIL
Returns the Cartesian 3D distance between this point and a specified x, y, z coordinate.
Definition: qgspoint.cpp:680
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition: qgspoint.cpp:264
QgsPoint childPoint(int index) const override
Returns point at index (for geometries without child geometries - i.e.
Definition: qgspoint.cpp:792
Q_GADGET double x
Definition: qgspoint.h:52
bool convertTo(QgsWkbTypes::Type type) override
Converts the geometry to a specified type.
Definition: qgspoint.cpp:620
bool boundingBoxIntersects(const QgsRectangle &rectangle) const override SIP_HOLDGIL
Returns true if the bounding box of this geometry intersects with a rectangle.
Definition: qgspoint.cpp:540
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspoint.cpp:104
double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *std::numeric_limits< double >::epsilon()) const override
Searches for the closest segment of the geometry to a given point.
Definition: qgspoint.cpp:465
int ringCount(int=0) const override
Returns the number of rings of which this geometry is built.
Definition: qgspoint.cpp:515
int nCoordinates() const override SIP_HOLDGIL
Returns the number of nodes contained in the geometry.
Definition: qgspoint.cpp:406
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
Definition: qgspoint.cpp:283
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
Definition: qgspoint.cpp:525
QgsPoint * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
Definition: qgspoint.cpp:798
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
Definition: qgspoint.cpp:442
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
Definition: qgspoint.cpp:459
double z
Definition: qgspoint.h:54
QgsRectangle boundingBox() const override SIP_HOLDGIL
Returns the minimal bounding box for the geometry.
Definition: qgspoint.cpp:772
double distanceSquared3D(double x, double y, double z) const SIP_HOLDGIL
Returns the Cartesian 3D squared distance between this point and a specified x, y,...
Definition: qgspoint.cpp:698
void transformVertices(const std::function< QgsPoint(const QgsPoint &) > &transform) override
Transforms the vertices from the geometry in place, applying the transform function to every vertex.
Definition: qgspoint.cpp:668
QgsPoint * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
Definition: qgspoint.cpp:109
int compareToSameClass(const QgsAbstractGeometry *other) const final
Compares to an other geometry of the same class, and returns a integer for sorting of the two geometr...
Definition: qgspoint.cpp:804
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
Definition: qgspoint.cpp:411
int childCount() const override
Returns number of child geometries (for geometries with child geometries) or child points (for geomet...
Definition: qgspoint.cpp:787
QString geometryType() const override SIP_HOLDGIL
Returns a unique string representing the geometry type.
Definition: qgspoint.cpp:777
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
Definition: qgspoint.cpp:325
double & rx()
Returns a reference to the x-coordinate of this point.
Definition: qgspoint.h:246
int vertexCount(int=0, int=0) const override
Returns the number of vertices of which this geometry is built.
Definition: qgspoint.cpp:510
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)
Construct a point with the provided initial coordinate values.
Definition: qgspoint.cpp:41
void swapXy() override
Swaps the x and y coordinates from the geometry.
Definition: qgspoint.cpp:614
void normalize() final SIP_HOLDGIL
Reorganizes the geometry into a normalized form (or "canonical" form).
Definition: qgspoint.cpp:762
double azimuth(const QgsPoint &other) const SIP_HOLDGIL
Calculates Cartesian azimuth between this point and other one (clockwise in degree,...
Definition: qgspoint.cpp:716
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
Definition: qgspoint.cpp:535
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
Definition: qgspoint.cpp:592
double m
Definition: qgspoint.h:55
double y
Definition: qgspoint.h:53
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
Definition: qgspoint.cpp:476
int partCount() const override
Returns count of parts contained in the geometry.
Definition: qgspoint.cpp:520
double inclination(const QgsPoint &other) const SIP_HOLDGIL
Calculates Cartesian inclination between this point and other one (starting from zenith = 0 to nadir ...
Definition: qgspoint.cpp:723
QString asKml(int precision=17) const override
Returns a KML representation of the geometry.
Definition: qgspoint.cpp:344
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
Definition: qgspoint.cpp:130
A rectangle specified with double values.
Definition: qgsrectangle.h:42
bool contains(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:363
WKB pointer handler.
Definition: qgswkbptr.h:44
Handles storage of information regarding WKB types and their properties.
Definition: qgswkbtypes.h:42
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1100
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static Type dropZ(Type type) SIP_HOLDGIL
Drops the z dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:1207
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:702
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1146
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1050
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1171
static Type dropM(Type type) SIP_HOLDGIL
Drops the m dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:1225
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 ...
Definition: MathUtils.cpp:292
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:1085
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
Definition: qgis.h:1187
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:1133
QVector< QgsRingSequence > QgsCoordinateSequence
QVector< QgsPointSequence > QgsRingSequence
QVector< QgsPoint > QgsPointSequence
int precision
Utility class for identifying a unique vertex within a geometry.