QGIS API Documentation  2.14.18-Essen
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::parseType( geometryType() ) )
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 {
266  mX = mY = mZ = mM = 0.;
267  clearCache();
268 }
269 
271 {
272  clearCache();
273  ct.transformInPlace( mX, mY, mZ, d );
274 }
275 
277 {
279 
280  cs.append( QgsRingSequenceV2() );
281  cs.back().append( QgsPointSequenceV2() << QgsPointV2( *this ) );
282 
283  return cs;
284 }
285 
286 /***************************************************************************
287  * This class is considered CRITICAL and any change MUST be accompanied with
288  * full unit tests.
289  * See details in QEP #17
290  ****************************************************************************/
291 
292 bool QgsPointV2::moveVertex( QgsVertexId position, const QgsPointV2& newPos )
293 {
294  Q_UNUSED( position );
295  clearCache();
296  mX = newPos.mX;
297  mY = newPos.mY;
298  if ( is3D() && newPos.is3D() )
299  {
300  mZ = newPos.mZ;
301  }
302  if ( isMeasure() && newPos.isMeasure() )
303  {
304  mM = newPos.mM;
305  }
306  return true;
307 }
308 
309 double QgsPointV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
310 {
311  Q_UNUSED( leftOf );
312  Q_UNUSED( epsilon );
313  segmentPt = *this;
314  vertexAfter = QgsVertexId( 0, 0, 0 );
315  return QgsGeometryUtils::sqrDistance2D( *this, pt );
316 }
317 
319 {
320  if ( id.vertex < 0 )
321  {
322  id.vertex = 0;
323  if ( id.part < 0 )
324  {
325  id.part = 0;
326  }
327  if ( id.ring < 0 )
328  {
329  id.ring = 0;
330  }
331  vertex = *this;
332  return true;
333  }
334  else
335  {
336  return false;
337  }
338 }
339 
340 /***************************************************************************
341  * This class is considered CRITICAL and any change MUST be accompanied with
342  * full unit tests.
343  * See details in QEP #17
344  ****************************************************************************/
345 
346 bool QgsPointV2::addZValue( double zValue )
347 {
348  if ( QgsWKBTypes::hasZ( mWkbType ) )
349  return false;
350 
352  mZ = zValue;
353  clearCache();
354  return true;
355 }
356 
357 bool QgsPointV2::addMValue( double mValue )
358 {
359  if ( QgsWKBTypes::hasM( mWkbType ) )
360  return false;
361 
363  mM = mValue;
364  clearCache();
365  return true;
366 }
367 
369 {
370  clearCache();
371  qreal x, y;
372  t.map( mX, mY, &x, &y );
373  mX = x;
374  mY = y;
375 }
376 
377 
379 {
380  if ( !is3D() )
381  return false;
382 
384  mZ = 0.0;
385  clearCache();
386  return true;
387 }
388 
390 {
391  if ( !isMeasure() )
392  return false;
393 
395  mM = 0.0;
396  clearCache();
397  return true;
398 }
399 
401 {
402  if ( type == mWkbType )
403  return true;
404 
405  clearCache();
406 
407  switch ( type )
408  {
409  case QgsWKBTypes::Point:
410  mZ = 0.0;
411  mM = 0.0;
412  mWkbType = type;
413  return true;
414  case QgsWKBTypes::PointZ:
416  mM = 0.0;
417  mWkbType = type;
418  return true;
419  case QgsWKBTypes::PointM:
420  mZ = 0.0;
421  mWkbType = type;
422  return true;
424  mWkbType = type;
425  return true;
426  default:
427  break;
428  }
429 
430  return false;
431 }
432 
433 
435 {
436  return QPointF( mX, mY );
437 }
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)
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform) override
Transforms the geometry using a coordinate transform.
Definition: qgspointv2.cpp:270
int length() const
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:746
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:703
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:656
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:292
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:285
int size() const
bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const override
Returns next vertex id and coordinates.
Definition: qgspointv2.cpp:318
void drawRect(const QRectF &rectangle)
virtual QString geometryType() const override
Returns a unique string representing the geometry type.
Definition: qgspointv2.h:155
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:800
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:770
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
static double sqrDistance2D(const QgsPointV2 &pt1, const QgsPointV2 &pt2)
Returns the squared 2D distance between two points.
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)
Definition: qgis.h:274
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:434
virtual bool dropMValue() override
Drops any measure values which exist in the geometry.
Definition: qgspointv2.cpp:389
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:400
A class to represent a point.
Definition: qgspoint.h:65
QList< QgsPointSequenceV2 > QgsRingSequenceV2
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:357
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:309
static Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
Definition: qgswkbtypes.h:817
virtual bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
Definition: qgspointv2.cpp:346
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
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
Definition: qgswkbtypes.cpp:32
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:37
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:378
virtual QgsCoordinateSequenceV2 coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
Definition: qgspointv2.cpp:276
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