QGIS API Documentation  2.18.3-Las Palmas (77b8c3d)
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  QString strCoordinates = qgsDoubleToString( mX, precision ) + ',' + qgsDoubleToString( mY, precision );
217  elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
218  elemPoint.appendChild( elemCoordinates );
219  return elemPoint;
220 }
221 
222 QDomElement QgsPointV2::asGML3( QDomDocument& doc, int precision, const QString& ns ) const
223 {
224  QDomElement elemPoint = doc.createElementNS( ns, "Point" );
225  QDomElement elemPosList = doc.createElementNS( ns, "pos" );
226  elemPosList.setAttribute( "srsDimension", is3D() ? 3 : 2 );
227  QString strCoordinates = qgsDoubleToString( mX, precision ) + ' ' + qgsDoubleToString( mY, precision );
228  if ( is3D() )
229  strCoordinates += ' ' + qgsDoubleToString( mZ, precision );
230 
231  elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
232  elemPoint.appendChild( elemPosList );
233  return elemPoint;
234 }
235 
236 /***************************************************************************
237  * This class is considered CRITICAL and any change MUST be accompanied with
238  * full unit tests.
239  * See details in QEP #17
240  ****************************************************************************/
241 
242 QString QgsPointV2::asJSON( int precision ) const
243 {
244  return "{\"type\": \"Point\", \"coordinates\": ["
245  + qgsDoubleToString( mX, precision ) + ", " + qgsDoubleToString( mY, precision )
246  + "]}";
247 }
248 
249 void QgsPointV2::draw( QPainter& p ) const
250 {
251  p.drawRect( mX - 2, mY - 2, 4, 4 );
252 }
253 
255 {
256  mX = mY = mZ = mM = 0.;
257  clearCache();
258 }
259 
261 {
262  clearCache();
263  if ( transformZ )
264  {
265  ct.transformInPlace( mX, mY, mZ, d );
266  }
267  else
268  {
269  double z = 0.0;
270  ct.transformInPlace( mX, mY, z, d );
271  }
272 }
273 
275 {
277 
278  cs.append( QgsRingSequenceV2() );
279  cs.back().append( QgsPointSequenceV2() << QgsPointV2( *this ) );
280 
281  return cs;
282 }
283 
285 {
286  return nullptr;
287 }
288 
289 /***************************************************************************
290  * This class is considered CRITICAL and any change MUST be accompanied with
291  * full unit tests.
292  * See details in QEP #17
293  ****************************************************************************/
294 
295 bool QgsPointV2::moveVertex( QgsVertexId position, const QgsPointV2& newPos )
296 {
297  Q_UNUSED( position );
298  clearCache();
299  mX = newPos.mX;
300  mY = newPos.mY;
301  if ( is3D() && newPos.is3D() )
302  {
303  mZ = newPos.mZ;
304  }
305  if ( isMeasure() && newPos.isMeasure() )
306  {
307  mM = newPos.mM;
308  }
309  return true;
310 }
311 
312 double QgsPointV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
313 {
314  Q_UNUSED( pt );
315  Q_UNUSED( segmentPt );
316  Q_UNUSED( vertexAfter );
317  Q_UNUSED( leftOf );
318  Q_UNUSED( epsilon );
319  return -1; // no segments - return error
320 }
321 
323 {
324  if ( id.vertex < 0 )
325  {
326  id.vertex = 0;
327  if ( id.part < 0 )
328  {
329  id.part = 0;
330  }
331  if ( id.ring < 0 )
332  {
333  id.ring = 0;
334  }
335  vertex = *this;
336  return true;
337  }
338  else
339  {
340  return false;
341  }
342 }
343 
344 /***************************************************************************
345  * This class is considered CRITICAL and any change MUST be accompanied with
346  * full unit tests.
347  * See details in QEP #17
348  ****************************************************************************/
349 
350 bool QgsPointV2::addZValue( double zValue )
351 {
352  if ( QgsWKBTypes::hasZ( mWkbType ) )
353  return false;
354 
356  mZ = zValue;
357  clearCache();
358  return true;
359 }
360 
361 bool QgsPointV2::addMValue( double mValue )
362 {
363  if ( QgsWKBTypes::hasM( mWkbType ) )
364  return false;
365 
367  mM = mValue;
368  clearCache();
369  return true;
370 }
371 
373 {
374  clearCache();
375  qreal x, y;
376  t.map( mX, mY, &x, &y );
377  mX = x;
378  mY = y;
379 }
380 
381 
383 {
384  if ( !is3D() )
385  return false;
386 
388  mZ = 0.0;
389  clearCache();
390  return true;
391 }
392 
394 {
395  if ( !isMeasure() )
396  return false;
397 
399  mM = 0.0;
400  clearCache();
401  return true;
402 }
403 
405 {
406  if ( type == mWkbType )
407  return true;
408 
409  clearCache();
410 
411  switch ( type )
412  {
413  case QgsWKBTypes::Point:
414  mZ = 0.0;
415  mM = 0.0;
416  mWkbType = type;
417  return true;
418  case QgsWKBTypes::PointZ:
420  mM = 0.0;
421  mWkbType = type;
422  return true;
423  case QgsWKBTypes::PointM:
424  mZ = 0.0;
425  mWkbType = type;
426  return true;
428  mWkbType = type;
429  return true;
430  default:
431  break;
432  }
433 
434  return false;
435 }
436 
437 
439 {
440  return QPointF( mX, mY );
441 }
virtual bool fromWkb(QgsConstWkbPtr wkb) override
Sets the geometry from a WKB string.
Definition: qgspointv2.cpp:99
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
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:222
QDomNode appendChild(const QDomNode &newChild)
double x() const
Returns the point&#39;s x-coordinate.
Definition: qgspointv2.h:68
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:249
bool operator==(const QgsPointV2 &pt) const
Definition: qgspointv2.cpp:80
QDomElement createElementNS(const QString &nsURI, const QString &qName)
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:667
bool operator!=(const QgsPointV2 &pt) const
Definition: qgspointv2.cpp:89
static endian_t endian()
Returns whether this machine uses big or little endian.
virtual bool moveVertex(QgsVertexId position, const QgsPointV2 &newPos) override
Moves a vertex within the geometry.
Definition: qgspointv2.cpp:295
QString wktTypeStr() const
Returns the WKT type string of the geometry.
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:322
double y() const
Returns the point&#39;s y-coordinate.
Definition: qgspointv2.h:74
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:38
void drawRect(const QRectF &rectangle)
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
void transformInPlace(double &x, double &y, double &z, TransformDirection direction=ForwardTransform) const
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.
bool isMeasure() const
Returns true if the geometry contains m values.
double z() const
Returns the point&#39;s z-coordinate.
Definition: qgspointv2.h:80
void setAttribute(const QString &name, const QString &value)
void clear() override
Clears the geometry, ie reset it to a null geometry.
Definition: qgspointv2.cpp:254
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:284
virtual QgsPointV2 * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspointv2.cpp:94
virtual bool dropMValue() override
Drops any measure values which exist in the geometry.
Definition: qgspointv2.cpp:393
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:404
QPointF toQPointF() const
Returns the point as a QPointF.
Definition: qgspointv2.cpp:438
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:260
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:361
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:312
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:350
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition: qgspointv2.cpp:200
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:242
Class for doing transforms between two map coordinate systems.
double m() const
Returns the point&#39;s m value.
Definition: qgspointv2.h:86
virtual void clearCache() const
Clears any cached parameters associated with the geometry, eg bounding boxes.
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;.
virtual bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
Definition: qgspointv2.cpp:382
virtual QgsCoordinateSequenceV2 coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
Definition: qgspointv2.cpp:274
T & back()
int wkbSize() const override
Returns the size of the WKB representation of the geometry.
Definition: qgspointv2.cpp:168
QList< QgsPointV2 > QgsPointSequenceV2