QGIS API Documentation  3.6.0-Noosa (5873452)
qgsogrutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsogrutils.cpp
3  ---------------
4  begin : February 2016
5  copyright : (C) 2016 Nyall Dawson
6  email : nyall dot dawson at gmail 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 "qgsogrutils.h"
17 #include "qgsapplication.h"
18 #include "qgslogger.h"
19 #include "qgsgeometry.h"
20 #include "qgsfields.h"
21 #include "qgslinestring.h"
22 #include <QTextCodec>
23 #include <QUuid>
24 #include <cpl_error.h>
25 #include <QJsonDocument>
26 
27 // Starting with GDAL 2.2, there are 2 concepts: unset fields and null fields
28 // whereas previously there was only unset fields. For QGIS purposes, both
29 // states (unset/null) are equivalent.
30 #ifndef OGRNullMarker
31 #define OGR_F_IsFieldSetAndNotNull OGR_F_IsFieldSet
32 #endif
33 
34 
35 
36 void gdal::OGRDataSourceDeleter::operator()( OGRDataSourceH source )
37 {
38  OGR_DS_Destroy( source );
39 }
40 
41 
42 void gdal::OGRGeometryDeleter::operator()( OGRGeometryH geometry )
43 {
44  OGR_G_DestroyGeometry( geometry );
45 }
46 
47 void gdal::OGRFldDeleter::operator()( OGRFieldDefnH definition )
48 {
49  OGR_Fld_Destroy( definition );
50 }
51 
52 void gdal::OGRFeatureDeleter::operator()( OGRFeatureH feature )
53 {
54  OGR_F_Destroy( feature );
55 }
56 
58 {
59  GDALClose( dataset );
60 }
61 
62 void gdal::fast_delete_and_close( gdal::dataset_unique_ptr &dataset, GDALDriverH driver, const QString &path )
63 {
64  // see https://github.com/qgis/QGIS/commit/d024910490a39e65e671f2055c5b6543e06c7042#commitcomment-25194282
65  // faster if we close the handle AFTER delete, but doesn't work for windows
66 #ifdef Q_OS_WIN
67  // close dataset handle
68  dataset.reset();
69 #endif
70 
71  CPLPushErrorHandler( CPLQuietErrorHandler );
72  GDALDeleteDataset( driver, path.toUtf8().constData() );
73  CPLPopErrorHandler();
74 
75 #ifndef Q_OS_WIN
76  // close dataset handle
77  dataset.reset();
78 #endif
79 }
80 
81 
82 void gdal::GDALWarpOptionsDeleter::operator()( GDALWarpOptions *options )
83 {
84  GDALDestroyWarpOptions( options );
85 }
86 
87 QgsFeature QgsOgrUtils::readOgrFeature( OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding )
88 {
89  QgsFeature feature;
90  if ( !ogrFet )
91  {
92  feature.setValid( false );
93  return feature;
94  }
95 
96  feature.setId( OGR_F_GetFID( ogrFet ) );
97  feature.setValid( true );
98 
99  if ( !readOgrFeatureGeometry( ogrFet, feature ) )
100  {
101  feature.setValid( false );
102  }
103 
104  if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
105  {
106  feature.setValid( false );
107  }
108 
109  return feature;
110 }
111 
112 QgsFields QgsOgrUtils::readOgrFields( OGRFeatureH ogrFet, QTextCodec *encoding )
113 {
114  QgsFields fields;
115 
116  if ( !ogrFet )
117  return fields;
118 
119  int fieldCount = OGR_F_GetFieldCount( ogrFet );
120  for ( int i = 0; i < fieldCount; ++i )
121  {
122  OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
123  if ( !fldDef )
124  {
125  fields.append( QgsField() );
126  continue;
127  }
128 
129  QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
130  QVariant::Type varType;
131  switch ( OGR_Fld_GetType( fldDef ) )
132  {
133  case OFTInteger:
134  if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
135  varType = QVariant::Bool;
136  else
137  varType = QVariant::Int;
138  break;
139  case OFTInteger64:
140  varType = QVariant::LongLong;
141  break;
142  case OFTReal:
143  varType = QVariant::Double;
144  break;
145  case OFTDate:
146  varType = QVariant::Date;
147  break;
148  case OFTTime:
149  varType = QVariant::Time;
150  break;
151  case OFTDateTime:
152  varType = QVariant::DateTime;
153  break;
154  case OFTString:
155 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0)
156  if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
157  varType = QVariant::Map;
158  else
159  varType = QVariant::String;
160  break;
161 #endif
162  default:
163  varType = QVariant::String; // other unsupported, leave it as a string
164  }
165  fields.append( QgsField( name, varType ) );
166  }
167  return fields;
168 }
169 
170 QVariant QgsOgrUtils::getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok )
171 {
172  if ( !ogrFet || attIndex < 0 || attIndex >= fields.count() )
173  {
174  if ( ok )
175  *ok = false;
176  return QVariant();
177  }
178 
179  OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
180 
181  if ( ! fldDef )
182  {
183  if ( ok )
184  *ok = false;
185 
186  QgsDebugMsg( QStringLiteral( "ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
187  return QVariant();
188  }
189 
190  QVariant value;
191 
192  if ( ok )
193  *ok = true;
194 
195  if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
196  {
197  switch ( fields.at( attIndex ).type() )
198  {
199  case QVariant::String:
200  {
201  if ( encoding )
202  value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
203  else
204  value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
205  break;
206  }
207  case QVariant::Int:
208  value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
209  break;
210  case QVariant::Bool:
211  value = QVariant( bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
212  break;
213  case QVariant::LongLong:
214  value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
215  break;
216  case QVariant::Double:
217  value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
218  break;
219  case QVariant::Date:
220  case QVariant::DateTime:
221  case QVariant::Time:
222  {
223  int year, month, day, hour, minute, second, tzf;
224 
225  OGR_F_GetFieldAsDateTime( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
226  if ( fields.at( attIndex ).type() == QVariant::Date )
227  value = QDate( year, month, day );
228  else if ( fields.at( attIndex ).type() == QVariant::Time )
229  value = QTime( hour, minute, second );
230  else
231  value = QDateTime( QDate( year, month, day ), QTime( hour, minute, second ) );
232  }
233  break;
234 
235  case QVariant::ByteArray:
236  {
237  int size = 0;
238  const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
239 
240  // QByteArray::fromRawData is funny. It doesn't take ownership of the data, so we have to explicitly call
241  // detach on it to force a copy which owns the data
242  QByteArray ba = QByteArray::fromRawData( reinterpret_cast<const char *>( b ), size );
243  ba.detach();
244 
245  value = ba;
246  break;
247  }
248 
249  case QVariant::Map:
250  {
251  //it has to be JSON
252  //it's null if no json format
253  if ( encoding )
254  value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
255  else
256  value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
257  break;
258  }
259  default:
260  Q_ASSERT_X( false, "QgsOgrUtils::getOgrFeatureAttribute", "unsupported field type" );
261  if ( ok )
262  *ok = false;
263  }
264  }
265  else
266  {
267  value = QVariant( QString() );
268  }
269 
270  return value;
271 }
272 
273 bool QgsOgrUtils::readOgrFeatureAttributes( OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding )
274 {
275  // read all attributes
276  feature.initAttributes( fields.count() );
277  feature.setFields( fields );
278 
279  if ( !ogrFet )
280  return false;
281 
282  bool ok = false;
283  for ( int idx = 0; idx < fields.count(); ++idx )
284  {
285  QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
286  if ( ok )
287  {
288  feature.setAttribute( idx, value );
289  }
290  }
291  return true;
292 }
293 
294 bool QgsOgrUtils::readOgrFeatureGeometry( OGRFeatureH ogrFet, QgsFeature &feature )
295 {
296  if ( !ogrFet )
297  return false;
298 
299  OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
300  if ( !geom )
301  feature.clearGeometry();
302  else
303  feature.setGeometry( ogrGeometryToQgsGeometry( geom ) );
304 
305  return true;
306 }
307 
308 std::unique_ptr< QgsPoint > ogrGeometryToQgsPoint( OGRGeometryH geom )
309 {
310  QgsWkbTypes::Type wkbType = static_cast<QgsWkbTypes::Type>( OGR_G_GetGeometryType( geom ) );
311 
312  double x, y, z, m;
313  OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
314  return qgis::make_unique< QgsPoint >( wkbType, x, y, z, m );
315 }
316 
317 std::unique_ptr< QgsLineString > ogrGeometryToQgsLineString( OGRGeometryH geom )
318 {
319  QgsWkbTypes::Type wkbType = static_cast<QgsWkbTypes::Type>( OGR_G_GetGeometryType( geom ) );
320 
321  int count = OGR_G_GetPointCount( geom );
322  QVector< double > x( count );
323  QVector< double > y( count );
324  QVector< double > z;
325  double *pz = nullptr;
326  if ( QgsWkbTypes::hasZ( wkbType ) )
327  {
328  z.resize( count );
329  pz = z.data();
330  }
331  double *pm = nullptr;
332  QVector< double > m;
333  if ( QgsWkbTypes::hasM( wkbType ) )
334  {
335  m.resize( count );
336  pm = m.data();
337  }
338  OGR_G_GetPointsZM( geom, x.data(), sizeof( double ), y.data(), sizeof( double ), pz, sizeof( double ), pm, sizeof( double ) );
339 
340  return qgis::make_unique< QgsLineString>( x, y, z, m, wkbType == QgsWkbTypes::LineString25D );
341 }
342 
344 {
345  if ( !geom )
346  return QgsGeometry();
347 
348  QgsWkbTypes::Type wkbType = static_cast<QgsWkbTypes::Type>( OGR_G_GetGeometryType( geom ) );
349  // optimised case for some geometry classes, avoiding wkb conversion on OGR/QGIS sides
350  // TODO - extend to other classes!
351  switch ( QgsWkbTypes::flatType( wkbType ) )
352  {
353  case QgsWkbTypes::Point:
354  {
355  return QgsGeometry( ogrGeometryToQgsPoint( geom ) );
356  }
357 
359  {
360  // optimised case for line -- avoid wkb conversion
361  return QgsGeometry( ogrGeometryToQgsLineString( geom ) );
362  }
363 
364  default:
365  break;
366  };
367 
368  // Fallback to inefficient WKB conversions
369 
370  // get the wkb representation
371  int memorySize = OGR_G_WkbSize( geom );
372  unsigned char *wkb = new unsigned char[memorySize];
373  OGR_G_ExportToWkb( geom, ( OGRwkbByteOrder ) QgsApplication::endian(), wkb );
374 
375  // Read original geometry type
376  uint32_t origGeomType;
377  memcpy( &origGeomType, wkb + 1, sizeof( uint32_t ) );
378  bool hasZ = ( origGeomType >= 1000 && origGeomType < 2000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
379  bool hasM = ( origGeomType >= 2000 && origGeomType < 3000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
380 
381  // PolyhedralSurface and TINs are not supported, map them to multipolygons...
382  if ( origGeomType % 1000 == 16 ) // is TIN, TINZ, TINM or TINZM
383  {
384  // TIN has the same wkb layout as a multipolygon, just need to overwrite the geom types...
385  int nDims = 2 + hasZ + hasM;
386  uint32_t newMultiType = static_cast<uint32_t>( QgsWkbTypes::zmType( QgsWkbTypes::MultiPolygon, hasZ, hasM ) );
387  uint32_t newSingleType = static_cast<uint32_t>( QgsWkbTypes::zmType( QgsWkbTypes::Polygon, hasZ, hasM ) );
388  unsigned char *wkbptr = wkb;
389 
390  // Endianness
391  wkbptr += 1;
392 
393  // Overwrite geom type
394  memcpy( wkbptr, &newMultiType, sizeof( uint32_t ) );
395  wkbptr += 4;
396 
397  // Geom count
398  uint32_t numGeoms;
399  memcpy( &numGeoms, wkb + 5, sizeof( uint32_t ) );
400  wkbptr += 4;
401 
402  // For each part, overwrite the geometry type to polygon (Z|M)
403  for ( uint32_t i = 0; i < numGeoms; ++i )
404  {
405  // Endianness
406  wkbptr += 1;
407 
408  // Overwrite geom type
409  memcpy( wkbptr, &newSingleType, sizeof( uint32_t ) );
410  wkbptr += sizeof( uint32_t );
411 
412  // skip coordinates
413  uint32_t nRings;
414  memcpy( &nRings, wkbptr, sizeof( uint32_t ) );
415  wkbptr += sizeof( uint32_t );
416 
417  for ( uint32_t j = 0; j < nRings; ++j )
418  {
419  uint32_t nPoints;
420  memcpy( &nPoints, wkbptr, sizeof( uint32_t ) );
421  wkbptr += sizeof( uint32_t ) + sizeof( double ) * nDims * nPoints;
422  }
423  }
424  }
425  else if ( origGeomType % 1000 == 15 ) // PolyhedralSurface, PolyhedralSurfaceZ, PolyhedralSurfaceM or PolyhedralSurfaceZM
426  {
427  // PolyhedralSurface has the same wkb layout as a MultiPolygon, just need to overwrite the geom type...
428  uint32_t newType = static_cast<uint32_t>( QgsWkbTypes::zmType( QgsWkbTypes::MultiPolygon, hasZ, hasM ) );
429  // Overwrite geom type
430  memcpy( wkb + 1, &newType, sizeof( uint32_t ) );
431  }
432 
433  QgsGeometry g;
434  g.fromWkb( wkb, memorySize );
435  return g;
436 }
437 
438 QgsFeatureList QgsOgrUtils::stringToFeatureList( const QString &string, const QgsFields &fields, QTextCodec *encoding )
439 {
440  QgsFeatureList features;
441  if ( string.isEmpty() )
442  return features;
443 
444  QString randomFileName = QStringLiteral( "/vsimem/%1" ).arg( QUuid::createUuid().toString() );
445 
446  // create memory file system object from string buffer
447  QByteArray ba = string.toUtf8();
448  VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), reinterpret_cast< GByte * >( ba.data() ),
449  static_cast< vsi_l_offset >( ba.size() ), FALSE ) );
450 
451  gdal::ogr_datasource_unique_ptr hDS( OGROpen( randomFileName.toUtf8().constData(), false, nullptr ) );
452  if ( !hDS )
453  {
454  VSIUnlink( randomFileName.toUtf8().constData() );
455  return features;
456  }
457 
458  OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
459  if ( !ogrLayer )
460  {
461  hDS.reset();
462  VSIUnlink( randomFileName.toUtf8().constData() );
463  return features;
464  }
465 
467  while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
468  {
469  QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
470  if ( feat.isValid() )
471  features << feat;
472  }
473 
474  hDS.reset();
475  VSIUnlink( randomFileName.toUtf8().constData() );
476 
477  return features;
478 }
479 
480 QgsFields QgsOgrUtils::stringToFields( const QString &string, QTextCodec *encoding )
481 {
482  QgsFields fields;
483  if ( string.isEmpty() )
484  return fields;
485 
486  QString randomFileName = QStringLiteral( "/vsimem/%1" ).arg( QUuid::createUuid().toString() );
487 
488  // create memory file system object from buffer
489  QByteArray ba = string.toUtf8();
490  VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), reinterpret_cast< GByte * >( ba.data() ),
491  static_cast< vsi_l_offset >( ba.size() ), FALSE ) );
492 
493  gdal::ogr_datasource_unique_ptr hDS( OGROpen( randomFileName.toUtf8().constData(), false, nullptr ) );
494  if ( !hDS )
495  {
496  VSIUnlink( randomFileName.toUtf8().constData() );
497  return fields;
498  }
499 
500  OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
501  if ( !ogrLayer )
502  {
503  hDS.reset();
504  VSIUnlink( randomFileName.toUtf8().constData() );
505  return fields;
506  }
507 
509  //read in the first feature only
510  if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
511  {
512  fields = readOgrFields( oFeat.get(), encoding );
513  }
514 
515  hDS.reset();
516  VSIUnlink( randomFileName.toUtf8().constData() );
517  return fields;
518 }
519 
520 QStringList QgsOgrUtils::cStringListToQStringList( char **stringList )
521 {
522  QStringList strings;
523 
524  // presume null terminated string list
525  for ( qgssize i = 0; stringList[i]; ++i )
526  {
527  strings.append( QString::fromUtf8( stringList[i] ) );
528  }
529 
530  return strings;
531 }
532 
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
void CORE_EXPORT operator()(OGRFeatureH feature)
Destroys an OGR feature, using the correct gdal calls.
Definition: qgsogrutils.cpp:52
static bool readOgrFeatureAttributes(OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding)
Reads all attributes from an OGR feature into a QgsFeature.
void setFields(const QgsFields &fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:162
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer&#39;s length...
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
static bool readOgrFeatureGeometry(OGRFeatureH ogrFet, QgsFeature &feature)
Reads the geometry from an OGR feature into a QgsFeature.
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
bool setAttribute(int field, const QVariant &attr)
Set an attribute&#39;s value by field index.
Definition: qgsfeature.cpp:211
void CORE_EXPORT operator()(OGRDataSourceH source)
Destroys an OGR data source, using the correct gdal calls.
Definition: qgsogrutils.cpp:36
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
static QgsFields readOgrFields(OGRFeatureH ogrFet, QTextCodec *encoding)
Reads an OGR feature and returns a corresponding fields collection.
#define OGR_F_IsFieldSetAndNotNull
Definition: qgsogrutils.cpp:31
static endian_t endian()
Returns whether this machine uses big or little endian.
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:770
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
std::unique_ptr< QgsPoint > ogrGeometryToQgsPoint(OGRGeometryH geom)
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a string representing a collection of features using OGR.
void CORE_EXPORT fast_delete_and_close(dataset_unique_ptr &dataset, GDALDriverH driver, const QString &path)
Performs a fast close of an unwanted GDAL dataset handle by deleting the underlying data store...
Definition: qgsogrutils.cpp:62
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
Definition: qgsogrutils.h:129
void CORE_EXPORT operator()(GDALDatasetH datasource)
Destroys an gdal dataset, using the correct gdal calls.
Definition: qgsogrutils.cpp:57
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:202
static QgsFeature readOgrFeature(OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding)
Reads an OGR feature and converts it to a QgsFeature.
Definition: qgsogrutils.cpp:87
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false) ...
Definition: qgsfields.cpp:59
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a string representing a collection of features using OGR...
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
void setId(QgsFeatureId id)
Sets the feature ID for this feature.
Definition: qgsfeature.cpp:112
void * GDALDatasetH
static QgsGeometry ogrGeometryToQgsGeometry(OGRGeometryH geom)
Converts an OGR geometry representation to a QgsGeometry object.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
Definition: qgis.h:596
void CORE_EXPORT operator()(GDALWarpOptions *options)
Destroys GDAL warp options, using the correct gdal calls.
Definition: qgsogrutils.cpp:82
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:188
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:151
static QVariant getOgrFeatureAttribute(OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok=nullptr)
Retrieves an attribute value from an OGR feature.
std::unique_ptr< QgsLineString > ogrGeometryToQgsLineString(OGRGeometryH geom)
void CORE_EXPORT operator()(OGRGeometryH geometry)
Destroys an OGR geometry, using the correct gdal calls.
Definition: qgsogrutils.cpp:42
void CORE_EXPORT operator()(OGRFieldDefnH definition)
Destroys an OGR field definition, using the correct gdal calls.
Definition: qgsogrutils.cpp:47
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
static Type zmType(Type type, bool hasZ, bool hasM)
Returns the modified input geometry type according to hasZ / hasM.
Definition: qgswkbtypes.h:528
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:820
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
Definition: qgsogrutils.h:134
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
Definition: qgsogrutils.h:114
static QStringList cStringListToQStringList(char **stringList)
Converts a c string list to a QStringList.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:429
QVariant::Type type
Definition: qgsfield.h:56