/src/PROJ/src/transformations/defmodel.hpp
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * Project: PROJ |
3 | | * Purpose: Functionality related to deformation model |
4 | | * Author: Even Rouault, <even.rouault at spatialys.com> |
5 | | * |
6 | | ****************************************************************************** |
7 | | * Copyright (c) 2020, Even Rouault, <even.rouault at spatialys.com> |
8 | | * |
9 | | * Permission is hereby granted, free of charge, to any person obtaining a |
10 | | * copy of this software and associated documentation files (the "Software"), |
11 | | * to deal in the Software without restriction, including without limitation |
12 | | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
13 | | * and/or sell copies of the Software, and to permit persons to whom the |
14 | | * Software is furnished to do so, subject to the following conditions: |
15 | | * |
16 | | * The above copyright notice and this permission notice shall be included |
17 | | * in all copies or substantial portions of the Software. |
18 | | * |
19 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
20 | | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
21 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
22 | | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
23 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
24 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
25 | | * DEALINGS IN THE SOFTWARE. |
26 | | *****************************************************************************/ |
27 | | |
28 | | /** This file implements the gridded deformation model proposol of |
29 | | * https://docs.google.com/document/d/1wiyrAmzqh8MZlzHSp3wf594Ob_M1LeFtDA5swuzvLZY |
30 | | * It is written in a generic way, independent of the rest of PROJ |
31 | | * infrastructure. |
32 | | * |
33 | | * Verbose debugging info can be turned on by setting the DEBUG_DEFMODEL macro |
34 | | */ |
35 | | |
36 | | #ifndef DEFMODEL_HPP |
37 | | #define DEFMODEL_HPP |
38 | | |
39 | | #ifdef PROJ_COMPILATION |
40 | | #include "proj/internal/include_nlohmann_json.hpp" |
41 | | #else |
42 | | #include "nlohmann/json.hpp" |
43 | | #endif |
44 | | |
45 | | #include <algorithm> |
46 | | #include <cmath> |
47 | | #include <exception> |
48 | | #include <limits> |
49 | | #include <memory> |
50 | | #include <string> |
51 | | #include <vector> |
52 | | |
53 | | #ifndef DEFORMATON_MODEL_NAMESPACE |
54 | | #define DEFORMATON_MODEL_NAMESPACE DeformationModel |
55 | | #endif |
56 | | |
57 | | #include "defmodel_exceptions.hpp" |
58 | | |
59 | | namespace DEFORMATON_MODEL_NAMESPACE { |
60 | | |
61 | | using json = nlohmann::json; |
62 | | |
63 | | // --------------------------------------------------------------------------- |
64 | | |
65 | | /** Spatial extent as a bounding box. */ |
66 | | class SpatialExtent { |
67 | | public: |
68 | | /** Parse the provided object as an extent. |
69 | | * |
70 | | * @throws ParsingException in case of error. |
71 | | */ |
72 | | static SpatialExtent parse(const json &j); |
73 | | |
74 | 0 | double minx() const { return mMinx; } |
75 | 0 | double miny() const { return mMiny; } |
76 | 0 | double maxx() const { return mMaxx; } |
77 | 0 | double maxy() const { return mMaxy; } |
78 | | |
79 | 0 | double minxNormalized(bool bIsGeographic) const { |
80 | 0 | return bIsGeographic ? mMinxRad : mMinx; |
81 | 0 | } |
82 | 0 | double minyNormalized(bool bIsGeographic) const { |
83 | 0 | return bIsGeographic ? mMinyRad : mMiny; |
84 | 0 | } |
85 | 0 | double maxxNormalized(bool bIsGeographic) const { |
86 | 0 | return bIsGeographic ? mMaxxRad : mMaxx; |
87 | 0 | } |
88 | 0 | double maxyNormalized(bool bIsGeographic) const { |
89 | 0 | return bIsGeographic ? mMaxyRad : mMaxy; |
90 | 0 | } |
91 | | |
92 | | protected: |
93 | | friend class MasterFile; |
94 | | friend class Component; |
95 | 3 | SpatialExtent() = default; |
96 | | |
97 | | private: |
98 | | double mMinx = std::numeric_limits<double>::quiet_NaN(); |
99 | | double mMiny = std::numeric_limits<double>::quiet_NaN(); |
100 | | double mMaxx = std::numeric_limits<double>::quiet_NaN(); |
101 | | double mMaxy = std::numeric_limits<double>::quiet_NaN(); |
102 | | double mMinxRad = std::numeric_limits<double>::quiet_NaN(); |
103 | | double mMinyRad = std::numeric_limits<double>::quiet_NaN(); |
104 | | double mMaxxRad = std::numeric_limits<double>::quiet_NaN(); |
105 | | double mMaxyRad = std::numeric_limits<double>::quiet_NaN(); |
106 | | }; |
107 | | |
108 | | // --------------------------------------------------------------------------- |
109 | | |
110 | | /** Epoch */ |
111 | | class Epoch { |
112 | | public: |
113 | | /** Constructor from a ISO 8601 date-time. May throw ParsingException */ |
114 | | explicit Epoch(const std::string &dt = std::string()); |
115 | | |
116 | | /** Return ISO 8601 date-time */ |
117 | 0 | const std::string &toString() const { return mDt; } |
118 | | |
119 | | /** Return decimal year */ |
120 | | double toDecimalYear() const; |
121 | | |
122 | | private: |
123 | | std::string mDt{}; |
124 | | double mDecimalYear = 0; |
125 | | }; |
126 | | |
127 | | // --------------------------------------------------------------------------- |
128 | | |
129 | | /** Component of a deformation model. */ |
130 | | class Component { |
131 | | public: |
132 | | /** Parse the provided object as a component. |
133 | | * |
134 | | * @throws ParsingException in case of error. |
135 | | */ |
136 | | static Component parse(const json &j); |
137 | | |
138 | | /** Get a text description of the component. */ |
139 | 0 | const std::string &description() const { return mDescription; } |
140 | | |
141 | | /** Get the region within which the component is defined. Outside this |
142 | | * region the component evaluates to 0. */ |
143 | 0 | const SpatialExtent &extent() const { return mSpatialExtent; } |
144 | | |
145 | | /** Get the displacement parameters defined by the component, one of |
146 | | * "none", "horizontal", "vertical", and "3d". The "none" option allows |
147 | | * for a component which defines uncertainty with different grids to those |
148 | | * defining displacement. */ |
149 | 0 | const std::string &displacementType() const { return mDisplacementType; } |
150 | | |
151 | | /** Get the uncertainty parameters defined by the component, |
152 | | * one of "none", "horizontal", "vertical", "3d". */ |
153 | 0 | const std::string &uncertaintyType() const { return mUncertaintyType; } |
154 | | |
155 | | /** Get the horizontal uncertainty to use if it is not defined explicitly |
156 | | * in the spatial model. */ |
157 | 0 | double horizontalUncertainty() const { return mHorizontalUncertainty; } |
158 | | |
159 | | /** Get the vertical uncertainty to use if it is not defined explicitly in |
160 | | * the spatial model. */ |
161 | 0 | double verticalUncertainty() const { return mVerticalUncertainty; } |
162 | | |
163 | | struct SpatialModel { |
164 | | /** Specifies the type of the spatial model data file. Initially it |
165 | | * is proposed that only "GeoTIFF" is supported. */ |
166 | | std::string type{}; |
167 | | |
168 | | /** How values in model should be interpolated. This proposal will |
169 | | * support "bilinear" and "geocentric_bilinear". */ |
170 | | std::string interpolationMethod{}; |
171 | | |
172 | | /** Specifies location of the spatial model GeoTIFF file relative to |
173 | | * the master JSON file. */ |
174 | | std::string filename{}; |
175 | | |
176 | | /** A hex encoded MD5 checksum of the grid file that can be used to |
177 | | * validate that it is the correct version of the file. */ |
178 | | std::string md5Checksum{}; |
179 | | }; |
180 | | |
181 | | /** Get the spatial model. */ |
182 | 0 | const SpatialModel &spatialModel() const { return mSpatialModel; } |
183 | | |
184 | | /** Generic type for a type function */ |
185 | | struct TimeFunction { |
186 | | std::string type{}; |
187 | | |
188 | | virtual ~TimeFunction(); |
189 | | |
190 | | virtual double evaluateAt(double dt) const = 0; |
191 | | |
192 | | protected: |
193 | 0 | TimeFunction() = default; |
194 | | }; |
195 | | struct ConstantTimeFunction : public TimeFunction { |
196 | | |
197 | | virtual double evaluateAt(double dt) const override; |
198 | | }; |
199 | | struct VelocityTimeFunction : public TimeFunction { |
200 | | /** Date/time at which the velocity function is zero. */ |
201 | | Epoch referenceEpoch{}; |
202 | | |
203 | | virtual double evaluateAt(double dt) const override; |
204 | | }; |
205 | | |
206 | | struct StepTimeFunction : public TimeFunction { |
207 | | /** Epoch at which the step function transitions from 0 to 1. */ |
208 | | Epoch stepEpoch{}; |
209 | | |
210 | | virtual double evaluateAt(double dt) const override; |
211 | | }; |
212 | | |
213 | | struct ReverseStepTimeFunction : public TimeFunction { |
214 | | /** Epoch at which the reverse step function transitions from 1. to 0 */ |
215 | | Epoch stepEpoch{}; |
216 | | |
217 | | virtual double evaluateAt(double dt) const override; |
218 | | }; |
219 | | |
220 | | struct PiecewiseTimeFunction : public TimeFunction { |
221 | | /** One of "zero", "constant", and "linear", defines the behavior of |
222 | | * the function before the first defined epoch */ |
223 | | std::string beforeFirst{}; |
224 | | |
225 | | /** One of "zero", "constant", and "linear", defines the behavior of |
226 | | * the function after the last defined epoch */ |
227 | | std::string afterLast{}; |
228 | | |
229 | | struct EpochScaleFactorTuple { |
230 | | /** Defines the date/time of the data point. */ |
231 | | Epoch epoch{}; |
232 | | |
233 | | /** Function value at the above epoch */ |
234 | | double scaleFactor = std::numeric_limits<double>::quiet_NaN(); |
235 | | }; |
236 | | |
237 | | /** A sorted array data points each defined by two elements. |
238 | | * The array is sorted in order of increasing epoch. |
239 | | * Note: where the time function includes a step it is represented by |
240 | | * two consecutive data points with the same epoch. The first defines |
241 | | * the scale factor that applies before the epoch and the second the |
242 | | * scale factor that applies after the epoch. */ |
243 | | std::vector<EpochScaleFactorTuple> model{}; |
244 | | |
245 | | virtual double evaluateAt(double dt) const override; |
246 | | }; |
247 | | |
248 | | struct ExponentialTimeFunction : public TimeFunction { |
249 | | /** The date/time at which the exponential decay starts. */ |
250 | | Epoch referenceEpoch{}; |
251 | | |
252 | | /** The date/time at which the exponential decay ends. */ |
253 | | Epoch endEpoch{}; |
254 | | |
255 | | /** The relaxation constant in years. */ |
256 | | double relaxationConstant = std::numeric_limits<double>::quiet_NaN(); |
257 | | |
258 | | /** The scale factor that applies before the reference epoch. */ |
259 | | double beforeScaleFactor = std::numeric_limits<double>::quiet_NaN(); |
260 | | |
261 | | /** Initial scale factor. */ |
262 | | double initialScaleFactor = std::numeric_limits<double>::quiet_NaN(); |
263 | | |
264 | | /** The scale factor the exponential function approaches. */ |
265 | | double finalScaleFactor = std::numeric_limits<double>::quiet_NaN(); |
266 | | |
267 | | virtual double evaluateAt(double dt) const override; |
268 | | }; |
269 | | |
270 | | /** Get the time function. */ |
271 | 0 | const TimeFunction *timeFunction() const { return mTimeFunction.get(); } |
272 | | |
273 | | private: |
274 | 0 | Component() = default; |
275 | | |
276 | | std::string mDescription{}; |
277 | | SpatialExtent mSpatialExtent{}; |
278 | | std::string mDisplacementType{}; |
279 | | std::string mUncertaintyType{}; |
280 | | double mHorizontalUncertainty = std::numeric_limits<double>::quiet_NaN(); |
281 | | double mVerticalUncertainty = std::numeric_limits<double>::quiet_NaN(); |
282 | | SpatialModel mSpatialModel{}; |
283 | | std::unique_ptr<TimeFunction> mTimeFunction{}; |
284 | | }; |
285 | | |
286 | 0 | Component::TimeFunction::~TimeFunction() = default; |
287 | | |
288 | | // --------------------------------------------------------------------------- |
289 | | |
290 | | /** Master file of a deformation model. */ |
291 | | class MasterFile { |
292 | | public: |
293 | | /** Parse the provided serialized JSON content and return an object. |
294 | | * |
295 | | * @throws ParsingException in case of error. |
296 | | */ |
297 | | static std::unique_ptr<MasterFile> parse(const std::string &text); |
298 | | |
299 | | /** Get file type. Should always be "deformation_model_master_file" */ |
300 | 0 | const std::string &fileType() const { return mFileType; } |
301 | | |
302 | | /** Get the version of the format. At time of writing, only "1.0" is known |
303 | | */ |
304 | 0 | const std::string &formatVersion() const { return mFormatVersion; } |
305 | | |
306 | | /** Get brief descriptive name of the deformation model. */ |
307 | 0 | const std::string &name() const { return mName; } |
308 | | |
309 | | /** Get a string identifying the version of the deformation model. |
310 | | * The format for specifying version is defined by the agency |
311 | | * responsible for the deformation model. */ |
312 | 0 | const std::string &version() const { return mVersion; } |
313 | | |
314 | | /** Get a string identifying the license of the file. |
315 | | * e.g "Create Commons Attribution 4.0 International" */ |
316 | 0 | const std::string &license() const { return mLicense; } |
317 | | |
318 | | /** Get a text description of the model. Intended to be longer than name() |
319 | | */ |
320 | 0 | const std::string &description() const { return mDescription; } |
321 | | |
322 | | /** Get a text description of the model. Intended to be longer than name() |
323 | | */ |
324 | 0 | const std::string &publicationDate() const { return mPublicationDate; } |
325 | | |
326 | | /** Basic information on the agency responsible for the model. */ |
327 | | struct Authority { |
328 | | std::string name{}; |
329 | | std::string url{}; |
330 | | std::string address{}; |
331 | | std::string email{}; |
332 | | }; |
333 | | |
334 | | /** Get basic information on the agency responsible for the model. */ |
335 | 0 | const Authority &authority() const { return mAuthority; } |
336 | | |
337 | | /** Hyperlink related to the model. */ |
338 | | struct Link { |
339 | | /** URL holding the information */ |
340 | | std::string href{}; |
341 | | |
342 | | /** Relationship to the dataset. e.g. "about", "source", "license", |
343 | | * "metadata" */ |
344 | | std::string rel{}; |
345 | | |
346 | | /** Mime type */ |
347 | | std::string type{}; |
348 | | |
349 | | /** Description of the link */ |
350 | | std::string title{}; |
351 | | }; |
352 | | |
353 | | /** Get links to related information. */ |
354 | 0 | const std::vector<Link> links() const { return mLinks; } |
355 | | |
356 | | /** Get a string identifying the source CRS. That is the coordinate |
357 | | * reference system to which the deformation model applies. Typically |
358 | | * "EPSG:XXXX" */ |
359 | 0 | const std::string &sourceCRS() const { return mSourceCRS; } |
360 | | |
361 | | /** Get a string identifying the target CRS. That is, for a time |
362 | | * dependent coordinate transformation, the coordinate reference |
363 | | * system resulting from applying the deformation. |
364 | | * Typically "EPSG:XXXX" */ |
365 | 0 | const std::string &targetCRS() const { return mTargetCRS; } |
366 | | |
367 | | /** Get a string identifying the definition CRS. That is, the |
368 | | * coordinate reference system used to define the component spatial |
369 | | * models. Typically "EPSG:XXXX" */ |
370 | 0 | const std::string &definitionCRS() const { return mDefinitionCRS; } |
371 | | |
372 | | /** Get the nominal reference epoch of the deformation model. Formatted |
373 | | * as a ISO-8601 date-time. This is not necessarily used to calculate |
374 | | * the deformation model - each component defines its own time function. */ |
375 | 0 | const std::string &referenceEpoch() const { return mReferenceEpoch; } |
376 | | |
377 | | /** Get the epoch at which the uncertainties of the deformation model |
378 | | * are calculated. Formatted as a ISO-8601 date-time. */ |
379 | 0 | const std::string &uncertaintyReferenceEpoch() const { |
380 | 0 | return mUncertaintyReferenceEpoch; |
381 | 0 | } |
382 | | |
383 | | /** Unit of horizontal offsets. Only "metre" and "degree" are supported. */ |
384 | 0 | const std::string &horizontalOffsetUnit() const { |
385 | 0 | return mHorizontalOffsetUnit; |
386 | 0 | } |
387 | | |
388 | | /** Unit of vertical offsets. Only "metre" is supported. */ |
389 | 0 | const std::string &verticalOffsetUnit() const { |
390 | 0 | return mVerticalOffsetUnit; |
391 | 0 | } |
392 | | |
393 | | /** Type of horizontal uncertainty. e.g "circular 95% confidence limit" */ |
394 | 0 | const std::string &horizontalUncertaintyType() const { |
395 | 0 | return mHorizontalUncertaintyType; |
396 | 0 | } |
397 | | |
398 | | /** Unit of horizontal uncertainty. Only "metre" is supported. */ |
399 | 0 | const std::string &horizontalUncertaintyUnit() const { |
400 | 0 | return mHorizontalUncertaintyUnit; |
401 | 0 | } |
402 | | |
403 | | /** Type of vertical uncertainty. e.g "circular 95% confidence limit" */ |
404 | 0 | const std::string &verticalUncertaintyType() const { |
405 | 0 | return mVerticalUncertaintyType; |
406 | 0 | } |
407 | | |
408 | | /** Unit of vertical uncertainty. Only "metre" is supported. */ |
409 | 0 | const std::string &verticalUncertaintyUnit() const { |
410 | 0 | return mVerticalUncertaintyUnit; |
411 | 0 | } |
412 | | |
413 | | /** Defines how the horizontal offsets are applied to geographic |
414 | | * coordinates. Only "addition" and "geocentric" are supported */ |
415 | 0 | const std::string &horizontalOffsetMethod() const { |
416 | 0 | return mHorizontalOffsetMethod; |
417 | 0 | } |
418 | | |
419 | | /** Get the region within which the deformation model is defined. |
420 | | * It cannot be calculated outside this region */ |
421 | 0 | const SpatialExtent &extent() const { return mSpatialExtent; } |
422 | | |
423 | | /** Defines the range of times for which the model is valid, specified |
424 | | * by a first and a last value. The deformation model is undefined for |
425 | | * dates outside this range. */ |
426 | | struct TimeExtent { |
427 | | Epoch first{}; |
428 | | Epoch last{}; |
429 | | }; |
430 | | |
431 | | /** Get the range of times for which the model is valid. */ |
432 | 0 | const TimeExtent &timeExtent() const { return mTimeExtent; } |
433 | | |
434 | | /** Get an array of the components comprising the deformation model. */ |
435 | 0 | const std::vector<Component> &components() const { return mComponents; } |
436 | | |
437 | | private: |
438 | 3 | MasterFile() = default; |
439 | | |
440 | | std::string mFileType{}; |
441 | | std::string mFormatVersion{}; |
442 | | std::string mName{}; |
443 | | std::string mVersion{}; |
444 | | std::string mLicense{}; |
445 | | std::string mDescription{}; |
446 | | std::string mPublicationDate{}; |
447 | | Authority mAuthority{}; |
448 | | std::vector<Link> mLinks{}; |
449 | | std::string mSourceCRS{}; |
450 | | std::string mTargetCRS{}; |
451 | | std::string mDefinitionCRS{}; |
452 | | std::string mReferenceEpoch{}; |
453 | | std::string mUncertaintyReferenceEpoch{}; |
454 | | std::string mHorizontalOffsetUnit{}; |
455 | | std::string mVerticalOffsetUnit{}; |
456 | | std::string mHorizontalUncertaintyType{}; |
457 | | std::string mHorizontalUncertaintyUnit{}; |
458 | | std::string mVerticalUncertaintyType{}; |
459 | | std::string mVerticalUncertaintyUnit{}; |
460 | | std::string mHorizontalOffsetMethod{}; |
461 | | SpatialExtent mSpatialExtent{}; |
462 | | TimeExtent mTimeExtent{}; |
463 | | std::vector<Component> mComponents{}; |
464 | | }; |
465 | | |
466 | | // --------------------------------------------------------------------------- |
467 | | |
468 | | /** Prototype for a Grid used by GridSet. Intended to be implemented |
469 | | * by user code */ |
470 | | struct GridPrototype { |
471 | | double minx = 0; |
472 | | double miny = 0; |
473 | | double resx = 0; |
474 | | double resy = 0; |
475 | | int width = 0; |
476 | | int height = 0; |
477 | | |
478 | | // cppcheck-suppress functionStatic |
479 | | bool getLongLatOffset(int /*ix*/, int /*iy*/, double & /*longOffsetRadian*/, |
480 | 0 | double & /*latOffsetRadian*/) const { |
481 | 0 | throw UnimplementedException("getLongLatOffset unimplemented"); |
482 | 0 | } |
483 | | |
484 | | // cppcheck-suppress functionStatic |
485 | 0 | bool getZOffset(int /*ix*/, int /*iy*/, double & /*zOffset*/) const { |
486 | 0 | throw UnimplementedException("getZOffset unimplemented"); |
487 | 0 | } |
488 | | |
489 | | // cppcheck-suppress functionStatic |
490 | | bool getEastingNorthingOffset(int /*ix*/, int /*iy*/, |
491 | | double & /*eastingOffset*/, |
492 | 0 | double & /*northingOffset*/) const { |
493 | 0 | throw UnimplementedException("getEastingNorthingOffset unimplemented"); |
494 | 0 | } |
495 | | |
496 | | // cppcheck-suppress functionStatic |
497 | | bool getLongLatZOffset(int /*ix*/, int /*iy*/, |
498 | | double & /*longOffsetRadian*/, |
499 | | double & /*latOffsetRadian*/, |
500 | 0 | double & /*zOffset*/) const { |
501 | 0 | throw UnimplementedException("getLongLatZOffset unimplemented"); |
502 | 0 | #if 0 |
503 | 0 | return getLongLatOffset(ix, iy, longOffsetRadian, latOffsetRadian) && |
504 | 0 | getZOffset(ix, iy, zOffset); |
505 | 0 | #endif |
506 | 0 | } |
507 | | |
508 | | // cppcheck-suppress functionStatic |
509 | | bool getEastingNorthingZOffset(int /*ix*/, int /*iy*/, |
510 | | double & /*eastingOffset*/, |
511 | | double & /*northingOffset*/, |
512 | 0 | double & /*zOffset*/) const { |
513 | 0 | throw UnimplementedException("getEastingNorthingOffset unimplemented"); |
514 | 0 | #if 0 |
515 | 0 | return getEastingNorthingOffset(ix, iy, eastingOffset, |
516 | 0 | northingOffset) && |
517 | 0 | getZOffset(ix, iy, zOffset); |
518 | 0 | #endif |
519 | 0 | } |
520 | | |
521 | | #ifdef DEBUG_DEFMODEL |
522 | | std::string name() const { |
523 | | throw UnimplementedException("name() unimplemented"); |
524 | | } |
525 | | #endif |
526 | | }; |
527 | | |
528 | | // --------------------------------------------------------------------------- |
529 | | |
530 | | /** Prototype for a GridSet used by EvaluatorIface. Intended to be implemented |
531 | | * by user code */ |
532 | | template <class Grid = GridPrototype> struct GridSetPrototype { |
533 | | // The return pointer should remain "stable" over time for a given grid |
534 | | // of a GridSet. |
535 | | // cppcheck-suppress functionStatic |
536 | | const Grid *gridAt(double /*x */, double /* y */) { |
537 | | throw UnimplementedException("gridAt unimplemented"); |
538 | | } |
539 | | }; |
540 | | |
541 | | // --------------------------------------------------------------------------- |
542 | | |
543 | | /** Prototype for a EvaluatorIface used by Evaluator. Intended to be implemented |
544 | | * by user code */ |
545 | | template <class Grid = GridPrototype, class GridSet = GridSetPrototype<>> |
546 | | struct EvaluatorIfacePrototype { |
547 | | |
548 | | std::unique_ptr<GridSet> open(const std::string & /* filename*/) { |
549 | | throw UnimplementedException("open unimplemented"); |
550 | | } |
551 | | |
552 | | // cppcheck-suppress functionStatic |
553 | | void geographicToGeocentric(double /* lam */, double /* phi */, |
554 | | double /* height*/, double /* a */, |
555 | | double /* b */, double /*es*/, double & /* X */, |
556 | | double & /* Y */, double & /* Z */) { |
557 | | throw UnimplementedException("geographicToGeocentric unimplemented"); |
558 | | } |
559 | | |
560 | | // cppcheck-suppress functionStatic |
561 | | void geocentricToGeographic(double /* X */, double /* Y */, double /* Z */, |
562 | | double /* a */, double /* b */, double /*es*/, |
563 | | double & /* lam */, double & /* phi */, |
564 | | double & /* height*/) { |
565 | | throw UnimplementedException("geocentricToGeographic unimplemented"); |
566 | | } |
567 | | |
568 | | // cppcheck-suppress functionStatic |
569 | | bool isGeographicCRS(const std::string & /* crsDef */) { |
570 | | throw UnimplementedException("isGeographicCRS unimplemented"); |
571 | | } |
572 | | |
573 | | #ifdef DEBUG_DEFMODEL |
574 | | void log(const std::string & /* msg */) { |
575 | | throw UnimplementedException("log unimplemented"); |
576 | | } |
577 | | #endif |
578 | | }; |
579 | | |
580 | | // --------------------------------------------------------------------------- |
581 | | |
582 | | /** Internal class to offer caching services over a Component */ |
583 | | template <class Grid, class GridSet> struct ComponentEx; |
584 | | |
585 | | // --------------------------------------------------------------------------- |
586 | | |
587 | | /** Class to evaluate the transformation of a coordinate */ |
588 | | template <class Grid = GridPrototype, class GridSet = GridSetPrototype<>, |
589 | | class EvaluatorIface = EvaluatorIfacePrototype<>> |
590 | | class Evaluator { |
591 | | public: |
592 | | /** Constructor. May throw EvaluatorException */ |
593 | | explicit Evaluator(std::unique_ptr<MasterFile> &&model, |
594 | | EvaluatorIface &iface, double a, double b); |
595 | | |
596 | | /** Evaluate displacement of a position given by (x,y,z,t) and |
597 | | * return it in (x_out,y_out_,z_out). |
598 | | * For geographic CRS (only supported at that time), x must be a |
599 | | * longitude, and y a latitude. |
600 | | */ |
601 | | bool forward(EvaluatorIface &iface, double x, double y, double z, double t, |
602 | 0 | double &x_out, double &y_out, double &z_out) { |
603 | 0 | return forward(iface, x, y, z, t, false, x_out, y_out, z_out); |
604 | 0 | } |
605 | | |
606 | | /** Apply inverse transformation. */ |
607 | | bool inverse(EvaluatorIface &iface, double x, double y, double z, double t, |
608 | | double &x_out, double &y_out, double &z_out); |
609 | | |
610 | | /** Clear grid cache */ |
611 | | void clearGridCache(); |
612 | | |
613 | | /** Return whether the definition CRS is a geographic CRS */ |
614 | 0 | bool isGeographicCRS() const { return mIsGeographicCRS; } |
615 | | |
616 | | private: |
617 | | std::unique_ptr<MasterFile> mModel; |
618 | | const double mA; |
619 | | const double mB; |
620 | | const double mEs; |
621 | | const bool mIsHorizontalUnitDegree; /* degree vs metre */ |
622 | | const bool mIsAddition; /* addition vs geocentric */ |
623 | | const bool mIsGeographicCRS; |
624 | | |
625 | | bool forward(EvaluatorIface &iface, double x, double y, double z, double t, |
626 | | bool forInverseComputation, double &x_out, double &y_out, |
627 | | double &z_out); |
628 | | |
629 | | std::vector<std::unique_ptr<ComponentEx<Grid, GridSet>>> mComponents{}; |
630 | | }; |
631 | | |
632 | | // --------------------------------------------------------------------------- |
633 | | |
634 | | } // namespace DEFORMATON_MODEL_NAMESPACE |
635 | | |
636 | | // --------------------------------------------------------------------------- |
637 | | |
638 | | #include "defmodel_impl.hpp" |
639 | | |
640 | | #endif // DEFMODEL_HPP |