QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 thread_local 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 thread_local 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 }
qgsgeometrytransformer.h
QgsPoint::partCount
int partCount() const override
Returns count of parts contained in the geometry.
Definition: qgspoint.cpp:520
QgsCoordinateSequence
QVector< QgsRingSequence > QgsCoordinateSequence
Definition: qgsabstractgeometry.h:57
QgsPoint::asGml3
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
QgsCoordinateTransform::transformInPlace
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...
Definition: qgscoordinatetransform.cpp:364
QgsPoint::ringCount
int ringCount(int=0) const override
Returns the number of rings of which this geometry is built.
Definition: qgspoint.cpp:515
QgsPoint::asJsonObject
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
Definition: qgspoint.cpp:325
QgsWkbTypes::dropM
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:1255
QgsAbstractGeometry::clearCache
virtual void clearCache() const
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
Definition: qgsabstractgeometry.cpp:146
QgsWkbTypes::Point
@ Point
Definition: qgswkbtypes.h:72
QgsPoint::QgsPoint
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
QgsPoint::isValid
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
QgsPoint::geometryType
QString geometryType() const override SIP_HOLDGIL
Returns a unique string representing the geometry type.
Definition: qgspoint.cpp:777
QgsPoint::vertexAt
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
Definition: qgspoint.cpp:525
QgsPoint::fromWkb
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
Definition: qgspoint.cpp:135
QgsPoint::distance
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:360
QgsWkbTypes::Point25D
@ Point25D
Definition: qgswkbtypes.h:125
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
qgswkbptr.h
QgsPoint::addZValue
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
Definition: qgspoint.cpp:551
QgsPoint::asWkt
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition: qgspoint.cpp:264
qgsmaptopixel.h
QgsPoint::draw
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
Definition: qgspoint.cpp:349
QgsWkbTypes::flatType
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
QgsAbstractGeometry::parts
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
Definition: qgsabstractgeometry.cpp:308
QgsPoint::closestSegment
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
QgsPoint::adjacentVertices
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
QgsPoint::clear
void clear() override
Clears the geometry, ie reset it to a null geometry.
Definition: qgspoint.cpp:359
QgsWkbTypes::addZ
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1176
QgsAbstractGeometry::wktTypeStr
QString wktTypeStr() const
Returns the WKT type string of the geometry.
Definition: qgsabstractgeometry.cpp:181
QgsPoint::z
double z
Definition: qgspoint.h:71
QgsPoint::coordinateSequence
QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
Definition: qgspoint.cpp:396
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:69
QgsPointXY::isEmpty
bool isEmpty() const SIP_HOLDGIL
Returns true if the geometry is empty.
Definition: qgspointxy.h:249
qgspoint.h
QgsAbstractGeometry::mWkbType
QgsWkbTypes::Type mWkbType
Definition: qgsabstractgeometry.h:1119
QgsPoint::toCurveType
QgsPoint * toCurveType() const override
Returns the geometry converted to the more generic curve type.
Definition: qgspoint.cpp:530
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsPoint::vertexCount
int vertexCount(int=0, int=0) const override
Returns the number of vertices of which this geometry is built.
Definition: qgspoint.cpp:510
QgsPoint::normalize
void normalize() final SIP_HOLDGIL
Reorganizes the geometry into a normalized form (or "canonical" form).
Definition: qgspoint.cpp:762
QgsPoint::vertexNumberFromVertexId
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
Definition: qgspoint.cpp:411
QgsPoint::project
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
qgsDoubleToString
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:2204
QgsPoint::transformVertices
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::dropMValue
bool dropMValue() override
Drops any measure values which exist in the geometry.
Definition: qgspoint.cpp:603
QgsPoint::clone
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspoint.cpp:104
qgsapplication.h
QgsAbstractGeometry::isMeasure
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
Definition: qgsabstractgeometry.h:228
QgsPoint::snappedToGrid
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
QgsWkbTypes::PointM
@ PointM
Definition: qgswkbtypes.h:99
MathUtils::leftOf
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
QgsPoint::y
double y
Definition: qgspoint.h:70
QgsWkbTypes::addM
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1201
precision
int precision
Definition: qgswfsgetfeature.cpp:103
QgsPoint::rx
double & rx()
Returns a reference to the x-coordinate of this point.
Definition: qgspoint.h:263
QgsWkbTypes::PointZM
@ PointZM
Definition: qgswkbtypes.h:112
QgsPoint::segmentLength
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
Definition: qgspoint.cpp:535
QgsPoint::addMValue
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
Definition: qgspoint.cpp:562
QgsAbstractGeometry::wkbType
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
Definition: qgsabstractgeometry.h:206
QgsWkbTypes::Unknown
@ Unknown
Definition: qgswkbtypes.h:71
QgsAbstractGeometry::AxisOrder
AxisOrder
Axis order for GML generation.
Definition: qgsabstractgeometry.h:138
QgsPoint::transform
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
QgsPoint::wkbSize
int wkbSize(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns the length of the QByteArray returned by asWkb()
Definition: qgspoint.cpp:238
QgsPoint::compareToSameClass
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
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsConstWkbPtr
A const WKB pointer.
Definition: qgswkbptr.h:137
QgsPoint::azimuth
double azimuth(const QgsPoint &other) const SIP_HOLDGIL
Calculates Cartesian azimuth between this point and other one (clockwise in degree,...
Definition: qgspoint.cpp:716
QgsFeedback
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
qgsRound
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
Definition: qgis.h:2319
QgsRectangle::contains
bool contains(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:363
QgsPoint::dropZValue
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
Definition: qgspoint.cpp:592
QgsPoint::vertexAngle
double vertexAngle(QgsVertexId vertex) const override
Angle undefined.
Definition: qgspoint.cpp:504
QgsWkbTypes::hasM
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1130
QgsWkbTypes::PointZ
@ PointZ
Definition: qgswkbtypes.h:86
QgsPoint::nCoordinates
int nCoordinates() const override SIP_HOLDGIL
Returns the number of nodes contained in the geometry.
Definition: qgspoint.cpp:406
QgsApplication::endian
static endian_t endian()
Returns whether this machine uses big or little endian.
Definition: qgsapplication.cpp:1404
QgsPoint::m
double m
Definition: qgspoint.h:72
qgscoordinatetransform.h
QgsWkbTypes::dropZ
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:1237
QgsPoint::boundary
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
Definition: qgspoint.cpp:419
QgsWkbPtr
WKB pointer handler.
Definition: qgswkbptr.h:43
QgsRingSequence
QVector< QgsPointSequence > QgsRingSequence
Definition: qgsabstractgeometry.h:56
QgsPoint::childCount
int childCount() const override
Returns number of child geometries (for geometries with child geometries) or child points (for geomet...
Definition: qgspoint.cpp:787
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:79
QgsPoint::inclination
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
qgsgeometryutils.h
QgsPoint::asGml2
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
QgsAbstractGeometry::is3D
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
Definition: qgsabstractgeometry.h:219
QgsPoint::removeDuplicateNodes
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
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsPoint::swapXy
void swapXy() override
Swaps the x and y coordinates from the geometry.
Definition: qgspoint.cpp:614
QgsPoint::asQPainterPath
QPainterPath asQPainterPath() const override
Returns the geometry represented as a QPainterPath.
Definition: qgspoint.cpp:354
QgsPoint::dimension
int dimension() const override SIP_HOLDGIL
Returns the inherent dimension of the geometry.
Definition: qgspoint.cpp:782
QgsPoint::moveVertex
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
Definition: qgspoint.cpp:442
QgsPoint::fromWkt
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
Definition: qgspoint.cpp:163
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:52
QgsPoint::childPoint
QgsPoint childPoint(int index) const override
Returns point at index (for geometries without child geometries - i.e.
Definition: qgspoint.cpp:792
QgsPoint::asWkb
QByteArray asWkb(QgsAbstractGeometry::WkbFlags=QgsAbstractGeometry::WkbFlags()) const override
Definition: qgspoint.cpp:245
QgsPoint::nextVertex
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
Definition: qgspoint.cpp:476
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:30
QgsAbstractGeometryTransformer
An abstract base class for classes which transform geometries by transforming input points to output ...
Definition: qgsgeometrytransformer.h:32
QgsPoint::boundingBoxIntersects
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::convertTo
bool convertTo(QgsWkbTypes::Type type) override
Converts the geometry to a specified type.
Definition: qgspoint.cpp:620
QgsWkbTypes::hasZ
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1080
QgsPoint::distanceSquared3D
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
QgsPoint::createEmptyWithSameType
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
QgsPoint::isEmpty
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
Definition: qgspoint.cpp:767
QgsWkbTypes
Handles storage of information regarding WKB types and their properties.
Definition: qgswkbtypes.h:41
Qgis::TransformDirection
TransformDirection
Indicates the direction (forward or inverse) of a transform.
Definition: qgis.h:1235
QgsConstWkbPtr::readHeader
QgsWkbTypes::Type readHeader() const
readHeader
Definition: qgswkbptr.cpp:54
QgsGeometryUtils::wktReadBlock
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 (...
Definition: qgsgeometryutils.cpp:1351
QgsPoint::asKml
QString asKml(int precision=17) const override
Returns a KML representation of the geometry.
Definition: qgspoint.cpp:344
QgsPoint::filterVertices
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
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsPoint::boundingBox
QgsRectangle boundingBox() const override SIP_HOLDGIL
Returns the minimal bounding box for the geometry.
Definition: qgspoint.cpp:772
QgsPoint::x
double x
Definition: qgspoint.h:69
QgsPoint::deleteVertex
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
Definition: qgspoint.cpp:459
QgsPoint::insertVertex
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
Definition: qgspoint.cpp:429
QgsAbstractGeometryTransformer::transformPoint
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.
QgsPoint::distance3D
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