Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
When exporting CRS information from GDAL >= 3.0, use WKT2 format
to avoid loss of CRS information
  • Loading branch information
nyalldawson committed Nov 28, 2019
1 parent 6ca436d commit f3eab35
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 20 deletions.
24 changes: 23 additions & 1 deletion src/core/providers/gdal/qgsgdalprovider.cpp
Expand Up @@ -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 )
{

Expand Down Expand Up @@ -330,6 +331,7 @@ bool QgsGdalProvider::crsFromWkt( const char *wkt )

return mCrs.isValid();
}
#endif

bool QgsGdalProvider::getCachedGdalHandles( QgsGdalProvider *provider,
GDALDatasetH &gdalBaseDataset,
Expand Down Expand Up @@ -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" ) )
{
Expand Down
2 changes: 2 additions & 0 deletions src/core/providers/gdal/qgsgdalprovider.h
Expand Up @@ -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();
Expand Down
15 changes: 2 additions & 13 deletions src/core/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -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
{
Expand Down
8 changes: 2 additions & 6 deletions src/core/qgscoordinatereferencesystem.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 );
Expand Down
30 changes: 30 additions & 0 deletions src/core/qgsogrutils.cpp
Expand Up @@ -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.
Expand Down Expand Up @@ -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 );
}
17 changes: 17 additions & 0 deletions src/core/qgsogrutils.h
Expand Up @@ -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

0 comments on commit f3eab35

Please sign in to comment.