@convex-dev/geospatial
Version:
A geospatial index for Convex
103 lines • 4.25 kB
JavaScript
import { Go } from "./goRuntime.js";
import { wasmSource } from "./s2wasm.js";
// Do some work at import time to speed `vitest` up (since it reuses the same module
// across tests, unlike the Convex runtime).
const wasmBinary = atob(wasmSource);
const wasmBuffer = new Uint8Array(wasmBinary.length);
for (let i = 0; i < wasmBinary.length; i++) {
wasmBuffer[i] = wasmBinary.charCodeAt(i);
}
// See https://docs.s2cell.aliddell.com/en/stable/useful_s2_links.html for useful articles
// for working with S2.
export class S2Bindings {
exports;
go;
decoder = new TextDecoder();
constructor(exports, go) {
this.exports = exports;
this.go = go;
}
static async load() {
const go = new Go();
const { instance } = await WebAssembly.instantiate(wasmBuffer, go.importObject);
await go.run(instance);
return new S2Bindings(instance.exports, go);
}
cellIDFromPoint(point) {
return this.exports.cellIDFromLatLng(point.latitude, point.longitude);
}
cellIDToken(cellID) {
const len = this.exports.cellIDToken(cellID);
if (len < 0) {
throw new Error(`Failed to get cell ID token`);
}
const ptr = this.exports.tokenBufferPtr();
const wasmMemory = new Uint8Array(this.exports.memory.buffer);
const buffer = wasmMemory.slice(ptr + 0, ptr + len);
return this.decoder.decode(buffer.buffer);
}
cellIDParent(cellID, level) {
return this.exports.cellIDParent(cellID, level);
}
cellIDLevel(cellID) {
return this.exports.cellIDLevel(cellID);
}
coverRectangle(rectangle, minLevel, maxLevel, levelMod, maxCells) {
const len = this.exports.coverRectangle(rectangle.south, rectangle.west, rectangle.north, rectangle.east, minLevel, maxLevel, levelMod, maxCells);
if (len < 0) {
throw new Error(`Failed to coverRectangle`);
}
const ptr = this.exports.coverRectangleBufferPtr();
const wasmMemory = new Uint8Array(this.exports.memory.buffer);
const buffer = wasmMemory.slice(ptr + 0, ptr + len * 8);
const uint64s = new BigUint64Array(buffer.buffer);
return [...uint64s];
}
rectangleContains(rectangle, point) {
return this.exports.rectangleContains(rectangle.south, rectangle.west, rectangle.north, rectangle.east, point.latitude, point.longitude);
}
cellVertexes(cellID) {
const result = [];
for (let k = 0; k < 4; k++) {
const latitude = this.exports.cellVertexLatDegrees(cellID, k);
const longitude = this.exports.cellVertexLngDegrees(cellID, k);
result.push({ latitude, longitude });
}
return result;
}
metersToChordAngle(meters) {
return this.exports.metersToChordAngle(meters);
}
chordAngleToMeters(chordAngle) {
return this.exports.chordAngleToMeters(chordAngle);
}
pointDistance(point1, point2) {
return this.exports.pointDistance(point1.latitude, point1.longitude, point2.latitude, point2.longitude);
}
initialCells(minLevel) {
const len = this.exports.initialCells(minLevel);
if (len < 0) {
throw new Error(`Failed to get initial cells`);
}
const ptr = this.exports.cellsBufferPtr();
const wasmMemory = new Uint8Array(this.exports.memory.buffer);
const buffer = wasmMemory.slice(ptr + 0, ptr + len * 8);
const uint64s = new BigUint64Array(buffer.buffer);
return [...uint64s];
}
minDistanceToCell(point, cellID) {
return this.exports.minDistanceToCell(point.latitude, point.longitude, cellID);
}
cellIDChildren(cellID, level) {
const len = this.exports.cellIDChildren(cellID, level);
if (len < 0) {
throw new Error(`Failed to get cell ID children for ${cellID} at level ${level}`);
}
const ptr = this.exports.cellsBufferPtr();
const wasmMemory = new Uint8Array(this.exports.memory.buffer);
const buffer = wasmMemory.slice(ptr + 0, ptr + len * 8);
const uint64s = new BigUint64Array(buffer.buffer);
return [...uint64s];
}
}
//# sourceMappingURL=s2Bindings.js.map