From 1da985c932dbf102192f58706eea3e031d3e967e Mon Sep 17 00:00:00 2001 From: que01 Date: Fri, 14 Aug 2026 10:26:35 +0800 Subject: [PATCH] feat: inspect native road movements --- scripts/workbench/app.js | 14 +++++++++----- scripts/workbench/index.html | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/workbench/app.js b/scripts/workbench/app.js index a525bdb..a826a73 100644 --- a/scripts/workbench/app.js +++ b/scripts/workbench/app.js @@ -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; } diff --git a/scripts/workbench/index.html b/scripts/workbench/index.html index 68a19e0..d3d16d6 100644 --- a/scripts/workbench/index.html +++ b/scripts/workbench/index.html @@ -1,4 +1,4 @@ 道路编译工作台
道路编译工作台
-
+