diff --git a/src/core/providers/gdal/qgsgdalprovider.cpp b/src/core/providers/gdal/qgsgdalprovider.cpp index 35fd53e1178..750867a8a7d 100644 --- a/src/core/providers/gdal/qgsgdalprovider.cpp +++ b/src/core/providers/gdal/qgsgdalprovider.cpp @@ -293,6 +293,7 @@ QgsGdalProvider *QgsGdalProvider::clone() const return new QgsGdalProvider( *this ); } +#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,0,0) bool QgsGdalProvider::crsFromWkt( const char *wkt ) { @@ -330,6 +331,7 @@ bool QgsGdalProvider::crsFromWkt( const char *wkt ) return mCrs.isValid(); } +#endif bool QgsGdalProvider::getCachedGdalHandles( QgsGdalProvider *provider, GDALDatasetH &gdalBaseDataset, @@ -2716,10 +2718,30 @@ void QgsGdalProvider::initBaseDataset() // Get the layer's projection info and set up the // QgsCoordinateTransform for this layer // NOTE: we must do this before metadata is called - +#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,0,0) + QString crsWkt; + if ( OGRSpatialReferenceH spatialRefSys = GDALGetSpatialRef( mGdalDataset ) ) + { + crsWkt = QgsOgrUtils::OGRSpatialReferenceToWkt( spatialRefSys ); + } + if ( crsWkt.isEmpty() ) + { + if ( OGRSpatialReferenceH spatialRefSys = GDALGetGCPSpatialRef( mGdalDataset ) ) + { + crsWkt = QgsOgrUtils::OGRSpatialReferenceToWkt( spatialRefSys ); + } + } + if ( !crsWkt.isEmpty() ) + { + mCrs = QgsCoordinateReferenceSystem::fromWkt( crsWkt ); + } + else + { +#else if ( !crsFromWkt( GDALGetProjectionRef( mGdalDataset ) ) && !crsFromWkt( GDALGetGCPProjection( mGdalDataset ) ) ) { +#endif if ( mGdalBaseDataset != mGdalDataset && GDALGetMetadata( mGdalBaseDataset, "RPC" ) ) { diff --git a/src/core/providers/gdal/qgsgdalprovider.h b/src/core/providers/gdal/qgsgdalprovider.h index 8dad9371998..37df170080f 100644 --- a/src/core/providers/gdal/qgsgdalprovider.h +++ b/src/core/providers/gdal/qgsgdalprovider.h @@ -239,8 +239,10 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase // update mode bool mUpdate; +#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,0,0) // initialize CRS from wkt bool crsFromWkt( const char *wkt ); +#endif //! Do some initialization on the dataset (e.g. handling of south-up datasets) void initBaseDataset(); diff --git a/src/core/providers/ogr/qgsogrprovider.cpp b/src/core/providers/ogr/qgsogrprovider.cpp index b12c63b4ddf..f6102408196 100644 --- a/src/core/providers/ogr/qgsogrprovider.cpp +++ b/src/core/providers/ogr/qgsogrprovider.cpp @@ -3698,20 +3698,9 @@ QgsCoordinateReferenceSystem QgsOgrProvider::crs() const // add towgs84 parameter QgsCoordinateReferenceSystem::setupESRIWktFix(); - OGRSpatialReferenceH mySpatialRefSys = mOgrLayer->GetSpatialRef(); - if ( mySpatialRefSys ) + if ( OGRSpatialReferenceH spatialRefSys = mOgrLayer->GetSpatialRef() ) { - // get the proj4 text - char *pszProj4 = nullptr; - OSRExportToProj4( mySpatialRefSys, &pszProj4 ); - QgsDebugMsgLevel( pszProj4, 4 ); - CPLFree( pszProj4 ); - - char *pszWkt = nullptr; - OSRExportToWkt( mySpatialRefSys, &pszWkt ); - - srs = QgsCoordinateReferenceSystem::fromWkt( pszWkt ); - CPLFree( pszWkt ); + srs = QgsOgrUtils::OGRSpatialReferenceToCrs( spatialRefSys ); } else { diff --git a/src/core/qgscoordinatereferencesystem.cpp b/src/core/qgscoordinatereferencesystem.cpp index 8157146578c..81f90c99f8a 100644 --- a/src/core/qgscoordinatereferencesystem.cpp +++ b/src/core/qgscoordinatereferencesystem.cpp @@ -38,6 +38,7 @@ #include "qgis.h" //const vals declared here #include "qgslocalec.h" #include "qgssettings.h" +#include "qgsogrutils.h" #include #if PROJ_VERSION_MAJOR>=6 @@ -335,7 +336,6 @@ bool QgsCoordinateReferenceSystem::createFromString( const QString &definition ) bool QgsCoordinateReferenceSystem::createFromUserInput( const QString &definition ) { QString userWkt; - char *wkt = nullptr; OGRSpatialReferenceH crs = OSRNewSpatialReference( nullptr ); // make sure towgs84 parameter is loaded if using an ESRI definition and gdal >= 1.9 @@ -346,11 +346,7 @@ bool QgsCoordinateReferenceSystem::createFromUserInput( const QString &definitio if ( OSRSetFromUserInput( crs, definition.toLocal8Bit().constData() ) == OGRERR_NONE ) { - if ( OSRExportToWkt( crs, &wkt ) == OGRERR_NONE ) - { - userWkt = wkt; - CPLFree( wkt ); - } + userWkt = QgsOgrUtils::OGRSpatialReferenceToWkt( crs ); OSRDestroySpatialReference( crs ); } //QgsDebugMsg( "definition: " + definition + " wkt = " + wkt ); diff --git a/src/core/qgsogrutils.cpp b/src/core/qgsogrutils.cpp index 92f0f0a0f34..ffd2b01642d 100644 --- a/src/core/qgsogrutils.cpp +++ b/src/core/qgsogrutils.cpp @@ -26,6 +26,8 @@ #include #include +#include "ogr_srs_api.h" + // Starting with GDAL 2.2, there are 2 concepts: unset fields and null fields // whereas previously there was only unset fields. For QGIS purposes, both // states (unset/null) are equivalent. @@ -714,3 +716,31 @@ QStringList QgsOgrUtils::cStringListToQStringList( char **stringList ) return strings; } +QString QgsOgrUtils::OGRSpatialReferenceToWkt( OGRSpatialReferenceH srs ) +{ + if ( !srs ) + return QString(); + + char *pszWkt = nullptr; +#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,0,0) + const QByteArray multiLineOption = QStringLiteral( "MULTILINE=NO" ).toLocal8Bit(); + const QByteArray formatOption = QStringLiteral( "FORMAT=WKT2" ).toLocal8Bit(); + const char *const options[] = {multiLineOption.constData(), formatOption.constData(), nullptr}; + OSRExportToWktEx( srs, &pszWkt, options ); +#else + OSRExportToWkt( srs, &pszWkt ); +#endif + + const QString res( pszWkt ); + CPLFree( pszWkt ); + return res; +} + +QgsCoordinateReferenceSystem QgsOgrUtils::OGRSpatialReferenceToCrs( OGRSpatialReferenceH srs ) +{ + const QString wkt = OGRSpatialReferenceToWkt( srs ); + if ( wkt.isEmpty() ) + return QgsCoordinateReferenceSystem(); + + return QgsCoordinateReferenceSystem::fromWkt( wkt ); +} diff --git a/src/core/qgsogrutils.h b/src/core/qgsogrutils.h index a1bb48ce7b1..5e333a29e48 100644 --- a/src/core/qgsogrutils.h +++ b/src/core/qgsogrutils.h @@ -268,6 +268,23 @@ class CORE_EXPORT QgsOgrUtils * \since QGIS 3.4.9 */ static QgsWkbTypes::Type ogrGeometryTypeToQgsWkbType( OGRwkbGeometryType ogrGeomType ); + + /** + * Returns a WKT string corresponding to the specified OGR \a srs object. + * + * The WKT string format will be selected using the most appropriate format (usually WKT2 if GDAL 3 is available). + * + * \since QGIS 3.10.1 + */ + static QString OGRSpatialReferenceToWkt( OGRSpatialReferenceH srs ); + + /** + * Returns a QgsCoordinateReferenceSystem corresponding to the specified OGR \a srs object, or an invalid + * QgsCoordinateReferenceSystem if \a srs could not be converted. + * + * \since QGIS 3.10.1 + */ + static QgsCoordinateReferenceSystem OGRSpatialReferenceToCrs( OGRSpatialReferenceH srs ); }; #endif // QGSOGRUTILS_H