I either found a bug or have a misunderstanding on how directed edges work, but basically: I calculated the neighbor in the i-direction of a cell two different ways, and although they agree sometimes, I also found a disagreement at the North Pole.
I started with the coordinates for the
North Pole (90 degrees, 0 degrees)
And got the containing cell at Resolution 5.
Calculation using Hex2d:
- Project lat/long coordinates to Hex2d.
- In theory the x-axis points in the direction of i and the distance between cell centers is 1, so I added 1 to the x value, which should give me the center of the neighbor in the i-direction, which I call the "first" neighbor. It has neighbor id=4.
- I converted the value to lat/long and got an H3Index string for it.
Calculation using Directed Edge:
- I created my own directed edge using bit manipulation
- Then used
getDirectedEdgeDestination to find the resulting H3Index.
Problem:
I think that these two methods should yield the same H3Index, but it gives different results
Results:
"bug_report": {
"target_latlng_deg": [
90.0,
0.0
],
"target_hex2d": [
59.886191626793995,
-69.045551815467732
],
"targe_cell_h3id": "85032623fffffff",
"target_cell_center_hex2d": [
60.0,
-69.282032302755084
],
"first_neighbor_center_latlng_deg": [
89.818557346385802,
3.4019746730708249
],
"first_neighbor_by_hex2d": "85032637fffffff",
"directed_edge_to_first_neighbor_cell_h3id": "145032623fffffff",
"first_neighbor_by_directed_edge_h3id": "85032633fffffff"
},
Hex2d calculation gave me: 85032637fffffff
Directed edge calculation gave me: 85032633fffffff
Sanity checks for the directed edge:
- Starts with 1 (using edge mode)
- Second nibble is 4, meaning the neighbor in the i direction
- The remainder '5032623fffffff' agrees with the origin cell '85032623fffffff'
Some code I did to explain lower-level details:
{
json_t *bug_report = json_object();
json_object_set_new(msg, "bug_report", bug_report);
json_t *pair = json_pack("[f, f]", latitude, longitude);
json_object_set_new(bug_report, "target_latlng_deg", pair);
//convert lat/lng to radians
const LatLng g = {latitude*M_PI_180, longitude*M_PI_180};
Vec2d v;
int f;
int res=5;
//Get hex2d for lat/lng
_geoToHex2d(&g, res, &f, &v);
pair = json_pack("[f, f]", v.x, v.y);
json_object_set_new(bug_report, "target_hex2d", pair);
CoordIJK target_cell_center_ijk;
Vec2d target_cell_center_hex2d;
_hex2dToCoordIJK(&v, &target_cell_center_ijk);
_ijkToHex2d(&target_cell_center_ijk, &target_cell_center_hex2d);
FaceIJK fijk = {f, cellCenterIJK};
H3Index target_cell_h3id = _faceIjkToH3(&fijk, resolution);
size_t H3_CANONICAL_STR_INDEX_SIZE = 17;
char h3_index_str[H3_CANONICAL_STR_INDEX_SIZE];
h3ToString(target_cell_h3id, h3_index_str, H3_CANONICAL_STR_INDEX_SIZE);
json_object_set_new(bug_report, "targe_cell_h3id", json_string(h3_index_str));
pair = json_pack("[f, f]", target_cell_center_hex2d.x, target_cell_center_hex2d.y);
json_object_set_new(bug_report, "target_cell_center_hex2d", pair);
//In theory this is the center in hex2d of the neighbor in x-direction?
Vec2d first_neighbor_center_hex2d = {target_cell_center_hex2d.x + 1, target_cell_center_hex2d.y};
LatLng first_neighbor_center_latlng;
_hex2dToGeo(&first_neighbor_center_hex2d, f, res, 0, &first_neighbor_center_latlng);
pair = json_pack("[f, f]", first_neighbor_center_latlng.lat*M_180_PI, first_neighbor_center_latlng.lng*M_180_PI);
json_object_set_new(bug_report, "first_neighbor_center_latlng_deg", pair);
H3Index first_neighbor_cell_center_h3id;
latLngToCell(&first_neighbor_center_latlng, res, &first_neighbor_cell_center_h3id);
h3ToString(first_neighbor_cell_center_h3id, h3_index_str, H3_CANONICAL_STR_INDEX_SIZE);
json_object_set_new(bug_report, "first_neighbor_by_hex2d", json_string(h3_index_str));
/*Calculate using directed edge now*/
//Clear the first 8 bits
H3Index directedEdgeTemplate = target_cell_h3id & ~((H3Index)0xFF<<(H3_NUM_BITS-8));
//Set for directed edge
directedEdgeTemplate |= (H3Index)H3_DIRECTEDEDGE_MODE << (H3_NUM_BITS-5);
// Neighbor id = 4 is in the x-direction.
int edge_id = 4;
H3Index directed_edge = directedEdgeTemplate | ((H3Index)edge_id << (H3_NUM_BITS-8));
h3ToString(directed_edge, h3_index_str, H3_CANONICAL_STR_INDEX_SIZE);
json_object_set_new(bug_report, "directed_edge_to_first_neighbor_cell_h3id", json_string(h3_index_str));
H3Index first_neighbor_by_directed_edge;
getDirectedEdgeDestination(directed_edge, &first_neighbor_by_directed_edge);
H3Error err = h3ToString(first_neighbor_by_directed_edge, h3_index_str, H3_CANONICAL_STR_INDEX_SIZE);
if (err) {
fprintf(stderr, "Error: %d", err);
}
json_object_set_new(bug_report, "first_neighbor_by_directed_edge_h3id", json_string(h3_index_str));
}
I have a picture for the North Pole, too -- made on Google Earth:
Shouldn't they yield the exact same H3Index or do I have a misunderstanding?
I think there's a bug in the directed edge logic, but I'm not sure exactly where.
``
Thanks for reading!
I either found a bug or have a misunderstanding on how directed edges work, but basically: I calculated the neighbor in the i-direction of a cell two different ways, and although they agree sometimes, I also found a disagreement at the North Pole.
I started with the coordinates for the
North Pole (90 degrees, 0 degrees)
And got the containing cell at Resolution 5.
Calculation using Hex2d:
Calculation using Directed Edge:
getDirectedEdgeDestinationto find the resulting H3Index.Problem:
I think that these two methods should yield the same H3Index, but it gives different results
Results:
Sanity checks for the directed edge:
Some code I did to explain lower-level details:
I have a picture for the North Pole, too -- made on Google Earth:
Shouldn't they yield the exact same H3Index or do I have a misunderstanding?
I think there's a bug in the directed edge logic, but I'm not sure exactly where.
``
Thanks for reading!