QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
34std::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 QgsDebugError( "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 QgsDebugError( "WKB exception: " + e.what() );
65 geom.reset();
66 }
67 }
68
69 return geom;
70}
71
72std::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
139std::unique_ptr< QgsAbstractGeometry > QgsGeometryFactory::fromPointXY( const QgsPointXY &point )
140{
141 return std::make_unique< QgsPoint >( point.x(), point.y() );
142}
143
144std::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
157std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::fromPolylineXY( const QgsPolylineXY &polyline )
158{
159 return linestringFromPolyline( polyline );
160}
161
162std::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
173std::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
197std::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
208std::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
228std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkbType( Qgis::WkbType t )
229{
230 const Qgis::WkbType type = QgsWkbTypes::flatType( t );
231 switch ( type )
232 {
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
264std::unique_ptr<QgsGeometryCollection> QgsGeometryFactory::createCollectionOfType( Qgis::WkbType 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}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:182
@ CompoundCurve
CompoundCurve.
@ LineString
LineString.
@ MultiPoint
MultiPoint.
@ Polygon
Polygon.
@ MultiPolygon
MultiPolygon.
@ Triangle
Triangle.
@ MultiLineString
MultiLineString.
@ Unknown
Unknown.
@ CircularString
CircularString.
@ GeometryCollection
GeometryCollection.
@ MultiCurve
MultiCurve.
@ CurvePolygon
CurvePolygon.
@ MultiSurface
MultiSurface.
A const WKB pointer.
Definition: qgswkbptr.h:138
Qgis::WkbType readHeader() const
readHeader
Definition: qgswkbptr.cpp:55
QString what() const
Definition: qgsexception.h:49
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
Q_GADGET 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.
Definition: qgswkbtypes.h:973
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1023
static Qgis::WkbType multiType(Qgis::WkbType type)
Returns the multi type for a WKB type.
Definition: qgswkbtypes.h:200
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:628
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
Definition: qgsgeometry.h:74
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:84
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
Definition: qgsgeometry.h:80
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition: qgsgeometry.h:62
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:91
#define QgsDebugError(str)
Definition: qgslogger.h:38