feat(qgis): add editable traffic signal assemblies
This commit is contained in:
@@ -144,20 +144,22 @@ OSM way 的端点不一定在原始 XML 中有三个以上相连 way;osm2stree
|
||||
|
||||
**教训**:**跨阶段契约必须随产物保存;兼容旧产物的字符串回退也要被审查**。
|
||||
|
||||
### 坑 6:部分构建复用了过期的交通信号锚点
|
||||
### 坑 6:部分构建复用了过期的交通信号运行时数据
|
||||
|
||||
`scripts/lib/traffic-signals.js` 根据当前 OSM 的 `highway=traffic_signals` 控制节点、
|
||||
`vehicle_stop_lines.geojson` 和 `intersection_surface.geojson` 派生
|
||||
`osm2streets_web_out/traffic_signals.json`。Blender 将这份文件中的每个 signal id 导出为
|
||||
三个动态灯节点和一组倒计时节点,`scripts/lib/cesium-preview.js` 再按相同 id 控制它们。
|
||||
`intermediates` 才能根据当前 OSM 的 `highway=traffic_signals` 控制节点、
|
||||
`vehicle_stop_lines.geojson` 和 `intersection_surface.geojson` 初始化可编辑的
|
||||
`traffic_signal_assemblies.geojson`。此后该 GeoJSON 是 QGIS 编辑生命周期内的事实源;
|
||||
`traffic_signals.json` 只是严格校验后派生的运行时数据。Blender 将其中每个稳定的
|
||||
`signal_uid` 导出为静态设施、三个动态灯节点和一组倒计时节点,
|
||||
`scripts/lib/cesium-preview.js` 再按相同 id 控制它们。
|
||||
|
||||
因此执行 `blender,cesium,preview` 这类部分构建时,必须在 Blender stage 入口重新写入
|
||||
交通信号文件。若沿用旧文件,GLB 可能已经包含新增 T/十字路口,但预览仍只控制旧的
|
||||
signal id,表现为灯不切换、数字叠加或路口整体异常。该刷新由
|
||||
因此执行 `blender,cesium,preview` 这类部分构建时,必须在 Blender stage 入口从当前
|
||||
`traffic_signal_assemblies.geojson` 重建运行时 JSON,但绝不能重新从 OSM 初始化位置,
|
||||
否则会覆盖 QGIS 中移动、旋转或禁用设施的编辑。该刷新由
|
||||
`scripts/build-area.js:buildBlenderScene()` 负责。
|
||||
|
||||
**教训**:**任何由输入 OSM 或归一化图层派生、又被多个后续 stage 共享的中间 JSON,
|
||||
都必须在最早消费它的 stage 重新生成,不能只在完整 `intermediates` 构建时生成。**
|
||||
**教训**:**跨阶段运行时 JSON 必须在最早消费它的 stage 从当前权威产物重建;同时要
|
||||
区分“初始化来源”和“编辑后的事实源”,不能用早期输入覆盖人工编辑。**
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -343,13 +343,14 @@ out.vehicleStopLines = crosswalkData.stopLines;
|
||||
// 原生 lane_markings 停止线不得复制到输出。
|
||||
```
|
||||
|
||||
## 信号锚点的跨阶段消费
|
||||
## 可编辑信号设施与运行时锚点的跨阶段消费
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
路口信号设施需要同时被 Blender 主 GLB 和 Cesium 预览消费时,使用
|
||||
`<geojsonDir>/traffic_signals.json`。它是附属 intermediates 产物,而不是第十个
|
||||
osm2streets/QGIS 图层。
|
||||
`<geojsonDir>/traffic_signal_assemblies.geojson` 是 GeoPackage/QGIS 中的附属可编辑点图层;
|
||||
`<geojsonDir>/traffic_signals.json` 是从它严格校验并派生的运行时产物。前者不属于九个
|
||||
`SCENE_LAYERS`,后者不进入 GeoPackage。
|
||||
|
||||
### 2. Signatures
|
||||
|
||||
@@ -366,15 +367,19 @@ area.outputs.trafficSignals
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
- `build-area.js:writeTrafficSignals()` 是锚点 JSON 的生产者,调用
|
||||
`traffic-signals.js:readTrafficSignals()`,输入为 `vehicle_stop_lines.geojson` 和
|
||||
`intersection_surface.geojson`。
|
||||
- `intermediates` 与 `reimport` 都必须在其 GeoJSON 产物稳定后重写锚点,确保 QGIS
|
||||
人工修补反导入后,Blender 和 preview 仍使用同一事实。
|
||||
- `intermediates` 从 OSM control、停止线和路口面初始化 `traffic_signal_assemblies.geojson`,
|
||||
并将其作为附属点层导入 GeoPackage;完整重跑 intermediates 会像道路图层一样覆盖人工编辑。
|
||||
- `reimport` 必须与九个场景层一起暂存导出附属层,先校验全部信号要素,再替换任何输出。
|
||||
- `build-area.js:writeTrafficSignals()` 只从当前 `traffic_signal_assemblies.geojson` 重建运行时
|
||||
`traffic_signals.json`。Blender 入口也执行这一步,但不得重新从 OSM 初始化位置。
|
||||
- `blender` 和 `preview` 在启动前必须检查该文件存在;前者把静态设施写进 `05_Props`,
|
||||
后者只叠加动态灯珠、倒计时和车辆相位。
|
||||
- `traffic_signals.json` 不得加入 `SCENE_LAYERS`、GeoPackage 或 QGIS 工程;这些层只能
|
||||
继续包含九个道路场景图层。
|
||||
- `traffic_signal_assemblies.geojson` 必须加入 GeoPackage/QGIS 工程,但不得加入
|
||||
`SCENE_LAYERS`、合并道路场景或栅格预览;`traffic_signals.json` 仍不得加入 GeoPackage。
|
||||
- `signal_uid` 必须由 control id、source way id 和相邻 arm node id 确定性生成;运行时 `id`
|
||||
使用该技术 id。`display_id` 可编辑且非空时唯一,修改它不得重命名 GLB 节点。
|
||||
- Point 几何是灯杆地面点;`stop_lon`/`stop_lat` 独立保存,移动杆件不得移动车辆停止点。
|
||||
- `enabled=false` 的要素保留在编辑层但不进入运行时 signals。
|
||||
- `layout.countdownLateralMeters` 等几何字段是 Blender/preview 的共同事实源;横向正值统一
|
||||
表示相对来车方向的右侧。不得在任一消费方用独立的负号约定替代它。
|
||||
- `layout.mastHeightMeters` 与 `layout.headCenterHeightMeters` 必须相等,表示横杆与灯壳的
|
||||
@@ -385,9 +390,9 @@ area.outputs.trafficSignals
|
||||
|
||||
| 条件 | 结果 |
|
||||
|---|---|
|
||||
| `intermediates` 或 `reimport` 有合法停止线和路口面 | 写出 `version` 与 `signals` 数组,即使数组为空 |
|
||||
| `intermediates` 或 `reimport` 有合法编辑层 | 写出 `version` 与 `signals` 数组,即使数组为空 |
|
||||
| 直接运行 `blender` / `preview` 但锚点不存在 | 在启动外部工具前报 `Traffic signal anchors not found` |
|
||||
| 单个停止线无法可靠关联路口 | 锚点生成器跳过该项,其他进口照常输出 |
|
||||
| `signal_uid` 缺失/重复、非空 `display_id` 重复、字段或 Point 无效 | 重导入在替换任何输出前失败 |
|
||||
| 用户仅修改 QGIS 后运行 `reimport` | 重新生成锚点,不沿用旧坐标 |
|
||||
|
||||
### 5. Good/Base/Bad Cases
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{"file":".trellis/spec/pipeline/cli-and-stages.md","reason":"Check stage ownership, diagnostics, and traffic signal contract compliance"}
|
||||
{"file":".trellis/spec/pipeline/external-tools.md","reason":"Check atomic reimport behavior and external-tool handling"}
|
||||
{"file":".trellis/spec/guides/cross-layer-thinking-guide.md","reason":"Check full editable-layer to runtime JSON to Blender/Cesium data flow"}
|
||||
{"file":".trellis/spec/guides/artifact-parity-guide.md","reason":"Check intended and unintended scene/GLB structural differences"}
|
||||
{"file":".trellis/spec/blender/testing.md","reason":"Check appropriate pure and Blender validation coverage"}
|
||||
100
.trellis/tasks/08-07-qgis-traffic-signal-overrides/design.md
Normal file
100
.trellis/tasks/08-07-qgis-traffic-signal-overrides/design.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Design: QGIS Traffic Signal Overrides
|
||||
|
||||
## Architecture
|
||||
|
||||
Introduce a separate auxiliary-edit-layer registry rather than adding traffic signals to `SCENE_LAYERS`. The initial registry contains one layer:
|
||||
|
||||
```text
|
||||
traffic_signal_assemblies.geojson
|
||||
geometry: Point (pole ground position, EPSG:4326)
|
||||
properties: stable identity, source identity, heading, phase, reach, stop point, enabled, z offset
|
||||
```
|
||||
|
||||
The existing runtime file remains:
|
||||
|
||||
```text
|
||||
traffic_signals.json
|
||||
version/layout/signals[] with full pose.* data
|
||||
```
|
||||
|
||||
The editable GeoJSON is the placement source; the runtime JSON is a derived consumer artifact.
|
||||
|
||||
## Data Flow
|
||||
|
||||
```text
|
||||
OSM controls + topology + stop lines + intersections
|
||||
|
|
||||
intermediates only
|
||||
v
|
||||
traffic_signal_assemblies.geojson
|
||||
|
|
||||
import into GeoPackage
|
||||
|
|
||||
edit in QGIS
|
||||
|
|
||||
reimport
|
||||
v
|
||||
traffic_signal_assemblies.geojson
|
||||
|
|
||||
validate + derive pose
|
||||
v
|
||||
traffic_signals.json
|
||||
/ \
|
||||
Blender preview/Cesium
|
||||
```
|
||||
|
||||
`blender` reruns the final validation/derivation arrow from the editable GeoJSON so derived JSON cannot be stale, but it never reruns the OSM initialization arrow.
|
||||
|
||||
## Editable Feature Contract
|
||||
|
||||
Recommended properties:
|
||||
|
||||
| Property | Type | Ownership |
|
||||
|---|---|---|
|
||||
| `signal_uid` | string | generated, immutable technical identity |
|
||||
| `display_id` | string | user-editable unique label/number |
|
||||
| `control_id` | string | generated OSM control id |
|
||||
| `approach_id` | string | generated physical approach identity |
|
||||
| `source_way_id` | string | generated matching/diagnostic field |
|
||||
| `heading_deg` | number | user-editable assembly facing direction |
|
||||
| `phase_group` | integer 0/1 | user-editable current two-phase group |
|
||||
| `mast_reach_m` | positive number | user-editable arm reach |
|
||||
| `stop_lon`, `stop_lat` | finite numbers | generated vehicle stop point, preserved when pole moves |
|
||||
| `enabled` | boolean/integer | user-editable suppression flag |
|
||||
| `z_offset_m` | finite number | user-editable vertical adjustment |
|
||||
|
||||
Point geometry is the pole longitude/latitude. The runtime `id` should be derived from `signal_uid`, not display numbering, so changing `display_id` does not rename GLB nodes or break preview control.
|
||||
|
||||
## Stable Identity
|
||||
|
||||
Extend parsed OSM arm data to retain enough deterministic source identity (control node, way, adjacent arm direction/node). Generate a technical key from those source values. Do not use sorted array index or rounded heading as the primary key.
|
||||
|
||||
If topology changes on a future `intermediates` run, the rebuilt GeoPackage may produce new identities. This is consistent with current road-edit lifecycle and is explicitly out of scope for MVP migration. Validation still reports duplicate identities and malformed source fields.
|
||||
|
||||
## QGIS Integration
|
||||
|
||||
- Add an auxiliary layer definition separate from the nine render layers.
|
||||
- Import it into the same GeoPackage after render layers.
|
||||
- Include it in the generated project but exclude it from the merged scene and 2D raster preview unless deliberately enabled for editing visibility.
|
||||
- Use a point marker plus rotated direction indicator driven by `heading_deg` and label by `display_id`, falling back to `signal_uid`.
|
||||
- Configure read-only/editor widgets where practical: technical/source ids read-only; phase group constrained to 0/1; numeric fields constrained to valid ranges; enabled as checkbox.
|
||||
|
||||
## Reimport and Atomicity
|
||||
|
||||
Extend the reimport layer manifest to include auxiliary editable layers while keeping render-scene merge derived only from `SCENE_LAYERS`. Export every layer into staging, parse and validate all editable features, then replace output files. Runtime JSON is written only after the staged auxiliary layer passes validation.
|
||||
|
||||
## Compatibility
|
||||
|
||||
- The next `intermediates` run bootstraps existing areas; no old JSON migration is required.
|
||||
- Main `.blend`/GLB geometry changes intentionally when a QGIS edit changes a signal.
|
||||
- Dynamic and countdown GLBs continue using runtime signal ids, now stable across ordinary reimport edits.
|
||||
- Current two-phase simulation remains unchanged.
|
||||
|
||||
## Risks and Controls
|
||||
|
||||
- **OSM way splitting changes source ids:** accepted across a full intermediates rebuild; ordinary reimport is stable.
|
||||
- **QGIS boolean/string coercion:** normalize known GDAL representations before strict validation and test the round-trip output.
|
||||
- **Accidental source-field editing:** mark technical fields read-only in QGIS and validate identity format during reimport.
|
||||
- **Partial overwrite on invalid auxiliary data:** retain the existing staging-before-replace discipline.
|
||||
- **Old spec conflict:** update pipeline specs that currently forbid traffic-signal anchors in GeoPackage, clarifying the distinction between editable assembly points and derived runtime anchors.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{"file":".trellis/spec/pipeline/cli-and-stages.md","reason":"Traffic signal stage ownership, reimport lifecycle, manifests, and current anchor contract"}
|
||||
{"file":".trellis/spec/pipeline/layer-registry.md","reason":"Keep the auxiliary editable layer separate from the nine render layers and preserve their order"}
|
||||
{"file":".trellis/spec/pipeline/external-tools.md","reason":"GeoPackage import/export and staging-before-replace requirements"}
|
||||
{"file":".trellis/spec/guides/cross-layer-thinking-guide.md","reason":"OSM to GeoJSON/GPKG to Blender/Cesium contract review"}
|
||||
{"file":".trellis/spec/blender/asset-generation.md","reason":"Signal pose and dynamic asset generation constraints"}
|
||||
{"file":".trellis/spec/preview/vehicle-routes.md","reason":"Vehicle stop coordinates and runtime signal data coupling"}
|
||||
@@ -0,0 +1,53 @@
|
||||
# Implementation Plan: QGIS Traffic Signal Overrides
|
||||
|
||||
## 1. Contracts and Pure Logic
|
||||
|
||||
- [x] Add an auxiliary editable-layer definition without modifying `SCENE_LAYERS` ordering.
|
||||
- [x] Extend OSM arm parsing with deterministic approach identity inputs.
|
||||
- [x] Split traffic-signal logic into automatic editable-feature generation, feature validation/normalization, and runtime pose derivation.
|
||||
- [x] Use stable technical ids for runtime signal ids; keep `display_id` as editable metadata.
|
||||
- [x] Add pure Node tests for T/cross counts, stable ids, movement/heading reconstruction, disabled features, duplicate ids, and invalid values.
|
||||
|
||||
## 2. Intermediates and QGIS
|
||||
|
||||
- [x] Write `traffic_signal_assemblies.geojson` after stop-line/intersection outputs are stable.
|
||||
- [x] Import the auxiliary point layer into the GeoPackage after the nine render layers.
|
||||
- [x] Extend generated QGIS project code with point/direction styling, labels, and field widgets/constraints.
|
||||
- [x] Confirm the auxiliary layer is excluded from merged road scene ordering and raster preview behavior.
|
||||
|
||||
## 3. Reimport and Stage Ownership
|
||||
|
||||
- [x] Extend `reimport-gpkg.js` to discover/export render and auxiliary layers through staging.
|
||||
- [x] Validate the staged editable layer before replacing any output artifact.
|
||||
- [x] Rebuild runtime `traffic_signals.json` from editable GeoJSON after `intermediates`, `reimport`, and at Blender entry.
|
||||
- [x] Remove Blender-entry OSM placement regeneration so QGIS edits remain authoritative.
|
||||
- [x] Extend stage manifests and diagnostics with auxiliary input/output records and feature counts.
|
||||
|
||||
## 4. Cross-Layer Consumers
|
||||
|
||||
- [x] Preserve `display_id` and stable runtime ids through Blender and Cesium metadata where useful.
|
||||
- [x] Verify static signal objects, dynamic lenses, countdown nodes, and vehicle stop behavior all consume the same enabled runtime records.
|
||||
- [x] Update pipeline specifications to replace the old prohibition with the editable-layer/derived-runtime distinction.
|
||||
|
||||
## 5. Validation
|
||||
|
||||
- [x] Run Node syntax checks and focused unit tests.
|
||||
- [x] Run existing preview-assets, preflight, budget, and relevant pipeline tests.
|
||||
- [x] Run `intermediates` and inspect the GeoPackage/QGIS project feature schema and styling.
|
||||
- [ ] Make a controlled QGIS edit to one signal (display id, point, heading), run `reimport,blender,cesium,preview`, and verify only the intended assembly changes. (`reimport` and Blender passed; Cesium/preview refresh was not repeated.)
|
||||
- [x] Confirm an invalid/duplicate edit fails before overwriting valid outputs.
|
||||
- [ ] Inspect Blender/Cesium structural digests and Safari preview for T and cross junctions. (Blocked this run by Blender 4.5.12 Metal startup SIGSEGV before project Python.)
|
||||
|
||||
## Risky Files / Rollback Points
|
||||
|
||||
- `scripts/lib/traffic-signals.js`: identity and pose contract; land pure tests before pipeline integration.
|
||||
- `scripts/build-osm2streets-qgis.js`: GeoPackage recreation and generated QGIS Python; verify auxiliary import independently before styling.
|
||||
- `scripts/reimport-gpkg.js`: atomic overwrite boundary; preserve staging semantics.
|
||||
- `scripts/build-area.js`: stage ownership; ensure Blender derives from editable GeoJSON rather than overwriting it.
|
||||
- `blender/osmassets/traffic_signals.py` and preview runtime should require minimal or no geometry changes; unexpected edits here indicate contract leakage.
|
||||
|
||||
## Review Gate Before Start
|
||||
|
||||
- [ ] User approves the final planning summary.
|
||||
- [ ] `prd.md`, `design.md`, and `implement.md` agree on full editable layer ownership and out-of-scope intermediates persistence.
|
||||
- [ ] No unresolved product decision remains.
|
||||
14
.trellis/tasks/08-07-qgis-traffic-signal-overrides/notes.md
Normal file
14
.trellis/tasks/08-07-qgis-traffic-signal-overrides/notes.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Debug Notes
|
||||
|
||||
## 2026-08-07 countdown node-name regression
|
||||
|
||||
Stable `signal_uid` values are intentionally descriptive and can exceed Blender's
|
||||
63-byte object-name limit. Using them directly in dynamic lens/countdown node
|
||||
names caused Blender to truncate names while Cesium looked up the untruncated
|
||||
strings. The countdown GLBs then exposed all digits without the runtime being
|
||||
able to hide the inactive values, appearing as overlapping/blurred numbers.
|
||||
|
||||
Runtime signal records now carry a deterministic short `nodeKey` (`ts_` plus
|
||||
the first 16 hex characters of SHA-256 of `signal_uid`). Blender uses it for
|
||||
dynamic object names and Cesium uses the same key for lookups. Preview keeps a
|
||||
fallback to `signal.id` for older metadata files.
|
||||
67
.trellis/tasks/08-07-qgis-traffic-signal-overrides/prd.md
Normal file
67
.trellis/tasks/08-07-qgis-traffic-signal-overrides/prd.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# QGIS Traffic Signal Overrides
|
||||
|
||||
## Goal
|
||||
|
||||
Make every automatically generated vehicle traffic signal independently identifiable and editable in QGIS. A user must be able to assign a display number, move a pole, rotate its assembly, adjust supported placement attributes, run `reimport`, and have Blender and Cesium consume that edited result without OSM regeneration overwriting it.
|
||||
|
||||
## Background
|
||||
|
||||
- Current traffic signals are derived from OSM `highway=traffic_signals` controls, road topology, `vehicle_stop_lines.geojson`, and `intersection_surface.geojson` by `scripts/lib/traffic-signals.js`.
|
||||
- Current sequential ids such as `signal-1` depend on generation order and are not suitable as persistent edit identities.
|
||||
- Current `<geojsonDir>/traffic_signals.json` contains fully derived `pose.*` data but is deliberately excluded from the GeoPackage and QGIS project.
|
||||
- Existing road editing establishes the desired lifecycle: `intermediates` initializes a GeoPackage, the user edits it in QGIS, and `reimport` exports the edited data back to GeoJSON. Running `intermediates` again may discard manual edits; that behavior remains explicit and unchanged.
|
||||
|
||||
## Requirements
|
||||
|
||||
### R1. Editable auxiliary layer
|
||||
|
||||
- `intermediates` must create a point FeatureCollection containing one feature per physical signal assembly and import it into the area GeoPackage.
|
||||
- The generated QGIS project must expose the layer with a visible directional symbol and a label suitable for identifying individual signals.
|
||||
- The auxiliary layer must not join `SCENE_LAYERS` or the merged road scene because it is an editing/control artifact, not a road render layer.
|
||||
|
||||
### R2. Stable identity and numbering
|
||||
|
||||
- Every generated feature must contain an immutable technical `signal_uid` derived deterministically from its OSM control and physical approach identity, rather than array order.
|
||||
- Every feature must contain an editable `display_id` intended for user-facing numbering.
|
||||
- Build/reimport validation must reject duplicate or missing `signal_uid` values and duplicate non-empty `display_id` values with an actionable error.
|
||||
|
||||
### R3. Editable placement contract
|
||||
|
||||
- Point geometry represents the pole ground position.
|
||||
- Editable attributes must include at least `display_id`, `heading_deg`, `phase_group`, `mast_reach_m`, `enabled`, and `z_offset_m`.
|
||||
- Source/control attributes required for matching and diagnostics must be preserved, including `control_id` and approach identity.
|
||||
- Vehicle stop coordinates remain independent attributes; moving the pole must not silently move the vehicle stop point.
|
||||
- After reimport, the pipeline must deterministically rebuild `pose.pole`, `pose.arm`, `pose.head`, `pose.lenses`, and `pose.countdown` from the edited point and attributes.
|
||||
|
||||
### R4. Stage ownership
|
||||
|
||||
- `intermediates` initializes the editable signal layer from current OSM/topology and derives the runtime `traffic_signals.json` from it.
|
||||
- `reimport` must stage, validate, and export the editable signal layer along with the existing road layers, then rebuild the runtime JSON.
|
||||
- `blender` must rebuild runtime `traffic_signals.json` from the current editable signal GeoJSON. It must not recompute signal placement directly from OSM and erase QGIS edits.
|
||||
- `cesium` and `preview` continue consuming artifacts derived from the same runtime JSON and retain matching signal node ids.
|
||||
|
||||
### R5. Diagnostics and compatibility
|
||||
|
||||
- Invalid geometry, invalid numeric fields, duplicate identities, unsupported phase groups, and unmatched source references must fail before replacing valid output artifacts.
|
||||
- `enabled=false` suppresses a signal without requiring feature deletion, so automatic regeneration cannot accidentally resurrect an intentionally disabled assembly within the same edit lifecycle.
|
||||
- Existing areas without an editable signal layer must receive one on their next `intermediates` run. No migration of previously hand-edited traffic signal JSON is required.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] A clean `intermediates` run creates the editable traffic-signal GeoJSON, a GeoPackage layer with the same feature count, and a QGIS project layer with labels and directional symbols.
|
||||
- [ ] T junctions produce three editable features and cross junctions produce four, each with a unique deterministic `signal_uid`.
|
||||
- [ ] Moving one point in QGIS and changing its `display_id` and `heading_deg`, followed by `reimport,blender,cesium,preview`, changes only that signal assembly's placement/identity-facing metadata while preserving its vehicle stop point.
|
||||
- [ ] Re-running `blender` after reimport does not overwrite the QGIS-edited pole position or heading from OSM.
|
||||
- [ ] Setting one feature to disabled removes its static and dynamic signal assets while leaving the other signals intact.
|
||||
- [ ] Duplicate `signal_uid` or non-empty `display_id`, invalid geometry, and invalid placement fields abort reimport without partially replacing GeoJSON outputs.
|
||||
- [ ] Blender/Cesium node counts and ids match the enabled features in the final runtime JSON; lights and countdowns continue switching correctly.
|
||||
- [ ] Existing road GeoPackage import/reimport behavior and merged scene layer order remain unchanged.
|
||||
- [ ] Unit/integration tests cover stable ids, editable-feature validation, override-to-pose reconstruction, auxiliary GeoPackage round-trip, and stage ownership.
|
||||
|
||||
## Out Of Scope
|
||||
|
||||
- Preserving QGIS edits across a subsequent full `intermediates` rebuild; as with road edits, users must preserve or reapply edits before regenerating the GeoPackage.
|
||||
- A complete traffic-controller timing editor or arbitrary multi-phase signal program.
|
||||
- Independent editing of each lens or countdown glyph position; those remain derived from the assembly point, heading, and shared layout.
|
||||
- Automatically assigning a stable identity to a brand-new signal feature drawn manually in QGIS.
|
||||
|
||||
26
.trellis/tasks/08-07-qgis-traffic-signal-overrides/task.json
Normal file
26
.trellis/tasks/08-07-qgis-traffic-signal-overrides/task.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "qgis-traffic-signal-overrides",
|
||||
"name": "qgis-traffic-signal-overrides",
|
||||
"title": "QGIS traffic signal overrides",
|
||||
"description": "",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "dingkang",
|
||||
"assignee": "dingkang",
|
||||
"createdAt": "2026-08-07",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
Reference in New Issue
Block a user