UNPKG

s2-tools

Version:

A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.

177 lines 5.53 kB
import { Info } from './info'; import { extendBBox } from '../../geometry'; /** * Convert an intermediate way to a vector feature * @param way - intermediate way * @param reader - OSM reader * @returns - way vector feature */ export async function intermediateWayToVectorFeature(way, reader) { const { addBBox } = reader; const { id, isArea, wayNodes, properties, metadata } = way; // build line const vectorLine = []; for (const ref of wayNodes) { const node = await reader.nodeGeometry.get(ref); if (node === undefined) return; vectorLine.push({ ...node }); } let bbox; if (addBBox) { for (const node of vectorLine) bbox = extendBBox(bbox, node); } // build geometry const geometry = isArea ? { type: 'Polygon', is3D: false, coordinates: [vectorLine], bbox } : { type: 'LineString', is3D: false, coordinates: vectorLine, bbox }; return { id, type: 'VectorFeature', properties, geometry, metadata: { info: metadata }, }; } /** * Way Class */ export class Way { primitiveBlock; reader; id = -1; info; // Parallel arrays #keys = []; #vals = []; #refs = []; // DELTA coded // Optional infield lat-lon // NOTE: I'm not going to bother implementing this, I've never seen it used. // #lats: number[] = []; // optional DELTA coded // #lons: number[] = []; // optional DELTA coded /** * @param primitiveBlock - the primitive block to access keys and values * @param reader - the OSM reader * @param pbf - the Protobuf object to read from */ constructor(primitiveBlock, reader, pbf) { this.primitiveBlock = primitiveBlock; this.reader = reader; pbf.readMessage(this.#readLayer, this); } /** * Checks if the way is filterable or not * @returns - true if the way is filterable */ isFilterable() { const { tagFilter, skipWays } = this.reader; if (skipWays) return true; if (tagFilter !== undefined) { for (let i = 0; i < this.#keys.length; i++) { const keyStr = this.primitiveBlock.getString(this.#keys[i]); const valStr = this.primitiveBlock.getString(this.#vals[i]); if (tagFilter.matchFound('Way', keyStr, valStr)) return false; } // if we make it here, we didn't find any matching tags return true; } return false; } /** * Access the way's properties * @returns - the way's properties */ properties() { return this.primitiveBlock.tags(this.#keys, this.#vals); } /** * Access the way's node IDs associated with this way * @returns - the way's nodes */ nodeRefs() { const res = []; let ref = 0; for (let i = 0; i < this.#refs.length; i++) { ref += this.#refs[i]; res.push(ref); } return res; } /** * Checks if the way has a key-value pair (value optional) * @param key - the key * @param val - the value * @returns - true if the way has the key and value */ hasKeyValue(key, val) { const { primitiveBlock: pb } = this; for (let i = 0; i < this.#keys.length; i++) { if (pb.getString(this.#keys[i]) === key) { if (val === undefined) return true; if (pb.getString(this.#vals[i]) === val) return true; } } return false; } /** * Checks if the way is an area based on it's key-value pairs * @returns - true if the way is an area */ isArea() { const { upgradeWaysToAreas } = this.reader; if ((upgradeWaysToAreas && this.#refs.length >= 4 && this.#refs[0] === this.#refs[this.#refs.length - 1]) || this.hasKeyValue('area', 'yes')) { return true; } return false; } /** * Converts the way to an intermediate vector feature (way's nodes have not been parsed) * @returns - the way as an intermediate vector feature */ toVectorFeature() { const isArea = this.isArea(); const wayNodes = this.nodeRefs(); if (wayNodes.length < 2) return; return { id: this.id, isArea, properties: this.properties(), wayNodes, metadata: this.info?.toBlock() ?? {}, }; } /** * @param tag - the tag of the message * @param way - the way to modify * @param pbf - the Protobuf object to read from */ #readLayer(tag, way, pbf) { if (tag === 1) way.id = pbf.readVarint(); else if (tag === 2) way.#keys = pbf.readPackedVarint(); else if (tag === 3) way.#vals = pbf.readPackedVarint(); else if (tag === 4) way.info = new Info(way.primitiveBlock, pbf); else if (tag === 8) way.#refs = pbf.readPackedSVarint(); // skip, not used. else if (tag === 9 || tag === 10) return; // else if (tag === 9) way.#lats = pbf.readPackedSVarint(); // else if (tag === 10) way.#lons = pbf.readPackedSVarint(); else throw new Error(`Unknown tag: ${tag}`); } } //# sourceMappingURL=way.js.map