QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsgeometryfactory.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometryfactory.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 "qgsgeometryfactory.h"
19 #include "qgscircularstring.h"
20 #include "qgscompoundcurve.h"
21 #include "qgscurvepolygon.h"
22 #include "qgspoint.h"
23 #include "qgspolygon.h"
24 #include "qgslinestring.h"
25 #include "qgsmulticurve.h"
26 #include "qgsmultilinestring.h"
27 #include "qgsmultipoint.h"
28 #include "qgsmultipolygon.h"
29 #include "qgsmultisurface.h"
30 #include "qgstriangle.h"
31 #include "qgswkbtypes.h"
32 #include "qgslogger.h"
33 
34 std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkb( QgsConstWkbPtr &wkbPtr )
35 {
36  if ( !wkbPtr )
37  return nullptr;
38 
39  //find out type (bytes 2-5)
41  try
42  {
43  type = wkbPtr.readHeader();
44  }
45  catch ( const QgsWkbException &e )
46  {
47  Q_UNUSED( e )
48  QgsDebugMsg( "WKB exception while reading header: " + e.what() );
49  return nullptr;
50  }
51  wkbPtr -= 1 + sizeof( int );
52 
53  std::unique_ptr< QgsAbstractGeometry > geom = geomFromWkbType( type );
54 
55  if ( geom )
56  {
57  try
58  {
59  geom->fromWkb( wkbPtr ); // also updates wkbPtr
60  }
61  catch ( const QgsWkbException &e )
62  {
63  Q_UNUSED( e )
64  QgsDebugMsg( "WKB exception: " + e.what() );
65  geom.reset();
66  }
67  }
68 
69  return geom;
70 }
71 
72 std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkt( const QString &text )
73 {
74  const QString trimmed = text.trimmed();
75  std::unique_ptr< QgsAbstractGeometry> geom;
76  if ( trimmed.startsWith( QLatin1String( "Point" ), Qt::CaseInsensitive ) )
77  {
78  geom = std::make_unique< QgsPoint >();
79  }
80  else if ( trimmed.startsWith( QLatin1String( "LineString" ), Qt::CaseInsensitive ) )
81  {
82  geom = std::make_unique< QgsLineString >();
83  }
84  else if ( trimmed.startsWith( QLatin1String( "CircularString" ), Qt::CaseInsensitive ) )
85  {
86  geom = std::make_unique< QgsCircularString >();
87  }
88  else if ( trimmed.startsWith( QLatin1String( "CompoundCurve" ), Qt::CaseInsensitive ) )
89  {
90  geom = std::make_unique< QgsCompoundCurve>();
91  }
92  else if ( trimmed.startsWith( QLatin1String( "Polygon" ), Qt::CaseInsensitive ) )
93  {
94  geom = std::make_unique< QgsPolygon >();
95  }
96  else if ( trimmed.startsWith( QLatin1String( "Triangle" ), Qt::CaseInsensitive ) )
97  {
98  geom = std::make_unique< QgsTriangle >();
99  }
100  else if ( trimmed.startsWith( QLatin1String( "CurvePolygon" ), Qt::CaseInsensitive ) )
101  {
102  geom = std::make_unique< QgsCurvePolygon >();
103  }
104  else if ( trimmed.startsWith( QLatin1String( "MultiPoint" ), Qt::CaseInsensitive ) )
105  {
106  geom = std::make_unique< QgsMultiPoint >();
107  }
108  else if ( trimmed.startsWith( QLatin1String( "MultiCurve" ), Qt::CaseInsensitive ) )
109  {
110  geom = std::make_unique< QgsMultiCurve >();
111  }
112  else if ( trimmed.startsWith( QLatin1String( "MultiLineString" ), Qt::CaseInsensitive ) )
113  {
114  geom = std::make_unique< QgsMultiLineString >();
115  }
116  else if ( trimmed.startsWith( QLatin1String( "MultiSurface" ), Qt::CaseInsensitive ) )
117  {
118  geom = std::make_unique< QgsMultiSurface >();
119  }
120  else if ( trimmed.startsWith( QLatin1String( "MultiPolygon" ), Qt::CaseInsensitive ) )
121  {
122  geom = std::make_unique< QgsMultiPolygon >();
123  }
124  else if ( trimmed.startsWith( QLatin1String( "GeometryCollection" ), Qt::CaseInsensitive ) )
125  {
126  geom = std::make_unique< QgsGeometryCollection >();
127  }
128 
129  if ( geom )
130  {
131  if ( !geom->fromWkt( text ) )
132  {
133  return nullptr;
134  }
135  }
136  return geom;
137 }
138 
139 std::unique_ptr< QgsAbstractGeometry > QgsGeometryFactory::fromPointXY( const QgsPointXY &point )
140 {
141  return std::make_unique< QgsPoint >( point.x(), point.y() );
142 }
143 
144 std::unique_ptr<QgsMultiPoint> QgsGeometryFactory::fromMultiPointXY( const QgsMultiPointXY &multipoint )
145 {
146  std::unique_ptr< QgsMultiPoint > mp = std::make_unique< QgsMultiPoint >();
147  QgsMultiPointXY::const_iterator ptIt = multipoint.constBegin();
148  mp->reserve( multipoint.size() );
149  for ( ; ptIt != multipoint.constEnd(); ++ptIt )
150  {
151  QgsPoint *pt = new QgsPoint( ptIt->x(), ptIt->y() );
152  mp->addGeometry( pt );
153  }
154  return mp;
155 }
156 
157 std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::fromPolylineXY( const QgsPolylineXY &polyline )
158 {
159  return linestringFromPolyline( polyline );
160 }
161 
162 std::unique_ptr<QgsMultiLineString> QgsGeometryFactory::fromMultiPolylineXY( const QgsMultiPolylineXY &multiline )
163 {
164  std::unique_ptr< QgsMultiLineString > mLine = std::make_unique< QgsMultiLineString >();
165  mLine->reserve( multiline.size() );
166  for ( int i = 0; i < multiline.size(); ++i )
167  {
168  mLine->addGeometry( fromPolylineXY( multiline.at( i ) ).release() );
169  }
170  return mLine;
171 }
172 
173 std::unique_ptr<QgsPolygon> QgsGeometryFactory::fromPolygonXY( const QgsPolygonXY &polygon )
174 {
175  std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
176 
177  QVector<QgsCurve *> holes;
178  holes.reserve( polygon.size() );
179  for ( int i = 0; i < polygon.size(); ++i )
180  {
181  std::unique_ptr< QgsLineString > l = linestringFromPolyline( polygon.at( i ) );
182  l->close();
183 
184  if ( i == 0 )
185  {
186  poly->setExteriorRing( l.release() );
187  }
188  else
189  {
190  holes.push_back( l.release() );
191  }
192  }
193  poly->setInteriorRings( holes );
194  return poly;
195 }
196 
197 std::unique_ptr< QgsMultiPolygon > QgsGeometryFactory::fromMultiPolygonXY( const QgsMultiPolygonXY &multipoly )
198 {
199  std::unique_ptr< QgsMultiPolygon > mp = std::make_unique< QgsMultiPolygon >();
200  mp->reserve( multipoly.size() );
201  for ( int i = 0; i < multipoly.size(); ++i )
202  {
203  mp->addGeometry( fromPolygonXY( multipoly.at( i ) ).release() );
204  }
205  return mp;
206 }
207 
208 std::unique_ptr<QgsLineString> QgsGeometryFactory::linestringFromPolyline( const QgsPolylineXY &polyline )
209 {
210  const int size = polyline.size();
211  QVector< double > x;
212  x.resize( size );
213  QVector< double > y;
214  y.resize( size );
215  double *destX = x.data();
216  double *destY = y.data();
217  const QgsPointXY *src = polyline.data();
218  for ( int i = 0; i < size; ++i )
219  {
220  *destX++ = src->x();
221  *destY++ = src->y();
222  src++;
223  }
224  std::unique_ptr< QgsLineString > line = std::make_unique< QgsLineString >( x, y );
225  return line;
226 }
227 
228 std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkbType( QgsWkbTypes::Type t )
229 {
230  const QgsWkbTypes::Type type = QgsWkbTypes::flatType( t );
231  switch ( type )
232  {
233  case QgsWkbTypes::Point:
234  return std::make_unique< QgsPoint >();
236  return std::make_unique< QgsLineString >();
238  return std::make_unique< QgsCircularString >();
240  return std::make_unique< QgsCompoundCurve >();
242  return std::make_unique< QgsPolygon >();
244  return std::make_unique< QgsCurvePolygon >();
246  return std::make_unique< QgsMultiLineString >();
248  return std::make_unique< QgsMultiPolygon >();
250  return std::make_unique< QgsMultiPoint >();
252  return std::make_unique< QgsMultiCurve >();
254  return std::make_unique< QgsMultiSurface >();
256  return std::make_unique< QgsGeometryCollection >();
258  return std::make_unique< QgsTriangle >();
259  default:
260  return nullptr;
261  }
262 }
263 
264 std::unique_ptr<QgsGeometryCollection> QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::Type t )
265 {
267  std::unique_ptr< QgsGeometryCollection > collect;
268  switch ( type )
269  {
271  collect = std::make_unique< QgsMultiPoint >();
272  break;
274  collect = std::make_unique< QgsMultiLineString >();
275  break;
277  collect = std::make_unique< QgsMultiCurve >();
278  break;
280  collect = std::make_unique< QgsMultiPolygon >();
281  break;
283  collect = std::make_unique< QgsMultiSurface >();
284  break;
286  collect = std::make_unique< QgsGeometryCollection >();
287  break;
288  default:
289  // should not be possible
290  return nullptr;
291  }
292  if ( QgsWkbTypes::hasM( t ) )
293  collect->addMValue();
294  if ( QgsWkbTypes::hasZ( t ) )
295  collect->addZValue();
296 
297  return collect;
298 }
A const WKB pointer.
Definition: qgswkbptr.h:138
QgsWkbTypes::Type readHeader() const
readHeader
Definition: qgswkbptr.cpp:54
QString what() const
Definition: qgsexception.h:48
static std::unique_ptr< QgsMultiPolygon > fromMultiPolygonXY(const QgsMultiPolygonXY &multipoly)
Construct geometry from a multipolygon.
static std::unique_ptr< QgsAbstractGeometry > geomFromWkb(QgsConstWkbPtr &wkb)
Construct geometry from a WKB string.
static std::unique_ptr< QgsAbstractGeometry > fromPolylineXY(const QgsPolylineXY &polyline)
Construct geometry from a polyline.
static std::unique_ptr< QgsMultiPoint > fromMultiPointXY(const QgsMultiPointXY &multipoint)
Construct geometry from a multipoint.
static std::unique_ptr< QgsAbstractGeometry > geomFromWkt(const QString &text)
Construct geometry from a WKT string.
static std::unique_ptr< QgsAbstractGeometry > geomFromWkbType(QgsWkbTypes::Type t)
Returns empty geometry from wkb type.
static std::unique_ptr< QgsMultiLineString > fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Construct geometry from a multipolyline.
static std::unique_ptr< QgsGeometryCollection > createCollectionOfType(QgsWkbTypes::Type type)
Returns a new geometry collection matching a specified WKB type.
static std::unique_ptr< QgsAbstractGeometry > fromPointXY(const QgsPointXY &point)
Construct geometry from a point.
static std::unique_ptr< QgsPolygon > fromPolygonXY(const QgsPolygonXY &polygon)
Construct geometry from a polygon.
A class to represent a 2D point.
Definition: qgspointxy.h:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Custom exception class for Wkb related exceptions.
Definition: qgswkbptr.h:31
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1130
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
@ GeometryCollection
Definition: qgswkbtypes.h:79
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
static Type multiType(Type type) SIP_HOLDGIL
Returns the multi type for a WKB type.
Definition: qgswkbtypes.h:304
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1080
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
Definition: qgsgeometry.h:76
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:86
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
Definition: qgsgeometry.h:82
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition: qgsgeometry.h:52
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:93
#define QgsDebugMsg(str)
Definition: qgslogger.h:38