or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-operations.mdcell-hierarchy.mdcore-cell-operations.mddirected-edges.mdgrid-navigation.mdindex.mdmeasurements.mdpolygon-operations.md

advanced-operations.mddocs/

0

# Advanced Operations

1

2

Specialized functions for advanced H3 operations including local coordinate systems, vertex operations, and system introspection. These functions enable sophisticated spatial analysis and provide access to H3's internal geometric structures.

3

4

## Capabilities

5

6

### Local Coordinate Systems

7

8

Convert between H3 cells and local (i,j) coordinate systems for efficient spatial operations.

9

10

```python { .api }

11

def cell_to_local_ij(origin: str, h: str) -> tuple[int, int]:

12

"""

13

Convert H3 cell to local (i,j) coordinates relative to an origin cell.

14

15

The local coordinate system is anchored to the origin cell's base cell,

16

not the origin cell itself. This provides consistent coordinates across

17

operations without recomputing the origin's position.

18

19

Args:

20

origin: Origin H3 cell identifier defining the coordinate system

21

h: Target H3 cell identifier to convert to local coordinates

22

23

Returns:

24

Tuple of (i, j) integer coordinates

25

26

Raises:

27

H3CellInvalidError: If either cell identifier is invalid

28

H3ResMismatchError: If cells have different resolutions

29

H3GridNavigationError: If cells are too far apart

30

31

Note:

32

Both cells must be at the same resolution.

33

The (0,0) coordinate represents the center of the base cell

34

containing the origin, not the origin cell itself.

35

"""

36

37

def local_ij_to_cell(origin: str, i: int, j: int) -> str:

38

"""

39

Convert local (i,j) coordinates to H3 cell relative to an origin cell.

40

41

This is the inverse operation of cell_to_local_ij().

42

43

Args:

44

origin: Origin H3 cell identifier defining the coordinate system

45

i: Integer i-coordinate

46

j: Integer j-coordinate

47

48

Returns:

49

H3 cell identifier at the specified local coordinates

50

51

Raises:

52

H3CellInvalidError: If origin is not a valid H3 cell

53

H3GridNavigationError: If coordinates are outside valid range

54

55

Note:

56

The coordinate system is anchored to the origin cell's base cell.

57

Large coordinate values may be outside the valid range.

58

"""

59

```

60

61

### Vertex Operations

62

63

Work with H3 cell vertices and their geometric properties.

64

65

```python { .api }

66

def cell_to_vertex(h: str, vertex_num: int) -> str:

67

"""

68

Get a specific vertex of an H3 cell by vertex number.

69

70

Args:

71

h: H3 cell identifier

72

vertex_num: Vertex number (0-5 for hexagons, 0-4 for pentagons)

73

74

Returns:

75

H3 vertex identifier

76

77

Raises:

78

H3CellInvalidError: If h is not a valid H3 cell

79

ValueError: If vertex_num is outside valid range for the cell

80

81

Note:

82

Hexagons have vertices 0-5, pentagons have vertices 0-4.

83

Vertex numbering follows a consistent orientation.

84

"""

85

86

def cell_to_vertexes(h: str) -> list[str]:

87

"""

88

Get all vertices of an H3 cell.

89

90

Args:

91

h: H3 cell identifier

92

93

Returns:

94

List of H3 vertex identifiers (5 for pentagons, 6 for hexagons)

95

96

Raises:

97

H3CellInvalidError: If h is not a valid H3 cell

98

99

Note:

100

Vertices are returned in consistent order around the cell boundary.

101

Pentagon cells return 5 vertices, hexagon cells return 6 vertices.

102

"""

103

104

def vertex_to_latlng(v: str) -> tuple[float, float]:

105

"""

106

Get the latitude and longitude coordinates of an H3 vertex.

107

108

Args:

109

v: H3 vertex identifier

110

111

Returns:

112

Tuple of (latitude, longitude) in degrees

113

114

Raises:

115

H3VertexInvalidError: If v is not a valid H3 vertex

116

117

Note:

118

Vertices represent the corner points where cell boundaries meet.

119

Multiple cells may share the same vertex.

120

"""

121

122

def is_valid_vertex(v: str) -> bool:

123

"""

124

Check if an H3 vertex identifier is valid.

125

126

Args:

127

v: H3 vertex identifier (string or int)

128

129

Returns:

130

True if valid H3 vertex, False otherwise

131

132

Note:

133

Returns False for any input that cannot be parsed as H3 vertex,

134

including H3 cells or edges.

135

"""

136

```

137

138

### System Introspection

139

140

Access specialized cells and system structure information.

141

142

```python { .api }

143

def get_pentagons(res: int) -> list[str]:

144

"""

145

Get all pentagon H3 cells at a given resolution.

146

147

Args:

148

res: H3 resolution (0-15)

149

150

Returns:

151

List of all 12 pentagon H3 cell identifiers at the specified resolution

152

153

Raises:

154

H3ResDomainError: If res < 0 or res > 15

155

156

Note:

157

There are exactly 12 pentagons at every resolution level.

158

Pentagons occur at the vertices of the underlying icosahedron.

159

Order is not guaranteed.

160

"""

161

162

def get_res0_cells() -> list[str]:

163

"""

164

Get all H3 cells at resolution 0 (base cells).

165

166

Returns:

167

List of all 122 base H3 cell identifiers

168

169

Note:

170

These are the coarsest cells in the H3 system.

171

Includes 12 pentagons and 110 hexagons.

172

All higher-resolution cells are descendants of these base cells.

173

Order is not guaranteed.

174

"""

175

176

def get_icosahedron_faces(h: str) -> set[int]:

177

"""

178

Get the icosahedron faces that intersect with an H3 cell.

179

180

H3 is based on an icosahedron projection, which has 20 triangular faces.

181

This function returns which faces are intersected by the given cell.

182

183

Args:

184

h: H3 cell identifier

185

186

Returns:

187

Python set of integers representing face numbers (0-19)

188

189

Raises:

190

H3CellInvalidError: If h is not a valid H3 cell

191

192

Note:

193

Most cells intersect 1 face, but cells near face boundaries

194

may intersect 2 or 3 faces. Face numbers range from 0 to 19.

195

"""

196

```

197

198

## Usage Examples

199

200

### Local Coordinate System Operations

201

202

```python

203

import h3

204

205

# Set up a local coordinate system

206

origin = h3.latlng_to_cell(37.7749, -122.4194, 9) # San Francisco

207

print(f"Origin cell: {origin}")

208

209

# Get some nearby cells

210

nearby_cells = h3.grid_disk(origin, k=2)

211

print(f"Working with {len(nearby_cells)} nearby cells")

212

213

# Convert cells to local coordinates

214

local_coords = {}

215

for cell in nearby_cells:

216

i, j = h3.cell_to_local_ij(origin, cell)

217

local_coords[cell] = (i, j)

218

219

print(f"\nLocal coordinates (first 10 cells):")

220

for cell, (i, j) in list(local_coords.items())[:10]:

221

print(f" {cell}: ({i:3d}, {j:3d})")

222

223

# Find origin's coordinates (should be relative to its base cell, not (0,0))

224

origin_i, origin_j = h3.cell_to_local_ij(origin, origin)

225

print(f"\nOrigin coordinates: ({origin_i}, {origin_j})")

226

print("Note: Origin coordinates are relative to base cell center, not (0,0)")

227

228

# Test round-trip conversion

229

test_cell = list(nearby_cells)[5]

230

i, j = h3.cell_to_local_ij(origin, test_cell)

231

recovered_cell = h3.local_ij_to_cell(origin, i, j)

232

233

print(f"\nRound-trip test:")

234

print(f" Original: {test_cell}")

235

print(f" Local coords: ({i}, {j})")

236

print(f" Recovered: {recovered_cell}")

237

print(f" Match: {test_cell == recovered_cell}")

238

```

239

240

### Grid Pattern Analysis with Local Coordinates

241

242

```python

243

import h3

244

import matplotlib.pyplot as plt

245

246

# Create a coordinate grid pattern

247

center = h3.latlng_to_cell(40.7589, -73.9851, 8) # NYC

248

region = h3.grid_disk(center, k=4)

249

250

# Convert to local coordinates for analysis

251

coords = []

252

cells = []

253

254

for cell in region:

255

i, j = h3.cell_to_local_ij(center, cell)

256

coords.append((i, j))

257

cells.append(cell)

258

259

print(f"Analyzing {len(region)} cells in local coordinate space")

260

261

# Find coordinate ranges

262

i_coords = [i for i, j in coords]

263

j_coords = [j for i, j in coords]

264

265

print(f"I coordinate range: {min(i_coords)} to {max(i_coords)}")

266

print(f"J coordinate range: {min(j_coords)} to {max(j_coords)}")

267

268

# Analyze coordinate distribution

269

i_span = max(i_coords) - min(i_coords)

270

j_span = max(j_coords) - min(j_coords)

271

print(f"Coordinate space spans: {i_span} x {j_span}")

272

273

# Find cells along coordinate axes

274

origin_i, origin_j = h3.cell_to_local_ij(center, center)

275

print(f"\nCells along coordinate axes (relative to origin at {origin_i}, {origin_j}):")

276

277

# Find cells with same i-coordinate as origin

278

same_i_cells = [(cell, i, j) for cell, (i, j) in zip(cells, coords) if i == origin_i]

279

print(f" Same I-coordinate ({origin_i}): {len(same_i_cells)} cells")

280

281

# Find cells with same j-coordinate as origin

282

same_j_cells = [(cell, i, j) for cell, (i, j) in zip(cells, coords) if j == origin_j]

283

print(f" Same J-coordinate ({origin_j}): {len(same_j_cells)} cells")

284

285

# Optional: Create a simple plot if matplotlib is available

286

try:

287

plt.figure(figsize=(10, 8))

288

plt.scatter(i_coords, j_coords, alpha=0.6)

289

plt.scatter([origin_i], [origin_j], color='red', s=100, label='Origin')

290

plt.xlabel('I Coordinate')

291

plt.ylabel('J Coordinate')

292

plt.title('H3 Cells in Local Coordinate Space')

293

plt.legend()

294

plt.grid(True, alpha=0.3)

295

plt.axis('equal')

296

plt.savefig('h3_local_coords.png', dpi=150, bbox_inches='tight')

297

print(f"\nCoordinate plot saved as 'h3_local_coords.png'")

298

except ImportError:

299

print(f"\nMatplotlib not available - skipping coordinate plot")

300

```

301

302

### Vertex Analysis

303

304

```python

305

import h3

306

307

# Analyze vertices for different cell types

308

test_cells = [

309

h3.latlng_to_cell(37.7749, -122.4194, 8), # Regular hexagon

310

h3.get_pentagons(8)[0] # Pentagon at same resolution

311

]

312

313

print("Vertex analysis:")

314

315

for i, cell in enumerate(test_cells):

316

cell_type = "pentagon" if h3.is_pentagon(cell) else "hexagon"

317

print(f"\nCell {i+1} ({cell_type}): {cell}")

318

319

# Get all vertices

320

vertices = h3.cell_to_vertexes(cell)

321

print(f" Vertices: {len(vertices)}")

322

323

# Show each vertex with coordinates

324

vertex_coords = []

325

for j, vertex in enumerate(vertices):

326

lat, lng = h3.vertex_to_latlng(vertex)

327

vertex_coords.append((lat, lng))

328

is_valid = h3.is_valid_vertex(vertex)

329

print(f" Vertex {j}: {vertex} -> {lat:.6f}, {lng:.6f} (valid: {is_valid})")

330

331

# Test individual vertex access

332

print(f" Individual vertex access:")

333

for vertex_num in range(len(vertices)):

334

individual_vertex = h3.cell_to_vertex(cell, vertex_num)

335

matches_list = individual_vertex == vertices[vertex_num]

336

print(f" Vertex {vertex_num}: {individual_vertex} (matches list: {matches_list})")

337

338

# Calculate vertex distances (perimeter)

339

perimeter = 0.0

340

for j in range(len(vertex_coords)):

341

start = vertex_coords[j]

342

end = vertex_coords[(j + 1) % len(vertex_coords)] # Wrap around

343

distance = h3.great_circle_distance(start, end, 'km')

344

perimeter += distance

345

print(f" Edge {j}-{(j+1) % len(vertex_coords)}: {distance:.6f} km")

346

347

print(f" Total perimeter: {perimeter:.6f} km")

348

349

# Compare to expected edge count

350

expected_vertices = 5 if h3.is_pentagon(cell) else 6

351

assert len(vertices) == expected_vertices

352

```

353

354

### Pentagon Location Analysis

355

356

```python

357

import h3

358

359

# Analyze pentagon distribution across resolutions

360

print("Pentagon analysis across resolutions:")

361

362

for res in range(0, 8):

363

pentagons = h3.get_pentagons(res)

364

print(f"\nResolution {res}: {len(pentagons)} pentagons")

365

366

# Analyze pentagon locations

367

pentagon_coords = []

368

for pentagon in pentagons:

369

lat, lng = h3.cell_to_latlng(pentagon)

370

pentagon_coords.append((lat, lng, pentagon))

371

372

# Sort by latitude to see distribution

373

pentagon_coords.sort(key=lambda x: x[0], reverse=True) # North to South

374

375

print(" Pentagon locations (North to South):")

376

for i, (lat, lng, pentagon) in enumerate(pentagon_coords[:5]): # Show first 5

377

base_cell = h3.get_base_cell_number(pentagon)

378

print(f" {i+1}: {pentagon} -> {lat:7.2f}°, {lng:8.2f}° (base cell {base_cell})")

379

380

if len(pentagon_coords) > 5:

381

print(f" ... and {len(pentagon_coords) - 5} more")

382

383

# Analyze pentagon neighbors

384

print(f"\nPentagon neighbor analysis at resolution 6:")

385

pentagon = h3.get_pentagons(6)[0]

386

neighbors = h3.grid_ring(pentagon, k=1)

387

388

print(f"Pentagon {pentagon}:")

389

print(f" Neighbors: {len(neighbors)} (expected 5 for pentagon)")

390

391

# Check if neighbors are hexagons

392

neighbor_types = {}

393

for neighbor in neighbors:

394

is_pent = h3.is_pentagon(neighbor)

395

neighbor_type = "pentagon" if is_pent else "hexagon"

396

neighbor_types[neighbor_type] = neighbor_types.get(neighbor_type, 0) + 1

397

398

print(f" Neighbor types: {dict(neighbor_types)}")

399

```

400

401

### Icosahedron Face Analysis

402

403

```python

404

import h3

405

406

# Analyze icosahedron face distribution

407

print("Icosahedron face analysis:")

408

409

# Test cells at different locations and resolutions

410

test_cases = [

411

("Equator", 0, 0, 5),

412

("North Pole region", 85, 0, 5),

413

("South Pole region", -85, 0, 5),

414

("Pacific", 0, -180, 5),

415

("Face boundary", 0, 0, 3), # Lower resolution to potentially cross faces

416

]

417

418

for name, lat, lng, res in test_cases:

419

cell = h3.latlng_to_cell(lat, lng, res)

420

faces = h3.get_icosahedron_faces(cell)

421

422

print(f"\n{name} (res {res}): {cell}")

423

print(f" Intersects faces: {sorted(faces)} ({len(faces)} faces)")

424

425

# Get neighbors and analyze their faces

426

neighbors = h3.grid_ring(cell, k=1)

427

neighbor_faces = set()

428

429

for neighbor in neighbors:

430

n_faces = h3.get_icosahedron_faces(neighbor)

431

neighbor_faces.update(n_faces)

432

433

all_faces = faces.union(neighbor_faces)

434

print(f" Cell + neighbors span faces: {sorted(all_faces)} ({len(all_faces)} total)")

435

436

# Find cells that cross multiple faces

437

print(f"\nSearching for multi-face cells at resolution 2:")

438

multi_face_count = 0

439

face_distribution = {}

440

441

# Sample some cells at low resolution

442

for base_cell in h3.get_res0_cells()[:20]: # Check first 20 base cells

443

children = h3.cell_to_children(base_cell, res=2)

444

445

for cell in children:

446

faces = h3.get_icosahedron_faces(cell)

447

face_count = len(faces)

448

face_distribution[face_count] = face_distribution.get(face_count, 0) + 1

449

450

if face_count > 1:

451

multi_face_count += 1

452

if multi_face_count <= 3: # Show first few examples

453

lat, lng = h3.cell_to_latlng(cell)

454

print(f" Multi-face cell: {cell} -> {sorted(faces)} at {lat:.2f}, {lng:.2f}")

455

456

print(f"\nFace intersection distribution (sample of {sum(face_distribution.values())} cells):")

457

for face_count, count in sorted(face_distribution.items()):

458

print(f" {face_count} face(s): {count} cells ({count/sum(face_distribution.values()):.1%})")

459

```

460

461

### System Structure Overview

462

463

```python

464

import h3

465

466

# Comprehensive system structure analysis

467

print("H3 System Structure Overview:")

468

469

# Base cell analysis

470

base_cells = h3.get_res0_cells()

471

pentagons_res0 = h3.get_pentagons(0)

472

473

print(f"\nBase structure (Resolution 0):")

474

print(f" Total base cells: {len(base_cells)}")

475

print(f" Pentagons: {len(pentagons_res0)}")

476

print(f" Hexagons: {len(base_cells) - len(pentagons_res0)}")

477

478

# Verify pentagon consistency

479

pentagon_base_cells = [cell for cell in base_cells if h3.is_pentagon(cell)]

480

print(f" Pentagon count verification: {len(pentagon_base_cells)} (should match {len(pentagons_res0)})")

481

482

# Show base cell number range

483

base_numbers = [h3.get_base_cell_number(cell) for cell in base_cells]

484

print(f" Base cell numbers: {min(base_numbers)} to {max(base_numbers)}")

485

486

# Child count analysis

487

print(f"\nHierarchy analysis (Resolution 0 -> 1):")

488

hex_child_counts = []

489

pent_child_counts = []

490

491

for cell in base_cells[:10]: # Sample first 10 base cells

492

children = h3.cell_to_children(cell, res=1)

493

child_count = len(children)

494

495

if h3.is_pentagon(cell):

496

pent_child_counts.append(child_count)

497

else:

498

hex_child_counts.append(child_count)

499

500

if hex_child_counts:

501

print(f" Hexagon children: {hex_child_counts[0]} (sample)")

502

if pent_child_counts:

503

print(f" Pentagon children: {pent_child_counts[0]} (sample)")

504

505

# Face coverage analysis

506

print(f"\nIcosahedron face coverage:")

507

face_cells = {}

508

509

for face_num in range(20):

510

# Find base cells that intersect this face

511

face_base_cells = []

512

for cell in base_cells:

513

faces = h3.get_icosahedron_faces(cell)

514

if face_num in faces:

515

face_base_cells.append(cell)

516

517

face_cells[face_num] = len(face_base_cells)

518

519

face_counts = list(face_cells.values())

520

print(f" Cells per face - min: {min(face_counts)}, max: {max(face_counts)}, avg: {sum(face_counts)/len(face_counts):.1f}")

521

522

# System capacity

523

print(f"\nSystem capacity:")

524

for res in [0, 5, 10, 15]:

525

total_cells = h3.get_num_cells(res)

526

pentagons = 12 # Always 12 pentagons

527

hexagons = total_cells - pentagons

528

529

print(f" Resolution {res:2d}: {total_cells:15,} total ({hexagons:15,} hex + {pentagons:2,} pent)")

530

531

print(f"\nMaximum theoretical capacity: {h3.get_num_cells(15):,} cells at resolution 15")

532

```