A high-performance DuckDB extension that provides functions for the A5 global geospatial index - a millimeter-accurate, equal-area indexing system for geospatial data.
A5 is an innovative geospatial index that partitions the world into pentagonal cells based on a geodesic grid. Key features include:
- π Global Coverage: Seamless indexing from global to millimeter scales
- π Equal Area: All cells at the same resolution level have identical area (OGC compliant)
- π 31 Resolution Levels: From world-spanning cells to sub-30mmΒ² precision
- β‘ Fast Spatial Operations: Optimized for aggregation, filtering, and spatial joins
Group point data spatially to understand distributions:
-- Analyze restaurant density by A5 cells
SELECT a5_lonlat_to_cell(longitude, latitude, 15) as cell_id, COUNT(*) as restaurant_count
FROM restaurants
GROUP BY cell_id
ORDER BY restaurant_count DESC;
The a5
extension is available as a DuckDB Community Extension:
INSTALL a5 FROM community;
LOAD a5;
-- Get the A5 cell for a specific location (latitude, longitude, resolution)
SELECT a5_lonlat_to_cell(-74.0060, 40.7128, 15) as nyc_cell; -- Times Square
βββββββββββββββββββββββ
β nyc_cell β
β uint64 β
βββββββββββββββββββββββ€
β 2742821848331845632 β
βββββββββββββββββββββββ
-- Find the area of that cell in square meters
SELECT a5_cell_area(15) as cell_area_m2;
βββββββββββββββββββββ
β cell_area_m2 β
β double β
βββββββββββββββββββββ€
β 31669.04205949599 β
βββββββββββββββββββββ
-- Get the center coordinates of a cell
SELECT a5_cell_to_lonlat(a5_lonlat_to_cell(-74.0060, 40.7128, 15)) as center_coords;
βββββββββββββββββββββββββββββββββββββββββββ
β center_coords β
β double[2] β
βββββββββββββββββββββββββββββββββββββββββββ€
β [-74.00764805615836, 40.71280225138428] β
βββββββββββββββββββββββββββββββββββββββββββ
-- Find parent cell at lower resolution
SELECT a5_cell_to_parent(a5_lonlat_to_cell(-74.0060, 40.7128, 15), 10) as parent_cell;
βββββββββββββββββββββββ
β parent_cell β
β uint64 β
βββββββββββββββββββββββ€
β 2742821365684895744 β
βββββββββββββββββββββββ
-- Get all children cells at higher resolution
SELECT a5_cell_to_children(a5_lonlat_to_cell(-74.0060, 40.7128, 10), 11) as child_cells;
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β child_cells β
β uint64[] β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β [2742820953368035328, 2742821228245942272, 2742821503123849216, 2742821778001756160] β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
To generate a GeoJSON polygon for the A5 cell above use this SQL along with DuckDB's spatial extension:
SELECT
ST_AsGeoJSON(
ST_MakePolygon(
ST_MakeLine(
list_transform(
a5_cell_to_boundary(
a5_lonlat_to_cell(-3.7037, 40.41677, 10)
),
x -> ST_Point(x[1], x[2])
)
)
)
) as g
This produces:
{
"type":"Polygon",
"coordinates":[
[
[-3.639321611065313,40.44502900567739],
[-3.6973300524360155,40.44427170464865],
[-3.7459288918337563,40.424159040292615],
[-3.70791029038422,40.394201800420205],
[-3.654438659632305,40.4080830654645],
[-3.639321611065313,40.44502900567739]
]
]
}
Visualizing that A5 cell shows:
{
"type":"Polygon",
"coordinates":[
[
[-3.639321611065313,40.44502900567739],
[-3.6973300524360155,40.44427170464865],
[-3.7459288918337563,40.424159040292615],
[-3.70791029038422,40.394201800420205],
[-3.654438659632305,40.4080830654645],
[-3.639321611065313,40.44502900567739]
]
]
}
Returns the A5 cell ID for given coordinates and resolution level.
Parameters:
latitude
(DOUBLE): Latitude in decimal degrees (-90 to 90)longitude
(DOUBLE): Longitude in decimal degrees (-180 to 180)resolution
(INTEGER): Resolution level (0-30, where 0 is coarsest)
Example:
SELECT a5_lonlat_to_cell(-0.1278, 51.5074, 12) as london_cell;
βββββββββββββββββββββββ
β london_cell β
β uint64 β
βββββββββββββββββββββββ€
β 7161033366718906368 β
βββββββββββββββββββββββ
Returns the area of an A5 cell in the specified resolution in square meters.
Example:
SELECT a5_cell_area(5) as area_m2;
ββββββββββββββββββββββ
β area_m2 β
β double β
ββββββββββββββββββββββ€
β 33207397446.578068 β
ββββββββββββββββββββββ
Returns the resolution level of an A5 cell.
Example:
SELECT a5_get_resolution(207618739568) as resolution;
ββββββββββββββ
β resolution β
β int32 β
ββββββββββββββ€
β 27 β
ββββββββββββββ
Returns the parent cell at a coarser resolution level.
Example:
SELECT a5_cell_to_parent(207618739568, 10) as parent_cell;
ββββββββββββββββββββ
β parent_cell β
β uint64 β
ββββββββββββββββββββ€
β 549755813888 β
ββββββββββββββββββββ
Returns all children cells at a finer resolution level.
Example:
SELECT unnest(a5_cell_to_children(207618739568, 28)) as child_cells;
ββββββββββββββββ
β child_cells β
β uint64 β
ββββββββββββββββ€
β 207618739528 β
β 207618739544 β
β 207618739560 β
β 207618739576 β
ββββββββββββββββ
Returns the center coordinates [longitude, latitude] of a cell.
Example:
SELECT a5_cell_to_lonlat(207618739568) as center;
βββββββββββββββββββββββββββββββββββββββββββ
β center β
β double[2] β
βββββββββββββββββββββββββββββββββββββββββββ€
β [-129.0078555564143, 52.76769886727584] β
βββββββββββββββββββββββββββββββββββββββββββ
Returns the boundary vertices of a cell as an array of [latitude, longitude] pairs.
Example:
SELECT unnest(a5_cell_to_boundary(207618739568)) as boundary_points;
βββββββββββββββββββββββββββββββββββββββββββββ
β boundary_points β
β double[2] β
βββββββββββββββββββββββββββββββββββββββββββββ€
β [-129.00785542696357, 52.767699205314614] β
β [-129.00785579342767, 52.767698942751544] β
β [-129.0078559316034, 52.76769861890205] β
β [-129.00785542684645, 52.76769862844177] β
β [-129.0078552032305, 52.767698940969176] β
β [-129.00785542696357, 52.767699205314614] β
βββββββββββββββββββββββββββββββββββββββββββββ
Returns the total number of A5 cells at a given resolution level.
Example:
SELECT a5_get_num_cells(15) as total_cells;
βββββββββββββββββββ
β total_cells β
β uint64 β
βββββββββββββββββββ€
β 16106127360 β
βββββββββββββββββββ
Returns all 12 base cells at resolution level 0.
Example:
SELECT unnest(a5_get_res0_cells()) as base_cells;
βββββββββββββββββββββββ
β base_cells β
β uint64 β
βββββββββββββββββββββββ€
β 144115188075855872 β
β 432345564227567616 β
β 720575940379279360 β
β 1008806316530991104 β
β 1297036692682702848 β
β 1585267068834414592 β
β 1873497444986126336 β
β 2161727821137838080 β
β 2449958197289549824 β
β 2738188573441261568 β
β 3026418949592973312 β
β 3314649325744685056 β
βββββββββββββββββββββββ€
β 12 rows β
βββββββββββββββββββββββ
Resolution | Cell Area (approx) | Use Case |
---|---|---|
0-5 | 42M kmΒ² - 33k kmΒ² | Continental/Country analysis |
6-10 | 8k kmΒ² - 130 kmΒ² | Regional/State analysis |
11-15 | 32 kmΒ² - 32 hectares | City/District analysis |
16-20 | 8 hectares - 124 mΒ² | Neighborhood/Building analysis |
21-25 | 31 mΒ² - 0.5 mΒ² | Room/Vehicle analysis |
26-30 | 8 cmΒ² - 0.03 mmΒ² | Precision measurements |
This project is licensed under the MIT License - see the LICENSE file for details.
- A5 Algorithm: This extension utilizes the
a5
Rust crate created by felixpalmer - A5 Specification: Based on the A5 geospatial index specification
- DuckDB Community: Built on the excellent DuckDB database system