Skip to content

Commit 69c3deb

Browse files
committed
Nicer API for datum transforms
Instead of using QPairs of ints, use more descriptive structs, also rename a lot of datum related methods for clarity and add docs
1 parent ed0c93f commit 69c3deb

24 files changed

+512
-224
lines changed

doc/api_break.dox

+8
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,14 @@ plugins calling these methods will need to be updated.
935935
- 'theNode', 'theDoc' parameters in readXML and writeXML have been renamed to 'node' and 'document' respectively
936936
- readXML() and writeXML() have been removed.
937937
- initialize() was removed.
938+
- datumTransformations() now returns a list of QgsCoordinateTransform.TransformPair instead of a list of lists.
939+
- datumTransformString() was renamed to datumTransformToProj()
940+
- datumTransformCrsInfo() was renamed to datumTransformInfo(), and now returns a QgsCoordinateTransform.TransformInfo object.
941+
- sourceDatumTransform() was renamed to sourceDatumTransformId()
942+
- setSourceDatumTransform() was renamed to setSourceDatumTransformId()
943+
- destinationDatumTransform() was renamed to destinationDatumTransformId()
944+
- setDestinationDatumTransform() was renamed to setDestinationDatumTransformId()
945+
938946

939947
QgsCoordinateTransformCache {#qgis_api_break_3_0_QgsCoordinateTransformCache}
940948
---------------------------

python/core/conversions.sip

+124
Original file line numberDiff line numberDiff line change
@@ -1848,6 +1848,130 @@ template<int, TYPE2*>
18481848
%End
18491849
};
18501850

1851+
template <TYPE>
1852+
%MappedType QMap< QPair< QString, QString>, TYPE >
1853+
{
1854+
%TypeHeaderCode
1855+
#include <QPair>
1856+
#include <QMap>
1857+
%End
1858+
1859+
%ConvertFromTypeCode
1860+
//convert map to a python dictionary
1861+
PyObject *d;
1862+
1863+
if ( ( d = PyDict_New() ) == NULL )
1864+
return NULL;
1865+
1866+
for ( auto it = sipCpp->constBegin(); it != sipCpp->constEnd(); ++ it )
1867+
{
1868+
PyObject *keyobj;
1869+
if ( ( keyobj = PyTuple_New( 2 ) ) == NULL )
1870+
{
1871+
Py_DECREF( d );
1872+
return NULL;
1873+
}
1874+
1875+
TYPE *t = new TYPE(it.value());
1876+
PyObject *tobj = sipConvertFromNewType(t, sipType_TYPE, sipTransferObj);
1877+
if ( tobj == NULL )
1878+
{
1879+
Py_DECREF(d);
1880+
delete t;
1881+
return NULL;
1882+
}
1883+
1884+
// build key
1885+
PyObject *k1obj = sipConvertFromNewType( new QString( it.key().first ), sipType_QString, sipTransferObj );
1886+
PyTuple_SetItem( keyobj, 0, k1obj );
1887+
PyObject *k2obj = sipConvertFromNewType( new QString( it.key().second ), sipType_QString, sipTransferObj );
1888+
PyTuple_SetItem( keyobj, 1, k2obj );
1889+
1890+
if(keyobj == NULL || tobj == NULL || PyDict_SetItem(d, keyobj, tobj) < 0)
1891+
{
1892+
Py_DECREF(d);
1893+
1894+
if (keyobj)
1895+
{
1896+
Py_DECREF(keyobj);
1897+
}
1898+
1899+
if (tobj)
1900+
{
1901+
Py_DECREF(tobj);
1902+
}
1903+
return NULL;
1904+
}
1905+
1906+
Py_DECREF(keyobj);
1907+
Py_DECREF(tobj);
1908+
}
1909+
1910+
return d;
1911+
%End
1912+
1913+
%ConvertToTypeCode
1914+
Py_ssize_t i = 0;
1915+
PyObject *kobj, *tobj;
1916+
1917+
// Check the type if that is all that is required.
1918+
if (sipIsErr == NULL)
1919+
{
1920+
if (!PyDict_Check(sipPy))
1921+
return 0;
1922+
1923+
while (PyDict_Next(sipPy, &i, &kobj, &tobj))
1924+
if (!sipCanConvertToType(tobj, sipType_TYPE, SIP_NOT_NONE))
1925+
return 0;
1926+
1927+
return 1;
1928+
}
1929+
1930+
PyObject *t1obj, *t2obj;
1931+
QMap< QPair< QString, QString>, TYPE > *qm = new QMap< QPair< QString, QString>, TYPE >;
1932+
1933+
int state;
1934+
while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
1935+
{
1936+
PyObject *sipKeyFirst = PyTuple_GetItem( t1obj, 0 );
1937+
PyObject *sipKeySecond = PyTuple_GetItem( t1obj, 1 );
1938+
QString *k1 = reinterpret_cast<QString *>(sipConvertToType(sipKeyFirst, sipType_QString, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr));
1939+
if (*sipIsErr)
1940+
{
1941+
sipReleaseType(k1, sipType_QString, state);
1942+
delete qm;
1943+
return 0;
1944+
}
1945+
1946+
QString *k2 = reinterpret_cast<QString *>(sipConvertToType(sipKeySecond, sipType_QString, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr));
1947+
if (*sipIsErr)
1948+
{
1949+
sipReleaseType(k1, sipType_QString, state);
1950+
sipReleaseType(k2, sipType_QString, state);
1951+
delete qm;
1952+
return 0;
1953+
}
1954+
1955+
TYPE *t = reinterpret_cast<TYPE *>(sipConvertToType(t2obj, sipType_TYPE, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr));
1956+
if (*sipIsErr)
1957+
{
1958+
sipReleaseType(t, sipType_TYPE, state);
1959+
1960+
delete qm;
1961+
return 0;
1962+
}
1963+
1964+
qm->insert( qMakePair( *k1,*k2 ), *t );
1965+
sipReleaseType(k1, sipType_QString, state);
1966+
sipReleaseType(k2, sipType_QString, state);
1967+
sipReleaseType(t, sipType_TYPE, state);
1968+
}
1969+
1970+
*sipCppPtr = qm;
1971+
1972+
return sipGetState( sipTransferObj );
1973+
%End
1974+
};
18511975

18521976
template <TYPE>
18531977
%MappedType QVector< TYPE* >

python/core/qgscoordinatetransformcontext.sip

+9-9
Original file line numberDiff line numberDiff line change
@@ -64,31 +64,31 @@ class QgsCoordinateTransformContext
6464

6565

6666

67-
QMap< QPair< QString, QString>, QPair< int, int > > sourceDestinationDatumTransforms() const;
67+
QMap< QPair< QString, QString>, QgsCoordinateTransform::TransformPair > sourceDestinationDatumTransforms() const;
6868
%Docstring
6969
Returns the stored mapping for source to destination CRS pairs to associated datum transforms to use.
7070
The map keys will be QgsCoordinateReferenceSystems.authid()s.
7171

72-
If either the source transform or destination transform is -1, then no datum transform is
72+
If either the source transform ID or destination transform ID is -1, then no datum transform is
7373
required for transformations for that source or destination.
7474

7575
\warning This method should not be used to calculate the corresponding datum transforms
7676
to use for a coordinate transform. Instead, always use calculateDatumTransforms()
7777
to determine this.
7878

7979
.. seealso:: addSourceDestinationDatumTransform()
80-
:rtype: QMap< QPair< str, QString>, QPair< int, int > >
80+
:rtype: QMap< QPair< str, QString>, QgsCoordinateTransform.TransformPair >
8181
%End
8282

8383
bool addSourceDestinationDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs,
8484
const QgsCoordinateReferenceSystem &destinationCrs,
85-
int sourceTransform,
86-
int destinationTransform );
85+
int sourceTransformId,
86+
int destinationTransformId );
8787
%Docstring
8888
Adds a new ``sourceTransform`` and ``destinationTransform`` to use when projecting coordinates
8989
from the the specified ``sourceCrs`` to the specified ``destinationCrs``.
9090

91-
If either ``sourceTransform`` or ``destinationTransform`` is -1, then no datum transform is
91+
If either ``sourceTransformId`` or ``destinationTransformId`` is -1, then no datum transform is
9292
required for transformations for that source or destination.
9393

9494
Returns true if the new transform pair was added successfully.
@@ -122,19 +122,19 @@ class QgsCoordinateTransformContext
122122
:rtype: bool
123123
%End
124124

125-
QPair< int, int > calculateDatumTransforms( const QgsCoordinateReferenceSystem &source,
125+
QgsCoordinateTransform::TransformPair calculateDatumTransforms( const QgsCoordinateReferenceSystem &source,
126126
const QgsCoordinateReferenceSystem &destination ) const;
127127
%Docstring
128128
Returns the pair of source and destination datum transforms to use
129129
for a transform from the specified ``source`` CRS to ``destination`` CRS.
130130

131-
Returns -1 if a datum transform should not be used for the source or
131+
Returns an ID of -1 if a datum transform should not be used for the source or
132132
destination.
133133

134134
.. note::
135135

136136
source and destination are reversible.
137-
:rtype: QPair< int, int >
137+
:rtype: QgsCoordinateTransform.TransformPair
138138
%End
139139

140140
void readXml( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context );

src/3d/qgs3dmapsettings.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
8585
if ( terrainGenType == "dem" )
8686
{
8787
QgsDemTerrainGenerator *demTerrainGenerator = new QgsDemTerrainGenerator;
88-
demTerrainGenerator->setCrs( mCrs );
88+
demTerrainGenerator->setCrs( mCrs, mTransformContext );
8989
mTerrainGenerator.reset( demTerrainGenerator );
9090
}
9191
else if ( terrainGenType == "quantized-mesh" )

src/3d/qgs3dutils.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,14 @@ QgsVector3D Qgs3DUtils::worldToMapCoordinates( const QgsVector3D &worldCoords, c
294294
worldCoords.y() + origin.z() );
295295
}
296296

297-
QgsVector3D Qgs3DUtils::transformWorldCoordinates( const QgsVector3D &worldPoint1, const QgsVector3D &origin1, const QgsCoordinateReferenceSystem &crs1, const QgsVector3D &origin2, const QgsCoordinateReferenceSystem &crs2 )
297+
QgsVector3D Qgs3DUtils::transformWorldCoordinates( const QgsVector3D &worldPoint1, const QgsVector3D &origin1, const QgsCoordinateReferenceSystem &crs1, const QgsVector3D &origin2, const QgsCoordinateReferenceSystem &crs2, const QgsCoordinateTransformContext &context )
298298
{
299299
QgsVector3D mapPoint1 = worldToMapCoordinates( worldPoint1, origin1 );
300300
QgsVector3D mapPoint2 = mapPoint1;
301301
if ( crs1 != crs2 )
302302
{
303303
// reproject if necessary
304-
QgsCoordinateTransform ct( crs1, crs2 );
304+
QgsCoordinateTransform ct( crs1, crs2, context );
305305
try
306306
{
307307
QgsPointXY pt = ct.transform( QgsPointXY( mapPoint1.x(), mapPoint1.y() ) );

src/3d/qgs3dutils.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ class _3D_EXPORT Qgs3DUtils
9898
static QgsVector3D worldToMapCoordinates( const QgsVector3D &worldCoords, const QgsVector3D &origin );
9999

100100
//! Transforms a world point from (origin1, crs1) to (origin2, crs2)
101-
static QgsVector3D transformWorldCoordinates( const QgsVector3D &worldPoint1, const QgsVector3D &origin1, const QgsCoordinateReferenceSystem &crs1, const QgsVector3D &origin2, const QgsCoordinateReferenceSystem &crs2 );
101+
static QgsVector3D transformWorldCoordinates( const QgsVector3D &worldPoint1, const QgsVector3D &origin1, const QgsCoordinateReferenceSystem &crs1, const QgsVector3D &origin2, const QgsCoordinateReferenceSystem &crs2,
102+
const QgsCoordinateTransformContext &context );
102103
};
103104

104105
#endif // QGS3DUTILS_H

src/3d/terrain/qgsdemterraingenerator.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ QgsRasterLayer *QgsDemTerrainGenerator::layer() const
3535
return qobject_cast<QgsRasterLayer *>( mLayer.layer.data() );
3636
}
3737

38-
void QgsDemTerrainGenerator::setCrs( const QgsCoordinateReferenceSystem &crs )
38+
void QgsDemTerrainGenerator::setCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context )
3939
{
4040
mCrs = crs;
41+
mTransformContext = context;
4142
updateGenerator();
4243
}
4344

@@ -103,7 +104,7 @@ void QgsDemTerrainGenerator::updateGenerator()
103104
if ( dem )
104105
{
105106
QgsRectangle te = dem->extent();
106-
QgsCoordinateTransform terrainToMapTransform( dem->crs(), mCrs );
107+
QgsCoordinateTransform terrainToMapTransform( dem->crs(), mCrs, mTransformContext );
107108
te = terrainToMapTransform.transformBoundingBox( te );
108109

109110
mTerrainTilingScheme = QgsTilingScheme( te, mCrs );

src/3d/terrain/qgsdemterraingenerator.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class _3D_EXPORT QgsDemTerrainGenerator : public QgsTerrainGenerator
4646
QgsRasterLayer *layer() const;
4747

4848
//! Sets CRS of the terrain
49-
void setCrs( const QgsCoordinateReferenceSystem &crs );
49+
void setCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context );
5050

5151
//! Sets resolution of the generator (how many elevation samples on one side of a terrain tile)
5252
void setResolution( int resolution ) { mResolution = resolution; updateGenerator(); }
@@ -77,6 +77,9 @@ class _3D_EXPORT QgsDemTerrainGenerator : public QgsTerrainGenerator
7777
QgsDemHeightMapGenerator *mHeightMapGenerator = nullptr;
7878

7979
QgsCoordinateReferenceSystem mCrs;
80+
81+
QgsCoordinateTransformContext mTransformContext;
82+
8083
//! source layer for heights
8184
QgsMapLayerRef mLayer;
8285
//! how many vertices to place on one side of the tile

src/app/3d/qgs3dmapcanvasdockwidget.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ void Qgs3DMapCanvasDockWidget::configure()
119119
QgsVector3D p = Qgs3DUtils::transformWorldCoordinates(
120120
oldLookingAt,
121121
oldOrigin, oldCrs,
122-
map->origin(), map->crs() );
122+
map->origin(), map->crs(), QgsProject::instance()->transformContext() );
123123

124124
if ( p != oldLookingAt )
125125
{

src/app/3d/qgs3dmapconfigwidget.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ void Qgs3DMapConfigWidget::apply()
9090
if ( tGenNeedsUpdate )
9191
{
9292
QgsDemTerrainGenerator *demTerrainGen = new QgsDemTerrainGenerator;
93-
demTerrainGen->setCrs( mMap->crs() );
93+
demTerrainGen->setCrs( mMap->crs(), QgsProject::instance()->transformContext() );
9494
demTerrainGen->setLayer( demLayer );
9595
demTerrainGen->setResolution( spinTerrainResolution->value() );
9696
demTerrainGen->setSkirtHeight( spinTerrainSkirtHeight->value() );
@@ -111,7 +111,7 @@ void Qgs3DMapConfigWidget::apply()
111111
{
112112
// reproject terrain's extent to map CRS
113113
QgsRectangle te = mMap->terrainGenerator()->extent();
114-
QgsCoordinateTransform terrainToMapTransform( mMap->terrainGenerator()->crs(), mMap->crs() );
114+
QgsCoordinateTransform terrainToMapTransform( mMap->terrainGenerator()->crs(), mMap->crs(), QgsProject::instance() );
115115
te = terrainToMapTransform.transformBoundingBox( te );
116116

117117
QgsPointXY center = te.center();
@@ -140,7 +140,7 @@ void Qgs3DMapConfigWidget::updateMaxZoomLevel()
140140
if ( demLayer )
141141
{
142142
QgsDemTerrainGenerator *demTerrainGen = new QgsDemTerrainGenerator;
143-
demTerrainGen->setCrs( mMap->crs() );
143+
demTerrainGen->setCrs( mMap->crs(), QgsProject::instance()->transformContext() );
144144
demTerrainGen->setLayer( demLayer );
145145
demTerrainGen->setResolution( spinTerrainResolution->value() );
146146
tGen.reset( demTerrainGen );

src/app/qgsdatumtransformtablewidget.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ QVariant QgsDatumTransformTableModel::data( const QModelIndex &index, int role )
8585
QPair< QString, QString> crses = mTransformContext.sourceDestinationDatumTransforms().keys().at( index.row() );
8686
sourceCrs = crses.first;
8787
destinationCrs = crses.second;
88-
QPair< int, int> transforms = mTransformContext.sourceDestinationDatumTransforms().value( crses );
89-
sourceTransform = transforms.first;
90-
destinationTransform = transforms.second;
88+
const QgsCoordinateTransform::TransformPair transforms = mTransformContext.sourceDestinationDatumTransforms().value( crses );
89+
sourceTransform = transforms.sourceTransformId;
90+
destinationTransform = transforms.destinationTransformId;
9191
#ifdef singlesourcedest
9292
}
9393
#endif
@@ -110,7 +110,7 @@ QVariant QgsDatumTransformTableModel::data( const QModelIndex &index, int role )
110110
case SourceTransformColumn:
111111
if ( sourceTransform != -1 )
112112
{
113-
return QgsCoordinateTransform::datumTransformString( sourceTransform );
113+
return QgsCoordinateTransform::datumTransformToProj( sourceTransform );
114114
}
115115
break;
116116
case DestinationCrsColumn:
@@ -119,7 +119,7 @@ QVariant QgsDatumTransformTableModel::data( const QModelIndex &index, int role )
119119
case DestinationTransformColumn:
120120
if ( destinationTransform != -1 )
121121
{
122-
return QgsCoordinateTransform::datumTransformString( destinationTransform );
122+
return QgsCoordinateTransform::datumTransformToProj( destinationTransform );
123123
}
124124
break;
125125
default:

0 commit comments

Comments
 (0)