QGIS API Documentation  2.10.1-Pisa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsgeometryutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometryutils.cpp
3  -------------------------------------------------------------------
4 Date : 21 Nov 2014
5 Copyright : (C) 2014 by Marco Hugentobler
6 email : marco.hugentobler at sourcepole dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsgeometryutils.h"
17 #include "qgswkbptr.h"
18 #include <QStringList>
19 
21 {
22  double minDist = std::numeric_limits<double>::max();
23  double currentDist = 0;
24  QgsPointV2 minDistPoint;
25 
26  QgsVertexId vertexId;
27  QgsPointV2 vertex;
28  while ( geom.nextVertex( vertexId, vertex ) )
29  {
30  currentDist = QgsGeometryUtils::sqrDistance2D( pt, vertex );
31  // The <= is on purpose: for geometries with closing vertices, this ensures
32  // that the closing vertex is retuned. For the node tool, the rubberband
33  // of the closing vertex is above the opening vertex, hence with the <=
34  // situations where the covered opening vertex rubberband is selected are
35  // avoided.
36  if ( currentDist <= minDist )
37  {
38  minDist = currentDist;
39  minDistPoint = vertex;
40  id.part = vertexId.part;
41  id.ring = vertexId.ring;
42  id.vertex = vertexId.vertex;
43  }
44  }
45 
46  return minDistPoint;
47 }
48 
49 void QgsGeometryUtils::adjacentVertices( const QgsAbstractGeometryV2& geom, const QgsVertexId& atVertex, QgsVertexId& beforeVertex, QgsVertexId& afterVertex )
50 {
51  bool polygonType = ( geom.dimension() == 2 );
53  geom.coordinateSequence( coords );
54 
55  //get feature
56  if ( coords.size() <= atVertex.part )
57  {
58  return; //error, no such feature
59  }
60  const QList< QList< QgsPointV2 > >& part = coords.at( atVertex.part );
61 
62  //get ring
63  if ( part.size() <= atVertex.ring )
64  {
65  return; //error, no such ring
66  }
67  const QList< QgsPointV2 >& ring = part.at( atVertex.ring );
68  if ( ring.size() <= atVertex.vertex )
69  {
70  return;
71  }
72 
73  //vertex in the middle
74  if ( atVertex.vertex > 0 && atVertex.vertex < ring.size() - 1 )
75  {
76  beforeVertex.part = atVertex.part; beforeVertex.ring = atVertex.ring; beforeVertex.vertex = atVertex.vertex - 1;
77  afterVertex.part = atVertex.part; afterVertex.ring = atVertex.ring; afterVertex.vertex = atVertex.vertex + 1;
78  }
79  else if ( atVertex.vertex == 0 )
80  {
81  afterVertex.part = atVertex.part; afterVertex.ring = atVertex.ring; afterVertex.vertex = atVertex.vertex + 1;
82  if ( polygonType && ring.size() > 3 )
83  {
84  beforeVertex.part = atVertex.part; beforeVertex.ring = atVertex.ring; beforeVertex.vertex = ring.size() - 2;
85  }
86  else
87  {
88  beforeVertex = QgsVertexId(); //before vertex invalid
89  }
90  }
91  else if ( atVertex.vertex == ring.size() - 1 )
92  {
93  beforeVertex.part = atVertex.part; beforeVertex.ring = atVertex.ring; beforeVertex.vertex = atVertex.vertex - 1;
94  if ( polygonType )
95  {
96  afterVertex.part = atVertex.part; afterVertex.ring = atVertex.ring; afterVertex.vertex = 1;
97  }
98  else
99  {
100  afterVertex = QgsVertexId(); //after vertex invalid
101  }
102  }
103 }
104 
105 double QgsGeometryUtils::sqrDistance2D( const QgsPointV2& pt1, const QgsPointV2& pt2 )
106 {
107  return ( pt1.x() - pt2.x() ) * ( pt1.x() - pt2.x() ) + ( pt1.y() - pt2.y() ) * ( pt1.y() - pt2.y() );
108 }
109 
110 double QgsGeometryUtils::sqrDistToLine( double ptX, double ptY, double x1, double y1, double x2, double y2, double& minDistX, double& minDistY, double epsilon )
111 {
112  //normal vector
113  double nx = y2 - y1;
114  double ny = -( x2 - x1 );
115 
116  double t;
117  t = ( ptX * ny - ptY * nx - x1 * ny + y1 * nx ) / (( x2 - x1 ) * ny - ( y2 - y1 ) * nx );
118 
119  if ( t < 0.0 )
120  {
121  minDistX = x1;
122  minDistY = y1;
123  }
124  else if ( t > 1.0 )
125  {
126  minDistX = x2;
127  minDistY = y2;
128  }
129  else
130  {
131  minDistX = x1 + t * ( x2 - x1 );
132  minDistY = y1 + t * ( y2 - y1 );
133  }
134 
135  double dist = ( minDistX - ptX ) * ( minDistX - ptX ) + ( minDistY - ptY ) * ( minDistY - ptY );
136 
137  //prevent rounding errors if the point is directly on the segment
138  if ( qgsDoubleNear( dist, 0.0, epsilon ) )
139  {
140  minDistX = ptX;
141  minDistY = ptY;
142  return 0.0;
143  }
144 
145  return dist;
146 }
147 
148 double QgsGeometryUtils::leftOfLine( double x, double y, double x1, double y1, double x2, double y2 )
149 {
150  double f1 = x - x1;
151  double f2 = y2 - y1;
152  double f3 = y - y1;
153  double f4 = x2 - x1;
154  return f1*f2 - f3*f4;
155 }
156 
157 QgsPointV2 QgsGeometryUtils::pointOnLineWithDistance( const QgsPointV2& startPoint, const QgsPointV2& directionPoint, double distance )
158 {
159  double dx = directionPoint.x() - startPoint.x();
160  double dy = directionPoint.y() - startPoint.y();
161  double length = sqrt( dx * dx + dy * dy );
162 
163  if ( qgsDoubleNear( length, 0.0 ) )
164  {
165  return startPoint;
166  }
167 
168  double scaleFactor = distance / length;
169  return QgsPointV2( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
170 }
171 
172 double QgsGeometryUtils::ccwAngle( double dy, double dx )
173 {
174  double angle = atan2( dy, dx ) * 180 / M_PI;
175  if ( angle < 0 )
176  {
177  return 360 + angle;
178  }
179  else if ( angle > 360 )
180  {
181  return 360 - angle;
182  }
183  return angle;
184 }
185 
186 void QgsGeometryUtils::circleCenterRadius( const QgsPointV2& pt1, const QgsPointV2& pt2, const QgsPointV2& pt3, double& radius, double& centerX, double& centerY )
187 {
188  double temp, bc, cd, det;
189 
190  //closed circle
191  if ( qgsDoubleNear( pt1.x(), pt3.x() ) && qgsDoubleNear( pt1.y(), pt3.y() ) )
192  {
193  centerX = pt2.x();
194  centerY = pt2.y();
195  radius = sqrt( pow( pt2.x() - pt1.x(), 2.0 ) + pow( pt2.y() - pt1.y(), 2.0 ) );
196  return;
197  }
198 
199  temp = pt2.x() * pt2.x() + pt2.y() * pt2.y();
200  bc = ( pt1.x() * pt1.x() + pt1.y() * pt1.y() - temp ) / 2.0;
201  cd = ( temp - pt3.x() * pt3.x() - pt3.y() * pt3.y() ) / 2.0;
202  det = ( pt1.x() - pt2.x() ) * ( pt2.y() - pt3.y() ) - ( pt2.x() - pt3.x() ) * ( pt1.y() - pt2.y() );
203 
204  /* Check colinearity */
205  if ( qgsDoubleNear( fabs( det ), 0.0 ) )
206  {
207  radius = -1.0;
208  return;
209  }
210 
211  det = 1.0 / det;
212  centerX = ( bc * ( pt2.y() - pt3.y() ) - cd * ( pt1.y() - pt2.y() ) ) * det;
213  centerY = (( pt1.x() - pt2.x() ) * cd - ( pt2.x() - pt3.x() ) * bc ) * det;
214  radius = sqrt(( centerX - pt1.x() ) * ( centerX - pt1.x() ) + ( centerY - pt1.y() ) * ( centerY - pt1.y() ) );
215 }
216 
217 bool QgsGeometryUtils::circleClockwise( double angle1, double angle2, double angle3 )
218 {
219  if ( angle3 >= angle1 )
220  {
221  if ( angle2 > angle1 && angle2 < angle3 )
222  {
223  return false;
224  }
225  else
226  {
227  return true;
228  }
229  }
230  else
231  {
232  if ( angle2 > angle1 || angle2 < angle3 )
233  {
234  return false;
235  }
236  else
237  {
238  return true;
239  }
240  }
241 }
242 
243 bool QgsGeometryUtils::circleAngleBetween( double angle, double angle1, double angle2, bool clockwise )
244 {
245  if ( clockwise )
246  {
247  if ( angle2 < angle1 )
248  {
249  return ( angle <= angle1 && angle >= angle2 );
250  }
251  else
252  {
253  return ( angle <= angle1 || angle >= angle2 );
254  }
255  }
256  else
257  {
258  if ( angle2 > angle1 )
259  {
260  return ( angle >= angle1 && angle <= angle2 );
261  }
262  else
263  {
264  return ( angle >= angle1 || angle <= angle2 );
265  }
266  }
267 }
268 
269 bool QgsGeometryUtils::angleOnCircle( double angle, double angle1, double angle2, double angle3 )
270 {
271  bool clockwise = circleClockwise( angle1, angle2, angle3 );
272  return circleAngleBetween( angle, angle1, angle3, clockwise );
273 }
274 
275 double QgsGeometryUtils::circleLength( double x1, double y1, double x2, double y2, double x3, double y3 )
276 {
277  double centerX, centerY, radius;
278  circleCenterRadius( QgsPointV2( x1, y1 ), QgsPointV2( x2, y2 ), QgsPointV2( x3, y3 ), radius, centerX, centerY );
279  double length = M_PI / 180.0 * radius * sweepAngle( centerX, centerY, x1, y1, x2, y2, x3, y3 );
280  if ( length < 0 )
281  {
282  length = -length;
283  }
284  return length;
285 }
286 
287 double QgsGeometryUtils::sweepAngle( double centerX, double centerY, double x1, double y1, double x2, double y2, double x3, double y3 )
288 {
289  double p1Angle = QgsGeometryUtils::ccwAngle( y1 - centerY, x1 - centerX );
290  double p2Angle = QgsGeometryUtils::ccwAngle( y2 - centerY, x2 - centerX );
291  double p3Angle = QgsGeometryUtils::ccwAngle( y3 - centerY, x3 - centerX );
292 
293  if ( p3Angle >= p1Angle )
294  {
295  if ( p2Angle > p1Angle && p2Angle < p3Angle )
296  {
297  return( p3Angle - p1Angle );
298  }
299  else
300  {
301  return ( - ( p1Angle + ( 360 - p3Angle ) ) );
302  }
303  }
304  else
305  {
306  if ( p2Angle < p1Angle && p2Angle > p3Angle )
307  {
308  return( -( p1Angle - p3Angle ) );
309  }
310  else
311  {
312  return( p3Angle + ( 360 - p1Angle ) );
313  }
314  }
315 }
316 
317 bool QgsGeometryUtils::segmentMidPoint( const QgsPointV2& p1, const QgsPointV2& p2, QgsPointV2& result, double radius, const QgsPointV2& mousePos )
318 {
319  QgsPointV2 midPoint(( p1.x() + p2.x() ) / 2.0, ( p1.y() + p2.y() ) / 2.0 );
320  double midDist = sqrt( sqrDistance2D( p1, midPoint ) );
321  if ( radius < midDist )
322  {
323  return false;
324  }
325  double centerMidDist = sqrt( radius * radius - midDist * midDist );
326  double dist = radius - centerMidDist;
327 
328  double midDx = midPoint.x() - p1.x();
329  double midDy = midPoint.y() - p1.y();
330 
331  //get the four possible midpoints
332  QList<QgsPointV2> possibleMidPoints;
333  possibleMidPoints.append( pointOnLineWithDistance( midPoint, QgsPointV2( midPoint.x() - midDy, midPoint.y() + midDx ), dist ) );
334  possibleMidPoints.append( pointOnLineWithDistance( midPoint, QgsPointV2( midPoint.x() - midDy, midPoint.y() + midDx ), 2 * radius - dist ) );
335  possibleMidPoints.append( pointOnLineWithDistance( midPoint, QgsPointV2( midPoint.x() + midDy, midPoint.y() - midDx ), dist ) );
336  possibleMidPoints.append( pointOnLineWithDistance( midPoint, QgsPointV2( midPoint.x() + midDy, midPoint.y() - midDx ), 2 * radius - dist ) );
337 
338  //take the closest one
339  double minDist = std::numeric_limits<double>::max();
340  int minDistIndex = -1;
341  for ( int i = 0; i < possibleMidPoints.size(); ++i )
342  {
343  double currentDist = sqrDistance2D( mousePos, possibleMidPoints.at( i ) );
344  if ( currentDist < minDist )
345  {
346  minDistIndex = i;
347  minDist = currentDist;
348  }
349  }
350 
351  if ( minDistIndex == -1 )
352  {
353  return false;
354  }
355 
356  result = possibleMidPoints.at( minDistIndex );
357  return true;
358 }
359 
360 QList<QgsPointV2> QgsGeometryUtils::pointsFromWKT( const QString &wktCoordinateList, bool is3D, bool isMeasure )
361 {
362  int dim = 2 + is3D + isMeasure;
363  QList<QgsPointV2> points;
364  foreach ( const QString& pointCoordinates, wktCoordinateList.split( ",", QString::SkipEmptyParts ) )
365  {
366  QStringList coordinates = pointCoordinates.split( " ", QString::SkipEmptyParts );
367  if ( coordinates.size() < dim )
368  continue;
369 
370  int idx = 0;
371  double x = coordinates[idx++].toDouble();
372  double y = coordinates[idx++].toDouble();
373 
374  double z = is3D ? coordinates[idx++].toDouble() : 0.;
375  double m = isMeasure ? coordinates[idx++].toDouble() : 0.;
376 
378  if ( is3D )
379  {
380  if ( isMeasure )
382  else
384  }
385  else
386  {
387  if ( isMeasure )
389  else
390  t = QgsWKBTypes::Point;
391  }
392 
393  points.append( QgsPointV2( t, x, y, z, m ) );
394  }
395  return points;
396 }
397 
398 void QgsGeometryUtils::pointsToWKB( QgsWkbPtr& wkb, const QList<QgsPointV2> &points, bool is3D, bool isMeasure )
399 {
400  wkb << static_cast<quint32>( points.size() );
401  foreach ( const QgsPointV2& point, points )
402  {
403  wkb << point.x() << point.y();
404  if ( is3D )
405  {
406  wkb << point.z();
407  }
408  if ( isMeasure )
409  {
410  wkb << point.m();
411  }
412  }
413 }
414 
415 QString QgsGeometryUtils::pointsToWKT( const QList<QgsPointV2>& points, int precision, bool is3D, bool isMeasure )
416 {
417  QString wkt = "(";
418  foreach ( const QgsPointV2& p, points )
419  {
420  wkt += qgsDoubleToString( p.x(), precision );
421  wkt += " " + qgsDoubleToString( p.y(), precision );
422  if ( is3D )
423  wkt += " " + qgsDoubleToString( p.z(), precision );
424  if ( isMeasure )
425  wkt += " " + qgsDoubleToString( p.m(), precision );
426  wkt += ", ";
427  }
428  if ( wkt.endsWith( ", " ) )
429  wkt.chop( 2 ); // Remove last ", "
430  wkt += ")";
431  return wkt;
432 }
433 
434 QDomElement QgsGeometryUtils::pointsToGML2( const QList<QgsPointV2>& points, QDomDocument& doc, int precision, const QString &ns )
435 {
436  QDomElement elemCoordinates = doc.createElementNS( ns, "coordinates" );
437 
438  QString strCoordinates;
439 
440  foreach ( const QgsPointV2& p, points )
441  strCoordinates += qgsDoubleToString( p.x(), precision ) + "," + qgsDoubleToString( p.y(), precision ) + " ";
442 
443  if ( strCoordinates.endsWith( " " ) )
444  strCoordinates.chop( 1 ); // Remove trailing space
445 
446  elemCoordinates.appendChild( doc.createTextNode( strCoordinates ) );
447  return elemCoordinates;
448 }
449 
450 QDomElement QgsGeometryUtils::pointsToGML3( const QList<QgsPointV2>& points, QDomDocument& doc, int precision, const QString &ns, bool is3D )
451 {
452  QDomElement elemPosList = doc.createElementNS( ns, "posList" );
453  elemPosList.setAttribute( "srsDimension", is3D ? 3 : 2 );
454 
455  QString strCoordinates;
456  foreach ( const QgsPointV2& p, points )
457  {
458  strCoordinates += qgsDoubleToString( p.x(), precision ) + " " + qgsDoubleToString( p.y(), precision ) + " ";
459  if ( is3D )
460  strCoordinates += qgsDoubleToString( p.z(), precision ) + " ";
461  }
462  if ( strCoordinates.endsWith( " " ) )
463  strCoordinates.chop( 1 ); // Remove trailing space
464 
465  elemPosList.appendChild( doc.createTextNode( strCoordinates ) );
466  return elemPosList;
467 }
468 
470 {
471  QString json = "[ ";
472  foreach ( const QgsPointV2& p, points )
473  {
474  json += "[" + qgsDoubleToString( p.x(), precision ) + ", " + qgsDoubleToString( p.y(), precision ) + "], ";
475  }
476  if ( json.endsWith( ", " ) )
477  {
478  json.chop( 2 ); // Remove last ", "
479  }
480  json += "]";
481  return json;
482 }
483 
485 {
486  QgsWKBTypes::Type wkbType = QgsWKBTypes::parseType( wkt );
487 
488  QRegExp cooRegEx( "^[^\\(]*\\((.*)\\)[^\\)]*$" );
489  QString contents = cooRegEx.indexIn( wkt ) >= 0 ? cooRegEx.cap( 1 ) : QString();
490  return qMakePair( wkbType, contents );
491 }
492 
494 {
495  int level = 0;
496  QString block;
497  QStringList blocks;
498  for ( int i = 0, n = wkt.length(); i < n; ++i )
499  {
500  if ( wkt[i].isSpace() && level == 0 )
501  continue;
502 
503  if ( wkt[i] == ',' && level == 0 )
504  {
505  if ( !block.isEmpty() )
506  {
507  if ( block.startsWith( "(" ) && !defaultType.isEmpty() )
508  block.prepend( defaultType + " " );
509  blocks.append( block );
510  }
511  block.clear();
512  continue;
513  }
514  if ( wkt[i] == '(' )
515  ++level;
516  else if ( wkt[i] == ')' )
517  --level;
518  block += wkt[i];
519  }
520  if ( !block.isEmpty() )
521  {
522  if ( block.startsWith( "(" ) && !defaultType.isEmpty() )
523  block.prepend( defaultType + " " );
524  blocks.append( block );
525  }
526  return blocks;
527 }
static QgsPointV2 pointOnLineWithDistance(const QgsPointV2 &startPoint, const QgsPointV2 &directionPoint, double distance)
Returns a point a specified distance toward a second point.
QString cap(int nth) 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 (...
static bool circleAngleBetween(double angle, double angle1, double angle2, bool clockwise)
Returns true if, in a circle, angle is between angle1 and angle2.
static double ccwAngle(double dy, double dx)
Returns the counter clockwise angle between a line with components dx, dy and the line with dx > 0 an...
QDomNode appendChild(const QDomNode &newChild)
double x() const
Definition: qgspointv2.h:41
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
QString & prepend(QChar ch)
static QString pointsToWKT(const QList< QgsPointV2 > &points, int precision, bool is3D, bool isMeasure)
Returns a WKT coordinate list.
const T & at(int i) const
static QString pointsToJSON(const QList< QgsPointV2 > &points, int precision)
Returns a geoJSON coordinates string.
static void circleCenterRadius(const QgsPointV2 &pt1, const QgsPointV2 &pt2, const QgsPointV2 &pt3, double &radius, double &centerX, double &centerY)
Returns radius and center of the circle through pt1, pt2, pt3.
Abstract base class for all geometries.
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType="")
Parses a WKT string and returns of list of blocks contained in the WKT.
static QgsPointV2 closestVertex(const QgsAbstractGeometryV2 &geom, const QgsPointV2 &pt, QgsVertexId &id)
Returns the closest vertex to a geometry for a specified point.
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.
static double circleLength(double x1, double y1, double x2, double y2, double x3, double y3)
Length of a circular string segment defined by pt1, pt2, pt3.
QDomElement createElementNS(const QString &nsURI, const QString &qName)
void chop(int n)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:350
int size() const
double y() const
Definition: qgspointv2.h:42
void clear()
int indexIn(const QString &str, int offset, CaretMode caretMode) const
static bool circleClockwise(double angle1, double angle2, double angle3)
Returns true if circle is ordered clockwise.
void append(const T &value)
static void adjacentVertices(const QgsAbstractGeometryV2 &geom, const QgsVertexId &atVertex, QgsVertexId &beforeVertex, QgsVertexId &afterVertex)
Returns vertices adjacent to a specified vertex within a geometry.
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.
double z() const
Definition: qgspointv2.h:43
void setAttribute(const QString &name, const QString &value)
Point geometry type.
Definition: qgspointv2.h:29
bool isEmpty() const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
#define M_PI
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
static bool angleOnCircle(double angle, double angle1, double angle2, double angle3)
Returns true if an angle is between angle1 and angle3 on a circle described by angle1, angle2 and angle3.
virtual bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const =0
Returns next vertex id and coordinates.
QDomText createTextNode(const QString &value)
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
static QDomElement pointsToGML3(const QList< QgsPointV2 > &points, QDomDocument &doc, int precision, const QString &ns, bool is3D)
Returns a gml::posList DOM element.
QString qgsDoubleToString(const double &a, const int &precision=17)
Definition: qgis.h:339
static bool segmentMidPoint(const QgsPointV2 &p1, const QgsPointV2 &p2, QgsPointV2 &result, double radius, const QgsPointV2 &mousePos)
Calculates midpoint on circle passing through p1 and p2, closest to given coordinate.
static double sweepAngle(double centerX, double centerY, double x1, double y1, double x2, double y2, double x3, double y3)
Calculates angle of a circular string part defined by pt1, pt2, pt3.
virtual int dimension() const =0
Returns the inherent dimension of the geometry.
static QList< QgsPointV2 > pointsFromWKT(const QString &wktCoordinateList, bool is3D, bool isMeasure)
Returns a list of points contained in a WKT string.
virtual void coordinateSequence(QList< QList< QList< QgsPointV2 > > > &coord) const =0
Retrieves the sequence of geometries, rings and nodes.
int length() const
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
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