1 /******************************************************************************
2  *
3  * Project:  PROJ
4  * Purpose:  ISO19111:2019 implementation
5  * Author:   Even Rouault <even dot rouault at spatialys dot com>
6  *
7  ******************************************************************************
8  * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #ifndef COORDINATEOPERATION_HH_INCLUDED
30 #define COORDINATEOPERATION_HH_INCLUDED
31 
32 #include <memory>
33 #include <string>
34 #include <utility>
35 #include <vector>
36 
37 #include "common.hpp"
38 #include "io.hpp"
39 #include "metadata.hpp"
40 
41 NS_PROJ_START
42 
43 namespace crs {
44 class CRS;
45 using CRSPtr = std::shared_ptr<CRS>;
46 using CRSNNPtr = util::nn<CRSPtr>;
47 
48 class DerivedCRS;
49 class ProjectedCRS;
50 } // namespace crs
51 
52 /** osgeo.proj.operation namespace
53 
54   \brief Coordinate operations (relationship between any two coordinate
55   reference systems).
56 
57   This covers Conversion, Transformation,
58   PointMotionOperation or ConcatenatedOperation.
59 */
60 namespace operation {
61 
62 // ---------------------------------------------------------------------------
63 
64 /** \brief Grid description */
65 struct GridDescription {
66     std::string shortName;   /**< Grid short filename */
67     std::string fullName;    /**< Grid full path name (if found) */
68     std::string packageName; /**< Package name (or empty) */
69     std::string url;         /**< Grid URL (if packageName is empty), or package
70                                     URL (or empty) */
71     bool directDownload;     /**< Whether url can be fetched directly. */
72     /** Whether the grid is released with an open license. */
73     bool openLicense;
74     bool available; /**< Whether GRID is available. */
75 
76     //! @cond Doxygen_Suppress
operator <operation::GridDescription77     bool operator<(const GridDescription &other) const {
78         return shortName < other.shortName;
79     }
80 
81     PROJ_DLL GridDescription();
82     PROJ_DLL ~GridDescription();
83     PROJ_DLL GridDescription(const GridDescription &);
84     PROJ_DLL GridDescription(GridDescription &&) noexcept;
85     //! @endcond
86 };
87 
88 // ---------------------------------------------------------------------------
89 
90 class CoordinateOperation;
91 /** Shared pointer of CoordinateOperation */
92 using CoordinateOperationPtr = std::shared_ptr<CoordinateOperation>;
93 /** Non-null shared pointer of CoordinateOperation */
94 using CoordinateOperationNNPtr = util::nn<CoordinateOperationPtr>;
95 
96 /** \brief Abstract class for a mathematical operation on coordinates.
97  *
98  * A mathematical operation:
99  * <ul>
100  * <li>on coordinates that transforms or converts them from one coordinate
101  * reference system to another coordinate reference system</li>
102  * <li>or that describes the change of coordinate values within one coordinate
103  * reference system due to the motion of the point between one coordinate epoch
104  * and another coordinate epoch.</li>
105  * </ul>
106  * Many but not all coordinate operations (from CRS A to CRS B) also uniquely
107  * define the inverse coordinate operation (from CRS B to CRS A). In some cases,
108  * the coordinate operation method algorithm for the inverse coordinate
109  * operation is the same as for the forward algorithm, but the signs of some
110  * coordinate operation parameter values have to be reversed. In other cases,
111  * different algorithms are required for the forward and inverse coordinate
112  * operations, but the same coordinate operation parameter values are used. If
113  * (some) entirely different parameter values are needed, a different coordinate
114  * operation shall be defined.
115  *
116  * \remark Implements CoordinateOperation from \ref ISO_19111_2019
117  */
118 class PROJ_GCC_DLL CoordinateOperation : public common::ObjectUsage,
119                                          public io::IPROJStringExportable,
120                                          public io::IJSONExportable {
121   public:
122     //! @cond Doxygen_Suppress
123     PROJ_DLL ~CoordinateOperation() override;
124     //! @endcond
125 
126     PROJ_DLL const util::optional<std::string> &operationVersion() const;
127     PROJ_DLL const std::vector<metadata::PositionalAccuracyNNPtr> &
128     coordinateOperationAccuracies() const;
129 
130     PROJ_DLL const crs::CRSPtr sourceCRS() const;
131     PROJ_DLL const crs::CRSPtr targetCRS() const;
132     PROJ_DLL const crs::CRSPtr &interpolationCRS() const;
133     PROJ_DLL const util::optional<common::DataEpoch> &
134     sourceCoordinateEpoch() const;
135     PROJ_DLL const util::optional<common::DataEpoch> &
136     targetCoordinateEpoch() const;
137 
138     // virtual void transform(...) = 0;  TODO
139 
140     /** \brief Return the inverse of the coordinate operation.
141      * @throw util::UnsupportedOperationException
142      */
143     PROJ_DLL virtual CoordinateOperationNNPtr inverse() const = 0;
144 
145     /** \brief Return grids needed by an operation. */
146     PROJ_DLL virtual std::set<GridDescription>
147     gridsNeeded(const io::DatabaseContextPtr &databaseContext,
148                 bool considerKnownGridsAsAvailable) const = 0;
149 
150     PROJ_DLL bool
151     isPROJInstantiable(const io::DatabaseContextPtr &databaseContext,
152                        bool considerKnownGridsAsAvailable) const;
153 
154     PROJ_DLL bool hasBallparkTransformation() const;
155 
156     PROJ_DLL static const std::string OPERATION_VERSION_KEY;
157 
158     PROJ_DLL CoordinateOperationNNPtr normalizeForVisualization() const;
159 
160     PROJ_PRIVATE :
161         //! @cond Doxygen_Suppress
162         PROJ_FOR_TEST CoordinateOperationNNPtr
163         shallowClone() const;
164     //! @endcond
165 
166   protected:
167     PROJ_INTERNAL CoordinateOperation();
168     PROJ_INTERNAL CoordinateOperation(const CoordinateOperation &other);
169 
170     PROJ_FRIEND(crs::DerivedCRS);
171     PROJ_FRIEND(io::AuthorityFactory);
172     PROJ_FRIEND(CoordinateOperationFactory);
173     PROJ_FRIEND(ConcatenatedOperation);
174     PROJ_INTERNAL void
175     setWeakSourceTargetCRS(std::weak_ptr<crs::CRS> sourceCRSIn,
176                            std::weak_ptr<crs::CRS> targetCRSIn);
177     PROJ_INTERNAL void setCRSs(const crs::CRSNNPtr &sourceCRSIn,
178                                const crs::CRSNNPtr &targetCRSIn,
179                                const crs::CRSPtr &interpolationCRSIn);
180     PROJ_INTERNAL void setCRSs(const CoordinateOperation *in,
181                                bool inverseSourceTarget);
182     PROJ_INTERNAL
183     void setAccuracies(
184         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
185     PROJ_INTERNAL void setHasBallparkTransformation(bool b);
186 
187     PROJ_INTERNAL void
188     setProperties(const util::PropertyMap
189                       &properties); // throw(InvalidValueTypeException)
190 
191     PROJ_INTERNAL virtual CoordinateOperationNNPtr _shallowClone() const = 0;
192 
193   private:
194     PROJ_OPAQUE_PRIVATE_DATA
195     CoordinateOperation &operator=(const CoordinateOperation &other) = delete;
196 };
197 
198 // ---------------------------------------------------------------------------
199 
200 /** \brief Abstract class modelling a parameter value (OperationParameter)
201  * or group of parameters.
202  *
203  * \remark Implements GeneralOperationParameter from \ref ISO_19111_2019
204  */
205 class PROJ_GCC_DLL GeneralOperationParameter : public common::IdentifiedObject {
206   public:
207     //! @cond Doxygen_Suppress
208     PROJ_DLL ~GeneralOperationParameter() override;
209     //! @endcond
210 
211     //! @cond Doxygen_Suppress
212     PROJ_INTERNAL bool _isEquivalentTo(
213         const util::IComparable *other,
214         util::IComparable::Criterion criterion =
215             util::IComparable::Criterion::STRICT,
216         const io::DatabaseContextPtr &dbContext = nullptr) const override = 0;
217     //! @endcond
218 
219   protected:
220     PROJ_INTERNAL GeneralOperationParameter();
221     PROJ_INTERNAL
222     GeneralOperationParameter(const GeneralOperationParameter &other);
223 
224   private:
225     PROJ_OPAQUE_PRIVATE_DATA
226     GeneralOperationParameter &
227     operator=(const GeneralOperationParameter &other) = delete;
228 };
229 
230 /** Shared pointer of GeneralOperationParameter */
231 using GeneralOperationParameterPtr = std::shared_ptr<GeneralOperationParameter>;
232 /** Non-null shared pointer of GeneralOperationParameter */
233 using GeneralOperationParameterNNPtr = util::nn<GeneralOperationParameterPtr>;
234 
235 // ---------------------------------------------------------------------------
236 
237 class OperationParameter;
238 /** Shared pointer of OperationParameter */
239 using OperationParameterPtr = std::shared_ptr<OperationParameter>;
240 /** Non-null shared pointer of OperationParameter */
241 using OperationParameterNNPtr = util::nn<OperationParameterPtr>;
242 
243 /** \brief The definition of a parameter used by a coordinate operation method.
244  *
245  * Most parameter values are numeric, but other types of parameter values are
246  * possible.
247  *
248  * \remark Implements OperationParameter from \ref ISO_19111_2019
249  */
250 class PROJ_GCC_DLL OperationParameter final : public GeneralOperationParameter {
251   public:
252     //! @cond Doxygen_Suppress
253     PROJ_DLL ~OperationParameter() override;
254     //! @endcond
255 
256     //! @cond Doxygen_Suppress
257     PROJ_INTERNAL bool _isEquivalentTo(
258         const util::IComparable *other,
259         util::IComparable::Criterion criterion =
260             util::IComparable::Criterion::STRICT,
261         const io::DatabaseContextPtr &dbContext = nullptr) const override;
262     //! @endcond
263 
264     // non-standard
265     PROJ_DLL static OperationParameterNNPtr
266     create(const util::PropertyMap &properties);
267 
268     PROJ_DLL int getEPSGCode() PROJ_PURE_DECL;
269 
270     PROJ_DLL static const char *getNameForEPSGCode(int epsg_code) noexcept;
271 
272   protected:
273     PROJ_INTERNAL OperationParameter();
274     PROJ_INTERNAL OperationParameter(const OperationParameter &other);
275     INLINED_MAKE_SHARED
276 
277   private:
278     PROJ_OPAQUE_PRIVATE_DATA
279     OperationParameter &operator=(const OperationParameter &other) = delete;
280 
281     // cppcheck-suppress functionStatic
282     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
283         const override; // throw(io::FormattingException)
284 };
285 
286 // ---------------------------------------------------------------------------
287 
288 //! @cond Doxygen_Suppress
289 struct MethodMapping;
290 //! @endcond
291 
292 /** \brief Abstract class modelling a parameter value (OperationParameterValue)
293  * or group of parameter values.
294  *
295  * \remark Implements GeneralParameterValue from \ref ISO_19111_2019
296  */
297 class PROJ_GCC_DLL GeneralParameterValue : public util::BaseObject,
298                                            public io::IWKTExportable,
299                                            public io::IJSONExportable,
300                                            public util::IComparable {
301   public:
302     //! @cond Doxygen_Suppress
303     PROJ_DLL ~GeneralParameterValue() override;
304 
305     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
306         const override = 0; // throw(io::FormattingException)
307 
308     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
309         const override = 0; // throw(FormattingException)
310 
311     PROJ_INTERNAL bool _isEquivalentTo(
312         const util::IComparable *other,
313         util::IComparable::Criterion criterion =
314             util::IComparable::Criterion::STRICT,
315         const io::DatabaseContextPtr &dbContext = nullptr) const override = 0;
316     //! @endcond
317 
318   protected:
319     //! @cond Doxygen_Suppress
320     PROJ_INTERNAL GeneralParameterValue();
321     PROJ_INTERNAL GeneralParameterValue(const GeneralParameterValue &other);
322 
323     friend class Conversion;
324     friend class SingleOperation;
325     PROJ_INTERNAL virtual void _exportToWKT(io::WKTFormatter *formatter,
326                                             const MethodMapping *mapping)
327         const = 0; // throw(io::FormattingException)
328                    //! @endcond
329 
330   private:
331     PROJ_OPAQUE_PRIVATE_DATA
332     GeneralParameterValue &
333     operator=(const GeneralParameterValue &other) = delete;
334 };
335 
336 /** Shared pointer of GeneralParameterValue */
337 using GeneralParameterValuePtr = std::shared_ptr<GeneralParameterValue>;
338 /** Non-null shared pointer of GeneralParameterValue */
339 using GeneralParameterValueNNPtr = util::nn<GeneralParameterValuePtr>;
340 
341 // ---------------------------------------------------------------------------
342 
343 class ParameterValue;
344 /** Shared pointer of ParameterValue */
345 using ParameterValuePtr = std::shared_ptr<ParameterValue>;
346 /** Non-null shared pointer of ParameterValue */
347 using ParameterValueNNPtr = util::nn<ParameterValuePtr>;
348 
349 /** \brief The value of the coordinate operation parameter.
350  *
351  * Most parameter values are numeric, but other types of parameter values are
352  * possible.
353  *
354  * \remark Implements ParameterValue from \ref ISO_19111_2019
355  */
356 class PROJ_GCC_DLL ParameterValue final : public util::BaseObject,
357                                           public io::IWKTExportable,
358                                           public util::IComparable {
359   public:
360     /** Type of the value. */
361     enum class Type {
362         /** Measure (i.e. value with a unit) */
363         MEASURE,
364         /** String */
365         STRING,
366         /** Integer */
367         INTEGER,
368         /** Boolean */
369         BOOLEAN,
370         /** Filename */
371         FILENAME
372     };
373     //! @cond Doxygen_Suppress
374     PROJ_DLL ~ParameterValue() override;
375 
376     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
377         const override; // throw(io::FormattingException)
378     //! @endcond
379 
380     PROJ_DLL static ParameterValueNNPtr
381     create(const common::Measure &measureIn);
382     PROJ_DLL static ParameterValueNNPtr create(const char *stringValueIn);
383     PROJ_DLL static ParameterValueNNPtr
384     create(const std::string &stringValueIn);
385     PROJ_DLL static ParameterValueNNPtr create(int integerValueIn);
386     PROJ_DLL static ParameterValueNNPtr create(bool booleanValueIn);
387     PROJ_DLL static ParameterValueNNPtr
388     createFilename(const std::string &stringValueIn);
389 
390     PROJ_DLL const Type &type() PROJ_PURE_DECL;
391     PROJ_DLL const common::Measure &value() PROJ_PURE_DECL;
392     PROJ_DLL const std::string &stringValue() PROJ_PURE_DECL;
393     PROJ_DLL const std::string &valueFile() PROJ_PURE_DECL;
394     PROJ_DLL int integerValue() PROJ_PURE_DECL;
395     PROJ_DLL bool booleanValue() PROJ_PURE_DECL;
396 
397     //! @cond Doxygen_Suppress
398     PROJ_INTERNAL bool _isEquivalentTo(
399         const util::IComparable *other,
400         util::IComparable::Criterion criterion =
401             util::IComparable::Criterion::STRICT,
402         const io::DatabaseContextPtr &dbContext = nullptr) const override;
403     //! @endcond
404 
405   protected:
406     PROJ_INTERNAL explicit ParameterValue(const common::Measure &measureIn);
407     PROJ_INTERNAL explicit ParameterValue(const std::string &stringValueIn,
408                                           Type typeIn);
409     PROJ_INTERNAL explicit ParameterValue(int integerValueIn);
410     PROJ_INTERNAL explicit ParameterValue(bool booleanValueIn);
411     INLINED_MAKE_SHARED
412   private:
413     PROJ_OPAQUE_PRIVATE_DATA
414     ParameterValue &operator=(const ParameterValue &other) = delete;
415 };
416 
417 // ---------------------------------------------------------------------------
418 
419 class OperationParameterValue;
420 /** Shared pointer of OperationParameterValue */
421 using OperationParameterValuePtr = std::shared_ptr<OperationParameterValue>;
422 /** Non-null shared pointer of OperationParameterValue */
423 using OperationParameterValueNNPtr = util::nn<OperationParameterValuePtr>;
424 
425 /** \brief A parameter value, ordered sequence of values, or reference to a
426  * file of parameter values.
427  *
428  * This combines a OperationParameter with the corresponding ParameterValue.
429  *
430  * \remark Implements OperationParameterValue from \ref ISO_19111_2019
431  */
432 class PROJ_GCC_DLL OperationParameterValue final
433     : public GeneralParameterValue {
434   public:
435     //! @cond Doxygen_Suppress
436     PROJ_DLL ~OperationParameterValue() override;
437     //! @endcond
438 
439     PROJ_DLL const OperationParameterNNPtr &parameter() PROJ_PURE_DECL;
440     PROJ_DLL const ParameterValueNNPtr &parameterValue() PROJ_PURE_DECL;
441 
442     PROJ_DLL static OperationParameterValueNNPtr
443     create(const OperationParameterNNPtr &parameterIn,
444            const ParameterValueNNPtr &valueIn);
445 
446     PROJ_PRIVATE :
447         //! @cond Doxygen_Suppress
448         PROJ_INTERNAL static bool
449         convertFromAbridged(const std::string &paramName, double &val,
450                             const common::UnitOfMeasure *&unit,
451                             int &paramEPSGCode);
452 
453     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
454         const override; // throw(io::FormattingException)
455 
456     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
457         const override; // throw(FormattingException)
458 
459     PROJ_INTERNAL bool _isEquivalentTo(
460         const util::IComparable *other,
461         util::IComparable::Criterion criterion =
462             util::IComparable::Criterion::STRICT,
463         const io::DatabaseContextPtr &dbContext = nullptr) const override;
464     //! @endcond
465 
466   protected:
467     PROJ_INTERNAL
468     OperationParameterValue(const OperationParameterNNPtr &parameterIn,
469                             const ParameterValueNNPtr &valueIn);
470     PROJ_INTERNAL OperationParameterValue(const OperationParameterValue &other);
471     INLINED_MAKE_SHARED
472 
473     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter,
474                                     const MethodMapping *mapping)
475         const override; // throw(io::FormattingException)
476 
477   private:
478     PROJ_OPAQUE_PRIVATE_DATA
479     OperationParameterValue &
480     operator=(const OperationParameterValue &other) = delete;
481 };
482 
483 // ---------------------------------------------------------------------------
484 
485 class OperationMethod;
486 /** Shared pointer of OperationMethod */
487 using OperationMethodPtr = std::shared_ptr<OperationMethod>;
488 /** Non-null shared pointer of OperationMethod */
489 using OperationMethodNNPtr = util::nn<OperationMethodPtr>;
490 
491 /** \brief The method (algorithm or procedure) used to perform the
492  * coordinate operation.
493  *
494  * For a projection method, this contains the name of the projection method
495  * and the name of the projection parameters.
496  *
497  * \remark Implements OperationMethod from \ref ISO_19111_2019
498  */
499 class PROJ_GCC_DLL OperationMethod : public common::IdentifiedObject,
500                                      public io::IJSONExportable {
501   public:
502     //! @cond Doxygen_Suppress
503     PROJ_DLL ~OperationMethod() override;
504     //! @endcond
505 
506     PROJ_DLL const util::optional<std::string> &formula() PROJ_PURE_DECL;
507     PROJ_DLL const util::optional<metadata::Citation> &
508     formulaCitation() PROJ_PURE_DECL;
509     PROJ_DLL const std::vector<GeneralOperationParameterNNPtr> &
510     parameters() PROJ_PURE_DECL;
511 
512     PROJ_DLL static OperationMethodNNPtr
513     create(const util::PropertyMap &properties,
514            const std::vector<GeneralOperationParameterNNPtr> &parameters);
515 
516     PROJ_DLL static OperationMethodNNPtr
517     create(const util::PropertyMap &properties,
518            const std::vector<OperationParameterNNPtr> &parameters);
519 
520     PROJ_DLL int getEPSGCode() PROJ_PURE_DECL;
521 
522     //! @cond Doxygen_Suppress
523     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
524         const override; // throw(io::FormattingException)
525 
526     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
527         const override; // throw(FormattingException)
528 
529     PROJ_INTERNAL bool _isEquivalentTo(
530         const util::IComparable *other,
531         util::IComparable::Criterion criterion =
532             util::IComparable::Criterion::STRICT,
533         const io::DatabaseContextPtr &dbContext = nullptr) const override;
534     //! @endcond
535 
536   protected:
537     PROJ_INTERNAL OperationMethod();
538     PROJ_INTERNAL OperationMethod(const OperationMethod &other);
539     INLINED_MAKE_SHARED
540     friend class Conversion;
541 
542   private:
543     PROJ_OPAQUE_PRIVATE_DATA
544     OperationMethod &operator=(const OperationMethod &other) = delete;
545 };
546 
547 // ---------------------------------------------------------------------------
548 
549 /** \brief Exception that can be thrown when an invalid operation is attempted
550  * to be constructed.
551  */
552 class PROJ_GCC_DLL InvalidOperation : public util::Exception {
553   public:
554     //! @cond Doxygen_Suppress
555     PROJ_INTERNAL explicit InvalidOperation(const char *message);
556     PROJ_INTERNAL explicit InvalidOperation(const std::string &message);
557     PROJ_DLL InvalidOperation(const InvalidOperation &other);
558     PROJ_DLL ~InvalidOperation() override;
559     //! @endcond
560 };
561 
562 // ---------------------------------------------------------------------------
563 
564 class SingleOperation;
565 /** Shared pointer of SingleOperation */
566 using SingleOperationPtr = std::shared_ptr<SingleOperation>;
567 /** Non-null shared pointer of SingleOperation */
568 using SingleOperationNNPtr = util::nn<SingleOperationPtr>;
569 
570 /** \brief A single (not concatenated) coordinate operation
571  * (CoordinateOperation)
572  *
573  * \remark Implements SingleOperation from \ref ISO_19111_2019
574  */
575 class PROJ_GCC_DLL SingleOperation : virtual public CoordinateOperation {
576   public:
577     //! @cond Doxygen_Suppress
578     PROJ_DLL ~SingleOperation() override;
579     //! @endcond
580 
581     PROJ_DLL const std::vector<GeneralParameterValueNNPtr> &
582     parameterValues() PROJ_PURE_DECL;
583     PROJ_DLL const OperationMethodNNPtr &method() PROJ_PURE_DECL;
584 
585     PROJ_DLL const ParameterValuePtr &
586     parameterValue(const std::string &paramName, int epsg_code = 0) const
587         noexcept;
588 
589     PROJ_DLL const ParameterValuePtr &parameterValue(int epsg_code) const
590         noexcept;
591 
592     PROJ_DLL const common::Measure &
593     parameterValueMeasure(const std::string &paramName, int epsg_code = 0) const
594         noexcept;
595 
596     PROJ_DLL const common::Measure &parameterValueMeasure(int epsg_code) const
597         noexcept;
598 
599     PROJ_DLL static SingleOperationNNPtr createPROJBased(
600         const util::PropertyMap &properties, const std::string &PROJString,
601         const crs::CRSPtr &sourceCRS, const crs::CRSPtr &targetCRS,
602         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies =
603             std::vector<metadata::PositionalAccuracyNNPtr>());
604 
605     PROJ_DLL std::set<GridDescription>
606     gridsNeeded(const io::DatabaseContextPtr &databaseContext,
607                 bool considerKnownGridsAsAvailable) const override;
608 
609     PROJ_DLL std::list<std::string> validateParameters() const;
610 
611     PROJ_PRIVATE :
612         //! @cond Doxygen_Suppress
613 
614         PROJ_DLL double
615         parameterValueNumeric(int epsg_code,
616                               const common::UnitOfMeasure &targetUnit) const
617         noexcept;
618 
619     PROJ_INTERNAL double
620     parameterValueNumeric(const char *param_name,
621                           const common::UnitOfMeasure &targetUnit) const
622         noexcept;
623 
624     PROJ_INTERNAL double parameterValueNumericAsSI(int epsg_code) const
625         noexcept;
626 
627     PROJ_INTERNAL bool _isEquivalentTo(
628         const util::IComparable *other,
629         util::IComparable::Criterion criterion =
630             util::IComparable::Criterion::STRICT,
631         const io::DatabaseContextPtr &dbContext = nullptr) const override;
632     //! @endcond
633 
634   protected:
635     PROJ_INTERNAL explicit SingleOperation(
636         const OperationMethodNNPtr &methodIn);
637     PROJ_INTERNAL SingleOperation(const SingleOperation &other);
638 
639     PROJ_INTERNAL void
640     setParameterValues(const std::vector<GeneralParameterValueNNPtr> &values);
641 
642     PROJ_INTERNAL void
643     exportTransformationToWKT(io::WKTFormatter *formatter) const;
644 
645     PROJ_INTERNAL bool
646     exportToPROJStringGeneric(io::PROJStringFormatter *formatter) const;
647 
648     PROJ_INTERNAL bool _isEquivalentTo(const util::IComparable *other,
649                                        util::IComparable::Criterion criterion,
650                                        const io::DatabaseContextPtr &dbContext,
651                                        bool inOtherDirection) const;
652 
653   private:
654     PROJ_OPAQUE_PRIVATE_DATA
655     SingleOperation &operator=(const SingleOperation &other) = delete;
656 };
657 
658 // ---------------------------------------------------------------------------
659 
660 class Conversion;
661 /** Shared pointer of Conversion */
662 using ConversionPtr = std::shared_ptr<Conversion>;
663 /** Non-null shared pointer of Conversion */
664 using ConversionNNPtr = util::nn<ConversionPtr>;
665 
666 /** \brief A mathematical operation on coordinates in which the parameter
667  * values are defined rather than empirically derived.
668  *
669  * Application of the coordinate conversion introduces no error into output
670  * coordinates. The best-known example of a coordinate conversion is a map
671  * projection. For coordinate conversions the output coordinates are referenced
672  * to the same datum as are the input coordinates.
673  *
674  * Coordinate conversions forming a component of a derived CRS have a source
675  * crs::CRS and a target crs::CRS that are NOT specified through the source and
676  * target
677  * associations, but through associations from crs::DerivedCRS to
678  * crs::SingleCRS.
679  *
680  * \remark Implements Conversion from \ref ISO_19111_2019
681  */
682 
683 /*!
684 
685 \section projection_parameters Projection parameters
686 
687 \subsection colatitude_cone_axis Co-latitude of cone axis
688 
689 The rotation applied to spherical coordinates for the oblique projection,
690 measured on the conformal sphere in the plane of the meridian of origin.
691 
692 EPSG:1036
693 
694 \subsection center_latitude Latitude of natural origin/Center Latitude
695 
696 The latitude of the point from which the values of both the geographical
697 coordinates on the ellipsoid and the grid coordinates on the projection are
698 deemed to increment or decrement for computational purposes. Alternatively it
699 may be considered as the latitude of the point which in the absence of
700 application of false coordinates has grid coordinates of (0,0).
701 
702 EPSG:8801
703 
704 \subsection center_longitude Longitude of natural origin/Central Meridian
705 
706 The longitude of the point from which the values of both the geographical
707 coordinates on the ellipsoid and the grid coordinates on the projection are
708 deemed to increment or decrement for computational purposes. Alternatively it
709 may be considered as the longitude of the point which in the absence of
710 application of false coordinates has grid coordinates of (0,0).  Sometimes known
711 as "central meridian (CM)".
712 
713 EPSG:8802
714 
715 \subsection scale Scale Factor
716 
717 The factor by which the map grid is reduced or enlarged during the projection
718 process, defined by its value at the natural origin.
719 
720 EPSG:8805
721 
722 \subsection false_easting False Easting
723 
724 Since the natural origin may be at or near the centre of the projection and
725 under normal coordinate circumstances would thus give rise to negative
726 coordinates over parts of the mapped area, this origin is usually given false
727 coordinates which are large enough to avoid this inconvenience. The False
728 Easting, FE, is the value assigned to the abscissa (east or west) axis of the
729 projection grid at the natural origin.
730 
731 EPSG:8806
732 
733 \subsection false_northing False Northing
734 
735 Since the natural origin may be at or near the centre of the projection and
736 under normal coordinate circumstances would thus give rise to negative
737 coordinates over parts of the mapped area, this origin is usually given false
738 coordinates which are large enough to avoid this inconvenience. The False
739 Northing, FN, is the value assigned to the ordinate (north or south) axis of the
740 projection grid at the natural origin.
741 
742 EPSG:8807
743 
744 \subsection latitude_projection_centre Latitute of projection centre
745 
746 For an oblique projection, this is the latitude of the point at which the
747 azimuth of the central line is defined.
748 
749 EPSG:8811
750 
751 \subsection longitude_projection_centre Longitude of projection centre
752 
753 For an oblique projection, this is the longitude of the point at which the
754 azimuth of the central line is defined.
755 
756 EPSG:8812
757 
758 \subsection azimuth_initial_line Azimuth of initial line
759 
760 The azimuthal direction (north zero, east of north being positive) of the great
761 circle which is the centre line of an oblique projection. The azimuth is given
762 at the projection centre.
763 
764 EPSG:8813
765 
766 \subsection angle_from_recitfied_to_skrew_grid Angle from Rectified to Skew Grid
767 
768 The angle at the natural origin of an oblique projection through which the
769 natural coordinate reference system is rotated to make the projection north
770 axis parallel with true north.
771 
772 EPSG:8814
773 
774 \subsection scale_factor_initial_line Scale factor on initial line
775 
776 The factor by which the map grid is reduced or enlarged during the projection
777 process, defined by its value at the projection center.
778 
779 EPSG:8815
780 
781 \subsection easting_projection_centre Easting at projection centre
782 
783 The easting value assigned to the projection centre.
784 
785 EPSG:8816
786 
787 \subsection northing_projection_centre Northing at projection centre
788 
789 The northing value assigned to the projection centre.
790 
791 EPSG:8817
792 
793 \subsection latitude_pseudo_standard_parallel Latitude of pseudo standard
794 parallel
795 
796 Latitude of the parallel on which the conic or cylindrical projection is based.
797 This latitude is not geographic, but is defined on the conformal sphere AFTER
798 its rotation to obtain the oblique aspect of the projection.
799 
800 EPSG:8818
801 
802 \subsection scale_factor_pseudo_standard_parallel Scale factor on pseudo
803 standard parallel
804 
805 The factor by which the map grid is reduced or enlarged during the projection
806 process, defined by its value at the pseudo-standard parallel.
807 EPSG:8819
808 
809 \subsection latitude_false_origin Latitude of false origin
810 
811 The latitude of the point which is not the natural origin and at which grid
812 coordinate values false easting and false northing are defined.
813 
814 EPSG:8821
815 
816 \subsection longitude_false_origin Longitude of false origin
817 
818 The longitude of the point which is not the natural origin and at which grid
819 coordinate values false easting and false northing are defined.
820 
821 EPSG:8822
822 
823 \subsection latitude_first_std_parallel Latitude of 1st standard parallel
824 
825 For a conic projection with two standard parallels, this is the latitude of one
826 of the parallels of intersection of the cone with the ellipsoid. It is normally
827 but not necessarily that nearest to the pole. Scale is true along this parallel.
828 
829 EPSG:8823
830 
831 \subsection latitude_second_std_parallel Latitude of 2nd standard parallel
832 
833 For a conic projection with two standard parallels, this is the latitude of one
834 of the parallels at which the cone intersects with the ellipsoid. It is normally
835 but not necessarily that nearest to the equator. Scale is true along this
836 parallel.
837 
838 EPSG:8824
839 
840 \subsection easting_false_origin Easting of false origin
841 
842 The easting value assigned to the false origin.
843 
844 EPSG:8826
845 
846 \subsection northing_false_origin Northing of false origin
847 
848 The northing value assigned to the false origin.
849 
850 EPSG:8827
851 
852 \subsection latitude_std_parallel Latitude of standard parallel
853 
854 For polar aspect azimuthal projections, the parallel on which the scale factor
855 is defined to be unity.
856 
857 EPSG:8832
858 
859 \subsection longitude_of_origin Longitude of origin
860 
861 For polar aspect azimuthal projections, the meridian along which the
862 northing axis increments and also across which parallels of latitude
863 increment towards the north pole.
864 
865 EPSG:8833
866 
867 */
868 
869 class PROJ_GCC_DLL Conversion : public SingleOperation {
870   public:
871     //! @cond Doxygen_Suppress
872     PROJ_DLL ~Conversion() override;
873     //! @endcond
874 
875     PROJ_DLL CoordinateOperationNNPtr inverse() const override;
876 
877     //! @cond Doxygen_Suppress
878     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
879         const override; // throw(io::FormattingException)
880     //! @endcond
881 
882     PROJ_DLL bool isUTM(int &zone, bool &north) const;
883 
884     PROJ_DLL ConversionNNPtr identify() const;
885 
886     PROJ_DLL static ConversionNNPtr
887     create(const util::PropertyMap &properties,
888            const OperationMethodNNPtr &methodIn,
889            const std::vector<GeneralParameterValueNNPtr>
890                &values); // throw InvalidOperation
891 
892     PROJ_DLL static ConversionNNPtr
893     create(const util::PropertyMap &propertiesConversion,
894            const util::PropertyMap &propertiesOperationMethod,
895            const std::vector<OperationParameterNNPtr> &parameters,
896            const std::vector<ParameterValueNNPtr>
897                &values); // throw InvalidOperation
898 
899     PROJ_DLL static ConversionNNPtr
900     createUTM(const util::PropertyMap &properties, int zone, bool north);
901 
902     PROJ_DLL static ConversionNNPtr createTransverseMercator(
903         const util::PropertyMap &properties, const common::Angle &centerLat,
904         const common::Angle &centerLong, const common::Scale &scale,
905         const common::Length &falseEasting,
906         const common::Length &falseNorthing);
907 
908     PROJ_DLL static ConversionNNPtr createGaussSchreiberTransverseMercator(
909         const util::PropertyMap &properties, const common::Angle &centerLat,
910         const common::Angle &centerLong, const common::Scale &scale,
911         const common::Length &falseEasting,
912         const common::Length &falseNorthing);
913 
914     PROJ_DLL static ConversionNNPtr createTransverseMercatorSouthOriented(
915         const util::PropertyMap &properties, const common::Angle &centerLat,
916         const common::Angle &centerLong, const common::Scale &scale,
917         const common::Length &falseEasting,
918         const common::Length &falseNorthing);
919 
920     PROJ_DLL static ConversionNNPtr
921     createTwoPointEquidistant(const util::PropertyMap &properties,
922                               const common::Angle &latitudeFirstPoint,
923                               const common::Angle &longitudeFirstPoint,
924                               const common::Angle &latitudeSecondPoint,
925                               const common::Angle &longitudeSeconPoint,
926                               const common::Length &falseEasting,
927                               const common::Length &falseNorthing);
928 
929     PROJ_DLL static ConversionNNPtr createTunisiaMappingGrid(
930         const util::PropertyMap &properties, const common::Angle &centerLat,
931         const common::Angle &centerLong, const common::Length &falseEasting,
932         const common::Length &falseNorthing);
933 
934     PROJ_DLL static ConversionNNPtr
935     createAlbersEqualArea(const util::PropertyMap &properties,
936                           const common::Angle &latitudeFalseOrigin,
937                           const common::Angle &longitudeFalseOrigin,
938                           const common::Angle &latitudeFirstParallel,
939                           const common::Angle &latitudeSecondParallel,
940                           const common::Length &eastingFalseOrigin,
941                           const common::Length &northingFalseOrigin);
942 
943     PROJ_DLL static ConversionNNPtr createLambertConicConformal_1SP(
944         const util::PropertyMap &properties, const common::Angle &centerLat,
945         const common::Angle &centerLong, const common::Scale &scale,
946         const common::Length &falseEasting,
947         const common::Length &falseNorthing);
948 
949     PROJ_DLL static ConversionNNPtr
950     createLambertConicConformal_2SP(const util::PropertyMap &properties,
951                                     const common::Angle &latitudeFalseOrigin,
952                                     const common::Angle &longitudeFalseOrigin,
953                                     const common::Angle &latitudeFirstParallel,
954                                     const common::Angle &latitudeSecondParallel,
955                                     const common::Length &eastingFalseOrigin,
956                                     const common::Length &northingFalseOrigin);
957 
958     PROJ_DLL static ConversionNNPtr createLambertConicConformal_2SP_Michigan(
959         const util::PropertyMap &properties,
960         const common::Angle &latitudeFalseOrigin,
961         const common::Angle &longitudeFalseOrigin,
962         const common::Angle &latitudeFirstParallel,
963         const common::Angle &latitudeSecondParallel,
964         const common::Length &eastingFalseOrigin,
965         const common::Length &northingFalseOrigin,
966         const common::Scale &ellipsoidScalingFactor);
967 
968     PROJ_DLL static ConversionNNPtr createLambertConicConformal_2SP_Belgium(
969         const util::PropertyMap &properties,
970         const common::Angle &latitudeFalseOrigin,
971         const common::Angle &longitudeFalseOrigin,
972         const common::Angle &latitudeFirstParallel,
973         const common::Angle &latitudeSecondParallel,
974         const common::Length &eastingFalseOrigin,
975         const common::Length &northingFalseOrigin);
976 
977     PROJ_DLL static ConversionNNPtr
978     createAzimuthalEquidistant(const util::PropertyMap &properties,
979                                const common::Angle &latitudeNatOrigin,
980                                const common::Angle &longitudeNatOrigin,
981                                const common::Length &falseEasting,
982                                const common::Length &falseNorthing);
983 
984     PROJ_DLL static ConversionNNPtr
985     createGuamProjection(const util::PropertyMap &properties,
986                          const common::Angle &latitudeNatOrigin,
987                          const common::Angle &longitudeNatOrigin,
988                          const common::Length &falseEasting,
989                          const common::Length &falseNorthing);
990 
991     PROJ_DLL static ConversionNNPtr
992     createBonne(const util::PropertyMap &properties,
993                 const common::Angle &latitudeNatOrigin,
994                 const common::Angle &longitudeNatOrigin,
995                 const common::Length &falseEasting,
996                 const common::Length &falseNorthing);
997 
998     PROJ_DLL static ConversionNNPtr createLambertCylindricalEqualAreaSpherical(
999         const util::PropertyMap &properties,
1000         const common::Angle &latitudeFirstParallel,
1001         const common::Angle &longitudeNatOrigin,
1002         const common::Length &falseEasting,
1003         const common::Length &falseNorthing);
1004 
1005     PROJ_DLL static ConversionNNPtr createLambertCylindricalEqualArea(
1006         const util::PropertyMap &properties,
1007         const common::Angle &latitudeFirstParallel,
1008         const common::Angle &longitudeNatOrigin,
1009         const common::Length &falseEasting,
1010         const common::Length &falseNorthing);
1011 
1012     PROJ_DLL static ConversionNNPtr createCassiniSoldner(
1013         const util::PropertyMap &properties, const common::Angle &centerLat,
1014         const common::Angle &centerLong, const common::Length &falseEasting,
1015         const common::Length &falseNorthing);
1016 
1017     PROJ_DLL static ConversionNNPtr
1018     createEquidistantConic(const util::PropertyMap &properties,
1019                            const common::Angle &centerLat,
1020                            const common::Angle &centerLong,
1021                            const common::Angle &latitudeFirstParallel,
1022                            const common::Angle &latitudeSecondParallel,
1023                            const common::Length &falseEasting,
1024                            const common::Length &falseNorthing);
1025 
1026     PROJ_DLL static ConversionNNPtr
1027     createEckertI(const util::PropertyMap &properties,
1028                   const common::Angle &centerLong,
1029                   const common::Length &falseEasting,
1030                   const common::Length &falseNorthing);
1031 
1032     PROJ_DLL static ConversionNNPtr
1033     createEckertII(const util::PropertyMap &properties,
1034                    const common::Angle &centerLong,
1035                    const common::Length &falseEasting,
1036                    const common::Length &falseNorthing);
1037 
1038     PROJ_DLL static ConversionNNPtr
1039     createEckertIII(const util::PropertyMap &properties,
1040                     const common::Angle &centerLong,
1041                     const common::Length &falseEasting,
1042                     const common::Length &falseNorthing);
1043 
1044     PROJ_DLL static ConversionNNPtr
1045     createEckertIV(const util::PropertyMap &properties,
1046                    const common::Angle &centerLong,
1047                    const common::Length &falseEasting,
1048                    const common::Length &falseNorthing);
1049 
1050     PROJ_DLL static ConversionNNPtr
1051     createEckertV(const util::PropertyMap &properties,
1052                   const common::Angle &centerLong,
1053                   const common::Length &falseEasting,
1054                   const common::Length &falseNorthing);
1055 
1056     PROJ_DLL static ConversionNNPtr
1057     createEckertVI(const util::PropertyMap &properties,
1058                    const common::Angle &centerLong,
1059                    const common::Length &falseEasting,
1060                    const common::Length &falseNorthing);
1061 
1062     PROJ_DLL static ConversionNNPtr
1063     createEquidistantCylindrical(const util::PropertyMap &properties,
1064                                  const common::Angle &latitudeFirstParallel,
1065                                  const common::Angle &longitudeNatOrigin,
1066                                  const common::Length &falseEasting,
1067                                  const common::Length &falseNorthing);
1068 
1069     PROJ_DLL static ConversionNNPtr createEquidistantCylindricalSpherical(
1070         const util::PropertyMap &properties,
1071         const common::Angle &latitudeFirstParallel,
1072         const common::Angle &longitudeNatOrigin,
1073         const common::Length &falseEasting,
1074         const common::Length &falseNorthing);
1075 
1076     PROJ_DLL static ConversionNNPtr
1077     createGall(const util::PropertyMap &properties,
1078                const common::Angle &centerLong,
1079                const common::Length &falseEasting,
1080                const common::Length &falseNorthing);
1081 
1082     PROJ_DLL static ConversionNNPtr
1083     createGoodeHomolosine(const util::PropertyMap &properties,
1084                           const common::Angle &centerLong,
1085                           const common::Length &falseEasting,
1086                           const common::Length &falseNorthing);
1087 
1088     PROJ_DLL static ConversionNNPtr
1089     createInterruptedGoodeHomolosine(const util::PropertyMap &properties,
1090                                      const common::Angle &centerLong,
1091                                      const common::Length &falseEasting,
1092                                      const common::Length &falseNorthing);
1093 
1094     PROJ_DLL static ConversionNNPtr createGeostationarySatelliteSweepX(
1095         const util::PropertyMap &properties, const common::Angle &centerLong,
1096         const common::Length &height, const common::Length &falseEasting,
1097         const common::Length &falseNorthing);
1098 
1099     PROJ_DLL static ConversionNNPtr createGeostationarySatelliteSweepY(
1100         const util::PropertyMap &properties, const common::Angle &centerLong,
1101         const common::Length &height, const common::Length &falseEasting,
1102         const common::Length &falseNorthing);
1103 
1104     PROJ_DLL static ConversionNNPtr createGnomonic(
1105         const util::PropertyMap &properties, const common::Angle &centerLat,
1106         const common::Angle &centerLong, const common::Length &falseEasting,
1107         const common::Length &falseNorthing);
1108 
1109     PROJ_DLL static ConversionNNPtr createHotineObliqueMercatorVariantA(
1110         const util::PropertyMap &properties,
1111         const common::Angle &latitudeProjectionCentre,
1112         const common::Angle &longitudeProjectionCentre,
1113         const common::Angle &azimuthInitialLine,
1114         const common::Angle &angleFromRectifiedToSkrewGrid,
1115         const common::Scale &scale, const common::Length &falseEasting,
1116         const common::Length &falseNorthing);
1117 
1118     PROJ_DLL static ConversionNNPtr createHotineObliqueMercatorVariantB(
1119         const util::PropertyMap &properties,
1120         const common::Angle &latitudeProjectionCentre,
1121         const common::Angle &longitudeProjectionCentre,
1122         const common::Angle &azimuthInitialLine,
1123         const common::Angle &angleFromRectifiedToSkrewGrid,
1124         const common::Scale &scale,
1125         const common::Length &eastingProjectionCentre,
1126         const common::Length &northingProjectionCentre);
1127 
1128     PROJ_DLL static ConversionNNPtr
1129     createHotineObliqueMercatorTwoPointNaturalOrigin(
1130         const util::PropertyMap &properties,
1131         const common::Angle &latitudeProjectionCentre,
1132         const common::Angle &latitudePoint1,
1133         const common::Angle &longitudePoint1,
1134         const common::Angle &latitudePoint2,
1135         const common::Angle &longitudePoint2, const common::Scale &scale,
1136         const common::Length &eastingProjectionCentre,
1137         const common::Length &northingProjectionCentre);
1138 
1139     PROJ_DLL static ConversionNNPtr
1140     createLabordeObliqueMercator(const util::PropertyMap &properties,
1141                                  const common::Angle &latitudeProjectionCentre,
1142                                  const common::Angle &longitudeProjectionCentre,
1143                                  const common::Angle &azimuthInitialLine,
1144                                  const common::Scale &scale,
1145                                  const common::Length &falseEasting,
1146                                  const common::Length &falseNorthing);
1147 
1148     PROJ_DLL static ConversionNNPtr createInternationalMapWorldPolyconic(
1149         const util::PropertyMap &properties, const common::Angle &centerLong,
1150         const common::Angle &latitudeFirstParallel,
1151         const common::Angle &latitudeSecondParallel,
1152         const common::Length &falseEasting,
1153         const common::Length &falseNorthing);
1154 
1155     PROJ_DLL static ConversionNNPtr createKrovakNorthOriented(
1156         const util::PropertyMap &properties,
1157         const common::Angle &latitudeProjectionCentre,
1158         const common::Angle &longitudeOfOrigin,
1159         const common::Angle &colatitudeConeAxis,
1160         const common::Angle &latitudePseudoStandardParallel,
1161         const common::Scale &scaleFactorPseudoStandardParallel,
1162         const common::Length &falseEasting,
1163         const common::Length &falseNorthing);
1164 
1165     PROJ_DLL static ConversionNNPtr
1166     createKrovak(const util::PropertyMap &properties,
1167                  const common::Angle &latitudeProjectionCentre,
1168                  const common::Angle &longitudeOfOrigin,
1169                  const common::Angle &colatitudeConeAxis,
1170                  const common::Angle &latitudePseudoStandardParallel,
1171                  const common::Scale &scaleFactorPseudoStandardParallel,
1172                  const common::Length &falseEasting,
1173                  const common::Length &falseNorthing);
1174 
1175     PROJ_DLL static ConversionNNPtr
1176     createLambertAzimuthalEqualArea(const util::PropertyMap &properties,
1177                                     const common::Angle &latitudeNatOrigin,
1178                                     const common::Angle &longitudeNatOrigin,
1179                                     const common::Length &falseEasting,
1180                                     const common::Length &falseNorthing);
1181 
1182     PROJ_DLL static ConversionNNPtr
1183     createMillerCylindrical(const util::PropertyMap &properties,
1184                             const common::Angle &centerLong,
1185                             const common::Length &falseEasting,
1186                             const common::Length &falseNorthing);
1187 
1188     PROJ_DLL static ConversionNNPtr createMercatorVariantA(
1189         const util::PropertyMap &properties, const common::Angle &centerLat,
1190         const common::Angle &centerLong, const common::Scale &scale,
1191         const common::Length &falseEasting,
1192         const common::Length &falseNorthing);
1193 
1194     PROJ_DLL static ConversionNNPtr
1195     createMercatorVariantB(const util::PropertyMap &properties,
1196                            const common::Angle &latitudeFirstParallel,
1197                            const common::Angle &centerLong,
1198                            const common::Length &falseEasting,
1199                            const common::Length &falseNorthing);
1200 
1201     PROJ_DLL static ConversionNNPtr createPopularVisualisationPseudoMercator(
1202         const util::PropertyMap &properties, const common::Angle &centerLat,
1203         const common::Angle &centerLong, const common::Length &falseEasting,
1204         const common::Length &falseNorthing);
1205 
1206     PROJ_DLL static ConversionNNPtr
1207     createMollweide(const util::PropertyMap &properties,
1208                     const common::Angle &centerLong,
1209                     const common::Length &falseEasting,
1210                     const common::Length &falseNorthing);
1211 
1212     PROJ_DLL static ConversionNNPtr createNewZealandMappingGrid(
1213         const util::PropertyMap &properties, const common::Angle &centerLat,
1214         const common::Angle &centerLong, const common::Length &falseEasting,
1215         const common::Length &falseNorthing);
1216 
1217     PROJ_DLL static ConversionNNPtr createObliqueStereographic(
1218         const util::PropertyMap &properties, const common::Angle &centerLat,
1219         const common::Angle &centerLong, const common::Scale &scale,
1220         const common::Length &falseEasting,
1221         const common::Length &falseNorthing);
1222 
1223     PROJ_DLL static ConversionNNPtr createOrthographic(
1224         const util::PropertyMap &properties, const common::Angle &centerLat,
1225         const common::Angle &centerLong, const common::Length &falseEasting,
1226         const common::Length &falseNorthing);
1227 
1228     PROJ_DLL static ConversionNNPtr createAmericanPolyconic(
1229         const util::PropertyMap &properties, const common::Angle &centerLat,
1230         const common::Angle &centerLong, const common::Length &falseEasting,
1231         const common::Length &falseNorthing);
1232 
1233     PROJ_DLL static ConversionNNPtr createPolarStereographicVariantA(
1234         const util::PropertyMap &properties, const common::Angle &centerLat,
1235         const common::Angle &centerLong, const common::Scale &scale,
1236         const common::Length &falseEasting,
1237         const common::Length &falseNorthing);
1238 
1239     PROJ_DLL static ConversionNNPtr createPolarStereographicVariantB(
1240         const util::PropertyMap &properties,
1241         const common::Angle &latitudeStandardParallel,
1242         const common::Angle &longitudeOfOrigin,
1243         const common::Length &falseEasting,
1244         const common::Length &falseNorthing);
1245 
1246     PROJ_DLL static ConversionNNPtr
1247     createRobinson(const util::PropertyMap &properties,
1248                    const common::Angle &centerLong,
1249                    const common::Length &falseEasting,
1250                    const common::Length &falseNorthing);
1251 
1252     PROJ_DLL static ConversionNNPtr
1253     createSinusoidal(const util::PropertyMap &properties,
1254                      const common::Angle &centerLong,
1255                      const common::Length &falseEasting,
1256                      const common::Length &falseNorthing);
1257 
1258     PROJ_DLL static ConversionNNPtr createStereographic(
1259         const util::PropertyMap &properties, const common::Angle &centerLat,
1260         const common::Angle &centerLong, const common::Scale &scale,
1261         const common::Length &falseEasting,
1262         const common::Length &falseNorthing);
1263 
1264     PROJ_DLL static ConversionNNPtr
1265     createVanDerGrinten(const util::PropertyMap &properties,
1266                         const common::Angle &centerLong,
1267                         const common::Length &falseEasting,
1268                         const common::Length &falseNorthing);
1269 
1270     PROJ_DLL static ConversionNNPtr
1271     createWagnerI(const util::PropertyMap &properties,
1272                   const common::Angle &centerLong,
1273                   const common::Length &falseEasting,
1274                   const common::Length &falseNorthing);
1275 
1276     PROJ_DLL static ConversionNNPtr
1277     createWagnerII(const util::PropertyMap &properties,
1278                    const common::Angle &centerLong,
1279                    const common::Length &falseEasting,
1280                    const common::Length &falseNorthing);
1281 
1282     PROJ_DLL static ConversionNNPtr
1283     createWagnerIII(const util::PropertyMap &properties,
1284                     const common::Angle &latitudeTrueScale,
1285                     const common::Angle &centerLong,
1286                     const common::Length &falseEasting,
1287                     const common::Length &falseNorthing);
1288 
1289     PROJ_DLL static ConversionNNPtr
1290     createWagnerIV(const util::PropertyMap &properties,
1291                    const common::Angle &centerLong,
1292                    const common::Length &falseEasting,
1293                    const common::Length &falseNorthing);
1294 
1295     PROJ_DLL static ConversionNNPtr
1296     createWagnerV(const util::PropertyMap &properties,
1297                   const common::Angle &centerLong,
1298                   const common::Length &falseEasting,
1299                   const common::Length &falseNorthing);
1300 
1301     PROJ_DLL static ConversionNNPtr
1302     createWagnerVI(const util::PropertyMap &properties,
1303                    const common::Angle &centerLong,
1304                    const common::Length &falseEasting,
1305                    const common::Length &falseNorthing);
1306 
1307     PROJ_DLL static ConversionNNPtr
1308     createWagnerVII(const util::PropertyMap &properties,
1309                     const common::Angle &centerLong,
1310                     const common::Length &falseEasting,
1311                     const common::Length &falseNorthing);
1312 
1313     PROJ_DLL static ConversionNNPtr createQuadrilateralizedSphericalCube(
1314         const util::PropertyMap &properties, const common::Angle &centerLat,
1315         const common::Angle &centerLong, const common::Length &falseEasting,
1316         const common::Length &falseNorthing);
1317 
1318     PROJ_DLL static ConversionNNPtr createSphericalCrossTrackHeight(
1319         const util::PropertyMap &properties, const common::Angle &pegPointLat,
1320         const common::Angle &pegPointLong, const common::Angle &pegPointHeading,
1321         const common::Length &pegPointHeight);
1322 
1323     PROJ_DLL static ConversionNNPtr
1324     createEqualEarth(const util::PropertyMap &properties,
1325                      const common::Angle &centerLong,
1326                      const common::Length &falseEasting,
1327                      const common::Length &falseNorthing);
1328 
1329     PROJ_DLL static ConversionNNPtr
1330     createVerticalPerspective(const util::PropertyMap &properties,
1331                               const common::Angle &topoOriginLat,
1332                               const common::Angle &topoOriginLong,
1333                               const common::Length &topoOriginHeight,
1334                               const common::Length &viewPointHeight,
1335                               const common::Length &falseEasting,
1336                               const common::Length &falseNorthing);
1337 
1338     PROJ_DLL static ConversionNNPtr createPoleRotationGRIBConvention(
1339         const util::PropertyMap &properties,
1340         const common::Angle &southPoleLatInUnrotatedCRS,
1341         const common::Angle &southPoleLongInUnrotatedCRS,
1342         const common::Angle &axisRotation);
1343 
1344     PROJ_DLL static ConversionNNPtr
1345     createChangeVerticalUnit(const util::PropertyMap &properties,
1346                              const common::Scale &factor);
1347 
1348     PROJ_DLL static ConversionNNPtr
1349     createHeightDepthReversal(const util::PropertyMap &properties);
1350 
1351     PROJ_DLL static ConversionNNPtr createAxisOrderReversal(bool is3D);
1352 
1353     PROJ_DLL static ConversionNNPtr
1354     createGeographicGeocentric(const util::PropertyMap &properties);
1355 
1356     PROJ_DLL ConversionPtr convertToOtherMethod(int targetEPSGCode) const;
1357 
1358     PROJ_PRIVATE :
1359         //! @cond Doxygen_Suppress
1360         PROJ_INTERNAL void
1361         _exportToPROJString(io::PROJStringFormatter *formatter)
1362             const override; // throw(FormattingException)
1363 
1364     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
1365         const override; // throw(FormattingException)
1366 
1367     PROJ_INTERNAL const char *getESRIMethodName() const;
1368 
1369     PROJ_INTERNAL const char *getWKT1GDALMethodName() const;
1370 
1371     PROJ_INTERNAL ConversionNNPtr shallowClone() const;
1372 
1373     PROJ_INTERNAL ConversionNNPtr alterParametersLinearUnit(
1374         const common::UnitOfMeasure &unit, bool convertToNewUnit) const;
1375 
1376     PROJ_INTERNAL static ConversionNNPtr
1377     createGeographicGeocentric(const crs::CRSNNPtr &sourceCRS,
1378                                const crs::CRSNNPtr &targetCRS);
1379 
1380     //! @endcond
1381 
1382   protected:
1383     PROJ_INTERNAL
1384     Conversion(const OperationMethodNNPtr &methodIn,
1385                const std::vector<GeneralParameterValueNNPtr> &values);
1386     PROJ_INTERNAL Conversion(const Conversion &other);
1387     INLINED_MAKE_SHARED
1388 
1389     PROJ_FRIEND(crs::ProjectedCRS);
1390     PROJ_INTERNAL bool addWKTExtensionNode(io::WKTFormatter *formatter) const;
1391 
1392     PROJ_INTERNAL CoordinateOperationNNPtr _shallowClone() const override;
1393 
1394   private:
1395     PROJ_OPAQUE_PRIVATE_DATA
1396     Conversion &operator=(const Conversion &other) = delete;
1397 
1398     PROJ_INTERNAL static ConversionNNPtr
1399     create(const util::PropertyMap &properties, int method_epsg_code,
1400            const std::vector<ParameterValueNNPtr> &values);
1401 
1402     PROJ_INTERNAL static ConversionNNPtr
1403     create(const util::PropertyMap &properties, const char *method_wkt2_name,
1404            const std::vector<ParameterValueNNPtr> &values);
1405 };
1406 
1407 // ---------------------------------------------------------------------------
1408 
1409 class Transformation;
1410 /** Shared pointer of Transformation */
1411 using TransformationPtr = std::shared_ptr<Transformation>;
1412 /** Non-null shared pointer of Transformation */
1413 using TransformationNNPtr = util::nn<TransformationPtr>;
1414 
1415 /** \brief A mathematical operation on coordinates in which parameters are
1416  * empirically derived from data containing the coordinates of a series of
1417  * points in both coordinate reference systems.
1418  *
1419  * This computational process is usually "over-determined", allowing derivation
1420  * of error (or accuracy) estimates for the coordinate transformation. Also,
1421  * the stochastic nature of the parameters may result in multiple (different)
1422  * versions of the same coordinate transformations between the same source and
1423  * target CRSs. Any single coordinate operation in which the input and output
1424  * coordinates are referenced to different datums (reference frames) will be a
1425  * coordinate transformation.
1426  *
1427  * \remark Implements Transformation from \ref ISO_19111_2019
1428  */
1429 class PROJ_GCC_DLL Transformation : public SingleOperation {
1430   public:
1431     //! @cond Doxygen_Suppress
1432     PROJ_DLL ~Transformation() override;
1433     //! @endcond
1434 
1435     PROJ_DLL const crs::CRSNNPtr &sourceCRS() PROJ_PURE_DECL;
1436     PROJ_DLL const crs::CRSNNPtr &targetCRS() PROJ_PURE_DECL;
1437 
1438     PROJ_DLL CoordinateOperationNNPtr inverse() const override;
1439 
1440     PROJ_DLL static TransformationNNPtr
1441     create(const util::PropertyMap &properties,
1442            const crs::CRSNNPtr &sourceCRSIn, const crs::CRSNNPtr &targetCRSIn,
1443            const crs::CRSPtr &interpolationCRSIn,
1444            const OperationMethodNNPtr &methodIn,
1445            const std::vector<GeneralParameterValueNNPtr> &values,
1446            const std::vector<metadata::PositionalAccuracyNNPtr>
1447                &accuracies); // throw InvalidOperation
1448 
1449     PROJ_DLL static TransformationNNPtr
1450     create(const util::PropertyMap &propertiesTransformation,
1451            const crs::CRSNNPtr &sourceCRSIn, const crs::CRSNNPtr &targetCRSIn,
1452            const crs::CRSPtr &interpolationCRSIn,
1453            const util::PropertyMap &propertiesOperationMethod,
1454            const std::vector<OperationParameterNNPtr> &parameters,
1455            const std::vector<ParameterValueNNPtr> &values,
1456            const std::vector<metadata::PositionalAccuracyNNPtr>
1457                &accuracies); // throw InvalidOperation
1458 
1459     PROJ_DLL static TransformationNNPtr createGeocentricTranslations(
1460         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1461         const crs::CRSNNPtr &targetCRSIn, double translationXMetre,
1462         double translationYMetre, double translationZMetre,
1463         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1464 
1465     PROJ_DLL static TransformationNNPtr createPositionVector(
1466         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1467         const crs::CRSNNPtr &targetCRSIn, double translationXMetre,
1468         double translationYMetre, double translationZMetre,
1469         double rotationXArcSecond, double rotationYArcSecond,
1470         double rotationZArcSecond, double scaleDifferencePPM,
1471         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1472 
1473     PROJ_DLL static TransformationNNPtr createCoordinateFrameRotation(
1474         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1475         const crs::CRSNNPtr &targetCRSIn, double translationXMetre,
1476         double translationYMetre, double translationZMetre,
1477         double rotationXArcSecond, double rotationYArcSecond,
1478         double rotationZArcSecond, double scaleDifferencePPM,
1479         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1480 
1481     PROJ_DLL static TransformationNNPtr createTimeDependentPositionVector(
1482         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1483         const crs::CRSNNPtr &targetCRSIn, double translationXMetre,
1484         double translationYMetre, double translationZMetre,
1485         double rotationXArcSecond, double rotationYArcSecond,
1486         double rotationZArcSecond, double scaleDifferencePPM,
1487         double rateTranslationX, double rateTranslationY,
1488         double rateTranslationZ, double rateRotationX, double rateRotationY,
1489         double rateRotationZ, double rateScaleDifference,
1490         double referenceEpochYear,
1491         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1492 
1493     PROJ_DLL static TransformationNNPtr
1494     createTimeDependentCoordinateFrameRotation(
1495         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1496         const crs::CRSNNPtr &targetCRSIn, double translationXMetre,
1497         double translationYMetre, double translationZMetre,
1498         double rotationXArcSecond, double rotationYArcSecond,
1499         double rotationZArcSecond, double scaleDifferencePPM,
1500         double rateTranslationX, double rateTranslationY,
1501         double rateTranslationZ, double rateRotationX, double rateRotationY,
1502         double rateRotationZ, double rateScaleDifference,
1503         double referenceEpochYear,
1504         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1505 
1506     PROJ_DLL static TransformationNNPtr createTOWGS84(
1507         const crs::CRSNNPtr &sourceCRSIn,
1508         const std::vector<double> &TOWGS84Parameters); // throw InvalidOperation
1509 
1510     PROJ_DLL static TransformationNNPtr createNTv2(
1511         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1512         const crs::CRSNNPtr &targetCRSIn, const std::string &filename,
1513         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1514 
1515     PROJ_DLL static TransformationNNPtr createMolodensky(
1516         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1517         const crs::CRSNNPtr &targetCRSIn, double translationXMetre,
1518         double translationYMetre, double translationZMetre,
1519         double semiMajorAxisDifferenceMetre, double flattingDifference,
1520         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1521 
1522     PROJ_DLL static TransformationNNPtr createAbridgedMolodensky(
1523         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1524         const crs::CRSNNPtr &targetCRSIn, double translationXMetre,
1525         double translationYMetre, double translationZMetre,
1526         double semiMajorAxisDifferenceMetre, double flattingDifference,
1527         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1528 
1529     PROJ_DLL static TransformationNNPtr
1530     createGravityRelatedHeightToGeographic3D(
1531         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1532         const crs::CRSNNPtr &targetCRSIn, const crs::CRSPtr &interpolationCRSIn,
1533         const std::string &filename,
1534         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1535 
1536     PROJ_DLL static TransformationNNPtr createVERTCON(
1537         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1538         const crs::CRSNNPtr &targetCRSIn, const std::string &filename,
1539         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1540 
1541     PROJ_DLL static TransformationNNPtr createLongitudeRotation(
1542         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1543         const crs::CRSNNPtr &targetCRSIn, const common::Angle &offset);
1544 
1545     PROJ_DLL static TransformationNNPtr createGeographic2DOffsets(
1546         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1547         const crs::CRSNNPtr &targetCRSIn, const common::Angle &offsetLat,
1548         const common::Angle &offsetLon,
1549         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1550 
1551     PROJ_DLL static TransformationNNPtr createGeographic3DOffsets(
1552         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1553         const crs::CRSNNPtr &targetCRSIn, const common::Angle &offsetLat,
1554         const common::Angle &offsetLon, const common::Length &offsetHeight,
1555         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1556 
1557     PROJ_DLL static TransformationNNPtr createGeographic2DWithHeightOffsets(
1558         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1559         const crs::CRSNNPtr &targetCRSIn, const common::Angle &offsetLat,
1560         const common::Angle &offsetLon, const common::Length &offsetHeight,
1561         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1562 
1563     PROJ_DLL static TransformationNNPtr createVerticalOffset(
1564         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1565         const crs::CRSNNPtr &targetCRSIn, const common::Length &offsetHeight,
1566         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1567 
1568     PROJ_DLL TransformationNNPtr substitutePROJAlternativeGridNames(
1569         io::DatabaseContextNNPtr databaseContext) const;
1570 
1571     PROJ_DLL static TransformationNNPtr createChangeVerticalUnit(
1572         const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
1573         const crs::CRSNNPtr &targetCRSIn, const common::Scale &factor,
1574         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1575 
1576     PROJ_PRIVATE :
1577         //! @cond Doxygen_Suppress
1578         PROJ_INTERNAL const std::string &
1579         getNTv2Filename() const;
1580 
1581     PROJ_FOR_TEST std::vector<double>
1582     getTOWGS84Parameters() const; // throw(io::FormattingException)
1583 
1584     PROJ_INTERNAL const std::string &getHeightToGeographic3DFilename() const;
1585 
1586     PROJ_INTERNAL bool isLongitudeRotation() const;
1587 
1588     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
1589         const override; // throw(io::FormattingException)
1590 
1591     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
1592         const override; // throw(FormattingException)
1593 
1594     PROJ_INTERNAL TransformationNNPtr shallowClone() const;
1595 
1596     PROJ_INTERNAL TransformationNNPtr
1597     promoteTo3D(const std::string &newName,
1598                 const io::DatabaseContextPtr &dbContext) const;
1599 
1600     PROJ_INTERNAL TransformationNNPtr
1601     demoteTo2D(const std::string &newName,
1602                const io::DatabaseContextPtr &dbContext) const;
1603 
1604     //! @endcond
1605 
1606   protected:
1607     PROJ_INTERNAL Transformation(
1608         const crs::CRSNNPtr &sourceCRSIn, const crs::CRSNNPtr &targetCRSIn,
1609         const crs::CRSPtr &interpolationCRSIn,
1610         const OperationMethodNNPtr &methodIn,
1611         const std::vector<GeneralParameterValueNNPtr> &values,
1612         const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies);
1613     PROJ_INTERNAL Transformation(const Transformation &other);
1614     INLINED_MAKE_SHARED
1615 
1616     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
1617         const override; // throw(FormattingException)
1618 
1619     PROJ_FRIEND(CoordinateOperationFactory);
1620     PROJ_INTERNAL TransformationNNPtr inverseAsTransformation() const;
1621 
1622     PROJ_INTERNAL CoordinateOperationNNPtr _shallowClone() const override;
1623 
1624   private:
1625     PROJ_OPAQUE_PRIVATE_DATA
1626 };
1627 
1628 // ---------------------------------------------------------------------------
1629 
1630 class PointMotionOperation;
1631 /** Shared pointer of PointMotionOperation */
1632 using PointMotionOperationPtr = std::shared_ptr<PointMotionOperation>;
1633 /** Non-null shared pointer of PointMotionOperation */
1634 using PointMotionOperationNNPtr = util::nn<PointMotionOperationPtr>;
1635 
1636 /** \brief A mathematical operation that describes the change of coordinate
1637  * values within one coordinate reference system due to the motion of the
1638  * point between one coordinate epoch and another coordinate epoch.
1639  *
1640  * The motion is due to tectonic plate movement or deformation.
1641  *
1642  * \remark Implements PointMotionOperation from \ref ISO_19111_2019
1643  */
1644 class PROJ_GCC_DLL PointMotionOperation : public SingleOperation {
1645   public:
1646     // TODO
1647     //! @cond Doxygen_Suppress
1648     PROJ_DLL ~PointMotionOperation() override;
1649     //! @endcond
1650 
1651   private:
1652     PointMotionOperation(const PointMotionOperation &) = delete;
1653 };
1654 
1655 // ---------------------------------------------------------------------------
1656 
1657 class ConcatenatedOperation;
1658 /** Shared pointer of ConcatenatedOperation */
1659 using ConcatenatedOperationPtr = std::shared_ptr<ConcatenatedOperation>;
1660 /** Non-null shared pointer of ConcatenatedOperation */
1661 using ConcatenatedOperationNNPtr = util::nn<ConcatenatedOperationPtr>;
1662 
1663 /** \brief An ordered sequence of two or more single coordinate operations
1664  * (SingleOperation).
1665  *
1666  * The sequence of coordinate operations is constrained by the requirement
1667  * that
1668  * the source coordinate reference system of step n+1 shall be the same as
1669  * the target coordinate reference system of step n.
1670  *
1671  * \remark Implements ConcatenatedOperation from \ref ISO_19111_2019
1672  */
1673 class PROJ_GCC_DLL ConcatenatedOperation final : public CoordinateOperation {
1674   public:
1675     //! @cond Doxygen_Suppress
1676     PROJ_DLL ~ConcatenatedOperation() override;
1677     //! @endcond
1678 
1679     PROJ_DLL const std::vector<CoordinateOperationNNPtr> &operations() const;
1680 
1681     PROJ_DLL CoordinateOperationNNPtr inverse() const override;
1682 
1683     PROJ_DLL static ConcatenatedOperationNNPtr
1684     create(const util::PropertyMap &properties,
1685            const std::vector<CoordinateOperationNNPtr> &operationsIn,
1686            const std::vector<metadata::PositionalAccuracyNNPtr>
1687                &accuracies); // throw InvalidOperation
1688 
1689     PROJ_DLL static CoordinateOperationNNPtr createComputeMetadata(
1690         const std::vector<CoordinateOperationNNPtr> &operationsIn,
1691         bool checkExtent); // throw InvalidOperation
1692 
1693     PROJ_DLL std::set<GridDescription>
1694     gridsNeeded(const io::DatabaseContextPtr &databaseContext,
1695                 bool considerKnownGridsAsAvailable) const override;
1696 
1697     PROJ_PRIVATE :
1698 
1699         //! @cond Doxygen_Suppress
1700         PROJ_INTERNAL void
1701         _exportToWKT(io::WKTFormatter *formatter)
1702             const override; // throw(io::FormattingException)
1703 
1704     PROJ_INTERNAL bool _isEquivalentTo(
1705         const util::IComparable *other,
1706         util::IComparable::Criterion criterion =
1707             util::IComparable::Criterion::STRICT,
1708         const io::DatabaseContextPtr &dbContext = nullptr) const override;
1709 
1710     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
1711         const override; // throw(FormattingException)
1712 
1713     PROJ_INTERNAL static void
1714     fixStepsDirection(const crs::CRSNNPtr &concatOpSourceCRS,
1715                       const crs::CRSNNPtr &concatOpTargetCRS,
1716                       std::vector<CoordinateOperationNNPtr> &operationsInOut);
1717     //! @endcond
1718 
1719   protected:
1720     PROJ_INTERNAL ConcatenatedOperation(const ConcatenatedOperation &other);
1721     PROJ_INTERNAL explicit ConcatenatedOperation(
1722         const std::vector<CoordinateOperationNNPtr> &operationsIn);
1723 
1724     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
1725         const override; // throw(FormattingException)
1726 
1727     PROJ_INTERNAL CoordinateOperationNNPtr _shallowClone() const override;
1728 
1729     INLINED_MAKE_SHARED
1730 
1731   private:
1732     PROJ_OPAQUE_PRIVATE_DATA
1733     ConcatenatedOperation &
1734     operator=(const ConcatenatedOperation &other) = delete;
1735 };
1736 
1737 // ---------------------------------------------------------------------------
1738 
1739 class CoordinateOperationContext;
1740 /** Unique pointer of CoordinateOperationContext */
1741 using CoordinateOperationContextPtr =
1742     std::unique_ptr<CoordinateOperationContext>;
1743 /** Non-null unique pointer of CoordinateOperationContext */
1744 using CoordinateOperationContextNNPtr = util::nn<CoordinateOperationContextPtr>;
1745 
1746 /** \brief Context in which a coordinate operation is to be used.
1747  *
1748  * \remark Implements [CoordinateOperationFactory
1749  * https://sis.apache.org/apidocs/org/apache/sis/referencing/operation/CoordinateOperationContext.html]
1750  * from
1751  * Apache SIS
1752  */
1753 
1754 class PROJ_GCC_DLL CoordinateOperationContext {
1755   public:
1756     //! @cond Doxygen_Suppress
1757     PROJ_DLL virtual ~CoordinateOperationContext();
1758     //! @endcond
1759 
1760     PROJ_DLL const io::AuthorityFactoryPtr &getAuthorityFactory() const;
1761 
1762     PROJ_DLL const metadata::ExtentPtr &getAreaOfInterest() const;
1763 
1764     PROJ_DLL void setAreaOfInterest(const metadata::ExtentPtr &extent);
1765 
1766     PROJ_DLL double getDesiredAccuracy() const;
1767 
1768     PROJ_DLL void setDesiredAccuracy(double accuracy);
1769 
1770     PROJ_DLL void setAllowBallparkTransformations(bool allow);
1771 
1772     PROJ_DLL bool getAllowBallparkTransformations() const;
1773 
1774     /** Specify how source and target CRS extent should be used to restrict
1775      * candidate operations (only taken into account if no explicit area of
1776      * interest is specified. */
1777     enum class SourceTargetCRSExtentUse {
1778         /** Ignore CRS extent */
1779         NONE,
1780         /** Test coordinate operation extent against both CRS extent. */
1781         BOTH,
1782         /** Test coordinate operation extent against the intersection of both
1783            CRS extent. */
1784         INTERSECTION,
1785         /** Test coordinate operation against the smallest of both CRS extent.
1786          */
1787         SMALLEST,
1788     };
1789 
1790     PROJ_DLL void setSourceAndTargetCRSExtentUse(SourceTargetCRSExtentUse use);
1791 
1792     PROJ_DLL SourceTargetCRSExtentUse getSourceAndTargetCRSExtentUse() const;
1793 
1794     /** Spatial criterion to restrict candidate operations. */
1795     enum class SpatialCriterion {
1796         /** The area of validity of transforms should strictly contain the
1797          * are of interest. */
1798         STRICT_CONTAINMENT,
1799 
1800         /** The area of validity of transforms should at least intersect the
1801          * area of interest. */
1802         PARTIAL_INTERSECTION
1803     };
1804 
1805     PROJ_DLL void setSpatialCriterion(SpatialCriterion criterion);
1806 
1807     PROJ_DLL SpatialCriterion getSpatialCriterion() const;
1808 
1809     PROJ_DLL void setUsePROJAlternativeGridNames(bool usePROJNames);
1810 
1811     PROJ_DLL bool getUsePROJAlternativeGridNames() const;
1812 
1813     PROJ_DLL void setDiscardSuperseded(bool discard);
1814 
1815     PROJ_DLL bool getDiscardSuperseded() const;
1816 
1817     /** Describe how grid availability is used. */
1818     enum class GridAvailabilityUse {
1819         /** Grid availability is only used for sorting results. Operations
1820          * where some grids are missing will be sorted last. */
1821         USE_FOR_SORTING,
1822 
1823         /** Completely discard an operation if a required grid is missing. */
1824         DISCARD_OPERATION_IF_MISSING_GRID,
1825 
1826         /** Ignore grid availability at all. Results will be presented as if
1827          * all grids were available. */
1828         IGNORE_GRID_AVAILABILITY,
1829 
1830         /** Results will be presented as if grids known to PROJ (that is
1831         * registered in the grid_alternatives table of its database) were
1832         * available. Used typically when networking is enabled.
1833         */
1834         KNOWN_AVAILABLE,
1835     };
1836 
1837     PROJ_DLL void setGridAvailabilityUse(GridAvailabilityUse use);
1838 
1839     PROJ_DLL GridAvailabilityUse getGridAvailabilityUse() const;
1840 
1841     /** Describe if and how intermediate CRS should be used */
1842     enum class IntermediateCRSUse {
1843         /** Always search for intermediate CRS. */
1844         ALWAYS,
1845 
1846         /** Only attempt looking for intermediate CRS if there is no direct
1847          * transformation available. */
1848         IF_NO_DIRECT_TRANSFORMATION,
1849 
1850         /* Do not attempt looking for intermediate CRS. */
1851         NEVER,
1852     };
1853 
1854     PROJ_DLL void setAllowUseIntermediateCRS(IntermediateCRSUse use);
1855 
1856     PROJ_DLL IntermediateCRSUse getAllowUseIntermediateCRS() const;
1857 
1858     PROJ_DLL void
1859     setIntermediateCRS(const std::vector<std::pair<std::string, std::string>>
1860                            &intermediateCRSAuthCodes);
1861 
1862     PROJ_DLL const std::vector<std::pair<std::string, std::string>> &
1863     getIntermediateCRS() const;
1864 
1865     PROJ_DLL static CoordinateOperationContextNNPtr
1866     create(const io::AuthorityFactoryPtr &authorityFactory,
1867            const metadata::ExtentPtr &extent, double accuracy);
1868 
1869   protected:
1870     PROJ_INTERNAL CoordinateOperationContext();
1871     INLINED_MAKE_UNIQUE
1872 
1873   private:
1874     PROJ_OPAQUE_PRIVATE_DATA
1875 };
1876 
1877 // ---------------------------------------------------------------------------
1878 
1879 class CoordinateOperationFactory;
1880 /** Unique pointer of CoordinateOperationFactory */
1881 using CoordinateOperationFactoryPtr =
1882     std::unique_ptr<CoordinateOperationFactory>;
1883 /** Non-null unique pointer of CoordinateOperationFactory */
1884 using CoordinateOperationFactoryNNPtr = util::nn<CoordinateOperationFactoryPtr>;
1885 
1886 /** \brief Creates coordinate operations. This factory is capable to find
1887  * coordinate transformations or conversions between two coordinate
1888  * reference
1889  * systems.
1890  *
1891  * \remark Implements (partially) CoordinateOperationFactory from \ref
1892  * GeoAPI
1893  */
1894 class PROJ_GCC_DLL CoordinateOperationFactory {
1895   public:
1896     //! @cond Doxygen_Suppress
1897     PROJ_DLL virtual ~CoordinateOperationFactory();
1898     //! @endcond
1899 
1900     PROJ_DLL CoordinateOperationPtr createOperation(
1901         const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS) const;
1902 
1903     PROJ_DLL std::vector<CoordinateOperationNNPtr>
1904     createOperations(const crs::CRSNNPtr &sourceCRS,
1905                      const crs::CRSNNPtr &targetCRS,
1906                      const CoordinateOperationContextNNPtr &context) const;
1907 
1908     PROJ_DLL static CoordinateOperationFactoryNNPtr create();
1909 
1910   protected:
1911     PROJ_INTERNAL CoordinateOperationFactory();
1912     INLINED_MAKE_UNIQUE
1913 
1914   private:
1915     PROJ_OPAQUE_PRIVATE_DATA
1916 };
1917 
1918 } // namespace operation
1919 
1920 NS_PROJ_END
1921 
1922 #endif //  COORDINATEOPERATION_HH_INCLUDED
1923