UNPKG

osm2geojson-lite

Version:

a lightweight yet faster osm (either in xml or in json formats) to geojson convertor - 4x faster than xmldom + osmtogeojson in most situations - implemented in pure JavaScript without any 3rd party dependency

109 lines (108 loc) 4.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WayCollection = void 0; const utils_1 = require("./utils"); class WayCollection extends Array { constructor() { super(); this.firstMap = {}; this.lastMap = {}; } addWay(way) { const w = way.toCoordsArray(); if (w.length > 0) { this.push(w); (0, utils_1.addToMap)(this.firstMap, (0, utils_1.coordsToKey)((0, utils_1.first)(w)), w); (0, utils_1.addToMap)(this.lastMap, (0, utils_1.coordsToKey)((0, utils_1.last)(w)), w); } } mergeWays() { const strings = []; let way = this.shift(); while (way) { (0, utils_1.removeFromMap)(this.firstMap, (0, utils_1.coordsToKey)((0, utils_1.first)(way)), way); (0, utils_1.removeFromMap)(this.lastMap, (0, utils_1.coordsToKey)((0, utils_1.last)(way)), way); let current = way; let next; do { let nextWay = this.getNextWay(current); next = nextWay.next; let mergeType = nextWay.mergeType; if (!next) { continue; } this.splice(this.indexOf(next), 1); (0, utils_1.removeFromMap)(this.firstMap, (0, utils_1.coordsToKey)((0, utils_1.first)(next)), next); (0, utils_1.removeFromMap)(this.lastMap, (0, utils_1.coordsToKey)((0, utils_1.last)(next)), next); switch (mergeType) { case 0 /* MergeType.EndStart */: current = current.concat(next.slice(1)); break; case 1 /* MergeType.EndEnd */: next.reverse(); current = current.concat(next.slice(1)); break; case 2 /* MergeType.StartStart */: current.reverse(); current = current.concat(next.slice(1)); break; case 3 /* MergeType.StartEnd */: current = next.concat(current.slice(1)); break; } } while (next); strings.push((0, utils_1.strArrayArrayToFloat)(current)); way = this.shift(); } return strings; } /** * Try to find the next way to add to the current way. * It first tries the next way in the array, and if this doesn't work, try any other way. */ getNextWay(current) { const lastKey = (0, utils_1.coordsToKey)((0, utils_1.last)(current)); const firstKey = (0, utils_1.coordsToKey)((0, utils_1.first)(current)); // Step 1: Prefer the next way in the array if it connects let next = this.length > 0 ? this[0] : null; if (next) { const nextFirstKey = (0, utils_1.coordsToKey)((0, utils_1.first)(next)); const nextLastKey = (0, utils_1.coordsToKey)((0, utils_1.last)(next)); if (lastKey === nextFirstKey) { return { next, mergeType: 0 /* MergeType.EndStart */ }; } if (lastKey === nextLastKey) { return { next, mergeType: 1 /* MergeType.EndEnd */ }; } if (firstKey === nextFirstKey) { return { next, mergeType: 2 /* MergeType.StartStart */ }; } if (firstKey === nextLastKey) { return { next, mergeType: 3 /* MergeType.StartEnd */ }; } } // Step 2: Fallback to map-based lookup if no sequential match next = (0, utils_1.getFirstFromMap)(this.firstMap, lastKey); if (next) { return { next, mergeType: 0 /* MergeType.EndStart */ }; } next = (0, utils_1.getFirstFromMap)(this.lastMap, lastKey); return { next, mergeType: 1 /* MergeType.EndEnd */ }; } toRings(direction) { const strings = this.mergeWays(); const rings = []; let str = strings.shift(); while (str) { if ((0, utils_1.isRing)(str)) { if ((0, utils_1.ringDirection)(str) !== direction) { str.reverse(); } rings.push(str); } str = strings.shift(); } return rings; } } exports.WayCollection = WayCollection;