Skip to main content

GridX Function Reference

GridX is fully lightweight as of v0.4.0: the quadbin (gbx_quadbin_*), BNG (gbx_bng_*), and custom-grid (gbx_custom_*) functions all run in both tiers LightweightHeavyweight. Each section below is marked with its tier. See Choosing an Execution Tier for the lightweight vs heavyweight comparison.

Complete reference for all GridX discrete-global-grid functions — CARTO Quadbin v0 and British National Grid (BNG).

Overview

GridX is GeoBrix's discrete-global-grid indexing package. It ships CARTO quadbin v0 for web-mercator-aligned global indexing, British National Grid (BNG) for Great Britain workloads, and custom user-defined grids — and pairs with the product's native H3 for global hex indexing.

  • Quadbin (CARTO v0) — a global zoom-indexed tile addressing scheme aligned with web-mercator slippy maps, compatible with CARTO's CDB_QuadKey IDs. Cell (z, x, y) coordinates align with the same XYZ tile grid that PMTiles / MVT readers consume — natural for slippy-map heatmaps and global analytics.
  • BNG (British National Grid) — the Ordnance Survey National Grid (OSGB36) used in Great Britain for spatial indexing and location-based services. Specialized for UK-based spatial data.
  • Custom user-defined grids — define a regional or equal-area grid and get cell math, polyfill, and tessellation on it.
Registration and import paths
  • Quadbin: databricks.labs.gbx.gridx.quadbin (Python) / com.databricks.labs.gbx.gridx.quadbin (Scala)
  • BNG: databricks.labs.gbx.gridx.bng (Python) / com.databricks.labs.gbx.gridx.bng (Scala)

Use RegisterBatch with functions=gridx.quadbin or functions=gridx.bng to register just one subpackage, or functions=all for everything.

Key Features

  • Grid Cell Operations: Create, manipulate, and query BNG grid cells
  • Area Calculations: Calculate areas of grid cells at different precisions (returns square kilometres)
  • Coordinate Conversion: Convert between grid references and coordinates
  • Spatial Indexing: Use BNG or quadbin for efficient spatial indexing
  • Multi-Resolution Support: Work with different grid resolutions (BNG: 1–6 integer indices; Quadbin: zoom 0..26)
  • K-Ring / K-Loop Neighbourhoods: Filled rings and hollow rings for both grid systems
  • Polyfill and Tessellation: Cover geometries with cells; tessellation returns per-cell clipped chip geometries
  • Custom Grids: Define your own regional or equal-area grid systems (cell math, polyfill, tessellation)

Setup

With GeoBrix already installed, register GridX in your session before running any example.

from databricks.labs.gbx.pygx import functions as gx
gx.register(spark) # registers all gbx_bng_*, gbx_quadbin_*, gbx_custom_* SQL functions

The examples on this page read from ten canonical DataFrames, one per fixture group. Each is available as a temp view for SQL examples. Point the placeholders at your own data to reproduce the examples:

View / DataFrameSchemaBacked byBacks
bng_cellscellid STRINGInline literal 'TQ3080' (1km cell, central London, EPSG:27700)BNG scalar ops: bng_aswkb, bng_aswkt, bng_cellarea, bng_centroid, bng_kring, bng_kloop
bng_cell_pairscellid1 STRING, cellid2 STRINGInline literals 'TQ3080', 'TQ3081' (adjacent cells, distance = 1)bng_distance, bng_euclideandistance
bng_pointseasting INT, northing INT, geom STRINGEasting 530000, northing 180000, WKT point (EPSG:27700)bng_pointascell, bng_eastnorthasbng
bng_polygonsgeom STRING3km × 3km BNG polygon in EPSG:27700 (London area)bng_geomkring, bng_geomkloop, bng_polyfill, bng_tessellate, and the 5 *explode generators
bng_chipschip STRUCT<cellid STRING, core BOOLEAN, chip BINARY>9 tessellation chips from the BNG polygon at resolution 3bng_cellintersection, bng_cellunion, bng_cellintersection_agg, bng_cellunion_agg
quadbin_cellscell LONGInline literal 5233961839712272383 (San Francisco, zoom 10)quadbin_aswkb, quadbin_centroid, quadbin_resolution, quadbin_kring, quadbin_cellunion
quadbin_cell_pairscell1 LONG, cell2 LONGTwo cells at (0.0, 0.0, z10) and (0.0, 0.1, z10) — distance = 1quadbin_distance
quadbin_polygonsgeom STRINGWGS84 polygon (-1,-1) → (1,1)quadbin_polyfill, quadbin_tessellate
quadbin_kring_cellscell LONG9 cells from kring(SF-z10, k=1)quadbin_cellunion_agg
custom_gridsgrid STRUCT, cell LONG, point STRINGBNG-like custom grid; cell at POINT(530000 180000), resolution 5All 7 custom_* functions

All ten views are built from inline literals in the doc-test fixture helpers (no external files or /Volumes dependency, so the examples run anywhere).

Map any GridX cell set with plot_static

vizx.plot_static renders a column of cell ids straight from a Spark DataFrame as a static, GitHub-renderable map over a basemap — and it's the one helper that covers every GridX grid: pass grid_system="quadbin", "bng", or "custom" (as well as "h3"). Each grid's native CRS is handled for you (e.g. BNG's EPSG:27700 is reprojected for the basemap), and "custom" takes the same grid spec via grid_conf=. It's the quickest way to eyeball the cells the functions below produce. See plot_static for the full parameter list.


Examples — Conventions

How to read the four tabs

Every function on this page shows one example, expressed identically across four tabs:

TabTierBadge
SQLBoth (default)
Python (light)pygx lightweight tier
Python (heavy)heavyweight tierBlue
Scalaheavyweight tierBlue

All four tabs operate on the same input fixture with the same arguments. Where a genuine tier difference exists — a diverging output schema or a behavior available only in one tier — the affected tab carries a labeled :::note. A difference without a label is a documentation error.

In each Python example, df = spark.table("<view>") or an equivalent inline spark.sql(...) call loads the canonical fixture. Each SQL example reads FROM <view> or uses an inline literal — no separate CREATE TEMP VIEW step is shown.

Output representation

The output cells in every function table follow a uniform convention so readers can compare tabs at a glance.

Cell-id strings — BNG cell-ids (e.g. 'TQ3080') and quadbin cells (e.g. 5233961839712272383) are shown in full when short.

Binary geometry ([E]WKB) — geometry returned as BINARY is elided with one token and a format annotation. Use (WKB binary) when no SRID is embedded; (EWKB binary) when an SRID is embedded (quadbin functions embed SRID 4326):

... (WKB binary)
... (EWKB binary)

WKT strings — short WKT strings are shown in full; longer strings are truncated with a type annotation:

POLYGON ((530000 180000, ...))
POLYGON (... (WKT)

Cell-id arrays — arrays of cell-ids show the first few entries followed by ... when the array is long:

['TQ2979', 'TQ2980', 'TQ2981', ..., 'TQ3181']   (9 cells)

Doubles / numeric scalars — shown as the real value (e.g. 1.0 for bng_cellarea).

Cell width — output cells are capped at approximately 60 characters. A longer value is truncated with ... and annotated with its type.

Identical-across-tier values — when all four tabs produce the same result (e.g. 'TQ3080' from bng_pointascell), each tab shows that value identically with the same annotation. Genuine tier differences are called out in a labeled :::note.

BNG domain rules

The following rules apply to all BNG functions (gbx_bng_*):

  • Coordinate system — BNG geometry inputs (points and polygons) must be in EPSG:27700 eastings/northings. WGS84 lon/lat coordinates (e.g. POINT(-0.1278 51.5074)) yield empty arrays or null results — this is the most common source of confusion.
  • Resolution — accepts integer indices ±1..±6 (1 = 100km, 2 = 10km, 3 = 1km, 4 = 100m, 5 = 10m, 6 = 1m; negative values are quadrants) or string keys from the resolution map (e.g. '1km', '100m', '10m'). Never pass metres-as-integer (e.g. 1000) — that interpretation is not supported by BNG.getResolution and raises an error.
  • bng_cellarea returns square kilometres — not square metres. A 1km cell returns 1.0.
  • Cell-id format — standard BNG grid references (e.g. 'TQ3080'). At resolution 3 (1km), the format is two letters + four digits; the resolution level is encoded in the string length.

BNG *explode generators — SQL LATERAL only

The five BNG explode generators (bng_kringexplode, bng_kloopexplode, bng_geomkringexplode, bng_geomkloopexplode, bng_tessellateexplode) are Python UDTFs in the lightweight tier — they have no Python DataFrame Column form. Calling them as Column expressions raises NotImplementedError. Use SQL LATERAL for both tiers:

SELECT t.*
FROM (SELECT 'TQ3080' AS cellid, 1 AS k) src,
LATERAL gbx_bng_kringexplode(src.cellid, src.k) t

The Python (light) tab for these functions shows the same spark.sql("... LATERAL ...") invocation.


Quadbin (CARTO v0)

LightweightHeavyweight Quadbin runs in both tiers. The lightweight tier is the pygx quadbin package — powered by the quadbin library + shapely; quadbin_distance / quadbin_polyfill cell math mirrors the heavyweight Quadbin.scala, and geometry outputs are EWKB SRID 4326 — identical gbx_quadbin_* SQL names, so it is a drop-in swap.

GeoBrix v0.4.0 adds a gridx/quadbin subpackage implementing the CARTO quadbin v0 64-bit packed (z, x, y) tile encoding used by Snowflake, dbt, Felt, and CARTO. Coordinates are EPSG:4326 lon/lat on the user-facing API; cells are encoded as web-mercator XYZ tiles internally. Resolutions range from 0 (whole world) to 26 (sub-metre).

Registration

Quadbin functions are under gridx.quadbin — independent of gridx.bng. Call functions.register(spark) once per session to install the gbx_quadbin_* SQL functions.

CARTO Quadbin v0 cells encode (z, x, y) web-mercator tile coordinates as a single BIGINT. Cell IDs are interoperable with CARTO's CDB_QuadKey and align with the slippy-map tile grid used by gbx_rst_xyzpyramid and gbx_st_asmvt_pyramid. Exact cell-set parity between the lightweight and heavyweight tiers is enforced by the cross-tier parity suite.

Resolution (zoom) range:

  • gbx_quadbin_pointascell, gbx_quadbin_resolution, gbx_quadbin_kring, gbx_quadbin_distance accept zoom 0..26.
  • gbx_quadbin_polyfill and gbx_quadbin_tessellate accept zoom 0..20.

quadbin_pointascell

LightweightHeavyweight

Convert a lon/lat coordinate (EPSG:4326) to the quadbin cell containing it at the given zoom.

Lightweight tier (pygx)

Powered by the quadbin package (numpy-vectorized encoder). Encodes WGS84 lon/lat to a quadbin cell at the given zoom; bit-identical to the heavyweight Quadbin.scala (incl. the antimeridian/pole tile clamp).

Signature: quadbin_pointascell(longitude: Column, latitude: Column, zoom: Column): Column

Returns:

  • BIGINT quadbin cell ID
SELECT gbx_quadbin_pointascell(-122.4194, 37.7749, 10) as sf_cell;
Example output
+-------------------+
|sf_cell |
+-------------------+
|5233961839712272383|
+-------------------+

quadbin_aswkb

LightweightHeavyweight

Return the quadbin cell footprint as EWKB (SRID=4326) — the four-corner polygon of the tile in lon/lat.

Lightweight tier (pygx)

Powered by the quadbin package + shapely. Cell boundary polygon as EWKB (SRID 4326).

Signature: quadbin_aswkb(cellId: Column): Column

Returns:

  • Binary EWKB polygon (SRID-tagged 4326)
SELECT gbx_quadbin_aswkb(gbx_quadbin_pointascell(-122.4194, 37.7749, 10)) AS wkb;
Example output
+--------+
|wkb |
+--------+
|[binary]|
+--------+
... (EWKB binary — quadbin cell footprint polygon, SRID 4326)

quadbin_centroid

LightweightHeavyweight

Return the quadbin cell centroid as an EWKB POINT (SRID=4326).

Lightweight tier (pygx)

Powered by the quadbin package + shapely. Cell centroid (bbox-corner mean, matching Quadbin.scala) as EWKB point (SRID 4326).

Signature: quadbin_centroid(cellId: Column): Column

Returns:

  • Binary EWKB point (SRID-tagged 4326)
SELECT gbx_quadbin_centroid(gbx_quadbin_pointascell(-122.4194, 37.7749, 10)) AS centroid;
Example output
+--------+
|centroid|
+--------+
|[binary]|
+--------+
... (EWKB binary — POINT at SF z10 cell centroid, SRID 4326)

quadbin_resolution

LightweightHeavyweight

Return the resolution (zoom) of a quadbin cell.

Lightweight tier (pygx)

Powered by the quadbin package (numpy-vectorized). Extracts the zoom level from a cell id.

Signature: quadbin_resolution(cellId: Column): Column

Returns:

  • INT zoom level (0..26)
SELECT gbx_quadbin_resolution(gbx_quadbin_pointascell(-122.4194, 37.7749, 10)) AS z;
Example output
+--+
|z |
+--+
|10|
+--+

quadbin_polyfill

LightweightHeavyweight

Polyfill a geometry's bounding box with all quadbin cells at the given zoom.

Lightweight tier (pygx)

Powered by the quadbin package + shapely. Enumerates the cells covering the geometry's bounding box at the resolution, mirroring Quadbin.scala's envelope semantics.

Signature: quadbin_polyfill(geom: Column, zoom: Column): Column

Returns:

  • ARRAY<BIGINT> of cell IDs covering the bbox
SELECT gbx_quadbin_polyfill('POLYGON((-1 -1, 1 -1, 1 1, -1 1, -1 -1))', 5) AS cells;
Example output
+--------------------------+
|cells |
+--------------------------+
|[5211790668774506495, ...]|
+--------------------------+
... (4 cells covering the WGS84 polygon at zoom 5)

quadbin_kring

LightweightHeavyweight

Return all cells within Chebyshev distance k of a quadbin cell (inclusive of the center cell).

Lightweight tier (pygx)

Powered by the quadbin package. All cells within Chebyshev distance k (inclusive).

Signature: quadbin_kring(cellId: Column, k: Column): Column

Returns:

  • ARRAY<BIGINT> of cell IDs (length (2k+1)^2)
SELECT gbx_quadbin_kring(gbx_quadbin_pointascell(-122.4194, 37.7749, 10), 1) AS kring;
Example output
+-------------------------------------+
|kring |
+-------------------------------------+
|[5233961839712272383, ..., (9 cells)]|
+-------------------------------------+
... (9 cells: SF z10 center plus 8 surrounding cells at k=1)

quadbin_tessellate

LightweightHeavyweight

Tessellate a geometry into quadbin cells. Like quadbin_polyfill but returns the per-cell geometry chip alongside the cell ID, suitable for chip-based join patterns.

Lightweight tier (pygx)

Powered by the quadbin package + shapely. Bbox polyfill then per-cell intersection with the input geometry; one STRUCT<cell, geom> per chip (EWKB, SRID 4326).

Signature: quadbin_tessellate(geom: Column, zoom: Column): Column

Returns:

  • ARRAY<STRUCT<cell: BIGINT, geom: BINARY>>
SELECT gbx_quadbin_tessellate('POLYGON((-1 -1, 1 -1, 1 1, -1 1, -1 -1))', 5) AS chips;
Example output
+----------------------------------------------+
|chips |
+----------------------------------------------+
|[{5211790668774506495, [binary]}, {5212..., ..|
+----------------------------------------------+
... (4 chips: each quadbin cell paired with its clipped geometry WKB (SRID 4326))

quadbin_cellunion

LightweightHeavyweight

Union an ARRAY<BIGINT> of quadbin cells into a single MultiPolygon EWKB.

Lightweight tier (pygx)

Powered by shapely (union_all of the cell polygons). Dissolves an ARRAY<LONG> of cells into one EWKB MultiPolygon (SRID 4326).

Signature: quadbin_cellunion(cellIds: Column): Column

Returns:

  • Binary EWKB multipolygon (SRID-tagged 4326)
SELECT gbx_quadbin_cellunion(
gbx_quadbin_kring(gbx_quadbin_pointascell(-122.4194, 37.7749, 10), 1)
) AS union_geom;
Example output
+----------+
|union_geom|
+----------+
|[binary] |
+----------+
... (EWKB binary — MultiPolygon dissolving the SF z10 kring, SRID 4326)

quadbin_cellunion_agg

LightweightHeavyweight Grouped-agg UDF

Aggregate-level union: dissolve a column of quadbin cell IDs (grouped per partition) into a single MultiPolygon EWKB. Use this instead of gbx_quadbin_cellunion when your cell IDs are spread across rows rather than already collected into an array.

Lightweight tier (pygx)

Powered by shapely. Grouped aggregate — groupBy(...).agg(gx.quadbin_cellunion_agg("cell")) dissolves a group's cell ids into one EWKB MultiPolygon (SRID 4326).

Signature: quadbin_cellunion_agg(cell: Column): Column

Returns:

  • BINARY EWKB multipolygon (SRID-tagged 4326) representing the dissolved coverage
SELECT region, gbx_quadbin_cellunion_agg(cell) AS coverage
FROM (
SELECT 'R1' AS region,
explode(gbx_quadbin_kring(gbx_quadbin_pointascell(-122.4194, 37.7749, 10), 1)) AS cell
) t
GROUP BY region;
Example output
+------+--------+
|region|coverage|
+------+--------+
|R1 |[binary]|
+------+--------+
... (BINARY EWKB — dissolved coverage of all 9 kring cells around SF z10, SRID 4326)

quadbin_distance

LightweightHeavyweight

Chebyshev (king-move) distance between two quadbin cells at the same resolution.

Lightweight tier (pygx)

Powered by the quadbin package. Chebyshev distance on tile coordinates; mirrors Quadbin.scala (errors if the two cells differ in resolution).

Signature: quadbin_distance(cellA: Column, cellB: Column): Column

Returns:

  • INT cell-step distance
SELECT gbx_quadbin_distance(
gbx_quadbin_pointascell(0.0, 0.0, 10),
gbx_quadbin_pointascell(0.0, 0.1, 10)
) AS d;
Example output
+-+
|d|
+-+
|1|
+-+

British National Grid (BNG)

LightweightHeavyweight BNG runs in both tiers. The lightweight tier is the pygx BNG package — powered by a pure-Python port of BNG.scala + shapely for geometry; identical gbx_bng_* SQL names, so it is a drop-in swap. Cell IDs are STRING references; geometry outputs are plain WKB in EPSG:27700 coordinates with no SRID (unlike quadbin's EWKB SRID 4326). Cell-id math (bng_eastnorthasbng, bng_pointascell, bng_distance, bng_kring, bng_polyfill, …) is exact-parity with the heavyweight tier; exact cell-set parity is enforced by the cross-tier parity suite.

The British National Grid is the national coordinate system for Great Britain, based on the Ordnance Survey National Grid (OSGB36). It divides Great Britain into grid squares identified by letter-based prefixes and numeric coordinates.

BNG Structure

  • Grid Squares: 100km x 100km squares identified by two letters (e.g., "TQ" for London, "NT" for Edinburgh)
  • Eastings and Northings: Numeric coordinates within each grid square (EPSG:27700)
  • Resolution Indices: Integer indices 1..6 (1=100km, 2=10km, 3=1km, 4=100m, 5=10m, 6=1m); negative indices select quadrant sub-cells. String keys (e.g. "1km", "100m") are also accepted via BNG.resolutionMap.

BNG Grid Reference Format

BNG references follow the format: [Letters][Eastings][Northings]

Examples:

  • TQ 38 80 — 1km precision (Tower of London area)
  • TQ 3800 8000 — 100m precision
  • TQ 38000 80000 — 10m precision
  • SU 12 34 — Different grid square

Precision Levels

PrecisionGrid SizeExampleUse Case
100000m100km x 100kmTQRegional analysis
10000m10km x 10kmTQ38District-level
1000m1km x 1kmTQ3080Local area analysis
100m100m x 100mTQ308808Neighborhood level
10m10m x 10mTQ30808080Building level
1m1m x 1mTQ3080080800Precise location

Major Grid Squares

Major 100km grid squares in Great Britain:

  • TQ — London area
  • SU — South Hampshire
  • NT — Edinburgh area
  • SD — Lake District
  • ST — Bristol area

Conversion Functions

Functions to convert BNG cell IDs to standard geometry formats.

bng_aswkb

LightweightHeavyweight

Convert a BNG cell ID to Well-Known Binary (WKB) format.

Lightweight tier (pygx)

Powered by a pure-Python port of BNG.scala + shapely. The cell footprint polygon as plain WKB in EPSG:27700 (no SRID).

Signature: bng_aswkb(cellId: Column): Column

Parameters:

  • cellId - BNG cell reference string

Returns:

  • Binary WKB geometry representation
SELECT gbx_bng_aswkb('TQ3080') as wkb_geom;
Example output
+--------+
|wkb_geom|
+--------+
|[binary]|
+--------+
... (WKB binary)

bng_aswkt

LightweightHeavyweight

Convert a BNG cell ID to Well-Known Text (WKT) format.

Lightweight tier (pygx)

Powered by a pure-Python port of BNG.scala + shapely. The cell footprint as WKT in EPSG:27700 coordinates.

Signature: bng_aswkt(cellId: Column): Column

Parameters:

  • cellId - BNG cell reference string

Returns:

  • String WKT geometry representation
SELECT gbx_bng_aswkt('TQ3080') as wkt_geom;
Example output
+----------------------------------------------------------+
|wkt_geom |
+----------------------------------------------------------+
|POLYGON ((531000 180000, 531000 181000, 530000 181000, ...|
+----------------------------------------------------------+
POLYGON ((531000 180000, 531000 181000, 530000 181000, 530000 180000, 531000 180000))

Core Functions

Fundamental operations on BNG cells.

bng_cellarea

LightweightHeavyweight

Calculate the area of a BNG grid cell.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala. Returns the cell area in square kilometres, matching the heavyweight tier.

Signature: bng_cellarea(cellId: Column): Column

Parameters:

  • cellId - BNG cell reference

Returns:

  • Double representing the cell area in square kilometres
SELECT gbx_bng_cellarea('TQ3080') AS area_km2;
Example output
+--------+
|area_km2|
+--------+
|1.0 |
+--------+

bng_centroid

LightweightHeavyweight

Get the centroid (center point) of a BNG cell.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely. Cell-center POINT as WKB in EPSG:27700 (no SRID).

Signature: bng_centroid(cellId: Column): Column

Parameters:

  • cellId - BNG cell reference

Returns:

  • Point geometry at cell center
SELECT gbx_bng_centroid('TQ3080') as centroid;
Example output
+--------+
|centroid|
+--------+
|[binary]|
+--------+
... (WKB binary — POINT(530500 180500) in EPSG:27700)

bng_distance

LightweightHeavyweight

Return the grid-step distance between two BNG cells.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala — Chebyshev grid-step count between two cells, exact-parity with the heavyweight tier. Returns LONG (grid steps, not metres).

Signature: bng_distance(cellid1: Column, cellid2: Column): Column

Parameters:

  • cellid1 - First BNG cell reference (STRING)
  • cellid2 - Second BNG cell reference (STRING)

Returns:

  • LONG — Chebyshev grid-step distance. Adjacent cells (sharing an edge or corner) return 1; the cell itself returns 0.
SELECT gbx_bng_distance('TQ3080', 'TQ3081') AS dist_steps;
Example output
+----------+
|dist_steps|
+----------+
|1 |
+----------+

bng_euclideandistance

LightweightHeavyweight

Return the Chebyshev grid-unit distance between two BNG cells.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala — Chebyshev distance in grid units, exact-parity with the heavyweight tier. Returns LONG (grid units, not metres).

Signature: bng_euclideandistance(cellid1: Column, cellid2: Column): Column

Parameters:

  • cellid1 - First BNG cell reference (STRING)
  • cellid2 - Second BNG cell reference (STRING)

Returns:

  • LONG — Chebyshev distance in grid units. Adjacent cells return 1; diagonal cells also return 1.
SELECT gbx_bng_euclideandistance('TQ3080', 'TQ3081') AS euclidean_dist;
Example output
+--------------+
|euclidean_dist|
+--------------+
|1 |
+--------------+

Cell Operations

Operations combining multiple BNG chip structs.

Chip-struct inputs required

bng_cellintersection and bng_cellunion take STRUCT<cellid STRING, core BOOLEAN, chip BINARY> chip inputs — the same struct produced by bng_tessellate / bng_tessellateexplode. Passing plain STRING cell IDs throws ClassCastException. Use bng_tessellate(geom, resolution) to produce chip inputs.

bng_cellintersection

LightweightHeavyweight

Intersect two BNG chip structs and return the dissolved intersection chip.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely. Returns the same STRUCT<cellid, core, chip> as the heavyweight tier (AGREE).

Signature: bng_cellintersection(chip1: Column, chip2: Column): Column

Parameters:

  • chip1 - First chip struct (STRUCT<cellid STRING, core BOOLEAN, chip BINARY>)
  • chip2 - Second chip struct (same schema)

Returns:

  • STRUCT<cellid STRING, core BOOLEAN, chip BINARY> — dissolved intersection chip. A fully interior chip (core=true) intersected with itself returns {cellid, true, null}.
SELECT gbx_bng_cellintersection(chip, chip) AS intersection_chip
FROM (
SELECT explode(
gbx_bng_tessellate(
'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))', 3
)
) AS chip
) t
WHERE t.chip.cellid = 'TQ3080';
Example output
+--------------------+
|intersection_chip |
+--------------------+
|{TQ3080, true, null}|
+--------------------+

bng_cellunion

LightweightHeavyweight

Union two BNG chip structs and return the dissolved union chip.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely. Returns the same STRUCT<cellid, core, chip> as the heavyweight tier (AGREE).

Signature: bng_cellunion(chip1: Column, chip2: Column): Column

Parameters:

  • chip1 - First chip struct (STRUCT<cellid STRING, core BOOLEAN, chip BINARY>)
  • chip2 - Second chip struct (same schema)

Returns:

  • STRUCT<cellid STRING, core BOOLEAN, chip BINARY> — dissolved union chip. A fully interior chip (core=true) unioned with itself returns {cellid, true, null}.
SELECT gbx_bng_cellunion(chip, chip) AS union_chip
FROM (
SELECT explode(
gbx_bng_tessellate(
'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))', 3
)
) AS chip
) t
WHERE t.chip.cellid = 'TQ3080';
Example output
+--------------------+
|union_chip |
+--------------------+
|{TQ3080, true, null}|
+--------------------+

Coordinate Conversion Functions

Convert coordinates or geometries to BNG cells.

bng_eastnorthasbng

LightweightHeavyweight

Convert easting/northing coordinates to a BNG cell reference.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala (numpy-vectorized encoder). Eastings/northings must be EPSG:27700 (e.g. 530000, 180000 for London). Bit-identical cell IDs to the heavyweight tier.

Signature: bng_eastnorthasbng(easting: Column, northing: Column, resolution: Column): Column

Parameters:

  • easting - Easting coordinate value
  • northing - Northing coordinate value
  • resolution - BNG resolution: integer index (1–6 or negative for quadrant) or string (e.g. '1km', '100m'). See resolutionMap in BNG.

Returns:

  • String BNG cell reference
-- Convert OS Grid Reference coordinates (easting, northing); resolution '1km' or integer 3
SELECT gbx_bng_eastnorthasbng(530000, 180000, '1km') as bng_cell;
Example output
+--------+
|bng_cell|
+--------+
|TQ3080 |
+--------+

bng_pointascell

LightweightHeavyweight

Convert a point geometry to a BNG grid cell. The point must be supplied as WKT or WKB (GeoBrix does not accept native Databricks geometry types).

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely. The point coordinates must be EPSG:27700 eastings/northings (e.g. POINT(530000 180000) for London), not WGS84 lon/lat. Exact-parity cell IDs with the heavyweight tier.

Signature: bng_pointascell(point: Column, resolution: Column): Column

Parameters:

  • point - Point geometry as WKT (string) or WKB (binary). Must be in EPSG:27700 eastings/northings (e.g. 'POINT(530000 180000)' for London). Do not use st_point() or other DBR native geometry functions — they return a type GeoBrix does not accept.
  • resolution - BNG resolution: integer index (e.g. 3 for 1 km) or string (e.g. '1km', '100m')

Returns:

  • String BNG cell reference
-- Point in BNG coordinates (eastings, northings); resolution '1km' for 1 km cell
SELECT gbx_bng_pointascell('POINT(530000 180000)', '1km') AS bng_cell;
Example output
+--------+
|bng_cell|
+--------+
|TQ3080 |
+--------+

K-Ring Functions

Generate neighboring cells using k-ring patterns.

bng_kring

LightweightHeavyweight

Generate a k-ring of cells around a center cell (filled disk).

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala. All cells within ring distance k (inclusive of the center). Exact cell-set parity with the heavyweight tier.

Signature: bng_kring(cellId: Column, k: Column): Column

Parameters:

  • cellId - BNG cell reference for center
  • k - Integer ring distance (0 = just center, 1 = center + neighbors, etc.)

Returns:

  • Array of BNG cell references in the k-ring
SELECT gbx_bng_kring('TQ3080', 1) AS kring;
Example output
+-----------------------------+
|kring |
+-----------------------------+
|[TQ2979, TQ2980, TQ2981, ...]|
+-----------------------------+
... (9 cells: center TQ3080 plus 8 surrounding cells at k=1)

bng_kloop

LightweightHeavyweight

Generate a k-loop of cells around a center cell (hollow ring).

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala. The cells at exactly ring distance k. Exact cell-set parity with the heavyweight tier.

Signature: bng_kloop(cellId: Column, k: Column): Column

Parameters:

  • cellId - BNG cell reference for center
  • k - Integer ring distance

Returns:

  • Array of BNG cell references at exactly distance k
SELECT gbx_bng_kloop('TQ3080', 1) AS kloop;
Example output
+-----------------------------+
|kloop |
+-----------------------------+
|[TQ2979, TQ2980, TQ2981, ...]|
+-----------------------------+
... (8 cells: hollow ring at k=1, center TQ3080 excluded)

bng_geomkring

LightweightHeavyweight

Generate a k-ring of cells around a geometry at specified resolution.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely. Polyfills the geometry then expands by ring distance k. Exact cell-set parity with the heavyweight tier.

Signature: bng_geomkring(geom: Column, resolution: Column, k: Column): Column

Parameters:

  • geom - Input geometry (any type)
  • resolution - BNG resolution: integer index (e.g. 3 for 1 km) or string (e.g. '1km', '100m')
  • k - Integer ring distance

Returns:

  • Array of BNG cell references
SELECT gbx_bng_geomkring(
'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))',
3, 1
) AS kring;
Example output
+-----------------------------+
|kring |
+-----------------------------+
|[TQ2878, TQ2879, TQ2880, ...]|
+-----------------------------+
... (25 cells: polyfill of BNG polygon expanded by k=1 ring)

bng_geomkloop

LightweightHeavyweight

Generate a k-loop of cells around a geometry at specified resolution.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely. Polyfills the geometry then returns only the cells at exactly ring distance k. Exact cell-set parity with the heavyweight tier.

Signature: bng_geomkloop(geom: Column, resolution: Column, k: Column): Column

Parameters:

  • geom - Input geometry (any type)
  • resolution - BNG resolution: integer index (e.g. 3 for 1 km) or string (e.g. '1km', '100m')
  • k - Integer ring distance

Returns:

  • Array of BNG cell references at exactly distance k
SELECT gbx_bng_geomkloop(
'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))',
3, 1
) AS kloop;
Example output
+-----------------------------+
|kloop |
+-----------------------------+
|[TQ2878, TQ2879, TQ2880, ...]|
+-----------------------------+
... (16 cells: outer ring at k=1 around the BNG polygon polyfill)

Tessellation Functions

Fill geometries with grid cells.

bng_polyfill

LightweightHeavyweight

Fill a geometry with BNG cells at specified resolution.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely. Enumerates the cells covering the geometry, mirroring the heavyweight seed-and-flood-fill. Exact cell-set parity with the heavyweight tier.

Signature: bng_polyfill(geometry: Column, resolution: Column): Column

Parameters:

  • geometry - Input geometry to fill
  • resolution - BNG resolution: integer index (e.g. 3 for 1 km) or string (e.g. '1km', '100m')

Returns:

  • Array of BNG cell IDs covering the geometry
SELECT gbx_bng_polyfill(
'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))',
3
) AS cells;
Example output
+-----------------------------+
|cells |
+-----------------------------+
|[TQ2979, TQ2980, TQ2981, ...]|
+-----------------------------+
... (9 cells covering the 3km × 3km BNG polygon at 1km resolution)

bng_tessellate

LightweightHeavyweight

Tessellate a geometry into BNG cells with their geometries.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely. Polyfill plus a per-cell core/border split, returning one STRUCT<cellid, core, chip> per cell (chip geometry as WKB in EPSG:27700, no SRID). Border chips are filtered to the input geometry type, matching the heavyweight tier.

Signature: bng_tessellate(geometry: Column, resolution: Column): Column

Parameters:

  • geometry - Input geometry to tessellate
  • resolution - BNG resolution: integer index (e.g. 3 for 1 km) or string (e.g. '1km', '100m')

Returns:

  • Array of structs containing cell ID and geometry
SELECT gbx_bng_tessellate(
'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))',
3
) AS chips;
Example output
+--------------------------------------------+
|chips |
+--------------------------------------------+
|[{TQ2979, false, [binary]}, {TQ3080, true,..|
+--------------------------------------------+
... (9 chips; TQ3080 is core (core=true, chip=null); border cells carry WKB clip geometry)

Aggregator Functions

Aggregate multiple cells into a single result.

bng_cellintersection_agg

LightweightHeavyweight Grouped-agg UDF

Aggregate intersection of multiple BNG cells.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely. A grouped aggregate — groupBy(cellid).agg(gx.bng_cellintersection_agg("chip")) intersects a group's chips (all belonging to one cell) into the dissolved chip geometry.

Lightweight and heavyweight return different types

Heavyweight gbx_bng_cellintersection_agg returns a chip STRUCT<cellid, core, chip>; the lightweight function returns BINARY (the dissolved chip geometry, WKB in EPSG:27700) in both Python and SQL. A PySpark grouped-aggregate pandas_udf cannot return a StructType, so the lightweight aggregate emits the chip geometry — the one meaningful payload of a dissolved aggregate. The aggregate only ever combines chips from a single cell, so the heavyweight struct's cellid is exactly the group key you GROUP BY, and core is recoverable from whether the chip equals the full cell — neither carries information beyond the BINARY chip. To reconstruct the heavyweight STRUCT shape in SQL, project the group key as cellid:

-- Lightweight SQL: rebuild the (cellid, chip) the heavyweight struct would carry
SELECT
group_key AS cellid,
gbx_bng_cellintersection_agg(chip) AS chip
FROM cells
GROUP BY group_key

Signature: bng_cellintersection_agg(cellId: Column): Column

Parameters:

  • cellId - BNG cell reference column to aggregate

Returns:

  • BNG cell ID representing common intersection
SELECT t.chip.cellid, gbx_bng_cellintersection_agg(t.chip) AS common_chip
FROM (
SELECT explode(gbx_bng_tessellate(
'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))', 3
)) AS chip
) t
WHERE t.chip.cellid = 'TQ3080'
GROUP BY t.chip.cellid;
Example output
# Heavyweight SQL (active tier = heavy/Scala) — STRUCT<cellid, core, chip>:
+------+--------------------+
|cellid|common_chip |
+------+--------------------+
|TQ3080|{TQ3080, true, null}|
+------+--------------------+
... (core cell TQ3080: chip=null means the full cell polygon)

# Lightweight SQL (active tier = pygx) — BINARY (dissolved chip WKB in EPSG:27700):
+------+-----------+
|cellid|common_chip|
+------+-----------+
|TQ3080|[binary] |
+------+-----------+
... (core cell TQ3080: [binary] is the WKB of the full TQ3080 polygon)

bng_cellunion_agg

LightweightHeavyweight Grouped-agg UDF

Aggregate union of multiple BNG cells.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely. A grouped aggregate — groupBy(cellid).agg(gx.bng_cellunion_agg("chip")) dissolves a group's chips (all belonging to one cell) into the unioned chip geometry.

Lightweight and heavyweight return different types

Heavyweight gbx_bng_cellunion_agg returns a chip STRUCT<cellid, core, chip>; the lightweight function returns BINARY (the dissolved chip geometry, WKB in EPSG:27700) in both Python and SQL. A PySpark grouped-aggregate pandas_udf cannot return a StructType, so the lightweight aggregate emits the chip geometry — the one meaningful payload of a dissolved aggregate. The aggregate only ever combines chips from a single cell, so the heavyweight struct's cellid is exactly the group key you GROUP BY, and core is recoverable from whether the chip equals the full cell — neither carries information beyond the BINARY chip. To reconstruct the heavyweight STRUCT shape in SQL, project the group key as cellid:

-- Lightweight SQL: rebuild the (cellid, chip) the heavyweight struct would carry
SELECT
group_key AS cellid,
gbx_bng_cellunion_agg(chip) AS chip
FROM cells
GROUP BY group_key

Signature: bng_cellunion_agg(cellId: Column): Column

Parameters:

  • cellId - BNG cell reference column to aggregate

Returns:

  • BNG cell ID representing bounding union
SELECT t.chip.cellid, gbx_bng_cellunion_agg(t.chip) AS union_chip
FROM (
SELECT explode(gbx_bng_tessellate(
'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))', 3
)) AS chip
) t
WHERE t.chip.cellid = 'TQ3080'
GROUP BY t.chip.cellid;
Example output
# Heavyweight SQL (active tier = heavy/Scala) — STRUCT<cellid, core, chip>:
+------+--------------------+
|cellid|union_chip |
+------+--------------------+
|TQ3080|{TQ3080, true, null}|
+------+--------------------+
... (core cell TQ3080: chip=null means the full cell polygon)

# Lightweight SQL (active tier = pygx) — BINARY (dissolved chip WKB in EPSG:27700):
+------+----------+
|cellid|union_chip|
+------+----------+
|TQ3080|[binary] |
+------+----------+
... (core cell TQ3080: [binary] is the WKB of the full TQ3080 polygon)

Generator Functions

Explode array results into individual rows.

bng_kringexplode

LightweightHeavyweight Streaming UDTF

Explode k-ring cells into separate rows.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala as a streaming UDTF — one output row per k-ring cell. Exact cell-set parity with the heavyweight tier.

Signature: bng_kringexplode(cellId: Column, k: Column): Column

Parameters:

  • cellId - BNG cell reference for center
  • k - Integer ring distance

Returns:

  • Exploded rows, one per cell in k-ring
SELECT t.*
FROM (SELECT 'TQ3080' AS cellid) src,
LATERAL gbx_bng_kringexplode(src.cellid, 1) t;

bng_kloopexplode

LightweightHeavyweight Streaming UDTF

Explode k-loop cells into separate rows.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala as a streaming UDTF — one output row per k-loop cell. Exact cell-set parity with the heavyweight tier.

Signature: bng_kloopexplode(cellId: Column, k: Column): Column

Parameters:

  • cellId - BNG cell reference for center
  • k - Integer ring distance

Returns:

  • Exploded rows, one per cell in k-loop
SELECT t.*
FROM (SELECT 'TQ3080' AS cellid) src,
LATERAL gbx_bng_kloopexplode(src.cellid, 1) t;

bng_geomkringexplode

LightweightHeavyweight Streaming UDTF

Explode geometry k-ring cells into separate rows.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely as a streaming UDTF — one output row per geometry k-ring cell. Exact cell-set parity with the heavyweight tier.

Signature: bng_geomkringexplode(geom: Column, resolution: Column, k: Column): Column

Parameters:

  • geom - Input geometry
  • resolution - BNG resolution: integer index (e.g. 3 for 1 km) or string (e.g. '1km', '100m')
  • k - Integer ring distance

Returns:

  • Exploded rows, one per cell
SELECT t.*
FROM (SELECT 'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))' AS geom) src,
LATERAL gbx_bng_geomkringexplode(src.geom, 3, 1) t;

bng_geomkloopexplode

LightweightHeavyweight Streaming UDTF

Explode geometry k-loop cells into separate rows.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely as a streaming UDTF — one output row per geometry k-loop cell. Exact cell-set parity with the heavyweight tier.

Signature: bng_geomkloopexplode(geom: Column, resolution: Column, k: Column): Column

Parameters:

  • geom - Input geometry
  • resolution - BNG resolution: integer index (e.g. 3 for 1 km) or string (e.g. '1km', '100m')
  • k - Integer ring distance

Returns:

  • Exploded rows, one per cell at distance k
SELECT t.*
FROM (SELECT 'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))' AS geom) src,
LATERAL gbx_bng_geomkloopexplode(src.geom, 3, 1) t;

bng_tessellateexplode

LightweightHeavyweight Streaming UDTF

Explode tessellated cells into separate rows.

Lightweight tier (pygx)

Powered by the pure-Python port of BNG.scala + shapely as a streaming UDTF — one output row per tessellated cell, each carrying the cell ID and chip geometry (WKB in EPSG:27700, no SRID).

Signature: bng_tessellateexplode(geometry: Column, resolution: Column): Column

Parameters:

  • geometry - Input geometry to tessellate
  • resolution - BNG resolution: integer index (e.g. 3 for 1 km) or string (e.g. '1km', '100m')

Returns:

  • Exploded rows with cell ID and geometry for each cell
SELECT t.*
FROM (SELECT 'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))' AS geom) src,
LATERAL gbx_bng_tessellateexplode(src.geom, 3) t;

BNG Reference Format

Standard Format

BNG references follow: [Letters][Eastings][Northings]

Common Resolutions

ResolutionGrid SizeExampleUse Case
100000m100km × 100kmTQRegional
10000m10km × 10kmTQ38District
1000m1km × 1kmTQ3080Local area
100m100m × 100mTQ308808Neighborhood
10m10m × 10mTQ30808080Building
1m1m × 1mTQ3080080800Precise location

Major Grid Squares

Major 100km grid squares in Great Britain:

  • TQ - London area
  • SU - South Hampshire
  • NT - Edinburgh area
  • SD - Lake District
  • ST - Bristol area

Custom Grid Functions

LightweightHeavyweight Custom-grid functions run in both tiers. The lightweight tier is the pygx custom-grid package — powered by a pure-Python port of the custom-grid system + shapely for geometry; identical gbx_custom_* SQL names, so it is a drop-in swap (no external grid library, unlike quadbin's quadbin package). Cell IDs are BIGINT values; geometry outputs are plain WKB with no SRID — the grid's srid is metadata only. Geometry inputs accept WKB, EWKB, WKT, or EWKT in both tiers. Cell-id math and cell sets are exact-parity with the heavyweight tier, enforced by the cross-tier parity suite. gbx_custom_grid returns the same descriptor struct in both tiers.

A custom grid is a user-defined regular rectangular grid specified by its spatial extent, root cell size, and a recursive split factor. Cell IDs are BIGINT values; hierarchy is controlled by cell_splits (each level subdivides root cells into cell_splits x cell_splits sub-cells). Use custom grids when neither BNG nor quadbin matches your coordinate reference system or cell-size requirements — for example, a national grid in EPSG:27700 with non-standard tile sizes.

custom_grid

LightweightHeavyweight

Define a user-specified regular grid from an origin, extent, cell size, split factor, and SRID.

Signature: gbx_custom_grid(boundXMin, boundXMax, boundYMin, boundYMax, cellSplits, rootCellSizeX, rootCellSizeY, srid)

Parameters:

  • boundXMin — minimum X bound of the grid extent
  • boundXMax — maximum X bound of the grid extent
  • boundYMin — minimum Y bound of the grid extent
  • boundYMax — maximum Y bound of the grid extent
  • cellSplits — number of splits per axis at each resolution level (e.g. 2 = 2x2 = 4 sub-cells per step)
  • rootCellSizeX — root cell width in CRS units
  • rootCellSizeY — root cell height in CRS units
  • srid — spatial reference ID (e.g. 27700 for BNG)

Returns:

  • STRUCT<bound_x_min, bound_x_max, bound_y_min, bound_y_max, cell_splits, root_cell_size_x, root_cell_size_y, srid> — a grid descriptor struct passed to all other gbx_custom_* functions.
SELECT gbx_custom_grid(0, 1000000, 0, 1000000, 2, 1000, 1000, 27700) AS grid;
Example output
+----------------------------------------------+
|grid |
+----------------------------------------------+
|{0, 1000000, 0, 1000000, 2, 1000, 1000, 27700}|
+----------------------------------------------+

custom_pointascell

LightweightHeavyweight

Index a point geometry into a custom grid cell ID at the specified resolution level.

Signature: gbx_custom_pointascell(point, grid, resolution)

Parameters:

  • point — point geometry as WKT (STRING) or WKB (BINARY) in the grid's CRS
  • grid — custom grid descriptor returned by gbx_custom_grid
  • resolution — resolution level (integer; 0 = root cells, higher = finer)

Returns:

  • BIGINT cell ID encoding the grid position at the given resolution
SELECT gbx_custom_pointascell('POINT(530000 180000)', gbx_custom_grid(0, 1000000, 0, 1000000, 2, 1000, 1000, 27700), 5) AS cell;
Example output
+------------------+
|cell |
+------------------+
|360287970373976640|
+------------------+

custom_cellaswkb

LightweightHeavyweight

Return the WKB footprint polygon of a custom grid cell.

Signature: gbx_custom_cellaswkb(cell, grid)

Parameters:

  • cellBIGINT cell ID
  • grid — custom grid descriptor returned by gbx_custom_grid

Returns:

  • BINARY WKB polygon representing the cell boundary (geometry ... (WKB binary))
SELECT gbx_custom_cellaswkb(360287970373976640, gbx_custom_grid(0, 1000000, 0, 1000000, 2, 1000, 1000, 27700)) AS geom;
Example output
+--------+
|geom |
+--------+
|[binary]|
+--------+
... (WKB binary — 31.25m × 31.25m custom grid cell footprint polygon)

custom_cellaswkt

LightweightHeavyweight

Return the WKT footprint polygon of a custom grid cell.

Signature: gbx_custom_cellaswkt(cell, grid)

Parameters:

  • cellBIGINT cell ID
  • grid — custom grid descriptor returned by gbx_custom_grid

Returns:

  • STRING WKT polygon representing the cell boundary
SELECT gbx_custom_cellaswkt(360287970373976640, gbx_custom_grid(0, 1000000, 0, 1000000, 2, 1000, 1000, 27700)) AS wkt;
Example output
+----------------------------------------------------------------------------------------------------+
|wkt |
+----------------------------------------------------------------------------------------------------+
|POLYGON ((530031.25 180000, 530031.25 180031.25, 530000 180031.25, 530000 180000, 530031.25 180000))|
+----------------------------------------------------------------------------------------------------+

custom_centroid

LightweightHeavyweight

Return the centroid of a custom grid cell as a WKB point.

Signature: gbx_custom_centroid(cell, grid)

Parameters:

  • cellBIGINT cell ID
  • grid — custom grid descriptor returned by gbx_custom_grid

Returns:

  • BINARY WKB point at the cell center (geometry ... (WKB binary))
SELECT gbx_custom_centroid(360287970373976640, gbx_custom_grid(0, 1000000, 0, 1000000, 2, 1000, 1000, 27700)) AS centroid;
Example output
+--------+
|centroid|
+--------+
|[binary]|
+--------+
... (WKB binary — POINT at the center of the 31.25m × 31.25m custom grid cell)

custom_polyfill

LightweightHeavyweight

Fill a geometry with all custom grid cell IDs at the specified resolution.

Signature: gbx_custom_polyfill(geom, grid, resolution)

Parameters:

  • geom — input geometry as WKT (STRING) or WKB (BINARY) in the grid's CRS
  • grid — custom grid descriptor returned by gbx_custom_grid
  • resolution — resolution level (integer; higher = finer cells)

Returns:

  • ARRAY<BIGINT> of cell IDs whose footprints intersect the geometry
SELECT gbx_custom_polyfill('POLYGON((529000 179000,529000 182000,532000 182000,532000 179000,529000 179000))', gbx_custom_grid(0, 1000000, 0, 1000000, 2, 1000, 1000, 27700), 1) AS cells;
Example output
+---------------------------------------------+
|cells |
+---------------------------------------------+
|[72057594038644994, ..., (36 cells at res=1)]|
+---------------------------------------------+
... (36 BIGINT cell IDs — 500m cells covering the 3km × 3km BNG polygon at resolution 1)

custom_kring

LightweightHeavyweight

Return all custom grid cells within k steps of a center cell (filled neighborhood, Chebyshev distance).

Signature: gbx_custom_kring(cell, grid, k)

Parameters:

  • cellBIGINT center cell ID
  • grid — custom grid descriptor returned by gbx_custom_grid
  • k — integer ring distance (0 = center only; 1 = 3x3 neighborhood including center)

Returns:

  • ARRAY<BIGINT> of cell IDs within distance k (up to (2k+1)^2 cells)
SELECT gbx_custom_kring(360287970373976640, gbx_custom_grid(0, 1000000, 0, 1000000, 2, 1000, 1000, 27700), 1) AS ring;
Example output
+-------------------------------------------+
|ring |
+-------------------------------------------+
|[360287970373976640, ..., (9 cells at k=1)]|
+-------------------------------------------+
... (9 BIGINT cell IDs — the 3×3 neighbourhood including center cell at resolution 5)

Performance Tips

1. Use Appropriate Resolution

Choose resolution based on analysis needs:

  • Coarse (10km) for regional analysis
  • Medium (1km) for local patterns
  • Fine (100m) for detailed studies

2. Leverage Aggregators

Use aggregator functions for efficient grouping:

SELECT t.chip.cellid, gbx_bng_cellunion_agg(t.chip) AS union_chip
FROM (
SELECT explode(gbx_bng_tessellate(
'POLYGON((529000 179000, 529000 182000, 532000 182000, 532000 179000, 529000 179000))', 3
)) AS chip
) t
WHERE t.chip.cellid = 'TQ3080'
GROUP BY t.chip.cellid;
Example output
# Heavyweight SQL (active tier = heavy/Scala) — STRUCT<cellid, core, chip>:
+------+--------------------+
|cellid|union_chip |
+------+--------------------+
|TQ3080|{TQ3080, true, null}|
+------+--------------------+
... (core cell TQ3080: chip=null means the full cell polygon)

# Lightweight SQL (active tier = pygx) — BINARY (dissolved chip WKB in EPSG:27700):
+------+----------+
|cellid|union_chip|
+------+----------+
|TQ3080|[binary] |
+------+----------+
... (core cell TQ3080: [binary] is the WKB of the full TQ3080 polygon)

3. Use Generators for Expansion

Generator functions (e.g. bng_kringexplode, bng_kloopexplode) are more efficient than using explode on array results. See the generator examples above.


Next Steps