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 COMMON_HH_INCLUDED
30 #define COMMON_HH_INCLUDED
31 
32 #include <memory>
33 #include <string>
34 #include <vector>
35 
36 #include "io.hpp"
37 #include "metadata.hpp"
38 #include "util.hpp"
39 
40 NS_PROJ_START
41 
42 /** osgeo.proj.common namespace
43  *
44  * \brief Common classes.
45  */
46 namespace common {
47 
48 // ---------------------------------------------------------------------------
49 
50 class UnitOfMeasure;
51 /** Shared pointer of UnitOfMeasure. */
52 using UnitOfMeasurePtr = std::shared_ptr<UnitOfMeasure>;
53 /** Non-null shared pointer of UnitOfMeasure. */
54 using UnitOfMeasureNNPtr = util::nn<UnitOfMeasurePtr>;
55 
56 /** \brief Unit of measure.
57  *
58  * This is a mutable object.
59  */
60 class PROJ_GCC_DLL UnitOfMeasure : public util::BaseObject {
61   public:
62     /** \brief Type of unit of measure. */
63     enum class PROJ_MSVC_DLL Type {
64         /** Unknown unit of measure */
65         UNKNOWN,
66         /** No unit of measure */
67         NONE,
68         /** Angular unit of measure */
69         ANGULAR,
70         /** Linear unit of measure */
71         LINEAR,
72         /** Scale unit of measure */
73         SCALE,
74         /** Time unit of measure */
75         TIME,
76         /** Parametric unit of measure */
77         PARAMETRIC,
78     };
79 
80     PROJ_DLL UnitOfMeasure(const std::string &nameIn = std::string(),
81                            double toSIIn = 1.0, Type typeIn = Type::UNKNOWN,
82                            const std::string &codeSpaceIn = std::string(),
83                            const std::string &codeIn = std::string());
84 
85     //! @cond Doxygen_Suppress
86     PROJ_DLL UnitOfMeasure(const UnitOfMeasure &other);
87     PROJ_DLL ~UnitOfMeasure() override;
88     PROJ_DLL UnitOfMeasure &operator=(const UnitOfMeasure &other);
89     PROJ_INTERNAL static UnitOfMeasureNNPtr create(const UnitOfMeasure &other);
90     //! @endcond
91 
92     PROJ_DLL const std::string &name() PROJ_PURE_DECL;
93     PROJ_DLL double conversionToSI() PROJ_PURE_DECL;
94     PROJ_DLL Type type() PROJ_PURE_DECL;
95 
96     PROJ_DLL const std::string &codeSpace() PROJ_PURE_DECL;
97     PROJ_DLL const std::string &code() PROJ_PURE_DECL;
98 
99     PROJ_DLL bool operator==(const UnitOfMeasure &other) PROJ_PURE_DECL;
100     PROJ_DLL bool operator!=(const UnitOfMeasure &other) PROJ_PURE_DECL;
101 
102     //! @cond Doxygen_Suppress
103     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter,
104                                     const std::string &unitType = std::string())
105         const; // throw(io::FormattingException)
106 
107     PROJ_INTERNAL void _exportToJSON(
108         io::JSONFormatter *formatter) const; // throw(io::FormattingException)
109 
110     PROJ_INTERNAL std::string exportToPROJString() const;
111 
112     PROJ_INTERNAL bool
113     _isEquivalentTo(const UnitOfMeasure &other,
114                     util::IComparable::Criterion criterion =
115                         util::IComparable::Criterion::STRICT) const;
116 
117     //! @endcond
118 
119     PROJ_DLL static const UnitOfMeasure NONE;
120 
121     PROJ_DLL static const UnitOfMeasure SCALE_UNITY;
122     PROJ_DLL static const UnitOfMeasure PARTS_PER_MILLION;
123     PROJ_DLL static const UnitOfMeasure PPM_PER_YEAR;
124 
125     PROJ_DLL static const UnitOfMeasure METRE;
126     PROJ_DLL static const UnitOfMeasure METRE_PER_YEAR;
127 
128     PROJ_DLL static const UnitOfMeasure RADIAN;
129     PROJ_DLL static const UnitOfMeasure MICRORADIAN;
130     PROJ_DLL static const UnitOfMeasure DEGREE;
131     PROJ_DLL static const UnitOfMeasure ARC_SECOND;
132     PROJ_DLL static const UnitOfMeasure GRAD;
133     PROJ_DLL static const UnitOfMeasure ARC_SECOND_PER_YEAR;
134 
135     PROJ_DLL static const UnitOfMeasure SECOND;
136     PROJ_DLL static const UnitOfMeasure YEAR;
137 
138   private:
139     PROJ_OPAQUE_PRIVATE_DATA
140 };
141 
142 // ---------------------------------------------------------------------------
143 
144 /** \brief Numeric value associated with a UnitOfMeasure. */
145 class Measure : public util::BaseObject {
146   public:
147     PROJ_DLL Measure(double valueIn = 0.0,
148                      const UnitOfMeasure &unitIn = UnitOfMeasure());
149 
150     //! @cond Doxygen_Suppress
151     PROJ_DLL Measure(const Measure &other);
152     PROJ_DLL ~Measure();
153     //! @endcond
154 
155     PROJ_DLL const UnitOfMeasure &unit() PROJ_PURE_DECL;
156     PROJ_DLL double getSIValue() PROJ_PURE_DECL;
157     PROJ_DLL double value() PROJ_PURE_DECL;
158 
159     PROJ_DLL double
160     convertToUnit(const UnitOfMeasure &otherUnit) PROJ_PURE_DECL;
161 
162     PROJ_DLL bool operator==(const Measure &other) PROJ_PURE_DECL;
163 
164     /** Default maximum resulative error. */
165     static constexpr double DEFAULT_MAX_REL_ERROR = 1e-10;
166 
167     PROJ_INTERNAL bool
168     _isEquivalentTo(const Measure &other,
169                     util::IComparable::Criterion criterion =
170                         util::IComparable::Criterion::STRICT,
171                     double maxRelativeError = DEFAULT_MAX_REL_ERROR) const;
172 
173   private:
174     PROJ_OPAQUE_PRIVATE_DATA
175     Measure &operator=(const Measure &) = delete;
176 };
177 
178 // ---------------------------------------------------------------------------
179 
180 /** \brief Numeric value, without a physical unit of measure. */
181 class Scale : public Measure {
182   public:
183     PROJ_DLL explicit Scale(double valueIn = 0.0);
184     PROJ_DLL explicit Scale(double valueIn, const UnitOfMeasure &unitIn);
185 
186     //! @cond Doxygen_Suppress
Scale(const Measure & other)187     explicit Scale(const Measure &other) : Scale(other.value(), other.unit()) {}
188     PROJ_DLL Scale(const Scale &other);
189     PROJ_DLL ~Scale() override;
190     //! @endcond
191 
192   protected:
193     PROJ_FRIEND_OPTIONAL(Scale);
194     Scale &operator=(const Scale &) = delete;
195 };
196 
197 // ---------------------------------------------------------------------------
198 
199 /** \brief Numeric value, with a angular unit of measure. */
200 class Angle : public Measure {
201   public:
202     PROJ_DLL explicit Angle(double valueIn = 0.0);
203     PROJ_DLL Angle(double valueIn, const UnitOfMeasure &unitIn);
204 
205     //! @cond Doxygen_Suppress
Angle(const Measure & other)206     explicit Angle(const Measure &other) : Angle(other.value(), other.unit()) {}
207     PROJ_DLL Angle(const Angle &other);
208     PROJ_DLL ~Angle() override;
209     //! @endcond
210 
211   protected:
212     PROJ_FRIEND_OPTIONAL(Angle);
213     Angle &operator=(const Angle &) = delete;
214 };
215 
216 // ---------------------------------------------------------------------------
217 
218 /** \brief Numeric value, with a linear unit of measure. */
219 class Length : public Measure {
220   public:
221     PROJ_DLL explicit Length(double valueIn = 0.0);
222     PROJ_DLL Length(double valueIn, const UnitOfMeasure &unitIn);
223 
224     //! @cond Doxygen_Suppress
Length(const Measure & other)225     explicit Length(const Measure &other)
226         : Length(other.value(), other.unit()) {}
227     PROJ_DLL Length(const Length &other);
228     PROJ_DLL ~Length() override;
229     //! @endcond
230 
231   protected:
232     PROJ_FRIEND_OPTIONAL(Length);
233     Length &operator=(const Length &) = delete;
234 };
235 
236 // ---------------------------------------------------------------------------
237 
238 /** \brief Date-time value, as a ISO:8601 encoded string, or other string
239  * encoding */
240 class DateTime {
241   public:
242     //! @cond Doxygen_Suppress
243     PROJ_DLL DateTime(const DateTime &other);
244     PROJ_DLL ~DateTime();
245     //! @endcond
246 
247     PROJ_DLL bool isISO_8601() const;
248     PROJ_DLL std::string toString() const;
249 
250     PROJ_DLL static DateTime
251     create(const std::string &str); // may throw Exception
252 
253   protected:
254     DateTime();
255     PROJ_FRIEND_OPTIONAL(DateTime);
256     DateTime &operator=(const DateTime &other);
257 
258   private:
259     explicit DateTime(const std::string &str);
260 
261     PROJ_OPAQUE_PRIVATE_DATA
262 };
263 
264 // ---------------------------------------------------------------------------
265 
266 /** \brief Data epoch */
267 class DataEpoch {
268   public:
269     //! @cond Doxygen_Suppress
270     PROJ_DLL explicit DataEpoch(const Measure &coordinateEpochIn);
271     PROJ_DLL DataEpoch(const DataEpoch &other);
272     PROJ_DLL ~DataEpoch();
273     //! @endcond
274 
275     PROJ_DLL const Measure &coordinateEpoch() const;
276 
277   protected:
278     DataEpoch();
279     PROJ_FRIEND_OPTIONAL(DataEpoch);
280 
281   private:
282     DataEpoch &operator=(const DataEpoch &other) = delete;
283     PROJ_OPAQUE_PRIVATE_DATA
284 };
285 
286 // ---------------------------------------------------------------------------
287 
288 class IdentifiedObject;
289 /** Shared pointer of IdentifiedObject. */
290 using IdentifiedObjectPtr = std::shared_ptr<IdentifiedObject>;
291 /** Non-null shared pointer of IdentifiedObject. */
292 using IdentifiedObjectNNPtr = util::nn<IdentifiedObjectPtr>;
293 
294 /** \brief Abstract class representating a CRS-related object that has an
295  * identification.
296  *
297  * \remark Implements IdentifiedObject from \ref ISO_19111_2019
298  */
299 class PROJ_GCC_DLL IdentifiedObject : public util::BaseObject,
300                                       public util::IComparable,
301                                       public io::IWKTExportable {
302   public:
303     //! @cond Doxygen_Suppress
304     PROJ_DLL ~IdentifiedObject() override;
305     //! @endcond
306 
307     PROJ_DLL static const std::string NAME_KEY;
308     PROJ_DLL static const std::string IDENTIFIERS_KEY;
309     PROJ_DLL static const std::string ALIAS_KEY;
310     PROJ_DLL static const std::string REMARKS_KEY;
311     PROJ_DLL static const std::string DEPRECATED_KEY;
312 
313     // in practice only name().description() is used
314     PROJ_DLL const metadata::IdentifierNNPtr &name() PROJ_PURE_DECL;
315     PROJ_DLL const std::string &nameStr() PROJ_PURE_DECL;
316     PROJ_DLL const std::vector<metadata::IdentifierNNPtr> &
317     identifiers() PROJ_PURE_DECL;
318     PROJ_DLL const std::vector<util::GenericNameNNPtr> &
319     aliases() PROJ_PURE_DECL;
320     PROJ_DLL const std::string &remarks() PROJ_PURE_DECL;
321 
322     // from Apache SIS AbstractIdentifiedObject
323     PROJ_DLL bool isDeprecated() PROJ_PURE_DECL;
324 
325     // Non-standard
326     PROJ_DLL std::string alias() PROJ_PURE_DECL;
327     PROJ_DLL int getEPSGCode() PROJ_PURE_DECL;
328 
329     PROJ_PRIVATE :
330         //! @cond Doxygen_Suppress
331         void
332         formatID(io::WKTFormatter *formatter) const;
333 
334     PROJ_INTERNAL void formatID(io::JSONFormatter *formatter) const;
335 
336     PROJ_INTERNAL void formatRemarks(io::WKTFormatter *formatter) const;
337 
338     PROJ_INTERNAL void formatRemarks(io::JSONFormatter *formatter) const;
339 
340     PROJ_INTERNAL bool _isEquivalentTo(
341         const util::IComparable *other,
342         util::IComparable::Criterion criterion =
343             util::IComparable::Criterion::STRICT,
344         const io::DatabaseContextPtr &dbContext = nullptr) const override;
345 
346     PROJ_INTERNAL bool _isEquivalentTo(
347         const IdentifiedObject *other, util::IComparable::Criterion criterion =
348                                            util::IComparable::Criterion::STRICT,
349         const io::DatabaseContextPtr &dbContext = nullptr) PROJ_PURE_DECL;
350     //! @endcond
351 
352   protected:
353     PROJ_FRIEND_OPTIONAL(IdentifiedObject);
354     INLINED_MAKE_SHARED
355     IdentifiedObject();
356     IdentifiedObject(const IdentifiedObject &other);
357 
358     void setProperties(const util::PropertyMap
359                            &properties); // throw(InvalidValueTypeException)
360 
361     virtual bool hasEquivalentNameToUsingAlias(
362         const IdentifiedObject *other,
363         const io::DatabaseContextPtr &dbContext) const;
364 
365   private:
366     PROJ_OPAQUE_PRIVATE_DATA
367     IdentifiedObject &operator=(const IdentifiedObject &other) = delete;
368 };
369 
370 // ---------------------------------------------------------------------------
371 
372 class ObjectDomain;
373 /** Shared pointer of ObjectDomain. */
374 using ObjectDomainPtr = std::shared_ptr<ObjectDomain>;
375 /** Non-null shared pointer of ObjectDomain. */
376 using ObjectDomainNNPtr = util::nn<ObjectDomainPtr>;
377 
378 /** \brief The scope and validity of a CRS-related object.
379  *
380  * \remark Implements ObjectDomain from \ref ISO_19111_2019
381  */
382 class PROJ_GCC_DLL ObjectDomain : public util::BaseObject,
383                                   public util::IComparable {
384   public:
385     //! @cond Doxygen_Suppress
386     PROJ_DLL ~ObjectDomain() override;
387     //! @endcond
388 
389     // In ISO_19111:2018, scope and domain are compulsory, but in WKT2:2015,
390     // they
391     // are not necessarily both specified
392     PROJ_DLL const util::optional<std::string> &scope() PROJ_PURE_DECL;
393     PROJ_DLL const metadata::ExtentPtr &domainOfValidity() PROJ_PURE_DECL;
394 
395     PROJ_DLL static ObjectDomainNNPtr
396     create(const util::optional<std::string> &scopeIn,
397            const metadata::ExtentPtr &extent);
398 
399     PROJ_PRIVATE :
400         //! @cond Doxygen_Suppress
401         void
402         _exportToWKT(io::WKTFormatter *formatter)
403             const; // throw(io::FormattingException)
404 
405     PROJ_INTERNAL void _exportToJSON(
406         io::JSONFormatter *formatter) const; // throw(FormattingException)
407 
408     bool _isEquivalentTo(
409         const util::IComparable *other,
410         util::IComparable::Criterion criterion =
411             util::IComparable::Criterion::STRICT,
412         const io::DatabaseContextPtr &dbContext = nullptr) const override;
413     //! @endcond
414 
415   protected:
416     //! @cond Doxygen_Suppress
417     ObjectDomain(const util::optional<std::string> &scopeIn,
418                  const metadata::ExtentPtr &extent);
419     //! @endcond
420 
421     ObjectDomain(const ObjectDomain &other);
422     INLINED_MAKE_SHARED
423 
424   private:
425     PROJ_OPAQUE_PRIVATE_DATA
426     ObjectDomain &operator=(const ObjectDomain &other) = delete;
427 };
428 
429 // ---------------------------------------------------------------------------
430 
431 class ObjectUsage;
432 /** Shared pointer of ObjectUsage. */
433 using ObjectUsagePtr = std::shared_ptr<ObjectUsage>;
434 /** Non-null shared pointer of ObjectUsage. */
435 using ObjectUsageNNPtr = util::nn<ObjectUsagePtr>;
436 
437 /** \brief Abstract class of a CRS-related object that has usages.
438  *
439  * \remark Implements ObjectUsage from \ref ISO_19111_2019
440  */
441 class PROJ_GCC_DLL ObjectUsage : public IdentifiedObject {
442   public:
443     //! @cond Doxygen_Suppress
444     PROJ_DLL ~ObjectUsage() override;
445     //! @endcond
446 
447     PROJ_DLL const std::vector<ObjectDomainNNPtr> &domains() PROJ_PURE_DECL;
448 
449     PROJ_DLL static const std::string SCOPE_KEY;
450     PROJ_DLL static const std::string DOMAIN_OF_VALIDITY_KEY;
451 
452     PROJ_DLL static const std::string OBJECT_DOMAIN_KEY;
453 
454     //! @cond Doxygen_Suppress
455     bool _isEquivalentTo(
456         const util::IComparable *other,
457         util::IComparable::Criterion criterion =
458             util::IComparable::Criterion::STRICT,
459         const io::DatabaseContextPtr &dbContext = nullptr) const override;
460     //! @endcond
461 
462   protected:
463     ObjectUsage();
464     ObjectUsage(const ObjectUsage &other);
465     void setProperties(const util::PropertyMap
466                            &properties); // throw(InvalidValueTypeException)
467 
468     void baseExportToWKT(
469         io::WKTFormatter *formatter) const; // throw(io::FormattingException)
470 
471     void baseExportToJSON(
472         io::JSONFormatter *formatter) const; // throw(io::FormattingException)
473 
474   private:
475     PROJ_OPAQUE_PRIVATE_DATA
476     ObjectUsage &operator=(const ObjectUsage &other) = delete;
477 };
478 
479 } // namespace common
480 
481 NS_PROJ_END
482 
483 #endif //  COMMON_HH_INCLUDED
484