Skip to content

Commit

Permalink
[api] Add methods for retrieving datum ensemble details for a
Browse files Browse the repository at this point in the history
QgsCoordinateReferenceSystem

Requires proj >= 8.0
  • Loading branch information
nyalldawson committed May 7, 2021
1 parent a4e4997 commit e9cf180
Show file tree
Hide file tree
Showing 10 changed files with 477 additions and 2 deletions.
17 changes: 17 additions & 0 deletions python/core/auto_generated/qgscoordinatereferencesystem.sip.in
Expand Up @@ -791,6 +791,23 @@ overridden with these.
Returns whether the CRS is a geographic CRS (using lat/lon coordinates)

:return: ``True`` if CRS is geographic, or ``False`` if it is a projected CRS
%End

QgsDatumEnsemble datumEnsemble() const throw( QgsNotSupportedException );
%Docstring
Attempts to retrieve datum ensemble details from the CRS.

If the CRS does not use a datum ensemble then an invalid :py:class:`QgsDatumEnsemble` will
be returned.

.. warning::

This method requires PROJ 8.0 or later

:raises :: py:class:`QgsNotSupportedException` on QGIS builds based on PROJ 7 or earlier.


.. versionadded:: 3.20
%End

bool hasAxisInverted() const;
Expand Down
152 changes: 152 additions & 0 deletions python/core/auto_generated/qgsdatums.sip.in
@@ -0,0 +1,152 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsdatums.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsDatumEnsembleMember
{
%Docstring(signature="appended")
Contains information about a member of a datum ensemble.

.. note::

Only used in builds based on on PROJ 7.2 or later

.. versionadded:: 3.20
%End

%TypeHeaderCode
#include "qgsdatums.h"
%End
public:

QString name() const;
%Docstring
Returns the name of the member.
%End

QString scope() const;
%Docstring
Returns the scope of operation, from EPSG registry database.
%End

QString remarks() const;
%Docstring
Remarks for operation, from EPSG registry database.
%End

QString authority() const;
%Docstring
Authority name, e.g. EPSG.
%End

QString code() const;
%Docstring
Authority code, e.g. "8447" (for EPSG:8447).
%End

SIP_PYOBJECT __repr__();
%MethodCode
QString id;
if ( !sipCpp->code().isEmpty() )
id = QStringLiteral( "%1 (%2:%3)" ).arg( sipCpp->name(), sipCpp->authority(), sipCpp->code() );
else
id = sipCpp->name();
QString str = QStringLiteral( "<QgsDatumEnsembleMember: %1>" ).arg( id );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
%End

};

class QgsDatumEnsemble
{
%Docstring(signature="appended")
Contains information about a datum ensemble.

.. note::

Only used in builds based on on PROJ 7.2 or later

.. versionadded:: 3.20
%End

%TypeHeaderCode
#include "qgsdatums.h"
%End
public:

bool isValid() const;
%Docstring
Returns ``True`` if the datum ensemble is a valid object, or ``False`` if it is a null/invalid
object.
%End

QString name() const;
%Docstring
Display name of datum ensemble.
%End

double accuracy() const;
%Docstring
Positional accuracy (in meters).
%End

QString authority() const;
%Docstring
Authority name, e.g. EPSG.
%End

QString code() const;
%Docstring
Identification code, e.g. "8447" (For EPSG:8447).
%End

QString scope() const;
%Docstring
Scope of ensemble, from EPSG registry database.
%End

QString remarks() const;
%Docstring
Remarks for ensemble, from EPSG registry database.
%End

QList< QgsDatumEnsembleMember > members() const;
%Docstring
Contains a list of members of the ensemble.
%End

SIP_PYOBJECT __repr__();
%MethodCode
QString str;
if ( !sipCpp->isValid() )
{
str = QStringLiteral( "<QgsDatumEnsemble: invalid>" );
}
else
{
QString id;
if ( !sipCpp->code().isEmpty() )
id = QStringLiteral( "%1 (%2:%3)" ).arg( sipCpp->name(), sipCpp->authority(), sipCpp->code() );
else
id = sipCpp->name();
str = QStringLiteral( "<QgsDatumEnsemble: %1>" ).arg( id );
}
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsdatums.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Expand Up @@ -46,6 +46,7 @@
%Include auto_generated/qgsdataprovidertemporalcapabilities.sip
%Include auto_generated/qgsdatasourceuri.sip
%Include auto_generated/qgsdatetimestatisticalsummary.sip
%Include auto_generated/qgsdatums.sip
%Include auto_generated/qgsdatumtransform.sip
%Include auto_generated/qgsdbfilterproxymodel.sip
%Include auto_generated/qgsdefaultvalue.sip
Expand Down
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -897,6 +897,7 @@ set(QGIS_CORE_HDRS
qgsdataprovidertemporalcapabilities.h
qgsdatasourceuri.h
qgsdatetimestatisticalsummary.h
qgsdatums.h
qgsdatumtransform.h
qgsdbfilterproxymodel.h
qgsdefaultvalue.h
Expand Down
47 changes: 47 additions & 0 deletions src/core/qgscoordinatereferencesystem.cpp
Expand Up @@ -40,6 +40,7 @@
#include "qgslocalec.h"
#include "qgssettings.h"
#include "qgsogrutils.h"
#include "qgsdatums.h"

#include <sqlite3.h>
#include "qgsprojutils.h"
Expand Down Expand Up @@ -1195,6 +1196,52 @@ bool QgsCoordinateReferenceSystem::isGeographic() const
return d->mIsGeographic;
}

QgsDatumEnsemble QgsCoordinateReferenceSystem::datumEnsemble() const
{
QgsDatumEnsemble res;
res.mValid = false;

const PJ *pj = projObject();
if ( !pj )
return res;

#if PROJ_VERSION_MAJOR>=8
PJ_CONTEXT *context = QgsProjContext::get();

QgsProjUtils::proj_pj_unique_ptr ensemble = QgsProjUtils::crsToDatumEnsemble( pj );
if ( !ensemble )
return res;

res.mValid = true;
res.mName = QString( proj_get_name( ensemble.get() ) );
res.mAuthority = QString( proj_get_id_auth_name( ensemble.get(), 0 ) );
res.mCode = QString( proj_get_id_code( ensemble.get(), 0 ) );
res.mRemarks = QString( proj_get_remarks( ensemble.get() ) );
res.mScope = QString( proj_get_scope( ensemble.get() ) );
res.mAccuracy = proj_datum_ensemble_get_accuracy( context, ensemble.get() );

const int memberCount = proj_datum_ensemble_get_member_count( context, ensemble.get() );
for ( int i = 0; i < memberCount; ++i )
{
QgsProjUtils::proj_pj_unique_ptr member( proj_datum_ensemble_get_member( context, ensemble.get(), i ) );
if ( !member )
continue;

QgsDatumEnsembleMember details;
details.mName = QString( proj_get_name( member.get() ) );
details.mAuthority = QString( proj_get_id_auth_name( member.get(), 0 ) );
details.mCode = QString( proj_get_id_code( member.get(), 0 ) );
details.mRemarks = QString( proj_get_remarks( member.get() ) );
details.mScope = QString( proj_get_scope( member.get() ) );

res.mMembers << details;
}
return res;
#else
throw QgsNotSupportedException( QStringLiteral( "Calculating datum ensembles requires a QGIS build based on PROJ 8.0 or later" ) );
#endif
}

QgsUnitTypes::DistanceUnit QgsCoordinateReferenceSystem::mapUnits() const
{
if ( !d->mIsValid )
Expand Down
15 changes: 15 additions & 0 deletions src/core/qgscoordinatereferencesystem.h
Expand Up @@ -39,6 +39,7 @@
class QDomNode;
class QDomDocument;
class QgsCoordinateReferenceSystemPrivate;
class QgsDatumEnsemble;

#ifndef SIP_RUN
struct PJconsts;
Expand Down Expand Up @@ -730,6 +731,20 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
*/
bool isGeographic() const;

/**
* Attempts to retrieve datum ensemble details from the CRS.
*
* If the CRS does not use a datum ensemble then an invalid QgsDatumEnsemble will
* be returned.
*
* \warning This method requires PROJ 8.0 or later
*
* \throws QgsNotSupportedException on QGIS builds based on PROJ 7 or earlier.
*
* \since QGIS 3.20
*/
QgsDatumEnsemble datumEnsemble() const SIP_THROW( QgsNotSupportedException );

/**
* Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS.
* \returns TRUE if CRS axis is inverted
Expand Down

0 comments on commit e9cf180

Please sign in to comment.