package

github.com/swilk19/h3_crystal

master / published Feb 22, 2026 / repository

Crystal bindings for Uber's H3

H3 Crystal

h3

build

Crystal bindings for Uber's H3 hexagonal spatial indexing library. Wraps the H3 C library v4.4.1 via Crystal's FFI with static linking — no system-level H3 install needed.

Please consult the H3 documentation for a full explanation of terminology and concepts.

Supported H3 Versions

The semantic versioning of this shard matches the versioning of the H3 C library. E.g. version 4.4.x of this shard is targeted for version 4.4.y of H3 C lib where x and y are independent patch levels.

Installation

Before installing, ensure you have CMake and a C compiler available (see H3 build dependencies).

  1. Add the dependency to your shard.yml:

    dependencies:
      h3_crystal:
        github: swilk19/h3_crystal
  2. Run shards install

The H3 C library is compiled from bundled source during installation and statically linked.

Usage

require "h3_crystal/h3"

# Convert coordinates to an H3 cell index
index = H3.from_geo_coordinates({40.689167, -74.044444}, 8)
# => 613229551440363519

# Inspect the index
H3.valid?(index)     # => true
H3.resolution(index) # => 8
H3.pentagon?(index)  # => false

# Convert back to coordinates
H3.to_geo_coordinates(index)
# => {40.68762931583634, -74.04099997186306}

# Find neighboring hexagons
H3.k_ring(index, 1) # => [613229551440363519, ...]  (7 cells)

# Get parent/children
H3.parent(index, 7)      # => parent cell at resolution 7
H3.children(index, 9)    # => array of child cells at resolution 9

# Measure distances
H3.distance(origin, destination) # => grid distance in cells
H3.great_circle_distance_km(lat1, lng1, lat2, lng2) # => km

# Work with directed edges
H3.origin_to_directed_edges(index) # => 6 directed edge indexes
H3.exact_edge_length_km(edge)      # => edge length in km

# Fill a polygon with hexagons
polygon = [{37.813318, -122.4089866}, {37.7866302, -122.3805436},
           {37.7198061, -122.3544736}, {37.7076131, -122.5123436}]
H3.polygon_to_cells(polygon, 9) # => array of H3 indexes

All public methods are called as H3.method_name.

API Coverage

This shard covers 97% of the H3 v4 API (75 of 77 exported C functions).

Indexing

MethodH3 FunctionDescription
from_geo_coordinateslatLngToCellConvert lat/lng to H3 index
to_geo_coordinatescellToLatLngConvert H3 index to lat/lng
to_boundarycellToBoundaryGet cell boundary coordinates

Inspection

MethodH3 FunctionDescription
resolutiongetResolutionGet resolution of an index
base_cellgetBaseCellNumberGet base cell number
from_stringstringToH3Parse hex string to index
to_stringh3ToStringConvert index to hex string
valid?isValidCellCheck if cell index is valid
valid_index?isValidIndexCheck if any H3 index is valid
pentagon?isPentagonCheck if cell is a pentagon
class_3_resolution?isResClassIIICheck if Class III resolution
max_face_countmaxFaceCountMax icosahedron faces for cell
facesgetIcosahedronFacesGet icosahedron face set

Traversal

MethodH3 FunctionDescription
k_ringgridDiskAll cells within k distance
k_ring_distancesgridDiskDistancesCells grouped by distance
hex_rangegridDiskUnsafeCells within k (no pentagons)
hex_range_distancesgridDiskDistancesUnsafeGrouped by distance (no pentagons)
hex_ringgridRingUnsafeHollow ring at distance k
hex_rangesgridDisksUnsafeMulti-origin disk (no pentagons)
distancegridDistanceGrid distance between cells
linegridPathCellsPath of cells between two cells
line_sizegridPathCellsSizeNumber of cells in path
max_kring_sizemaxGridDiskSizeMax cells in a disk
max_grid_ring_sizemaxGridRingSizeMax cells in a ring

Hierarchy

MethodH3 FunctionDescription
parentcellToParentGet parent cell
childrencellToChildrenGet child cells
max_childrencellToChildrenSizeMax number of children
center_childcellToCenterChildGet center child cell
cell_to_child_poscellToChildPosPosition of child within parent
child_pos_to_cellchildPosToCellChild cell from position
compactcompactCellsCompact a cell set
uncompactuncompactCellsUncompact a cell set
max_uncompact_sizeuncompactCellsSizeMax cells after uncompaction

Directed Edges

MethodH3 FunctionDescription
are_neighbor_cellsareNeighborCellsCheck if cells are neighbors
cells_to_directed_edgecellsToDirectedEdgeGet edge between neighbors
valid_directed_edge?isValidDirectedEdgeCheck if edge is valid
directed_edge_origingetDirectedEdgeOriginGet origin cell of edge
directed_edge_destinationgetDirectedEdgeDestinationGet destination cell
directed_edge_to_cellsdirectedEdgeToCellsGet both cells of an edge
origin_to_directed_edgesoriginToDirectedEdgesAll edges from a cell
directed_edge_to_boundarydirectedEdgeToBoundaryGet edge boundary coords
exact_edge_length_radsedgeLengthRadsEdge length in radians
exact_edge_length_kmedgeLengthKmEdge length in km
exact_edge_length_medgeLengthMEdge length in metres

Vertex

MethodH3 FunctionDescription
cell_to_vertexcellToVertexGet vertex index
cell_to_vertexescellToVertexesGet all vertex indexes
vertex_to_lat_lngvertexToLatLngGet vertex coordinates
valid_vertex?isValidVertexCheck if vertex is valid

Local IJ Coordinates

MethodH3 FunctionDescription
cell_to_local_ijcellToLocalIjCell to local IJ coords
local_ij_to_celllocalIjToCellLocal IJ coords to cell

Polygon / Region

MethodH3 FunctionDescription
polygon_to_cellspolygonToCellsFill polygon with cells
max_polygon_to_cells_sizemaxPolygonToCellsSizeMax cells for polygon fill
cells_to_multi_polygoncellsToLinkedMultiPolygonCells to polygon boundaries

Measurements & Utilities

MethodH3 FunctionDescription
cell_area_rads2cellAreaRads2Exact cell area (radians)
cell_area_km2cellAreaKm2Exact cell area (km²)
cell_area_m2cellAreaM2Exact cell area (m²)
great_circle_distance_radsgreatCircleDistanceRadsDistance (radians)
great_circle_distance_kmgreatCircleDistanceKmDistance (km)
great_circle_distance_mgreatCircleDistanceMDistance (metres)
hex_area_km2getHexagonAreaAvgKm2Avg hex area at resolution
hex_area_m2getHexagonAreaAvgM2Avg hex area at resolution
edge_length_kmgetHexagonEdgeLengthAvgKmAvg edge length at resolution
edge_length_mgetHexagonEdgeLengthAvgMAvg edge length at resolution
hexagon_countgetNumCellsTotal cells at resolution
base_cellsgetRes0CellsAll 122 base cells
pentagonsgetPentagonsPentagon cells at resolution
degs_to_radsdegsToRadsDegrees to radians
rads_to_degsradsToDegsRadians to degrees
describe_h3_errordescribeH3ErrorError code description
get_index_digitgetIndexDigitDirection digit at resolution

GeoJSON Integration (Optional)

For projects that work with GeoJSON data, an optional integration with the geocrystal/geojson shard is available.

require "h3_crystal/h3/geojson"

# Fill a GeoJSON Polygon with H3 cells
polygon = GeoJSON::Polygon.new([
  [[-122.4089866, 37.813318], [-122.3805436, 37.7866302],
   [-122.3544736, 37.7198061], [-122.5123436, 37.7076131],
   [-122.4089866, 37.813318]]
])
cells = H3.polygon_to_cells(polygon, 9)

# Fill a GeoJSON MultiPolygon
multi = GeoJSON::MultiPolygon.new([polygon1, polygon2])
cells = H3.polygon_to_cells(multi, 9)

# Convert cells back to GeoJSON
multi_polygon = H3.cells_to_geojson_multi_polygon(cells)
multi_polygon.to_json # => valid GeoJSON

The geojson shard is listed as a dependency. Consumers must explicitly require "h3_crystal/h3/geojson" to activate the integration.

Development

mise install                      # Install Crystal version from .mise.toml
shards install                    # Install deps + build C library
crystal spec --verbose            # Run all tests
crystal tool format --check       # Check formatting

Contributing

  1. Fork it (https://github.com/swilk19/h3_crystal/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

Special Thanks

API