UNPKG

maplibre-gl-indoor

Version:

A MapLibre plugin to visualize multi-level buildings

87 lines (78 loc) 2.24 kB
import type { BBox, FeatureCollection, Geometry } from "geojson"; import bbox from "@turf/bbox"; import type { LevelsRange } from "./Types"; /** * Extract level from feature * * @returns {LevelsRange | null} the level or the range of level. * @param level */ export function extractLevelRangeFromFeature( level: string, ): LevelsRange | null { const splitLevel: LevelsRange[] = level .split(";") .map(parseLevelRange) .filter((r) => r !== null); if (!splitLevel.length) return null; return { max: Math.max(...splitLevel.map((l) => l.max)), min: Math.min(...splitLevel.map((l) => l.min)), }; } /** * Extract levels range and bounds from geojson * * @param {FeatureCollection<Geometry>} geojson the geojson * @returns {Object} the levels range and bounds. */ export function extractLevelsRangeAndBounds( geojson: FeatureCollection<Geometry>, ): { bounds: BBox; levelsRange: LevelsRange; } { if (geojson.type !== "FeatureCollection") { throw new Error( geojson.type + " is not allowed as a top level collection, please use FeatureCollection instead.", ); } const levelRanges: LevelsRange[] = geojson.features .filter( (feat) => !!feat.properties && typeof feat.properties.level === "string", ) .map((feat) => extractLevelRangeFromFeature(feat.properties?.level ?? "")) .filter((r) => r !== null); if (levelRanges.length == 0) { console.debug(geojson); throw new Error( "the FeatureCollection does not contain a single level. " + "Cannot compute the range of levels to display", ); } return { bounds: bbox(geojson), levelsRange: { max: Math.max(...levelRanges.map((l) => l.max)), min: Math.min(...levelRanges.map((l) => l.min)), }, }; } /** * Extract level from feature * * @returns {LevelsRange | null} the level or the range of level. * @param range e.g. "-1~-2" */ export function parseLevelRange(range: string): LevelsRange | null { const splitRange = range.split("~"); const parsedRange = { max: parseFloat(splitRange[1]), min: parseFloat(splitRange[0]), }; if (isNaN(parsedRange.min) || isNaN(parsedRange.max)) { return null; } return parsedRange; }