Skip to content

Fix cursor frequency readout never matching VFO flag value (#1369)#1699

Closed
M7HNF-Ian wants to merge 1 commit into
aethersdr:mainfrom
M7HNF-Ian:fix/1369-cursor-freq-snap
Closed

Fix cursor frequency readout never matching VFO flag value (#1369)#1699
M7HNF-Ian wants to merge 1 commit into
aethersdr:mainfrom
M7HNF-Ian:fix/1369-cursor-freq-snap

Conversation

@M7HNF-Ian

Copy link
Copy Markdown
Contributor

Summary

Two bugs in SpectrumWidget combined to make the cursor frequency overlay always disagree with the VFO flag:

1. mhzToX() truncated instead of rounding
static_cast<int>(px) floors toward zero, so every VFO marker, filter edge, and spot pin was drawn up to 1 pixel left of its true frequency. Changed to std::round().

2. Cursor readout had no VFO snap
xToMhz(cursorPixel) maps a discrete pixel back to MHz. At typical zoom levels (1 MHz bandwidth, 800px wide) one pixel ≈ 1250 Hz, so hovering directly over a VFO marker could show a frequency several hundred Hz away from the flag value — the two could never be exactly equal.

Fix: if the cursor is within 8 px of any slice's VFO marker, the readout snaps to the radio-reported exact frequency. Elsewhere it continues to show the pixel-derived value.

Test plan

  • Hover cursor slowly over a VFO flag — readout should snap to match the flag frequency exactly when within ~8 px
  • Move cursor away from all flags — readout should show the interpolated pixel frequency normally
  • With two slices active, verify each snaps independently
  • Zoom in to narrow bandwidth — VFO marker should be visually centred on the correct frequency

🤖 Generated with Claude Code

…#1369)

Two changes in SpectrumWidget:

1. mhzToX() used static_cast<int>(px) which truncates toward zero, placing
   every VFO/filter/spot marker up to 1 pixel left of its true position.
   Changed to std::round() so markers are centred on the correct pixel.

2. The cursor frequency label computed xToMhz(cursorPixel) which maps a
   pixel back to MHz. Because pixels are discrete, hovering directly over a
   VFO marker still showed a slightly different value to what the VFO flag
   displayed (off by up to half a pixel's worth of bandwidth — kHz-scale
   on typical zoom levels). Added a snap: if the cursor is within 8 px of
   any slice's VFO marker, show the exact radio-reported frequency instead
   of the pixel-derived approximation. The readout now exactly matches the
   flag when near a VFO, and shows the pixel-derived value elsewhere.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@aethersdr-agent aethersdr-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice fix, @Chaosuk97 — both the rounding fix in mhzToX() and the cursor snap logic are clean and well-targeted. A couple of observations:

The std::round() change (line 1503) — Correct fix. The old static_cast<int> truncation gave a systematic leftward bias on the VFO marker, filter edges, and spot pins. std::round() centres them properly. No issues here.

The cursor snap loop (lines 3198–3204) — The approach is sound: iterate m_sliceOverlays, check pixel distance, snap if within 8 px. Two minor things to consider:

  1. mhzToX() called per slice per frame — This is inside the GPU render path (renderGpuFrame), so it runs every paint. With typical slice counts (1–4) this is negligible. If someone ever had an unusual number of slices it still wouldn't matter since mhzToX is just arithmetic. No concern here, just noting I checked.

  2. Snap priority with overlapping slices — If two VFO markers are within 16 px of each other (possible at very narrow zoom), the cursor snaps to whichever slice appears first in m_sliceOverlays. This seems fine for the use case — the user would need to be at an extreme zoom for this to matter, and the break ensures deterministic behaviour. Not worth over-engineering.

Scope check — Only SpectrumWidget.cpp changed, both hunks directly address #1369. No scope creep.

Potential merge conflict — PR #1694 (aetherclaude/issue-1690) also touches SpectrumWidget.cpp/.h. Whichever lands second will need a trivial rebase, but the changes are in different areas so it should be clean.

Overall this looks good to merge. Thanks for the contribution!

@ten9876

ten9876 commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Claude here — superseded by #1703 (just merged as 8c33310), which includes everything from this PR plus the setSliceOverlayFreq early-exit + markOverlayDirty() call. Same mhzToX round fix, same 8 px cursor snap.

Thanks for the fix Ian — since both came from you, no credit lost either way.

— 73, Jeremy KK7GWY & Claude (AI dev partner)

@ten9876 ten9876 closed this Apr 20, 2026
@M7HNF-Ian M7HNF-Ian deleted the fix/1369-cursor-freq-snap branch June 7, 2026 14:58
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