Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * Project: PROJ |
3 | | * Purpose: Grid management |
4 | | * Author: Even Rouault, <even.rouault at spatialys.com> |
5 | | * |
6 | | ****************************************************************************** |
7 | | * Copyright (c) 2019, 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 | | #ifndef GRIDS_HPP_INCLUDED |
29 | | #define GRIDS_HPP_INCLUDED |
30 | | |
31 | | #include <memory> |
32 | | #include <vector> |
33 | | |
34 | | #include "proj.h" |
35 | | #include "proj/util.hpp" |
36 | | |
37 | | NS_PROJ_START |
38 | | |
39 | | struct ExtentAndRes { |
40 | | bool isGeographic; // whether extent and resolutions are in a geographic or |
41 | | // projected CRS |
42 | | double west; // in radian for geographic, in CRS units otherwise |
43 | | double south; // in radian for geographic, in CRS units otherwise |
44 | | double east; // in radian for geographic, in CRS units otherwise |
45 | | double north; // in radian for geographic, in CRS units otherwise |
46 | | double resX; // in radian for geographic, in CRS units otherwise |
47 | | double resY; // in radian for geographic, in CRS units otherwise |
48 | | double invResX; // = 1 / resX; |
49 | | double invResY; // = 1 / resY; |
50 | | |
51 | | void computeInvRes(); |
52 | | |
53 | | bool fullWorldLongitude() const; |
54 | | bool contains(const ExtentAndRes &other) const; |
55 | | bool intersects(const ExtentAndRes &other) const; |
56 | | }; |
57 | | |
58 | | // --------------------------------------------------------------------------- |
59 | | |
60 | | class PROJ_GCC_DLL Grid { |
61 | | protected: |
62 | | std::string m_name; |
63 | | int m_width; |
64 | | int m_height; |
65 | | ExtentAndRes m_extent; |
66 | | |
67 | | Grid(const std::string &nameIn, int widthIn, int heightIn, |
68 | | const ExtentAndRes &extentIn); |
69 | | |
70 | | public: |
71 | | PROJ_FOR_TEST virtual ~Grid(); |
72 | | |
73 | 0 | PROJ_FOR_TEST int width() const { return m_width; } |
74 | 0 | PROJ_FOR_TEST int height() const { return m_height; } |
75 | 0 | PROJ_FOR_TEST const ExtentAndRes &extentAndRes() const { return m_extent; } |
76 | 0 | PROJ_FOR_TEST const std::string &name() const { return m_name; } |
77 | | |
78 | | virtual const std::string &metadataItem(const std::string &key, |
79 | | int sample = -1) const = 0; |
80 | | |
81 | 0 | PROJ_FOR_TEST virtual bool isNullGrid() const { return false; } |
82 | | PROJ_FOR_TEST virtual bool hasChanged() const = 0; |
83 | | }; |
84 | | |
85 | | // --------------------------------------------------------------------------- |
86 | | |
87 | | class PROJ_GCC_DLL VerticalShiftGrid : public Grid { |
88 | | protected: |
89 | | std::vector<std::unique_ptr<VerticalShiftGrid>> m_children{}; |
90 | | |
91 | | public: |
92 | | PROJ_FOR_TEST VerticalShiftGrid(const std::string &nameIn, int widthIn, |
93 | | int heightIn, const ExtentAndRes &extentIn); |
94 | | PROJ_FOR_TEST ~VerticalShiftGrid() override; |
95 | | |
96 | | PROJ_FOR_TEST const VerticalShiftGrid *gridAt(double longitude, |
97 | | double lat) const; |
98 | | |
99 | | PROJ_FOR_TEST virtual bool isNodata(float /*val*/, |
100 | | double /* multiplier */) const = 0; |
101 | | |
102 | | // x = 0 is western-most column, y = 0 is southern-most line |
103 | | PROJ_FOR_TEST virtual bool valueAt(int x, int y, float &out) const = 0; |
104 | | |
105 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx) = 0; |
106 | | }; |
107 | | |
108 | | // --------------------------------------------------------------------------- |
109 | | |
110 | | class PROJ_GCC_DLL VerticalShiftGridSet { |
111 | | protected: |
112 | | std::string m_name{}; |
113 | | std::string m_format{}; |
114 | | std::vector<std::unique_ptr<VerticalShiftGrid>> m_grids{}; |
115 | | |
116 | | VerticalShiftGridSet(); |
117 | | |
118 | | public: |
119 | | PROJ_FOR_TEST virtual ~VerticalShiftGridSet(); |
120 | | |
121 | | PROJ_FOR_TEST static std::unique_ptr<VerticalShiftGridSet> |
122 | | open(PJ_CONTEXT *ctx, const std::string &filename); |
123 | | |
124 | 0 | PROJ_FOR_TEST const std::string &name() const { return m_name; } |
125 | 0 | PROJ_FOR_TEST const std::string &format() const { return m_format; } |
126 | | PROJ_FOR_TEST const std::vector<std::unique_ptr<VerticalShiftGrid>> & |
127 | 0 | grids() const { |
128 | 0 | return m_grids; |
129 | 0 | } |
130 | | PROJ_FOR_TEST const VerticalShiftGrid *gridAt(double longitude, |
131 | | double lat) const; |
132 | | |
133 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx); |
134 | | PROJ_FOR_TEST virtual bool reopen(PJ_CONTEXT *ctx); |
135 | | }; |
136 | | |
137 | | // --------------------------------------------------------------------------- |
138 | | |
139 | | class PROJ_GCC_DLL HorizontalShiftGrid : public Grid { |
140 | | protected: |
141 | | std::vector<std::unique_ptr<HorizontalShiftGrid>> m_children{}; |
142 | | |
143 | | public: |
144 | | PROJ_FOR_TEST HorizontalShiftGrid(const std::string &nameIn, int widthIn, |
145 | | int heightIn, |
146 | | const ExtentAndRes &extentIn); |
147 | | PROJ_FOR_TEST ~HorizontalShiftGrid() override; |
148 | | |
149 | | PROJ_FOR_TEST const HorizontalShiftGrid *gridAt(double longitude, |
150 | | double lat) const; |
151 | | |
152 | | // x = 0 is western-most column, y = 0 is southern-most line |
153 | | PROJ_FOR_TEST virtual bool valueAt(int x, int y, |
154 | | bool compensateNTConvention, |
155 | | float &longShift, |
156 | | float &latShift) const = 0; |
157 | | |
158 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx) = 0; |
159 | | }; |
160 | | |
161 | | // --------------------------------------------------------------------------- |
162 | | |
163 | | class PROJ_GCC_DLL HorizontalShiftGridSet { |
164 | | protected: |
165 | | std::string m_name{}; |
166 | | std::string m_format{}; |
167 | | std::vector<std::unique_ptr<HorizontalShiftGrid>> m_grids{}; |
168 | | |
169 | | HorizontalShiftGridSet(); |
170 | | |
171 | | public: |
172 | | PROJ_FOR_TEST virtual ~HorizontalShiftGridSet(); |
173 | | |
174 | | PROJ_FOR_TEST static std::unique_ptr<HorizontalShiftGridSet> |
175 | | open(PJ_CONTEXT *ctx, const std::string &filename); |
176 | | |
177 | 0 | PROJ_FOR_TEST const std::string &name() const { return m_name; } |
178 | 0 | PROJ_FOR_TEST const std::string &format() const { return m_format; } |
179 | | PROJ_FOR_TEST const std::vector<std::unique_ptr<HorizontalShiftGrid>> & |
180 | 0 | grids() const { |
181 | 0 | return m_grids; |
182 | 0 | } |
183 | | PROJ_FOR_TEST const HorizontalShiftGrid *gridAt(double longitude, |
184 | | double lat) const; |
185 | | |
186 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx); |
187 | | PROJ_FOR_TEST virtual bool reopen(PJ_CONTEXT *ctx); |
188 | | }; |
189 | | |
190 | | // --------------------------------------------------------------------------- |
191 | | |
192 | | class PROJ_GCC_DLL GenericShiftGrid : public Grid { |
193 | | protected: |
194 | | std::vector<std::unique_ptr<GenericShiftGrid>> m_children{}; |
195 | | |
196 | | public: |
197 | | PROJ_FOR_TEST GenericShiftGrid(const std::string &nameIn, int widthIn, |
198 | | int heightIn, const ExtentAndRes &extentIn); |
199 | | |
200 | | PROJ_FOR_TEST ~GenericShiftGrid() override; |
201 | | |
202 | | PROJ_FOR_TEST const GenericShiftGrid *gridAt(double x, double y) const; |
203 | | |
204 | | virtual const std::string &type() const = 0; |
205 | | |
206 | | PROJ_FOR_TEST virtual std::string unit(int sample) const = 0; |
207 | | |
208 | | PROJ_FOR_TEST virtual std::string description(int sample) const = 0; |
209 | | |
210 | | PROJ_FOR_TEST virtual int samplesPerPixel() const = 0; |
211 | | |
212 | | // x = 0 is western-most column, y = 0 is southern-most line |
213 | | PROJ_FOR_TEST virtual bool valueAt(int x, int y, int sample, |
214 | | float &out) const = 0; |
215 | | |
216 | | PROJ_FOR_TEST virtual bool valuesAt(int x_start, int y_start, int x_count, |
217 | | int y_count, int sample_count, |
218 | | const int *sample_idx, float *out, |
219 | | bool &nodataFound) const; |
220 | | |
221 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx) = 0; |
222 | | }; |
223 | | |
224 | | // --------------------------------------------------------------------------- |
225 | | |
226 | | class PROJ_GCC_DLL GenericShiftGridSet { |
227 | | protected: |
228 | | std::string m_name{}; |
229 | | std::string m_format{}; |
230 | | std::vector<std::unique_ptr<GenericShiftGrid>> m_grids{}; |
231 | | |
232 | | GenericShiftGridSet(); |
233 | | |
234 | | public: |
235 | | PROJ_FOR_TEST virtual ~GenericShiftGridSet(); |
236 | | |
237 | | PROJ_FOR_TEST static std::unique_ptr<GenericShiftGridSet> |
238 | | open(PJ_CONTEXT *ctx, const std::string &filename); |
239 | | |
240 | 0 | PROJ_FOR_TEST const std::string &name() const { return m_name; } |
241 | 0 | PROJ_FOR_TEST const std::string &format() const { return m_format; } |
242 | | PROJ_FOR_TEST const std::vector<std::unique_ptr<GenericShiftGrid>> & |
243 | 8 | grids() const { |
244 | 8 | return m_grids; |
245 | 8 | } |
246 | | PROJ_FOR_TEST const GenericShiftGrid *gridAt(double x, double y) const; |
247 | | PROJ_FOR_TEST const GenericShiftGrid *gridAt(const std::string &type, |
248 | | double x, double y) const; |
249 | | |
250 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx); |
251 | | PROJ_FOR_TEST virtual bool reopen(PJ_CONTEXT *ctx); |
252 | | }; |
253 | | |
254 | | // --------------------------------------------------------------------------- |
255 | | |
256 | | typedef std::vector<std::unique_ptr<HorizontalShiftGridSet>> ListOfHGrids; |
257 | | typedef std::vector<std::unique_ptr<VerticalShiftGridSet>> ListOfVGrids; |
258 | | typedef std::vector<std::unique_ptr<GenericShiftGridSet>> ListOfGenericGrids; |
259 | | |
260 | | ListOfVGrids pj_vgrid_init(PJ *P, const char *grids); |
261 | | ListOfHGrids pj_hgrid_init(PJ *P, const char *grids); |
262 | | ListOfGenericGrids pj_generic_grid_init(PJ *P, const char *grids); |
263 | | |
264 | | PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp); |
265 | | double pj_vgrid_value(PJ *P, const ListOfVGrids &, PJ_LP lp, |
266 | | double vmultiplier); |
267 | | PJ_LP pj_hgrid_apply(PJ_CONTEXT *ctx, const ListOfHGrids &grids, PJ_LP lp, |
268 | | PJ_DIRECTION direction); |
269 | | |
270 | | const GenericShiftGrid *pj_find_generic_grid(const ListOfGenericGrids &grids, |
271 | | const PJ_LP &input, |
272 | | GenericShiftGridSet *&gridSetOut); |
273 | | bool pj_bilinear_interpolation_three_samples( |
274 | | PJ_CONTEXT *ctx, const GenericShiftGrid *grid, const PJ_LP &lp, int idx1, |
275 | | int idx2, int idx3, double &v1, double &v2, double &v3, bool &must_retry); |
276 | | |
277 | | NS_PROJ_END |
278 | | |
279 | | #endif // GRIDS_HPP_INCLUDED |