Files
geointel/frontend/src/lib/geojsonBounds.ts
T
Codex 490325e0cd
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s
feat: map the complete municipality of Mol
2026-07-14 05:35:15 +02:00

76 lines
2.1 KiB
TypeScript

export interface GeoJsonBounds {
minX: number
minY: number
maxX: number
maxY: number
}
function extendBounds(bounds: GeoJsonBounds | null, x: number, y: number): GeoJsonBounds {
if (!bounds) {
return { minX: x, minY: y, maxX: x, maxY: y }
}
bounds.minX = Math.min(bounds.minX, x)
bounds.minY = Math.min(bounds.minY, y)
bounds.maxX = Math.max(bounds.maxX, x)
bounds.maxY = Math.max(bounds.maxY, y)
return bounds
}
function scanCoordinates(coordinates: unknown, initial: GeoJsonBounds | null): GeoJsonBounds | null {
let bounds = initial
const stack: unknown[] = [coordinates]
while (stack.length > 0) {
const value = stack.pop()
if (!Array.isArray(value)) {
continue
}
if (value.length >= 2 && typeof value[0] === 'number' && typeof value[1] === 'number') {
if (Number.isFinite(value[0]) && Number.isFinite(value[1])) {
bounds = extendBounds(bounds, value[0], value[1])
}
continue
}
for (const child of value) {
stack.push(child)
}
}
return bounds
}
export function geometryBounds(geometry: GeoJSON.Geometry | null | undefined): GeoJsonBounds | null {
if (!geometry) {
return null
}
if (geometry.type === 'GeometryCollection') {
return geometry.geometries.reduce<GeoJsonBounds | null>(
(bounds, child) => mergeBounds(bounds, geometryBounds(child)),
null,
)
}
return scanCoordinates(geometry.coordinates, null)
}
export function mergeBounds(left: GeoJsonBounds | null, right: GeoJsonBounds | null): GeoJsonBounds | null {
if (!left) {
return right ? { ...right } : null
}
if (!right) {
return left
}
left.minX = Math.min(left.minX, right.minX)
left.minY = Math.min(left.minY, right.minY)
left.maxX = Math.max(left.maxX, right.maxX)
left.maxY = Math.max(left.maxY, right.maxY)
return left
}
export function featureCollectionBounds(collection: GeoJSON.FeatureCollection | null | undefined): GeoJsonBounds | null {
if (!collection) {
return null
}
return collection.features.reduce<GeoJsonBounds | null>(
(bounds, feature) => mergeBounds(bounds, geometryBounds(feature.geometry)),
null,
)
}