/src/gdal/proj/src/iso19111/operation/parametervalue.cpp
Line | Count | Source (jump to first uncovered line) |
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 FROM_PROJ_CPP |
30 | | #define FROM_PROJ_CPP |
31 | | #endif |
32 | | |
33 | | #include "proj/common.hpp" |
34 | | #include "proj/coordinateoperation.hpp" |
35 | | #include "proj/util.hpp" |
36 | | |
37 | | #include "proj/internal/internal.hpp" |
38 | | |
39 | | #include <cassert> |
40 | | #include <cstring> |
41 | | #include <memory> |
42 | | #include <string> |
43 | | #include <vector> |
44 | | |
45 | | using namespace NS_PROJ::internal; |
46 | | |
47 | | // --------------------------------------------------------------------------- |
48 | | |
49 | | NS_PROJ_START |
50 | | namespace operation { |
51 | | |
52 | | // --------------------------------------------------------------------------- |
53 | | |
54 | | //! @cond Doxygen_Suppress |
55 | | struct ParameterValue::Private { |
56 | | ParameterValue::Type type_{ParameterValue::Type::STRING}; |
57 | | std::unique_ptr<common::Measure> measure_{}; |
58 | | std::unique_ptr<std::string> stringValue_{}; |
59 | | int integerValue_{}; |
60 | | bool booleanValue_{}; |
61 | | |
62 | | explicit Private(const common::Measure &valueIn) |
63 | 8.04M | : type_(ParameterValue::Type::MEASURE), |
64 | 8.04M | measure_(std::make_unique<common::Measure>(valueIn)) {} |
65 | | |
66 | | Private(const std::string &stringValueIn, ParameterValue::Type typeIn) |
67 | 275k | : type_(typeIn), |
68 | 275k | stringValue_(std::make_unique<std::string>(stringValueIn)) {} |
69 | | |
70 | | explicit Private(int integerValueIn) |
71 | 287 | : type_(ParameterValue::Type::INTEGER), integerValue_(integerValueIn) {} |
72 | | |
73 | | explicit Private(bool booleanValueIn) |
74 | 0 | : type_(ParameterValue::Type::BOOLEAN), booleanValue_(booleanValueIn) {} |
75 | | }; |
76 | | //! @endcond |
77 | | |
78 | | // --------------------------------------------------------------------------- |
79 | | |
80 | | //! @cond Doxygen_Suppress |
81 | 8.31M | ParameterValue::~ParameterValue() = default; |
82 | | //! @endcond |
83 | | |
84 | | // --------------------------------------------------------------------------- |
85 | | |
86 | | ParameterValue::ParameterValue(const common::Measure &measureIn) |
87 | 8.04M | : d(std::make_unique<Private>(measureIn)) {} |
88 | | |
89 | | // --------------------------------------------------------------------------- |
90 | | |
91 | | ParameterValue::ParameterValue(const std::string &stringValueIn, |
92 | | ParameterValue::Type typeIn) |
93 | 275k | : d(std::make_unique<Private>(stringValueIn, typeIn)) {} |
94 | | |
95 | | // --------------------------------------------------------------------------- |
96 | | |
97 | | ParameterValue::ParameterValue(int integerValueIn) |
98 | 287 | : d(std::make_unique<Private>(integerValueIn)) {} |
99 | | |
100 | | // --------------------------------------------------------------------------- |
101 | | |
102 | | ParameterValue::ParameterValue(bool booleanValueIn) |
103 | 0 | : d(std::make_unique<Private>(booleanValueIn)) {} |
104 | | |
105 | | // --------------------------------------------------------------------------- |
106 | | |
107 | | /** \brief Instantiate a ParameterValue from a Measure (i.e. a value associated |
108 | | * with a |
109 | | * unit) |
110 | | * |
111 | | * @return a new ParameterValue. |
112 | | */ |
113 | 8.04M | ParameterValueNNPtr ParameterValue::create(const common::Measure &measureIn) { |
114 | 8.04M | return ParameterValue::nn_make_shared<ParameterValue>(measureIn); |
115 | 8.04M | } |
116 | | |
117 | | // --------------------------------------------------------------------------- |
118 | | |
119 | | /** \brief Instantiate a ParameterValue from a string value. |
120 | | * |
121 | | * @return a new ParameterValue. |
122 | | */ |
123 | 0 | ParameterValueNNPtr ParameterValue::create(const char *stringValueIn) { |
124 | 0 | return ParameterValue::nn_make_shared<ParameterValue>( |
125 | 0 | std::string(stringValueIn), ParameterValue::Type::STRING); |
126 | 0 | } |
127 | | |
128 | | // --------------------------------------------------------------------------- |
129 | | |
130 | | /** \brief Instantiate a ParameterValue from a string value. |
131 | | * |
132 | | * @return a new ParameterValue. |
133 | | */ |
134 | 2.61k | ParameterValueNNPtr ParameterValue::create(const std::string &stringValueIn) { |
135 | 2.61k | return ParameterValue::nn_make_shared<ParameterValue>( |
136 | 2.61k | stringValueIn, ParameterValue::Type::STRING); |
137 | 2.61k | } |
138 | | |
139 | | // --------------------------------------------------------------------------- |
140 | | |
141 | | /** \brief Instantiate a ParameterValue from a filename. |
142 | | * |
143 | | * @return a new ParameterValue. |
144 | | */ |
145 | | ParameterValueNNPtr |
146 | 273k | ParameterValue::createFilename(const std::string &stringValueIn) { |
147 | 273k | return ParameterValue::nn_make_shared<ParameterValue>( |
148 | 273k | stringValueIn, ParameterValue::Type::FILENAME); |
149 | 273k | } |
150 | | |
151 | | // --------------------------------------------------------------------------- |
152 | | |
153 | | /** \brief Instantiate a ParameterValue from a integer value. |
154 | | * |
155 | | * @return a new ParameterValue. |
156 | | */ |
157 | 287 | ParameterValueNNPtr ParameterValue::create(int integerValueIn) { |
158 | 287 | return ParameterValue::nn_make_shared<ParameterValue>(integerValueIn); |
159 | 287 | } |
160 | | |
161 | | // --------------------------------------------------------------------------- |
162 | | |
163 | | /** \brief Instantiate a ParameterValue from a boolean value. |
164 | | * |
165 | | * @return a new ParameterValue. |
166 | | */ |
167 | 0 | ParameterValueNNPtr ParameterValue::create(bool booleanValueIn) { |
168 | 0 | return ParameterValue::nn_make_shared<ParameterValue>(booleanValueIn); |
169 | 0 | } |
170 | | |
171 | | // --------------------------------------------------------------------------- |
172 | | |
173 | | /** \brief Returns the type of a parameter value. |
174 | | * |
175 | | * @return the type. |
176 | | */ |
177 | 9.84M | const ParameterValue::Type &ParameterValue::type() PROJ_PURE_DEFN { |
178 | 9.84M | return d->type_; |
179 | 9.84M | } |
180 | | |
181 | | // --------------------------------------------------------------------------- |
182 | | |
183 | | /** \brief Returns the value as a Measure (assumes type() == Type::MEASURE) |
184 | | * @return the value as a Measure. |
185 | | */ |
186 | 8.28M | const common::Measure &ParameterValue::value() PROJ_PURE_DEFN { |
187 | 8.28M | return *d->measure_; |
188 | 8.28M | } |
189 | | |
190 | | // --------------------------------------------------------------------------- |
191 | | |
192 | | /** \brief Returns the value as a string (assumes type() == Type::STRING) |
193 | | * @return the value as a string. |
194 | | */ |
195 | 37.7k | const std::string &ParameterValue::stringValue() PROJ_PURE_DEFN { |
196 | 37.7k | return *d->stringValue_; |
197 | 37.7k | } |
198 | | |
199 | | // --------------------------------------------------------------------------- |
200 | | |
201 | | /** \brief Returns the value as a filename (assumes type() == Type::FILENAME) |
202 | | * @return the value as a filename. |
203 | | */ |
204 | 353k | const std::string &ParameterValue::valueFile() PROJ_PURE_DEFN { |
205 | 353k | return *d->stringValue_; |
206 | 353k | } |
207 | | |
208 | | // --------------------------------------------------------------------------- |
209 | | |
210 | | /** \brief Returns the value as a integer (assumes type() == Type::INTEGER) |
211 | | * @return the value as a integer. |
212 | | */ |
213 | 206 | int ParameterValue::integerValue() PROJ_PURE_DEFN { return d->integerValue_; } |
214 | | |
215 | | // --------------------------------------------------------------------------- |
216 | | |
217 | | /** \brief Returns the value as a boolean (assumes type() == Type::BOOLEAN) |
218 | | * @return the value as a boolean. |
219 | | */ |
220 | 0 | bool ParameterValue::booleanValue() PROJ_PURE_DEFN { return d->booleanValue_; } |
221 | | |
222 | | // --------------------------------------------------------------------------- |
223 | | |
224 | | //! @cond Doxygen_Suppress |
225 | 1.93M | void ParameterValue::_exportToWKT(io::WKTFormatter *formatter) const { |
226 | 1.93M | const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; |
227 | | |
228 | 1.93M | const auto &l_type = type(); |
229 | 1.93M | if (l_type == Type::MEASURE) { |
230 | 1.89M | const auto &l_value = value(); |
231 | 1.89M | if (formatter->abridgedTransformation()) { |
232 | 60.7k | const auto &unit = l_value.unit(); |
233 | 60.7k | const auto &unitType = unit.type(); |
234 | 60.7k | if (unitType == common::UnitOfMeasure::Type::LINEAR) { |
235 | 31.7k | formatter->add(l_value.getSIValue()); |
236 | 31.7k | } else if (unitType == common::UnitOfMeasure::Type::ANGULAR) { |
237 | 21.7k | formatter->add( |
238 | 21.7k | l_value.convertToUnit(common::UnitOfMeasure::ARC_SECOND)); |
239 | 21.7k | } else if (unit == common::UnitOfMeasure::PARTS_PER_MILLION) { |
240 | 7.25k | formatter->add(1.0 + l_value.value() * 1e-6); |
241 | 7.25k | } else { |
242 | 0 | formatter->add(l_value.value()); |
243 | 0 | } |
244 | 1.83M | } else { |
245 | 1.83M | const auto &unit = l_value.unit(); |
246 | 1.83M | if (isWKT2) { |
247 | 512k | formatter->add(l_value.value()); |
248 | 1.32M | } else { |
249 | | // In WKT1, as we don't output the natural unit, output to the |
250 | | // registered linear / angular unit. |
251 | 1.32M | const auto &unitType = unit.type(); |
252 | 1.32M | if (unitType == common::UnitOfMeasure::Type::LINEAR) { |
253 | 517k | const auto &targetUnit = *(formatter->axisLinearUnit()); |
254 | 517k | if (targetUnit.conversionToSI() == 0.0) { |
255 | 368 | throw io::FormattingException( |
256 | 368 | "cannot convert value to target linear unit"); |
257 | 368 | } |
258 | 517k | formatter->add(l_value.convertToUnit(targetUnit)); |
259 | 804k | } else if (unitType == common::UnitOfMeasure::Type::ANGULAR) { |
260 | 627k | const auto &targetUnit = *(formatter->axisAngularUnit()); |
261 | 627k | if (targetUnit.conversionToSI() == 0.0) { |
262 | 27 | throw io::FormattingException( |
263 | 27 | "cannot convert value to target angular unit"); |
264 | 27 | } |
265 | 627k | formatter->add(l_value.convertToUnit(targetUnit)); |
266 | 627k | } else { |
267 | 176k | formatter->add(l_value.getSIValue()); |
268 | 176k | } |
269 | 1.32M | } |
270 | 1.83M | if (isWKT2 && unit != common::UnitOfMeasure::NONE) { |
271 | 494k | if (!formatter |
272 | 494k | ->primeMeridianOrParameterUnitOmittedIfSameAsAxis() || |
273 | 494k | (unit != common::UnitOfMeasure::SCALE_UNITY && |
274 | 0 | unit != *(formatter->axisLinearUnit()) && |
275 | 494k | unit != *(formatter->axisAngularUnit()))) { |
276 | 494k | unit._exportToWKT(formatter); |
277 | 494k | } |
278 | 494k | } |
279 | 1.83M | } |
280 | 1.89M | } else if (l_type == Type::STRING || l_type == Type::FILENAME) { |
281 | 35.5k | formatter->addQuotedString(stringValue()); |
282 | 35.5k | } else if (l_type == Type::INTEGER) { |
283 | 0 | formatter->add(integerValue()); |
284 | 0 | } else { |
285 | 0 | throw io::FormattingException("boolean parameter value not handled"); |
286 | 0 | } |
287 | 1.93M | } |
288 | | //! @endcond |
289 | | |
290 | | // --------------------------------------------------------------------------- |
291 | | |
292 | | //! @cond Doxygen_Suppress |
293 | | bool ParameterValue::_isEquivalentTo(const util::IComparable *other, |
294 | | util::IComparable::Criterion criterion, |
295 | 231k | const io::DatabaseContextPtr &) const { |
296 | 231k | auto otherPV = dynamic_cast<const ParameterValue *>(other); |
297 | 231k | if (otherPV == nullptr) { |
298 | 0 | return false; |
299 | 0 | } |
300 | 231k | if (type() != otherPV->type()) { |
301 | 0 | return false; |
302 | 0 | } |
303 | 231k | switch (type()) { |
304 | 230k | case Type::MEASURE: { |
305 | 230k | return value()._isEquivalentTo(otherPV->value(), criterion, 2e-10); |
306 | 0 | } |
307 | | |
308 | 0 | case Type::STRING: |
309 | 1.12k | case Type::FILENAME: { |
310 | 1.12k | return stringValue() == otherPV->stringValue(); |
311 | 0 | } |
312 | | |
313 | 0 | case Type::INTEGER: { |
314 | 0 | return integerValue() == otherPV->integerValue(); |
315 | 0 | } |
316 | | |
317 | 0 | case Type::BOOLEAN: { |
318 | 0 | return booleanValue() == otherPV->booleanValue(); |
319 | 0 | } |
320 | | |
321 | 0 | default: { |
322 | 0 | assert(false); |
323 | 0 | break; |
324 | 0 | } |
325 | 231k | } |
326 | 0 | return true; |
327 | 231k | } |
328 | | //! @endcond |
329 | | // --------------------------------------------------------------------------- |
330 | | |
331 | | } // namespace operation |
332 | | |
333 | | NS_PROJ_END |