Skip to content

@studnicky/geo-data-builder

Builds the binary geohash lookup artifacts (geohash4.bin, overrides.bin, tuples.json) consumed by @studnicky/geo-resolver.

Walks every geohash-4 base cell on Earth, resolves each one's country/timezone (and, where configured, water-body name) via a pluggable oracle and sampling strategy, and interns the results into compact binary/JSON artifacts. Mixed cells — ones straddling a border or coastline — are either resolved with a single fixed-depth sample or recursively subdivided down to maxDescentDepth additional geohash characters, depending on the options passed to the build.

Install

bash
pnpm add @studnicky/geo-data-builder

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

Corner-grid sampling

CornerGridSampler samples four inset corners plus an interior grid per cell, with a default and a custom-density configuration:

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

function demonstrateCornerGridSampling(): { 'allWithinBox': boolean; 'defaultPointCount': number; 'sparsePointCount': number } {
  const boundingBox = { 'maxLat': 10, 'maxLon': 20, 'minLat': 0, 'minLon': 0 };

  // create() with no options uses the default 4-corner + 3x3 interior grid
  const defaultSampler = CornerGridSampler.create();
  const defaultPoints = defaultSampler.samplePoints(boundingBox);
  console.log('default sampler point count:', defaultPoints.length);

  // create() with options trades sample density for build time/accuracy
  const sparseSampler = CornerGridSampler.create({ 'interiorGridSize': 1 });
  const sparsePoints = sparseSampler.samplePoints(boundingBox);
  console.log('sparse sampler point count:', sparsePoints.length);

  // every sampled point stays within the requested bounding box
  const allWithinBox = defaultPoints.every((point) => {
    return point.latitude >= boundingBox.minLat && point.latitude <= boundingBox.maxLat
      && point.longitude >= boundingBox.minLon && point.longitude <= boundingBox.maxLon;
  });
  console.log('all default points within bounding box:', allWithinBox);

  return { 'allWithinBox': allWithinBox, 'defaultPointCount': defaultPoints.length, 'sparsePointCount': sparsePoints.length };
}

Fluent sampler builder

CornerGridSamplerBuilder constructs a sampler through a fluent API, trading sample density for build time/accuracy:

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

function demonstrateCornerGridSamplerBuilder(): { 'firstCornerLatitude': number | null; 'pointCount': number } {
  const boundingBox = { 'maxLat': 10, 'maxLon': 20, 'minLat': 0, 'minLon': 0 };

  // build a sampler with a tighter corner inset and a larger interior grid
  const sampler = CornerGridSamplerBuilder.create()
    .withCornerInset(0.02)
    .withInteriorGridSize(4)
    .build();

  const points = sampler.samplePoints(boundingBox);
  const firstPoint = points[0];
  console.log('builder sampler point count:', points.length);
  console.log('first corner:', firstPoint);

  return { 'firstCornerLatitude': firstPoint?.latitude ?? null, 'pointCount': points.length };
}

Source on GitHub