Summary
Connector arrows in generated SVGs originate from the wrong point on their source element. The originating port of an edge is specified in the source file, but the SVG renderer never reads it — Ea::Svg::ConnectorRouter derives the source point from a bounds-based heuristic instead of consuming the stored connector port.
Observed in production SPAs (e.g. PLATEAU CityGML 2.0 / 3.0 on https://metanorma.github.io/plateau-models/citygml-2/): edges cut through element bodies and arrowheads detach from the box edge they should touch.
Mechanism
Ea::Model::DiagramConnector already models the port (lib/ea/model/diagram_connector.rb):
source_element_ref / source_duid / source_edge (int, element edge code)
target_element_ref / target_duid / target_edge
waypoints (EA's stored polyline — first/last points are the edge endpoints)
But:
- The renderer never consumes them.
grep -rn "source_edge|source_duid|target_edge" lib/ea/svg/ → zero hits. Ea::Svg::ConnectorRouter#source_point (connector_router.rb:45) computes the origin via edge_point / primary_edge / horizontal_exit? — a nearest-edge guess from source/target bounds — and the stored waypoints are not snapped to it.
- The QEA builder never populates them. Only the XMI builder assigns
source_edge (lib/ea/sources/xmi/diagram_builder.rb:165); lib/ea/sources/qea/diagram_builder.rb leaves source_edge/source_duid/target_edge/target_duid nil for QEA sources (the primary SPA pipeline). In generated shards every connector shows sourceEdge: null, sourceDuid: null while a non-empty waypoints polyline is present.
So for QEA models the router guesses; the file (which specifies the port) is unused on both levels.
Reproduction
Public model: models/20260227_current_plateau_v5.0.qea in https://github.com/metanorma/plateau-models (any diagram with connectors; e.g. 位置図_C0601, id 0016F797-D055-4717-AF1A-606413D0A166):
ea svg 位置図_C0601 models/20260227_current_plateau_v5.0.qea --output sample.svg
or view https://metanorma.github.io/plateau-models/citygml-2/index.html#/diagram/0016F797-D055-4717-AF1A-606413D0A166 — connector lines visibly pass through boxes and the arrow tail does not dock at the source element edge.
Suggested direction
- QEA
diagram_builder: populate source_edge/source_duid/target_edge/target_duid from the QEA connector geometry (and/or treat the first/last stored waypoints as authoritative edge endpoints).
ConnectorRouter: when source_edge (or a stored endpoint waypoint) is present, dock source_point/target_point to it and route from there; keep the current heuristic only as fallback for sources without port data.
Sibling rendering defect: #51 (TextRenderer nil→Float).
Summary
Connector arrows in generated SVGs originate from the wrong point on their source element. The originating port of an edge is specified in the source file, but the SVG renderer never reads it —
Ea::Svg::ConnectorRouterderives the source point from a bounds-based heuristic instead of consuming the stored connector port.Observed in production SPAs (e.g. PLATEAU CityGML 2.0 / 3.0 on https://metanorma.github.io/plateau-models/citygml-2/): edges cut through element bodies and arrowheads detach from the box edge they should touch.
Mechanism
Ea::Model::DiagramConnectoralready models the port (lib/ea/model/diagram_connector.rb):source_element_ref/source_duid/source_edge(int, element edge code)target_element_ref/target_duid/target_edgewaypoints(EA's stored polyline — first/last points are the edge endpoints)But:
grep -rn "source_edge|source_duid|target_edge" lib/ea/svg/→ zero hits.Ea::Svg::ConnectorRouter#source_point(connector_router.rb:45) computes the origin viaedge_point/primary_edge/horizontal_exit?— a nearest-edge guess from source/target bounds — and the storedwaypointsare not snapped to it.source_edge(lib/ea/sources/xmi/diagram_builder.rb:165);lib/ea/sources/qea/diagram_builder.rbleavessource_edge/source_duid/target_edge/target_duidnil for QEA sources (the primary SPA pipeline). In generated shards every connector showssourceEdge: null, sourceDuid: nullwhile a non-emptywaypointspolyline is present.So for QEA models the router guesses; the file (which specifies the port) is unused on both levels.
Reproduction
Public model:
models/20260227_current_plateau_v5.0.qeain https://github.com/metanorma/plateau-models (any diagram with connectors; e.g.位置図_C0601, id0016F797-D055-4717-AF1A-606413D0A166):or view https://metanorma.github.io/plateau-models/citygml-2/index.html#/diagram/0016F797-D055-4717-AF1A-606413D0A166 — connector lines visibly pass through boxes and the arrow tail does not dock at the source element edge.
Suggested direction
diagram_builder: populatesource_edge/source_duid/target_edge/target_duidfrom the QEA connector geometry (and/or treat the first/last stored waypoints as authoritative edge endpoints).ConnectorRouter: whensource_edge(or a stored endpoint waypoint) is present, docksource_point/target_pointto it and route from there; keep the current heuristic only as fallback for sources without port data.Sibling rendering defect: #51 (TextRenderer nil→Float).