QGIS API Documentation  2.14.11-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  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 {
257  mX = mY = mZ = mM = 0.;
258  clearCache();
259 }
260 
262 {
263  clearCache();
264  ct.transformInPlace( mX, mY, mZ, d );
265 }
266 
268 {
270 
271  cs.append( QgsRingSequenceV2() );
272  cs.back().append( QgsPointSequenceV2() << QgsPointV2( *this ) );
273 
274  return cs;
275 }
276 
277 /***************************************************************************
278  * This class is considered CRITICAL and any change MUST be accompanied with
279  * full unit tests.
280  * See details in QEP #17
281  ****************************************************************************/
282 
283 bool QgsPointV2::moveVertex( QgsVertexId position, const QgsPointV2& newPos )
284 {
285  Q_UNUSED( position );
286  clearCache();
287  mX = newPos.mX;
288  mY = newPos.mY;
289  if ( is3D() && newPos.is3D() )
290  {
291  mZ = newPos.mZ;
292  }
293  if ( isMeasure() && newPos.isMeasure() )
294  {
295  mM = newPos.mM;
296  }
297  return true;
298 }
299 
300 double QgsPointV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
301 {
302  Q_UNUSED( leftOf );
303  Q_UNUSED( epsilon );
304  segmentPt = *this;
305  vertexAfter = QgsVertexId( 0, 0, 0 );
306  return QgsGeometryUtils::sqrDistance2D( *this, pt );
307 }
308 
310 {
311  if ( id.vertex < 0 )
312  {
313  id.vertex = 0;
314  if ( id.part < 0 )
315  {
316  id.part = 0;
317  }
318  if ( id.ring < 0 )
319  {
320  id.ring = 0;
321  }
322  vertex = *this;
323  return true;
324  }
325  else
326  {
327  return false;
328  }
329 }
330 
331 /***************************************************************************
332  * This class is considered CRITICAL and any change MUST be accompanied with
333  * full unit tests.
334  * See details in QEP #17
335  ****************************************************************************/
336 
337 bool QgsPointV2::addZValue( double zValue )
338 {
339  if ( QgsWKBTypes::hasZ( mWkbType ) )
340  return false;
341 
343  mZ = zValue;
344  clearCache();
345  return true;
346 }
347 
348 bool QgsPointV2::addMValue( double mValue )
349 {
350  if ( QgsWKBTypes::hasM( mWkbType ) )
351  return false;
352 
354  mM = mValue;
355  clearCache();
356  return true;
357 }
358 
360 {
361  clearCache();
362  qreal x, y;
363  t.map( mX, mY, &x, &y );
364  mX = x;
365  mY = y;
366 }
367 
368 
370 {
371  if ( !is3D() )
372  return false;
373 
375  mZ = 0.0;
376  clearCache();
377  return true;
378 }
379 
381 {
382  if ( !isMeasure() )
383  return false;
384 
386  mM = 0.0;
387  clearCache();
388  return true;
389 }
390 
392 {
393  if ( type == mWkbType )
394  return true;
395 
396  clearCache();
397 
398  switch ( type )
399  {
400  case QgsWKBTypes::Point:
401  mZ = 0.0;
402  mM = 0.0;
403  mWkbType = type;
404  return true;
405  case QgsWKBTypes::PointZ:
407  mM = 0.0;
408  mWkbType = type;
409  return true;
410  case QgsWKBTypes::PointM:
411  mZ = 0.0;
412  mWkbType = type;
413  return true;
415  mWkbType = type;
416  return true;
417  default:
418  break;
419  }
420 
421  return false;
422 }
423 
424 
426 {
427  return QPointF( mX, mY );
428 }
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:222
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:261
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:249
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:283
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:309
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:254
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:425
virtual bool dropMValue() override
Drops any measure values which exist in the geometry.
Definition: qgspointv2.cpp:380
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:391
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:348
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:300
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:337
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:242
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:369
virtual QgsCoordinateSequenceV2 coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
Definition: qgspointv2.cpp:267
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