26 #include <cpl_error.h> 27 #include <QJsonDocument> 33 #define OGR_F_IsFieldSetAndNotNull OGR_F_IsFieldSet 40 OGR_DS_Destroy( source );
46 OGR_G_DestroyGeometry( geometry );
51 OGR_Fld_Destroy( definition );
56 OGR_F_Destroy( feature );
73 CPLPushErrorHandler( CPLQuietErrorHandler );
74 GDALDeleteDataset( driver, path.toUtf8().constData() );
86 GDALDestroyWarpOptions( options );
98 feature.
setId( OGR_F_GetFID( ogrFet ) );
101 if ( !readOgrFeatureGeometry( ogrFet, feature ) )
106 if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
121 int fieldCount = OGR_F_GetFieldCount( ogrFet );
122 for (
int i = 0; i < fieldCount; ++i )
124 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
131 QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
132 QVariant::Type varType;
133 switch ( OGR_Fld_GetType( fldDef ) )
136 if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
137 varType = QVariant::Bool;
139 varType = QVariant::Int;
142 varType = QVariant::LongLong;
145 varType = QVariant::Double;
148 varType = QVariant::Date;
151 varType = QVariant::Time;
154 varType = QVariant::DateTime;
157 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0) 158 if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
159 varType = QVariant::Map;
161 varType = QVariant::String;
165 varType = QVariant::String;
174 if ( !ogrFet || attIndex < 0 || attIndex >= fields.
count() )
181 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
188 QgsDebugMsg( QStringLiteral(
"ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
199 switch ( fields.
at( attIndex ).
type() )
201 case QVariant::String:
204 value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
206 value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
210 value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
213 value = QVariant(
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
215 case QVariant::LongLong:
216 value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
218 case QVariant::Double:
219 value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
222 case QVariant::DateTime:
225 int year, month, day, hour, minute, second, tzf;
227 OGR_F_GetFieldAsDateTime( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
228 if ( fields.
at( attIndex ).
type() == QVariant::Date )
229 value = QDate( year, month, day );
230 else if ( fields.
at( attIndex ).
type() == QVariant::Time )
231 value = QTime( hour, minute, second );
233 value = QDateTime( QDate( year, month, day ), QTime( hour, minute, second ) );
237 case QVariant::ByteArray:
240 const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
244 QByteArray ba = QByteArray::fromRawData( reinterpret_cast<const char *>( b ), size );
253 if ( fields.
at( attIndex ).
subType() == QVariant::String )
256 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
257 const int count = CSLCount( lst );
260 for (
int i = 0; i < count; i++ )
263 list << encoding->toUnicode( lst[i] );
265 list << QString::fromUtf8( lst[i] );
272 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
284 value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
286 value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
290 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
297 value = QVariant( QString() );
313 for (
int idx = 0; idx < fields.
count(); ++idx )
315 QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
329 OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
333 feature.
setGeometry( ogrGeometryToQgsGeometry( geom ) );
343 OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
344 return qgis::make_unique< QgsPoint >( wkbType, x, y, z, m );
349 std::unique_ptr< QgsMultiPoint > mp = qgis::make_unique< QgsMultiPoint >();
351 const int count = OGR_G_GetGeometryCount( geom );
352 mp->reserve( count );
353 for (
int i = 0; i < count; ++i )
365 int count = OGR_G_GetPointCount( geom );
366 QVector< double > x( count );
367 QVector< double > y( count );
369 double *pz =
nullptr;
375 double *pm =
nullptr;
382 OGR_G_GetPointsZM( geom, x.data(),
sizeof( double ), y.data(),
sizeof( double ), pz,
sizeof(
double ), pm,
sizeof( double ) );
389 std::unique_ptr< QgsMultiLineString > mp = qgis::make_unique< QgsMultiLineString >();
391 const int count = OGR_G_GetGeometryCount( geom );
392 mp->reserve( count );
393 for (
int i = 0; i < count; ++i )
403 switch ( ogrGeomType )
405 case wkbUnknown:
return QgsWkbTypes::Type::Unknown;
406 case wkbPoint:
return QgsWkbTypes::Type::Point;
407 case wkbLineString:
return QgsWkbTypes::Type::LineString;
408 case wkbPolygon:
return QgsWkbTypes::Type::Polygon;
409 case wkbMultiPoint:
return QgsWkbTypes::Type::MultiPoint;
410 case wkbMultiLineString:
return QgsWkbTypes::Type::MultiLineString;
411 case wkbMultiPolygon:
return QgsWkbTypes::Type::MultiPolygon;
412 case wkbGeometryCollection:
return QgsWkbTypes::Type::GeometryCollection;
413 case wkbCircularString:
return QgsWkbTypes::Type::CircularString;
414 case wkbCompoundCurve:
return QgsWkbTypes::Type::CompoundCurve;
415 case wkbCurvePolygon:
return QgsWkbTypes::Type::CurvePolygon;
416 case wkbMultiCurve:
return QgsWkbTypes::Type::MultiCurve;
417 case wkbMultiSurface:
return QgsWkbTypes::Type::MultiSurface;
418 case wkbCurve:
return QgsWkbTypes::Type::Unknown;
419 case wkbSurface:
return QgsWkbTypes::Type::Unknown;
420 case wkbPolyhedralSurface:
return QgsWkbTypes::Type::Unknown;
421 case wkbTIN:
return QgsWkbTypes::Type::Unknown;
422 case wkbTriangle:
return QgsWkbTypes::Type::Triangle;
424 case wkbNone:
return QgsWkbTypes::Type::NoGeometry;
425 case wkbLinearRing:
return QgsWkbTypes::Type::LineString;
427 case wkbCircularStringZ:
return QgsWkbTypes::Type::CircularStringZ;
428 case wkbCompoundCurveZ:
return QgsWkbTypes::Type::CompoundCurveZ;
429 case wkbCurvePolygonZ:
return QgsWkbTypes::Type::CurvePolygonZ;
430 case wkbMultiCurveZ:
return QgsWkbTypes::Type::MultiCurveZ;
431 case wkbMultiSurfaceZ:
return QgsWkbTypes::Type::MultiSurfaceZ;
432 case wkbCurveZ:
return QgsWkbTypes::Type::Unknown;
433 case wkbSurfaceZ:
return QgsWkbTypes::Type::Unknown;
434 case wkbPolyhedralSurfaceZ:
return QgsWkbTypes::Type::Unknown;
435 case wkbTINZ:
return QgsWkbTypes::Type::Unknown;
436 case wkbTriangleZ:
return QgsWkbTypes::Type::TriangleZ;
438 case wkbPointM:
return QgsWkbTypes::Type::PointM;
439 case wkbLineStringM:
return QgsWkbTypes::Type::LineStringM;
440 case wkbPolygonM:
return QgsWkbTypes::Type::PolygonM;
441 case wkbMultiPointM:
return QgsWkbTypes::Type::MultiPointM;
442 case wkbMultiLineStringM:
return QgsWkbTypes::Type::MultiLineStringM;
443 case wkbMultiPolygonM:
return QgsWkbTypes::Type::MultiPolygonM;
444 case wkbGeometryCollectionM:
return QgsWkbTypes::Type::GeometryCollectionM;
445 case wkbCircularStringM:
return QgsWkbTypes::Type::CircularStringM;
446 case wkbCompoundCurveM:
return QgsWkbTypes::Type::CompoundCurveM;
447 case wkbCurvePolygonM:
return QgsWkbTypes::Type::CurvePolygonM;
448 case wkbMultiCurveM:
return QgsWkbTypes::Type::MultiCurveM;
449 case wkbMultiSurfaceM:
return QgsWkbTypes::Type::MultiSurfaceM;
450 case wkbCurveM:
return QgsWkbTypes::Type::Unknown;
451 case wkbSurfaceM:
return QgsWkbTypes::Type::Unknown;
452 case wkbPolyhedralSurfaceM:
return QgsWkbTypes::Type::Unknown;
453 case wkbTINM:
return QgsWkbTypes::Type::Unknown;
454 case wkbTriangleM:
return QgsWkbTypes::Type::TriangleM;
456 case wkbPointZM:
return QgsWkbTypes::Type::PointZM;
457 case wkbLineStringZM:
return QgsWkbTypes::Type::LineStringZM;
458 case wkbPolygonZM:
return QgsWkbTypes::Type::PolygonZM;
459 case wkbMultiPointZM:
return QgsWkbTypes::Type::MultiPointZM;
460 case wkbMultiLineStringZM:
return QgsWkbTypes::Type::MultiLineStringZM;
461 case wkbMultiPolygonZM:
return QgsWkbTypes::Type::MultiPolygonZM;
462 case wkbGeometryCollectionZM:
return QgsWkbTypes::Type::GeometryCollectionZM;
463 case wkbCircularStringZM:
return QgsWkbTypes::Type::CircularStringZM;
464 case wkbCompoundCurveZM:
return QgsWkbTypes::Type::CompoundCurveZM;
465 case wkbCurvePolygonZM:
return QgsWkbTypes::Type::CurvePolygonZM;
466 case wkbMultiCurveZM:
return QgsWkbTypes::Type::MultiCurveZM;
467 case wkbMultiSurfaceZM:
return QgsWkbTypes::Type::MultiSurfaceZM;
468 case wkbCurveZM:
return QgsWkbTypes::Type::Unknown;
469 case wkbSurfaceZM:
return QgsWkbTypes::Type::Unknown;
470 case wkbPolyhedralSurfaceZM:
return QgsWkbTypes::Type::Unknown;
471 case wkbTINZM:
return QgsWkbTypes::Type::Unknown;
472 case wkbTriangleZM:
return QgsWkbTypes::Type::TriangleZM;
474 case wkbPoint25D:
return QgsWkbTypes::Type::PointZ;
475 case wkbLineString25D:
return QgsWkbTypes::Type::LineStringZ;
476 case wkbPolygon25D:
return QgsWkbTypes::Type::PolygonZ;
477 case wkbMultiPoint25D:
return QgsWkbTypes::Type::MultiPointZ;
478 case wkbMultiLineString25D:
return QgsWkbTypes::Type::MultiLineStringZ;
479 case wkbMultiPolygon25D:
return QgsWkbTypes::Type::MultiPolygonZ;
480 case wkbGeometryCollection25D:
return QgsWkbTypes::Type::GeometryCollectionZ;
484 return QgsWkbTypes::Type::Unknown;
492 const auto ogrGeomType = OGR_G_GetGeometryType( geom );
527 if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
530 if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
531 wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
533 auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
534 auto ret = ogrGeometryToQgsGeometry( newGeom );
535 OGR_G_DestroyGeometry( newGeom );
541 int memorySize = OGR_G_WkbSize( geom );
542 unsigned char *wkb =
new unsigned char[memorySize];
546 uint32_t origGeomType;
547 memcpy( &origGeomType, wkb + 1,
sizeof( uint32_t ) );
548 bool hasZ = ( origGeomType >= 1000 && origGeomType < 2000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
549 bool hasM = ( origGeomType >= 2000 && origGeomType < 3000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
552 if ( origGeomType % 1000 == 16 )
555 int nDims = 2 + hasZ + hasM;
558 unsigned char *wkbptr = wkb;
564 memcpy( wkbptr, &newMultiType,
sizeof( uint32_t ) );
569 memcpy( &numGeoms, wkb + 5,
sizeof( uint32_t ) );
573 for ( uint32_t i = 0; i < numGeoms; ++i )
579 memcpy( wkbptr, &newSingleType,
sizeof( uint32_t ) );
580 wkbptr +=
sizeof( uint32_t );
584 memcpy( &nRings, wkbptr,
sizeof( uint32_t ) );
585 wkbptr +=
sizeof( uint32_t );
587 for ( uint32_t j = 0; j < nRings; ++j )
590 memcpy( &nPoints, wkbptr,
sizeof( uint32_t ) );
591 wkbptr +=
sizeof( uint32_t ) +
sizeof(
double ) * nDims * nPoints;
595 else if ( origGeomType % 1000 == 15 )
600 memcpy( wkb + 1, &newType,
sizeof( uint32_t ) );
611 if (
string.isEmpty() )
614 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
617 QByteArray ba =
string.toUtf8();
618 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
619 static_cast< vsi_l_offset >( ba.size() ), FALSE ) );
624 VSIUnlink( randomFileName.toUtf8().constData() );
628 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
632 VSIUnlink( randomFileName.toUtf8().constData() );
637 while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
639 QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
645 VSIUnlink( randomFileName.toUtf8().constData() );
653 if (
string.isEmpty() )
656 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
659 QByteArray ba =
string.toUtf8();
660 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
661 static_cast< vsi_l_offset >( ba.size() ), FALSE ) );
666 VSIUnlink( randomFileName.toUtf8().constData() );
670 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
674 VSIUnlink( randomFileName.toUtf8().constData() );
680 if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
682 fields = readOgrFields( oFeat.get(), encoding );
686 VSIUnlink( randomFileName.toUtf8().constData() );
695 for (
qgssize i = 0; stringList[i]; ++i )
697 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.
std::unique_ptr< QgsMultiLineString > ogrGeometryToQgsMultiLineString(OGRGeometryH geom)
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.
std::unique_ptr< QgsMultiPoint > ogrGeometryToQgsMultiPoint(OGRGeometryH geom)
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.