1cimport h3lib
2from .h3lib cimport bool, H3int
3
4from .util cimport (
5    check_cell,
6    check_edge,
7    check_res,
8    create_ptr,
9    create_mv,
10)
11
12from .util import H3ValueError
13
14cpdef bool are_neighbors(H3int h1, H3int h2):
15    check_cell(h1)
16    check_cell(h2)
17
18    return h3lib.h3IndexesAreNeighbors(h1, h2) == 1
19
20
21cpdef H3int edge(H3int origin, H3int destination) except 1:
22    check_cell(origin)
23    check_cell(destination)
24
25    if h3lib.h3IndexesAreNeighbors(origin, destination) != 1:
26        s = 'Cells are not neighbors: {} and {}'
27        s = s.format(hex(origin), hex(destination))
28        raise H3ValueError(s)
29
30    return h3lib.getH3UnidirectionalEdge(origin, destination)
31
32
33cpdef bool is_edge(H3int e):
34    return h3lib.h3UnidirectionalEdgeIsValid(e) == 1
35
36cpdef H3int edge_origin(H3int e) except 1:
37    # without the check, with an invalid input, the function will just return 0
38    check_edge(e)
39
40    return h3lib.getOriginH3IndexFromUnidirectionalEdge(e)
41
42cpdef H3int edge_destination(H3int e) except 1:
43    check_edge(e)
44
45    return h3lib.getDestinationH3IndexFromUnidirectionalEdge(e)
46
47cpdef (H3int, H3int) edge_cells(H3int e) except *:
48    check_edge(e)
49
50    return edge_origin(e), edge_destination(e)
51
52cpdef H3int[:] edges_from_cell(H3int origin):
53    """ Returns the 6 (or 5 for pentagons) directed edges
54    for the given origin cell
55    """
56    check_cell(origin)
57
58    ptr = create_ptr(6)
59    h3lib.getH3UnidirectionalEdgesFromHexagon(origin, ptr)
60    mv = create_mv(ptr, 6)
61
62    return mv
63
64
65cpdef double mean_edge_length(int resolution, unit='km') except -1:
66    check_res(resolution)
67
68    length = h3lib.edgeLengthKm(resolution)
69
70    # todo: multiple units
71    convert = {
72        'km': 1.0,
73        'm': 1000.0
74    }
75
76    try:
77        length *= convert[unit]
78    except:
79        raise H3ValueError('Unknown unit: {}'.format(unit))
80
81    return length
82
83
84cpdef double edge_length(H3int e, unit='km') except -1:
85    check_edge(e)
86
87    # todo: maybe kick this logic up to the python level
88    # it might be a little cleaner, because we can do the "switch statement"
89    # with a dict, but would require exposing more C functions
90
91    if unit == 'rads':
92        length = h3lib.exactEdgeLengthRads(e)
93    elif unit == 'km':
94        length = h3lib.exactEdgeLengthKm(e)
95    elif unit == 'm':
96        length = h3lib.exactEdgeLengthM(e)
97    else:
98        raise H3ValueError('Unknown unit: {}'.format(unit))
99
100    return length
101