feat: inspect native road movements
This commit is contained in:
@@ -22,6 +22,8 @@ const hint = document.querySelector("#hint");
|
||||
const roadName = document.querySelector("#road-name");
|
||||
const movementSummary = document.querySelector("#movement-summary");
|
||||
const laneConvention = document.querySelector("#lane-convention");
|
||||
const selectedMovementPanel = document.querySelector("#selected-movement");
|
||||
const movementDetail = document.querySelector("#movement-detail");
|
||||
const directionSwitch = document.querySelector("#direction-switch");
|
||||
const widthInput = document.querySelector("#width");
|
||||
const lanesInput = document.querySelector("#lanes");
|
||||
@@ -38,6 +40,7 @@ const compileButton = document.querySelector("#compile");
|
||||
|
||||
let state;
|
||||
let selectedRoad = null;
|
||||
let selectedMovement = null;
|
||||
let staged = [];
|
||||
let manualFromEndpoint = null;
|
||||
let diagnosticFilter = "all";
|
||||
@@ -55,7 +58,7 @@ const layers = {
|
||||
const map = new Map({ target: "map", layers: [layers.reference, layers.native, layers.osm, layers.lanes, layers.connectors, layers.diagnostics, layers.selectedRoad, layers.osmDirection], view: new View({ center: [0, 0], zoom: 2 }) });
|
||||
const select = new Select({ condition: click, layers: (layer) => manualFromEndpoint ? layer === layers.osm : [layers.osm, layers.lanes, layers.connectors, layers.native, layers.diagnostics].includes(layer), hitTolerance: 8, style: new Style({ stroke: new Stroke({ color: "#005e89", width: 5 }), fill: new Fill({ color: "rgba(0, 94, 137, .18)" }) }) });
|
||||
map.addInteraction(select);
|
||||
select.on("select", ({ selected }) => { const feature = selected[0]; if (!feature) return; if (manualFromEndpoint) return chooseManualTarget(roadForFeature(feature)); selectRoad(roadForFeature(feature)); });
|
||||
select.on("select", ({ selected }) => { const feature = selected[0]; if (!feature) return; if (manualFromEndpoint) return chooseManualTarget(roadForFeature(feature)); const movement = state.compiled.movements?.find((item) => item.id === feature.get("movement_id")) || null; selectRoad(roadForFeature(feature), undefined, movement); });
|
||||
map.on("pointermove", (event) => { map.getTargetElement().style.cursor = map.hasFeatureAtPixel(event.pixel, { hitTolerance: 8 }) ? "pointer" : ""; });
|
||||
|
||||
function message(text) { status.textContent = text; }
|
||||
@@ -90,16 +93,17 @@ function effectiveLaneEnabled(connector) { const id = `车道连接:${laneId(con
|
||||
function effectiveConnectionEnabled(connection) { const id = `连接:${connection.id}`; const override = [...staged, ...state.overrides.overrides].find((item) => item.id === id); return override ? override.enabled : connection.enabled; }
|
||||
function effectiveConnectorEnabled(connector) { const connection = state?.compiled.model.connections.find((item) => item.id === connector.connection_id); return effectiveLaneEnabled(connector) && (!connection || effectiveConnectionEnabled(connection)); }
|
||||
|
||||
function selectRoad(road, note) {
|
||||
selectedRoad = road; layers.osm.changed(); layers.lanes.changed(); layers.connectors.changed(); refreshOsmDirection();
|
||||
function selectRoad(road, note, movement = null) {
|
||||
selectedRoad = road; selectedMovement = movement; layers.osm.changed(); layers.lanes.changed(); layers.connectors.changed(); refreshOsmDirection();
|
||||
layers.selectedRoad.getSource().clear(); if (road) layers.selectedRoad.getSource().addFeature(new Feature({ geometry: new LineString(road.centerline).transform("EPSG:4326", "EPSG:3857") }));
|
||||
form.hidden = !road; hint.hidden = Boolean(road); if (!road) return;
|
||||
roadName.textContent = `${roadLabel(road)}(${osmDirectionLabel(road)})`;
|
||||
widthInput.value = road.widthMeters; lanesInput.value = road.laneCount; leftInput.checked = road.sidewalkLeft; rightInput.checked = road.sidewalkRight;
|
||||
evidence.textContent = JSON.stringify({ OSM道路: road.osmWayIds, 参数来源: road.provenance, 已应用修改: road.appliedOverrideIds, 原始标签: road.tags }, null, 2);
|
||||
evidence.textContent = JSON.stringify({ OSM道路: road.osmWayIds, 当前方向节点顺序: road.sourceNodeIds, 参数来源: road.provenance, 已应用修改: road.appliedOverrideIds, 原始标签: road.tags }, null, 2);
|
||||
laneConvention.textContent = road.laneCount === 1 ? "蓝色箭头在 OSM 原始中心线上,表示当前方向;“沿 OSM 方向”即节点顺序。本方向只有一条车道。" : "蓝色箭头在 OSM 原始中心线上,表示当前方向;“沿 OSM 方向”即节点顺序。车道按行驶方向从左向右编号。";
|
||||
renderDirectionSwitch(road); renderMovementSummary(road); renderConnections(road); message(note || `已选中:${roadLabel(road)}`);
|
||||
renderDirectionSwitch(road); renderMovementSummary(road); renderSelectedMovement(); renderConnections(road); message(note || `已选中:${roadLabel(road)}`);
|
||||
}
|
||||
function renderSelectedMovement() { selectedMovementPanel.hidden = !selectedMovement; if (!selectedMovement) return; const targetRoad = state.compiled.model.roads.find((road) => road.id === selectedMovement.toRoadId); const labels = { left: "左转", through: "直行", right: "右转", uturn: "掉头" }; const geometry = selectedMovement.geometryStatus === "connector" ? "已绘制路径" : selectedMovement.geometryStatus === "continuous" ? "节点连续" : "路径过长未绘制"; movementDetail.textContent = `${labels[selectedMovement.turn] || selectedMovement.turn}:${lanePositionLabel(selectedRoad, laneIndex(selectedMovement.fromLaneId))} → ${lanePositionLabel(targetRoad, laneIndex(selectedMovement.toLaneId))}\n目标:${roadLabel(targetRoad)}(${osmDirectionLabel(targetRoad)})\n来源端点:${selectedRoad.sourceNodeIds.at(-1)};目标端点:${targetRoad.sourceNodeIds[0]}\n路口节点:${selectedMovement.nodeId}\n状态:${geometry}\n来源:${selectedMovement.provenance}`; }
|
||||
function renderDirectionSwitch(road) {
|
||||
directionSwitch.innerHTML = ""; const alternatives = state.compiled.model.roads.filter((item) => item.osmWayIds.join(",") === road.osmWayIds.join(","));
|
||||
if (alternatives.length < 2) { directionSwitch.textContent = "单向道路"; return; }
|
||||
|
||||
Reference in New Issue
Block a user