QGIS API Documentation  2.10.1-Pisa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgslinestringv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslinestringv2.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 #include "qgslinestringv2.h"
19 #include "qgsapplication.h"
20 #include "qgscoordinatetransform.h"
21 #include "qgsgeometryutils.h"
22 #include "qgsmaptopixel.h"
23 #include "qgswkbptr.h"
24 #include <QPainter>
25 #include <limits>
26 #include <QDomDocument>
27 
29 {
31 }
32 
34 {}
35 
37 {
38  return new QgsLineStringV2( *this );
39 }
40 
42 {
43  mCoords.clear();
44  mZ.clear();
45  mM.clear();
47 }
48 
49 bool QgsLineStringV2::fromWkb( const unsigned char* wkb )
50 {
51  if ( !wkb )
52  {
53  return false;
54  }
55  QgsConstWkbPtr wkbPtr( wkb );
56  QgsWKBTypes::Type type = wkbPtr.readHeader();
58  {
59  return false;
60  }
61  mWkbType = type;
62  importVerticesFromWkb( wkbPtr );
63  return true;
64 }
65 
67 {
68  mWkbType = type;
69  importVerticesFromWkb( wkb );
70 }
71 
73 {
74  clear();
75 
77 
78  if ( QgsWKBTypes::flatType( parts.first ) != QgsWKBTypes::parseType( geometryType() ) )
79  return false;
80  mWkbType = parts.first;
81 
83  return true;
84 }
85 
87 {
88  int size = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
89  size += numPoints() * ( 2 + is3D() + isMeasure() ) * sizeof( double );
90  return size;
91 }
92 
93 unsigned char* QgsLineStringV2::asWkb( int& binarySize ) const
94 {
95  binarySize = wkbSize();
96  unsigned char* geomPtr = new unsigned char[binarySize];
97  QgsWkbPtr wkb( geomPtr );
98  wkb << static_cast<char>( QgsApplication::endian() );
99  wkb << static_cast<quint32>( wkbType() );
100  QList<QgsPointV2> pts;
101  points( pts );
102  QgsGeometryUtils::pointsToWKB( wkb, pts, is3D(), isMeasure() );
103  return geomPtr;
104 }
105 
106 QString QgsLineStringV2::asWkt( int precision ) const
107 {
108  QString wkt = wktTypeStr() + " ";
109  QList<QgsPointV2> pts;
110  points( pts );
111  wkt += QgsGeometryUtils::pointsToWKT( pts, precision, is3D(), isMeasure() );
112  return wkt;
113 }
114 
115 QDomElement QgsLineStringV2::asGML2( QDomDocument& doc, int precision, const QString& ns ) const
116 {
117  QList<QgsPointV2> pts;
118  points( pts );
119 
120  QDomElement elemLineString = doc.createElementNS( ns, "LineString" );
121  elemLineString.appendChild( QgsGeometryUtils::pointsToGML2( pts, doc, precision, ns ) );
122 
123  return elemLineString;
124 }
125 
126 QDomElement QgsLineStringV2::asGML3( QDomDocument& doc, int precision, const QString& ns ) const
127 {
128  QList<QgsPointV2> pts;
129  points( pts );
130 
131  QDomElement elemCurve = doc.createElementNS( ns, "Curve" );
132  QDomElement elemSegments = doc.createElementNS( ns, "segments" );
133  QDomElement elemArcString = doc.createElementNS( ns, "LineString" );
134  elemArcString.appendChild( QgsGeometryUtils::pointsToGML3( pts, doc, precision, ns, is3D() ) );
135  elemSegments.appendChild( elemArcString );
136  elemCurve.appendChild( elemSegments );
137 
138  return elemCurve;
139 }
140 
141 QString QgsLineStringV2::asJSON( int precision ) const
142 {
143  QList<QgsPointV2> pts;
144  points( pts );
145 
146  return "{\"type\": \"LineString\", \"coordinates\": " + QgsGeometryUtils::pointsToJSON( pts, precision ) + "}";
147 }
148 
150 {
151  double length = 0;
152  int size = mCoords.size();
153  double dx, dy;
154  for ( int i = 1; i < size; ++i )
155  {
156  dx = mCoords[i].x() - mCoords[ i - 1 ].x();
157  dy = mCoords[i].y() - mCoords[ i - 1 ].y();
158  length += sqrt( dx * dx + dy * dy );
159  }
160  return length;
161 }
162 
164 {
165  if ( numPoints() < 1 )
166  {
167  return QgsPointV2();
168  }
169  return pointN( 0 );
170 }
171 
173 {
174  if ( numPoints() < 1 )
175  {
176  return QgsPointV2();
177  }
178  return pointN( numPoints() - 1 );
179 }
180 
182 {
183  return static_cast<QgsLineStringV2*>( clone() );
184 }
185 
187 {
188  return mCoords.size();
189 }
190 
192 {
193  if ( mCoords.size() <= i )
194  {
195  return QgsPointV2();
196  }
197 
198  const QPointF& pt = mCoords.at( i );
199  double z = 0;
200  double m = 0;
201 
202  bool hasZ = is3D();
203  if ( hasZ )
204  {
205  z = mZ.at( i );
206  }
207  bool hasM = isMeasure();
208  if ( hasM )
209  {
210  m = mM.at( i );
211  }
212 
214  if ( hasZ && hasM )
215  {
217  }
218  else if ( hasZ )
219  {
221  }
222  else if ( hasM )
223  {
225  }
226  return QgsPointV2( t, pt.x(), pt.y(), z, m );
227 }
228 
230 {
231  pts.clear();
232  int nPoints = numPoints();
233  for ( int i = 0; i < nPoints; ++i )
234  {
235  pts.push_back( pointN( i ) );
236  }
237 }
238 
240 {
241  if ( points.size() < 1 )
242  {
244  mCoords.clear();
245  mZ.clear();
246  mM.clear();
247  return;
248  }
249 
250  //get wkb type from first point
251  const QgsPointV2& firstPt = points.at( 0 );
252  bool hasZ = firstPt.is3D();
253  bool hasM = firstPt.isMeasure();
254 
256 
257  mCoords.resize( points.size() );
258  if ( hasZ )
259  {
260  mZ.resize( points.size() );
261  }
262  else
263  {
264  mZ.clear();
265  }
266  if ( hasM )
267  {
268  mM.resize( points.size() );
269  }
270  else
271  {
272  mM.clear();
273  }
274 
275  for ( int i = 0; i < points.size(); ++i )
276  {
277  mCoords[i].rx() = points[i].x();
278  mCoords[i].ry() = points[i].y();
279  if ( hasZ )
280  {
281  mZ[i] = points[i].z();
282  }
283  if ( hasM )
284  {
285  mM[i] = points[i].m();
286  }
287  }
288 }
289 
291 {
292  if ( !line )
293  {
294  return;
295  }
296 
297  mCoords += line->mCoords;
298  mZ += line->mZ;
299  mM += line->mM;
300 }
301 
303 {
304  p.drawPolyline( mCoords );
305 }
306 
308 {
309  int nPoints = numPoints();
310  if ( nPoints < 1 )
311  {
312  return;
313  }
314 
315  if ( path.isEmpty() || path.currentPosition() != mCoords[0] )
316  {
317  path.moveTo( mCoords[0] );
318  }
319 
320  for ( int i = 1; i < nPoints; ++i )
321  {
322  path.lineTo( mCoords[i] );
323  }
324 }
325 
327 {
328  p.drawPolygon( mCoords );
329 }
330 
332 {
333  ct.transformPolygon( mCoords );
334 }
335 
337 {
338  mCoords = t.map( mCoords );
339 }
340 
341 bool QgsLineStringV2::insertVertex( const QgsVertexId& position, const QgsPointV2& vertex )
342 {
343  if ( position.vertex < 0 || position.vertex > mCoords.size() )
344  {
345  return false;
346  }
347  mCoords.insert( position.vertex, QPointF( vertex.x(), vertex.y() ) );
348  if ( is3D() )
349  {
350  mZ.insert( position.vertex, vertex.z() );
351  }
352  if ( isMeasure() )
353  {
354  mM.insert( position.vertex, vertex.m() );
355  }
356  return true;
357 }
358 
359 bool QgsLineStringV2::moveVertex( const QgsVertexId& position, const QgsPointV2& newPos )
360 {
361  if ( position.vertex < 0 || position.vertex >= mCoords.size() )
362  {
363  return false;
364  }
365  mCoords[position.vertex].rx() = newPos.x();
366  mCoords[position.vertex].ry() = newPos.y();
367  if ( is3D() && newPos.is3D() )
368  {
369  mZ[position.vertex] = newPos.z();
370  }
371  if ( isMeasure() && newPos.isMeasure() )
372  {
373  mM[position.vertex] = newPos.m();
374  }
375  mBoundingBox = QgsRectangle(); //set bounding box invalid
376  return true;
377 }
378 
380 {
381  if ( position.vertex >= mCoords.size() || position.vertex < 0 )
382  {
383  return false;
384  }
385 
386  mCoords.remove( position.vertex );
387  if ( is3D() )
388  {
389  mZ.remove( position.vertex );
390  }
391  if ( isMeasure() )
392  {
393  mM.remove( position.vertex );
394  }
395  return true;
396 }
397 
399 {
401  {
403  }
404 
405  mCoords.append( QPointF( pt.x(), pt.y() ) );
406  if ( is3D() )
407  {
408  mZ.append( pt.z() );
409  }
410  if ( isMeasure() )
411  {
412  mM.append( pt.m() );
413  }
414 }
415 
416 double QgsLineStringV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
417 {
418  double sqrDist = std::numeric_limits<double>::max();
419  double testDist = 0;
420  double segmentPtX, segmentPtY;
421 
422  int size = mCoords.size();
423  for ( int i = 1; i < size; ++i )
424  {
425  const QPointF& prev = mCoords.at( i - 1 );
426  const QPointF& currentPt = mCoords.at( i );
427  testDist = QgsGeometryUtils::sqrDistToLine( pt.x(), pt.y(), prev.x(), prev.y(), currentPt.x(), currentPt.y(), segmentPtX, segmentPtY, epsilon );
428  if ( testDist < sqrDist )
429  {
430  sqrDist = testDist;
431  segmentPt.setX( segmentPtX );
432  segmentPt.setY( segmentPtY );
433  if ( leftOf )
434  {
435  *leftOf = ( QgsGeometryUtils::leftOfLine( segmentPtX, segmentPtY, prev.x(), prev.y(), pt.x(), pt.y() ) < 0 );
436  }
437  vertexAfter.part = 0; vertexAfter.ring = 0; vertexAfter.vertex = i;
438  }
439  }
440  return sqrDist;
441 }
442 
444 {
445  if ( i >= numPoints() )
446  {
447  return false;
448  }
449  vertex = pointN( i );
451  return true;
452 }
453 
454 void QgsLineStringV2::sumUpArea( double& sum ) const
455 {
456  int maxIndex = numPoints() - 1;
457  for ( int i = 0; i < maxIndex; ++i )
458  {
459  sum += 0.5 * ( mCoords[i].x() * mCoords[i+1].y() - mCoords[i].y() * mCoords[i+1].x() );
460  }
461 }
462 
463 void QgsLineStringV2::importVerticesFromWkb( const QgsConstWkbPtr& wkb )
464 {
465  bool hasZ = is3D();
466  bool hasM = isMeasure();
467  int nVertices = 0;
468  wkb >> nVertices;
469  mCoords.resize( nVertices );
470  hasZ ? mZ.resize( nVertices ) : mZ.clear();
471  hasM ? mM.resize( nVertices ) : mM.clear();
472  for ( int i = 0; i < nVertices; ++i )
473  {
474  wkb >> mCoords[i].rx();
475  wkb >> mCoords[i].ry();
476  if ( hasZ )
477  {
478  wkb >> mZ[i];
479  }
480  if ( hasM )
481  {
482  wkb >> mM[i];
483  }
484  }
485 }
486 
488 {
489  if ( numPoints() < 1 || isClosed() )
490  {
491  return;
492  }
493  addVertex( startPoint() );
494 }
void clear()
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
void close()
Appends first point if not already closed.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
QDomElement asGML2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
QgsPointV2 pointN(int i) const
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 (...
virtual bool moveVertex(const QgsVertexId &position, const QgsPointV2 &newPos) override
Moves a vertex within the geometry.
QPointF currentPosition() const
QDomNode appendChild(const QDomNode &newChild)
void append(const T &value)
double x() const
Definition: qgspointv2.h:41
void push_back(const T &value)
void transformPolygon(QPolygonF &poly, TransformDirection direction=ForwardTransform) const
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
void points(QList< QgsPointV2 > &pt) const override
Returns a list of points within the curve.
QPoint map(const QPoint &point) const
virtual bool insertVertex(const QgsVertexId &position, const QgsPointV2 &vertex) override
Inserts a vertex into the geometry.
void transform(const QgsCoordinateTransform &ct) override
Transforms the geometry using a coordinate transform.
void drawPolyline(const QPointF *points, int pointCount)
virtual bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
const T & at(int i) const
static QString pointsToWKT(const QList< QgsPointV2 > &points, int precision, bool is3D, bool isMeasure)
Returns a WKT coordinate list.
static QString pointsToJSON(const QList< QgsPointV2 > &points, int precision)
Returns a geoJSON coordinates string.
void insert(int i, const T &value)
virtual QgsAbstractGeometryV2 * clone() const override
Clones the geometry by performing a deep copy.
Abstract base class for all geometries.
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
void moveTo(const QPointF &point)
void setX(double x)
Definition: qgspointv2.h:46
static double leftOfLine(double x, double y, double x1, double y1, double x2, double y2)
Returns < 0 if point(x/y) is left of the line x1,y1 -> x2,y2.
void append(const QgsLineStringV2 *line)
QDomElement createElementNS(const QString &nsURI, const QString &qName)
virtual QgsPointV2 endPoint() const override
Returns the end point of the curve.
static endian_t endian()
Returns whether this machine uses big or little endian.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
void setY(double y)
Definition: qgspointv2.h:47
int size() const
void addToPainterPath(QPainterPath &path) const override
Adds a curve to a painter path.
double y() const
Definition: qgspointv2.h:42
virtual QgsLineStringV2 * curveToLine() const override
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:8
bool pointAt(int i, QgsPointV2 &vertex, QgsVertexId::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
void clear()
static Type flatType(Type type)
Definition: qgswkbtypes.cpp:46
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
qreal x() const
qreal y() const
void resize(int size)
Utility class for identifying a unique vertex within a geometry.
bool isMeasure() const
Returns true if the geometry contains m values.
double z() const
Definition: qgspointv2.h:43
Line string geometry type.
QDomElement asGML3(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML3 representation of the geometry.
void lineTo(const QPointF &endPoint)
Point geometry type.
Definition: qgspointv2.h:29
void fromWkbPoints(QgsWKBTypes::Type type, const QgsConstWkbPtr &wkb)
void remove(int i)
virtual double length() const override
Returns the length (or perimeter for area geometries) of the geometry.
unsigned char * asWkb(int &binarySize) const override
Returns a WKB representation of the geometry.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
void setZMTypeFromSubGeometry(const QgsAbstractGeometryV2 *subggeom, QgsWKBTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
virtual QString geometryType() const override
Returns a unique string representing the geometry type.
virtual bool deleteVertex(const QgsVertexId &position) override
Deletes a vertex within the geometry.
QString asJSON(int precision=17) const override
Returns a GeoJSON representation of the geometry.
static QDomElement pointsToGML3(const QList< QgsPointV2 > &points, QDomDocument &doc, int precision, const QString &ns, bool is3D)
Returns a gml::posList DOM element.
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.
virtual QgsPointV2 startPoint() const override
Returns the starting point of the curve.
void addVertex(const QgsPointV2 &pt)
const T & at(int i) const
void setPoints(const QList< QgsPointV2 > &points)
virtual bool isClosed() const
Returns true if the curve is closed.
Definition: qgscurvev2.cpp:27
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
bool isEmpty() const
static QList< QgsPointV2 > pointsFromWKT(const QString &wktCoordinateList, bool is3D, bool isMeasure)
Returns a list of points contained in a WKT string.
Class for doing transforms between two map coordinate systems.
double m() const
Definition: qgspointv2.h:44
static double sqrDistToLine(double ptX, double ptY, double x1, double y1, double x2, double y2, double &minDistX, double &minDistY, double epsilon)
Returns the squared distance between a point and a line.
static Type parseType(const QString &wktStr)
Definition: qgswkbtypes.cpp:56
double ANALYSIS_EXPORT leftOf(Point3D *thepoint, Point3D *p1, Point3D *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'.
virtual bool fromWkb(const unsigned char *wkb) override
Sets the geometry from a WKB string.
int wkbSize() const override
Returns the size of the WKB representation of the geometry.
void sumUpArea(double &sum) const override
Calculates the area of the curve.
Abstract base class for curved geometry type.
Definition: qgscurvev2.h:32
int size() const
static void pointsToWKB(QgsWkbPtr &wkb, const QList< QgsPointV2 > &points, bool is3D, bool isMeasure)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
static QDomElement pointsToGML2(const QList< QgsPointV2 > &points, QDomDocument &doc, int precision, const QString &ns)
Returns a gml::coordinates DOM element.
int max(int a, int b)
Definition: util.h:87
virtual void clear() override
Clears the geometry, ie reset it to a null geometry.
int numPoints() const override
Returns the number of points in the curve.