Files
next-tjwater-drainage-frontend/features/workbench/map/measurement-layers.ts
T

156 lines
4.4 KiB
TypeScript

import type {
FilterSpecification,
GeoJSONSource,
GeoJSONSourceSpecification,
StyleSpecification
} from "maplibre-gl";
import type { FeatureCollection, Geometry, LineString, Point, Polygon } from "geojson";
import { SOURCE_LAYERS } from "./sources";
import { MAP_STYLE_TOKENS } from "./map-colors";
import { WORKBENCH_INTERACTION_BEFORE_ID } from "./layers";
export const MEASUREMENT_SOURCE_ID = "workbench-measurement";
export const MEASUREMENT_SELECTED_PIPES_LAYER_ID = "workbench-measurement-selected-pipes";
export type MeasurementFeatureCollection = FeatureCollection<Geometry, { kind: "vertex" | "line" | "polygon" }>;
export const emptyMeasurementFeatureCollection: MeasurementFeatureCollection = {
type: "FeatureCollection",
features: []
};
export const measurementSource = {
type: "geojson",
data: emptyMeasurementFeatureCollection
} satisfies GeoJSONSourceSpecification;
export const measurementLayers: StyleSpecification["layers"] = [
{
id: MEASUREMENT_SELECTED_PIPES_LAYER_ID,
type: "line",
source: "conduits",
"source-layer": SOURCE_LAYERS.conduits,
minzoom: 9,
filter: ["in", ["get", "id"], ["literal", []]],
paint: {
"line-color": MAP_STYLE_TOKENS.state.selected,
"line-width": ["interpolate", ["linear"], ["zoom"], 9, 4, 13, 7, 17, 11],
"line-opacity": 0.68
}
},
{
id: "workbench-measurement-polygon-fill",
type: "fill",
source: MEASUREMENT_SOURCE_ID,
filter: ["==", ["get", "kind"], "polygon"],
paint: {
"fill-color": MAP_STYLE_TOKENS.tool.geometry,
"fill-opacity": 0.12
}
},
{
id: "workbench-measurement-line",
type: "line",
source: MEASUREMENT_SOURCE_ID,
filter: ["any", ["==", ["get", "kind"], "line"], ["==", ["get", "kind"], "polygon"]],
paint: {
"line-color": MAP_STYLE_TOKENS.tool.geometry,
"line-width": 2.5,
"line-dasharray": [2, 1.5],
"line-opacity": 0.9
}
},
{
id: "workbench-measurement-vertex",
type: "circle",
source: MEASUREMENT_SOURCE_ID,
filter: ["==", ["get", "kind"], "vertex"],
paint: {
"circle-color": MAP_STYLE_TOKENS.state.selected,
"circle-radius": 4,
"circle-stroke-color": MAP_STYLE_TOKENS.canvas.casing,
"circle-stroke-width": 1.5
}
}
];
export function ensureMeasurementLayers(map: {
getSource: (id: string) => unknown;
addSource: (id: string, source: GeoJSONSourceSpecification) => void;
getLayer: (id: string) => unknown;
addLayer: (layer: NonNullable<StyleSpecification["layers"]>[number], beforeId?: string) => void;
}) {
if (!map.getSource(MEASUREMENT_SOURCE_ID)) {
map.addSource(MEASUREMENT_SOURCE_ID, measurementSource);
}
measurementLayers.forEach((layer) => {
if (!map.getLayer(layer.id)) {
map.addLayer(layer, WORKBENCH_INTERACTION_BEFORE_ID);
}
});
}
export function setMeasurementSourceData(
map: { getSource: (id: string) => unknown },
data: MeasurementFeatureCollection
) {
const source = map.getSource(MEASUREMENT_SOURCE_ID) as GeoJSONSource | undefined;
source?.setData(data);
}
export function setSelectedMeasurementPipeIds(
map: { getLayer: (id: string) => unknown; setFilter: (id: string, filter?: FilterSpecification) => void },
pipeIds: string[]
) {
if (!map.getLayer(MEASUREMENT_SELECTED_PIPES_LAYER_ID)) {
return;
}
map.setFilter(MEASUREMENT_SELECTED_PIPES_LAYER_ID, ["in", ["get", "id"], ["literal", pipeIds]]);
}
export function createMeasurementFeatureCollection(
coordinates: [number, number][],
mode: "distance" | "area" | "segment"
): MeasurementFeatureCollection {
const features: MeasurementFeatureCollection["features"] = coordinates.map((coordinate, index) => ({
type: "Feature",
id: `measurement-vertex-${index}`,
properties: { kind: "vertex" },
geometry: {
type: "Point",
coordinates: coordinate
} satisfies Point
}));
if (coordinates.length >= 2) {
features.push({
type: "Feature",
id: "measurement-line",
properties: { kind: "line" },
geometry: {
type: "LineString",
coordinates
} satisfies LineString
});
}
if (mode === "area" && coordinates.length >= 3) {
features.push({
type: "Feature",
id: "measurement-polygon",
properties: { kind: "polygon" },
geometry: {
type: "Polygon",
coordinates: [[...coordinates, coordinates[0]]]
} satisfies Polygon
});
}
return {
type: "FeatureCollection",
features
};
}