OmniSciDB  72c90bc290
coordijk.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-2018 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  *
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 <math.h>
24 // #include <stdio.h>
25 // #include <stdlib.h>
26 // #include <string.h>
27
29 // #include "geoCoord.h"
30 // #include "mathExtensions.h"
31
40 EXTENSION_INLINE bool _setIJK(CoordIJK(ijk), int i, int j, int k) {
41  ijk[I_INDEX] = i;
42  ijk[J_INDEX] = j;
43  ijk[K_INDEX] = k;
44  return true;
45 }
46
47 // /**
48 // * Determine the containing hex in ijk+ coordinates for a 2D cartesian
49 // * coordinate vector (from DGGRID).
50 // *
51 // * @param v The 2D cartesian coordinate vector.
52 // * @param h The ijk+ coordinates of the containing hex.
53 // */
55  double a1, a2;
56  double x1, x2;
57  int m1, m2;
58  double r1, r2;
59
60  // quantize into the ij system and then normalize
61  h[K_INDEX] = 0;
62
63  a1 = fabs(v[X_INDEX]);
64  a2 = fabs(v[Y_INDEX]);
65
66  // first do a reverse conversion
67  x2 = a2 / M_SIN60;
68  x1 = a1 + x2 / 2.0;
69
70  // check if we have the center of a hex
71  m1 = x1;
72  m2 = x2;
73
74  // otherwise round correctly
75  r1 = x1 - m1;
76  r2 = x2 - m2;
77
78  if (r1 < 0.5) {
79  if (r1 < 1.0 / 3.0) {
80  if (r2 < (1.0 + r1) / 2.0) {
81  h[I_INDEX] = m1;
82  h[J_INDEX] = m2;
83  } else {
84  h[I_INDEX] = m1;
85  h[J_INDEX] = m2 + 1;
86  }
87  } else {
88  if (r2 < (1.0 - r1)) {
89  h[J_INDEX] = m2;
90  } else {
91  h[J_INDEX] = m2 + 1;
92  }
93
94  if ((1.0 - r1) <= r2 && r2 < (2.0 * r1)) {
95  h[I_INDEX] = m1 + 1;
96  } else {
97  h[I_INDEX] = m1;
98  }
99  }
100  } else {
101  if (r1 < 2.0 / 3.0) {
102  if (r2 < (1.0 - r1)) {
103  h[J_INDEX] = m2;
104  } else {
105  h[J_INDEX] = m2 + 1;
106  }
107
108  if ((2.0 * r1 - 1.0) < r2 && r2 < (1.0 - r1)) {
109  h[I_INDEX] = m1;
110  } else {
111  h[I_INDEX] = m1 + 1;
112  }
113  } else {
114  if (r2 < (r1 / 2.0)) {
115  h[I_INDEX] = m1 + 1;
116  h[J_INDEX] = m2;
117  } else {
118  h[I_INDEX] = m1 + 1;
119  h[J_INDEX] = m2 + 1;
120  }
121  }
122  }
123
124  // now fold across the axes if necessary
125
126  if (v[X_INDEX] < 0.0) {
127  if ((h[J_INDEX] % 2) == 0) // even
128  {
129  long long int axisi = h[J_INDEX] / 2;
130  long long int diff = h[I_INDEX] - axisi;
131  h[I_INDEX] = h[I_INDEX] - 2.0 * diff;
132  } else {
133  long long int axisi = (h[J_INDEX] + 1) / 2;
134  long long int diff = h[I_INDEX] - axisi;
135  h[I_INDEX] = h[I_INDEX] - (2.0 * diff + 1);
136  }
137  }
138
139  if (v[Y_INDEX] < 0.0) {
140  h[I_INDEX] = h[I_INDEX] - (2 * h[J_INDEX] + 1) / 2;
141  h[J_INDEX] = -1 * h[J_INDEX];
142  }
143
144  _ijkNormalize(h);
145
146  return true;
147 }
148
156  int i = h[I_INDEX] - h[K_INDEX];
157  int j = h[J_INDEX] - h[K_INDEX];
158
159  v[X_INDEX] = i - 0.5 * j;
160  v[Y_INDEX] = j * M_SQRT3_2;
161  return true;
162 }
163
172 EXTENSION_INLINE int _ijkMatches(const CoordIJK(c1), const CoordIJK(c2)) {
173  return (c1[I_INDEX] == c2[I_INDEX] && c1[J_INDEX] == c2[J_INDEX] &&
174  c1[K_INDEX] == c2[K_INDEX]);
175 }
176
184 EXTENSION_INLINE bool _ijkAdd(const CoordIJK(h1), const CoordIJK(h2), CoordIJK(sum)) {
185  sum[I_INDEX] = h1[I_INDEX] + h2[I_INDEX];
186  sum[J_INDEX] = h1[J_INDEX] + h2[J_INDEX];
187  sum[K_INDEX] = h1[K_INDEX] + h2[K_INDEX];
188  return true;
189 }
190
198 EXTENSION_INLINE bool _ijkSub(const CoordIJK(h1), const CoordIJK(h2), CoordIJK(diff)) {
199  diff[I_INDEX] = h1[I_INDEX] - h2[I_INDEX];
200  diff[J_INDEX] = h1[J_INDEX] - h2[J_INDEX];
201  diff[K_INDEX] = h1[K_INDEX] - h2[K_INDEX];
202  return true;
203 }
204
211 EXTENSION_INLINE bool _ijkScale(CoordIJK(c), int factor) {
212  c[I_INDEX] *= factor;
213  c[J_INDEX] *= factor;
214  c[K_INDEX] *= factor;
215  return true;
216 }
217
225  // remove any negative values
226  if (c[I_INDEX] < 0) {
227  c[J_INDEX] -= c[I_INDEX];
228  c[K_INDEX] -= c[I_INDEX];
229  c[I_INDEX] = 0;
230  }
231
232  if (c[J_INDEX] < 0) {
233  c[I_INDEX] -= c[J_INDEX];
234  c[K_INDEX] -= c[J_INDEX];
235  c[J_INDEX] = 0;
236  }
237
238  if (c[K_INDEX] < 0) {
239  c[I_INDEX] -= c[K_INDEX];
240  c[J_INDEX] -= c[K_INDEX];
241  c[K_INDEX] = 0;
242  }
243
244  // remove the min value if needed
245  int min = c[I_INDEX];
246  if (c[J_INDEX] < min)
247  min = c[J_INDEX];
248  if (c[K_INDEX] < min)
249  min = c[K_INDEX];
250  if (min > 0) {
251  c[I_INDEX] -= min;
252  c[J_INDEX] -= min;
253  c[K_INDEX] -= min;
254  }
255
256  return true;
257 }
258
267  CoordIJK(c) = CoordIJK_clone(ijk);
268  _ijkNormalize(c);
269
270  Direction digit = INVALID_DIGIT;
271  for (int i = CENTER_DIGIT; i < NUM_DIGITS; i++) {
272  if (_ijkMatches(c, UNIT_VECS[i])) {
273  digit = Direction(i);
274  break;
275  }
276  }
277
278  return digit;
279 }
280
288  // convert to CoordIJ
289  int i = ijk[I_INDEX] - ijk[K_INDEX];
290  int j = ijk[J_INDEX] - ijk[K_INDEX];
291
292  ijk[I_INDEX] = (int)lround((3 * i - j) / 7.0);
293  ijk[J_INDEX] = (int)lround((i + 2 * j) / 7.0);
294  ijk[K_INDEX] = 0;
295  _ijkNormalize(ijk);
296
297  return true;
298 }
299
307  // convert to CoordIJ
308  int i = ijk[I_INDEX] - ijk[K_INDEX];
309  int j = ijk[J_INDEX] - ijk[K_INDEX];
310
311  ijk[I_INDEX] = (int)lround((2 * i + j) / 7.0);
312  ijk[J_INDEX] = (int)lround((3 * j - i) / 7.0);
313  ijk[K_INDEX] = 0;
314  _ijkNormalize(ijk);
315  return true;
316 }
317
326  // res r unit vectors in res r+1
327  CoordIJK(iVec) = {3, 0, 1};
328  CoordIJK(jVec) = {1, 3, 0};
329  CoordIJK(kVec) = {0, 1, 3};
330
331  _ijkScale(iVec, ijk[I_INDEX]);
332  _ijkScale(jVec, ijk[J_INDEX]);
333  _ijkScale(kVec, ijk[K_INDEX]);
334
335  _ijkAdd(iVec, jVec, ijk);
336  _ijkAdd(ijk, kVec, ijk);
337
338  _ijkNormalize(ijk);
339  return true;
340 }
341
349  // res r unit vectors in res r+1
350  CoordIJK(iVec) = {3, 1, 0};
351  CoordIJK(jVec) = {0, 3, 1};
352  CoordIJK(kVec) = {1, 0, 3};
353
354  _ijkScale(iVec, ijk[I_INDEX]);
355  _ijkScale(jVec, ijk[J_INDEX]);
356  _ijkScale(kVec, ijk[K_INDEX]);
357
358  _ijkAdd(iVec, jVec, ijk);
359  _ijkAdd(ijk, kVec, ijk);
360
361  _ijkNormalize(ijk);
362  return true;
363 }
364
372 EXTENSION_NOINLINE bool _neighbor(CoordIJK(ijk), int digit) {
373  if (digit > CENTER_DIGIT && digit < NUM_DIGITS) {
374  _ijkAdd(ijk, UNIT_VECS[digit], ijk);
375  _ijkNormalize(ijk);
376  }
377  return true;
378 }
379
386  // unit vector rotations
387  CoordIJK(iVec) = {1, 1, 0};
388  CoordIJK(jVec) = {0, 1, 1};
389  CoordIJK(kVec) = {1, 0, 1};
390
391  _ijkScale(iVec, ijk[I_INDEX]);
392  _ijkScale(jVec, ijk[J_INDEX]);
393  _ijkScale(kVec, ijk[K_INDEX]);
394
395  _ijkAdd(iVec, jVec, ijk);
396  _ijkAdd(ijk, kVec, ijk);
397
398  _ijkNormalize(ijk);
399  return true;
400 }
401
408  // unit vector rotations
409  CoordIJK(iVec) = {1, 0, 1};
410  CoordIJK(jVec) = {1, 1, 0};
411  CoordIJK(kVec) = {0, 1, 1};
412
413  _ijkScale(iVec, ijk[I_INDEX]);
414  _ijkScale(jVec, ijk[J_INDEX]);
415  _ijkScale(kVec, ijk[K_INDEX]);
416
417  _ijkAdd(iVec, jVec, ijk);
418  _ijkAdd(ijk, kVec, ijk);
419
420  _ijkNormalize(ijk);
421  return true;
422 }
423
430  switch (Direction(digit)) {
431  case K_AXES_DIGIT:
432  return IK_AXES_DIGIT;
433  case IK_AXES_DIGIT:
434  return I_AXES_DIGIT;
435  case I_AXES_DIGIT:
436  return IJ_AXES_DIGIT;
437  case IJ_AXES_DIGIT:
438  return J_AXES_DIGIT;
439  case J_AXES_DIGIT:
440  return JK_AXES_DIGIT;
441  case JK_AXES_DIGIT:
442  return K_AXES_DIGIT;
443  default:
444  return digit;
445  }
446 }
447
454  switch (Direction(digit)) {
455  case K_AXES_DIGIT:
456  return JK_AXES_DIGIT;
457  case JK_AXES_DIGIT:
458  return J_AXES_DIGIT;
459  case J_AXES_DIGIT:
460  return IJ_AXES_DIGIT;
461  case IJ_AXES_DIGIT:
462  return I_AXES_DIGIT;
463  case I_AXES_DIGIT:
464  return IK_AXES_DIGIT;
465  case IK_AXES_DIGIT:
466  return K_AXES_DIGIT;
467  default:
468  return digit;
469  }
470 }
471
472 // /**
473 // * Find the normalized ijk coordinates of the hex centered on the indicated
474 // * hex at the next finer aperture 3 counter-clockwise resolution. Works in
475 // * place.
476 // *
477 // * @param ijk The ijk coordinates.
478 // */
479 // void _downAp3(CoordIJK* ijk) {
480 // // res r unit vectors in res r+1
481 // CoordIJK iVec = {2, 0, 1};
482 // CoordIJK jVec = {1, 2, 0};
483 // CoordIJK kVec = {0, 1, 2};
484
485 // _ijkScale(&iVec, ijk->i);
486 // _ijkScale(&jVec, ijk->j);
487 // _ijkScale(&kVec, ijk->k);
488
489 // _ijkAdd(&iVec, &jVec, ijk);
490 // _ijkAdd(ijk, &kVec, ijk);
491
492 // _ijkNormalize(ijk);
493 // }
494
495 // /**
496 // * Find the normalized ijk coordinates of the hex centered on the indicated
497 // * hex at the next finer aperture 3 clockwise resolution. Works in place.
498 // *
499 // * @param ijk The ijk coordinates.
500 // */
501 // void _downAp3r(CoordIJK* ijk) {
502 // // res r unit vectors in res r+1
503 // CoordIJK iVec = {2, 1, 0};
504 // CoordIJK jVec = {0, 2, 1};
505 // CoordIJK kVec = {1, 0, 2};
506
507 // _ijkScale(&iVec, ijk->i);
508 // _ijkScale(&jVec, ijk->j);
509 // _ijkScale(&kVec, ijk->k);
510
511 // _ijkAdd(&iVec, &jVec, ijk);
512 // _ijkAdd(ijk, &kVec, ijk);
513
514 // _ijkNormalize(ijk);
515 // }
516
517 // /**
518 // * Finds the distance between the two coordinates. Returns result.
519 // *
520 // * @param c1 The first set of ijk coordinates.
521 // * @param c2 The second set of ijk coordinates.
522 // */
523 // int ijkDistance(const CoordIJK* c1, const CoordIJK* c2) {
524 // CoordIJK diff;
525 // _ijkSub(c1, c2, &diff);
526 // _ijkNormalize(&diff);
527 // CoordIJK absDiff = {abs(diff.i), abs(diff.j), abs(diff.k)};
528 // return MAX(absDiff.i, MAX(absDiff.j, absDiff.k));
529 // }
530
531 // /**
532 // * Transforms coordinates from the IJK+ coordinate system to the IJ coordinate
533 // * system.
534 // *
535 // * @param ijk The input IJK+ coordinates
536 // * @param ij The output IJ coordinates
537 // */
538 // void ijkToIj(const CoordIJK* ijk, CoordIJ* ij) {
539 // ij->i = ijk->i - ijk->k;
540 // ij->j = ijk->j - ijk->k;
541 // }
542
543 // /**
544 // * Transforms coordinates from the IJ coordinate system to the IJK+ coordinate
545 // * system.
546 // *
547 // * @param ij The input IJ coordinates
548 // * @param ijk The output IJK+ coordinates
549 // */
550 // void ijToIjk(const CoordIJ* ij, CoordIJK* ijk) {
551 // ijk->i = ij->i;
552 // ijk->j = ij->j;
553 // ijk->k = 0;
554
555 // _ijkNormalize(ijk);
556 // }
557
558 // /**
559 // * Convert IJK coordinates to cube coordinates, in place
560 // * @param ijk Coordinate to convert
561 // */
562 // void ijkToCube(CoordIJK* ijk) {
563 // ijk->i = -ijk->i + ijk->k;
564 // ijk->j = ijk->j - ijk->k;
565 // ijk->k = -ijk->i - ijk->j;
566 // }
567
568 // /**
569 // * Convert cube coordinates to IJK coordinates, in place
570 // * @param ijk Coordinate to convert
571 // */
572 // void cubeToIjk(CoordIJK* ijk) {
573 // ijk->i = -ijk->i;
574 // ijk->k = 0;
575 // _ijkNormalize(ijk);
576 // }
EXTENSION_NOINLINE int _unitIjkToDigit(const CoordIJK(ijk))
Definition: coordijk.hpp:266
#define EXTENSION_NOINLINE
Definition: heavydbTypes.h:58
EXTENSION_INLINE bool _ijkSub(const CoordIJK(h1), const CoordIJK(h2), CoordIJK(diff))
Definition: coordijk.hpp:198
Constants used by more than one source code file.
EXTENSION_NOINLINE bool _neighbor(CoordIJK(ijk), int digit)
Definition: coordijk.hpp:372
#define J_INDEX
Definition: coordijk.h:43
EXTENSION_NOINLINE bool _ijkRotate60ccw(CoordIJK(ijk))
Definition: coordijk.hpp:385
EXTENSION_INLINE int _ijkMatches(const CoordIJK(c1), const CoordIJK(c2))
Definition: coordijk.hpp:172
EXTENSION_NOINLINE bool _downAp7r(CoordIJK(ijk))
Definition: coordijk.hpp:348
EXTENSION_NOINLINE bool _ijkRotate60cw(CoordIJK(ijk))
Definition: coordijk.hpp:407
EXTENSION_INLINE bool _ijkScale(CoordIJK(c), int factor)
Definition: coordijk.hpp:211
EXTENSION_NOINLINE bool _hex2dToCoordIJK(const Vec2d(v), CoordIJK(h))
Definition: coordijk.hpp:54
EXTENSION_NOINLINE int _rotate60ccw(int digit)
Definition: coordijk.hpp:429
#define CoordIJK_clone(ijk)
Definition: coordijk.h:47
#define EXTENSION_INLINE
Definition: heavydbTypes.h:57
#define Vec2d(variable_name)
Definition: vec2d.h:28
EXTENSION_INLINE bool _ijkAdd(const CoordIJK(h1), const CoordIJK(h2), CoordIJK(sum))
Definition: coordijk.hpp:184
#define M_SQRT3_2
Definition: constants.h:44
EXTENSION_INLINE bool _ijkToHex2d(const CoordIJK(h), Vec2d(v))
Definition: coordijk.hpp:155
#define I_INDEX
Definition: coordijk.h:42
Direction
H3 digit representing ijk+ axes direction. Values will be within the lowest 3 bits of an integer...
Definition: coordijk.h:75
EXTENSION_NOINLINE int _rotate60cw(int digit)
Definition: coordijk.hpp:453
#define X_INDEX
Definition: vec2d.h:26
#define CoordIJK(variable_name)
Definition: coordijk.h:45
EXTENSION_NOINLINE bool _downAp7(CoordIJK(ijk))
Definition: coordijk.hpp:325
EXTENSION_NOINLINE bool _upAp7(CoordIJK(ijk))
Definition: coordijk.hpp:287
#define K_INDEX
Definition: coordijk.h:44
#define Y_INDEX
Definition: vec2d.h:27
Header file for CoordIJK functions including conversion from lat/lon.
EXTENSION_NOINLINE bool _upAp7r(CoordIJK(ijk))
Definition: coordijk.hpp:306
EXTENSION_INLINE bool _setIJK(CoordIJK(ijk), int i, int j, int k)
Definition: coordijk.hpp:40
EXTENSION_NOINLINE bool _ijkNormalize(CoordIJK(c))
Definition: coordijk.hpp:224
#define M_SIN60
Definition: constants.h:46