Skip to content

@studnicky/geo-layer-state

Geohash-indexed state/province lookup: resolves a WGS-84 coordinate to its containing admin-1 region name via a bit-packed cell table with adaptive-depth boundary overrides.

This package resolves a (lat, lon) coordinate to the name of its containing Natural Earth admin-1 region (state, province, etc.), or null outside every mapped feature. Cell classification, adaptive-depth override descent, and artifact encoding are delegated to @studnicky/geo-boundary-layer-kit; this package supplies only the admin-1-specific NamedFeatureResolver oracle (properties.name extraction from Natural Earth GeoJSON) that the kit builds and looks up against.

Install

bash
pnpm add @studnicky/geo-layer-state

Requires @studnicky:registry=https://npm.pkg.github.com in .npmrc.

Lookup against the bundled fixture

StateLookup.default() loads a bundled synthetic fixture artifact for development and testing:

ts
import { StateLookup } from '../src/index.js';

function demonstrateLookupDefault(): { 'alpha': string | null; 'beta': string | null; 'outside': string | null; 'synthetic': boolean; 'warningCount': number } {
  const warnings: string[] = [];

  function collectWarning(message: string): void {
    warnings.push(message);
  }

  const lookup = StateLookup.default({ 'onPlaceholderWarning': collectWarning });

  // lookup resolves a WGS-84 coordinate to its containing state/province name
  const alpha = lookup.lookup(2.5, 2.5);
  const beta = lookup.lookup(2.5, 7.5);
  console.log('point inside Alpha:', alpha);
  console.log('point inside Beta:', beta);

  // a point outside every feature resolves to null
  const outside = lookup.lookup(-70, -70);
  console.log('point outside every feature:', outside);

  // the bundled default artifact is a synthetic fixture, so default() warns once
  console.log('placeholder warning:', warnings[0]);

  // .metadata exposes the artifact's provenance
  console.log('metadata.synthetic:', lookup.metadata.synthetic);

  return { 'alpha': alpha, 'beta': beta, 'outside': outside, 'synthetic': lookup.metadata.synthetic, 'warningCount': warnings.length };
}

Building from a FeatureCollection

StateBuilder.build() builds a real artifact from a Natural Earth admin-1 FeatureCollection, then BoundaryLayerLookup.fromArtifact() loads it for lookups:

ts
import { BoundaryLayerLookup, StateBuilder } from '../src/index.js';

async function demonstrateBuildAndLookup(): Promise<{ 'doverland': string | null; 'mixedCellCount': number; 'ricoland': string | null }> {
  // a tiny 2-state admin-1 FeatureCollection, standing in for a real Natural Earth fetch
  const featureCollection: FeatureCollection = {
    'features': [
      { 'geometry': { 'coordinates': [[[0, 0], [5, 0], [5, 5], [0, 5], [0, 0]]], 'type': 'Polygon' }, 'properties': { 'name': 'Ricoland' }, 'type': 'Feature' },
      { 'geometry': { 'coordinates': [[[5, 0], [10, 0], [10, 5], [5, 5], [5, 0]]], 'type': 'Polygon' }, 'properties': { 'name': 'Doverland' }, 'type': 'Feature' }
    ],
    'type': 'FeatureCollection'
  };
  const fakeFetch: typeof fetch = () => {
    const response = new Response(JSON.stringify(featureCollection), { 'status': 200 });
    return Promise.resolve(response);
  };

  // StateBuilder.build fetches admin-1 via the injected adapter and encodes a cell table + override tree
  const adapter = NaturalEarthAdapter.create(fakeFetch);
  const result = await StateBuilder.build({ 'adapter': adapter, 'maxDescentDepth': 2 });
  console.log('mixed cell count:', result.mixedCellCount);

  // BoundaryLayerLookup.fromArtifact decodes the built artifact for lookups, without the placeholder-warning check StateLookup.default performs
  const lookup = BoundaryLayerLookup.fromArtifact(result.artifact);
  const ricoland = lookup.lookup(2.5, 2.5);
  const doverland = lookup.lookup(2.5, 7.5);
  console.log('point inside Ricoland:', ricoland);
  console.log('point inside Doverland:', doverland);

  return { 'doverland': doverland, 'mixedCellCount': result.mixedCellCount, 'ricoland': ricoland };
}

Source on GitHub