1 /*************************************************************************** 2 qgsogrutils.h 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 #ifndef QGSOGRUTILS_H 17 #define QGSOGRUTILS_H 18 19 #define SIP_NO_FILE 20 21 #include "qgis_core.h" 22 #include "qgsfeature.h" 23 24 #include <ogr_api.h> 25 #include <gdal.h> 26 #include <gdalwarper.h> 27 #include "cpl_conv.h" 28 #include "cpl_string.h" 29 30 namespace gdal 31 { 32 33 /** 34 * Destroys OGR data sources. 35 */ 36 struct OGRDataSourceDeleter 37 { 38 39 /** 40 * Destroys an OGR data \a source, using the correct gdal calls. 41 */ 42 void CORE_EXPORT operator()( OGRDataSourceH source ); 43 44 }; 45 46 /** 47 * Destroys OGR geometries. 48 */ 49 struct OGRGeometryDeleter 50 { 51 52 /** 53 * Destroys an OGR \a geometry, using the correct gdal calls. 54 */ 55 void CORE_EXPORT operator()( OGRGeometryH geometry ); 56 57 }; 58 59 /** 60 * Destroys OGR field definition. 61 */ 62 struct OGRFldDeleter 63 { 64 65 /** 66 * Destroys an OGR field \a definition, using the correct gdal calls. 67 */ 68 void CORE_EXPORT operator()( OGRFieldDefnH definition ); 69 70 }; 71 72 /** 73 * Destroys OGR feature. 74 */ 75 struct OGRFeatureDeleter 76 { 77 78 /** 79 * Destroys an OGR \a feature, using the correct gdal calls. 80 */ 81 void CORE_EXPORT operator()( OGRFeatureH feature ); 82 83 }; 84 85 /** 86 * Closes and cleanups GDAL dataset. 87 */ 88 struct GDALDatasetCloser 89 { 90 91 /** 92 * Destroys an gdal \a dataset, using the correct gdal calls. 93 */ 94 void CORE_EXPORT operator()( GDALDatasetH datasource ); 95 96 }; 97 98 /** 99 * Closes and cleanups GDAL warp options. 100 */ 101 struct GDALWarpOptionsDeleter 102 { 103 104 /** 105 * Destroys GDAL warp \a options, using the correct gdal calls. 106 */ 107 void CORE_EXPORT operator()( GDALWarpOptions *options ); 108 109 }; 110 111 /** 112 * Scoped OGR data source. 113 */ 114 using ogr_datasource_unique_ptr = std::unique_ptr< std::remove_pointer<OGRDataSourceH>::type, OGRDataSourceDeleter >; 115 116 /** 117 * Scoped OGR geometry. 118 */ 119 using ogr_geometry_unique_ptr = std::unique_ptr< std::remove_pointer<OGRGeometryH>::type, OGRGeometryDeleter >; 120 121 /** 122 * Scoped OGR field definition. 123 */ 124 using ogr_field_def_unique_ptr = std::unique_ptr< std::remove_pointer<OGRFieldDefnH>::type, OGRFldDeleter >; 125 126 /** 127 * Scoped OGR feature. 128 */ 129 using ogr_feature_unique_ptr = std::unique_ptr< std::remove_pointer<OGRFeatureH>::type, OGRFeatureDeleter >; 130 131 /** 132 * Scoped GDAL dataset. 133 */ 134 using dataset_unique_ptr = std::unique_ptr< std::remove_pointer<GDALDatasetH>::type, GDALDatasetCloser >; 135 136 /** 137 * Performs a fast close of an unwanted GDAL dataset handle by deleting the underlying 138 * data store. Use when the resultant dataset is no longer required, e.g. as a result 139 * of user cancellation of an operation. 140 * 141 * Requires a gdal \a dataset pointer, the corresponding gdal \a driver and underlying 142 * dataset file \a path. 143 */ 144 void CORE_EXPORT fast_delete_and_close( dataset_unique_ptr &dataset, GDALDriverH driver, const QString &path ); 145 146 /** 147 * Scoped GDAL warp options. 148 */ 149 using warp_options_unique_ptr = std::unique_ptr< GDALWarpOptions, GDALWarpOptionsDeleter >; 150 } 151 152 /** 153 * \ingroup core 154 * \class QgsOgrUtils 155 * \brief Utilities for working with OGR features and layers 156 * 157 * Contains helper utilities for assisting work with both OGR features and layers. 158 * \note not available in Python bindings 159 * \since QGIS 2.16 160 */ 161 class CORE_EXPORT QgsOgrUtils 162 { 163 public: 164 165 /** 166 * Reads an OGR feature and converts it to a QgsFeature. 167 * \param ogrFet OGR feature handle 168 * \param fields fields collection corresponding to feature 169 * \param encoding text encoding 170 * \returns valid feature if read was successful 171 */ 172 static QgsFeature readOgrFeature( OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding ); 173 174 /** 175 * Reads an OGR feature and returns a corresponding fields collection. 176 * \param ogrFet OGR feature handle 177 * \param encoding text encoding 178 * \returns fields collection if read was successful 179 */ 180 static QgsFields readOgrFields( OGRFeatureH ogrFet, QTextCodec *encoding ); 181 182 /** 183 * Retrieves an attribute value from an OGR feature. 184 * \param ogrFet OGR feature handle 185 * \param fields fields collection corresponding to feature 186 * \param attIndex index of attribute to retrieve 187 * \param encoding text encoding 188 * \param ok optional storage for success of retrieval 189 * \returns attribute converted to a QVariant object 190 * \see readOgrFeatureAttributes() 191 */ 192 static QVariant getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok = nullptr ); 193 194 /** 195 * Retrieves an attribute value from an OGR feature, using a provided \a field definition. 196 * \param ogrFet OGR feature handle 197 * \param field definition of corresponding field 198 * \param attIndex index of attribute to retrieve from \a ogrFet 199 * \param encoding text encoding 200 * \param ok optional storage for success of retrieval 201 * \returns attribute converted to a QVariant object 202 * \see readOgrFeatureAttributes() 203 * 204 * \since QGIS 3.10.1 205 */ 206 static QVariant getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsField &field, int attIndex, QTextCodec *encoding, bool *ok = nullptr ); 207 208 /** 209 * Reads all attributes from an OGR feature into a QgsFeature. 210 * \param ogrFet OGR feature handle 211 * \param fields fields collection corresponding to feature 212 * \param feature QgsFeature to store attributes in 213 * \param encoding text encoding 214 * \returns TRUE if attribute read was successful 215 * \see getOgrFeatureAttribute() 216 */ 217 static bool readOgrFeatureAttributes( OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding ); 218 219 /** 220 * Reads the geometry from an OGR feature into a QgsFeature. 221 * \param ogrFet OGR feature handle 222 * \param feature QgsFeature to store geometry in 223 * \returns TRUE if geometry read was successful 224 * \see readOgrFeatureAttributes() 225 * \see ogrGeometryToQgsGeometry() 226 */ 227 static bool readOgrFeatureGeometry( OGRFeatureH ogrFet, QgsFeature &feature ); 228 229 /** 230 * Converts an OGR geometry representation to a QgsGeometry object 231 * \param geom OGR geometry handle 232 * \returns QgsGeometry object. If conversion was not successful the geometry 233 * will be empty. 234 * \see readOgrFeatureGeometry() 235 */ 236 static QgsGeometry ogrGeometryToQgsGeometry( OGRGeometryH geom ); 237 238 /** 239 * Attempts to parse a string representing a collection of features using OGR. For example, this method can be 240 * used to convert a GeoJSON encoded collection to a list of QgsFeatures. 241 * \param string string to parse 242 * \param fields fields collection to use for parsed features (\see stringToFields()) 243 * \param encoding text encoding 244 * \returns list of parsed features, or an empty list if no features could be parsed 245 * \see stringToFields() 246 */ 247 static QgsFeatureList stringToFeatureList( const QString &string, const QgsFields &fields, QTextCodec *encoding ); 248 249 /** 250 * Attempts to retrieve the fields from a string representing a collection of features using OGR. 251 * \param string string to parse 252 * \param encoding text encoding 253 * \returns retrieved fields collection, or an empty list if no fields could be determined from the string 254 * \see stringToFeatureList() 255 */ 256 static QgsFields stringToFields( const QString &string, QTextCodec *encoding ); 257 258 /** 259 * Converts a c string list to a QStringList. Presumes a null terminated string list. 260 * 261 * \since QGIS 3.2 262 */ 263 static QStringList cStringListToQStringList( char **stringList ); 264 265 /** 266 * Converts a OGRwkbGeometryType to QgsWkbTypes::Type 267 * 268 * \since QGIS 3.4.9 269 */ 270 static QgsWkbTypes::Type ogrGeometryTypeToQgsWkbType( OGRwkbGeometryType ogrGeomType ); 271 272 /** 273 * Returns a WKT string corresponding to the specified OGR \a srs object. 274 * 275 * The WKT string format will be selected using the most appropriate format (usually WKT2 if GDAL 3 is available). 276 * 277 * \since QGIS 3.10.1 278 */ 279 static QString OGRSpatialReferenceToWkt( OGRSpatialReferenceH srs ); 280 281 /** 282 * Returns a QgsCoordinateReferenceSystem corresponding to the specified OGR \a srs object, or an invalid 283 * QgsCoordinateReferenceSystem if \a srs could not be converted. 284 * 285 * \since QGIS 3.10.1 286 */ 287 static QgsCoordinateReferenceSystem OGRSpatialReferenceToCrs( OGRSpatialReferenceH srs ); 288 289 /** 290 * Reads the encoding of the shapefile at the specified \a path (where \a path is the 291 * location of the ".shp" file). 292 * 293 * This method considers both the CPG specified encoding and the DBF LDID encoding 294 * (priority goes to CPG based encoding) 295 * 296 * \see readShapefileEncodingFromCpg() 297 * \see readShapefileEncodingFromLdid() 298 * \since QGIS 3.12 299 */ 300 static QString readShapefileEncoding( const QString &path ); 301 302 /** 303 * Reads the encoding of the shapefile at the specified \a path (where \a path is the 304 * location of the ".shp" file), from the CPG specified encoding. 305 * 306 * Return an empty string if CPG based encoding was not found. 307 * 308 * \see readShapefileEncoding() 309 * \since QGIS 3.12 310 */ 311 static QString readShapefileEncodingFromCpg( const QString &path ); 312 313 /** 314 * Reads the encoding of the shapefile at the specified \a path (where \a path is the 315 * location of the ".shp" file), from the DBF LDID encoding. 316 * 317 * Return an empty string if LDID based encoding was not found. 318 * 319 * \see readShapefileEncoding() 320 * \since QGIS 3.12 321 */ 322 static QString readShapefileEncodingFromLdid( const QString &path ); 323 }; 324 325 #endif // QGSOGRUTILS_H 326