0
# Directed Edges
1
2
Operations for working with directed edges between adjacent H3 cells. H3 directed edges represent connections between neighboring cells and enable analysis of cell boundaries, adjacency relationships, and edge-based operations.
3
4
## Capabilities
5
6
### Edge Creation and Validation
7
8
Create and validate H3 directed edges between adjacent cells.
9
10
```python { .api }
11
def cells_to_directed_edge(origin: str, destination: str) -> str:
12
"""
13
Create a directed edge between two adjacent H3 cells.
14
15
Creates an H3 directed edge identifier representing the connection
16
from origin cell to destination cell.
17
18
Args:
19
origin: Starting H3 cell identifier
20
destination: Ending H3 cell identifier
21
22
Returns:
23
H3 directed edge identifier
24
25
Raises:
26
H3CellInvalidError: If either cell identifier is invalid
27
H3NotNeighborsError: If cells are not adjacent neighbors
28
H3ResMismatchError: If cells have different resolutions
29
30
Note:
31
Cells must be immediate neighbors (grid_distance = 1).
32
Both cells must be at the same resolution.
33
Edge direction matters: edge(A,B) ≠ edge(B,A).
34
"""
35
36
def is_valid_directed_edge(edge: str) -> bool:
37
"""
38
Check if an H3 directed edge identifier is valid.
39
40
Args:
41
edge: H3 directed edge identifier (string or int)
42
43
Returns:
44
True if valid H3 directed edge, False otherwise
45
46
Note:
47
Returns False for any input that cannot be parsed as H3 edge,
48
including H3 cells or vertices.
49
"""
50
```
51
52
### Edge Decomposition
53
54
Extract information from H3 directed edges.
55
56
```python { .api }
57
def directed_edge_to_cells(e: str) -> tuple[str, str]:
58
"""
59
Get the origin and destination cells from a directed edge.
60
61
Args:
62
e: H3 directed edge identifier
63
64
Returns:
65
Tuple of (origin_cell, destination_cell)
66
67
Raises:
68
H3DirEdgeInvalidError: If e is not a valid H3 directed edge
69
70
Note:
71
This is the inverse operation of cells_to_directed_edge().
72
"""
73
74
def get_directed_edge_origin(e: str) -> str:
75
"""
76
Get the origin cell from a directed edge.
77
78
Args:
79
e: H3 directed edge identifier
80
81
Returns:
82
Origin H3 cell identifier
83
84
Raises:
85
H3DirEdgeInvalidError: If e is not a valid H3 directed edge
86
"""
87
88
def get_directed_edge_destination(e: str) -> str:
89
"""
90
Get the destination cell from a directed edge.
91
92
Args:
93
e: H3 directed edge identifier
94
95
Returns:
96
Destination H3 cell identifier
97
98
Raises:
99
H3DirEdgeInvalidError: If e is not a valid H3 directed edge
100
"""
101
```
102
103
### Edge Enumeration
104
105
Find all directed edges associated with a cell.
106
107
```python { .api }
108
def origin_to_directed_edges(origin: str) -> list[str]:
109
"""
110
Get all directed edges starting from an origin cell.
111
112
Returns edges from the origin cell to each of its neighbors.
113
114
Args:
115
origin: H3 cell identifier
116
117
Returns:
118
List of H3 directed edge identifiers starting from origin.
119
Order is not guaranteed.
120
121
Raises:
122
H3CellInvalidError: If origin is not a valid H3 cell
123
124
Note:
125
Hexagon cells return 6 edges, pentagon cells return 5 edges.
126
Each edge connects to one of the cell's immediate neighbors.
127
"""
128
```
129
130
### Edge Geometry
131
132
Extract geometric information from directed edges.
133
134
```python { .api }
135
def directed_edge_to_boundary(edge: str) -> tuple[tuple[float, float], ...]:
136
"""
137
Get the boundary points of a directed edge.
138
139
Returns the line segments that form the edge boundary between
140
two adjacent cells.
141
142
Args:
143
edge: H3 directed edge identifier
144
145
Returns:
146
Tuple of (lat, lng) coordinate pairs defining the edge boundary.
147
Typically returns 2 points (start and end of the edge line).
148
149
Raises:
150
H3DirEdgeInvalidError: If edge is not a valid H3 directed edge
151
152
Note:
153
Points are ordered from origin cell boundary toward destination cell.
154
The edge represents the shared boundary between the two cells.
155
"""
156
```
157
158
## Usage Examples
159
160
### Basic Edge Operations
161
162
```python
163
import h3
164
165
# Create two adjacent cells
166
origin = h3.latlng_to_cell(37.7749, -122.4194, 9)
167
neighbors = h3.grid_ring(origin, k=1)
168
destination = neighbors[0] # Pick first neighbor
169
170
print(f"Origin: {origin}")
171
print(f"Destination: {destination}")
172
173
# Verify they are neighbors
174
is_neighbor = h3.are_neighbor_cells(origin, destination)
175
print(f"Are neighbors: {is_neighbor}")
176
177
# Create directed edge
178
edge = h3.cells_to_directed_edge(origin, destination)
179
print(f"Directed edge: {edge}")
180
181
# Validate the edge
182
is_valid = h3.is_valid_directed_edge(edge)
183
print(f"Edge is valid: {is_valid}")
184
```
185
186
### Edge Decomposition
187
188
```python
189
import h3
190
191
# Start with a known edge
192
origin = h3.latlng_to_cell(40.7589, -73.9851, 8) # NYC
193
all_edges = h3.origin_to_directed_edges(origin)
194
edge = all_edges[0] # Pick first edge
195
196
print(f"Working with edge: {edge}")
197
198
# Extract components
199
extracted_origin = h3.get_directed_edge_origin(edge)
200
extracted_dest = h3.get_directed_edge_destination(edge)
201
202
print(f"Extracted origin: {extracted_origin}")
203
print(f"Extracted destination: {extracted_dest}")
204
print(f"Origin matches: {origin == extracted_origin}")
205
206
# Use combined extraction
207
origin_dest = h3.directed_edge_to_cells(edge)
208
print(f"Combined extraction: {origin_dest}")
209
print(f"Matches individual: {(extracted_origin, extracted_dest) == origin_dest}")
210
211
# Verify round-trip
212
reconstructed_edge = h3.cells_to_directed_edge(extracted_origin, extracted_dest)
213
print(f"Reconstructed edge: {reconstructed_edge}")
214
print(f"Round-trip success: {edge == reconstructed_edge}")
215
```
216
217
### Edge Enumeration and Analysis
218
219
```python
220
import h3
221
222
# Analyze edges for different cell types
223
cells = [
224
h3.latlng_to_cell(37.7749, -122.4194, 7), # Regular hexagon
225
h3.get_pentagons(7)[0] # Pentagon at same resolution
226
]
227
228
for i, cell in enumerate(cells):
229
cell_type = "pentagon" if h3.is_pentagon(cell) else "hexagon"
230
print(f"\nCell {i+1} ({cell_type}): {cell}")
231
232
# Get all outgoing edges
233
edges = h3.origin_to_directed_edges(cell)
234
print(f" Outgoing edges: {len(edges)}")
235
236
# Analyze each edge
237
for j, edge in enumerate(edges):
238
dest = h3.get_directed_edge_destination(edge)
239
print(f" Edge {j}: {edge} -> {dest}")
240
241
# Verify neighbor relationship
242
is_neighbor = h3.are_neighbor_cells(cell, dest)
243
assert is_neighbor, f"Edge destination should be neighbor"
244
245
# Expected: hexagon has 6 edges, pentagon has 5 edges
246
expected_count = 5 if h3.is_pentagon(cell) else 6
247
print(f" Expected edges: {expected_count}, actual: {len(edges)}")
248
assert len(edges) == expected_count
249
```
250
251
### Edge Geometry and Boundaries
252
253
```python
254
import h3
255
256
# Create an edge and examine its geometry
257
center = h3.latlng_to_cell(51.5074, -0.1278, 9) # London
258
neighbors = h3.grid_ring(center, k=1)
259
edge = h3.cells_to_directed_edge(center, neighbors[0])
260
261
print(f"Analyzing edge: {edge}")
262
263
# Get edge boundary
264
boundary = h3.directed_edge_to_boundary(edge)
265
print(f"Edge boundary points: {len(boundary)}")
266
267
for i, (lat, lng) in enumerate(boundary):
268
print(f" Point {i}: {lat:.6f}, {lng:.6f}")
269
270
# Compare with cell boundaries
271
origin_boundary = h3.cell_to_boundary(center)
272
dest_boundary = h3.cell_to_boundary(neighbors[0])
273
274
print(f"\nOrigin cell boundary: {len(origin_boundary)} points")
275
print(f"Destination cell boundary: {len(dest_boundary)} points")
276
277
# Edge boundary should be part of both cell boundaries
278
print(f"\nEdge represents shared boundary between cells")
279
```
280
281
### Edge Network Analysis
282
283
```python
284
import h3
285
286
# Build a local edge network
287
center = h3.latlng_to_cell(37.7749, -122.4194, 8)
288
region = h3.grid_disk(center, k=2)
289
290
print(f"Analyzing edge network for {len(region)} cells")
291
292
# Collect all edges within the region
293
all_edges = []
294
edge_count_by_cell = {}
295
296
for cell in region:
297
edges = h3.origin_to_directed_edges(cell)
298
299
# Filter edges to only include those within our region
300
internal_edges = []
301
for edge in edges:
302
dest = h3.get_directed_edge_destination(edge)
303
if dest in region:
304
internal_edges.append(edge)
305
306
all_edges.extend(internal_edges)
307
edge_count_by_cell[cell] = len(internal_edges)
308
309
print(f"Total internal edges: {len(all_edges)}")
310
311
# Analyze edge distribution
312
edge_counts = list(edge_count_by_cell.values())
313
print(f"Edge count per cell - min: {min(edge_counts)}, max: {max(edge_counts)}, avg: {sum(edge_counts)/len(edge_counts):.1f}")
314
315
# Verify each edge connects cells within region
316
print("\nValidating edge network:")
317
valid_edges = 0
318
for edge in all_edges:
319
origin, dest = h3.directed_edge_to_cells(edge)
320
if origin in region and dest in region:
321
valid_edges += 1
322
323
print(f"Valid internal edges: {valid_edges}/{len(all_edges)}")
324
```
325
326
### Bidirectional Edge Analysis
327
328
```python
329
import h3
330
331
# Analyze bidirectional relationships
332
cell_a = h3.latlng_to_cell(40.7589, -73.9851, 9)
333
neighbors = h3.grid_ring(cell_a, k=1)
334
cell_b = neighbors[0]
335
336
print(f"Cell A: {cell_a}")
337
print(f"Cell B: {cell_b}")
338
339
# Create edges in both directions
340
edge_a_to_b = h3.cells_to_directed_edge(cell_a, cell_b)
341
edge_b_to_a = h3.cells_to_directed_edge(cell_b, cell_a)
342
343
print(f"A->B edge: {edge_a_to_b}")
344
print(f"B->A edge: {edge_b_to_a}")
345
print(f"Edges are different: {edge_a_to_b != edge_b_to_a}")
346
347
# Verify both edges represent the same geometric boundary
348
boundary_a_to_b = h3.directed_edge_to_boundary(edge_a_to_b)
349
boundary_b_to_a = h3.directed_edge_to_boundary(edge_b_to_a)
350
351
print(f"\nBoundary A->B: {len(boundary_a_to_b)} points")
352
print(f"Boundary B->A: {len(boundary_b_to_a)} points")
353
354
# Boundaries should be related (possibly reversed)
355
print(f"Same boundary points: {set(boundary_a_to_b) == set(boundary_b_to_a)}")
356
357
# Check all pairs of neighbors have symmetric edges
358
cell_edges = h3.origin_to_directed_edges(cell_a)
359
print(f"\nSymmetric edge verification:")
360
361
for edge in cell_edges:
362
neighbor = h3.get_directed_edge_destination(edge)
363
reverse_edge = h3.cells_to_directed_edge(neighbor, cell_a)
364
365
print(f" {cell_a} -> {neighbor}: {edge}")
366
print(f" {neighbor} -> {cell_a}: {reverse_edge}")
367
print(f" Both valid: {h3.is_valid_directed_edge(edge) and h3.is_valid_directed_edge(reverse_edge)}")
368
```
369
370
### Edge Length Calculation
371
372
```python
373
import h3
374
375
# Calculate edge lengths using the edge measurement functions
376
center = h3.latlng_to_cell(0, 0, 10) # Equator, high resolution
377
edges = h3.origin_to_directed_edges(center)
378
379
print(f"Edge length analysis for resolution 10 cell at equator:")
380
print(f"Cell has {len(edges)} edges")
381
382
# Calculate length of each edge
383
edge_lengths = []
384
for i, edge in enumerate(edges):
385
length_km = h3.edge_length(edge, 'km')
386
length_m = h3.edge_length(edge, 'm')
387
edge_lengths.append(length_km)
388
389
print(f" Edge {i}: {length_km:.3f} km ({length_m:.1f} m)")
390
391
# Compare to average for this resolution
392
avg_edge_length = h3.average_hexagon_edge_length(10, 'km')
393
actual_avg = sum(edge_lengths) / len(edge_lengths)
394
395
print(f"\nAverage edge length (H3 system): {avg_edge_length:.3f} km")
396
print(f"Average edge length (this cell): {actual_avg:.3f} km")
397
print(f"Match: {abs(avg_edge_length - actual_avg) < 0.001}")
398
399
# Variation in edge lengths (should be minimal for regular hexagon)
400
max_length = max(edge_lengths)
401
min_length = min(edge_lengths)
402
variation = (max_length - min_length) / avg_edge_length
403
404
print(f"Edge length variation: {variation:.1%}")
405
```