When exporting CRS information from GDAL >= 3.0, use WKT2 format

to avoid loss of CRS information
This commit is contained in:
Nyall Dawson 2019-11-27 17:08:22 +10:00
parent 6ca436d1fd
commit f3eab35cde
6 changed files with 76 additions and 20 deletions

View File

@ -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" ) )
{

View File

@ -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();

View File

@ -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
{

View File

@ -38,6 +38,7 @@
#include "qgis.h" //const vals declared here
#include "qgslocalec.h"
#include "qgssettings.h"
#include "qgsogrutils.h"
#include <sqlite3.h>
#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 );

View File

@ -26,6 +26,8 @@
#include <cpl_error.h>
#include <QJsonDocument>
#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 );
}

View File

@ -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