QGIS API Documentation  2.14.0-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 }
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
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
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:656
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:283
QString wktTypeStr() const
Returns the WKT type string of the geometry.
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
double y() const
Returns the point&#39;s y-coordinate.
Definition: qgspointv2.h:74
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:37
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
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.
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)
Definition: qgis.h:274
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: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
QPointF toQPointF() const
Returns the point as a QPointF.
Definition: qgspointv2.cpp:425
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
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
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;.
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()
int wkbSize() const override
Returns the size of the WKB representation of the geometry.
Definition: qgspointv2.cpp:168
QList< QgsPointV2 > QgsPointSequenceV2