QGIS API Documentation  2.12.0-Lyon
qgsabstractgeometryv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsabstractgeometryv2.cpp
3  -------------------------------------------------------------------
4 Date : 04 Sept 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 "qgsapplication.h"
17 #include "qgsabstractgeometryv2.h"
18 #include "qgswkbptr.h"
19 #include "qgsgeos.h"
20 #include "qgsmaptopixel.h"
21 #include <limits>
22 #include <QTransform>
23 
25 {
26 }
27 
29 {
30 }
31 
33 {
34  mWkbType = geom.mWkbType;
35 }
36 
38 {
39  if ( &geom != this )
40  {
41  clear();
42  mWkbType = geom.mWkbType;
43  }
44  return *this;
45 }
46 
48 {
49  if ( mBoundingBox.isNull() )
50  {
52  }
53  return mBoundingBox;
54 }
55 
57 {
58  return(( mWkbType >= 1001 && mWkbType <= 1017 ) || ( mWkbType > 3000 || mWkbType & 0x80000000 ) );
59 }
60 
62 {
63  return ( mWkbType >= 2001 && mWkbType <= 3017 );
64 }
65 
66 #if 0
67 void QgsAbstractGeometryV2::clip( const QgsRectangle& rect )
68 {
69  // TODO
70  // - Implementation
71  // - API doc in header
72 
73  // Don't insert Q_UNUSED, so we have a warning that reminds us of this TODO
74 }
75 #endif
76 
78 {
79  if ( !subgeom )
80  {
81  return;
82  }
83 
84  bool hasZ = subgeom->is3D();
85  bool hasM = subgeom->isMeasure();
86 
87  if ( hasZ && hasM )
88  {
89  mWkbType = ( QgsWKBTypes::Type )( baseGeomType + 3000 );
90  }
91  else if ( hasZ )
92  {
93  mWkbType = ( QgsWKBTypes::Type )( baseGeomType + 1000 );
94  }
95  else if ( hasM )
96  {
97  mWkbType = ( QgsWKBTypes::Type )( baseGeomType + 2000 );
98  }
99  else
100  {
101  mWkbType = baseGeomType;
102  }
103 }
104 
106 {
107  double xmin = std::numeric_limits<double>::max();
108  double ymin = std::numeric_limits<double>::max();
109  double xmax = -std::numeric_limits<double>::max();
110  double ymax = -std::numeric_limits<double>::max();
111 
112  QgsVertexId id;
113  QgsPointV2 vertex;
114  double x, y;
115  while ( nextVertex( id, vertex ) )
116  {
117  x = vertex.x();
118  y = vertex.y();
119  if ( x < xmin )
120  xmin = x;
121  if ( x > xmax )
122  xmax = x;
123  if ( y < ymin )
124  ymin = y;
125  if ( y > ymax )
126  ymax = y;
127  }
128 
129  return QgsRectangle( xmin, ymin, xmax, ymax );
130 }
131 
133 {
134  QList< QList< QList< QgsPointV2 > > > coordinates;
135  coordinateSequence( coordinates );
136  int nCoords = 0;
137 
138  QList< QList< QList< QgsPointV2 > > >::const_iterator partIt = coordinates.constBegin();
139  for ( ; partIt != coordinates.constEnd(); ++partIt )
140  {
141  const QList< QList< QgsPointV2 > >& part = *partIt;
142  QList< QList< QgsPointV2 > >::const_iterator ringIt = part.constBegin();
143  for ( ; ringIt != part.constEnd(); ++ringIt )
144  {
145  nCoords += ringIt->size();
146  }
147  }
148 
149  return nCoords;
150 }
151 
153 {
154  QString wkt = geometryType();
155  if ( is3D() )
156  wkt += "Z";
157  if ( isMeasure() )
158  wkt += "M";
159  return wkt;
160 }
161 
162 bool QgsAbstractGeometryV2::readWkbHeader( QgsConstWkbPtr& wkbPtr, QgsWKBTypes::Type& wkbType, bool& endianSwap, QgsWKBTypes::Type expectedType )
163 {
164  if ( !static_cast<const unsigned char*>( wkbPtr ) )
165  {
166  return false;
167  }
168 
169  char wkbEndian;
170  wkbPtr >> wkbEndian;
171  endianSwap = wkbEndian != QgsApplication::endian();
172 
173  wkbPtr >> wkbType;
174  if ( endianSwap )
175  QgsApplication::endian_swap( wkbType );
176 
177  if ( QgsWKBTypes::flatType( wkbType ) != expectedType )
178  {
179  wkbType = QgsWKBTypes::Unknown;
180  return false;
181  }
182  return true;
183 }
184 
186 {
187  // http://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon
188  // Pick the first ring of first part for the moment
189 
190  int n = vertexCount( 0, 0 );
191  if ( n == 1 )
192  {
193  return vertexAt( QgsVertexId( 0, 0, 0 ) );
194  }
195 
196  double A = 0.;
197  double Cx = 0.;
198  double Cy = 0.;
199  int i = 0, j = 1;
200  if ( vertexAt( QgsVertexId( 0, 0, 0 ) ) != vertexAt( QgsVertexId( 0, 0, n - 1 ) ) )
201  {
202  i = n - 1;
203  j = 0;
204  }
205  for ( ; j < n; i = j++ )
206  {
207  QgsPointV2 vi = vertexAt( QgsVertexId( 0, 0, i ) );
208  QgsPointV2 vj = vertexAt( QgsVertexId( 0, 0, j ) );
209  double d = vi.x() * vj.y() - vj.x() * vi.y();
210  A += d;
211  Cx += ( vi.x() + vj.x() ) * d;
212  Cy += ( vi.y() + vj.y() ) * d;
213  }
214 
215  if ( A < 1E-12 )
216  {
217  Cx = Cy = 0.;
218  for ( int i = 0; i < n - 1; ++i )
219  {
220  QgsPointV2 vi = vertexAt( QgsVertexId( 0, 0, i ) );
221  Cx += vi.x();
222  Cy += vi.y();
223  }
224  return QgsPointV2( Cx / ( n - 1 ), Cy / ( n - 1 ) );
225  }
226  else
227  {
228  return QgsPointV2( Cx / ( 3. * A ), Cy / ( 3. * A ) );
229  }
230 }
231 
233 {
234  QgsVertexId vId; QgsPointV2 vertex;
235  return !nextVertex( vId, vertex );
236 }
static void endian_swap(T &value)
Swap the endianness of the specified value.
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
virtual QgsPointV2 centroid() const
Returns the centroid of the geometry.
virtual QgsAbstractGeometryV2 & operator=(const QgsAbstractGeometryV2 &geom)
double x() const
Definition: qgspointv2.h:42
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Abstract base class for all geometries.
static endian_t endian()
Returns whether this machine uses big or little endian.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
int nCoordinates() const
Returns the number of nodes contained in the geometry.
static bool readWkbHeader(QgsConstWkbPtr &wkbPtr, QgsWKBTypes::Type &wkbType, bool &endianSwap, QgsWKBTypes::Type expectedType)
Reads a WKB header and tests its validity.
int size() const
double y() const
Definition: qgspointv2.h:43
virtual void clear()=0
Clears the geometry, ie reset it to a null geometry.
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
static Type flatType(Type type)
Definition: qgswkbtypes.cpp:46
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
Utility class for identifying a unique vertex within a geometry.
bool isMeasure() const
Returns true if the geometry contains m values.
virtual QgsRectangle calculateBoundingBox() const
Calculates the minimal bounding box for the geometry.
bool isEmpty() const
Returns true if the geometry is empty.
Point geometry type.
Definition: qgspointv2.h:29
void setZMTypeFromSubGeometry(const QgsAbstractGeometryV2 *subggeom, QgsWKBTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
virtual bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const =0
Returns next vertex id and coordinates.
virtual QgsPointV2 vertexAt(const QgsVertexId &id) const =0
Returns the point corresponding to a specified vertex id.
virtual QString geometryType() const =0
Returns a unique string representing the geometry type.
virtual int vertexCount(int part=0, int ring=0) const =0
Class to store information about wkb types.
Definition: qgswkbtypes.h:25
virtual void coordinateSequence(QList< QList< QList< QgsPointV2 > > > &coord) const =0
Retrieves the sequence of geometries, rings and nodes.
const_iterator constEnd() const
const_iterator constBegin() const
QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.