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 | | friend class GTiffDataset; |
63 | | std::string m_name; |
64 | | int m_width; |
65 | | int m_height; |
66 | | ExtentAndRes m_extent; |
67 | | |
68 | | Grid(const std::string &nameIn, int widthIn, int heightIn, |
69 | | const ExtentAndRes &extentIn); |
70 | | |
71 | | public: |
72 | | PROJ_FOR_TEST virtual ~Grid(); |
73 | | |
74 | 0 | PROJ_FOR_TEST int width() const { return m_width; } |
75 | 0 | PROJ_FOR_TEST int height() const { return m_height; } |
76 | 0 | PROJ_FOR_TEST const ExtentAndRes &extentAndRes() const { return m_extent; } |
77 | 0 | PROJ_FOR_TEST const std::string &name() const { return m_name; } |
78 | | |
79 | | virtual const std::string &metadataItem(const std::string &key, |
80 | | int sample = -1) const = 0; |
81 | | |
82 | 0 | PROJ_FOR_TEST virtual bool isNullGrid() const { return false; } |
83 | | PROJ_FOR_TEST virtual bool hasChanged() const = 0; |
84 | | }; |
85 | | |
86 | | // --------------------------------------------------------------------------- |
87 | | |
88 | | class PROJ_GCC_DLL VerticalShiftGrid : public Grid { |
89 | | protected: |
90 | | std::vector<std::unique_ptr<VerticalShiftGrid>> m_children{}; |
91 | | |
92 | | public: |
93 | | PROJ_FOR_TEST VerticalShiftGrid(const std::string &nameIn, int widthIn, |
94 | | int heightIn, const ExtentAndRes &extentIn); |
95 | | PROJ_FOR_TEST ~VerticalShiftGrid() override; |
96 | | |
97 | | PROJ_FOR_TEST const VerticalShiftGrid *gridAt(double longitude, |
98 | | double lat) const; |
99 | | |
100 | | PROJ_FOR_TEST virtual bool isNodata(float /*val*/, |
101 | | double /* multiplier */) const = 0; |
102 | | |
103 | | // x = 0 is western-most column, y = 0 is southern-most line |
104 | | PROJ_FOR_TEST virtual bool valueAt(int x, int y, float &out) const = 0; |
105 | | |
106 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx) = 0; |
107 | | }; |
108 | | |
109 | | // --------------------------------------------------------------------------- |
110 | | |
111 | | class PROJ_GCC_DLL VerticalShiftGridSet { |
112 | | protected: |
113 | | std::string m_name{}; |
114 | | std::string m_format{}; |
115 | | std::vector<std::unique_ptr<VerticalShiftGrid>> m_grids{}; |
116 | | |
117 | | VerticalShiftGridSet(); |
118 | | |
119 | | public: |
120 | | PROJ_FOR_TEST virtual ~VerticalShiftGridSet(); |
121 | | |
122 | | PROJ_FOR_TEST static std::unique_ptr<VerticalShiftGridSet> |
123 | | open(PJ_CONTEXT *ctx, const std::string &filename); |
124 | | |
125 | 0 | PROJ_FOR_TEST const std::string &name() const { return m_name; } |
126 | 0 | PROJ_FOR_TEST const std::string &format() const { return m_format; } |
127 | | PROJ_FOR_TEST const std::vector<std::unique_ptr<VerticalShiftGrid>> & |
128 | 0 | grids() const { |
129 | 0 | return m_grids; |
130 | 0 | } |
131 | | PROJ_FOR_TEST const VerticalShiftGrid *gridAt(double longitude, |
132 | | double lat) const; |
133 | | |
134 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx); |
135 | | PROJ_FOR_TEST virtual bool reopen(PJ_CONTEXT *ctx); |
136 | | }; |
137 | | |
138 | | // --------------------------------------------------------------------------- |
139 | | |
140 | | class PROJ_GCC_DLL HorizontalShiftGrid : public Grid { |
141 | | protected: |
142 | | std::vector<std::unique_ptr<HorizontalShiftGrid>> m_children{}; |
143 | | |
144 | | public: |
145 | | PROJ_FOR_TEST HorizontalShiftGrid(const std::string &nameIn, int widthIn, |
146 | | int heightIn, |
147 | | const ExtentAndRes &extentIn); |
148 | | PROJ_FOR_TEST ~HorizontalShiftGrid() override; |
149 | | |
150 | | PROJ_FOR_TEST const HorizontalShiftGrid *gridAt(double longitude, |
151 | | double lat) const; |
152 | | |
153 | | // x = 0 is western-most column, y = 0 is southern-most line |
154 | | PROJ_FOR_TEST virtual bool valueAt(int x, int y, |
155 | | bool compensateNTConvention, |
156 | | float &longShift, |
157 | | float &latShift) const = 0; |
158 | | |
159 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx) = 0; |
160 | | }; |
161 | | |
162 | | // --------------------------------------------------------------------------- |
163 | | |
164 | | class PROJ_GCC_DLL HorizontalShiftGridSet { |
165 | | protected: |
166 | | std::string m_name{}; |
167 | | std::string m_format{}; |
168 | | std::vector<std::unique_ptr<HorizontalShiftGrid>> m_grids{}; |
169 | | |
170 | | HorizontalShiftGridSet(); |
171 | | |
172 | | public: |
173 | | PROJ_FOR_TEST virtual ~HorizontalShiftGridSet(); |
174 | | |
175 | | PROJ_FOR_TEST static std::unique_ptr<HorizontalShiftGridSet> |
176 | | open(PJ_CONTEXT *ctx, const std::string &filename); |
177 | | |
178 | 0 | PROJ_FOR_TEST const std::string &name() const { return m_name; } |
179 | 0 | PROJ_FOR_TEST const std::string &format() const { return m_format; } |
180 | | PROJ_FOR_TEST const std::vector<std::unique_ptr<HorizontalShiftGrid>> & |
181 | 0 | grids() const { |
182 | 0 | return m_grids; |
183 | 0 | } |
184 | | PROJ_FOR_TEST const HorizontalShiftGrid *gridAt(double longitude, |
185 | | double lat) const; |
186 | | |
187 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx); |
188 | | PROJ_FOR_TEST virtual bool reopen(PJ_CONTEXT *ctx); |
189 | | }; |
190 | | |
191 | | // --------------------------------------------------------------------------- |
192 | | |
193 | | class PROJ_GCC_DLL GenericShiftGrid : public Grid { |
194 | | protected: |
195 | | std::vector<std::unique_ptr<GenericShiftGrid>> m_children{}; |
196 | | |
197 | | public: |
198 | | PROJ_FOR_TEST GenericShiftGrid(const std::string &nameIn, int widthIn, |
199 | | int heightIn, const ExtentAndRes &extentIn); |
200 | | |
201 | | PROJ_FOR_TEST ~GenericShiftGrid() override; |
202 | | |
203 | | PROJ_FOR_TEST const GenericShiftGrid *gridAt(double x, double y) const; |
204 | | |
205 | | virtual const std::string &type() const = 0; |
206 | | |
207 | | PROJ_FOR_TEST virtual std::string unit(int sample) const = 0; |
208 | | |
209 | | PROJ_FOR_TEST virtual std::string description(int sample) const = 0; |
210 | | |
211 | | PROJ_FOR_TEST virtual int samplesPerPixel() const = 0; |
212 | | |
213 | | // x = 0 is western-most column, y = 0 is southern-most line |
214 | | PROJ_FOR_TEST virtual bool valueAt(int x, int y, int sample, |
215 | | float &out) const = 0; |
216 | | |
217 | | PROJ_FOR_TEST virtual bool valuesAt(int x_start, int y_start, int x_count, |
218 | | int y_count, int sample_count, |
219 | | const int *sample_idx, float *out, |
220 | | bool &nodataFound) const; |
221 | | |
222 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx) = 0; |
223 | | }; |
224 | | |
225 | | // --------------------------------------------------------------------------- |
226 | | |
227 | | class PROJ_GCC_DLL GenericShiftGridSet { |
228 | | protected: |
229 | | std::string m_name{}; |
230 | | std::string m_format{}; |
231 | | std::vector<std::unique_ptr<GenericShiftGrid>> m_grids{}; |
232 | | |
233 | | GenericShiftGridSet(); |
234 | | |
235 | | public: |
236 | | PROJ_FOR_TEST virtual ~GenericShiftGridSet(); |
237 | | |
238 | | PROJ_FOR_TEST static std::unique_ptr<GenericShiftGridSet> |
239 | | open(PJ_CONTEXT *ctx, const std::string &filename); |
240 | | |
241 | 0 | PROJ_FOR_TEST const std::string &name() const { return m_name; } |
242 | 0 | PROJ_FOR_TEST const std::string &format() const { return m_format; } |
243 | | PROJ_FOR_TEST const std::vector<std::unique_ptr<GenericShiftGrid>> & |
244 | 4 | grids() const { |
245 | 4 | return m_grids; |
246 | 4 | } |
247 | | PROJ_FOR_TEST const GenericShiftGrid *gridAt(double x, double y) const; |
248 | | PROJ_FOR_TEST const GenericShiftGrid *gridAt(const std::string &type, |
249 | | double x, double y) const; |
250 | | |
251 | | PROJ_FOR_TEST virtual void reassign_context(PJ_CONTEXT *ctx); |
252 | | PROJ_FOR_TEST virtual bool reopen(PJ_CONTEXT *ctx); |
253 | | }; |
254 | | |
255 | | // --------------------------------------------------------------------------- |
256 | | |
257 | | typedef std::vector<std::unique_ptr<HorizontalShiftGridSet>> ListOfHGrids; |
258 | | typedef std::vector<std::unique_ptr<VerticalShiftGridSet>> ListOfVGrids; |
259 | | typedef std::vector<std::unique_ptr<GenericShiftGridSet>> ListOfGenericGrids; |
260 | | |
261 | | ListOfVGrids pj_vgrid_init(PJ *P, const char *grids); |
262 | | ListOfHGrids pj_hgrid_init(PJ *P, const char *grids); |
263 | | ListOfGenericGrids pj_generic_grid_init(PJ *P, const char *grids); |
264 | | |
265 | | PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp); |
266 | | double pj_vgrid_value(PJ *P, const ListOfVGrids &, PJ_LP lp, |
267 | | double vmultiplier); |
268 | | PJ_LP pj_hgrid_apply(PJ_CONTEXT *ctx, const ListOfHGrids &grids, PJ_LP lp, |
269 | | PJ_DIRECTION direction); |
270 | | |
271 | | const GenericShiftGrid *pj_find_generic_grid(const ListOfGenericGrids &grids, |
272 | | const PJ_LP &input, |
273 | | GenericShiftGridSet *&gridSetOut); |
274 | | bool pj_bilinear_interpolation_three_samples( |
275 | | PJ_CONTEXT *ctx, const GenericShiftGrid *grid, const PJ_LP &lp, int idx1, |
276 | | int idx2, int idx3, double &v1, double &v2, double &v3, bool &must_retry); |
277 | | |
278 | | NS_PROJ_END |
279 | | |
280 | | #endif // GRIDS_HPP_INCLUDED |