72 lines
2.6 KiB
TypeScript
72 lines
2.6 KiB
TypeScript
import type { GeoJSONVTInternalFeature, GeoJSONVTInternalLineStringFeature, GeoJSONVTInternalMultiLineStringFeature, GeoJSONVTInternalMultiPointFeature, GeoJSONVTInternalMultiPolygonFeature, GeoJSONVTInternalPointFeature, GeoJSONVTInternalPolygonFeature } from "./definitions";
|
|
|
|
type FeatureTypeMap = {
|
|
Point: GeoJSONVTInternalPointFeature["geometry"];
|
|
MultiPoint: GeoJSONVTInternalMultiPointFeature["geometry"];
|
|
LineString: GeoJSONVTInternalLineStringFeature["geometry"];
|
|
MultiLineString: GeoJSONVTInternalMultiLineStringFeature["geometry"];
|
|
Polygon: GeoJSONVTInternalPolygonFeature["geometry"];
|
|
MultiPolygon: GeoJSONVTInternalMultiPolygonFeature["geometry"];
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param id - the feature's ID
|
|
* @param type - the feature's type
|
|
* @param geom - the feature's geometry
|
|
* @param tags - the feature's properties
|
|
* @returns the created feature
|
|
*/
|
|
export function createFeature<T extends GeoJSONVTInternalFeature["type"]>(id: number | string | undefined, type: T, geom: FeatureTypeMap[T], tags: GeoJSON.GeoJsonProperties): GeoJSONVTInternalFeature {
|
|
// This is mostly for TypeScript type narrowing
|
|
const data = { type, geom } as { [K in GeoJSONVTInternalFeature["type"]]: { type: K, geom: FeatureTypeMap[K] } }[GeoJSONVTInternalFeature["type"]];
|
|
|
|
const feature = {
|
|
id: id == null ? null : id,
|
|
type: data.type,
|
|
geometry: data.geom,
|
|
tags,
|
|
minX: Infinity,
|
|
minY: Infinity,
|
|
maxX: -Infinity,
|
|
maxY: -Infinity
|
|
} as GeoJSONVTInternalFeature;
|
|
|
|
switch (data.type) {
|
|
case 'Point':
|
|
case 'MultiPoint':
|
|
case 'LineString':
|
|
calcLineBBox(feature, data.geom);
|
|
break;
|
|
|
|
case 'Polygon':
|
|
// the outer ring (ie [0]) contains all inner rings
|
|
calcLineBBox(feature, data.geom[0]);
|
|
break;
|
|
|
|
case 'MultiLineString':
|
|
for (const line of data.geom) {
|
|
calcLineBBox(feature, line);
|
|
}
|
|
break;
|
|
|
|
case 'MultiPolygon':
|
|
for (const polygon of data.geom) {
|
|
// the outer ring (ie [0]) contains all inner rings
|
|
calcLineBBox(feature, polygon[0]);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return feature;
|
|
}
|
|
|
|
function calcLineBBox(feature: GeoJSONVTInternalFeature, geom: number[]) {
|
|
for (let i = 0; i < geom.length; i += 3) {
|
|
feature.minX = Math.min(feature.minX, geom[i]);
|
|
feature.minY = Math.min(feature.minY, geom[i + 1]);
|
|
feature.maxX = Math.max(feature.maxX, geom[i]);
|
|
feature.maxY = Math.max(feature.maxY, geom[i + 1]);
|
|
}
|
|
}
|