Skip to content

feat(router/speedy): CH router visualization tool — CHQueryExporter + D3.js split-screen HTML#59

Draft
steffenaxer with Copilot wants to merge 13 commits into
tech-demo-chRouterfrom
copilot/implement-ch-router-visualization
Draft

feat(router/speedy): CH router visualization tool — CHQueryExporter + D3.js split-screen HTML#59
steffenaxer with Copilot wants to merge 13 commits into
tech-demo-chRouterfrom
copilot/implement-ch-router-visualization

Conversation

Copilot AI commented Apr 14, 2026

Copy link
Copy Markdown
  • Fix SpeedyALT phase info-box messages (were describing Dijkstra-like radial expansion; now describe ALT directed search with landmarks)
  • Add routeCost and routeLinks to Java exporter JSON output (CHQueryResult now stores bestCost)
  • Handle edge case: output null when no path found (POSITIVE_INFINITY guard)
  • Add route result info (path links count, travel cost) to final overlay HTML
  • Update showFinalOverlay() to display route results from JSON with backwards-compat fallback
  • Enlarge drawFinalOverlayToCanvas card (400×220 → 440×280) and add route info with separator line
  • Validate JS and CSS syntax
Original prompt

Visualisierungskonzept umsetzen

The user has attached the following files from their workspace:

  • matsim/tools/ch-viz/plan-chRouterVisualization.prompt.md

TITLE: CH-Router Visualization for Berlin Network (D3.js + Video Export)

USER INTENT: The user wants to save a detailed implementation plan as a prompt file for building an interactive visualization of the Contraction Hierarchies (CH) router algorithm, intended for a LinkedIn promotional post for iteratively.io.

TASK DESCRIPTION:
Build a two-component visualization system:

  1. Java Data Exporter (CHQueryExporter.java) that runs an instrumented CH query AND Dijkstra query on the Berlin network and exports step-by-step search state as JSON
  2. Standalone HTML/D3.js Visualization (ch-visualization.html) with:
    • Split-screen Dijkstra vs CH comparison (synchronized animation)
    • Shortcut unpacking animation showing how CH shortcuts decompose into real edges
    • Live statistics overlay showing search space savings
    • Dark theme with iteratively.io branding
    • Native WebM video export via MediaRecorder + canvas.captureStream(60fps)
    • 2.5D toggle showing hierarchy levels
    • Cinema mode for screen recording

EXISTING:

  • Plan file saved at: matsim/tools/ch-viz/plan-chRouterVisualization.prompt.md
  • Berlin network exists at: examples/scenarios/berlin/network.xml.gz (GK4 coordinate system, ~10k nodes)
  • Berlin config at: examples/scenarios/berlin/config.xml
  • All CH routing source code is already implemented in matsim/src/main/java/org/matsim/core/router/speedy/:
    • CHRouter.java — static bidirectional CH query (L152-321 for main loop, L368-394 for edge unpacking)
    • CHRouterTimeDep.java — time-dependent CATCHUp CH query (L178-380 for main loop, L429-448 for edge unpacking)
    • CHGraph.java — CH overlay graph with CSR layout, nodeLevel[], edgeOrigLink[], edgeLower1[], edgeLower2[]
    • CHBuilder.java — contraction hierarchy builder (~2848 lines, parallel ND-based contraction)
    • CHRouterFactory.java — factory with caching, ND ordering, TTF customization pipeline
    • CHTTFCustomizer.java — time-dependent TTF customization
    • CHCustomizer.java — static weight customization
    • SpeedyDijkstra.java — reference Dijkstra implementation (L110-178 for main loop)
    • SpeedyGraph.java — optimized graph data structure with spatial node ordering
    • SpeedyGraphBuilder.java — graph builder with Z-order Morton curve reordering

PENDING:

  • CHQueryExporter.java — New file at matsim/src/main/java/org/matsim/core/router/speedy/CHQueryExporter.java. Must:

    • Load Berlin network via NetworkUtils.readNetwork()
    • Build SpeedyGraph via SpeedyGraphBuilder.buildWithSpatialOrdering()
    • Build CHGraph via CHBuilder.build() + CHTTFCustomizer.customize()
    • Run instrumented CH query (copy loop from CHRouter.calcLeastCostPathImpl()) recording per-PQ-poll events: {step, dir, nodeIdx, cost, parentIdx, stalled, isMeeting}
    • Run instrumented Dijkstra query (copy loop from SpeedyDijkstra.calcLeastCostPathImpl()) recording per-PQ-poll events: {step, nodeIdx, cost}
    • Export shortcut unpack tree as nested JSON from edgeLower1/edgeLower2 arrays
    • Export all nodes with WGS84 coords (transform via TransformationFactory.getCoordinateTransformation("GK4", "WGS84")), nodeLevel[], and edges
    • Export final unpacked path with coordinates
    • Optional BBox filter to reduce to ~2000-4000 visible nodes
    • Output: ch-query-data.json
  • ch-visualization.html — New file at matsim/tools/ch-viz/ch-visualization.html. Must implement:

    • Split-screen layout (16:9): left=Dijkstra canvas, right=CH canvas, synchronized
    • Berlin network edges as thin dark gray lines via d3.geoMercator() projection
    • Animation loop via requestAnimationFrame with speed control
    • Dijkstra side: growing red/orange "cloud" of all settled nodes
    • CH side: slim bidirectional diamond (forward=blue #58a6ff, backward=orange #f78166)
    • Stall-on-demand visualization as gray flash
    • Meeting point golden glow pulse (#d29922)
    • Phase 2: shortcut unpacking animation (shortcuts split into children edges with morph transitions)
    • Final path as green animated-dash line (#3fb950)
    • Live counters: "Settled: X" + percentage on both sides
    • Final comparison overlay: "Dijkstra: N nodes — CH: M nodes → X% less search space"
    • Info boxes with phase explanations (fade in/out)
    • Dark theme (#0d1117 background, #1e2937 network edges)
    • iteratively.io watermark bottom-right
    • Controls: Play/Pause, Step, Speed slider (1x-20x), progress bar, Reset, 2.5D toggle
    • Cinema Mode button (hides controls, auto-plays with pauses between phases)
    • Record button: canvas.captureStream(60) + MediaRecorder (VP9/WebM) → auto-download ch-router-berlin.webm
    • Off-screen composite canvas for recording both panels
    • Off-screen base map canvas for performance (blit per frame)
    • OD pair dropdown with 3-...

Copilot AI and others added 2 commits April 14, 2026 16:52
Copilot AI changed the title [WIP] Implement CH-Router visualization system for Berlin network feat(router/speedy): CH router visualization tool — CHQueryExporter + D3.js split-screen HTML Apr 14, 2026
Copilot AI requested a review from steffenaxer April 14, 2026 16:56
… for proper WGS84 display

The mercatorY() function was returning radians while longitude was in degrees,
causing a ~100:1 aspect ratio distortion that squished the Berlin network into
a thin horizontal line. Now outputs degree-equivalent units (multiplied by
180/PI), matching the standard Web Mercator convention used by Leaflet and
OpenLayers. This makes the projection compatible with future slippy-map tile
overlays (OSM, Mapbox, etc.).

Agent-Logs-Url: https://github.com/steffenaxer/matsim-libs/sessions/82274a59-eb4c-410f-827e-4a5e09fb5b9b

Co-authored-by: steffenaxer <26229392+steffenaxer@users.noreply.github.com>
Copilot AI and others added 2 commits April 14, 2026 18:58
…, longer routes

- Replace custom canvas projection with Leaflet.js tile maps (OSM dark theme)
- Synchronized zoom/pan between both map panels
- Modern glassmorphism UI with Inter font, refined color palette
- Step slider (range input) for seeking forward/backward through events
- Forward/backward step buttons with arrow key support
- 2.5D mode applies CSS perspective transform to map containers
- Longer OD routes in Java exporter (Spandau→Marzahn, Frohnau→Lichtenrade, etc.)
- Canvas overlays on top of Leaflet for network/search visualization
- devicePixelRatio-aware rendering for HiDPI displays

Agent-Logs-Url: https://github.com/steffenaxer/matsim-libs/sessions/38e277ad-1a22-4836-b94e-ea1400fd85ff

Co-authored-by: steffenaxer <26229392+steffenaxer@users.noreply.github.com>
… features)

Agent-Logs-Url: https://github.com/steffenaxer/matsim-libs/sessions/38e277ad-1a22-4836-b94e-ea1400fd85ff

Co-authored-by: steffenaxer <26229392+steffenaxer@users.noreply.github.com>
…erflow:hidden

- Replace OSM tiles + broken CSS filter hack with CartoDB Dark Matter (natively dark)
- Remove aggressive invert/contrast filter that made map unreadable
- Add overflow:hidden to .panel to prevent 2.5D rotation from bleeding across panels

Agent-Logs-Url: https://github.com/steffenaxer/matsim-libs/sessions/2209a7e6-3f0c-46e7-ac0a-beaf405e1173

Co-authored-by: steffenaxer <26229392+steffenaxer@users.noreply.github.com>
…et internals

The canvas overlays had z-index:2 which is below Leaflet's internal tile pane
(z-index ~200) and overlay pane (~400). Raised canvas to z-index:1000,
info-box/watermark to 1001. Also properly positioned .leaflet-container with
position:absolute;inset:0 within .map-wrap.

Agent-Logs-Url: https://github.com/steffenaxer/matsim-libs/sessions/cd8a4f8f-93f0-4295-8084-125aea9324b0

Co-authored-by: steffenaxer <26229392+steffenaxer@users.noreply.github.com>
…ecording

- Dropdown: dark background (#1e2233) for select and option elements
- Final card: solid opaque background, brighter text (#fff/#cbd5e1), box-shadow
- Initial zoom: fit to query route (start/end/path) with pad(0.5) instead of
  entire network; re-fit when changing OD pair
- Video recording: composite map tiles + canvas overlays + labels + final card;
  enable CORS on tile layer for canvas tile rendering
- Added drawMapTilesToCanvas() and drawFinalOverlayToCanvas() helpers

Agent-Logs-Url: https://github.com/steffenaxer/matsim-libs/sessions/43f3115c-e0ff-417f-b3d4-c4ea795848ba

Co-authored-by: steffenaxer <26229392+steffenaxer@users.noreply.github.com>
Copilot AI and others added 2 commits April 14, 2026 20:31
…ay; info-boxes in video

Java exporter (CHQueryExporter):
- Switch to identity graph ordering (SpeedyGraphBuilder.build)
- Build SpeedyALTData (16 landmarks) for ALT heuristic
- Replace instrumented Dijkstra with instrumented SpeedyALT query
  (uses ALT estimation, dead-end pruning — matches SpeedyALT.java)
- Rename JSON field 'dijkstraEvents' → 'speedyALTEvents'

HTML visualization:
- Rename all 'Dijkstra' labels → 'SpeedyALT' (title, panels, phase
  messages, final overlay, video labels)
- Support both speedyALTEvents and dijkstraEvents JSON fields (backward compat)
- Draw info-box overlay text onto composite canvas during video recording
  (new drawInfoBoxToCanvas helper with rounded-rect pill background)
- Delay final overlay by ~2s after search ends so the route path is
  visible first (phase 0→1→2 state machine)
- Keep recording for 3s after final overlay appears to capture it

README: Updated to reflect SpeedyALT comparison

Agent-Logs-Url: https://github.com/steffenaxer/matsim-libs/sessions/b1cbd2a4-34d0-4967-9e33-d5d221f864be

Co-authored-by: steffenaxer <26229392+steffenaxer@users.noreply.github.com>
… variables

Agent-Logs-Url: https://github.com/steffenaxer/matsim-libs/sessions/b1cbd2a4-34d0-4967-9e33-d5d221f864be

Co-authored-by: steffenaxer <26229392+steffenaxer@users.noreply.github.com>
Copilot AI and others added 2 commits April 14, 2026 20:48
…nal overlay, enlarge card

- SpeedyALT phase messages now accurately describe ALT heuristic behavior
  (landmarks, directed search, fewer nodes than Dijkstra)
- Final overlay card enlarged from 400x220 to 440x280 and max-width 520px
- Route result info (links count, cost) added to HTML and canvas overlays
- Java exporter: add routeCost and routeLinks fields to JSON output
- CHQueryResult now stores bestCost for export

Agent-Logs-Url: https://github.com/steffenaxer/matsim-libs/sessions/facab8bc-3da3-42ec-9057-355df02c7305

Co-authored-by: steffenaxer <26229392+steffenaxer@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants