UNPKG

geos.js

Version:

an easy-to-use JavaScript wrapper over WebAssembly build of GEOS

146 lines (128 loc) 4.36 kB
import type { OutPtr } from '../core/reusable-memory.mjs'; import type { u32 } from '../core/types/WasmGEOS.mjs'; import { POINTER } from '../core/symbols.mjs'; import { type Geometry, GeometryRef } from '../geom/Geometry.mjs'; import { geos } from '../core/geos.mjs'; export interface WKBInputOptions { /** * Automatically repair structural errors in the input (currently just unclosed rings) while reading. * @default false */ fix?: boolean; } /** * Creates a {@link Geometry} from Well-Known Binary (WKB) representation. * * @param wkb - Binary data containing WKB representation of the geometry * @param options - Optional WKB input configuration * @returns A new geometry object created from the WKB data * @throws {GEOSError} on invalid WKB data * * @see {@link https://libgeos.org/specifications/wkb} * * @example #live * const wkb = new Uint8Array([ * 1, // 1 - LE * 1, 0, 0, 0, // 1 - point * 105, 87, 20, 139, 10, 191, 5, 64, // Math.E - x * 24, 45, 68, 84, 251, 33, 9, 64, // Math.PI - y * ]); * const pt = fromWKB(wkb); // point([ Math.E, Math.PI ]); */ export function fromWKB(wkb: Uint8Array, options?: WKBInputOptions): Geometry { const cache = geos.b_r; const key = options ? [ options.fix ].join() : ''; let readerPtr = cache[ key ]; if (!readerPtr) { const ptr = geos.GEOSWKBReader_create(); if (options) { const { fix } = options; if (fix != null) { geos.GEOSWKBReader_setFixStructure(ptr, +fix); } } readerPtr = cache[ key ] = ptr; } const wkbLen = wkb.length; const buff = geos.buffByL(wkbLen); try { geos.U8.set(wkb, buff[ POINTER ]); const geomPtr = geos.GEOSWKBReader_read(readerPtr, buff[ POINTER ], wkbLen); return new GeometryRef(geomPtr) as Geometry; } finally { buff.freeIfTmp(); } } export interface WKBOutputOptions { /** * Output dimensionality of the writer. * @default 4 */ dim?: 2 | 3 | 4; /** * Output flavor of the writer. * - [`extended`]{@link https://libgeos.org/specifications/wkb/#extended-wkb} * - [`iso`]{@link https://libgeos.org/specifications/wkb/#iso-wkb} * @default 'extended' */ flavor?: 'extended' | 'iso'; /** * Output byte order of the writer. * Little/Big Endian. * @default 'le' */ byteOrder?: 'le' | 'be'; /** * Whether SRID values should be output in WKB. * Many WKB readers do not support SRID values, use with caution. * @default false */ srid?: boolean; } /** * Converts a geometry object to its Well-Known Binary (WKB) representation. * * @param geometry - The geometry object to be converted to WKB * @param options - Optional WKB output configuration * @returns A Uint8Array containing the WKB representation of the geometry * * @see {@link https://libgeos.org/specifications/wkb} * * @example #live * const pt = point([ Math.E, Math.PI, 1 ]); * const wkb1 = toWKB(pt); // Uint8Array([...]) * const wkb2 = toWKB(pt, { dim: 2 }); // Uint8Array([...]) */ export function toWKB(geometry: Geometry, options?: WKBOutputOptions): Uint8Array { const cache = geos.b_w; const key = options ? [ options.dim, options.flavor, options.byteOrder, options.srid ].join() : ''; let writerPtr = cache[ key ]; if (!writerPtr) { const ptr = geos.GEOSWKBWriter_create(); if (options) { const { dim, flavor, byteOrder, srid } = options; if (dim != null) { geos.GEOSWKBWriter_setOutputDimension(ptr, dim); } if (flavor != null) { geos.GEOSWKBWriter_setFlavor(ptr, flavor === 'iso' ? 2 : 1); } if (byteOrder != null) { geos.GEOSWKBWriter_setByteOrder(ptr, byteOrder === 'be' ? 0 : 1); } if (srid != null) { geos.GEOSWKBWriter_setIncludeSRID(ptr, +srid); } } writerPtr = cache[ key ] = ptr; } const len = geos.u1 as OutPtr<u32>; const ptr = geos.GEOSWKBWriter_write(writerPtr, geometry[ POINTER ], len[ POINTER ]); const wkb = geos.U8.slice(ptr, ptr + len.get()); geos.free(ptr); return wkb; }