1 /***************************************************************************
2                qgsdatumtransform.h
3                ------------------------
4     begin                : Dec 2017
5     copyright            : (C) 2017 Nyall Dawson
6     email                : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 #ifndef QGSDATUMTRANSFORM_H
18 #define QGSDATUMTRANSFORM_H
19 
20 #include "qgis_core.h"
21 #include "qgis_sip.h"
22 #include "qgsrectangle.h"
23 #include <QString>
24 #include <QList>
25 
26 class QgsCoordinateReferenceSystem;
27 
28 #ifndef SIP_RUN
29 struct PJconsts;
30 typedef struct PJconsts PJ;
31 #endif
32 
33 /**
34  * \brief Contains methods and classes relating the datum transformations.
35  * \ingroup core
36  *
37  * \see QgsCoordinateTransformContext
38  * \see QgsCoordinateTransform
39  *
40  * \since QGIS 3.0
41  */
42 class CORE_EXPORT QgsDatumTransform
43 {
44 
45   public:
46 
47     /**
48      * Contains datum transform information.
49      * \deprecated Not used for builds based on Proj >= 6.0
50      * \since QGIS 3.0
51      */
52     struct TransformPair
53     {
54 
55       /**
56        * Constructor for a TransformPair with the specified \a sourceTransformId
57        * and \a destinationTransformId transforms.
58        */
59       TransformPair( int sourceTransformId = -1, int destinationTransformId = -1 )
sourceTransformIdTransformPair60         : sourceTransformId( sourceTransformId )
61         , destinationTransformId( destinationTransformId )
62       {}
63 
64       /**
65         * ID for the datum transform to use when projecting from the source CRS.
66         * \see QgsCoordinateTransform::datumTransformCrsInfo()
67        */
68       int sourceTransformId = -1;
69 
70       /**
71        * ID for the datum transform to use when projecting to the destination CRS.
72        * \see QgsCoordinateTransform::datumTransformCrsInfo()
73        */
74       int destinationTransformId = -1;
75 
76       // TODO c++20 - replace with = default
77       bool operator==( QgsDatumTransform::TransformPair other ) const
78       {
79         return other.sourceTransformId == sourceTransformId && other.destinationTransformId == destinationTransformId;
80       }
81 
82       bool operator!=( QgsDatumTransform::TransformPair other ) const
83       {
84         return other.sourceTransformId != sourceTransformId || other.destinationTransformId != destinationTransformId;
85       }
86 
87     };
88 
89     /**
90      * Contains datum transform information.
91      * \deprecated Not used on builds based on Proj >= 6.0
92      */
93     struct TransformInfo
94     {
95       //! Datum transform ID
96       int datumTransformId = -1;
97 
98       //! EPSG code for the transform, or 0 if not found in EPSG database
99       int epsgCode = 0;
100 
101       //! Source CRS auth ID
102       QString sourceCrsAuthId;
103 
104       //! Destination CRS auth ID
105       QString destinationCrsAuthId;
106 
107       //! Source CRS description
108       QString sourceCrsDescription;
109 
110       //! Destination CRS description
111       QString destinationCrsDescription;
112 
113       //! Transform remarks
114       QString remarks;
115 
116       //! Scope of transform
117       QString scope;
118 
119       //! True if transform is the preferred transform to use for the source/destination CRS combination
120       bool preferred = false;
121 
122       //! True if transform is deprecated
123       bool deprecated = false;
124 
125     };
126 
127 
128     /**
129      * Contains information about a projection transformation grid file.
130      * \since QGIS 3.8
131      */
132     struct GridDetails
133     {
134       //! Short name of transform grid
135       QString shortName;
136       //! Full name of transform grid
137       QString fullName;
138       //! Name of package the grid is included within
139       QString packageName;
140       //! Url to download grid from
141       QString url;
142       //! TRUE if direct download of grid is possible
143       bool directDownload = false;
144       //! TRUE if grid is available under an open license
145       bool openLicense = false;
146       //! TRUE if grid is currently available for use
147       bool isAvailable = false;
148     };
149 
150     /**
151      * Contains information about a single coordinate operation.
152      *
153      * \note Only used in builds based on on Proj >= 6.2
154      * \since QGIS 3.10
155      */
156     struct SingleOperationDetails
157     {
158       //! Scope of operation, from EPSG registry database
159       QString scope;
160 
161       //! Remarks for operation, from EPSG registry database
162       QString remarks;
163 
164       //! Area of use, from EPSG registry database
165       QString areaOfUse;
166 
167       //! Authority name, e.g. EPSG.
168       QString authority;
169 
170       //! Authority code, e.g. "8447" (for EPSG:8447).
171       QString code;
172     };
173 
174     /**
175      * Contains information about a coordinate transformation operation.
176      *
177      * \note Only used in builds based on on Proj >= 6.0
178      * \since QGIS 3.8
179      */
180     struct TransformDetails
181     {
182       //! Proj representation of transform operation
183       QString proj;
184       //! Display name of transform operation
185       QString name;
186       //! Transformation accuracy (in meters)
187       double accuracy = 0;
188 
189       /**
190        * Authority name, e.g. EPSG.
191        *
192        * This is only available for single step coordinate operations. For multi-step operations, check
193        * \a operationDetails instead.
194        */
195       QString authority;
196 
197       /**
198        * Identification code, e.g. "8447" (For EPSG:8447).
199        *
200        * This is only available for single step coordinate operations. For multi-step operations, check
201        * \a operationDetails instead.
202        */
203       QString code;
204 
205       /**
206        * Scope of operation, from EPSG registry database.
207        *
208        * This is only available for single step coordinate operations. For multi-step operations, check
209        * \a operationDetails instead.
210        */
211       QString scope;
212 
213       /**
214       * Remarks for operation, from EPSG registry database.
215       *
216       * This is only available for single step coordinate operations. For multi-step operations, check
217       * \a operationDetails instead.
218       */
219       QString remarks;
220 
221       /**
222        * TRUE if operation is available.
223        *
224        * If FALSE, it likely means a transform grid is required which is not
225        * available.
226        */
227       bool isAvailable = false;
228 
229       /**
230        * Area of use string.
231        *
232        * This is only available for single step coordinate operations. For multi-step operations, check
233        * \a operationDetails instead.
234        *
235        * \see bounds
236        */
237       QString areaOfUse;
238 
239       /**
240        * Valid bounds for the coordinate operation.
241        * \see areaOfUse
242        */
243       QgsRectangle bounds;
244 
245       /**
246        * Contains a list of transform grids used by the operation.
247        */
248       QList< QgsDatumTransform::GridDetails > grids;
249 
250       /**
251        * Contains information about the single operation steps used in the transform operation.
252        *
253        * \note Only used in builds based on on Proj >= 6.2
254        * \since QGIS 3.10
255        */
256       QList< QgsDatumTransform::SingleOperationDetails > operationDetails;
257     };
258 
259     /**
260      * Returns a list of coordinate operations available for transforming
261      * coordinates from the \a source to \a destination CRS.
262      *
263      * This list is sorted in order of preference, with the most preferable
264      * operation listed first.
265      *
266      * Not all operations may be available for use. Check QgsDatumTransform::TransformDetails::isAvailable
267      * first. Operations may require grid shift files which are not available on the local
268      * install.
269      *
270      * If \a includeSuperseded is TRUE, superseded (but not deprecated) transforms will be included
271      * in the results. This requires Proj >= 6.2.
272      *
273      * \note Requires Proj 6.0 or later. Builds based on earlier Proj versions will always return an empty list,
274      * and the deprecated API from QgsDatumTransform must be used instead.
275      *
276      * \since QGIS 3.8
277      */
278     static QList< QgsDatumTransform::TransformDetails > operations( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, bool includeSuperseded = false );
279 
280     /**
281      * Returns a list of datum transformations which are available for the given \a source and \a destination CRS.
282      * \see datumTransformToProj()
283      * \see datumTransformInfo()
284      *
285      * \deprecated Not used for builds based on Proj >= 6.0
286      */
287     Q_DECL_DEPRECATED static QList< QgsDatumTransform::TransformPair > datumTransformations( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) SIP_DEPRECATED;
288 
289     /**
290      * Returns a proj string representing the specified \a datumTransformId datum transform ID.
291      * \see datumTransformations()
292      * \see datumTransformInfo()
293      * \see projStringToDatumTransformId()
294      *
295      * \deprecated Not used for builds based on Proj >= 6.0
296      */
297     Q_DECL_DEPRECATED static QString datumTransformToProj( int datumTransformId ) SIP_DEPRECATED;
298 
299     /**
300      * Returns the datum transform ID corresponding to a specified proj \a string.
301      * Returns -1 if matching datum ID was not found.
302      * \see datumTransformToProj()
303      *
304      * \deprecated Not used for builds based on Proj >= 6.0
305      */
306     Q_DECL_DEPRECATED static int projStringToDatumTransformId( const QString &string ) SIP_DEPRECATED;
307 
308     /**
309      * Returns detailed information about the specified \a datumTransformId.
310      * If \a datumTransformId was not a valid transform ID, a TransformInfo with TransformInfo::datumTransformId of
311      * -1 will be returned.
312      * \see datumTransformations()
313      * \see datumTransformToProj()
314      *
315      * \deprecated Not used for builds based on Proj >= 6.0
316     */
317     Q_DECL_DEPRECATED static QgsDatumTransform::TransformInfo datumTransformInfo( int datumTransformId ) SIP_DEPRECATED;
318 
319 #ifndef SIP_RUN
320 
321     /**
322      * Returns the transform details for a Proj coordinate operation \a op.
323      *
324      * \note Requires Proj 6.0 or later
325      * \since QGIS 3.8
326      */
327     static QgsDatumTransform::TransformDetails transformDetailsFromPj( PJ *op );
328 #endif
329 
330   private:
331 
332     static void searchDatumTransform( const QString &sql, QList< int > &transforms );
333 
334 
335 };
336 
337 #endif // QGSDATUMTRANSFORM_H
338