QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgspointv2.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 "qgspointv2.h"
20 #include "qgsapplication.h"
21 #include "qgscoordinatetransform.h"
22 #include "qgsgeometryutils.h"
23 #include "qgsmaptopixel.h"
24 #include "qgswkbptr.h"
25 #include <QPainter>
26 
27 /***************************************************************************
28  * This class is considered CRITICAL and any change MUST be accompanied with
29  * full unit tests.
30  * See details in QEP #17
31  ****************************************************************************/
32 
33 QgsPointV2::QgsPointV2( double x, double y )
35  , mX( x )
36  , mY( y )
37  , mZ( 0.0 )
38  , mM( 0.0 )
39 {
41 }
42 
45  , mX( p.x() )
46  , mY( p.y() )
47  , mZ( 0.0 )
48  , mM( 0.0 )
49 {
51 }
52 
55  , mX( p.x() )
56  , mY( p.y() )
57  , mZ( 0.0 )
58  , mM( 0.0 )
59 {
61 }
62 
63 QgsPointV2::QgsPointV2( QgsWKBTypes::Type type, double x, double y, double z, double m )
64  : mX( x )
65  , mY( y )
66  , mZ( z )
67  , mM( m )
68 {
69  //protect against non-point WKB types
70  Q_ASSERT( QgsWKBTypes::flatType( type ) == QgsWKBTypes::Point );
71  mWkbType = type;
72 }
73 
74 /***************************************************************************
75  * This class is considered CRITICAL and any change MUST be accompanied with
76  * full unit tests.
77  * See details in QEP #17
78  ****************************************************************************/
79 
80 bool QgsPointV2::operator==( const QgsPointV2& pt ) const
81 {
82  return ( pt.wkbType() == wkbType() &&
83  qgsDoubleNear( pt.x(), mX, 1E-8 ) &&
84  qgsDoubleNear( pt.y(), mY, 1E-8 ) &&
85  qgsDoubleNear( pt.z(), mZ, 1E-8 ) &&
86  qgsDoubleNear( pt.m(), mM, 1E-8 ) );
87 }
88 
89 bool QgsPointV2::operator!=( const QgsPointV2& pt ) const
90 {
91  return !operator==( pt );
92 }
93 
95 {
96  return new QgsPointV2( *this );
97 }
98 
100 {
101  QgsWKBTypes::Type type = wkbPtr.readHeader();
102  if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::Point )
103  {
104  clear();
105  return false;
106  }
107  mWkbType = type;
108 
109  wkbPtr >> mX;
110  wkbPtr >> mY;
111  if ( is3D() )
112  wkbPtr >> mZ;
113  if ( isMeasure() )
114  wkbPtr >> mM;
115 
116  clearCache();
117 
118  return true;
119 }
120 
121 /***************************************************************************
122  * This class is considered CRITICAL and any change MUST be accompanied with
123  * full unit tests.
124  * See details in QEP #17
125  ****************************************************************************/
126 
127 bool QgsPointV2::fromWkt( const QString& wkt )
128 {
129  clear();
130 
132 
133  if ( QgsWKBTypes::flatType( parts.first ) != QgsWKBTypes::Point )
134  return false;
135  mWkbType = parts.first;
136 
137  QStringList coordinates = parts.second.split( ' ', QString::SkipEmptyParts );
138  if ( coordinates.size() < 2 )
139  {
140  clear();
141  return false;
142  }
143  else if ( coordinates.size() == 3 && !is3D() && !isMeasure() )
144  {
145  // 3 dimensional coordinates, but not specifically marked as such. We allow this
146  // anyway and upgrade geometry to have Z dimension
148  }
149  else if ( coordinates.size() >= 4 && ( !is3D() || !isMeasure() ) )
150  {
151  // 4 (or more) dimensional coordinates, but not specifically marked as such. We allow this
152  // anyway and upgrade geometry to have Z&M dimensions
155  }
156 
157  int idx = 0;
158  mX = coordinates[idx++].toDouble();
159  mY = coordinates[idx++].toDouble();
160  if ( is3D() && coordinates.length() > 2 )
161  mZ = coordinates[idx++].toDouble();
162  if ( isMeasure() && coordinates.length() > 2 + is3D() )
163  mM = coordinates[idx++].toDouble();
164 
165  return true;
166 }
167 
169 {
170  int size = sizeof( char ) + sizeof( quint32 );
171  size += ( 2 + is3D() + isMeasure() ) * sizeof( double );
172  return size;
173 }
174 
175 /***************************************************************************
176  * This class is considered CRITICAL and any change MUST be accompanied with
177  * full unit tests.
178  * See details in QEP #17
179  ****************************************************************************/
180 
181 unsigned char* QgsPointV2::asWkb( int& binarySize ) const
182 {
183  binarySize = wkbSize();
184  unsigned char* geomPtr = new unsigned char[binarySize];
185  QgsWkbPtr wkb( geomPtr, binarySize );
186  wkb << static_cast<char>( QgsApplication::endian() );
187  wkb << static_cast<quint32>( wkbType() );
188  wkb << mX << mY;
189  if ( is3D() )
190  {
191  wkb << mZ;
192  }
193  if ( isMeasure() )
194  {
195  wkb << mM;
196  }
197  return geomPtr;
198 }
199 
200 QString QgsPointV2::asWkt( int precision ) const
201 {
202  QString wkt = wktTypeStr() + " (";
203  wkt += qgsDoubleToString( mX, precision ) + ' ' + qgsDoubleToString( mY, precision );
204  if ( is3D() )
205  wkt += ' ' + qgsDoubleToString( mZ, precision );
206  if ( isMeasure() )
207  wkt += ' ' + qgsDoubleToString( mM, precision );
208  wkt += ')';
209  return wkt;
210 }
211 
212 QDomElement QgsPointV2::asGML2( QDomDocument& doc, int precision, const QString& ns ) const
213 {
214  QDomElement elemPoint = doc.createElementNS( ns, "Point" );
215  QDomElement elemCoordinates = doc.createElementNS( ns, "coordinates" );
216 
217  // coordinate separator
218  QString cs = ",";
219  // tupel separator
220  QString ts = " ";
221 
222  elemCoordinates.setAttribute( "cs", cs );
223  elemCoordinates.setAttribute( "ts", ts );
224 
225  QString strCoordinates = qgsDoubleToString( mX, precision ) + cs + qgsDoubleToString( mY, precision );
226  elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
227  elemPoint.appendChild( elemCoordinates );
228  return elemPoint;
229 }
230 
231 QDomElement QgsPointV2::asGML3( QDomDocument& doc, int precision, const QString& ns ) const
232 {
233  QDomElement elemPoint = doc.createElementNS( ns, "Point" );
234  QDomElement elemPosList = doc.createElementNS( ns, "pos" );
235  elemPosList.setAttribute( "srsDimension", is3D() ? 3 : 2 );
236  QString strCoordinates = qgsDoubleToString( mX, precision ) + ' ' + qgsDoubleToString( mY, precision );
237  if ( is3D() )
238  strCoordinates += ' ' + qgsDoubleToString( mZ, precision );
239 
240  elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
241  elemPoint.appendChild( elemPosList );
242  return elemPoint;
243 }
244 
245 /***************************************************************************
246  * This class is considered CRITICAL and any change MUST be accompanied with
247  * full unit tests.
248  * See details in QEP #17
249  ****************************************************************************/
250 
251 QString QgsPointV2::asJSON( int precision ) const
252 {
253  return "{\"type\": \"Point\", \"coordinates\": ["
254  + qgsDoubleToString( mX, precision ) + ", " + qgsDoubleToString( mY, precision )
255  + "]}";
256 }
257 
258 void QgsPointV2::draw( QPainter& p ) const
259 {
260  p.drawRect( mX - 2, mY - 2, 4, 4 );
261 }
262 
264 {
265  mX = mY = mZ = mM = 0.;
266  clearCache();
267 }
268 
270 {
271  clearCache();
272  if ( transformZ )
273  {
274  ct.transformInPlace( mX, mY, mZ, d );
275  }
276  else
277  {
278  double z = 0.0;
279  ct.transformInPlace( mX, mY, z, d );
280  }
281 }
282 
284 {
286 
287  cs.append( QgsRingSequenceV2() );
288  cs.back().append( QgsPointSequenceV2() << QgsPointV2( *this ) );
289 
290  return cs;
291 }
292 
294 {
295  return nullptr;
296 }
297 
298 /***************************************************************************
299  * This class is considered CRITICAL and any change MUST be accompanied with
300  * full unit tests.
301  * See details in QEP #17
302  ****************************************************************************/
303 
304 bool QgsPointV2::moveVertex( QgsVertexId position, const QgsPointV2& newPos )
305 {
306  Q_UNUSED( position );
307  clearCache();
308  mX = newPos.mX;
309  mY = newPos.mY;
310  if ( is3D() && newPos.is3D() )
311  {
312  mZ = newPos.mZ;
313  }
314  if ( isMeasure() && newPos.isMeasure() )
315  {
316  mM = newPos.mM;
317  }
318  return true;
319 }
320 
321 double QgsPointV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
322 {
323  Q_UNUSED( pt );
324  Q_UNUSED( segmentPt );
325  Q_UNUSED( vertexAfter );
326  Q_UNUSED( leftOf );
327  Q_UNUSED( epsilon );
328  return -1; // no segments - return error
329 }
330 
332 {
333  if ( id.vertex < 0 )
334  {
335  id.vertex = 0;
336  if ( id.part < 0 )
337  {
338  id.part = 0;
339  }
340  if ( id.ring < 0 )
341  {
342  id.ring = 0;
343  }
344  vertex = *this;
345  return true;
346  }
347  else
348  {
349  return false;
350  }
351 }
352 
353 /***************************************************************************
354  * This class is considered CRITICAL and any change MUST be accompanied with
355  * full unit tests.
356  * See details in QEP #17
357  ****************************************************************************/
358 
359 bool QgsPointV2::addZValue( double zValue )
360 {
361  if ( QgsWKBTypes::hasZ( mWkbType ) )
362  return false;
363 
365  mZ = zValue;
366  clearCache();
367  return true;
368 }
369 
370 bool QgsPointV2::addMValue( double mValue )
371 {
372  if ( QgsWKBTypes::hasM( mWkbType ) )
373  return false;
374 
376  mM = mValue;
377  clearCache();
378  return true;
379 }
380 
382 {
383  clearCache();
384  qreal x, y;
385  t.map( mX, mY, &x, &y );
386  mX = x;
387  mY = y;
388 }
389 
390 
392 {
393  if ( !is3D() )
394  return false;
395 
397  mZ = 0.0;
398  clearCache();
399  return true;
400 }
401 
403 {
404  if ( !isMeasure() )
405  return false;
406 
408  mM = 0.0;
409  clearCache();
410  return true;
411 }
412 
414 {
415  if ( type == mWkbType )
416  return true;
417 
418  clearCache();
419 
420  switch ( type )
421  {
422  case QgsWKBTypes::Point:
423  mZ = 0.0;
424  mM = 0.0;
425  mWkbType = type;
426  return true;
427  case QgsWKBTypes::PointZ:
429  mM = 0.0;
430  mWkbType = type;
431  return true;
432  case QgsWKBTypes::PointM:
433  mZ = 0.0;
434  mWkbType = type;
435  return true;
437  mWkbType = type;
438  return true;
439  default:
440  break;
441  }
442 
443  return false;
444 }
445 
446 
448 {
449  return QPointF( mX, mY );
450 }
QString wktTypeStr() const
Returns the WKT type string of the geometry.
virtual bool fromWkb(QgsConstWkbPtr wkb) override
Sets the geometry from a WKB string.
Definition: qgspointv2.cpp:99
bool operator==(const QgsPointV2 &pt) const
Definition: qgspointv2.cpp:80
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 (...
QDomElement asGML3(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML3 representation of the geometry.
Definition: qgspointv2.cpp:231
QDomNode appendChild(const QDomNode &newChild)
int length() const
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:757
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:714
QPoint map(const QPoint &point) const
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
Abstract base class for all geometries.
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
Definition: qgspointv2.cpp:258
QDomElement createElementNS(const QString &nsURI, const QString &qName)
double z() const
Returns the point&#39;s z-coordinate.
Definition: qgspointv2.h:80
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:667
double y() const
Returns the point&#39;s y-coordinate.
Definition: qgspointv2.h:74
static endian_t endian()
Returns whether this machine uses big or little endian.
virtual void clearCache() const
Clears any cached parameters associated with the geometry, eg bounding boxes.
virtual bool moveVertex(QgsVertexId position, const QgsPointV2 &newPos) override
Moves a vertex within the geometry.
Definition: qgspointv2.cpp:304
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:353
int size() const
bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const override
Returns next vertex id and coordinates.
Definition: qgspointv2.cpp:331
void drawRect(const QRectF &rectangle)
void append(const T &value)
static Type dropZ(Type type)
Drops the z dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:811
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:781
QgsPointV2(double x=0.0, double y=0.0)
Construct a 2 dimensional point with an initial x and y coordinate.
Definition: qgspointv2.cpp:33
Utility class for identifying a unique vertex within a geometry.
void setAttribute(const QString &name, const QString &value)
bool isMeasure() const
Returns true if the geometry contains m values.
void clear() override
Clears the geometry, ie reset it to a null geometry.
Definition: qgspointv2.cpp:263
Point geometry type, with support for z-dimension and m-values.
Definition: qgspointv2.h:34
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:341
virtual QgsAbstractGeometryV2 * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
Definition: qgspointv2.cpp:293
double x() const
Returns the point&#39;s x-coordinate.
Definition: qgspointv2.h:68
virtual QgsPointV2 * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspointv2.cpp:94
QPointF toQPointF() const
Returns the point as a QPointF.
Definition: qgspointv2.cpp:447
virtual bool dropMValue() override
Drops any measure values which exist in the geometry.
Definition: qgspointv2.cpp:402
QDomElement asGML2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
Definition: qgspointv2.cpp:212
virtual bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
Definition: qgspointv2.cpp:127
bool convertTo(QgsWKBTypes::Type type) override
Converts the geometry to a specified type.
Definition: qgspointv2.cpp:413
A class to represent a point.
Definition: qgspoint.h:117
QList< QgsPointSequenceV2 > QgsRingSequenceV2
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
Definition: qgspointv2.cpp:269
QDomText createTextNode(const QString &value)
virtual bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
Definition: qgspointv2.cpp:370
double closestSegment(const QgsPointV2 &pt, QgsPointV2 &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon) const override
Searches for the closest segment of the geometry to a given point.
Definition: qgspointv2.cpp:321
static Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:828
virtual bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
Definition: qgspointv2.cpp:359
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition: qgspointv2.cpp:200
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
unsigned char * asWkb(int &binarySize) const override
Returns a WKB representation of the geometry.
Definition: qgspointv2.cpp:181
QString asJSON(int precision=17) const override
Returns a GeoJSON representation of the geometry.
Definition: qgspointv2.cpp:251
Class for doing transforms between two map coordinate systems.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
double ANALYSIS_EXPORT leftOf(Point3D *thepoint, Point3D *p1, Point3D *p2)
Returns whether &#39;thepoint&#39; is left or right of the line from &#39;p1&#39; to &#39;p2&#39;.
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:38
bool operator!=(const QgsPointV2 &pt) const
Definition: qgspointv2.cpp:89
void transformInPlace(double &x, double &y, double &z, TransformDirection direction=ForwardTransform) const
virtual bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
Definition: qgspointv2.cpp:391
virtual QgsCoordinateSequenceV2 coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
Definition: qgspointv2.cpp:283
T & back()
double m() const
Returns the point&#39;s m value.
Definition: qgspointv2.h:86
int wkbSize() const override
Returns the size of the WKB representation of the geometry.
Definition: qgspointv2.cpp:168
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
QList< QgsPointV2 > QgsPointSequenceV2