feat: migrate workbench to React
This commit is contained in:
160
workbench/client/src/map/layers.ts
Normal file
160
workbench/client/src/map/layers.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import Feature from 'ol/Feature';
|
||||
import GeoJSON from 'ol/format/GeoJSON';
|
||||
import LineString from 'ol/geom/LineString';
|
||||
import Point from 'ol/geom/Point';
|
||||
import VectorLayer from 'ol/layer/Vector';
|
||||
import VectorSource from 'ol/source/Vector';
|
||||
import CircleStyle from 'ol/style/Circle';
|
||||
import Fill from 'ol/style/Fill';
|
||||
import RegularShape from 'ol/style/RegularShape';
|
||||
import Stroke from 'ol/style/Stroke';
|
||||
import Style from 'ol/style/Style';
|
||||
import type { Road, WorkbenchState } from '../types/state';
|
||||
|
||||
const geojson = new GeoJSON();
|
||||
const source = () => new VectorSource();
|
||||
export type LayerName =
|
||||
| 'reference'
|
||||
| 'gaodeReference'
|
||||
| 'native'
|
||||
| 'sidewalks'
|
||||
| 'osm'
|
||||
| 'lanes'
|
||||
| 'edgeLines'
|
||||
| 'directionArrows'
|
||||
| 'markings'
|
||||
| 'centerLines'
|
||||
| 'controls'
|
||||
| 'signals'
|
||||
| 'connectors'
|
||||
| 'diagnostics'
|
||||
| 'selectedRoad';
|
||||
export function createLayers(onRoad: () => Road | null, scene: () => boolean) {
|
||||
const simple = (color: string, width = 1) =>
|
||||
new Style({ fill: new Fill({ color: `${color}55` }), stroke: new Stroke({ color, width }) });
|
||||
const layers: Record<LayerName, VectorLayer<VectorSource>> = {
|
||||
reference: new VectorLayer({ source: source(), visible: false, style: simple('#8999a0') }),
|
||||
gaodeReference: new VectorLayer({ source: source(), style: simple('#2563eb', 1.5) }),
|
||||
native: new VectorLayer({
|
||||
source: source(),
|
||||
style: () => (scene() ? new Style({ fill: new Fill({ color: '#3f4b50' }) }) : simple('#296956')),
|
||||
}),
|
||||
sidewalks: new VectorLayer({
|
||||
source: source(),
|
||||
style: () => (scene() ? new Style({ fill: new Fill({ color: '#b7b9ad' }) }) : simple('#9b7c40')),
|
||||
}),
|
||||
osm: new VectorLayer({
|
||||
source: source(),
|
||||
style: (f) =>
|
||||
new Style({
|
||||
stroke: new Stroke({
|
||||
color: f.get('road_id') === onRoad()?.id ? '#006e91' : '#263630',
|
||||
width: f.get('road_id') === onRoad()?.id ? 5 : 2,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
lanes: new VectorLayer({
|
||||
source: source(),
|
||||
style: new Style({ stroke: new Stroke({ color: '#f5f6ee', width: 1.5, lineDash: [5, 4] }) }),
|
||||
}),
|
||||
edgeLines: new VectorLayer({
|
||||
source: source(),
|
||||
visible: false,
|
||||
style: new Style({ stroke: new Stroke({ color: '#f5f6ee', width: 1 }) }),
|
||||
}),
|
||||
directionArrows: new VectorLayer({
|
||||
source: source(),
|
||||
style: new Style({ fill: new Fill({ color: '#f5f6ee' }), stroke: new Stroke({ color: '#d9dacf', width: 1 }) }),
|
||||
}),
|
||||
markings: new VectorLayer({
|
||||
source: source(),
|
||||
style: new Style({ fill: new Fill({ color: '#f5f6ee' }), stroke: new Stroke({ color: '#d9dacf', width: 1 }) }),
|
||||
}),
|
||||
centerLines: new VectorLayer({
|
||||
source: source(),
|
||||
style: new Style({ fill: new Fill({ color: '#f5be2a' }), stroke: new Stroke({ color: '#d29d16', width: 1 }) }),
|
||||
}),
|
||||
controls: new VectorLayer({
|
||||
source: source(),
|
||||
style: new Style({ fill: new Fill({ color: '#f5f6ee' }), stroke: new Stroke({ color: '#d9dacf', width: 1 }) }),
|
||||
}),
|
||||
signals: new VectorLayer({
|
||||
source: source(),
|
||||
style: new Style({
|
||||
image: new RegularShape({
|
||||
points: 4,
|
||||
radius: 6,
|
||||
angle: Math.PI / 4,
|
||||
fill: new Fill({ color: '#263630' }),
|
||||
stroke: new Stroke({ color: '#fff', width: 2 }),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
connectors: new VectorLayer({
|
||||
source: source(),
|
||||
style: new Style({ stroke: new Stroke({ color: '#ad3a76', width: 2, lineDash: [7, 5] }) }),
|
||||
}),
|
||||
diagnostics: new VectorLayer({
|
||||
source: source(),
|
||||
style: (f) =>
|
||||
new Style({
|
||||
image: new CircleStyle({
|
||||
radius: 6,
|
||||
fill: new Fill({ color: f.get('severity') === 'error' ? '#bf3b2e' : '#d49318' }),
|
||||
stroke: new Stroke({ color: '#fff', width: 1 }),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
selectedRoad: new VectorLayer({
|
||||
source: source(),
|
||||
style: new Style({ stroke: new Stroke({ color: '#00a5cf', width: 8 }) }),
|
||||
}),
|
||||
};
|
||||
return layers;
|
||||
}
|
||||
function features(value: unknown) {
|
||||
return geojson.readFeatures((value || { type: 'FeatureCollection', features: [] }) as object, {
|
||||
dataProjection: 'EPSG:4326',
|
||||
featureProjection: 'EPSG:3857',
|
||||
});
|
||||
}
|
||||
export function updateLayers(layers: ReturnType<typeof createLayers>, state: WorkbenchState, selected: Road | null) {
|
||||
const get = (name: LayerName) => layers[name].getSource()!;
|
||||
const put = (name: LayerName, value: unknown) => {
|
||||
const target = get(name);
|
||||
target.clear();
|
||||
target.addFeatures(features(value));
|
||||
};
|
||||
put('reference', state.layers.osm2streetsRoadSurface);
|
||||
put('gaodeReference', state.junctionReference?.converted);
|
||||
put('native', state.layers.nativeRoadSurface);
|
||||
get('native').addFeatures(features(state.layers.nativeIntersectionSurface));
|
||||
put('sidewalks', state.layers.nativeSidewalkSurface);
|
||||
const roads = state.compiled.model.roads.map(
|
||||
(road) =>
|
||||
new Feature({ geometry: new LineString(road.centerline).transform('EPSG:4326', 'EPSG:3857'), road_id: road.id }),
|
||||
);
|
||||
put('osm', { type: 'FeatureCollection', features: [] });
|
||||
get('osm').addFeatures(roads);
|
||||
put('lanes', state.layers.laneCenterlines);
|
||||
put('edgeLines', state.layers.edgeLines);
|
||||
put('directionArrows', state.layers.directionArrows);
|
||||
put('markings', state.layers.laneSeparators);
|
||||
get('markings').addFeatures(features(state.layers.turnArrows));
|
||||
put('centerLines', state.layers.centerLines);
|
||||
put('controls', state.layers.crosswalks);
|
||||
get('controls').addFeatures(features(state.layers.vehicleStopLines));
|
||||
put('signals', state.trafficSignals.assemblies);
|
||||
put('connectors', state.layers.connectors);
|
||||
put('diagnostics', {
|
||||
type: 'FeatureCollection',
|
||||
features: state.compiled.diagnostics
|
||||
.filter((item) => item.geometry)
|
||||
.map(({ geometry, ...properties }) => ({ type: 'Feature', properties, geometry: geometry! })),
|
||||
});
|
||||
put('selectedRoad', { type: 'FeatureCollection', features: [] });
|
||||
if (selected)
|
||||
get('selectedRoad').addFeature(
|
||||
new Feature({ geometry: new LineString(selected.centerline).transform('EPSG:4326', 'EPSG:3857') }),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user