OmniSciDB  6686921089
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
faceijk.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-2020 Uber Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
22 
23 // #include <assert.h>
24 // #include <math.h>
25 // #include <stdio.h>
26 // #include <stdlib.h>
27 // #include <string.h>
28 
29 // #include "constants.h"
30 // #include "coordijk.h"
34 
36 #define M_SQRT7 2.6457513110645905905016157536392604257102
37 
39 DEVICE const GeoCoordArray(faceCenterGeo, NUM_ICOSA_FACES) = {
40  {0.803582649718989942, 1.248397419617396099}, // face 0
41  {1.307747883455638156, 2.536945009877921159}, // face 1
42  {1.054751253523952054, -1.347517358900396623}, // face 2
43  {0.600191595538186799, -0.450603909469755746}, // face 3
44  {0.491715428198773866, 0.401988202911306943}, // face 4
45  {0.172745327415618701, 1.678146885280433686}, // face 5
46  {0.605929321571350690, 2.953923329812411617}, // face 6
47  {0.427370518328979641, -1.888876200336285401}, // face 7
48  {-0.079066118549212831, -0.733429513380867741}, // face 8
49  {-0.230961644455383637, 0.506495587332349035}, // face 9
50  {0.079066118549212831, 2.408163140208925497}, // face 10
51  {0.230961644455383637, -2.635097066257444203}, // face 11
52  {-0.172745327415618701, -1.463445768309359553}, // face 12
53  {-0.605929321571350690, -0.187669323777381622}, // face 13
54  {-0.427370518328979641, 1.252716453253507838}, // face 14
55  {-0.600191595538186799, 2.690988744120037492}, // face 15
56  {-0.491715428198773866, -2.739604450678486295}, // face 16
57  {-0.803582649718989942, -1.893195233972397139}, // face 17
58  {-1.307747883455638156, -0.604647643711872080}, // face 18
59  {-1.054751253523952054, 1.794075294689396615}, // face 19
60 };
61 
63 DEVICE static const Vec3dArray(faceCenterPoint, NUM_ICOSA_FACES) = {
64  {0.2199307791404606, 0.6583691780274996, 0.7198475378926182}, // face 0
65  {-0.2139234834501421, 0.1478171829550703, 0.9656017935214205}, // face 1
66  {0.1092625278784797, -0.4811951572873210, 0.8697775121287253}, // face 2
67  {0.7428567301586791, -0.3593941678278028, 0.5648005936517033}, // face 3
68  {0.8112534709140969, 0.3448953237639384, 0.4721387736413930}, // face 4
69  {-0.1055498149613921, 0.9794457296411413, 0.1718874610009365}, // face 5
70  {-0.8075407579970092, 0.1533552485898818, 0.5695261994882688}, // face 6
71  {-0.2846148069787907, -0.8644080972654206, 0.4144792552473539}, // face 7
72  {0.7405621473854482, -0.6673299564565524, -0.0789837646326737}, // face 8
73  {0.8512303986474293, 0.4722343788582681, -0.2289137388687808}, // face 9
74  {-0.7405621473854481, 0.6673299564565524, 0.0789837646326737}, // face 10
75  {-0.8512303986474292, -0.4722343788582682, 0.2289137388687808}, // face 11
76  {0.1055498149613919, -0.9794457296411413, -0.1718874610009365}, // face 12
77  {0.8075407579970092, -0.1533552485898819, -0.5695261994882688}, // face 13
78  {0.2846148069787908, 0.8644080972654204, -0.4144792552473539}, // face 14
79  {-0.7428567301586791, 0.3593941678278027, -0.5648005936517033}, // face 15
80  {-0.8112534709140971, -0.3448953237639382, -0.4721387736413930}, // face 16
81  {-0.2199307791404607, -0.6583691780274996, -0.7198475378926182}, // face 17
82  {0.2139234834501420, -0.1478171829550704, -0.9656017935214205}, // face 18
83  {-0.1092625278784796, 0.4811951572873210, -0.8697775121287253}, // face 19
84 };
85 
89 DEVICE static const double faceAxesAzRadsCII[NUM_ICOSA_FACES][3] = {
90  {5.619958268523939882, 3.525563166130744542, 1.431168063737548730}, // face 0
91  {5.760339081714187279, 3.665943979320991689, 1.571548876927796127}, // face 1
92  {0.780213654393430055, 4.969003859179821079, 2.874608756786625655}, // face 2
93  {0.430469363979999913, 4.619259568766391033, 2.524864466373195467}, // face 3
94  {6.130269123335111400, 4.035874020941915804, 1.941478918548720291}, // face 4
95  {2.692877706530642877, 0.598482604137447119, 4.787272808923838195}, // face 5
96  {2.982963003477243874, 0.888567901084048369, 5.077358105870439581}, // face 6
97  {3.532912002790141181, 1.438516900396945656, 5.627307105183336758}, // face 7
98  {3.494305004259568154, 1.399909901866372864, 5.588700106652763840}, // face 8
99  {3.003214169499538391, 0.908819067106342928, 5.097609271892733906}, // face 9
100  {5.930472956509811562, 3.836077854116615875, 1.741682751723420374}, // face 10
101  {0.138378484090254847, 4.327168688876645809, 2.232773586483450311}, // face 11
102  {0.448714947059150361, 4.637505151845541521, 2.543110049452346120}, // face 12
103  {0.158629650112549365, 4.347419854898940135, 2.253024752505744869}, // face 13
104  {5.891865957979238535, 3.797470855586042958, 1.703075753192847583}, // face 14
105  {2.711123289609793325, 0.616728187216597771, 4.805518392002988683}, // face 15
106  {3.294508837434268316, 1.200113735041072948, 5.388903939827463911}, // face 16
107  {3.804819692245439833, 1.710424589852244509, 5.899214794638635174}, // face 17
108  {3.664438879055192436, 1.570043776661997111, 5.758833981448388027}, // face 18
109  {2.361378999196363184, 0.266983896803167583, 4.455774101589558636}, // face 19
110 };
111 
113 DEVICE static const FaceOrientIJK2DArray(faceNeighbors, NUM_ICOSA_FACES, 4) = {
114  {
115  // face 0
116  {0, 0, 0, 0, 0}, // central face
117  {2, 0, 2, 4, 1}, // ij quadrant
118  {2, 2, 0, 1, 5}, // ki quadrant
119  {0, 2, 2, 5, 3} // jk quadrant
120  },
121  {
122  // face 1
123  {0, 0, 0, 1, 0}, // central face
124  {2, 0, 2, 0, 1}, // ij quadrant
125  {2, 2, 0, 2, 5}, // ki quadrant
126  {0, 2, 2, 6, 3} // jk quadrant
127  },
128  {
129  // face 2
130  {0, 0, 0, 2, 0}, // central face
131  {2, 0, 2, 1, 1}, // ij quadrant
132  {2, 2, 0, 3, 5}, // ki quadrant
133  {0, 2, 2, 7, 3} // jk quadrant
134  },
135  {
136  // face 3
137  {0, 0, 0, 3, 0}, // central face
138  {2, 0, 2, 2, 1}, // ij quadrant
139  {2, 2, 0, 4, 5}, // ki quadrant
140  {0, 2, 2, 8, 3} // jk quadrant
141  },
142  {
143  // face 4
144  {0, 0, 0, 4, 0}, // central face
145  {2, 0, 2, 3, 1}, // ij quadrant
146  {2, 2, 0, 0, 5}, // ki quadrant
147  {0, 2, 2, 9, 3} // jk quadrant
148  },
149  {
150  // face 5
151  {0, 0, 0, 5, 0}, // central face
152  {2, 2, 0, 10, 3}, // ij quadrant
153  {2, 0, 2, 14, 3}, // ki quadrant
154  {0, 2, 2, 0, 3} // jk quadrant
155  },
156  {
157  // face 6
158  {0, 0, 0, 6, 0}, // central face
159  {2, 2, 0, 11, 3}, // ij quadrant
160  {2, 0, 2, 10, 3}, // ki quadrant
161  {0, 2, 2, 1, 3} // jk quadrant
162  },
163  {
164  // face 7
165  {0, 0, 0, 7, 0}, // central face
166  {2, 2, 0, 12, 3}, // ij quadrant
167  {2, 0, 2, 11, 3}, // ki quadrant
168  {0, 2, 2, 2, 3} // jk quadrant
169  },
170  {
171  // face 8
172  {0, 0, 0, 8, 0}, // central face
173  {2, 2, 0, 13, 3}, // ij quadrant
174  {2, 0, 2, 12, 3}, // ki quadrant
175  {0, 2, 2, 3, 3} // jk quadrant
176  },
177  {
178  // face 9
179  {0, 0, 0, 9, 0}, // central face
180  {2, 2, 0, 14, 3}, // ij quadrant
181  {2, 0, 2, 13, 3}, // ki quadrant
182  {0, 2, 2, 4, 3} // jk quadrant
183  },
184  {
185  // face 10
186  {0, 0, 0, 10, 0}, // central face
187  {2, 2, 0, 5, 3}, // ij quadrant
188  {2, 0, 2, 6, 3}, // ki quadrant
189  {0, 2, 2, 15, 3} // jk quadrant
190  },
191  {
192  // face 11
193  {0, 0, 0, 11, 0}, // central face
194  {2, 2, 0, 6, 3}, // ij quadrant
195  {2, 0, 2, 7, 3}, // ki quadrant
196  {0, 2, 2, 16, 3} // jk quadrant
197  },
198  {
199  // face 12
200  {0, 0, 0, 12, 0}, // central face
201  {2, 2, 0, 7, 3}, // ij quadrant
202  {2, 0, 2, 8, 3}, // ki quadrant
203  {0, 2, 2, 17, 3} // jk quadrant
204  },
205  {
206  // face 13
207  {0, 0, 0, 13, 0}, // central face
208  {2, 2, 0, 8, 3}, // ij quadrant
209  {2, 0, 2, 9, 3}, // ki quadrant
210  {0, 2, 2, 18, 3} // jk quadrant
211  },
212  {
213  // face 14
214  {0, 0, 0, 14, 0}, // central face
215  {2, 2, 0, 9, 3}, // ij quadrant
216  {2, 0, 2, 5, 3}, // ki quadrant
217  {0, 2, 2, 19, 3} // jk quadrant
218  },
219  {
220  // face 15
221  {0, 0, 0, 15, 0}, // central face
222  {2, 0, 2, 16, 1}, // ij quadrant
223  {2, 2, 0, 19, 5}, // ki quadrant
224  {0, 2, 2, 10, 3} // jk quadrant
225  },
226  {
227  // face 16
228  {0, 0, 0, 16, 0}, // central face
229  {2, 0, 2, 17, 1}, // ij quadrant
230  {2, 2, 0, 15, 5}, // ki quadrant
231  {0, 2, 2, 11, 3} // jk quadrant
232  },
233  {
234  // face 17
235  {0, 0, 0, 17, 0}, // central face
236  {2, 0, 2, 18, 1}, // ij quadrant
237  {2, 2, 0, 16, 5}, // ki quadrant
238  {0, 2, 2, 12, 3} // jk quadrant
239  },
240  {
241  // face 18
242  {0, 0, 0, 18, 0}, // central face
243  {2, 0, 2, 19, 1}, // ij quadrant
244  {2, 2, 0, 17, 5}, // ki quadrant
245  {0, 2, 2, 13, 3} // jk quadrant
246  },
247  {
248  // face 19
249  {0, 0, 0, 19, 0}, // central face
250  {2, 0, 2, 15, 1}, // ij quadrant
251  {2, 2, 0, 18, 5}, // ki quadrant
252  {0, 2, 2, 14, 3} // jk quadrant
253  }};
254 
255 // /** @brief direction from the origin face to the destination face, relative to
256 // * the origin face's coordinate system, or -1 if not adjacent.
257 // */
258 // static const int adjacentFaceDir[NUM_ICOSA_FACES][NUM_ICOSA_FACES] = {
259 // {0, KI, -1, -1, IJ, JK, -1, -1, -1, -1,
260 // -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // face 0
261 // {IJ, 0, KI, -1, -1, -1, JK, -1, -1, -1,
262 // -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // face 1
263 // {-1, IJ, 0, KI, -1, -1, -1, JK, -1, -1,
264 // -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // face 2
265 // {-1, -1, IJ, 0, KI, -1, -1, -1, JK, -1,
266 // -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // face 3
267 // {KI, -1, -1, IJ, 0, -1, -1, -1, -1, JK,
268 // -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // face 4
269 // {JK, -1, -1, -1, -1, 0, -1, -1, -1, -1,
270 // IJ, -1, -1, -1, KI, -1, -1, -1, -1, -1}, // face 5
271 // {-1, JK, -1, -1, -1, -1, 0, -1, -1, -1,
272 // KI, IJ, -1, -1, -1, -1, -1, -1, -1, -1}, // face 6
273 // {-1, -1, JK, -1, -1, -1, -1, 0, -1, -1,
274 // -1, KI, IJ, -1, -1, -1, -1, -1, -1, -1}, // face 7
275 // {-1, -1, -1, JK, -1, -1, -1, -1, 0, -1,
276 // -1, -1, KI, IJ, -1, -1, -1, -1, -1, -1}, // face 8
277 // {-1, -1, -1, -1, JK, -1, -1, -1, -1, 0,
278 // -1, -1, -1, KI, IJ, -1, -1, -1, -1, -1}, // face 9
279 // {-1, -1, -1, -1, -1, IJ, KI, -1, -1, -1,
280 // 0, -1, -1, -1, -1, JK, -1, -1, -1, -1}, // face 10
281 // {-1, -1, -1, -1, -1, -1, IJ, KI, -1, -1,
282 // -1, 0, -1, -1, -1, -1, JK, -1, -1, -1}, // face 11
283 // {-1, -1, -1, -1, -1, -1, -1, IJ, KI, -1,
284 // -1, -1, 0, -1, -1, -1, -1, JK, -1, -1}, // face 12
285 // {-1, -1, -1, -1, -1, -1, -1, -1, IJ, KI,
286 // -1, -1, -1, 0, -1, -1, -1, -1, JK, -1}, // face 13
287 // {-1, -1, -1, -1, -1, KI, -1, -1, -1, IJ,
288 // -1, -1, -1, -1, 0, -1, -1, -1, -1, JK}, // face 14
289 // {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
290 // JK, -1, -1, -1, -1, 0, IJ, -1, -1, KI}, // face 15
291 // {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
292 // -1, JK, -1, -1, -1, KI, 0, IJ, -1, -1}, // face 16
293 // {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
294 // -1, -1, JK, -1, -1, -1, KI, 0, IJ, -1}, // face 17
295 // {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
296 // -1, -1, -1, JK, -1, -1, -1, KI, 0, IJ}, // face 18
297 // {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
298 // -1, -1, -1, -1, JK, IJ, -1, -1, KI, 0} // face 19
299 // };
300 
302 DEVICE static const int maxDimByCIIres[] = {
303  2, // res 0
304  -1, // res 1
305  14, // res 2
306  -1, // res 3
307  98, // res 4
308  -1, // res 5
309  686, // res 6
310  -1, // res 7
311  4802, // res 8
312  -1, // res 9
313  33614, // res 10
314  -1, // res 11
315  235298, // res 12
316  -1, // res 13
317  1647086, // res 14
318  -1, // res 15
319  11529602 // res 16
320 };
321 
323 DEVICE static const int unitScaleByCIIres[] = {
324  1, // res 0
325  -1, // res 1
326  7, // res 2
327  -1, // res 3
328  49, // res 4
329  -1, // res 5
330  343, // res 6
331  -1, // res 7
332  2401, // res 8
333  -1, // res 9
334  16807, // res 10
335  -1, // res 11
336  117649, // res 12
337  -1, // res 13
338  823543, // res 14
339  -1, // res 15
340  5764801 // res 16
341 };
342 
351  return res % 2;
352 }
353 
363  // first convert to hex2d
364  Vec2d(v);
365  _geoToHex2d(g, res, &h[FACE_INDEX], v);
366 
367  // then convert to ijk+
368  _hex2dToCoordIJK(v, h);
369 
370  return true;
371 }
372 
382 EXTENSION_NOINLINE bool _geoToHex2d(const GeoCoord(g), int res, int* face, Vec2d(v)) {
383  Vec3d(v3d);
384  _geoToVec3d(g, v3d);
385 
386  // determine the icosahedron face
387  *face = 0;
388  double sqd = _pointSquareDist(faceCenterPoint[0], v3d);
389  for (int f = 1; f < NUM_ICOSA_FACES; f++) {
390  double sqdT = _pointSquareDist(faceCenterPoint[f], v3d);
391  if (sqdT < sqd) {
392  *face = f;
393  sqd = sqdT;
394  }
395  }
396 
397  // cos(r) = 1 - 2 * sin^2(r/2) = 1 - 2 * (sqd / 4) = 1 - sqd/2
398  double r = acos(1 - sqd / 2);
399 
400  if (r < EPSILON) {
401  v[X_INDEX] = v[Y_INDEX] = 0.0;
402  return true;
403  }
404 
405  // now have face and r, now find CCW theta from CII i-axis
406  double theta = _posAngleRads(faceAxesAzRadsCII[*face][0] -
407  _posAngleRads(_geoAzimuthRads(faceCenterGeo[*face], g)));
408 
409  // adjust theta for Class III (odd resolutions)
410  if (isResClassIII(res))
411  theta = _posAngleRads(theta - M_AP7_ROT_RADS);
412 
413  // perform gnomonic scaling of r
414  r = tan(r);
415 
416  // scale for current resolution length u
417  r /= RES0_U_GNOMONIC;
418  for (int i = 0; i < res; i++)
419  r *= M_SQRT7;
420 
421  // we now have (r, theta) in hex2d with theta ccw from x-axes
422 
423  // convert to local x,y
424  v[X_INDEX] = r * cos(theta);
425  v[Y_INDEX] = r * sin(theta);
426 
427  return true;
428 }
429 
443  int face,
444  int res,
445  int substrate,
446  GeoCoord(g)) {
447  // calculate (r, theta) in hex2d
448  double r = _v2dMag(v);
449 
450  if (r < EPSILON) {
451  GeoCoordCopy(g, faceCenterGeo[face]);
452  return true;
453  }
454 
455  double theta = atan2(v[Y_INDEX], v[X_INDEX]);
456 
457  // scale for current resolution length u
458  for (int i = 0; i < res; i++)
459  r /= M_SQRT7;
460 
461  // scale accordingly if this is a substrate grid
462  if (substrate) {
463  r /= 3.0;
464  if (isResClassIII(res))
465  r /= M_SQRT7;
466  }
467 
468  r *= RES0_U_GNOMONIC;
469 
470  // perform inverse gnomonic scaling of r
471  r = atan(r);
472 
473  // adjust theta for Class III
474  // if a substrate grid, then it's already been adjusted for Class III
475  if (!substrate && isResClassIII(res))
476  theta = _posAngleRads(theta + M_AP7_ROT_RADS);
477 
478  // find theta as an azimuth
479  theta = _posAngleRads(faceAxesAzRadsCII[face][0] - theta);
480 
481  // now find the point at (r,theta) from the face center
482  _geoAzDistanceRads(faceCenterGeo[face], theta, r, g);
483 
484  return true;
485 }
486 
495 EXTENSION_NOINLINE bool _faceIjkToGeo(const FaceIJK(h), int res, GeoCoord(g)) {
496  Vec2d(v);
497  _ijkToHex2d(h, v);
498  _hex2dToGeo(v, h[FACE_INDEX], res, 0, g);
499  return true;
500 }
501 
502 // /**
503 // * Generates the cell boundary in spherical coordinates for a pentagonal cell
504 // * given by a FaceIJK address at a specified resolution.
505 // *
506 // * @param h The FaceIJK address of the pentagonal cell.
507 // * @param res The H3 resolution of the cell.
508 // * @param start The first topological vertex to return.
509 // * @param length The number of topological vertexes to return.
510 // * @param g The spherical coordinates of the cell boundary.
511 // */
512 // void _faceIjkPentToGeoBoundary(const FaceIJK* h, int res, int start, int length,
513 // GeoBoundary* g) {
514 // int adjRes = res;
515 // FaceIJK centerIJK = *h;
516 // FaceIJK fijkVerts[NUM_PENT_VERTS];
517 // _faceIjkPentToVerts(&centerIJK, &adjRes, fijkVerts);
518 
519 // // If we're returning the entire loop, we need one more iteration in case
520 // // of a distortion vertex on the last edge
521 // int additionalIteration = length == NUM_PENT_VERTS ? 1 : 0;
522 
523 // // convert each vertex to lat/lon
524 // // adjust the face of each vertex as appropriate and introduce
525 // // edge-crossing vertices as needed
526 // g->numVerts = 0;
527 // FaceIJK lastFijk;
528 // for (int vert = start; vert < start + length + additionalIteration;
529 // vert++) {
530 // int v = vert % NUM_PENT_VERTS;
531 
532 // FaceIJK fijk = fijkVerts[v];
533 
534 // _adjustPentVertOverage(&fijk, adjRes);
535 
536 // // all Class III pentagon edges cross icosa edges
537 // // note that Class II pentagons have vertices on the edge,
538 // // not edge intersections
539 // if (isResClassIII(res) && vert > start) {
540 // // find hex2d of the two vertexes on the last face
541 
542 // FaceIJK tmpFijk = fijk;
543 
544 // Vec2d orig2d0;
545 // _ijkToHex2d(&lastFijk.coord, &orig2d0);
546 
547 // int currentToLastDir = adjacentFaceDir[tmpFijk.face][lastFijk.face];
548 
549 // const FaceOrientIJK* fijkOrient =
550 // &faceNeighbors[tmpFijk.face][currentToLastDir];
551 
552 // tmpFijk.face = fijkOrient->face;
553 // CoordIJK* ijk = &tmpFijk.coord;
554 
555 // // rotate and translate for adjacent face
556 // for (int i = 0; i < fijkOrient->ccwRot60; i++) _ijkRotate60ccw(ijk);
557 
558 // CoordIJK transVec = fijkOrient->translate;
559 // _ijkScale(&transVec, unitScaleByCIIres[adjRes] * 3);
560 // _ijkAdd(ijk, &transVec, ijk);
561 // _ijkNormalize(ijk);
562 
563 // Vec2d orig2d1;
564 // _ijkToHex2d(ijk, &orig2d1);
565 
566 // // find the appropriate icosa face edge vertexes
567 // int maxDim = maxDimByCIIres[adjRes];
568 // Vec2d v0 = {3.0 * maxDim, 0.0};
569 // Vec2d v1 = {-1.5 * maxDim, 3.0 * M_SQRT3_2 * maxDim};
570 // Vec2d v2 = {-1.5 * maxDim, -3.0 * M_SQRT3_2 * maxDim};
571 
572 // Vec2d* edge0;
573 // Vec2d* edge1;
574 // switch (adjacentFaceDir[tmpFijk.face][fijk.face]) {
575 // case IJ:
576 // edge0 = &v0;
577 // edge1 = &v1;
578 // break;
579 // case JK:
580 // edge0 = &v1;
581 // edge1 = &v2;
582 // break;
583 // case KI:
584 // default:
585 // assert(adjacentFaceDir[tmpFijk.face][fijk.face] == KI);
586 // edge0 = &v2;
587 // edge1 = &v0;
588 // break;
589 // }
590 
591 // // find the intersection and add the lat/lon point to the result
592 // Vec2d inter;
593 // _v2dIntersect(&orig2d0, &orig2d1, edge0, edge1, &inter);
594 // _hex2dToGeo(&inter, tmpFijk.face, adjRes, 1,
595 // &g->verts[g->numVerts]);
596 // g->numVerts++;
597 // }
598 
599 // // convert vertex to lat/lon and add to the result
600 // // vert == start + NUM_PENT_VERTS is only used to test for possible
601 // // intersection on last edge
602 // if (vert < start + NUM_PENT_VERTS) {
603 // Vec2d vec;
604 // _ijkToHex2d(&fijk.coord, &vec);
605 // _hex2dToGeo(&vec, fijk.face, adjRes, 1, &g->verts[g->numVerts]);
606 // g->numVerts++;
607 // }
608 
609 // lastFijk = fijk;
610 // }
611 // }
612 
613 // /**
614 // * Get the vertices of a pentagon cell as substrate FaceIJK addresses
615 // *
616 // * @param fijk The FaceIJK address of the cell.
617 // * @param res The H3 resolution of the cell. This may be adjusted if
618 // * necessary for the substrate grid resolution.
619 // * @param fijkVerts Output array for the vertices
620 // */
621 // void _faceIjkPentToVerts(FaceIJK* fijk, int* res, FaceIJK* fijkVerts) {
622 // // the vertexes of an origin-centered pentagon in a Class II resolution on a
623 // // substrate grid with aperture sequence 33r. The aperture 3 gets us the
624 // // vertices, and the 3r gets us back to Class II.
625 // // vertices listed ccw from the i-axes
626 // CoordIJK vertsCII[NUM_PENT_VERTS] = {
627 // {2, 1, 0}, // 0
628 // {1, 2, 0}, // 1
629 // {0, 2, 1}, // 2
630 // {0, 1, 2}, // 3
631 // {1, 0, 2}, // 4
632 // };
633 
634 // // the vertexes of an origin-centered pentagon in a Class III resolution on
635 // // a substrate grid with aperture sequence 33r7r. The aperture 3 gets us the
636 // // vertices, and the 3r7r gets us to Class II. vertices listed ccw from the
637 // // i-axes
638 // CoordIJK vertsCIII[NUM_PENT_VERTS] = {
639 // {5, 4, 0}, // 0
640 // {1, 5, 0}, // 1
641 // {0, 5, 4}, // 2
642 // {0, 1, 5}, // 3
643 // {4, 0, 5}, // 4
644 // };
645 
646 // // get the correct set of substrate vertices for this resolution
647 // CoordIJK* verts;
648 // if (isResClassIII(*res))
649 // verts = vertsCIII;
650 // else
651 // verts = vertsCII;
652 
653 // // adjust the center point to be in an aperture 33r substrate grid
654 // // these should be composed for speed
655 // _downAp3(&fijk->coord);
656 // _downAp3r(&fijk->coord);
657 
658 // // if res is Class III we need to add a cw aperture 7 to get to
659 // // icosahedral Class II
660 // if (isResClassIII(*res)) {
661 // _downAp7r(&fijk->coord);
662 // *res += 1;
663 // }
664 
665 // // The center point is now in the same substrate grid as the origin
666 // // cell vertices. Add the center point substate coordinates
667 // // to each vertex to translate the vertices to that cell.
668 // for (int v = 0; v < NUM_PENT_VERTS; v++) {
669 // fijkVerts[v].face = fijk->face;
670 // _ijkAdd(&fijk->coord, &verts[v], &fijkVerts[v].coord);
671 // _ijkNormalize(&fijkVerts[v].coord);
672 // }
673 // }
674 
675 // /**
676 // * Generates the cell boundary in spherical coordinates for a cell given by a
677 // * FaceIJK address at a specified resolution.
678 // *
679 // * @param h The FaceIJK address of the cell.
680 // * @param res The H3 resolution of the cell.
681 // * @param start The first topological vertex to return.
682 // * @param length The number of topological vertexes to return.
683 // * @param g The spherical coordinates of the cell boundary.
684 // */
685 // void _faceIjkToGeoBoundary(const FaceIJK* h, int res, int start, int length,
686 // GeoBoundary* g) {
687 // int adjRes = res;
688 // FaceIJK centerIJK = *h;
689 // FaceIJK fijkVerts[NUM_HEX_VERTS];
690 // _faceIjkToVerts(&centerIJK, &adjRes, fijkVerts);
691 
692 // // If we're returning the entire loop, we need one more iteration in case
693 // // of a distortion vertex on the last edge
694 // int additionalIteration = length == NUM_HEX_VERTS ? 1 : 0;
695 
696 // // convert each vertex to lat/lon
697 // // adjust the face of each vertex as appropriate and introduce
698 // // edge-crossing vertices as needed
699 // g->numVerts = 0;
700 // int lastFace = -1;
701 // Overage lastOverage = NO_OVERAGE;
702 // for (int vert = start; vert < start + length + additionalIteration;
703 // vert++) {
704 // int v = vert % NUM_HEX_VERTS;
705 
706 // FaceIJK fijk = fijkVerts[v];
707 
708 // const int pentLeading4 = 0;
709 // Overage overage = _adjustOverageClassII(&fijk, adjRes, pentLeading4, 1);
710 
711 // /*
712 // Check for edge-crossing. Each face of the underlying icosahedron is a
713 // different projection plane. So if an edge of the hexagon crosses an
714 // icosahedron edge, an additional vertex must be introduced at that
715 // intersection point. Then each half of the cell edge can be projected
716 // to geographic coordinates using the appropriate icosahedron face
717 // projection. Note that Class II cell edges have vertices on the face
718 // edge, with no edge line intersections.
719 // */
720 // if (isResClassIII(res) && vert > start && fijk.face != lastFace &&
721 // lastOverage != FACE_EDGE) {
722 // // find hex2d of the two vertexes on original face
723 // int lastV = (v + 5) % NUM_HEX_VERTS;
724 // Vec2d orig2d0;
725 // _ijkToHex2d(&fijkVerts[lastV].coord, &orig2d0);
726 
727 // Vec2d orig2d1;
728 // _ijkToHex2d(&fijkVerts[v].coord, &orig2d1);
729 
730 // // find the appropriate icosa face edge vertexes
731 // int maxDim = maxDimByCIIres[adjRes];
732 // Vec2d v0 = {3.0 * maxDim, 0.0};
733 // Vec2d v1 = {-1.5 * maxDim, 3.0 * M_SQRT3_2 * maxDim};
734 // Vec2d v2 = {-1.5 * maxDim, -3.0 * M_SQRT3_2 * maxDim};
735 
736 // int face2 = ((lastFace == centerIJK.face) ? fijk.face : lastFace);
737 // Vec2d* edge0;
738 // Vec2d* edge1;
739 // switch (adjacentFaceDir[centerIJK.face][face2]) {
740 // case IJ:
741 // edge0 = &v0;
742 // edge1 = &v1;
743 // break;
744 // case JK:
745 // edge0 = &v1;
746 // edge1 = &v2;
747 // break;
748 // // case KI:
749 // default:
750 // assert(adjacentFaceDir[centerIJK.face][face2] == KI);
751 // edge0 = &v2;
752 // edge1 = &v0;
753 // break;
754 // }
755 
756 // // find the intersection and add the lat/lon point to the result
757 // Vec2d inter;
758 // _v2dIntersect(&orig2d0, &orig2d1, edge0, edge1, &inter);
759 // /*
760 // If a point of intersection occurs at a hexagon vertex, then each
761 // adjacent hexagon edge will lie completely on a single icosahedron
762 // face, and no additional vertex is required.
763 // */
764 // bool isIntersectionAtVertex =
765 // _v2dEquals(&orig2d0, &inter) || _v2dEquals(&orig2d1, &inter);
766 // if (!isIntersectionAtVertex) {
767 // _hex2dToGeo(&inter, centerIJK.face, adjRes, 1,
768 // &g->verts[g->numVerts]);
769 // g->numVerts++;
770 // }
771 // }
772 
773 // // convert vertex to lat/lon and add to the result
774 // // vert == start + NUM_HEX_VERTS is only used to test for possible
775 // // intersection on last edge
776 // if (vert < start + NUM_HEX_VERTS) {
777 // Vec2d vec;
778 // _ijkToHex2d(&fijk.coord, &vec);
779 // _hex2dToGeo(&vec, fijk.face, adjRes, 1, &g->verts[g->numVerts]);
780 // g->numVerts++;
781 // }
782 
783 // lastFace = fijk.face;
784 // lastOverage = overage;
785 // }
786 // }
787 
788 // /**
789 // * Get the vertices of a cell as substrate FaceIJK addresses
790 // *
791 // * @param fijk The FaceIJK address of the cell.
792 // * @param res The H3 resolution of the cell. This may be adjusted if
793 // * necessary for the substrate grid resolution.
794 // * @param fijkVerts Output array for the vertices
795 // */
796 // void _faceIjkToVerts(FaceIJK* fijk, int* res, FaceIJK* fijkVerts) {
797 // // the vertexes of an origin-centered cell in a Class II resolution on a
798 // // substrate grid with aperture sequence 33r. The aperture 3 gets us the
799 // // vertices, and the 3r gets us back to Class II.
800 // // vertices listed ccw from the i-axes
801 // CoordIJK vertsCII[NUM_HEX_VERTS] = {
802 // {2, 1, 0}, // 0
803 // {1, 2, 0}, // 1
804 // {0, 2, 1}, // 2
805 // {0, 1, 2}, // 3
806 // {1, 0, 2}, // 4
807 // {2, 0, 1} // 5
808 // };
809 
810 // // the vertexes of an origin-centered cell in a Class III resolution on a
811 // // substrate grid with aperture sequence 33r7r. The aperture 3 gets us the
812 // // vertices, and the 3r7r gets us to Class II.
813 // // vertices listed ccw from the i-axes
814 // CoordIJK vertsCIII[NUM_HEX_VERTS] = {
815 // {5, 4, 0}, // 0
816 // {1, 5, 0}, // 1
817 // {0, 5, 4}, // 2
818 // {0, 1, 5}, // 3
819 // {4, 0, 5}, // 4
820 // {5, 0, 1} // 5
821 // };
822 
823 // // get the correct set of substrate vertices for this resolution
824 // CoordIJK* verts;
825 // if (isResClassIII(*res))
826 // verts = vertsCIII;
827 // else
828 // verts = vertsCII;
829 
830 // // adjust the center point to be in an aperture 33r substrate grid
831 // // these should be composed for speed
832 // _downAp3(&fijk->coord);
833 // _downAp3r(&fijk->coord);
834 
835 // // if res is Class III we need to add a cw aperture 7 to get to
836 // // icosahedral Class II
837 // if (isResClassIII(*res)) {
838 // _downAp7r(&fijk->coord);
839 // *res += 1;
840 // }
841 
842 // // The center point is now in the same substrate grid as the origin
843 // // cell vertices. Add the center point substate coordinates
844 // // to each vertex to translate the vertices to that cell.
845 // for (int v = 0; v < NUM_HEX_VERTS; v++) {
846 // fijkVerts[v].face = fijk->face;
847 // _ijkAdd(&fijk->coord, &verts[v], &fijkVerts[v].coord);
848 // _ijkNormalize(&fijkVerts[v].coord);
849 // }
850 // }
851 
865  int res,
866  int pentLeading4,
867  int substrate) {
868  Overage overage = NO_OVERAGE;
869 
870  CoordIJK_ptr(ijk) = fijk;
871 
872  // get the maximum dimension value; scale if a substrate grid
873  int maxDim = maxDimByCIIres[res];
874  if (substrate)
875  maxDim *= 3;
876 
877  // check for overage
878  if (substrate && ijk[I_INDEX] + ijk[J_INDEX] + ijk[K_INDEX] == maxDim) // on edge
879  overage = FACE_EDGE;
880  else if (ijk[I_INDEX] + ijk[J_INDEX] + ijk[K_INDEX] > maxDim) // overage
881  {
882  overage = NEW_FACE;
883 
884  const int* fijkOrient;
885  if (ijk[K_INDEX] > 0) {
886  if (ijk[J_INDEX] > 0) // jk "quadrant"
887  fijkOrient = faceNeighbors[fijk[FACE_INDEX]][JK];
888  else // ik "quadrant"
889  {
890  fijkOrient = faceNeighbors[fijk[FACE_INDEX]][KI];
891 
892  // adjust for the pentagonal missing sequence
893  if (pentLeading4) {
894  // translate origin to center of pentagon
895  CoordIJK(origin);
896  _setIJK(origin, maxDim, 0, 0);
897  CoordIJK(tmp);
898  _ijkSub(ijk, origin, tmp);
899  // rotate to adjust for the missing sequence
900  _ijkRotate60cw(tmp);
901  // translate the origin back to the center of the triangle
902  _ijkAdd(tmp, origin, ijk);
903  }
904  }
905  } else // ij "quadrant"
906  fijkOrient = faceNeighbors[fijk[FACE_INDEX]][IJ];
907 
908  fijk[FACE_INDEX] = fijkOrient[FACE_INDEX];
909 
910  // rotate and translate for adjacent face
911  for (int i = 0; i < fijkOrient[CCWROT_60_INDEX]; i++)
912  _ijkRotate60ccw(ijk);
913 
914  CoordIJK(transVec) = CoordIJK_clone(fijkOrient);
915  int unitScale = unitScaleByCIIres[res];
916  if (substrate)
917  unitScale *= 3;
918  _ijkScale(transVec, unitScale);
919  _ijkAdd(ijk, transVec, ijk);
920  _ijkNormalize(ijk);
921 
922  // overage points on pentagon boundaries can end up on edges
923  if (substrate && ijk[I_INDEX] + ijk[J_INDEX] + ijk[K_INDEX] == maxDim) // on edge
924  overage = FACE_EDGE;
925  }
926 
927  return overage;
928 }
929 
930 // /**
931 // * Adjusts a FaceIJK address for a pentagon vertex in a substrate grid in
932 // * place so that the resulting cell address is relative to the correct
933 // * icosahedral face.
934 // *
935 // * @param fijk The FaceIJK address of the cell.
936 // * @param res The H3 resolution of the cell.
937 // */
938 // Overage _adjustPentVertOverage(FaceIJK* fijk, int res) {
939 // int pentLeading4 = 0;
940 // Overage overage;
941 // do {
942 // overage = _adjustOverageClassII(fijk, res, pentLeading4, 1);
943 // } while (overage == NEW_FACE);
944 // return overage;
945 // }
Overage
Definition: faceijk.h:78
#define CCWROT_60_INDEX
Definition: faceijk.h:53
#define GeoCoord(variable_name)
Definition: h3api.h:94
EXTENSION_INLINE int isResClassIII(int res)
Definition: faceijk.hpp:350
EXTENSION_NOINLINE bool _hex2dToGeo(const Vec2d(v), int face, int res, int substrate, GeoCoord(g))
Definition: faceijk.hpp:442
static DEVICE const int unitScaleByCIIres[]
unit scale distance table
Definition: faceijk.hpp:323
#define FaceIJK(variable_name)
Definition: faceijk.h:36
#define M_AP7_ROT_RADS
Definition: constants.h:51
H3Index functions.
EXTENSION_INLINE bool _ijkSub(const CoordIJK(h1), const CoordIJK(h2), CoordIJK(diff))
Definition: coordijk.hpp:198
static DEVICE const double faceAxesAzRadsCII[NUM_ICOSA_FACES][3]
icosahedron face ijk axes as azimuth in radians from face center to vertex 0/1/2 respectively ...
Definition: faceijk.hpp:89
#define J_INDEX
Definition: coordijk.h:43
DEVICE const GeoCoordArray(faceCenterGeo, NUM_ICOSA_FACES)
icosahedron face centers in lat/lon radians
EXTENSION_NOINLINE bool _ijkRotate60ccw(CoordIJK(ijk))
Definition: coordijk.hpp:385
#define IJ
Definition: faceijk.h:68
static DEVICE const FaceOrientIJK2DArray(faceNeighbors, NUM_ICOSA_FACES, 4)
Definition of which faces neighbor each other.
EXTENSION_NOINLINE bool _ijkRotate60cw(CoordIJK(ijk))
Definition: coordijk.hpp:407
EXTENSION_INLINE bool _ijkScale(CoordIJK(c), int factor)
Definition: coordijk.hpp:211
#define NUM_ICOSA_FACES
Definition: constants.h:71
EXTENSION_NOINLINE bool _hex2dToCoordIJK(const Vec2d(v), CoordIJK(h))
Definition: coordijk.hpp:54
#define DEVICE
#define M_SQRT7
Definition: faceijk.hpp:36
EXTENSION_NOINLINE bool _geoToHex2d(const GeoCoord(g), int res, int *face, Vec2d(v))
Definition: faceijk.hpp:382
#define EXTENSION_NOINLINE
Definition: OmniSciTypes.h:28
EXTENSION_NOINLINE double _posAngleRads(double rads)
Definition: geoCoord.hpp:35
#define CoordIJK_clone(ijk)
Definition: coordijk.h:47
#define Vec2d(variable_name)
Definition: vec2d.h:28
#define KI
Definition: faceijk.h:70
Geodetic (lat/lon) functions.
EXTENSION_NOINLINE bool _geoAzDistanceRads(const GeoCoord(p1), double az, double distance, GeoCoord(p2))
Definition: geoCoord.hpp:204
EXTENSION_INLINE bool _ijkAdd(const CoordIJK(h1), const CoordIJK(h2), CoordIJK(sum))
Definition: coordijk.hpp:184
EXTENSION_INLINE bool _ijkToHex2d(const CoordIJK(h), Vec2d(v))
Definition: coordijk.hpp:155
#define I_INDEX
Definition: coordijk.h:42
#define CoordIJK_ptr(variable_name)
Definition: coordijk.h:46
#define X_INDEX
Definition: vec2d.h:26
#define CoordIJK(variable_name)
Definition: coordijk.h:45
#define Vec3d(variable_name)
Definition: vec3d.h:29
#define JK
Definition: faceijk.h:72
FaceIJK functions including conversion to/from lat/lon.
#define FACE_INDEX
Definition: faceijk.h:35
#define EPSILON
Definition: constants.h:42
EXTENSION_NOINLINE bool _geoToVec3d(const GeoCoord(geo), Vec3d(v))
Definition: vec3d.hpp:52
EXTENSION_NOINLINE bool _faceIjkToGeo(const FaceIJK(h), int res, GeoCoord(g))
Definition: faceijk.hpp:495
#define RES0_U_GNOMONIC
Definition: constants.h:65
3D floating point vector functions.
EXTENSION_NOINLINE double _geoAzimuthRads(const GeoCoord(p1), const GeoCoord(p2))
Definition: geoCoord.hpp:187
static DEVICE const int maxDimByCIIres[]
direction from the origin face to the destination face, relative to the origin face&#39;s coordinate syst...
Definition: faceijk.hpp:302
#define K_INDEX
Definition: coordijk.h:44
#define Y_INDEX
Definition: vec2d.h:27
#define EXTENSION_INLINE
Definition: OmniSciTypes.h:27
char * f
static DEVICE const Vec3dArray(faceCenterPoint, NUM_ICOSA_FACES)
icosahedron face centers in x/y/z on the unit sphere
EXTENSION_NOINLINE double _pointSquareDist(const Vec3d(v1), const Vec3d(v2))
Definition: vec3d.hpp:41
EXTENSION_INLINE double _v2dMag(const Vec2d(v))
Definition: vec2d.hpp:30
EXTENSION_NOINLINE int _adjustOverageClassII(FaceIJK(fijk), int res, int pentLeading4, int substrate)
Definition: faceijk.hpp:864
EXTENSION_INLINE bool _setIJK(CoordIJK(ijk), int i, int j, int k)
Definition: coordijk.hpp:40
EXTENSION_NOINLINE bool _geoToFaceIjk(const GeoCoord(g), int res, FaceIJK(h))
Definition: faceijk.hpp:362
EXTENSION_NOINLINE bool _ijkNormalize(CoordIJK(c))
Definition: coordijk.hpp:224
#define GeoCoordCopy(dest_coord, src_coord)
Definition: h3api.h:96