Skip to content

Commit

Permalink
Add utility function to convert QgsCoordinateReferenceSystem to OGR SRS
Browse files Browse the repository at this point in the history
and include coordinate epoch for GDAL 3.4+
  • Loading branch information
nyalldawson committed Aug 8, 2021
1 parent 906b7f0 commit fbee77c
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/core/qgsogrutils.cpp
Expand Up @@ -957,7 +957,37 @@ QgsCoordinateReferenceSystem QgsOgrUtils::OGRSpatialReferenceToCrs( OGRSpatialRe
if ( wkt.isEmpty() )
return QgsCoordinateReferenceSystem();

#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
QgsCoordinateReferenceSystem res = QgsCoordinateReferenceSystem::fromWkt( wkt );
const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
if ( coordinateEpoch > 0 )
res.setCoordinateEpoch( coordinateEpoch );
return res;
#else
return QgsCoordinateReferenceSystem::fromWkt( wkt );
#endif
}

OGRSpatialReferenceH QgsOgrUtils::crsToOGRSpatialReference( const QgsCoordinateReferenceSystem &crs )
{
if ( crs.isValid() )
{
const QString srsWkt = crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED_GDAL );

if ( OGRSpatialReferenceH ogrSrs = OSRNewSpatialReference( srsWkt.toLocal8Bit().constData() ) )
{
OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
if ( !std::isnan( crs.coordinateEpoch() ) )
{
OSRSetCoordinateEpoch( ogrSrs, crs.coordinateEpoch() );
}
#endif
return ogrSrs;
}
}

return nullptr;
}

QString QgsOgrUtils::readShapefileEncoding( const QString &path )
Expand Down
9 changes: 9 additions & 0 deletions src/core/qgsogrutils.h
Expand Up @@ -294,6 +294,15 @@ class CORE_EXPORT QgsOgrUtils
*/
static QgsCoordinateReferenceSystem OGRSpatialReferenceToCrs( OGRSpatialReferenceH srs );

/**
* Returns a OGRSpatialReferenceH corresponding to the specified \a crs object.
*
* \note Caller must release the returned object with OSRRelease.
*
* \since QGIS 3.22
*/
static OGRSpatialReferenceH crsToOGRSpatialReference( const QgsCoordinateReferenceSystem &crs );

/**
* Reads the encoding of the shapefile at the specified \a path (where \a path is the
* location of the ".shp" file).
Expand Down
33 changes: 33 additions & 0 deletions tests/src/core/testqgsogrutils.cpp
Expand Up @@ -21,6 +21,8 @@
#include <ogr_api.h>
#include "cpl_conv.h"
#include "cpl_string.h"
#include <ogr_srs_api.h>
#include <gdal.h>

#include "qgsfield.h"
#include "qgsgeometry.h"
Expand Down Expand Up @@ -57,6 +59,7 @@ class TestQgsOgrUtils: public QObject
void parseStyleString_data();
void parseStyleString();
void convertStyleString();
void ogrCrsConversion();

private:

Expand Down Expand Up @@ -716,5 +719,35 @@ void TestQgsOgrUtils::convertStyleString()
QCOMPARE( qgis::down_cast<QgsSimpleMarkerSymbolLayer * >( symbol->symbolLayer( 0 ) )->strokeStyle(), Qt::NoPen );
}

void TestQgsOgrUtils::ogrCrsConversion()
{
// test conversion utilities for OGR srs objects

QgsCoordinateReferenceSystem crs1( QStringLiteral( "EPSG:3111" ) );
OGRSpatialReferenceH srs = QgsOgrUtils::crsToOGRSpatialReference( crs1 );
QVERIFY( srs );
QgsCoordinateReferenceSystem crs2( QgsOgrUtils::OGRSpatialReferenceToCrs( srs ) );
// round trip should be lossless
QCOMPARE( crs1, crs2 );
OSRRelease( srs );
srs = nullptr;

#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
QVERIFY( std::isnan( crs2.coordinateEpoch() ) );

// test conversion with a coordinate epoch, should work on GDAL 3.4+
crs1 = QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) );
crs1.setCoordinateEpoch( 2020.7 );
srs = QgsOgrUtils::crsToOGRSpatialReference( crs1 );
QVERIFY( srs );
crs2 = QgsCoordinateReferenceSystem( QgsOgrUtils::OGRSpatialReferenceToCrs( srs ) );
// round trip should be lossless
QCOMPARE( crs1, crs2 );
QCOMPARE( crs2.coordinateEpoch(), 2020.7 );
OSRRelease( srs );
srs = nullptr;
#endif
}

QGSTEST_MAIN( TestQgsOgrUtils )
#include "testqgsogrutils.moc"

0 comments on commit fbee77c

Please sign in to comment.