24 #include <cpl_error.h> 25 #include <QJsonDocument> 31 #define OGR_F_IsFieldSetAndNotNull OGR_F_IsFieldSet 38 OGR_DS_Destroy( source );
44 OGR_G_DestroyGeometry( geometry );
49 OGR_Fld_Destroy( definition );
54 OGR_F_Destroy( feature );
71 CPLPushErrorHandler( CPLQuietErrorHandler );
72 GDALDeleteDataset( driver, path.toUtf8().constData() );
84 GDALDestroyWarpOptions( options );
96 feature.
setId( OGR_F_GetFID( ogrFet ) );
99 if ( !readOgrFeatureGeometry( ogrFet, feature ) )
104 if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
119 int fieldCount = OGR_F_GetFieldCount( ogrFet );
120 for (
int i = 0; i < fieldCount; ++i )
122 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
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 ) )
134 if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
135 varType = QVariant::Bool;
137 varType = QVariant::Int;
140 varType = QVariant::LongLong;
143 varType = QVariant::Double;
146 varType = QVariant::Date;
149 varType = QVariant::Time;
152 varType = QVariant::DateTime;
155 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0) 156 if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
157 varType = QVariant::Map;
159 varType = QVariant::String;
163 varType = QVariant::String;
172 if ( !ogrFet || attIndex < 0 || attIndex >= fields.
count() )
179 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
186 QgsDebugMsg( QStringLiteral(
"ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
197 switch ( fields.
at( attIndex ).
type() )
199 case QVariant::String:
202 value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
204 value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
208 value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
211 value = QVariant(
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
213 case QVariant::LongLong:
214 value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
216 case QVariant::Double:
217 value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
220 case QVariant::DateTime:
223 int year, month, day, hour, minute, second, tzf;
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 );
231 value = QDateTime( QDate( year, month, day ), QTime( hour, minute, second ) );
235 case QVariant::ByteArray:
238 const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
242 QByteArray ba = QByteArray::fromRawData( reinterpret_cast<const char *>( b ), size );
251 if ( fields.
at( attIndex ).
subType() == QVariant::String )
254 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
255 const int count = CSLCount( lst );
258 for (
int i = 0; i < count; i++ )
261 list << encoding->toUnicode( lst[i] );
263 list << QString::fromUtf8( lst[i] );
270 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
282 value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
284 value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
288 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
295 value = QVariant( QString() );
311 for (
int idx = 0; idx < fields.
count(); ++idx )
313 QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
327 OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
331 feature.
setGeometry( ogrGeometryToQgsGeometry( geom ) );
341 OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
342 return qgis::make_unique< QgsPoint >( wkbType, x, y, z, m );
349 int count = OGR_G_GetPointCount( geom );
350 QVector< double > x( count );
351 QVector< double > y( count );
353 double *pz =
nullptr;
359 double *pm =
nullptr;
366 OGR_G_GetPointsZM( geom, x.data(),
sizeof( double ), y.data(),
sizeof( double ), pz,
sizeof(
double ), pm,
sizeof( double ) );
373 switch ( ogrGeomType )
375 case wkbUnknown:
return QgsWkbTypes::Type::Unknown;
376 case wkbPoint:
return QgsWkbTypes::Type::Point;
377 case wkbLineString:
return QgsWkbTypes::Type::LineString;
378 case wkbPolygon:
return QgsWkbTypes::Type::Polygon;
379 case wkbMultiPoint:
return QgsWkbTypes::Type::MultiPoint;
380 case wkbMultiLineString:
return QgsWkbTypes::Type::MultiLineString;
381 case wkbMultiPolygon:
return QgsWkbTypes::Type::MultiPolygon;
382 case wkbGeometryCollection:
return QgsWkbTypes::Type::GeometryCollection;
383 case wkbCircularString:
return QgsWkbTypes::Type::CircularString;
384 case wkbCompoundCurve:
return QgsWkbTypes::Type::CompoundCurve;
385 case wkbCurvePolygon:
return QgsWkbTypes::Type::CurvePolygon;
386 case wkbMultiCurve:
return QgsWkbTypes::Type::MultiCurve;
387 case wkbMultiSurface:
return QgsWkbTypes::Type::MultiSurface;
388 case wkbCurve:
return QgsWkbTypes::Type::Unknown;
389 case wkbSurface:
return QgsWkbTypes::Type::Unknown;
390 case wkbPolyhedralSurface:
return QgsWkbTypes::Type::Unknown;
391 case wkbTIN:
return QgsWkbTypes::Type::Unknown;
392 case wkbTriangle:
return QgsWkbTypes::Type::Triangle;
394 case wkbNone:
return QgsWkbTypes::Type::NoGeometry;
395 case wkbLinearRing:
return QgsWkbTypes::Type::LineString;
397 case wkbCircularStringZ:
return QgsWkbTypes::Type::CircularStringZ;
398 case wkbCompoundCurveZ:
return QgsWkbTypes::Type::CompoundCurveZ;
399 case wkbCurvePolygonZ:
return QgsWkbTypes::Type::CurvePolygonZ;
400 case wkbMultiCurveZ:
return QgsWkbTypes::Type::MultiCurveZ;
401 case wkbMultiSurfaceZ:
return QgsWkbTypes::Type::MultiSurfaceZ;
402 case wkbCurveZ:
return QgsWkbTypes::Type::Unknown;
403 case wkbSurfaceZ:
return QgsWkbTypes::Type::Unknown;
404 case wkbPolyhedralSurfaceZ:
return QgsWkbTypes::Type::Unknown;
405 case wkbTINZ:
return QgsWkbTypes::Type::Unknown;
406 case wkbTriangleZ:
return QgsWkbTypes::Type::TriangleZ;
408 case wkbPointM:
return QgsWkbTypes::Type::PointM;
409 case wkbLineStringM:
return QgsWkbTypes::Type::LineStringM;
410 case wkbPolygonM:
return QgsWkbTypes::Type::PolygonM;
411 case wkbMultiPointM:
return QgsWkbTypes::Type::MultiPointM;
412 case wkbMultiLineStringM:
return QgsWkbTypes::Type::MultiLineStringM;
413 case wkbMultiPolygonM:
return QgsWkbTypes::Type::MultiPolygonM;
414 case wkbGeometryCollectionM:
return QgsWkbTypes::Type::GeometryCollectionM;
415 case wkbCircularStringM:
return QgsWkbTypes::Type::CircularStringM;
416 case wkbCompoundCurveM:
return QgsWkbTypes::Type::CompoundCurveM;
417 case wkbCurvePolygonM:
return QgsWkbTypes::Type::CurvePolygonM;
418 case wkbMultiCurveM:
return QgsWkbTypes::Type::MultiCurveM;
419 case wkbMultiSurfaceM:
return QgsWkbTypes::Type::MultiSurfaceM;
420 case wkbCurveM:
return QgsWkbTypes::Type::Unknown;
421 case wkbSurfaceM:
return QgsWkbTypes::Type::Unknown;
422 case wkbPolyhedralSurfaceM:
return QgsWkbTypes::Type::Unknown;
423 case wkbTINM:
return QgsWkbTypes::Type::Unknown;
424 case wkbTriangleM:
return QgsWkbTypes::Type::TriangleM;
426 case wkbPointZM:
return QgsWkbTypes::Type::PointZM;
427 case wkbLineStringZM:
return QgsWkbTypes::Type::LineStringZM;
428 case wkbPolygonZM:
return QgsWkbTypes::Type::PolygonZM;
429 case wkbMultiPointZM:
return QgsWkbTypes::Type::MultiPointZM;
430 case wkbMultiLineStringZM:
return QgsWkbTypes::Type::MultiLineStringZM;
431 case wkbMultiPolygonZM:
return QgsWkbTypes::Type::MultiPolygonZM;
432 case wkbGeometryCollectionZM:
return QgsWkbTypes::Type::GeometryCollectionZM;
433 case wkbCircularStringZM:
return QgsWkbTypes::Type::CircularStringZM;
434 case wkbCompoundCurveZM:
return QgsWkbTypes::Type::CompoundCurveZM;
435 case wkbCurvePolygonZM:
return QgsWkbTypes::Type::CurvePolygonZM;
436 case wkbMultiCurveZM:
return QgsWkbTypes::Type::MultiCurveZM;
437 case wkbMultiSurfaceZM:
return QgsWkbTypes::Type::MultiSurfaceZM;
438 case wkbCurveZM:
return QgsWkbTypes::Type::Unknown;
439 case wkbSurfaceZM:
return QgsWkbTypes::Type::Unknown;
440 case wkbPolyhedralSurfaceZM:
return QgsWkbTypes::Type::Unknown;
441 case wkbTINZM:
return QgsWkbTypes::Type::Unknown;
442 case wkbTriangleZM:
return QgsWkbTypes::Type::TriangleZM;
444 case wkbPoint25D:
return QgsWkbTypes::Type::PointZ;
445 case wkbLineString25D:
return QgsWkbTypes::Type::LineStringZ;
446 case wkbPolygon25D:
return QgsWkbTypes::Type::PolygonZ;
447 case wkbMultiPoint25D:
return QgsWkbTypes::Type::MultiPointZ;
448 case wkbMultiLineString25D:
return QgsWkbTypes::Type::MultiLineStringZ;
449 case wkbMultiPolygon25D:
return QgsWkbTypes::Type::MultiPolygonZ;
450 case wkbGeometryCollection25D:
return QgsWkbTypes::Type::GeometryCollectionZ;
454 return QgsWkbTypes::Type::Unknown;
462 const auto ogrGeomType = OGR_G_GetGeometryType( geom );
486 if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
489 if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
490 wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
492 auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
493 auto ret = ogrGeometryToQgsGeometry( newGeom );
494 OGR_G_DestroyGeometry( newGeom );
500 int memorySize = OGR_G_WkbSize( geom );
501 unsigned char *wkb =
new unsigned char[memorySize];
505 uint32_t origGeomType;
506 memcpy( &origGeomType, wkb + 1,
sizeof( uint32_t ) );
507 bool hasZ = ( origGeomType >= 1000 && origGeomType < 2000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
508 bool hasM = ( origGeomType >= 2000 && origGeomType < 3000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
511 if ( origGeomType % 1000 == 16 )
514 int nDims = 2 + hasZ + hasM;
517 unsigned char *wkbptr = wkb;
523 memcpy( wkbptr, &newMultiType,
sizeof( uint32_t ) );
528 memcpy( &numGeoms, wkb + 5,
sizeof( uint32_t ) );
532 for ( uint32_t i = 0; i < numGeoms; ++i )
538 memcpy( wkbptr, &newSingleType,
sizeof( uint32_t ) );
539 wkbptr +=
sizeof( uint32_t );
543 memcpy( &nRings, wkbptr,
sizeof( uint32_t ) );
544 wkbptr +=
sizeof( uint32_t );
546 for ( uint32_t j = 0; j < nRings; ++j )
549 memcpy( &nPoints, wkbptr,
sizeof( uint32_t ) );
550 wkbptr +=
sizeof( uint32_t ) +
sizeof(
double ) * nDims * nPoints;
554 else if ( origGeomType % 1000 == 15 )
559 memcpy( wkb + 1, &newType,
sizeof( uint32_t ) );
570 if (
string.isEmpty() )
573 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
576 QByteArray ba =
string.toUtf8();
577 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
578 static_cast< vsi_l_offset >( ba.size() ), FALSE ) );
583 VSIUnlink( randomFileName.toUtf8().constData() );
587 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
591 VSIUnlink( randomFileName.toUtf8().constData() );
596 while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
598 QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
604 VSIUnlink( randomFileName.toUtf8().constData() );
612 if (
string.isEmpty() )
615 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
618 QByteArray ba =
string.toUtf8();
619 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
620 static_cast< vsi_l_offset >( ba.size() ), FALSE ) );
625 VSIUnlink( randomFileName.toUtf8().constData() );
629 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
633 VSIUnlink( randomFileName.toUtf8().constData() );
639 if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
641 fields = readOgrFields( oFeat.get(), encoding );
645 VSIUnlink( randomFileName.toUtf8().constData() );
654 for (
qgssize i = 0; stringList[i]; ++i )
656 strings.append( QString::fromUtf8( stringList[i] ) );
bool isValid() const
Returns the validity of this feature.
void CORE_EXPORT operator()(OGRFeatureH feature)
Destroys an OGR feature, using the correct gdal calls.
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.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length...
QList< QgsFeature > QgsFeatureList
static bool readOgrFeatureGeometry(OGRFeatureH ogrFet, QgsFeature &feature)
Reads the geometry from an OGR feature into a QgsFeature.
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
bool setAttribute(int field, const QVariant &attr)
Set an attribute's value by field index.
void CORE_EXPORT operator()(OGRDataSourceH source)
Destroys an OGR data source, using the correct gdal calls.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
static QgsFields readOgrFields(OGRFeatureH ogrFet, QTextCodec *encoding)
Reads an OGR feature and returns a corresponding fields collection.
#define OGR_F_IsFieldSetAndNotNull
static endian_t endian()
Returns whether this machine uses big or little endian.
int count() const
Returns number of items.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Type
The WKB type describes the number of dimensions a geometry has.
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...
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
void CORE_EXPORT operator()(GDALDatasetH datasource)
Destroys an gdal dataset, using the correct gdal calls.
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
static QgsFeature readOgrFeature(OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding)
Reads an OGR feature and converts it to a QgsFeature.
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) ...
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.
void setId(QgsFeatureId id)
Sets the feature ID for this feature.
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...
void CORE_EXPORT operator()(GDALWarpOptions *options)
Destroys GDAL warp options, using the correct gdal calls.
void setValid(bool validity)
Sets the validity of the feature.
void clearGeometry()
Removes any geometry associated with the feature.
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.
void CORE_EXPORT operator()(OGRFieldDefnH definition)
Destroys an OGR field definition, using the correct gdal calls.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
static QgsWkbTypes::Type ogrGeometryTypeToQgsWkbType(OGRwkbGeometryType ogrGeomType)
Converts a OGRwkbGeometryType to QgsWkbTypes::Type.
static Type zmType(Type type, bool hasZ, bool hasM)
Returns the modified input geometry type according to hasZ / hasM.
QVariant::Type subType() const
If the field is a collection, gets its element's type.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
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.