News:

Simutrans Wiki Manual
The official on-line manual for Simutrans. Read and contribute.

Show a line's real route on the main map

Started by victor_18993, July 23, 2026, 09:56:02 PM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

victor_18993

Right now Simutrans tells you a line's stops, but not the path its vehicles actually take between them.
On a simple network you can guess it; on a dense one with parallel tracks, one-way sections and waypoints,
you often can't. I would like to add an optional overlay that draws the real route of a selected line on the
main isometric map, so you can see where it goes, in what order it visits its stops, where the two directions
differ, and where a segment has no valid route at all.

I want to be honest about what already exists, because this proposal is deliberately built on top of it
rather than reinventing anything:

- The minimap already draws line routes, but as straight stop-to-stop segments in 2D, not the real path over
  the rails, and not on the main view.
- The schedule editor already highlights a schedule's stop tiles on the main 3D map (visualize_schedule),
  reusing the existing highlight and marked flags. It highlights the stops, not the path between them.

So what I am proposing is essentially the schedule highlight applied to a whole line's real route: same
proven rendering mechanism (the existing per-object highlight and per-tile marked flags, cleared when the
window closes), but the tiles that get highlighted are the ones the engine's own pathfinder returns, not
straight lines. The route would be computed with the real routing code (route_t::calc_route), segment by
segment between consecutive schedule entries, so it follows real track, respects one-way masks and signals,
and can honestly show a segment as broken when there is no route.

One real design question I would like your opinion on. A route in Simutrans is not a property of the line, it
is a property of a vehicle: electrification, minimum-speed signals and one-way rules can make the same
schedule route differently for different convoys, and a line can have convoys that differ. For a first
version I would compute the route of the line's first active convoy and label it clearly as such, and for a
line with no convoys fall back to straight dotted stop-to-stop segments marked as approximate. I think that
is the honest minimum, but I would rather hear your view than guess.

What I am NOT proposing, to keep the scope small and safe:

- no savegame format change, and no persistent state of any kind
- no change to how convoys move or how routes are calculated
- no new overlay architecture and no new classes; it reuses the highlight/marked flags
- the route is computed once when you turn the view on (never per frame, since the pathfinder cannot run
  inside the display step), cached, and cleared when you close the window or switch line
- one line at a time, opt-in from a single button on the line window, off by default
- it stays purely local and visual, so it is safe in network games

Direction arrows on the main map, distinguishing overlapping there-and-back on the same track, and later
diagnostics (where electrification ends, a platform too short, a blocked segment) are natural follow-ups, but
I deliberately left them out of the first version.

Before I write any code I would like to know: do you want this real-path-on-main-map view at all, given the
minimap and schedule-highlight precedents? And does computing the first active convoy's route sound like the
right representative choice, or would you frame it differently? I would rather agree the shape first and then
send a small, focused patch.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

prissi

Some things to consider:
1) Routes cannot caluclate in the GUI code, since it runs in sync_steps while route calculation can only run in a step (since there is only on static mapping and bucket list). Hence, one would need an internal tool that highlight the route as those are run in a step. Certainly doable, adds some overhead.
2) Also, some routes, like ships can be very long and take longer to computer. Also water tiles do not highlight as they have no way. Same for airplanes. (Also routes change on runway utilisation there) and there are routes which are not on ways too.
3) I would suggest a second highlighting color for way in that case, so one can see the stop. Otherwise the stop cannot be change easily.



victor_18993

Thanks, this gives me a much clearer direction.

I agree that the route calculation should not live in the GUI path. I will rework the prototype so that the GUI only requests the operation, while an internal tool performs the route calculation during a proper step and then stores the result for display.

I will also separate the route overlay from the stop highlighting instead of trying to reuse the same highlight state. A second colour should make the route and its scheduled stops much easier to distinguish and avoid the current interaction between both highlights.

For water, aircraft and route sections without a way, I will not assume that every route tile can be highlighted as infrastructure. I will first define how those unsupported or non-way sections should be represented, and I will include long ship routes in the performance tests before extending the patch.

I will keep the current version as a proof of concept and make these architectural changes in the next iteration. Thanks for pointing out the step/sync-step distinction and the cases that the current prototype does not cover.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

victor_18993

Hi prissi, and everyone following the thread,

Thank you for the detailed feedback earlier. I took the direction you gave and built a first functional slice around it, rather than keep piling onto the prototype. I would really like your read on the architecture and the visual approach before I extend the scope any further.

This is a first cut, not a finished solution. It is meant to be reviewed.

What changes

The route no longer borrows the obj_t::highlight bit. That bit is now left entirely to the stops. The route geometry is kept in a separate, display-only overlay, and the stops keep their red highlight through the existing mechanism. So route and stops are now two independent channels: a tile can be on the route without being flagged, and a stop stays flagged whether or not the route passes through it.

The route is drawn in the owning player's colour, so different companies' lines read differently. Outward and return legs are shown on opposite lanes, so a there-and-back line reads as two parallel lines instead of one line drawn twice. That directional offset reuses the engine's existing driveleft offset table, with the travel direction taken from ribi_t::get_dir, so the return leg lands on the opposite side by construction.

How it fits the architecture

I tried hard to stay inside how Simutrans already works rather than bolt on a parallel graphics system.

The route is no longer computed from the GUI or in sync_step. Toggling the overlay from the line window only issues a small local tool; the actual pathfinding runs later, inside a normal tool step. The world holds the resulting path as temporary visual state, and main_view_t::display draws it procedurally. Nothing is serialized, nothing touches routing, the schedule or determinism, and the overlay is cleared on new map, load and rotate90.

Visual finish

The stroke is a player-colour core with a discreet dark outline and slightly rounded joins and ends, so it reads on both dark and light ground without hiding the way underneath. The exact weight, halo and brightness are a first, conservative proposal — very much open to your taste.

Validation

Rebased onto r12102. Clean build, and the product patch also builds in isolation. The small dedicated bench passes 8/8 (including the check that route and stop channels stay independent), the standard test suite passes 201/201, and a determinism run comes out identical. I checked the visuals on dark and on snow-covered (light) terrain, on straights, diagonals, a loop, a there-and-back, and at near and far zoom.

Current scope

This first slice deliberately does not include ships, aircraft, or route sections with no way under them yet. Automatic invalidation after a schedule edit is also not wired up, so for now the overlay reflects the route as of the last time it was toggled on, and there is no distinct marker for broken legs. I did not want to guess at those before the core representation is settled.

One honest note on left-hand driving: the lane offset reuses the engine's own table and should be correct by construction, but a clean visual check on a map created with left-hand traffic from the start is still pending. I would rather flag that than claim it is verified.

What I would appreciate your view on

- whether keeping the route in a separate display-only overlay fits the architecture you have in mind;
- whether the small accessor I added on vehicle_base_t (to reuse the lane offset table) is acceptable, or whether you would prefer it exposed differently;
- whether the drawing belongs in main_view_t::display or somewhere else;
- whether the visual finish is going in the right direction;
- and whether it is worth continuing next with no-way sections and schedule-edit invalidation.

I will hold off on extending the scope until I hear what you think. Thanks again for the guidance.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

victor_18993

First reviewable implementation: showing a line's real route on the main map
Thanks for the earlier feedback and for pointing me towards using the real route and the existing directional offsets.
I have now prepared a first reviewable implementation following that direction and keeping it inside the current Simutrans architecture.
The main change is that the route no longer reuses
obj_t::highlight.
Instead, the calculated path is stored as a temporary display-only overlay in the world. The stops keep their existing red highlight, so the route and the stops now use two independent visual channels.
The GUI does not calculate or own the route. The button only activates a tool, the tool calculates the real route, the world stores the temporary overlay state, and
main_view_t::display draws it.
The route:
  • uses the player colour;
  • follows the actual calculated tiles;
  • places outbound and return directions on opposite sides;
  • reuses the existing driving-side offset table;
  • resolves directional offsets at shared nodes, so the lines remain continuous through corners instead of crossing;
  • uses a small bevel at normal turns and a compact return connection for 180-degree reversals.
I also added a conservative visual treatment: a two-pixel player-coloured core, a thin dark outline and small rounded joins. This is only a first visual proposal and I am completely open to changing the thickness, brightness or outline if another style would fit Simutrans better.
The overlay is not saved and does not affect routing, simulation state or determinism. It is cleared together with its stop highlights and active line identity when the map is initialised, loaded or rotated.
Failed route sections are now separated explicitly, so the renderer cannot accidentally connect two valid sections across an unroutable gap.
The line-management buttons also read the active overlay state from the world. This avoids inconsistent states when several line windows are open: switching from one line to another updates the real active line, and closing an unrelated window does not remove the currently displayed route.
The current patch is based on
r12102 and contains only the ten product files. The test scaffolding is separate and is not included in the attached patch.
Validation completed:
  • isolated Release build of the product patch on a clean
    r12102;
  • no new warnings in the modified product files;
  • dedicated route-overlay bench: 10/10;
  • standard suite: 201/201;
  • deterministic repeated runs;
  • visual checks on dark and light terrain, loops, diagonals, reversals and long schedules.
The current scope is intentionally limited. It does not yet include:
  • ships;
  • aircraft;
  • routes without a way;
  • automatic invalidation after editing a schedule;
  • a special marker for broken route sections;
  • more than one route overlay at a time.
Before extending it further, I would appreciate feedback on the architecture, especially:
  • whether keeping the temporary overlay state in
    karte_t is acceptable;
  • whether drawing it from
    main_view_t::display is the right place;
  • whether the small public accessor for the existing driving-side offsets is acceptable;
  • whether the node-based joins and the proposed visual style are going in the right direction;
  • and whether the next step should be routes without a way or automatic invalidation after schedule changes.
I am attaching the product patch and a few screenshots showing the independent route and stop highlights, directional lanes, corners and the dark/light terrain comparison.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

prissi

Impressive, but some comments:

It should work with normal schedules too, not only lines, and better automatically and update when a schedule updates, like the current stop highliting. I know that is some extra work. To make it easier, after each schedule change tool is doing its ::work, it could check whether the displayed schedule is the current and update this.

The state machine of some vehicles is changed after calcualting a route (convois after choose signals or overtaking, and airplanes totally). So you cannot use the front vehicle as test_driver since its state would be different afterwards but need to allocate a new one.

Better treat all curves as diagonals as routes going diagonal stretches look like staircases. For this, the route also can return a ribi, which would indicate the required direction. This would probably solve also the current "hanging corner" problem.

victor_18993

Thank you, these comments are very helpful.

I agree that the overlay should not be limited to lines. I will generalise it so that it can display both line schedules and standalone convoy schedules. I will also make it update automatically after a successful schedule change, but only when the modified schedule is the one currently being displayed.

I will replace the current use of the convoy's front vehicle as the test driver. The revised implementation will create a separate temporary vehicle based on the representative vehicle descriptor, so route probing cannot alter the state of a real convoy. I will pay particular attention to choose signals, overtaking and the specialised aircraft route calculation.

For the rendering, I will preserve the ribi returned by the calculated route instead of reconstructing the direction only from adjacent coordinates. Curves will then be rendered as diagonal stretches where appropriate, which should also address the staircase and hanging-corner problems.

These changes require some restructuring of the prototype, especially changing the stored overlay identity from line-only to a general schedule source. I will prepare a revised patch and regression tests before posting the next version.

Thanks again for pointing me in the right direction.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

prissi

Do not worry about chose signals. That routes may diverge is ok, that is their purpose. Just use the return of test driver. Make sure, that the test driver has the same owner, as route with private signs may otherwise differ.

victor_18993

Hello prissi,

I have reduced and revised the proposal following your feedback.

The feature now works for both sources:

- a line schedule, from the line-management window;
- an individual convoy schedule, from the convoy-information window.

Both use a small "Show route on map" button. The route is calculated with a disposable vehicle probe of the correct subclass and drawn as a display-only overlay. It does not modify the real convoy, reservations, savegames or synchronized network state.

The revised implementation also:

- keeps the route ribi, so diagonal stretches are drawn as straight diagonals instead of a staircase;
- highlights scheduled stops through the existing, separate highlight channel;
- updates automatically after line, convoy or individual-schedule changes;
- follows a convoy requester when it changes line or becomes lineless;
- reacts centrally when representative convoy membership changes, including depot sales, line deletion, automatic trimming and direct AI/internal calls;
- chooses another usable convoy when the representative disappears, or clears the overlay when none remains.

The route calculation preserves the relevant convoy context, including ownership, electrification, speed and convoy length. The maximum platform-search length matches the vehicle family: road uses convoy length, rail uses convoy length or 8888 according to stop_halt_as_scheduled, and water uses zero. Aircraft keep their existing air_vehicle_t routing path.

Validation:

- clean MinGW64 build;
- automated deterministic bench: 24 PASS, 1 SKIP, 0 FAIL;
- road, rail, monorail and ship validated end-to-end;
- exact overlay trace compared with an independent, non-destructive oracle;
- requester, deletion, line-change, broken-leg and diagonal-route regressions covered;
- visual validation performed in-game.

The single SKIP is the aircraft end-to-end scenario: pak64 rejects scripted airport-stop placement on the flat headless fixture. The aircraft code path is selected, but I am not claiming a complete aircraft test.

The attached patch contains only the 15 product files and is based on r12103 (315c9cf66). The test-only scripting hooks and temporary screenshot tour are not included.

I would appreciate feedback on whether this reduced architecture is suitable for upstream, particularly:

1. whether the transient overlay state belongs on karte_t;
2. whether the lifecycle notifications from convoi_t/simline_t are acceptable;
3. whether the same button in line and convoy windows is the desired UI.

Regards
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)