/src/proj/src/projections/airocean.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* enable predefined math constants M_* for MS Visual Studio */ |
2 | | #if defined(_MSC_VER) || defined(_WIN32) |
3 | | #ifndef _USE_MATH_DEFINES |
4 | | #define _USE_MATH_DEFINES |
5 | | #endif |
6 | | #endif |
7 | | |
8 | | #include <cmath> |
9 | | #include <cstdint> |
10 | | #include <errno.h> |
11 | | |
12 | | #include "proj.h" |
13 | | #include "proj_internal.h" |
14 | | |
15 | | PROJ_HEAD(airocean, "Airocean") "\n\tMisc, Sph&Ell"; |
16 | | |
17 | | namespace { // anonymous namespace |
18 | | struct pj_face { |
19 | | PJ_XYZ p1; |
20 | | PJ_XYZ p2; |
21 | | PJ_XYZ p3; |
22 | | }; |
23 | | } // namespace |
24 | | |
25 | | /* |
26 | | The vertices of the faces of the icosahedron are inspired by those used by |
27 | | Robert W. Gray. |
28 | | |
29 | | Original Reference: |
30 | | Robert W. Gray (1995) Exact Transformation Equations for |
31 | | Fuller's World Map, Vol. 32. Autumn, 1995, pp. 17-25. |
32 | | |
33 | | To accommodate for land parts that would be interrupted by using a mere |
34 | | icosahedron, some faces are split in two (Australia) and 3 (Japan) subfaces. |
35 | | |
36 | | The parameters below were computed using the script located at: |
37 | | scripts/build_airocean_parameters.py |
38 | | (relative to the root of the project) |
39 | | */ |
40 | | // Define the 23 faces and subfaces |
41 | | constexpr pj_face base_ico_faces[23] = { |
42 | | {{0.42015242670871, 0.07814524940278296, 0.9040825506150193}, |
43 | | {0.5188367303273644, 0.8354203803782358, 0.18133183755726245}, |
44 | | {0.9950094394362416, -0.09134779527642793, 0.040147175877166645}}, |
45 | | {{0.42015242670871, 0.07814524940278296, 0.9040825506150193}, |
46 | | {-0.4146822253203352, 0.6559624054348008, 0.6306758078914754}, |
47 | | {0.5188367303273644, 0.8354203803782358, 0.18133183755726245}}, |
48 | | {{0.42015242670871, 0.07814524940278296, 0.9040825506150193}, |
49 | | {-0.5154559599440418, -0.381716898287133, 0.7672009925177475}, |
50 | | {-0.4146822253203352, 0.6559624054348008, 0.6306758078914754}}, |
51 | | {{0.42015242670871, 0.07814524940278296, 0.9040825506150193}, |
52 | | {0.3557814025329447, -0.8435800024661781, 0.40223422660292557}, |
53 | | {-0.5154559599440418, -0.381716898287133, 0.7672009925177475}}, |
54 | | {{0.42015242670871, 0.07814524940278296, 0.9040825506150193}, |
55 | | {0.9950094394362416, -0.09134779527642793, 0.040147175877166645}, |
56 | | {0.3557814025329447, -0.8435800024661781, 0.40223422660292557}}, |
57 | | {{0.9950094394362416, -0.09134779527642793, 0.040147175877166645}, |
58 | | {0.5188367303273644, 0.8354203803782358, 0.18133183755726245}, |
59 | | {0.5154559599440418, 0.381716898287133, -0.7672009925177475}}, |
60 | | {{0.5154559599440418, 0.381716898287133, -0.7672009925177475}, |
61 | | {0.5188367303273644, 0.8354203803782358, 0.18133183755726245}, |
62 | | {-0.3557814025329447, 0.8435800024661781, -0.40223422660292557}}, |
63 | | {{-0.3557814025329447, 0.8435800024661781, -0.40223422660292557}, |
64 | | {0.5188367303273644, 0.8354203803782358, 0.18133183755726245}, |
65 | | {-0.4146822253203352, 0.6559624054348008, 0.6306758078914754}}, |
66 | | {{-0.5154559599440418, -0.381716898287133, 0.7672009925177475}, |
67 | | {-0.9950094394362416, 0.09134779527642793, -0.040147175877166645}, |
68 | | {-0.4146822253203352, 0.6559624054348008, 0.6306758078914754}}, |
69 | | {{-0.5154559599440418, -0.381716898287133, 0.7672009925177475}, |
70 | | {-0.5188367303273644, -0.8354203803782358, -0.18133183755726245}, |
71 | | {-0.9950094394362416, 0.09134779527642793, -0.040147175877166645}}, |
72 | | {{-0.5154559599440418, -0.381716898287133, 0.7672009925177475}, |
73 | | {0.3557814025329447, -0.8435800024661781, 0.40223422660292557}, |
74 | | {-0.5188367303273644, -0.8354203803782358, -0.18133183755726245}}, |
75 | | {{-0.5188367303273644, -0.8354203803782358, -0.18133183755726245}, |
76 | | {0.3557814025329447, -0.8435800024661781, 0.40223422660292557}, |
77 | | {0.4146822253203352, -0.6559624054348008, -0.6306758078914754}}, |
78 | | {{0.4146822253203352, -0.6559624054348008, -0.6306758078914754}, |
79 | | {0.3557814025329447, -0.8435800024661781, 0.40223422660292557}, |
80 | | {0.9950094394362416, -0.09134779527642793, 0.040147175877166645}}, |
81 | | {{0.5154559599440418, 0.381716898287133, -0.7672009925177475}, |
82 | | {0.4146822253203352, -0.6559624054348008, -0.6306758078914754}, |
83 | | {0.9950094394362416, -0.09134779527642793, 0.040147175877166645}}, |
84 | | {{-0.42015242670871, -0.07814524940278296, -0.9040825506150193}, |
85 | | {-0.3557814025329447, 0.8435800024661781, -0.40223422660292557}, |
86 | | {-0.9950094394362416, 0.09134779527642793, -0.040147175877166645}}, |
87 | | {{-0.42015242670871, -0.07814524940278296, -0.9040825506150193}, |
88 | | {-0.9950094394362416, 0.09134779527642793, -0.040147175877166645}, |
89 | | {-0.5188367303273644, -0.8354203803782358, -0.18133183755726245}}, |
90 | | {{-0.42015242670871, -0.07814524940278296, -0.9040825506150193}, |
91 | | {-0.5188367303273644, -0.8354203803782358, -0.18133183755726245}, |
92 | | {0.4146822253203352, -0.6559624054348008, -0.6306758078914754}}, |
93 | | {{-0.42015242670871, -0.07814524940278296, -0.9040825506150193}, |
94 | | {0.4146822253203352, -0.6559624054348008, -0.6306758078914754}, |
95 | | {0.5154559599440418, 0.381716898287133, -0.7672009925177475}}, |
96 | | {{-0.3557814025329447, 0.8435800024661781, -0.40223422660292557}, |
97 | | {-0.38796691462082733, 0.3827173765316976, -0.6531583886089725}, |
98 | | {0.5154559599440418, 0.381716898287133, -0.7672009925177475}}, |
99 | | {{-0.42015242670871, -0.07814524940278296, -0.9040825506150193}, |
100 | | {0.5154559599440418, 0.381716898287133, -0.7672009925177475}, |
101 | | {-0.38796691462082733, 0.3827173765316976, -0.6531583886089725}}, |
102 | | {{-0.9950094394362416, 0.09134779527642793, -0.040147175877166645}, |
103 | | {-0.3557814025329447, 0.8435800024661781, -0.40223422660292557}, |
104 | | {-0.5884910224298405, 0.5302967343924689, 0.06276480180379439}}, |
105 | | {{-0.3557814025329447, 0.8435800024661781, -0.40223422660292557}, |
106 | | {-0.4146822253203352, 0.6559624054348008, 0.6306758078914754}, |
107 | | {-0.5884910224298405, 0.5302967343924689, 0.06276480180379439}}, |
108 | | {{-0.9950094394362416, 0.09134779527642793, -0.040147175877166645}, |
109 | | {-0.5884910224298405, 0.5302967343924689, 0.06276480180379439}, |
110 | | {-0.4146822253203352, 0.6559624054348008, 0.6306758078914754}}}; |
111 | | // // Define the centers for each face or subface |
112 | | constexpr PJ_XYZ base_ico_centers[23] = { |
113 | | {0.6446661988241054, 0.27407261150153034, 0.37518718801648276}, |
114 | | {0.17476897723857973, 0.5231760117386065, 0.5720300653545857}, |
115 | | {-0.16999525285188902, 0.1174635855168169, 0.7673197836747474}, |
116 | | {0.08682595643253761, -0.3823838837835094, 0.6911725899118975}, |
117 | | {0.5903144228926321, -0.28559418277994103, 0.44882131769837047}, |
118 | | {0.6764340432358825, 0.375263161129647, -0.18190732636110615}, |
119 | | {0.22617042924615385, 0.6869057603771823, -0.3293677938544702}, |
120 | | {-0.0838756325086385, 0.778320929426405, 0.13659113961527075}, |
121 | | {-0.6417158749002062, 0.12186443414136523, 0.45257654151068544}, |
122 | | {-0.6764340432358825, -0.375263161129647, 0.18190732636110615}, |
123 | | {-0.22617042924615385, -0.6869057603771823, 0.32936779385447024}, |
124 | | {0.0838756325086385, -0.778320929426405, -0.13659113961527075}, |
125 | | {0.5884910224298405, -0.5302967343924689, -0.06276480180379439}, |
126 | | {0.6417158749002062, -0.12186443414136523, -0.4525765415106855}, |
127 | | {-0.5903144228926321, 0.28559418277994103, -0.44882131769837047}, |
128 | | {-0.6446661988241054, -0.2740726115015303, -0.37518718801648276}, |
129 | | {-0.17476897723857973, -0.5231760117386065, -0.5720300653545857}, |
130 | | {0.16999525285188902, -0.11746358551681692, -0.7673197836747474}, |
131 | | {-0.07609745240324339, 0.5360047590950029, -0.6075312025765486}, |
132 | | {-0.09755446046183185, 0.2287630084720159, -0.7748139772472463}, |
133 | | {-0.646427288133009, 0.48840817737835834, -0.12653886689209928}, |
134 | | {-0.4529848834277068, 0.6766130474311494, 0.09706879436411474}, |
135 | | {-0.6660608957288058, 0.4258689783678992, 0.2177644779393677}}; |
136 | | // // Define the normals for each face and subface |
137 | | constexpr PJ_XYZ base_ico_normals[23] = { |
138 | | {0.8112534709140969, 0.34489532376393844, 0.47213877364139306}, |
139 | | {0.21993077914046083, 0.6583691780274996, 0.7198475378926182}, |
140 | | {-0.21392348345014195, 0.1478171829550702, 0.9656017935214206}, |
141 | | {0.10926252787847963, -0.4811951572873208, 0.8697775121287253}, |
142 | | {0.7428567301586793, -0.35939416782780276, 0.5648005936517034}, |
143 | | {0.8512303986474292, 0.4722343788582682, -0.2289137388687808}, |
144 | | {0.2846148069787909, 0.8644080972654203, -0.4144792552473538}, |
145 | | {-0.10554981496139187, 0.9794457296411412, 0.17188746100093646}, |
146 | | {-0.8075407579970092, 0.15335524858988167, 0.5695261994882688}, |
147 | | {-0.8512303986474292, -0.4722343788582682, 0.22891373886878083}, |
148 | | {-0.2846148069787909, -0.8644080972654203, 0.4144792552473538}, |
149 | | {0.10554981496139185, -0.9794457296411412, -0.17188746100093638}, |
150 | | {0.7405621473854482, -0.6673299564565524, -0.07898376463267347}, |
151 | | {0.8075407579970092, -0.15335524858988167, -0.5695261994882688}, |
152 | | {-0.7428567301586793, 0.35939416782780276, -0.5648005936517034}, |
153 | | {-0.8112534709140969, -0.34489532376393844, -0.47213877364139306}, |
154 | | {-0.21993077914046083, -0.6583691780274996, -0.7198475378926182}, |
155 | | {0.21392348345014195, -0.1478171829550702, -0.9656017935214206}, |
156 | | {-0.10926252787847963, 0.4811951572873209, -0.8697775121287253}, |
157 | | {-0.10926252787847968, 0.4811951572873209, -0.8697775121287253}, |
158 | | {-0.740562147385448, 0.6673299564565524, 0.07898376463267354}, |
159 | | {-0.7405621473854481, 0.6673299564565524, 0.07898376463267347}, |
160 | | {-0.7405621473854481, 0.6673299564565525, 0.07898376463267329}}; |
161 | | |
162 | | // /* |
163 | | // The points of the Airocean projection map are deduced from the unfolded |
164 | | // net of the altered icosahedron defined above. The distances in the |
165 | | // projected 2d space are expressed in meter. |
166 | | // */ |
167 | | // // Define the 23 unfolded surfaces used (from icosahedron + split faces) |
168 | | constexpr pj_face base_airocean_faces[23] = { |
169 | | {{1.8211859946200586, 3.1543866727148018, 1.0}, |
170 | | {1.8211859946200586, 4.205848896953069, 1.0}, |
171 | | {2.7317789919300877, 3.6801177848339353, 1.0}}, |
172 | | {{1.8211859946200586, 3.1543866727148018, 1.0}, |
173 | | {0.9105929973100293, 3.6801177848339353, 1.0}, |
174 | | {1.8211859946200586, 4.205848896953069, 1.0}}, |
175 | | {{1.8211859946200586, 3.1543866727148018, 1.0}, |
176 | | {0.9105929973100293, 2.628655560595668, 1.0}, |
177 | | {0.9105929973100293, 3.6801177848339353, 1.0}}, |
178 | | {{1.8211859946200586, 3.1543866727148018, 1.0}, |
179 | | {1.8211859946200586, 2.1029244484765344, 1.0}, |
180 | | {0.9105929973100293, 2.628655560595668, 1.0}}, |
181 | | {{1.8211859946200586, 3.1543866727148018, 1.0}, |
182 | | {2.7317789919300877, 3.6801177848339353, 1.0}, |
183 | | {2.7317789919300877, 2.628655560595668, 1.0}}, |
184 | | {{2.7317789919300877, 3.6801177848339353, 1.0}, |
185 | | {1.8211859946200586, 4.205848896953069, 1.0}, |
186 | | {2.7317789919300877, 4.731580009072203, 1.0}}, |
187 | | {{1.8211859946200586, 5.257311121191336, 1.0}, |
188 | | {1.8211859946200586, 4.205848896953069, 1.0}, |
189 | | {0.9105929973100293, 4.731580009072203, 1.0}}, |
190 | | {{0.9105929973100293, 4.731580009072203, 1.0}, |
191 | | {1.8211859946200586, 4.205848896953069, 1.0}, |
192 | | {0.9105929973100293, 3.6801177848339353, 1.0}}, |
193 | | {{0.9105929973100293, 2.628655560595668, 1.0}, |
194 | | {0.0, 3.1543866727148018, 1.0}, |
195 | | {0.9105929973100293, 3.6801177848339353, 1.0}}, |
196 | | {{0.9105929973100293, 2.628655560595668, 1.0}, |
197 | | {0.9105929973100293, 1.5771933363574009, 1.0}, |
198 | | {0.0, 2.1029244484765344, 1.0}}, |
199 | | {{0.9105929973100293, 2.628655560595668, 1.0}, |
200 | | {1.8211859946200586, 2.1029244484765344, 1.0}, |
201 | | {0.9105929973100293, 1.5771933363574009, 1.0}}, |
202 | | {{0.9105929973100293, 1.5771933363574009, 1.0}, |
203 | | {1.8211859946200586, 2.1029244484765344, 1.0}, |
204 | | {1.8211859946200586, 1.0514622242382672, 1.0}}, |
205 | | {{1.8211859946200586, 1.0514622242382672, 1.0}, |
206 | | {1.8211859946200586, 2.1029244484765344, 1.0}, |
207 | | {2.7317789919300877, 1.5771933363574009, 1.0}}, |
208 | | {{1.8211859946200586, 0.0, 1.0}, |
209 | | {1.8211859946200586, 1.0514622242382672, 1.0}, |
210 | | {2.7317789919300877, 0.5257311121191336, 1.0}}, |
211 | | {{0.0, 5.257311121191336, 1.0}, |
212 | | {0.9105929973100293, 4.731580009072203, 1.0}, |
213 | | {0.0, 4.205848896953069, 1.0}}, |
214 | | {{0.0, 1.0514622242382672, 1.0}, |
215 | | {0.0, 2.1029244484765344, 1.0}, |
216 | | {0.9105929973100293, 1.5771933363574009, 1.0}}, |
217 | | {{0.9105929973100293, 0.5257311121191336, 1.0}, |
218 | | {0.9105929973100293, 1.5771933363574009, 1.0}, |
219 | | {1.8211859946200586, 1.0514622242382672, 1.0}}, |
220 | | {{0.9105929973100293, 0.5257311121191336, 1.0}, |
221 | | {1.8211859946200586, 1.0514622242382672, 1.0}, |
222 | | {1.8211859946200586, 0.0, 1.0}}, |
223 | | {{0.9105929973100293, 4.731580009072203, 1.0}, |
224 | | {0.45529649865501465, 4.994445565131769, 1.0}, |
225 | | {0.9105929973100293, 5.78304223331047, 1.0}}, |
226 | | {{0.9105929973100293, 0.5257311121191336, 1.0}, |
227 | | {1.8211859946200586, 0.0, 1.0}, |
228 | | {0.9105929973100293, 0.0, 1.0}}, |
229 | | {{0.0, 4.205848896953069, 1.0}, |
230 | | {0.9105929973100293, 4.731580009072203, 1.0}, |
231 | | {0.6070619982066862, 4.205848896953069, 1.0}}, |
232 | | {{0.9105929973100293, 4.731580009072203, 1.0}, |
233 | | {0.9105929973100293, 3.6801177848339353, 1.0}, |
234 | | {0.6070619982066862, 4.205848896953069, 1.0}}, |
235 | | {{0.0, 3.1543866727148018, 1.0}, |
236 | | {0.3035309991033431, 3.6801177848339353, 1.0}, |
237 | | {0.9105929973100293, 3.6801177848339353, 1.0}}}; |
238 | | |
239 | | // /* |
240 | | // The parameters here are extracted from the transition matrices |
241 | | // that allow converting a icosahedron face or subface to its |
242 | | // corresponding face in the Airocean projected space. |
243 | | // Since only a few parameters of those matrices are relevant, |
244 | | // the irrelevant ones has been discarded. |
245 | | // */ |
246 | | // // Icosahedron to Airocean (forward) |
247 | | constexpr double base_ico_air_trans[23][4][4] = { |
248 | | {{0.5771127852625935, -0.6019490725122667, -0.5519041105011566, |
249 | | 2.1247169937234016}, |
250 | | {0.09385435001257117, 0.7202114479424703, -0.6873767753105484, |
251 | | 3.6801177848339357}, |
252 | | {0.8112534709140967, 0.3448953237639384, 0.4721387736413929, |
253 | | -0.7946544722917659}, |
254 | | {0.0, 0.0, 0.0, 1.0}}, |
255 | | {{0.9709901201198636, -0.2187361325341673, -0.09660585361978567, |
256 | | 1.5176549955167156}, |
257 | | {0.09385435001257089, 0.7202114479424708, -0.687376775310548, |
258 | | 3.6801177848339353}, |
259 | | {0.21993077914046077, 0.6583691780274995, 0.7198475378926181, |
260 | | -0.7946544722917659}, |
261 | | {0.0, 0.0, 0.0, 1.0}}, |
262 | | {{0.9721374115064793, -0.06476823821979226, 0.2252863255224028, |
263 | | 1.2141239964133725}, |
264 | | {0.09584151698527507, 0.9868916636293633, -0.12984316647721492, |
265 | | 3.1543866727148013}, |
266 | | {-0.21392348345014195, 0.1478171829550702, 0.9656017935214207, |
267 | | -0.7946544722917663}, |
268 | | {0.0, 0.0, 0.0, 1.0}}, |
269 | | {{0.9921258753731454, -0.0010987106726278763, -0.1252399307326839, |
270 | | 1.5176549955167151}, |
271 | | {0.06122048200295415, 0.8766128070237673, 0.47728611874350335, |
272 | | 2.6286555605956674}, |
273 | | {0.10926252787847969, -0.4811951572873209, 0.8697775121287256, |
274 | | -0.7946544722917663}, |
275 | | {0.0, 0.0, 0.0, 1.0}}, |
276 | | {{0.28030414798915965, -0.5991800396948614, -0.7499419075177327, |
277 | | 2.428247992826745}, |
278 | | {0.6079419898954396, 0.7154153424148981, -0.34436524905882676, |
279 | | 3.1543866727148013}, |
280 | | {0.742856730158679, -0.3593941678278027, 0.5648005936517032, |
281 | | -0.794654472291766}, |
282 | | {0.0, 0.0, 0.0, 1.0}}, |
283 | | {{0.25960661905056537, -0.7580069591045613, -0.5983559586852888, |
284 | | 2.428247992826744}, |
285 | | {-0.4560824615830708, 0.4499112594427941, -0.7678337364709403, |
286 | | 4.205848896953069}, |
287 | | {0.8512303986474292, 0.47223437885826813, -0.22891373886878083, |
288 | | -0.7946544722917661}, |
289 | | {0.0, 0.0, 0.0, 1.0}}, |
290 | | {{0.958636570067365, -0.258086064605963, 0.12003128669511368, |
291 | | 1.5176549955167158}, |
292 | | {-0.003215303703157293, -0.43149765310854393, -0.9021083289627215, |
293 | | 4.731580009072202}, |
294 | | {0.2846148069787908, 0.8644080972654206, -0.41447925524735385, |
295 | | -0.7946544722917662}, |
296 | | {0.0, 0.0, 0.0, 1.0}}, |
297 | | {{0.992834940445074, 0.09405868118990741, 0.07370037668995856, |
298 | | 1.2141239964133723}, |
299 | | {0.056018011327093935, 0.17843493822832973, -0.982355819052552, |
300 | | 4.205848896953068}, |
301 | | {-0.10554981496139189, 0.9794457296411413, 0.17188746100093644, |
302 | | -0.7946544722917662}, |
303 | | {0.0, 0.0, 0.0, 1.0}}, |
304 | | {{0.5819727895662967, 0.05026939415592827, 0.8116530417706931, |
305 | | 0.6070619982066865}, |
306 | | {0.09584151698527442, 0.9868916636293634, -0.1298431664772149, |
307 | | 3.1543866727148013}, |
308 | | {-0.8075407579970093, 0.1533552485898817, 0.5695261994882689, |
309 | | -0.7946544722917663}, |
310 | | {0.0, 0.0, 0.0, 1.0}}, |
311 | | {{0.5247823074767625, -0.7686380596783918, 0.36578554232391575, |
312 | | 0.6070619982066867}, |
313 | | {0.0032153037031566203, 0.4314976531085445, 0.9021083289627214, |
314 | | 2.102924448476535}, |
315 | | {-0.8512303986474292, -0.47223437885826813, 0.22891373886878078, |
316 | | -0.7946544722917661}, |
317 | | {0.0, 0.0, 0.0, 1.0}}, |
318 | | {{0.9586365700673652, -0.2580860646059632, 0.12003128669511379, |
319 | | 1.2141239964133719}, |
320 | | {0.003215303703156878, 0.43149765310854465, 0.9021083289627218, |
321 | | 2.1029244484765344}, |
322 | | {-0.2846148069787909, -0.8644080972654204, 0.4144792552473538, |
323 | | -0.7946544722917662}, |
324 | | {0.0, 0.0, 0.0, 1.0}}, |
325 | | {{0.9928349404450738, 0.0940586811899076, 0.07370037668995869, |
326 | | 1.5176549955167153}, |
327 | | {-0.05601801132709388, -0.17843493822832968, 0.9823558190525513, |
328 | | 1.5771933363574009}, |
329 | | {0.10554981496139189, -0.9794457296411413, -0.17188746100093644, |
330 | | -0.7946544722917662}, |
331 | | {0.0, 0.0, 0.0, 1.0}}, |
332 | | {{0.6696489291164518, 0.7230710214322986, 0.1695246580826539, |
333 | | 2.1247169937234016}, |
334 | | {-0.05601801132709365, -0.17843493822832943, 0.9823558190525516, |
335 | | 1.5771933363574009}, |
336 | | {0.7405621473854482, -0.6673299564565524, -0.07898376463267347, |
337 | | -0.7946544722917662}, |
338 | | {0.0, 0.0, 0.0, 1.0}}, |
339 | | {{0.5819727895662965, 0.050269394155928314, 0.811653041770693, |
340 | | 2.1247169937234016}, |
341 | | {-0.09584151698527484, -0.9868916636293626, 0.129843166477215, |
342 | | 0.5257311121191333}, |
343 | | {0.8075407579970093, -0.1533552485898817, -0.5695261994882689, |
344 | | -0.7946544722917663}, |
345 | | {0.0, 0.0, 0.0, 1.0}}, |
346 | | {{0.3863411332821331, 0.9191578806358752, 0.07674189989336716, |
347 | | 0.30353099910334314}, |
348 | | {0.5467215078924839, -0.16119746460886833, -0.8216513678023304, |
349 | | 4.731580009072203}, |
350 | | {-0.742856730158679, 0.35939416782780265, -0.5648005936517032, |
351 | | -0.794654472291766}, |
352 | | {0.0, 0.0, 0.0, 1.0}}, |
353 | | {{0.20727614126473407, -0.9246959462706865, 0.31933369413978446, |
354 | | 0.303530999103343}, |
355 | | {-0.5467215078924849, 0.1611974646088691, 0.8216513678023303, |
356 | | 1.5771933363574007}, |
357 | | {-0.8112534709140967, -0.34489532376393833, -0.47213877364139295, |
358 | | -0.794654472291766}, |
359 | | {0.0, 0.0, 0.0, 1.0}}, |
360 | | {{0.9709901201198639, -0.21873613253416718, -0.09660585361978535, |
361 | | 1.2141239964133725}, |
362 | | {-0.09385435001257073, -0.7202114479424704, 0.6873767753105484, |
363 | | 1.0514622242382674}, |
364 | | {-0.21993077914046086, -0.6583691780274995, -0.719847537892618, |
365 | | -0.794654472291766}, |
366 | | {0.0, 0.0, 0.0, 1.0}}, |
367 | | {{0.9721374115064794, -0.0647682382197923, 0.2252863255224031, |
368 | | 1.5176549955167156}, |
369 | | {-0.09584151698527477, -0.9868916636293626, 0.12984316647721514, |
370 | | 0.5257311121191336}, |
371 | | {0.21392348345014198, -0.1478171829550702, -0.9656017935214205, |
372 | | -0.7946544722917661}, |
373 | | {0.0, 0.0, 0.0, 1.0}}, |
374 | | {{0.5490814303330593, 0.7586196048290541, 0.350721938339208, |
375 | | 0.6070619982066862}, |
376 | | {0.8285959708235409, -0.43925791486578636, -0.3471040209544599, |
377 | | 5.257311121191335}, |
378 | | {-0.10926252787847968, 0.48119515728732093, -0.8697775121287254, |
379 | | -0.7946544722917663}, |
380 | | {0.0, 0.0, 0.0, 1.0}}, |
381 | | {{0.9921258753731453, -0.0010987106726278503, -0.125239930732684, |
382 | | 1.2141239964133725}, |
383 | | {-0.061220482002954366, -0.8766128070237673, -0.4772861187435034, 0.0}, |
384 | | {-0.10926252787847965, 0.48119515728732093, -0.8697775121287254, |
385 | | -0.7946544722917663}, |
386 | | {0.0, 0.0, 0.0, 1.0}}, |
387 | | {{0.6696489291164521, 0.7230710214322988, 0.169524658082654, |
388 | | 0.607061998206686}, |
389 | | {0.05601801132709396, 0.17843493822832968, -0.9823558190525518, |
390 | | 4.205848896953069}, |
391 | | {-0.7405621473854482, 0.6673299564565525, 0.07898376463267334, |
392 | | -0.7946544722917662}, |
393 | | {0.0, 0.0, 0.0, 1.0}}, |
394 | | {{0.6696489291164525, 0.7230710214322987, 0.1695246580826538, |
395 | | 0.6070619982066863}, |
396 | | {0.05601801132709517, 0.1784349382283307, -0.9823558190525518, |
397 | | 4.205848896953069}, |
398 | | {-0.7405621473854483, 0.6673299564565526, 0.07898376463267348, |
399 | | -0.7946544722917663}, |
400 | | {0.0, 0.0, 0.0, 1.0}}, |
401 | | {{0.28631144367947836, 0.20700632128770896, 0.9355074238963061, |
402 | | 0.3035309991033428}, |
403 | | {0.6079419898954391, 0.7154153424148978, -0.3443652490588263, |
404 | | 3.6801177848339357}, |
405 | | {-0.7405621473854481, 0.6673299564565525, 0.07898376463267341, |
406 | | -0.7946544722917661}, |
407 | | {0.0, 0.0, 0.0, 1.0}}}; |
408 | | // // Airocean to Icosahedron (inverse) |
409 | | constexpr double base_air_ico_trans[23][4][4] = { |
410 | | {{0.577112785262594, 0.09385435001257074, 0.8112534709140972, |
411 | | -0.9269302059836626}, |
412 | | {-0.6019490725122669, 0.7202114479424705, 0.3448953237639385, |
413 | | -1.0974189231897016}, |
414 | | {-0.5519041105011576, -0.6873767753105482, 0.47213877364139284, |
415 | | 4.0774547262062395}, |
416 | | {0.0, 0.0, 0.0, 1.0}}, |
417 | | {{0.970990120119864, 0.09385435001257075, 0.21993077914046097, |
418 | | -1.6442540918239978}, |
419 | | {-0.21873613253416777, 0.7202114479424705, 0.6583691780274992, |
420 | | -1.7953209624349933}, |
421 | | {-0.09660585361978517, -0.6873767753105485, 0.7198475378926187, |
422 | | 3.248271917398959}, |
423 | | {0.0, 0.0, 0.0, 1.0}}, |
424 | | {{0.9721374115064793, 0.09584151698527468, -0.21392348345014173, |
425 | | -1.6526118158442071}, |
426 | | {-0.06476823821979319, 0.9868916636293628, 0.14781718295507035, |
427 | | -2.916937653420916}, |
428 | | {0.22528632552240307, -0.12984316647721503, 0.9656017935214205, |
429 | | 0.9033698036730199}, |
430 | | {0.0, 0.0, 0.0, 1.0}}, |
431 | | {{0.9921258753731454, 0.061220482002954296, 0.10926252787847969, |
432 | | -1.5798063949483236}, |
433 | | {-0.0010987106726281115, 0.8766128070237668, -0.48119515728732043, |
434 | | -2.68502954971497}, |
435 | | {-0.12523993073268413, 0.4772861187435032, 0.8697775121287253, |
436 | | -0.3733772136037109}, |
437 | | {0.0, 0.0, 0.0, 1.0}}, |
438 | | {{0.2803041479891603, 0.6079419898954391, 0.7428567301586791, |
439 | | -2.0080176725529477}, |
440 | | {-0.5991800396948611, 0.7154153424148979, -0.35939416782780287, |
441 | | -1.0873330756182955}, |
442 | | {-0.7499419075177335, -0.3443652490588265, 0.5648005936517035, |
443 | | 3.3561274015422433}, |
444 | | {0.0, 0.0, 0.0, 1.0}}, |
445 | | {{0.2596066190505654, -0.4560824615830712, 0.8512303986474292, |
446 | | 1.9642587095706099}, |
447 | | {-0.7580069591045617, 0.4499112594427949, 0.47223437885826836, |
448 | | 0.3236332638697585}, |
449 | | {-0.5983559586852887, -0.7678337364709401, -0.22891373886878078, |
450 | | 4.500442002892026}, |
451 | | {0.0, 0.0, 0.0, 1.0}}, |
452 | | {{0.958636570067365, -0.003215303703156967, 0.28461480697879094, |
453 | | -1.2134956834766393}, |
454 | | {-0.2580860646059631, -0.43149765310854504, 0.8644080972654203, |
455 | | 3.1202570350096352}, |
456 | | {0.12003128669511316, -0.9021083289627222, -0.4144792552473535, |
457 | | 3.756863859611938}, |
458 | | {0.0, 0.0, 0.0, 1.0}}, |
459 | | {{0.992834940445074, 0.05601801132709367, -0.10554981496139178, |
460 | | -1.5249036493302057}, |
461 | | {0.09405868118990754, 0.17843493822832954, 0.9794457296411412, |
462 | | -0.08634836060276646}, |
463 | | {0.07370037668995799, -0.9823558190525513, 0.1718874610009362, |
464 | | 4.17874988170889}, |
465 | | {0.0, 0.0, 0.0, 1.0}}, |
466 | | {{0.581972789566297, 0.09584151698527493, -0.8075407579970092, |
467 | | -1.297330643307362}, |
468 | | {0.05026939415592872, 0.986891663629363, 0.15335524858988142, |
469 | | -3.0216901158893736}, |
470 | | {0.8116530417706934, -0.12984316647721506, 0.5695261994882689, |
471 | | 0.3694283780016493}, |
472 | | {0.0, 0.0, 0.0, 1.0}}, |
473 | | {{0.5247823074767624, 0.0032153037031565812, -0.8512303986474291, |
474 | | -1.0017709802028867}, |
475 | | {-0.7686380596783923, 0.431497653108545, -0.47223437885826824, |
476 | | -0.8160591689057779}, |
477 | | {0.36578554232391597, 0.9021083289627221, 0.22891373886878089, |
478 | | -1.937212836027187}, |
479 | | {0.0, 0.0, 0.0, 1.0}}, |
480 | | {{0.9586365700673654, 0.0032153037031565886, -0.2846148069787907, |
481 | | -1.3968356335709964}, |
482 | | {-0.258086064605963, 0.43149765310854504, -0.8644080972654202, |
483 | | -1.2809642403813966}, |
484 | | {0.12003128669511362, 0.9021083289627224, 0.41447925524735396, |
485 | | -1.7134307317924613}, |
486 | | {0.0, 0.0, 0.0, 1.0}}, |
487 | | {{0.9928349404450739, -0.05601801132709361, 0.10554981496139221, |
488 | | -1.3345540404002831}, |
489 | | {0.09405868118990741, -0.17843493822832956, -0.9794457296411411, |
490 | | -0.639643161258916}, |
491 | | {0.07370037668995856, 0.982355819052552, -0.17188746100093616, |
492 | | -1.7978079362118518}, |
493 | | {0.0, 0.0, 0.0, 1.0}}, |
494 | | {{0.6696489291164524, -0.056018011327093886, 0.7405621473854481, |
495 | | -0.7459722029114777}, |
496 | | {0.723071021432299, -0.1784349382283297, -0.6673299564565522, |
497 | | -1.7851916257515466}, |
498 | | {0.16952465808265363, 0.9823558190525522, -0.07898376463267373, |
499 | | -1.9723217754287594}, |
500 | | {0.0, 0.0, 0.0, 1.0}}, |
501 | | {{0.5819727895662968, -0.09584151698527477, 0.8075407579970091, |
502 | | -0.5444247336640644}, |
503 | | {0.05026939415592821, -0.9868916636293631, -0.15335524858988164, |
504 | | 0.29016698169232114}, |
505 | | {0.8116530417706935, 0.1298431664772151, -0.569526199488269, |
506 | | -2.2453721446813035}, |
507 | | {0.0, 0.0, 0.0, 1.0}}, |
508 | | {{0.3863411332821329, 0.5467215078924852, -0.7428567301586795, |
509 | | -3.2944374903463687}, |
510 | | {0.9191578806358753, -0.16119746460886916, 0.3593941678278029, |
511 | | 0.7693199739932717}, |
512 | | {0.07674189989336772, -0.8216513678023304, -0.564800593651703, |
513 | | 3.4155943230742447}, |
514 | | {0.0, 0.0, 0.0, 1.0}}, |
515 | | {{0.20727614126473443, -0.546721507892485, -0.8112534709140969, |
516 | | 0.15470458601882164}, |
517 | | {-0.9246959462706867, 0.16119746460886913, -0.3448953237639384, |
518 | | -0.24763829408199384}, |
519 | | {0.31933369413978435, 0.8216513678023302, -0.4721387736413931, |
520 | | -1.768017925352872}, |
521 | | {0.0, 0.0, 0.0, 1.0}}, |
522 | | {{0.9709901201198642, -0.09385435001257068, -0.21993077914046077, |
523 | | -1.2549870787377553}, |
524 | | {-0.2187361325341676, -0.7202114479424703, -0.6583691780274997, |
525 | | 0.4996719066292349}, |
526 | | {-0.09660585361978546, 0.6873767753105482, -0.7198475378926181, |
527 | | -1.1774892933385632}, |
528 | | {0.0, 0.0, 0.0, 1.0}}, |
529 | | {{0.9721374115064794, -0.09584151698527459, 0.21392348345014212, |
530 | | -1.2549870787377553}, |
531 | | {-0.06476823821979266, -0.9868916636293628, -0.14781718295507024, |
532 | | 0.49967190662923483}, |
533 | | {0.2252863255224028, 0.12984316647721506, -0.9656017935214204, |
534 | | -1.1774892933385632}, |
535 | | {0.0, 0.0, 0.0, 1.0}}, |
536 | | {{0.5490814303330579, 0.8285959708235412, -0.10926252787847955, |
537 | | -4.776339239093644}, |
538 | | {0.7586196048290552, -0.4392579148657884, 0.4811951572873209, |
539 | | 2.231170271492442}, |
540 | | {0.3507219383392087, -0.3471040209544594, -0.8697775121287253, |
541 | | 0.9207512789590909}, |
542 | | {0.0, 0.0, 0.0, 1.0}}, |
543 | | {{0.9921258753731456, -0.061220482002954546, -0.10926252787847962, |
544 | | -1.2913897891856965}, |
545 | | {-0.00109871067262767, -0.8766128070237672, 0.48119515728732093, |
546 | | 0.38371785477626236}, |
547 | | {-0.12523993073268386, -0.47728611874350324, -0.8697775121287252, |
548 | | -0.5391157847001973}, |
549 | | {0.0, 0.0, 0.0, 1.0}}, |
550 | | {{0.6696489291164526, 0.0560180113270932, -0.7405621473854482, |
551 | | -1.2306127305858023}, |
552 | | {0.723071021432299, 0.17843493822832968, 0.6673299564565522, |
553 | | -0.6591225928490807}, |
554 | | {0.16952465808265377, -0.9823558190525503, 0.07898376463267326, |
555 | | 4.09149296210043}, |
556 | | {0.0, 0.0, 0.0, 1.0}}, |
557 | | {{0.669648929116452, 0.056018011327093706, -0.740562147385448, |
558 | | -1.230612730585803}, |
559 | | {0.7230710214322988, 0.1784349382283296, 0.6673299564565524, |
560 | | -0.6591225928490807}, |
561 | | {0.1695246580826554, -0.9823558190525514, 0.0789837646326731, |
562 | | 4.091492962100434}, |
563 | | {0.0, 0.0, 0.0, 1.0}}, |
564 | | {{0.2863114436794785, 0.6079419898954399, -0.7405621473854486, |
565 | | -2.9126935501461353}, |
566 | | {0.2070063212877089, 0.7154153424148983, 0.6673299564565521, |
567 | | -2.165348826292825}, |
568 | | {0.935507423896306, -0.3443652490588271, 0.07898376463267351, |
569 | | 1.046113976300111}, |
570 | | {0.0, 0.0, 0.0, 1.0}}}; |
571 | | |
572 | | // By default the resulting orientation of the projection is vertical |
573 | | // the following transforms are used to alter the projection data |
574 | | // so that the resulting orientation is horizontal instead |
575 | | constexpr double orient_horizontal_trans[4][4] = { |
576 | | {0.0, -1.0, 0.0, 5.78304223331047}, |
577 | | {1.0, 0.0, 0.0, 0.0}, |
578 | | {0.0, 0.0, 1.0, 0.0}, |
579 | | {0.0, 0.0, 0.0, 1.0}}; |
580 | | constexpr double orient_horizontal_inv_trans[4][4] = { |
581 | | {0.0, 1.0, 0.0, 0.0}, |
582 | | {-1.0, -0.0, -0.0, 5.78304223331047}, |
583 | | {0.0, 0.0, 1.0, 0.0}, |
584 | | {0.0, 0.0, 0.0, 1.0}}; |
585 | | |
586 | | namespace { // anonymous namespace |
587 | | |
588 | | struct pj_airocean_data { |
589 | | pj_face ico_faces[23] = {}; |
590 | | PJ_XYZ ico_centers[23] = {}; |
591 | | PJ_XYZ ico_normals[23] = {}; |
592 | | pj_face airocean_faces[23] = {}; |
593 | | double ico_air_trans[23][4][4] = {}; |
594 | | double air_ico_trans[23][4][4] = {}; |
595 | | |
596 | 0 | void initialize() { |
597 | 0 | memcpy(this->ico_faces, base_ico_faces, sizeof(pj_face[23])); |
598 | 0 | memcpy(this->airocean_faces, base_airocean_faces, sizeof(pj_face[23])); |
599 | 0 | memcpy(this->ico_centers, base_ico_centers, sizeof(PJ_XYZ[23])); |
600 | 0 | memcpy(this->ico_normals, base_ico_normals, sizeof(PJ_XYZ[23])); |
601 | 0 | memcpy(this->ico_air_trans, base_ico_air_trans, |
602 | 0 | sizeof(double[23][4][4])); |
603 | 0 | memcpy(this->air_ico_trans, base_air_ico_trans, |
604 | 0 | sizeof(double[23][4][4])); |
605 | 0 | } |
606 | | |
607 | | static void mat_mult(const double m1[4][4], const double m2[4][4], |
608 | 0 | double res[4][4]) { |
609 | 0 | for (unsigned char i = 0; i < 4; ++i) |
610 | 0 | for (unsigned char j = 0; j < 4; ++j) |
611 | 0 | res[i][j] = (m1[i][0] * m2[0][j]) + (m1[i][1] * m2[1][j]) + |
612 | 0 | (m1[i][2] * m2[2][j]) + (m1[i][3] * m2[3][j]); |
613 | 0 | } |
614 | | |
615 | 0 | static PJ_XYZ vec_mult(const double m[4][4], const PJ_XYZ *v) { |
616 | 0 | double x = m[0][0] * v->x + m[0][1] * v->y + m[0][2] * v->z + m[0][3]; |
617 | 0 | double y = m[1][0] * v->x + m[1][1] * v->y + m[1][2] * v->z + m[1][3]; |
618 | 0 | double z = m[2][0] * v->x + m[2][1] * v->y + m[2][2] * v->z + m[2][3]; |
619 | 0 | return {x, y, z}; |
620 | 0 | } |
621 | | |
622 | 0 | void transform(const double m[4][4], const double inv_m[4][4]) { |
623 | 0 | for (unsigned char i = 0; i < 23; i++) { |
624 | 0 | mat_mult(m, base_ico_air_trans[i], this->ico_air_trans[i]); |
625 | 0 | mat_mult(base_air_ico_trans[i], inv_m, this->air_ico_trans[i]); |
626 | 0 | this->airocean_faces[i] = { |
627 | 0 | vec_mult(m, &base_airocean_faces[i].p1), |
628 | 0 | vec_mult(m, &base_airocean_faces[i].p2), |
629 | 0 | vec_mult(m, &base_airocean_faces[i].p3), |
630 | 0 | }; |
631 | 0 | } |
632 | 0 | } |
633 | | }; |
634 | | |
635 | | } // anonymous namespace |
636 | | |
637 | 0 | inline double det(const PJ_XYZ *u, const PJ_XYZ *v, const PJ_XYZ *w) { |
638 | 0 | return (u->x * (v->y * w->z - v->z * w->y) - |
639 | 0 | v->x * (u->y * w->z - u->z * w->y) + |
640 | 0 | w->x * (u->y * v->z - u->z * v->y)); |
641 | 0 | } |
642 | | |
643 | 0 | inline bool is_point_in_face(const PJ_XYZ *p, const pj_face *face) { |
644 | 0 | return (det(p, &face->p2, &face->p3) <= 0 && |
645 | 0 | det(&face->p1, p, &face->p3) <= 0 && |
646 | 0 | det(&face->p1, &face->p2, p) <= 0); |
647 | 0 | } |
648 | | |
649 | | inline unsigned char get_ico_face_index(const pj_airocean_data *pj_data, |
650 | 0 | const PJ_XYZ *p) { |
651 | 0 | for (unsigned char i = 0; i < 23; i++) { |
652 | 0 | if (is_point_in_face(p, &pj_data->ico_faces[i])) { |
653 | 0 | return i; |
654 | 0 | } |
655 | 0 | } |
656 | | |
657 | 0 | return 23; |
658 | 0 | } |
659 | | |
660 | | inline unsigned char get_dym_face_index(const pj_airocean_data *pj_data, |
661 | 0 | const PJ_XY *p) { |
662 | 0 | const PJ_XYZ pp{p->x, p->y, 1.0}; |
663 | 0 | for (unsigned char i = 0; i < 23; i++) { |
664 | 0 | if (is_point_in_face(&pp, &pj_data->airocean_faces[i])) { |
665 | 0 | return i; |
666 | 0 | } |
667 | 0 | } |
668 | | |
669 | 0 | return 23; |
670 | 0 | } |
671 | | |
672 | | inline PJ_XY ico_to_dym(const pj_airocean_data *pj_data, const PJ_XYZ *p, |
673 | 0 | unsigned char face_id) { |
674 | 0 | return PJ_XY{ |
675 | 0 | pj_data->ico_air_trans[face_id][0][0] * p->x + // * -1 |
676 | 0 | pj_data->ico_air_trans[face_id][0][1] * p->y + // |
677 | 0 | pj_data->ico_air_trans[face_id][0][2] * p->z + // |
678 | 0 | pj_data->ico_air_trans[face_id][0][3], // +1000 |
679 | 0 | pj_data->ico_air_trans[face_id][1][0] * p->x + |
680 | 0 | pj_data->ico_air_trans[face_id][1][1] * p->y + |
681 | 0 | pj_data->ico_air_trans[face_id][1][2] * p->z + |
682 | 0 | pj_data->ico_air_trans[face_id][1][3], |
683 | 0 | }; |
684 | 0 | } |
685 | | |
686 | | inline PJ_XYZ dym_to_ico(const pj_airocean_data *pj_data, const PJ_XY *p, |
687 | 0 | unsigned char face_id) { |
688 | 0 | return PJ_XYZ{ |
689 | 0 | pj_data->air_ico_trans[face_id][0][0] * p->x + // * -1 |
690 | 0 | pj_data->air_ico_trans[face_id][0][1] * p->y + // |
691 | 0 | pj_data->air_ico_trans[face_id][0][3], // + [face_id][0][0] * 1000 |
692 | 0 | pj_data->air_ico_trans[face_id][1][0] * p->x + |
693 | 0 | pj_data->air_ico_trans[face_id][1][1] * p->y + |
694 | 0 | pj_data->air_ico_trans[face_id][1][3], |
695 | 0 | pj_data->air_ico_trans[face_id][2][0] * p->x + |
696 | 0 | pj_data->air_ico_trans[face_id][2][1] * p->y + |
697 | 0 | pj_data->air_ico_trans[face_id][2][3], |
698 | 0 | }; |
699 | 0 | } |
700 | | |
701 | | inline PJ_XYZ cartesian_to_ico(const pj_airocean_data *pj_data, const PJ_XYZ *p, |
702 | 0 | unsigned char face_id) { |
703 | 0 | const PJ_XYZ *center = &pj_data->ico_centers[face_id]; |
704 | 0 | const PJ_XYZ *normal = &pj_data->ico_normals[face_id]; |
705 | | |
706 | | // cppcheck-suppress unreadVariable |
707 | 0 | double a = |
708 | 0 | 1.0 - (center->x * normal->x + center->y * normal->y + |
709 | 0 | center->z * normal->z) / |
710 | 0 | (p->x * normal->x + p->y * normal->y + p->z * normal->z); |
711 | |
|
712 | 0 | return PJ_XYZ{ |
713 | 0 | p->x - a * p->x, |
714 | 0 | p->y - a * p->y, |
715 | 0 | p->z - a * p->z, |
716 | 0 | }; |
717 | 0 | } |
718 | | |
719 | | // ============================================ |
720 | | // |
721 | | // The Forward and Inverse Functions |
722 | | // |
723 | | // ============================================ |
724 | 0 | static PJ_XY airocean_forward(PJ_LP lp, PJ *P) { |
725 | 0 | const struct pj_airocean_data *Q = |
726 | 0 | static_cast<struct pj_airocean_data *>(P->opaque); |
727 | |
|
728 | 0 | double lat; |
729 | | |
730 | | /* Convert the geodetic latitude to a geocentric latitude. |
731 | | * This corresponds to the shift from the ellipsoid to the sphere |
732 | | * described in [LK12]. */ |
733 | 0 | if (P->es != 0.0) { |
734 | 0 | double one_minus_f = 1.0 - (P->a - P->b) / P->a; |
735 | 0 | double one_minus_f_squared = one_minus_f * one_minus_f; |
736 | 0 | lat = atan(one_minus_f_squared * tan(lp.phi)); |
737 | 0 | } else { |
738 | 0 | lat = lp.phi; |
739 | 0 | } |
740 | | |
741 | | // Convert the lat/long to x,y,z on the unit sphere |
742 | 0 | double x, y, z; |
743 | 0 | double sinlat, coslat; |
744 | 0 | double sinlon, coslon; |
745 | |
|
746 | 0 | sinlat = sin(lat); |
747 | 0 | coslat = cos(lat); |
748 | 0 | sinlon = sin(lp.lam); |
749 | 0 | coslon = cos(lp.lam); |
750 | 0 | x = coslat * coslon; |
751 | 0 | y = coslat * sinlon; |
752 | 0 | z = sinlat; |
753 | |
|
754 | 0 | PJ_XYZ cartesianPoint{x, y, z}; |
755 | |
|
756 | 0 | unsigned char face_id = get_ico_face_index(Q, &cartesianPoint); |
757 | 0 | if (face_id == 23) { |
758 | | // not sure this can happen |
759 | 0 | proj_errno_set(P, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN); |
760 | 0 | PJ_XY xy; |
761 | 0 | xy.x = HUGE_VAL; |
762 | 0 | xy.y = HUGE_VAL; |
763 | 0 | return xy; |
764 | 0 | } |
765 | | |
766 | 0 | PJ_XYZ icoPoint = cartesian_to_ico(Q, &cartesianPoint, face_id); |
767 | |
|
768 | 0 | PJ_XY airoceanPoint = ico_to_dym(Q, &icoPoint, face_id); |
769 | |
|
770 | 0 | return airoceanPoint; |
771 | 0 | } |
772 | | |
773 | 0 | static PJ_LP airocean_inverse(PJ_XY xy, PJ *P) { |
774 | 0 | const struct pj_airocean_data *Q = |
775 | 0 | static_cast<struct pj_airocean_data *>(P->opaque); |
776 | |
|
777 | 0 | PJ_LP lp = {0.0, 0.0}; |
778 | |
|
779 | 0 | unsigned char face_id = get_dym_face_index(Q, &xy); |
780 | |
|
781 | 0 | if (face_id == 23) { |
782 | | // Point lies outside icosahedron net faces |
783 | 0 | proj_errno_set(P, PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN); |
784 | 0 | lp.lam = HUGE_VAL; |
785 | 0 | lp.phi = HUGE_VAL; |
786 | 0 | return lp; |
787 | 0 | } |
788 | | |
789 | 0 | PJ_XYZ sphereCoords = dym_to_ico(Q, &xy, face_id); |
790 | |
|
791 | 0 | double norm = sqrt((sphereCoords.x * sphereCoords.x) + |
792 | 0 | (sphereCoords.y * sphereCoords.y) + |
793 | 0 | (sphereCoords.z * sphereCoords.z)); |
794 | 0 | double q = sphereCoords.x / norm; |
795 | 0 | double r = sphereCoords.y / norm; |
796 | 0 | double s = sphereCoords.z / norm; |
797 | | |
798 | | // Get the spherical angles from the x y z |
799 | 0 | lp.phi = acos(-s) - M_HALFPI; |
800 | 0 | lp.lam = atan2(r, q); |
801 | | |
802 | | /* Apply the shift from the sphere to the ellipsoid as described |
803 | | * in [LK12]. */ |
804 | 0 | if (P->es != 0.0) { |
805 | 0 | int invert_sign; |
806 | 0 | volatile double tanphi, xa; |
807 | 0 | invert_sign = (lp.phi < 0.0 ? 1 : 0); |
808 | 0 | tanphi = tan(lp.phi); |
809 | 0 | double one_minus_f = 1.0 - (P->a - P->b) / P->a; |
810 | 0 | double a_squared = P->a * P->a; |
811 | 0 | xa = P->b / sqrt(tanphi * tanphi + one_minus_f * one_minus_f); |
812 | 0 | lp.phi = atan(sqrt(a_squared - xa * xa) / (one_minus_f * xa)); |
813 | 0 | if (invert_sign) { |
814 | 0 | lp.phi = -lp.phi; |
815 | 0 | } |
816 | 0 | } |
817 | |
|
818 | 0 | return lp; |
819 | 0 | } |
820 | | |
821 | 0 | PJ *PJ_PROJECTION(airocean) { |
822 | 0 | char *opt; |
823 | 0 | struct pj_airocean_data *Q = static_cast<struct pj_airocean_data *>( |
824 | 0 | calloc(1, sizeof(struct pj_airocean_data))); |
825 | 0 | if (nullptr == Q) |
826 | 0 | return pj_default_destructor(P, PROJ_ERR_OTHER /*ENOMEM*/); |
827 | 0 | Q->initialize(); |
828 | 0 | P->opaque = Q; |
829 | 0 | opt = pj_param(P->ctx, P->params, "sorient").s; |
830 | 0 | if (opt) { |
831 | 0 | if (!strcmp(opt, "horizontal")) { |
832 | 0 | Q->transform(orient_horizontal_trans, orient_horizontal_inv_trans); |
833 | 0 | } else if (!strcmp(opt, "vertical")) { |
834 | | // the orientation is vertical by default. |
835 | 0 | } else { |
836 | 0 | proj_log_error(P, _("Invalid value for orient: only vertical or " |
837 | 0 | "horizontal are supported")); |
838 | 0 | return pj_default_destructor(P, |
839 | 0 | PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE); |
840 | 0 | } |
841 | 0 | } |
842 | | |
843 | 0 | P->inv = airocean_inverse; |
844 | 0 | P->fwd = airocean_forward; |
845 | |
|
846 | 0 | return P; |
847 | 0 | } |