QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 "qgsmultipoint.h"
23 #include "qgsmultilinestring.h"
24 #include "qgsogrprovider.h"
25 #include <QTextCodec>
26 #include <QUuid>
27 #include <cpl_error.h>
28 #include <QJsonDocument>
29 #include <QFileInfo>
30 #include <QDir>
31 #include <QTextStream>
32 #include <QDataStream>
33 
34 #include "ogr_srs_api.h"
35 
36 // Starting with GDAL 2.2, there are 2 concepts: unset fields and null fields
37 // whereas previously there was only unset fields. For QGIS purposes, both
38 // states (unset/null) are equivalent.
39 #ifndef OGRNullMarker
40 #define OGR_F_IsFieldSetAndNotNull OGR_F_IsFieldSet
41 #endif
42 
43 
44 
45 void gdal::OGRDataSourceDeleter::operator()( OGRDataSourceH source )
46 {
47  OGR_DS_Destroy( source );
48 }
49 
50 
51 void gdal::OGRGeometryDeleter::operator()( OGRGeometryH geometry )
52 {
53  OGR_G_DestroyGeometry( geometry );
54 }
55 
56 void gdal::OGRFldDeleter::operator()( OGRFieldDefnH definition )
57 {
58  OGR_Fld_Destroy( definition );
59 }
60 
61 void gdal::OGRFeatureDeleter::operator()( OGRFeatureH feature )
62 {
63  OGR_F_Destroy( feature );
64 }
65 
67 {
68  GDALClose( dataset );
69 }
70 
71 void gdal::fast_delete_and_close( gdal::dataset_unique_ptr &dataset, GDALDriverH driver, const QString &path )
72 {
73  // see https://github.com/qgis/QGIS/commit/d024910490a39e65e671f2055c5b6543e06c7042#commitcomment-25194282
74  // faster if we close the handle AFTER delete, but doesn't work for windows
75 #ifdef Q_OS_WIN
76  // close dataset handle
77  dataset.reset();
78 #endif
79 
80  CPLPushErrorHandler( CPLQuietErrorHandler );
81  GDALDeleteDataset( driver, path.toUtf8().constData() );
82  CPLPopErrorHandler();
83 
84 #ifndef Q_OS_WIN
85  // close dataset handle
86  dataset.reset();
87 #endif
88 }
89 
90 
91 void gdal::GDALWarpOptionsDeleter::operator()( GDALWarpOptions *options )
92 {
93  GDALDestroyWarpOptions( options );
94 }
95 
96 QgsFeature QgsOgrUtils::readOgrFeature( OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding )
97 {
98  QgsFeature feature;
99  if ( !ogrFet )
100  {
101  feature.setValid( false );
102  return feature;
103  }
104 
105  feature.setId( OGR_F_GetFID( ogrFet ) );
106  feature.setValid( true );
107 
108  if ( !readOgrFeatureGeometry( ogrFet, feature ) )
109  {
110  feature.setValid( false );
111  }
112 
113  if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
114  {
115  feature.setValid( false );
116  }
117 
118  return feature;
119 }
120 
121 QgsFields QgsOgrUtils::readOgrFields( OGRFeatureH ogrFet, QTextCodec *encoding )
122 {
123  QgsFields fields;
124 
125  if ( !ogrFet )
126  return fields;
127 
128  int fieldCount = OGR_F_GetFieldCount( ogrFet );
129  for ( int i = 0; i < fieldCount; ++i )
130  {
131  OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
132  if ( !fldDef )
133  {
134  fields.append( QgsField() );
135  continue;
136  }
137 
138  QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
139  QVariant::Type varType;
140  switch ( OGR_Fld_GetType( fldDef ) )
141  {
142  case OFTInteger:
143  if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
144  varType = QVariant::Bool;
145  else
146  varType = QVariant::Int;
147  break;
148  case OFTInteger64:
149  varType = QVariant::LongLong;
150  break;
151  case OFTReal:
152  varType = QVariant::Double;
153  break;
154  case OFTDate:
155  varType = QVariant::Date;
156  break;
157  case OFTTime:
158  varType = QVariant::Time;
159  break;
160  case OFTDateTime:
161  varType = QVariant::DateTime;
162  break;
163  case OFTString:
164 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0)
165  if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
166  varType = QVariant::Map;
167  else
168  varType = QVariant::String;
169  break;
170 #endif
171  default:
172  varType = QVariant::String; // other unsupported, leave it as a string
173  }
174  fields.append( QgsField( name, varType ) );
175  }
176  return fields;
177 }
178 
179 
180 QVariant QgsOgrUtils::getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok )
181 {
182  if ( attIndex < 0 || attIndex >= fields.count() )
183  {
184  if ( ok )
185  *ok = false;
186  return QVariant();
187  }
188 
189  const QgsField field = fields.at( attIndex );
190  return getOgrFeatureAttribute( ogrFet, field, attIndex, encoding, ok );
191 }
192 
193 QVariant QgsOgrUtils::getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsField &field, int attIndex, QTextCodec *encoding, bool *ok )
194 {
195  if ( !ogrFet || attIndex < 0 )
196  {
197  if ( ok )
198  *ok = false;
199  return QVariant();
200  }
201 
202  OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
203 
204  if ( ! fldDef )
205  {
206  if ( ok )
207  *ok = false;
208 
209  QgsDebugMsg( QStringLiteral( "ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
210  return QVariant();
211  }
212 
213  QVariant value;
214 
215  if ( ok )
216  *ok = true;
217 
218  if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
219  {
220  switch ( field.type() )
221  {
222  case QVariant::String:
223  {
224  if ( encoding )
225  value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
226  else
227  value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
228  break;
229  }
230  case QVariant::Int:
231  value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
232  break;
233  case QVariant::Bool:
234  value = QVariant( bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
235  break;
236  case QVariant::LongLong:
237  value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
238  break;
239  case QVariant::Double:
240  value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
241  break;
242  case QVariant::Date:
243  case QVariant::DateTime:
244  case QVariant::Time:
245  {
246  int year, month, day, hour, minute, second, tzf;
247 
248  OGR_F_GetFieldAsDateTime( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
249  if ( field.type() == QVariant::Date )
250  value = QDate( year, month, day );
251  else if ( field.type() == QVariant::Time )
252  value = QTime( hour, minute, second );
253  else
254  value = QDateTime( QDate( year, month, day ), QTime( hour, minute, second ) );
255  }
256  break;
257 
258  case QVariant::ByteArray:
259  {
260  int size = 0;
261  const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
262 
263  // QByteArray::fromRawData is funny. It doesn't take ownership of the data, so we have to explicitly call
264  // detach on it to force a copy which owns the data
265  QByteArray ba = QByteArray::fromRawData( reinterpret_cast<const char *>( b ), size );
266  ba.detach();
267 
268  value = ba;
269  break;
270  }
271 
272  case QVariant::List:
273  {
274  if ( field.subType() == QVariant::String )
275  {
276  QStringList list;
277  char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
278  const int count = CSLCount( lst );
279  if ( count > 0 )
280  {
281  for ( int i = 0; i < count; i++ )
282  {
283  if ( encoding )
284  list << encoding->toUnicode( lst[i] );
285  else
286  list << QString::fromUtf8( lst[i] );
287  }
288  }
289  value = list;
290  }
291  else
292  {
293  Q_ASSERT_X( false, "QgsOgrUtils::getOgrFeatureAttribute", "unsupported field type" );
294  if ( ok )
295  *ok = false;
296  }
297  break;
298  }
299 
300  case QVariant::Map:
301  {
302  //it has to be JSON
303  //it's null if no json format
304  if ( encoding )
305  value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
306  else
307  value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
308  break;
309  }
310  default:
311  Q_ASSERT_X( false, "QgsOgrUtils::getOgrFeatureAttribute", "unsupported field type" );
312  if ( ok )
313  *ok = false;
314  }
315  }
316  else
317  {
318  value = QVariant( QString() );
319  }
320 
321  return value;
322 }
323 
324 bool QgsOgrUtils::readOgrFeatureAttributes( OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding )
325 {
326  // read all attributes
327  feature.initAttributes( fields.count() );
328  feature.setFields( fields );
329 
330  if ( !ogrFet )
331  return false;
332 
333  bool ok = false;
334  for ( int idx = 0; idx < fields.count(); ++idx )
335  {
336  QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
337  if ( ok )
338  {
339  feature.setAttribute( idx, value );
340  }
341  }
342  return true;
343 }
344 
345 bool QgsOgrUtils::readOgrFeatureGeometry( OGRFeatureH ogrFet, QgsFeature &feature )
346 {
347  if ( !ogrFet )
348  return false;
349 
350  OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
351  if ( !geom )
352  feature.clearGeometry();
353  else
354  feature.setGeometry( ogrGeometryToQgsGeometry( geom ) );
355 
356  return true;
357 }
358 
359 std::unique_ptr< QgsPoint > ogrGeometryToQgsPoint( OGRGeometryH geom )
360 {
361  QgsWkbTypes::Type wkbType = static_cast<QgsWkbTypes::Type>( OGR_G_GetGeometryType( geom ) );
362 
363  double x, y, z, m;
364  OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
365  return qgis::make_unique< QgsPoint >( wkbType, x, y, z, m );
366 }
367 
368 std::unique_ptr< QgsMultiPoint > ogrGeometryToQgsMultiPoint( OGRGeometryH geom )
369 {
370  std::unique_ptr< QgsMultiPoint > mp = qgis::make_unique< QgsMultiPoint >();
371 
372  const int count = OGR_G_GetGeometryCount( geom );
373  mp->reserve( count );
374  for ( int i = 0; i < count; ++i )
375  {
376  mp->addGeometry( ogrGeometryToQgsPoint( OGR_G_GetGeometryRef( geom, i ) ).release() );
377  }
378 
379  return mp;
380 }
381 
382 std::unique_ptr< QgsLineString > ogrGeometryToQgsLineString( OGRGeometryH geom )
383 {
384  QgsWkbTypes::Type wkbType = static_cast<QgsWkbTypes::Type>( OGR_G_GetGeometryType( geom ) );
385 
386  int count = OGR_G_GetPointCount( geom );
387  QVector< double > x( count );
388  QVector< double > y( count );
389  QVector< double > z;
390  double *pz = nullptr;
391  if ( QgsWkbTypes::hasZ( wkbType ) )
392  {
393  z.resize( count );
394  pz = z.data();
395  }
396  double *pm = nullptr;
397  QVector< double > m;
398  if ( QgsWkbTypes::hasM( wkbType ) )
399  {
400  m.resize( count );
401  pm = m.data();
402  }
403  OGR_G_GetPointsZM( geom, x.data(), sizeof( double ), y.data(), sizeof( double ), pz, sizeof( double ), pm, sizeof( double ) );
404 
405  return qgis::make_unique< QgsLineString>( x, y, z, m, wkbType == QgsWkbTypes::LineString25D );
406 }
407 
408 std::unique_ptr< QgsMultiLineString > ogrGeometryToQgsMultiLineString( OGRGeometryH geom )
409 {
410  std::unique_ptr< QgsMultiLineString > mp = qgis::make_unique< QgsMultiLineString >();
411 
412  const int count = OGR_G_GetGeometryCount( geom );
413  mp->reserve( count );
414  for ( int i = 0; i < count; ++i )
415  {
416  mp->addGeometry( ogrGeometryToQgsLineString( OGR_G_GetGeometryRef( geom, i ) ).release() );
417  }
418 
419  return mp;
420 }
421 
423 {
424  switch ( ogrGeomType )
425  {
426  case wkbUnknown: return QgsWkbTypes::Type::Unknown;
427  case wkbPoint: return QgsWkbTypes::Type::Point;
428  case wkbLineString: return QgsWkbTypes::Type::LineString;
429  case wkbPolygon: return QgsWkbTypes::Type::Polygon;
430  case wkbMultiPoint: return QgsWkbTypes::Type::MultiPoint;
431  case wkbMultiLineString: return QgsWkbTypes::Type::MultiLineString;
432  case wkbMultiPolygon: return QgsWkbTypes::Type::MultiPolygon;
433  case wkbGeometryCollection: return QgsWkbTypes::Type::GeometryCollection;
434  case wkbCircularString: return QgsWkbTypes::Type::CircularString;
435  case wkbCompoundCurve: return QgsWkbTypes::Type::CompoundCurve;
436  case wkbCurvePolygon: return QgsWkbTypes::Type::CurvePolygon;
437  case wkbMultiCurve: return QgsWkbTypes::Type::MultiCurve;
438  case wkbMultiSurface: return QgsWkbTypes::Type::MultiSurface;
439  case wkbCurve: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
440  case wkbSurface: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
441  case wkbPolyhedralSurface: return QgsWkbTypes::Type::Unknown; // no actual matching
442  case wkbTIN: return QgsWkbTypes::Type::Unknown; // no actual matching
443  case wkbTriangle: return QgsWkbTypes::Type::Triangle;
444 
445  case wkbNone: return QgsWkbTypes::Type::NoGeometry;
446  case wkbLinearRing: return QgsWkbTypes::Type::LineString; // approximate match
447 
448  case wkbCircularStringZ: return QgsWkbTypes::Type::CircularStringZ;
449  case wkbCompoundCurveZ: return QgsWkbTypes::Type::CompoundCurveZ;
450  case wkbCurvePolygonZ: return QgsWkbTypes::Type::CurvePolygonZ;
451  case wkbMultiCurveZ: return QgsWkbTypes::Type::MultiCurveZ;
452  case wkbMultiSurfaceZ: return QgsWkbTypes::Type::MultiSurfaceZ;
453  case wkbCurveZ: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
454  case wkbSurfaceZ: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
455  case wkbPolyhedralSurfaceZ: return QgsWkbTypes::Type::Unknown; // no actual matching
456  case wkbTINZ: return QgsWkbTypes::Type::Unknown; // no actual matching
457  case wkbTriangleZ: return QgsWkbTypes::Type::TriangleZ;
458 
459  case wkbPointM: return QgsWkbTypes::Type::PointM;
460  case wkbLineStringM: return QgsWkbTypes::Type::LineStringM;
461  case wkbPolygonM: return QgsWkbTypes::Type::PolygonM;
462  case wkbMultiPointM: return QgsWkbTypes::Type::MultiPointM;
463  case wkbMultiLineStringM: return QgsWkbTypes::Type::MultiLineStringM;
464  case wkbMultiPolygonM: return QgsWkbTypes::Type::MultiPolygonM;
465  case wkbGeometryCollectionM: return QgsWkbTypes::Type::GeometryCollectionM;
466  case wkbCircularStringM: return QgsWkbTypes::Type::CircularStringM;
467  case wkbCompoundCurveM: return QgsWkbTypes::Type::CompoundCurveM;
468  case wkbCurvePolygonM: return QgsWkbTypes::Type::CurvePolygonM;
469  case wkbMultiCurveM: return QgsWkbTypes::Type::MultiCurveM;
470  case wkbMultiSurfaceM: return QgsWkbTypes::Type::MultiSurfaceM;
471  case wkbCurveM: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
472  case wkbSurfaceM: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
473  case wkbPolyhedralSurfaceM: return QgsWkbTypes::Type::Unknown; // no actual matching
474  case wkbTINM: return QgsWkbTypes::Type::Unknown; // no actual matching
475  case wkbTriangleM: return QgsWkbTypes::Type::TriangleM;
476 
477  case wkbPointZM: return QgsWkbTypes::Type::PointZM;
478  case wkbLineStringZM: return QgsWkbTypes::Type::LineStringZM;
479  case wkbPolygonZM: return QgsWkbTypes::Type::PolygonZM;
480  case wkbMultiPointZM: return QgsWkbTypes::Type::MultiPointZM;
481  case wkbMultiLineStringZM: return QgsWkbTypes::Type::MultiLineStringZM;
482  case wkbMultiPolygonZM: return QgsWkbTypes::Type::MultiPolygonZM;
483  case wkbGeometryCollectionZM: return QgsWkbTypes::Type::GeometryCollectionZM;
484  case wkbCircularStringZM: return QgsWkbTypes::Type::CircularStringZM;
485  case wkbCompoundCurveZM: return QgsWkbTypes::Type::CompoundCurveZM;
486  case wkbCurvePolygonZM: return QgsWkbTypes::Type::CurvePolygonZM;
487  case wkbMultiCurveZM: return QgsWkbTypes::Type::MultiCurveZM;
488  case wkbMultiSurfaceZM: return QgsWkbTypes::Type::MultiSurfaceZM;
489  case wkbCurveZM: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
490  case wkbSurfaceZM: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
491  case wkbPolyhedralSurfaceZM: return QgsWkbTypes::Type::Unknown; // no actual matching
492  case wkbTINZM: return QgsWkbTypes::Type::Unknown; // no actual matching
493  case wkbTriangleZM: return QgsWkbTypes::Type::TriangleZM;
494 
495  case wkbPoint25D: return QgsWkbTypes::Type::PointZ;
496  case wkbLineString25D: return QgsWkbTypes::Type::LineStringZ;
497  case wkbPolygon25D: return QgsWkbTypes::Type::PolygonZ;
498  case wkbMultiPoint25D: return QgsWkbTypes::Type::MultiPointZ;
499  case wkbMultiLineString25D: return QgsWkbTypes::Type::MultiLineStringZ;
500  case wkbMultiPolygon25D: return QgsWkbTypes::Type::MultiPolygonZ;
501  case wkbGeometryCollection25D: return QgsWkbTypes::Type::GeometryCollectionZ;
502  }
503 
504  // should not reach that point normally
505  return QgsWkbTypes::Type::Unknown;
506 }
507 
509 {
510  if ( !geom )
511  return QgsGeometry();
512 
513  const auto ogrGeomType = OGR_G_GetGeometryType( geom );
514  QgsWkbTypes::Type wkbType = ogrGeometryTypeToQgsWkbType( ogrGeomType );
515 
516  // optimised case for some geometry classes, avoiding wkb conversion on OGR/QGIS sides
517  // TODO - extend to other classes!
518  switch ( QgsWkbTypes::flatType( wkbType ) )
519  {
520  case QgsWkbTypes::Point:
521  {
522  return QgsGeometry( ogrGeometryToQgsPoint( geom ) );
523  }
524 
526  {
527  return QgsGeometry( ogrGeometryToQgsMultiPoint( geom ) );
528  }
529 
531  {
532  // optimised case for line -- avoid wkb conversion
533  return QgsGeometry( ogrGeometryToQgsLineString( geom ) );
534  }
535 
537  {
538  // optimised case for line -- avoid wkb conversion
540  }
541 
542  default:
543  break;
544  };
545 
546  // Fallback to inefficient WKB conversions
547 
548  if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
549  {
550  // Shapefile MultiPatch can be reported as GeometryCollectionZ of TINZ
551  if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
552  wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
553  {
554  auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
555  auto ret = ogrGeometryToQgsGeometry( newGeom );
556  OGR_G_DestroyGeometry( newGeom );
557  return ret;
558  }
559  }
560 
561  // get the wkb representation
562  int memorySize = OGR_G_WkbSize( geom );
563  unsigned char *wkb = new unsigned char[memorySize];
564  OGR_G_ExportToWkb( geom, static_cast<OGRwkbByteOrder>( QgsApplication::endian() ), wkb );
565 
566  // Read original geometry type
567  uint32_t origGeomType;
568  memcpy( &origGeomType, wkb + 1, sizeof( uint32_t ) );
569  bool hasZ = ( origGeomType >= 1000 && origGeomType < 2000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
570  bool hasM = ( origGeomType >= 2000 && origGeomType < 3000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
571 
572  // PolyhedralSurface and TINs are not supported, map them to multipolygons...
573  if ( origGeomType % 1000 == 16 ) // is TIN, TINZ, TINM or TINZM
574  {
575  // TIN has the same wkb layout as a multipolygon, just need to overwrite the geom types...
576  int nDims = 2 + hasZ + hasM;
577  uint32_t newMultiType = static_cast<uint32_t>( QgsWkbTypes::zmType( QgsWkbTypes::MultiPolygon, hasZ, hasM ) );
578  uint32_t newSingleType = static_cast<uint32_t>( QgsWkbTypes::zmType( QgsWkbTypes::Polygon, hasZ, hasM ) );
579  unsigned char *wkbptr = wkb;
580 
581  // Endianness
582  wkbptr += 1;
583 
584  // Overwrite geom type
585  memcpy( wkbptr, &newMultiType, sizeof( uint32_t ) );
586  wkbptr += 4;
587 
588  // Geom count
589  uint32_t numGeoms;
590  memcpy( &numGeoms, wkb + 5, sizeof( uint32_t ) );
591  wkbptr += 4;
592 
593  // For each part, overwrite the geometry type to polygon (Z|M)
594  for ( uint32_t i = 0; i < numGeoms; ++i )
595  {
596  // Endianness
597  wkbptr += 1;
598 
599  // Overwrite geom type
600  memcpy( wkbptr, &newSingleType, sizeof( uint32_t ) );
601  wkbptr += sizeof( uint32_t );
602 
603  // skip coordinates
604  uint32_t nRings;
605  memcpy( &nRings, wkbptr, sizeof( uint32_t ) );
606  wkbptr += sizeof( uint32_t );
607 
608  for ( uint32_t j = 0; j < nRings; ++j )
609  {
610  uint32_t nPoints;
611  memcpy( &nPoints, wkbptr, sizeof( uint32_t ) );
612  wkbptr += sizeof( uint32_t ) + sizeof( double ) * nDims * nPoints;
613  }
614  }
615  }
616  else if ( origGeomType % 1000 == 15 ) // PolyhedralSurface, PolyhedralSurfaceZ, PolyhedralSurfaceM or PolyhedralSurfaceZM
617  {
618  // PolyhedralSurface has the same wkb layout as a MultiPolygon, just need to overwrite the geom type...
619  uint32_t newType = static_cast<uint32_t>( QgsWkbTypes::zmType( QgsWkbTypes::MultiPolygon, hasZ, hasM ) );
620  // Overwrite geom type
621  memcpy( wkb + 1, &newType, sizeof( uint32_t ) );
622  }
623 
624  QgsGeometry g;
625  g.fromWkb( wkb, memorySize );
626  return g;
627 }
628 
629 QgsFeatureList QgsOgrUtils::stringToFeatureList( const QString &string, const QgsFields &fields, QTextCodec *encoding )
630 {
631  QgsFeatureList features;
632  if ( string.isEmpty() )
633  return features;
634 
635  QString randomFileName = QStringLiteral( "/vsimem/%1" ).arg( QUuid::createUuid().toString() );
636 
637  // create memory file system object from string buffer
638  QByteArray ba = string.toUtf8();
639  VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), reinterpret_cast< GByte * >( ba.data() ),
640  static_cast< vsi_l_offset >( ba.size() ), FALSE ) );
641 
642  gdal::ogr_datasource_unique_ptr hDS( OGROpen( randomFileName.toUtf8().constData(), false, nullptr ) );
643  if ( !hDS )
644  {
645  VSIUnlink( randomFileName.toUtf8().constData() );
646  return features;
647  }
648 
649  OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
650  if ( !ogrLayer )
651  {
652  hDS.reset();
653  VSIUnlink( randomFileName.toUtf8().constData() );
654  return features;
655  }
656 
658  while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
659  {
660  QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
661  if ( feat.isValid() )
662  features << feat;
663  }
664 
665  hDS.reset();
666  VSIUnlink( randomFileName.toUtf8().constData() );
667 
668  return features;
669 }
670 
671 QgsFields QgsOgrUtils::stringToFields( const QString &string, QTextCodec *encoding )
672 {
673  QgsFields fields;
674  if ( string.isEmpty() )
675  return fields;
676 
677  QString randomFileName = QStringLiteral( "/vsimem/%1" ).arg( QUuid::createUuid().toString() );
678 
679  // create memory file system object from buffer
680  QByteArray ba = string.toUtf8();
681  VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), reinterpret_cast< GByte * >( ba.data() ),
682  static_cast< vsi_l_offset >( ba.size() ), FALSE ) );
683 
684  gdal::ogr_datasource_unique_ptr hDS( OGROpen( randomFileName.toUtf8().constData(), false, nullptr ) );
685  if ( !hDS )
686  {
687  VSIUnlink( randomFileName.toUtf8().constData() );
688  return fields;
689  }
690 
691  OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
692  if ( !ogrLayer )
693  {
694  hDS.reset();
695  VSIUnlink( randomFileName.toUtf8().constData() );
696  return fields;
697  }
698 
700  //read in the first feature only
701  if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
702  {
703  fields = readOgrFields( oFeat.get(), encoding );
704  }
705 
706  hDS.reset();
707  VSIUnlink( randomFileName.toUtf8().constData() );
708  return fields;
709 }
710 
711 QStringList QgsOgrUtils::cStringListToQStringList( char **stringList )
712 {
713  QStringList strings;
714 
715  // presume null terminated string list
716  for ( qgssize i = 0; stringList[i]; ++i )
717  {
718  strings.append( QString::fromUtf8( stringList[i] ) );
719  }
720 
721  return strings;
722 }
723 
725 {
726  if ( !srs )
727  return QString();
728 
729  char *pszWkt = nullptr;
730 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,0,0)
731  const QByteArray multiLineOption = QStringLiteral( "MULTILINE=NO" ).toLocal8Bit();
732  const QByteArray formatOption = QStringLiteral( "FORMAT=WKT2" ).toLocal8Bit();
733  const char *const options[] = {multiLineOption.constData(), formatOption.constData(), nullptr};
734  OSRExportToWktEx( srs, &pszWkt, options );
735 #else
736  OSRExportToWkt( srs, &pszWkt );
737 #endif
738 
739  const QString res( pszWkt );
740  CPLFree( pszWkt );
741  return res;
742 }
743 
745 {
746  const QString wkt = OGRSpatialReferenceToWkt( srs );
747  if ( wkt.isEmpty() )
749 
751 }
752 
753 QString QgsOgrUtils::readShapefileEncoding( const QString &path )
754 {
755  const QString cpgEncoding = readShapefileEncodingFromCpg( path );
756  if ( !cpgEncoding.isEmpty() )
757  return cpgEncoding;
758 
759  return readShapefileEncodingFromLdid( path );
760 }
761 
762 QString QgsOgrUtils::readShapefileEncodingFromCpg( const QString &path )
763 {
764 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0)
765  QString errCause;
766  QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path, false, QStringList(), 0, errCause, false );
767  return layer ? layer->GetMetadataItem( QStringLiteral( "ENCODING_FROM_CPG" ), QStringLiteral( "SHAPEFILE" ) ) : QString();
768 #else
769  if ( !QFileInfo::exists( path ) )
770  return QString();
771 
772  // first try to read cpg file, if present
773  const QFileInfo fi( path );
774  const QString baseName = fi.completeBaseName();
775  const QString cpgPath = fi.dir().filePath( QStringLiteral( "%1.%2" ).arg( baseName, fi.suffix() == QLatin1String( "SHP" ) ? QStringLiteral( "CPG" ) : QStringLiteral( "cpg" ) ) );
776  if ( QFile::exists( cpgPath ) )
777  {
778  QFile cpgFile( cpgPath );
779  if ( cpgFile.open( QIODevice::ReadOnly ) )
780  {
781  QTextStream cpgStream( &cpgFile );
782  const QString cpgString = cpgStream.readLine();
783  cpgFile.close();
784 
785  if ( !cpgString.isEmpty() )
786  {
787  // from OGRShapeLayer::ConvertCodePage
788  // https://github.com/OSGeo/gdal/blob/master/gdal/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp#L342
789  bool ok = false;
790  int cpgCodePage = cpgString.toInt( &ok );
791  if ( ok && ( ( cpgCodePage >= 437 && cpgCodePage <= 950 )
792  || ( cpgCodePage >= 1250 && cpgCodePage <= 1258 ) ) )
793  {
794  return QStringLiteral( "CP%1" ).arg( cpgCodePage );
795  }
796  else if ( cpgString.startsWith( QLatin1String( "8859" ) ) )
797  {
798  if ( cpgString.length() > 4 && cpgString.at( 4 ) == '-' )
799  return QStringLiteral( "ISO-8859-%1" ).arg( cpgString.mid( 5 ) );
800  else
801  return QStringLiteral( "ISO-8859-%1" ).arg( cpgString.mid( 4 ) );
802  }
803  else if ( cpgString.startsWith( QLatin1String( "UTF-8" ), Qt::CaseInsensitive ) ||
804  cpgString.startsWith( QLatin1String( "UTF8" ), Qt::CaseInsensitive ) )
805  return QStringLiteral( "UTF-8" );
806  else if ( cpgString.startsWith( QLatin1String( "ANSI 1251" ), Qt::CaseInsensitive ) )
807  return QStringLiteral( "CP1251" );
808 
809  return cpgString;
810  }
811  }
812  }
813 #endif
814  return QString();
815 }
816 
817 QString QgsOgrUtils::readShapefileEncodingFromLdid( const QString &path )
818 {
819 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0)
820  QString errCause;
821  QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path, false, QStringList(), 0, errCause, false );
822  return layer ? layer->GetMetadataItem( QStringLiteral( "ENCODING_FROM_LDID" ), QStringLiteral( "SHAPEFILE" ) ) : QString();
823 #else
824  // from OGRShapeLayer::ConvertCodePage
825  // https://github.com/OSGeo/gdal/blob/master/gdal/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp#L342
826 
827  if ( !QFileInfo::exists( path ) )
828  return QString();
829 
830  // first try to read cpg file, if present
831  const QFileInfo fi( path );
832  const QString baseName = fi.completeBaseName();
833 
834  // fallback to LDID value, read from DBF file
835  const QString dbfPath = fi.dir().filePath( QStringLiteral( "%1.%2" ).arg( baseName, fi.suffix() == QLatin1String( "SHP" ) ? QStringLiteral( "DBF" ) : QStringLiteral( "dbf" ) ) );
836  if ( QFile::exists( dbfPath ) )
837  {
838  QFile dbfFile( dbfPath );
839  if ( dbfFile.open( QIODevice::ReadOnly ) )
840  {
841  dbfFile.read( 29 );
842  QDataStream dbfIn( &dbfFile );
843  dbfIn.setByteOrder( QDataStream::LittleEndian );
844  quint8 ldid;
845  dbfIn >> ldid;
846  dbfFile.close();
847 
848  int nCP = -1; // Windows code page.
849 
850  // http://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTM
851  switch ( ldid )
852  {
853  case 1: nCP = 437; break;
854  case 2: nCP = 850; break;
855  case 3: nCP = 1252; break;
856  case 4: nCP = 10000; break;
857  case 8: nCP = 865; break;
858  case 10: nCP = 850; break;
859  case 11: nCP = 437; break;
860  case 13: nCP = 437; break;
861  case 14: nCP = 850; break;
862  case 15: nCP = 437; break;
863  case 16: nCP = 850; break;
864  case 17: nCP = 437; break;
865  case 18: nCP = 850; break;
866  case 19: nCP = 932; break;
867  case 20: nCP = 850; break;
868  case 21: nCP = 437; break;
869  case 22: nCP = 850; break;
870  case 23: nCP = 865; break;
871  case 24: nCP = 437; break;
872  case 25: nCP = 437; break;
873  case 26: nCP = 850; break;
874  case 27: nCP = 437; break;
875  case 28: nCP = 863; break;
876  case 29: nCP = 850; break;
877  case 31: nCP = 852; break;
878  case 34: nCP = 852; break;
879  case 35: nCP = 852; break;
880  case 36: nCP = 860; break;
881  case 37: nCP = 850; break;
882  case 38: nCP = 866; break;
883  case 55: nCP = 850; break;
884  case 64: nCP = 852; break;
885  case 77: nCP = 936; break;
886  case 78: nCP = 949; break;
887  case 79: nCP = 950; break;
888  case 80: nCP = 874; break;
889  case 87: return QStringLiteral( "ISO-8859-1" );
890  case 88: nCP = 1252; break;
891  case 89: nCP = 1252; break;
892  case 100: nCP = 852; break;
893  case 101: nCP = 866; break;
894  case 102: nCP = 865; break;
895  case 103: nCP = 861; break;
896  case 104: nCP = 895; break;
897  case 105: nCP = 620; break;
898  case 106: nCP = 737; break;
899  case 107: nCP = 857; break;
900  case 108: nCP = 863; break;
901  case 120: nCP = 950; break;
902  case 121: nCP = 949; break;
903  case 122: nCP = 936; break;
904  case 123: nCP = 932; break;
905  case 124: nCP = 874; break;
906  case 134: nCP = 737; break;
907  case 135: nCP = 852; break;
908  case 136: nCP = 857; break;
909  case 150: nCP = 10007; break;
910  case 151: nCP = 10029; break;
911  case 200: nCP = 1250; break;
912  case 201: nCP = 1251; break;
913  case 202: nCP = 1254; break;
914  case 203: nCP = 1253; break;
915  case 204: nCP = 1257; break;
916  default: break;
917  }
918 
919  if ( nCP != -1 )
920  {
921  return QStringLiteral( "CP%1" ).arg( nCP );
922  }
923  }
924  }
925  return QString();
926 #endif
927 }
QgsOgrUtils::readOgrFeatureAttributes
static bool readOgrFeatureAttributes(OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding)
Reads all attributes from an OGR feature into a QgsFeature.
Definition: qgsogrutils.cpp:324
qgsfields.h
gdal::ogr_feature_unique_ptr
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
Definition: qgsogrutils.h:129
QgsWkbTypes::Point
@ Point
Definition: qgswkbtypes.h:71
qgslinestring.h
QgsWkbTypes::MultiPolygon
@ MultiPolygon
Definition: qgswkbtypes.h:77
QgsOgrUtils::readOgrFeatureGeometry
static bool readOgrFeatureGeometry(OGRFeatureH ogrFet, QgsFeature &feature)
Reads the geometry from an OGR feature into a QgsFeature.
Definition: qgsogrutils.cpp:345
QgsFeature::setId
void setId(QgsFeatureId id)
Sets the feature ID for this feature.
Definition: qgsfeature.cpp:112
QgsFeature::initAttributes
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:202
QgsWkbTypes::LineString25D
@ LineString25D
Definition: qgswkbtypes.h:125
gdal::OGRFldDeleter::operator()
void CORE_EXPORT operator()(OGRFieldDefnH definition)
Destroys an OGR field definition, using the correct gdal calls.
Definition: qgsogrutils.cpp:56
gdal::ogr_datasource_unique_ptr
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
Definition: qgsogrutils.h:114
QgsWkbTypes::LineString
@ LineString
Definition: qgswkbtypes.h:72
QgsFields::count
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
gdal::GDALDatasetCloser::operator()
void CORE_EXPORT operator()(GDALDatasetH datasource)
Destroys an gdal dataset, using the correct gdal calls.
Definition: qgsogrutils.cpp:66
QgsFields
Definition: qgsfields.h:44
QgsGeometry::fromWkb
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
Definition: qgsgeometry.cpp:332
qgsmultipoint.h
gdal::OGRDataSourceDeleter::operator()
void CORE_EXPORT operator()(OGRDataSourceH source)
Destroys an OGR data source, using the correct gdal calls.
Definition: qgsogrutils.cpp:45
QgsFeature::setValid
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:188
QgsOgrUtils::readShapefileEncoding
static QString readShapefileEncoding(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
Definition: qgsogrutils.cpp:753
qgsogrutils.h
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
QgsOgrUtils::OGRSpatialReferenceToWkt
static QString OGRSpatialReferenceToWkt(OGRSpatialReferenceH srs)
Returns a WKT string corresponding to the specified OGR srs object.
Definition: qgsogrutils.cpp:724
QgsOgrUtils::stringToFeatureList
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a string representing a collection of features using OGR.
Definition: qgsogrutils.cpp:629
QgsWkbTypes::hasZ
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1042
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsFields::append
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
ogrGeometryToQgsMultiPoint
std::unique_ptr< QgsMultiPoint > ogrGeometryToQgsMultiPoint(OGRGeometryH geom)
Definition: qgsogrutils.cpp:368
QgsFeature::clearGeometry
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:151
OGR_F_IsFieldSetAndNotNull
#define OGR_F_IsFieldSetAndNotNull
Definition: qgsogrutils.cpp:40
qgsapplication.h
OGRSpatialReferenceH
void * OGRSpatialReferenceH
Definition: qgscoordinatereferencesystem.h:60
ogrGeometryToQgsPoint
std::unique_ptr< QgsPoint > ogrGeometryToQgsPoint(OGRGeometryH geom)
Definition: qgsogrutils.cpp:359
QgsWkbTypes::MultiLineString
@ MultiLineString
Definition: qgswkbtypes.h:76
QgsOgrUtils::stringToFields
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a string representing a collection of features using OGR.
Definition: qgsogrutils.cpp:671
QgsOgrUtils::readOgrFields
static QgsFields readOgrFields(OGRFeatureH ogrFet, QTextCodec *encoding)
Reads an OGR feature and returns a corresponding fields collection.
Definition: qgsogrutils.cpp:121
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:137
gdal::dataset_unique_ptr
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
Definition: qgsogrutils.h:134
gdal::OGRFeatureDeleter::operator()
void CORE_EXPORT operator()(OGRFeatureH feature)
Destroys an OGR feature, using the correct gdal calls.
Definition: qgsogrutils.cpp:61
QgsFeature::isValid
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
QgsFeature::setFields
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
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:572
QgsOgrUtils::readOgrFeature
static QgsFeature readOgrFeature(OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding)
Reads an OGR feature and converts it to a QgsFeature.
Definition: qgsogrutils.cpp:96
QgsApplication::endian
static endian_t endian()
Returns whether this machine uses big or little endian.
Definition: qgsapplication.cpp:1230
gdal::fast_delete_and_close
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:71
QgsCoordinateReferenceSystem
Definition: qgscoordinatereferencesystem.h:206
QgsOgrUtils::ogrGeometryToQgsGeometry
static QgsGeometry ogrGeometryToQgsGeometry(OGRGeometryH geom)
Converts an OGR geometry representation to a QgsGeometry object.
Definition: qgsogrutils.cpp:508
QgsWkbTypes::zmType
static Type zmType(Type type, bool hasZ, bool hasM)
Returns the modified input geometry type according to hasZ / hasM.
Definition: qgswkbtypes.h:800
QgsField::subType
QVariant::Type subType() const
If the field is a collection, gets its element's type.
Definition: qgsfield.cpp:134
QgsFeature::setAttribute
bool setAttribute(int field, const QVariant &attr)
Set an attribute's value by field index.
Definition: qgsfeature.cpp:211
QgsWkbTypes::hasM
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1092
qgsgeometry.h
QgsGeometry
Definition: qgsgeometry.h:122
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:73
QgsWkbTypes::MultiPoint
@ MultiPoint
Definition: qgswkbtypes.h:75
QgsOgrUtils::OGRSpatialReferenceToCrs
static QgsCoordinateReferenceSystem OGRSpatialReferenceToCrs(OGRSpatialReferenceH srs)
Returns a QgsCoordinateReferenceSystem corresponding to the specified OGR srs object,...
Definition: qgsogrutils.cpp:744
QgsOgrUtils::readShapefileEncodingFromLdid
static QString readShapefileEncodingFromLdid(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
Definition: qgsogrutils.cpp:817
gdal::OGRGeometryDeleter::operator()
void CORE_EXPORT operator()(OGRGeometryH geometry)
Destroys an OGR geometry, using the correct gdal calls.
Definition: qgsogrutils.cpp:51
QgsOgrUtils::readShapefileEncodingFromCpg
static QString readShapefileEncodingFromCpg(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
Definition: qgsogrutils.cpp:762
QgsFeature
Definition: qgsfeature.h:55
QgsOgrUtils::getOgrFeatureAttribute
static QVariant getOgrFeatureAttribute(OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok=nullptr)
Retrieves an attribute value from an OGR feature.
Definition: qgsogrutils.cpp:180
qgslogger.h
ogrGeometryToQgsLineString
std::unique_ptr< QgsLineString > ogrGeometryToQgsLineString(OGRGeometryH geom)
Definition: qgsogrutils.cpp:382
QgsFields::at
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
QgsCoordinateReferenceSystem::fromWkt
static QgsCoordinateReferenceSystem fromWkt(const QString &wkt)
Creates a CRS from a WKT spatial ref sys definition string.
Definition: qgscoordinatereferencesystem.cpp:233
QgsOgrUtils::ogrGeometryTypeToQgsWkbType
static QgsWkbTypes::Type ogrGeometryTypeToQgsWkbType(OGRwkbGeometryType ogrGeomType)
Converts a OGRwkbGeometryType to QgsWkbTypes::Type.
Definition: qgsogrutils.cpp:422
ogrGeometryToQgsMultiLineString
std::unique_ptr< QgsMultiLineString > ogrGeometryToQgsMultiLineString(OGRGeometryH geom)
Definition: qgsogrutils.cpp:408
QgsField::type
QVariant::Type type
Definition: qgsfield.h:57
gdal::GDALWarpOptionsDeleter::operator()
void CORE_EXPORT operator()(GDALWarpOptions *options)
Destroys GDAL warp options, using the correct gdal calls.
Definition: qgsogrutils.cpp:91
QgsOgrUtils::cStringListToQStringList
static QStringList cStringListToQStringList(char **stringList)
Converts a c string list to a QStringList.
Definition: qgsogrutils.cpp:711
QgsWkbTypes::flatType
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:701
qgsmultilinestring.h
qgssize
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:723
QgsField
Definition: qgsfield.h:49
GDALDatasetH
void * GDALDatasetH
Definition: qgsalignraster.h:28