Skip to content

Directed Edge disagrees with Hex2d i-direction Neighbor Resolution for the North Pole #1118

@joshuaRosales

Description

@joshuaRosales

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:

  1. Project lat/long coordinates to Hex2d.
  2. 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.
  3. I converted the value to lat/long and got an H3Index string for it.
Image

Calculation using Directed Edge:

  1. I created my own directed edge using bit manipulation
  2. 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:

Image

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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions