feat(qgis): add editable traffic signal assemblies
This commit is contained in:
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.
|
||||
|
||||
Reference in New Issue
Block a user