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
JavaScript
"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;