=============== LIBRARY RULES =============== From library maintainers: - geohash-kit uses [lng, lat] coordinate order (GeoJSON standard), not [lat, lng]. - All functions are tree-shakeable ESM exports — import only what you need. - Use coverPolygon() for area-based Nostr relay queries with g-tags. ### Setup the development environment Source: https://github.com/forgesworn/geohash-kit/blob/main/CONTRIBUTING.md Clone the repository and install dependencies to begin development. ```bash git clone https://github.com/forgesworn/geohash-kit.git cd geohash-kit npm install ``` -------------------------------- ### Benchmark Output Example Source: https://github.com/forgesworn/geohash-kit/blob/main/docs/BENCHMARKS.md Example of a raw benchmark output line showing precision, cell count, and timing metrics. ```text · precision 5–7, maxCells 200 1,035.26 0.8585 1.9708 0.9659 1.0163 1.3699 1.5299 1.9708 ±1.06% 518 ``` -------------------------------- ### Install geohash-kit Source: https://github.com/forgesworn/geohash-kit/blob/main/README.md Install the geohash-kit package using npm. ```bash npm install geohash-kit ``` -------------------------------- ### Publishing Nostr Events with Geohashes Source: https://github.com/forgesworn/geohash-kit/blob/main/README.md Example of how to encode a location, generate a Nostr tag ladder, and add it to an event for publishing. ```typescript import { encode } from 'geohash-kit/core' import { createGTagLadder } from 'geohash-kit/nostr' const hash = encode(51.5074, -0.1278, 6) const tags = createGTagLadder(hash) // Add to your event: [['g','g'], ['g','gc'], ..., ['g','gcpvjb']] ``` -------------------------------- ### Subscribe to Nearby Events on Nostr Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Example of creating a Nostr REQ filter to subscribe to events in a nearby area. It uses `createGTagFilter` to generate the necessary '#g' tag filter. ```typescript import { createGTagFilter } from 'geohash-kit' const filter = createGTagFilter(51.5074, -0.1278, 5000) // Use in Nostr REQ: ['REQ', subId, { kinds: [1], ...filter }] ``` -------------------------------- ### Publish Nostr Event with Location Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Example of publishing a Nostr event with location data. It first encodes coordinates to a geohash and then generates a g-tag ladder for inclusion in the event tags. ```typescript import { encode, createGTagLadder } from 'geohash-kit' const geohash = encode(51.5074, -0.1278, 6) // 'gcpvjb' const tags = createGTagLadder(geohash) // Add tags to your Nostr event: // [['g','g'], ['g','gc'], ['g','gcp'], ['g','gcpv'], ['g','gcpvj'], ['g','gcpvjb']] ``` -------------------------------- ### Get geohash children Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Generate the 32 geohash strings for the children of a given geohash at the next precision level. ```typescript children(hash: string): string[] children('g') // 'g0', 'g1', ..., 'gz' (32 entries) children('') // '0', '1', ..., 'z' (32 top-level cells) ``` -------------------------------- ### Run Benchmarks Source: https://github.com/forgesworn/geohash-kit/blob/main/docs/BENCHMARKS.md Commands to execute performance benchmarks using Vitest. ```bash npm run bench ``` ```bash npx vitest bench src/core.bench.ts ``` ```bash npx vitest bench --reporter=verbose src/core.bench.ts -t "encode" ``` ```bash npx vitest bench -t "polygonToGeohashes" ``` -------------------------------- ### precisionToRadius Source: https://context7.com/forgesworn/geohash-kit/llms.txt Gets the approximate cell radius in meters for a given geohash precision level. ```APIDOC ## precisionToRadius(precision) ### Description Get the approximate cell radius in metres for a given precision level. ### Method N/A (Function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript import { precisionToRadius } from 'geohash-kit/core' console.log(precisionToRadius(1)) // 2_500_000 (~2500 km) console.log(precisionToRadius(5)) // 2_400 (~2.4 km) console.log(precisionToRadius(7)) // 76 (~76 m) console.log(precisionToRadius(9)) // 2.4 (~2.4 m) ``` ### Response #### Success Response (200) Number: The approximate radius in meters for the given precision. #### Response Example ```json { "example": 2400 } ``` ``` -------------------------------- ### Run Multiple Benchmarks Source: https://github.com/forgesworn/geohash-kit/blob/main/docs/BENCHMARKS.md Loop command to run benchmarks multiple times for rigorous comparison. ```bash for i in {1..3}; do npm run bench; done ``` -------------------------------- ### Get all 8 geohash neighbours Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Retrieve all 8 adjacent geohash cells for a given geohash. ```typescript neighbours(hash: string): Record neighbours('gcpvj') // { n: '...', ne: '...', e: '...', se: '...', s: '...', sw: '...', w: '...', nw: '...' } ``` -------------------------------- ### Check Android Compatibility Vectors Source: https://github.com/forgesworn/geohash-kit/blob/main/README.md Command to verify compatibility vectors for Android parity implementations after building the project. ```bash npm run vectors:check ``` -------------------------------- ### CI/CD Test Commands Source: https://github.com/forgesworn/geohash-kit/blob/main/docs/BENCHMARKS.md Commands for running benchmarks and unit tests in a development or CI/CD environment. ```bash npm run bench # Run all benchmarks npm test # Run unit tests only npm run test:watch # Watch tests ``` -------------------------------- ### Run Benchmarks Source: https://github.com/forgesworn/geohash-kit/blob/main/README.md Command to execute the performance benchmarks included with the geohash-kit library. ```bash npm run bench ``` -------------------------------- ### Get Geohash Children Source: https://context7.com/forgesworn/geohash-kit/llms.txt Obtain all 32 children of a geohash at the next precision level. Top-level cells are children of an empty string. ```typescript import { children } from 'geohash-kit/core' // Get children of a cell const kids = children('g') console.log(kids.length) // 32 console.log(kids) // ['g0', 'g1', 'g2', ..., 'gz'] // Top-level cells (children of empty string) const topLevel = children('') console.log(topLevel) // ['0', '1', '2', ..., 'z'] (32 cells covering Earth) ``` -------------------------------- ### Get All 8 Adjacent Geohashes Source: https://context7.com/forgesworn/geohash-kit/llms.txt Retrieve all 8 adjacent geohash cells, returned as a directional object. Allows easy access to specific neighbours. ```typescript import { neighbours } from 'geohash-kit/core' const adj = neighbours('gcpvj') console.log(adj) // { // n: 'gcpvn', // ne: 'gcpvp', // e: 'gcpvm', // se: 'gcpvk', // s: 'gcpvh', // sw: 'gcpv5', // w: 'gcpv7', // nw: 'gcpvq' // } // Access specific neighbours console.log(`Northern neighbour: ${adj.n}`) console.log(`All neighbours: ${Object.values(adj).join(', ')}`) ``` -------------------------------- ### Run test commands Source: https://github.com/forgesworn/geohash-kit/blob/main/CONTRIBUTING.md Commands for executing the test suite in various modes. ```bash # Run all tests npm test # Run a specific test file npx vitest run src/core.test.ts # Watch mode npm run test:watch ``` -------------------------------- ### Get Geohash Cell Bounds Source: https://context7.com/forgesworn/geohash-kit/llms.txt Retrieve the bounding rectangle (min/max latitude and longitude) of a geohash cell. An empty string returns world bounds. ```typescript import { bounds } from 'geohash-kit/core' const rect = bounds('gcpvj') console.log(rect) // { // minLat: 51.48773193359375, // maxLat: 51.53167724609375, // minLon: -0.1483154296875, // maxLon: -0.10437011718750001 // } // Empty string returns world bounds const world = bounds('') console.log(world) // { minLat: -90, maxLat: 90, minLon: -180, maxLon: 180 } ``` -------------------------------- ### Project directory structure Source: https://github.com/forgesworn/geohash-kit/blob/main/CONTRIBUTING.md Overview of the source code organization. ```text src/ core.ts — encode, decode, bounds, neighbours, distance coverage.ts — polygon coverage, GeoJSON, convex hull, deduplication nostr.ts — Nostr g-tag ladders, REQ filters, ring expansion index.ts — barrel re-export ``` -------------------------------- ### Get Single Adjacent Geohash Source: https://context7.com/forgesworn/geohash-kit/llms.txt Retrieve a single adjacent geohash cell in a specified direction (n, ne, e, se, s, sw, w, nw). ```typescript import { neighbour } from 'geohash-kit/core' const north = neighbour('gcpvj', 'n') const northeast = neighbour('gcpvj', 'ne') const south = neighbour('gcpvj', 's') console.log(`North of gcpvj: ${north}`) console.log(`Northeast of gcpvj: ${northeast}`) console.log(`South of gcpvj: ${south}`) ``` -------------------------------- ### createGTagLadder Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Generates a multi-precision g-tag ladder for Nostr event publishing. ```APIDOC ## createGTagLadder(geohash, minPrecision?) ### Description Generate multi-precision g-tag ladder for Nostr event publishing. ### Parameters - **geohash** (string) - Required - The base geohash string. - **minPrecision** (number) - Optional - The minimum precision level to start the ladder. ### Response - **string[][]** - An array of tag arrays representing the ladder. ``` -------------------------------- ### Get single geohash neighbour Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Calculate the geohash string for an adjacent cell in a specified direction (n, ne, e, se, s, sw, w, nw). ```typescript neighbour(hash: string, direction: Direction): string neighbour('gcpvj', 'n') // north neighbour at same precision neighbour('gcpvj', 'ne') // north-east neighbour ``` -------------------------------- ### Import geohash-kit modules Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Import functions from the geohash-kit library. You can import all functions from the barrel file or specific functions from subpaths for better tree-shaking. ```typescript // Barrel (everything) import { encode, polygonToGeohashes, createGTagLadder } from 'geohash-kit' // Subpath (tree-shakeable) import { encode, decode, bounds } from 'geohash-kit/core' import { polygonToGeohashes } from 'geohash-kit/coverage' import { createGTagLadder } from 'geohash-kit/nostr' ``` -------------------------------- ### Get geohash cell bounds Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Retrieve the bounding rectangle (min/max latitude and longitude) for a given geohash cell. An empty string returns the bounds of the entire world. ```typescript bounds(hash: string): GeohashBounds bounds('gcpvj') // { minLat: 51.50, maxLat: 51.52, minLon: -0.15, maxLon: -0.10 } bounds('') // { minLat: -90, maxLat: 90, minLon: -180, maxLon: 180 } ``` -------------------------------- ### nostr.createGTagLadder(geohash, minPrecision?) Source: https://github.com/forgesworn/geohash-kit/blob/main/docs/android-compat.md Creates a list of Nostr "g" tags for a given geohash. ```APIDOC ## nostr.createGTagLadder(geohash, minPrecision?) ### Description Creates a list of Nostr "g" tags (prefixed with "g") for a given geohash, starting from a minimum precision. ### Method Not applicable (function signature) ### Endpoint Not applicable (function signature) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **geohash** (string) - Required - The geohash string. - **minPrecision** (number) - Optional - The minimum precision for the generated tags. Defaults to 1. ### Request Example ```json { "geohash": "9q8yyk8p4p", "minPrecision": 4 } ``` ### Response #### Success Response (200) - **gTagLadder** (array) - An array of strings, where each string is a Nostr "g" tag (e.g., `["g", "prefix"]`). #### Response Example ```json [ "g9q8yyk8p4p", "g9q8yyk8p4", "g9q8yyk8", "g9q8yyk", "g9q8yy", "g9q8y", "g9q8", "g9q", "g9", "g" ] ``` ### Behavioral Rules - Emits `["g", prefix]` for each precision from `max(1, minPrecision)` to `geohash.length`. - Empty geohash returns `[]`. ``` -------------------------------- ### Import Geohash Kit Functions Source: https://context7.com/forgesworn/geohash-kit/llms.txt Import functions from the main package or use tree-shakeable subpath exports for specific functionalities. ```typescript // Barrel import (everything) import { encode, decode, polygonToGeohashes, createGTagLadder } from 'geohash-kit' // Subpath imports (tree-shakeable) import { encode, decode, bounds, neighbours, distance } from 'geohash-kit/core' import { polygonToGeohashes, geohashesToGeoJSON } from 'geohash-kit/coverage' import { createGTagLadder, createGTagFilter } from 'geohash-kit/nostr' ``` -------------------------------- ### Implement Nostr location workflow Source: https://context7.com/forgesworn/geohash-kit/llms.txt Demonstrates the end-to-end process of tagging events with location ladders and querying them using geohash filters. ```typescript import { encode } from 'geohash-kit/core' import { createGTagLadder, createGTagFilter, bestGeohash, parseGTags, } from 'geohash-kit/nostr' // ===== PUBLISHER: Tag an event with location ===== const publisherLat = 51.5074 const publisherLon = -0.1278 const publisherHash = encode(publisherLat, publisherLon, 6) const eventTags = createGTagLadder(publisherHash) const event = { kind: 1, content: 'Great coffee shop in London!', tags: eventTags, // ... pubkey, sig, etc. } console.log('Publishing with tags:', eventTags) // ===== SUBSCRIBER: Query nearby events ===== const subscriberLat = 51.5080 const subscriberLon = -0.1270 const filter = createGTagFilter(subscriberLat, subscriberLon, 2000) const req = ['REQ', 'nearby-posts', { kinds: [1], ...filter, limit: 50, }] console.log('Subscribing with filter:', filter) // ===== MATCHING: Verify event matches filter ===== const tagValues = eventTags.map(t => t[1]) const filterSet = new Set(filter['#g']) const matches = tagValues.some(v => filterSet.has(v)) console.log('Event matches filter:', matches) // true // ===== RECEIVER: Parse event location ===== const receivedBestHash = bestGeohash(event.tags) const allGeoTags = parseGTags(event.tags) console.log('Event location (best):', receivedBestHash) console.log('All precision levels:', allGeoTags) ``` -------------------------------- ### Import Change: CommonJS to ESM Source: https://github.com/forgesworn/geohash-kit/blob/main/README.md Illustrates the change in import syntax when migrating from CommonJS (require) to ECMAScript Modules (import). ```typescript // Before const ngeohash = require('ngeohash') // After (ESM) import { encode, decode, bounds, neighbours } from 'geohash-kit' ``` -------------------------------- ### Get Best Geohash from Nostr Event Tags Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Returns the highest-precision g tag found in a Nostr event's tag array. Returns undefined if no g tags are present. ```typescript bestGeohash(tags: string[][]): string | undefined ``` ```typescript bestGeohash([['g', 'g'], ['g', 'gc'], ['g', 'gcpvj']]) // 'gcpvj' ``` ```typescript bestGeohash([['p', 'abc']]) // undefined ``` -------------------------------- ### Calculate Approximate Cell Radius from Precision Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Use `precisionToRadius` to get the approximate cell radius in meters for a given geohash precision level. Higher precision values result in smaller radii. ```typescript precisionToRadius(precision: number): number ``` ```typescript precisionToRadius(1) // 2_500_000 ``` ```typescript precisionToRadius(5) // 2_400 ``` ```typescript precisionToRadius(9) // 2.4 ``` -------------------------------- ### Perform Basic Geohash and Nostr Operations Source: https://github.com/forgesworn/geohash-kit/blob/main/llms.txt Demonstrates encoding coordinates, finding neighbors, covering polygons, and generating Nostr-compatible tags and filters. ```typescript import { encode, neighbours, polygonToGeohashes, createGTagLadder, createGTagFilter } from 'geohash-kit' // Encode a location const hash = encode(51.5074, -0.1278) // 'gcpvj' // Get adjacent cells const adj = neighbours(hash) // { n: '...', ne: '...', ... } // Cover a polygon with geohashes const coverage = polygonToGeohashes([[-0.15, 51.50], [-0.10, 51.50], [-0.10, 51.52], [-0.15, 51.52]]) // Generate Nostr event tags const tags = createGTagLadder(hash) // [['g','g'], ['g','gc'], ['g','gcp'], ['g','gcpv'], ['g','gcpvj']] // Generate Nostr subscription filter const filter = createGTagFilter(51.5074, -0.1278, 5000) // { '#g': ['gcpvj', 'gcpvm', ...] } ``` -------------------------------- ### Subscribing to Nostr Events by Location Source: https://github.com/forgesworn/geohash-kit/blob/main/README.md Demonstrates creating Nostr subscription filters for location-based queries, either from coordinates and radius or explicit precision and ring count. ```typescript import { createGTagFilter, nearbyFilter } from 'geohash-kit/nostr' // From coordinates + radius const filter = createGTagFilter(51.5074, -0.1278, 5000) // { '#g': ['gcpvj', ...neighbours] } // Or with explicit precision and ring count const filter2 = nearbyFilter(51.5074, -0.1278, { precision: 4, rings: 2 }) ``` -------------------------------- ### Get approximate radius from geohash precision Source: https://context7.com/forgesworn/geohash-kit/llms.txt The `precisionToRadius` function returns the approximate cell radius in meters for a given geohash precision level. This provides an estimate of the geographic area covered by a geohash at that precision. ```typescript import { precisionToRadius } from 'geohash-kit/core' console.log(precisionToRadius(1)) // 2_500_000 (~2500 km) console.log(precisionToRadius(5)) // 2_400 (~2.4 km) console.log(precisionToRadius(7)) // 76 (~76 m) console.log(precisionToRadius(9)) // 2.4 (~2.4 m) ``` -------------------------------- ### Geometric Point and Polygon Tests Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Utilities for performing geometric tests like point-in-polygon and bounds overlap. ```APIDOC ## convexHull(input) ### Description Computes the convex hull of a set of 2D points using Andrew's monotone chain algorithm. It handles edge cases like empty input, single point, two points, collinear points, and duplicates. The algorithm runs in O(n log n) time and returns hull vertices in counter-clockwise order. ### Method N/A (Function within a library) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **input** ([number, number][]) - Required - An array of points, where each point is a tuple of [x, y] coordinates. ### Request Example ```typescript convexHull([[0, 0], [4, 0], [4, 3], [0, 3], [2, 1]]) // Returns [[0, 0], [4, 0], [4, 3], [0, 3]] (interior point excluded) convexHull([[0, 0], [1, 1], [2, 2]]) // Returns [[0, 0], [2, 2]] (collinear points result in endpoints only) ``` ### Response #### Success Response (200) - **hullVertices** ([number, number][]) - An array of points representing the vertices of the convex hull in counter-clockwise order. #### Response Example ```json [ [0, 0], [4, 0], [4, 3], [0, 3] ] ``` ## pointInPolygon(point, polygon) ### Description Performs a ray-casting test to determine if a given point lies inside a polygon. ### Method N/A (Function within a library) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **point** ([number, number]) - Required - The point to test, as a [longitude, latitude] or [x, y] tuple. - **polygon** ([number, number][]) - Required - The polygon, defined as an array of [longitude, latitude] or [x, y] vertices. ### Request Example ```typescript pointInPolygon([5, 5], [[0, 0], [10, 0], [10, 10], [0, 10]]) // Returns true ``` ### Response #### Success Response (200) - **isInside** (boolean) - True if the point is inside the polygon, false otherwise. #### Response Example ```json { "isInside": true } ``` ## boundsOverlapsPolygon(bounds, polygon) ### Description Checks if the bounding box of a geohash cell overlaps with a given polygon. ### Method N/A (Function within a library) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **bounds** (GeohashBounds) - Required - The bounding box of a geohash cell. - **polygon** ([number, number][]) - Required - The polygon, defined as an array of [longitude, latitude] or [x, y] vertices. ### Request Example ```typescript boundsOverlapsPolygon(geohashBounds, polygon) ``` ### Response #### Success Response (200) - **overlaps** (boolean) - True if the bounds overlap the polygon, false otherwise. #### Response Example ```json { "overlaps": true } ``` ``` -------------------------------- ### expandRings Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Expands a geohash into concentric rings of neighbours. ```APIDOC ## expandRings(hash, rings?) ### Description Expand geohash into concentric rings of neighbours. ### Parameters - **hash** (string) - Required - The center geohash. - **rings** (number) - Optional - Number of rings to expand. ### Response - **string[][]** - An array of arrays containing geohashes for each ring. ``` -------------------------------- ### Coverage Functions Source: https://context7.com/forgesworn/geohash-kit/llms.txt Utilities for converting polygons to geohashes and vice versa, enabling location-based filtering. ```APIDOC ## polygonToGeohashes(polygon, precision) ### Description Converts a GeoJSON-like polygon to an array of geohashes that cover the polygon's area. ### Method N/A (Function) ### Endpoint N/A (Function) ### Parameters - **polygon** (object) - Required - A GeoJSON-like polygon object. Example: `{ type: 'Polygon', coordinates: [[ [lon1, lat1], [lon2, lat2], ... ]] }`. - **precision** (number) - Required - The desired precision for the geohashes. ### Request Example ```typescript import { polygonToGeohashes } from 'geohash-kit/coverage' const polygon = { type: 'Polygon', coordinates: [[[-0.12, 51.50], [-0.11, 51.50], [-0.11, 51.51], [-0.12, 51.51], [-0.12, 51.50]]] } const geohashes = polygonToGeohashes(polygon, 5) console.log(geohashes) ``` ### Response #### Success Response (200) - **geohashes** (array) - An array of geohash strings covering the polygon. #### Response Example ```json { "geohashes": ["gcpvj", "gcpvk", ...] } ``` ## geohashesToGeoJSON(geohashes) ### Description Converts an array of geohashes into a GeoJSON FeatureCollection of polygons. ### Method N/A (Function) ### Endpoint N/A (Function) ### Parameters - **geohashes** (array) - Required - An array of geohash strings. ### Request Example ```typescript import { geohashesToGeoJSON } from 'geohash-kit/coverage' const geohashes = ['gcpvj', 'gcpvk'] const geoJSON = geohashesToGeoJSON(geohashes) console.log(geoJSON) ``` ### Response #### Success Response (200) - **geoJSON** (object) - A GeoJSON FeatureCollection object representing the geohashes as polygons. #### Response Example ```json { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Polygon", "coordinates": [[[-0.1483154296875, 51.48773193359375], [-0.1043701171875, 51.48773193359375], [-0.1043701171875, 51.53167724609375], [-0.1483154296875, 51.53167724609375], [-0.1483154296875, 51.48773193359375]]] }, "properties": { "geohash": "gcpvj" } }, ... ] } ``` ``` -------------------------------- ### Nostr Location Round-trip: Publish, Subscribe, Match Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Demonstrates a full cycle of publishing a location-tagged Nostr event and subscribing to nearby events, including logic to check for matches between published tags and subscription filters. ```typescript import { encode, createGTagLadder, createGTagFilter } from 'geohash-kit' // Publisher const hash = encode(51.5074, -0.1278, 6) const eventTags = createGTagLadder(hash) // Subscriber (nearby location) const filter = createGTagFilter(51.5080, -0.1270, 2000) // Match: at least one event tag value appears in the filter const tagValues = eventTags.map(t => t[1]) const filterSet = new Set(filter['#g']) const matches = tagValues.some(v => filterSet.has(v)) // true ``` -------------------------------- ### bestGeohash Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Returns the highest-precision g tag from an event's tag array. ```APIDOC ## bestGeohash(tags) ### Description Return the highest-precision g tag from an event's tag array. ### Parameters - **tags** (string[][]) - Required - The tag array from a Nostr event. ### Response - **string | undefined** - The highest precision geohash string or undefined if none found. ``` -------------------------------- ### Polygon Coverage Operations Source: https://github.com/forgesworn/geohash-kit/blob/main/llms.txt Enables covering polygons with geohashes using adaptive subdivision and provides utilities for converting between geohashes and GeoJSON. ```APIDOC ## Polygon Coverage Operations ### Description Polygon-to-geohash coverage with adaptive threshold subdivision. ### Functions - **polygonToGeohashes**(polygon, options?) → multi-precision hash set (accepts [lon,lat][], GeoJSON Polygon, or MultiPolygon) - **geohashesToGeoJSON**(hashes) → GeoJSON FeatureCollection - **geohashesToConvexHull**(hashes) → polygon vertices - **convexHull**(points) → [x, y][] (Andrew's monotone chain, counter-clockwise winding) - **deduplicateGeohashes**(hashes, options?) → ancestor-free set ({ lossy: true } for 30/32 merges) - **pointInPolygon**(point, polygon) → boolean - **boundsOverlapsPolygon**(bounds, polygon) → boolean - **boundsFullyInsidePolygon**(bounds, polygon) → boolean ``` -------------------------------- ### Geohash Core Operations Source: https://github.com/forgesworn/geohash-kit/blob/main/llms.txt Provides basic geohash operations such as encoding, decoding, calculating bounds, finding neighbors, and measuring distances. ```APIDOC ## Geohash Core Operations ### Description Provides basic geohash operations: encode, decode, bounds, neighbours, distance. ### Functions - **encode**(lat, lon, precision?) → geohash string - **decode**(hash) → { lat, lon, error } - **bounds**(hash) → { minLat, maxLat, minLon, maxLon } - **neighbours**(hash) → { n, ne, e, se, s, sw, w, nw } - **neighbour**(hash, direction) → adjacent hash - **children**(hash) → 32 child hashes - **contains**(a, b) → boolean (prefix containment) - **matchesAny**(hash, candidates) → boolean - **distance**(hashA, hashB) → metres - **distanceFromCoords**(lat1, lon1, lat2, lon2) → metres - **midpoint**(hashA, hashB) → { lat, lon } - **midpointFromCoords**(lat1, lon1, lat2, lon2) → { lat, lon } - **midpointFromCoordsMulti**(points) → { lat, lon } (spherical vector mean) - **radiusToPrecision**(metres) → precision level (1-9) - **precisionToRadius**(precision) → metres ``` -------------------------------- ### core.encode(lat, lon, precision?) Source: https://github.com/forgesworn/geohash-kit/blob/main/docs/android-compat.md Encodes latitude and longitude into a geohash string. ```APIDOC ## core.encode(lat, lon, precision?) ### Description Encodes latitude and longitude into a geohash string with an optional precision. ### Method Not applicable (function signature) ### Endpoint Not applicable (function signature) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **lat** (number) - Required - Latitude must be finite and in `[-90, 90]`. - **lon** (number) - Required - Longitude must be finite and in `[-180, 180]`. - **precision** (number) - Optional - Precision must be finite, rounded to nearest integer, min `1`, max `12`. ### Request Example ```json { "lat": 37.7749, "lon": -122.4194, "precision": 10 } ``` ### Response #### Success Response (200) - **geohash** (string) - The resulting geohash string. #### Response Example ```json { "geohash": "9q8yyk8p4p" } ``` ### Error Handling - Invalid input throws `RangeError`. ``` -------------------------------- ### Polygon Coverage API Source: https://github.com/forgesworn/geohash-kit/blob/main/README.md Tools for converting polygons into geohash sets and performing spatial overlap tests. ```APIDOC ## Polygon Coverage ### Description Functions to convert polygons into geohash sets and perform spatial analysis. ### Functions - **polygonToGeohashes(polygon, options?)**: Adaptive threshold polygon coverage; accepts [lon, lat][], GeoJSON Polygon, or MultiPolygon - **geohashesToGeoJSON(hashes)**: GeoJSON FeatureCollection for map rendering - **geohashesToConvexHull(hashes)**: Convex hull reconstruction - **deduplicateGeohashes(hashes, options?)**: Remove redundant ancestors; { lossy: true } merges ≥30/32 siblings - **pointInPolygon(point, polygon)**: Ray-casting point-in-polygon test - **boundsOverlapsPolygon(bounds, polygon)**: Bounds–polygon overlap test - **boundsFullyInsidePolygon(bounds, polygon)**: Bounds fully inside polygon test ### CoverageOptions - **minPrecision** (number) - Optional - **maxPrecision** (number) - Optional - **maxCells** (number) - Optional - **mergeThreshold** (number) - Optional ``` -------------------------------- ### Nostr g-tag Utilities Source: https://github.com/forgesworn/geohash-kit/blob/main/llms.txt Provides Nostr-specific utilities for creating g-tag filters for event publishing and relay subscriptions. ```APIDOC ## Nostr g-tag Utilities ### Description Nostr-specific g-tag utilities for event publishing and relay subscription. ### Functions - **createGTagLadder**(geohash, minPrecision?) → string[][] (event tags) - **createGTagFilter**(lat, lon, radiusMetres) → { "#g": string[] } - **createGTagFilterFromGeohashes**(hashes) → { "#g": string[] } - **expandRings**(hash, rings?) → string[][] (concentric neighbour rings) - **nearbyFilter**(lat, lon, options?) → { "#g": string[] } - **parseGTags**(tags) → { geohash, precision }[] - **bestGeohash**(tags) → string | undefined ``` -------------------------------- ### Reconstruct Convex Polygon from Geohash Set Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Use `geohashesToConvexHull` to reconstruct a convex polygon from a set of geohashes using Andrew's monotone chain algorithm. The output is an array of [lon, lat] vertices. ```typescript geohashesToConvexHull(hashes: string[]): [number, number][] ``` ```typescript const hull = geohashesToConvexHull(['gcpvj', 'gcpvm', 'gcpvn']) // [[lon, lat], [lon, lat], ...] — convex hull vertices ``` -------------------------------- ### Nostr Integration API Source: https://github.com/forgesworn/geohash-kit/blob/main/README.md Utilities for creating Nostr REQ filters and managing g-tags. ```APIDOC ## Nostr Utilities ### Description Functions for integrating geohashes with the Nostr protocol, specifically for location-based event filtering. ### Functions - **createGTagLadder(geohash, minPrecision?)**: Multi-precision g-tag ladder - **createGTagFilter(lat, lon, radiusMetres)**: REQ filter from coordinates - **createGTagFilterFromGeohashes(hashes)**: REQ filter from hash set - **expandRings(hash, rings?)**: Concentric neighbour rings - **nearbyFilter(lat, lon, options?)**: Encode + expand + filter - **parseGTags(tags)**: Extract g tags from event - **bestGeohash(tags)**: Highest-precision g tag ``` -------------------------------- ### Compute Convex Hull from Points Source: https://context7.com/forgesworn/geohash-kit/llms.txt Calculates the convex hull for arbitrary [x, y] points, returning vertices in counter-clockwise order. ```typescript import { convexHull } from 'geohash-kit/coverage' const points: [number, number][] = [ [0, 0], [4, 0], [4, 3], [0, 3], [2, 1] // interior point ] const hull = convexHull(points) console.log(hull) // [[0, 0], [4, 0], [4, 3], [0, 3]] - interior excluded // Handles collinear points const collinear = convexHull([[0, 0], [1, 1], [2, 2]]) console.log(collinear) // [[0, 0], [2, 2]] - endpoints only ``` -------------------------------- ### Geohash Precision and Radius Conversion Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Utilities for converting between geographic radius in meters and geohash precision levels. ```APIDOC ## radiusToPrecision(metres) ### Description Determines the optimal geohash precision level for a given search radius in meters. ### Method N/A (Function within a library) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **metres** (number) - Required - The search radius in meters. ### Request Example ```typescript radiusToPrecision(5000000) // Returns 1 radiusToPrecision(2500) // Returns 5 radiusToPrecision(80) // Returns 7 radiusToPrecision(2) // Returns 9 ``` ### Response #### Success Response (200) - **precision** (number) - The optimal geohash precision level. #### Response Example ```json { "precision": 5 } ``` ## precisionToRadius(precision) ### Description Calculates the approximate cell radius in meters for a given geohash precision level. ### Method N/A (Function within a library) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **precision** (number) - Required - The geohash precision level. ### Request Example ```typescript precisionToRadius(1) // Returns 2500000 precisionToRadius(5) // Returns 2400 precisionToRadius(9) // Returns 2.4 ``` ### Response #### Success Response (200) - **radius** (number) - The approximate cell radius in meters. #### Response Example ```json { "radius": 2400 } ``` ### Precision Table | Precision | Cell width | Cell height | Approx. radius | |-----------|-----------|-------------|----------------| | 1 | ~5,000 km | ~5,000 km | ~2,500 km | | 2 | ~1,250 km | ~625 km | ~630 km | | 3 | ~156 km | ~156 km | ~78 km | | 4 | ~39.1 km | ~19.5 km | ~20 km | | 5 | ~4.89 km | ~4.89 km | ~2.4 km | | 6 | ~1.22 km | ~0.61 km | ~610 m | | 7 | ~153 m | ~153 m | ~76 m | | 8 | ~38.2 m | ~19.1 m | ~19 m | | 9 | ~4.77 m | ~4.77 m | ~2.4 m | ``` -------------------------------- ### Check geohash against multiple candidates Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Verify if a given geohash matches any geohash in a provided array of candidates, supporting multi-precision sets. ```typescript matchesAny(hash: string, candidates: string[]): boolean matchesAny('gcvdn', ['gcpvj', 'gcvd', 'u10h']) // true (gcvd is prefix) matchesAny('gcvdn', ['gcpvj', 'u10h']) // false ``` -------------------------------- ### Geohash Encoding and Decoding Source: https://github.com/forgesworn/geohash-kit/blob/main/README.md Encode latitude and longitude to a geohash string, and decode a geohash back to coordinates. Also demonstrates retrieving neighboring geohashes and calculating distances. ```typescript import { encode, decode, neighbours, distance, } from 'geohash-kit' // Encode a location const hash = encode(51.5074, -0.1278) // 'gcpvj' // Decode back to coordinates const { lat, lon, error } = decode(hash) // Get adjacent cells const adj = neighbours(hash) // { n, ne, e, se, s, sw, w, nw } // Distance between two geohashes const d = distance('gcpvj', 'u09tu') // ~340km (London → Paris) ``` -------------------------------- ### core.decode(hash) Source: https://github.com/forgesworn/geohash-kit/blob/main/docs/android-compat.md Decodes a geohash string into its center point and error. ```APIDOC ## core.decode(hash) ### Description Decodes a geohash string into its center point coordinates and the associated error. ### Method Not applicable (function signature) ### Endpoint Not applicable (function signature) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **hash** (string) - Required - The geohash string to decode. ### Request Example ```json { "hash": "9q8yyk8p4p" } ``` ### Response #### Success Response (200) - **lat** (number) - The latitude of the center point. - **lon** (number) - The longitude of the center point. - **error** (object) - An object containing the latitude and longitude error. - **lat** (number) - The latitude error. - **lon** (number) - The longitude error. #### Response Example ```json { "lat": 37.7749, "lon": -122.4194, "error": { "lat": 0.00002288818359375, "lon": 0.0000457763671875 } } ``` ### Error Handling - Empty hash throws `TypeError`. - Non-base32 characters throw `TypeError`. ``` -------------------------------- ### Compute Convex Hull from Geohashes Source: https://context7.com/forgesworn/geohash-kit/llms.txt Generates a convex hull polygon from a set of geohashes using Andrew's monotone chain algorithm. ```typescript import { polygonToGeohashes, geohashesToConvexHull } from 'geohash-kit/coverage' const polygon: [number, number][] = [ [-0.15, 51.50], [-0.10, 51.50], [-0.10, 51.52], [-0.15, 51.52], ] const hashes = polygonToGeohashes(polygon) const hull = geohashesToConvexHull(hashes) console.log(hull) // [[lon, lat], [lon, lat], ...] vertices in counter-clockwise order ``` -------------------------------- ### nearbyFilter Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Convenience method to encode, expand rings, and flatten to a filter. ```APIDOC ## nearbyFilter(lat, lon, options?) ### Description Convenience: encode + expand rings + flatten to filter. ### Parameters - **lat** (number) - Required - Latitude. - **lon** (number) - Required - Longitude. - **options** ({ precision?: number; rings?: number }) - Optional - Configuration for precision and ring expansion. ### Response - **{ '#g': string[] }** - A filter object containing the geohash tags. ``` -------------------------------- ### Create Nostr G-Tag Filter from Coordinates Source: https://context7.com/forgesworn/geohash-kit/llms.txt Generates a #g filter for Nostr subscriptions based on a center point and search radius. ```typescript import { createGTagFilter } from 'geohash-kit/nostr' // Search within 5km of London const filter = createGTagFilter(51.5074, -0.1278, 5000) console.log(filter) // { '#g': ['gcpvj', 'gcpvm', 'gcpvn', 'gcpvp', 'gcpvk', 'gcpvh', 'gcpv5', 'gcpv7', 'gcpvq'] } // Use in Nostr REQ subscription const req = ['REQ', 'sub-id', { kinds: [1], ...filter, limit: 100, }] console.log(JSON.stringify(req)) ``` -------------------------------- ### convexHull Source: https://context7.com/forgesworn/geohash-kit/llms.txt Computes the convex hull of arbitrary [x, y] points. ```APIDOC ## convexHull(points) ### Description Compute the convex hull of arbitrary [x, y] points. Returns vertices in counter-clockwise winding order. ### Parameters #### Request Body - **points** (Array<[number, number]>) - Required - The input points. ### Response - **hull** (Array<[number, number]>) - Vertices of the convex hull. ``` -------------------------------- ### Generate Nostr G-Tag Ladder Source: https://context7.com/forgesworn/geohash-kit/llms.txt Creates a multi-precision ladder of g-tags for Nostr events to improve discoverability across different zoom levels. ```typescript import { encode } from 'geohash-kit/core' import { createGTagLadder } from 'geohash-kit/nostr' const hash = encode(51.5074, -0.1278, 6) const tags = createGTagLadder(hash) console.log(tags) // [ // ['g', 'g'], // ['g', 'gc'], // ['g', 'gcp'], // ['g', 'gcpv'], // ['g', 'gcpvj'], // ['g', 'gcpvjb'] // ] // Start from precision 3 (skip top levels) const shortLadder = createGTagLadder(hash, 3) console.log(shortLadder) // [['g', 'gcp'], ['g', 'gcpv'], ['g', 'gcpvj'], ['g', 'gcpvjb']] // Add to Nostr event const event = { kind: 1, content: 'Hello from London!', tags: [ ...tags, // other tags... ], } ``` -------------------------------- ### Nostr Subscription Filter Creation Source: https://github.com/forgesworn/geohash-kit/blob/main/README.md Create a Nostr subscription filter for querying events within a certain radius of a given coordinate. This uses geohash proximity matching. ```typescript import { createGTagFilter } from 'geohash-kit/nostr' const filter = createGTagFilter(51.5074, -0.1278, 5000) // { '#g': ['gcpvj', 'gcpvm', ...] } ``` -------------------------------- ### createGTagFilter Source: https://github.com/forgesworn/geohash-kit/blob/main/llms-full.txt Generates a #g filter for Nostr REQ from coordinates and radius. ```APIDOC ## createGTagFilter(lat, lon, radiusMetres) ### Description Generate a #g filter for Nostr REQ from coordinates and radius. Encodes location, selects precision from radius, and expands to neighbours. ### Parameters - **lat** (number) - Required - Latitude. - **lon** (number) - Required - Longitude. - **radiusMetres** (number) - Required - Search radius in meters. ### Response - **{ '#g': string[] }** - A filter object containing the geohash tags. ```