Skip to content

Fix: legend/basemap settings not persisted + coordinate drift on repeated saves#16

Open
flamuf wants to merge 5 commits into
OpenWaterAnalytics:mainfrom
flamuf:main
Open

Fix: legend/basemap settings not persisted + coordinate drift on repeated saves#16
flamuf wants to merge 5 commits into
OpenWaterAnalytics:mainfrom
flamuf:main

Conversation

@flamuf

@flamuf flamuf commented Jul 10, 2026

Copy link
Copy Markdown

This PR fixes two related persistence bugs where display settings are
saved to the project .ini file but never correctly restored on reopen:

  1. Legend interval thresholds (NodeIntervals/LinkIntervals) - only
    colors were being saved, never the numeric threshold values that
    define which value range maps to which legend color.

  2. Basemap grayscale/brightness style - neither was being persisted
    at all.

Root cause: both settings were being read too early in the load
sequence, before later initialization steps (InitThemes for legend
intervals, LoadBasemapFromWeb for basemap style) overwrite them with
defaults. The fix adds two new restore functions
(ReadLegendIntervals, ReadBasemapStyle) called at the correct point
in InitFormContents, after the respective reset happens.

Tested manually: legend thresholds and basemap grayscale/brightness
now correctly survive save -> close -> reopen.

Update: This PR now also includes a fix for a separate issue (#15) -
coordinate rounding drift on repeated saves. See details below.

Fixes #15 (follow-up to the Save() fix suggested there).

The originally suggested fix for #15 works, but transforms coordinates
through PROJ on every save (native EPSG -> WGS84 -> native EPSG). Since
each transform introduces a small floating-point rounding error, this
accumulates with repeated saves - nodes that started very close
together can drift apart or overlap after enough save cycles.

This adds a different approach: node, vertex, and label coordinates in
their native (pre-transform) CRS are cached exactly once, right before
the first transform to WGS84 happens. Save() then writes out these
pristine cached values directly - no transform call involved - and
restores the live WGS84 display values afterward.

Tested manually over many repeated save/close/reopen cycles with a
network using Swiss LV95 (EPSG:2056) coordinates - no drift observed.

@flamuf flamuf changed the title Fix: legend interval thresholds and basemap grayscale/brightness not persisted Fix: legend/basemap settings not persisted + coordinate drift on repeated saves Jul 11, 2026
@LRossman

Copy link
Copy Markdown
Collaborator

Unfortunately the coordinate caching code is incomplete since it doesn't handle the cases where the UI user adds a new object, deletes an object, moves an object or edits a link's vertices. I also feel that it adds a lot of specialized code to address a rather infrequently occurring issue (a lot of users might be running their models without using a web basemap).

Two alternative approaches that might avoid any coordinate drift are:

  1. Save the re-transformed coordinates to file using more significant figures (would require making changes to EPANET's EN_saveinpfile function).
  2. Transform the original EPSG coordinates to WGS84 on the fly each time the network map is redrawn (although I doubt this would be performant).

@flamuf

flamuf commented Jul 13, 2026

Copy link
Copy Markdown
Author

Thanks for taking the time to look at this and for the honest feedback - you're
right that the caching approach doesn't handle add/delete/move/
vertex-edit, and I agree that silently discarding an edit on save would
be worse than the original drift issue.

I ran some rough comparisons of zoom performance with a web basemap
active. For what it's worth, EPSG:4326 (no coordinate transform needed
at all) showed the same noticeable lag as EPSG:2056, and even the
official 1.0.2 build showed similar lag with a web basemap active
(a local image basemap, by contrast, felt smooth). I'm not familiar
enough with the rest of the codebase to know if that's meaningful,
but it made me wonder whether the lag might be coming from somewhere
in the tile loading/refresh path rather than from coordinate transform work
itself - in which case option 2 might end up adding transform overhead
on top of an unrelated existing bottleneck.

If it's helpful, it could be worth trying to make the cache reactive
instead of static - updating the cached coordinate at the same points
in the code that already set HasChanged := true (on move/add/delete/
vertex edit), so it never goes stale relative to what the user is
editing, without needing a transform on every redraw.

There might also be a cleaner longer-term option: keeping the native
coordinates as the single source of truth always, and splitting the
transform into two stages at render time - native to WGS84 (the
expensive PROJ step) done once when the basemap loads, and WGS84 to
screen pixels (cheap, no PROJ needed) done on every redraw. That would
avoid touching the stored coordinates at all, but it's a bigger change
to the rendering path I think... .

Thank you much for the feedback.

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.

Map view corrupts after Save when using EPSG:2056 (Swiss LV95) coordinates

2 participants