feat: initialize drainage network frontend
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
import type {
|
||||
FilterSpecification,
|
||||
GeoJSONSource,
|
||||
GeoJSONSourceSpecification,
|
||||
StyleSpecification
|
||||
} from "maplibre-gl";
|
||||
import type { FeatureCollection, Geometry, LineString, Point, Polygon } from "geojson";
|
||||
import { SOURCE_LAYERS } from "./sources";
|
||||
|
||||
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: "pipes",
|
||||
"source-layer": SOURCE_LAYERS.pipes,
|
||||
minzoom: 9,
|
||||
filter: ["in", ["get", "id"], ["literal", []]],
|
||||
paint: {
|
||||
"line-color": "#2563eb",
|
||||
"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": "#2563eb",
|
||||
"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": "#2563eb",
|
||||
"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": "#2563eb",
|
||||
"circle-radius": 4,
|
||||
"circle-stroke-color": "#ffffff",
|
||||
"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]) => void;
|
||||
}) {
|
||||
if (!map.getSource(MEASUREMENT_SOURCE_ID)) {
|
||||
map.addSource(MEASUREMENT_SOURCE_ID, measurementSource);
|
||||
}
|
||||
|
||||
measurementLayers.forEach((layer) => {
|
||||
if (!map.getLayer(layer.id)) {
|
||||
map.addLayer(layer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user