QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
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"
32#include "qgstriangle.h"
33#include "qgswkbtypes.h"
34#include "qgslogger.h"
35
36std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkb( QgsConstWkbPtr &wkbPtr )
37{
38 if ( !wkbPtr )
39 return nullptr;
40
41 //find out type (bytes 2-5)
43 try
44 {
45 type = wkbPtr.readHeader();
46 }
47 catch ( const QgsWkbException &e )
48 {
49 Q_UNUSED( e )
50 QgsDebugError( "WKB exception while reading header: " + e.what() );
51 return nullptr;
52 }
53 wkbPtr -= 1 + sizeof( int );
54
55 std::unique_ptr< QgsAbstractGeometry > geom = geomFromWkbType( type );
56
57 if ( geom )
58 {
59 try
60 {
61 geom->fromWkb( wkbPtr ); // also updates wkbPtr
62 }
63 catch ( const QgsWkbException &e )
64 {
65 Q_UNUSED( e )
66 QgsDebugError( "WKB exception: " + e.what() );
67 geom.reset();
68 }
69 }
70
71 return geom;
72}
73
74std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkt( const QString &text )
75{
76 const QString trimmed = text.trimmed();
77 std::unique_ptr< QgsAbstractGeometry> geom;
78 if ( trimmed.startsWith( QLatin1String( "Point" ), Qt::CaseInsensitive ) )
79 {
80 geom = std::make_unique< QgsPoint >();
81 }
82 else if ( trimmed.startsWith( QLatin1String( "LineString" ), Qt::CaseInsensitive ) )
83 {
84 geom = std::make_unique< QgsLineString >();
85 }
86 else if ( trimmed.startsWith( QLatin1String( "CircularString" ), Qt::CaseInsensitive ) )
87 {
88 geom = std::make_unique< QgsCircularString >();
89 }
90 else if ( trimmed.startsWith( QLatin1String( "CompoundCurve" ), Qt::CaseInsensitive ) )
91 {
92 geom = std::make_unique< QgsCompoundCurve>();
93 }
94 else if ( trimmed.startsWith( QLatin1String( "Polygon" ), Qt::CaseInsensitive ) )
95 {
96 geom = std::make_unique< QgsPolygon >();
97 }
98 else if ( trimmed.startsWith( QLatin1String( "Triangle" ), Qt::CaseInsensitive ) )
99 {
100 geom = std::make_unique< QgsTriangle >();
101 }
102 else if ( trimmed.startsWith( QLatin1String( "CurvePolygon" ), Qt::CaseInsensitive ) )
103 {
104 geom = std::make_unique< QgsCurvePolygon >();
105 }
106 else if ( trimmed.startsWith( QLatin1String( "MultiPoint" ), Qt::CaseInsensitive ) )
107 {
108 geom = std::make_unique< QgsMultiPoint >();
109 }
110 else if ( trimmed.startsWith( QLatin1String( "MultiCurve" ), Qt::CaseInsensitive ) )
111 {
112 geom = std::make_unique< QgsMultiCurve >();
113 }
114 else if ( trimmed.startsWith( QLatin1String( "MultiLineString" ), Qt::CaseInsensitive ) )
115 {
116 geom = std::make_unique< QgsMultiLineString >();
117 }
118 else if ( trimmed.startsWith( QLatin1String( "MultiSurface" ), Qt::CaseInsensitive ) )
119 {
120 geom = std::make_unique< QgsMultiSurface >();
121 }
122 else if ( trimmed.startsWith( QLatin1String( "MultiPolygon" ), Qt::CaseInsensitive ) )
123 {
124 geom = std::make_unique< QgsMultiPolygon >();
125 }
126 else if ( trimmed.startsWith( QLatin1String( "GeometryCollection" ), Qt::CaseInsensitive ) )
127 {
128 geom = std::make_unique< QgsGeometryCollection >();
129 }
130 else if ( trimmed.startsWith( QLatin1String( "PolyhedralSurface" ), Qt::CaseInsensitive ) )
131 {
132 geom = std::make_unique< QgsPolyhedralSurface >();
133 }
134 else if ( trimmed.startsWith( QLatin1String( "TIN" ), Qt::CaseInsensitive ) )
135 {
136 geom = std::make_unique< QgsTriangulatedSurface >();
137 }
138
139 if ( geom )
140 {
141 if ( !geom->fromWkt( text ) )
142 {
143 return nullptr;
144 }
145 }
146 return geom;
147}
148
149std::unique_ptr< QgsAbstractGeometry > QgsGeometryFactory::fromPointXY( const QgsPointXY &point )
150{
151 return std::make_unique< QgsPoint >( point.x(), point.y() );
152}
153
154std::unique_ptr<QgsMultiPoint> QgsGeometryFactory::fromMultiPointXY( const QgsMultiPointXY &multipoint )
155{
156 std::unique_ptr< QgsMultiPoint > mp = std::make_unique< QgsMultiPoint >();
157 QgsMultiPointXY::const_iterator ptIt = multipoint.constBegin();
158 mp->reserve( multipoint.size() );
159 for ( ; ptIt != multipoint.constEnd(); ++ptIt )
160 {
161 QgsPoint *pt = new QgsPoint( ptIt->x(), ptIt->y() );
162 mp->addGeometry( pt );
163 }
164 return mp;
165}
166
167std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::fromPolylineXY( const QgsPolylineXY &polyline )
168{
169 return linestringFromPolyline( polyline );
170}
171
172std::unique_ptr<QgsMultiLineString> QgsGeometryFactory::fromMultiPolylineXY( const QgsMultiPolylineXY &multiline )
173{
174 std::unique_ptr< QgsMultiLineString > mLine = std::make_unique< QgsMultiLineString >();
175 mLine->reserve( multiline.size() );
176 for ( int i = 0; i < multiline.size(); ++i )
177 {
178 mLine->addGeometry( fromPolylineXY( multiline.at( i ) ).release() );
179 }
180 return mLine;
181}
182
183std::unique_ptr<QgsPolygon> QgsGeometryFactory::fromPolygonXY( const QgsPolygonXY &polygon )
184{
185 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
186
187 QVector<QgsCurve *> holes;
188 holes.reserve( polygon.size() );
189 for ( int i = 0; i < polygon.size(); ++i )
190 {
191 std::unique_ptr< QgsLineString > l = linestringFromPolyline( polygon.at( i ) );
192 l->close();
193
194 if ( i == 0 )
195 {
196 poly->setExteriorRing( l.release() );
197 }
198 else
199 {
200 holes.push_back( l.release() );
201 }
202 }
203 poly->setInteriorRings( holes );
204 return poly;
205}
206
207std::unique_ptr< QgsMultiPolygon > QgsGeometryFactory::fromMultiPolygonXY( const QgsMultiPolygonXY &multipoly )
208{
209 std::unique_ptr< QgsMultiPolygon > mp = std::make_unique< QgsMultiPolygon >();
210 mp->reserve( multipoly.size() );
211 for ( int i = 0; i < multipoly.size(); ++i )
212 {
213 mp->addGeometry( fromPolygonXY( multipoly.at( i ) ).release() );
214 }
215 return mp;
216}
217
218std::unique_ptr<QgsLineString> QgsGeometryFactory::linestringFromPolyline( const QgsPolylineXY &polyline )
219{
220 const int size = polyline.size();
221 QVector< double > x;
222 x.resize( size );
223 QVector< double > y;
224 y.resize( size );
225 double *destX = x.data();
226 double *destY = y.data();
227 const QgsPointXY *src = polyline.data();
228 for ( int i = 0; i < size; ++i )
229 {
230 *destX++ = src->x();
231 *destY++ = src->y();
232 src++;
233 }
234 std::unique_ptr< QgsLineString > line = std::make_unique< QgsLineString >( x, y );
235 return line;
236}
237
238std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkbType( Qgis::WkbType t )
239{
240 const Qgis::WkbType type = QgsWkbTypes::flatType( t );
241 switch ( type )
242 {
244 return std::make_unique< QgsPoint >();
246 return std::make_unique< QgsLineString >();
248 return std::make_unique< QgsCircularString >();
250 return std::make_unique< QgsCompoundCurve >();
252 return std::make_unique< QgsPolygon >();
254 return std::make_unique< QgsCurvePolygon >();
256 return std::make_unique< QgsMultiLineString >();
258 return std::make_unique< QgsMultiPolygon >();
260 return std::make_unique< QgsMultiPoint >();
262 return std::make_unique< QgsMultiCurve >();
264 return std::make_unique< QgsMultiSurface >();
266 return std::make_unique< QgsGeometryCollection >();
268 return std::make_unique< QgsTriangle >();
270 return std::make_unique< QgsPolyhedralSurface >();
272 return std::make_unique< QgsTriangulatedSurface >();
273 default:
274 return nullptr;
275 }
276}
277
278std::unique_ptr<QgsGeometryCollection> QgsGeometryFactory::createCollectionOfType( Qgis::WkbType t )
279{
281 std::unique_ptr< QgsGeometryCollection > collect;
282 switch ( type )
283 {
285 collect = std::make_unique< QgsMultiPoint >();
286 break;
288 collect = std::make_unique< QgsMultiLineString >();
289 break;
291 collect = std::make_unique< QgsMultiCurve >();
292 break;
294 collect = std::make_unique< QgsMultiPolygon >();
295 break;
297 collect = std::make_unique< QgsMultiSurface >();
298 break;
300 collect = std::make_unique< QgsGeometryCollection >();
301 break;
302 default:
303 // should not be possible
304 return nullptr;
305 }
306 if ( QgsWkbTypes::hasM( t ) )
307 collect->addMValue();
308 if ( QgsWkbTypes::hasZ( t ) )
309 collect->addZValue();
310
311 return collect;
312}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:256
@ CompoundCurve
CompoundCurve.
@ LineString
LineString.
@ MultiPoint
MultiPoint.
@ Polygon
Polygon.
@ MultiPolygon
MultiPolygon.
@ Triangle
Triangle.
@ MultiLineString
MultiLineString.
@ Unknown
Unknown.
@ CircularString
CircularString.
@ GeometryCollection
GeometryCollection.
@ MultiCurve
MultiCurve.
@ CurvePolygon
CurvePolygon.
@ PolyhedralSurface
PolyhedralSurface.
@ MultiSurface
MultiSurface.
A const WKB pointer.
Definition qgswkbptr.h:138
Qgis::WkbType readHeader() const
readHeader
Definition qgswkbptr.cpp:55
QString what() const
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< QgsGeometryCollection > createCollectionOfType(Qgis::WkbType type)
Returns a new geometry collection matching a specified WKB type.
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< QgsMultiLineString > fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Construct geometry from a multipolyline.
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.
static std::unique_ptr< QgsAbstractGeometry > geomFromWkbType(Qgis::WkbType t)
Returns empty geometry from wkb type.
A class to represent a 2D point.
Definition qgspointxy.h:60
double y
Definition qgspointxy.h:64
double x
Definition qgspointxy.h:63
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 hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
static Qgis::WkbType multiType(Qgis::WkbType type)
Returns the multi type for a WKB type.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition qgsgeometry.h:62
QVector< QgsPolylineXY > QgsPolygonXY
QVector< QgsPolylineXY > QgsMultiPolylineXY
QVector< QgsPointXY > QgsMultiPointXY
QVector< QgsPointXY > QgsPolylineXY
QVector< QgsPolygonXY > QgsMultiPolygonXY
#define QgsDebugError(str)
Definition qgslogger.h:38