From efc0e4247ae2c7f00f924ce5eec155abaf2e4131 Mon Sep 17 00:00:00 2001 From: James Yuzawa Date: Thu, 26 Sep 2024 21:57:52 -0400 Subject: [PATCH] preserve waterfall during zooms and pans --- src/qtgui/plotter.cpp | 67 +++++++++++++++++++++++++++++++++++++------ src/qtgui/plotter.h | 9 ++++++ 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/qtgui/plotter.cpp b/src/qtgui/plotter.cpp index b3065006d..19254f673 100644 --- a/src/qtgui/plotter.cpp +++ b/src/qtgui/plotter.cpp @@ -382,6 +382,8 @@ void CPlotter::mouseMoveEvent(QMouseEvent* event) qint64 delta_hz = qRound64((qreal)delta_px * (qreal)m_Span / (qreal)w); if (delta_hz != 0) // update m_Xzero only on real change { + qint64 old_min_freq = getMinFrequency(); + qint64 old_max_freq = getMaxFrequency(); if (event->buttons() & Qt::MiddleButton) { m_CenterFreq += delta_hz; @@ -399,6 +401,7 @@ void CPlotter::mouseMoveEvent(QMouseEvent* event) m_Xzero = px; + moveWaterfall(old_min_freq, old_max_freq); updateOverlay(); } } @@ -552,6 +555,36 @@ void CPlotter::mouseMoveEvent(QMouseEvent* event) } +void CPlotter::moveWaterfall(qint64 old_min_freq, qint64 old_max_freq) +{ + if(m_WaterfallImage.isNull()) + { + return; + } + qint64 old_span = old_max_freq - old_min_freq; + qint64 new_min_freq = getMinFrequency(); + qint64 new_max_freq = getMaxFrequency(); + int waterfall_width = m_WaterfallImage.width(); + int waterfall_height = m_WaterfallImage.height(); + qreal ratio = (qreal)waterfall_width / (qreal)old_span; + qint64 new_left = qRound((qreal)(new_min_freq - old_min_freq) * ratio); + qint64 new_right = qRound((qreal)(new_max_freq - old_min_freq) * ratio); + qint64 new_width = new_right - new_left; + // Shift left or right + m_WaterfallImage = m_WaterfallImage.copy(new_left, 0, new_width, waterfall_height); + // Zoom in or out + if(new_width != waterfall_width) + { + m_WaterfallImage = m_WaterfallImage.scaled(waterfall_width, waterfall_height, Qt::IgnoreAspectRatio, + new_width < waterfall_width ? Qt::FastTransformation : Qt::SmoothTransformation); + } + if (msec_per_wfline > 0) + { + clearWaterfallBuf(); + } +} + + int CPlotter::getNearestPeak(QPoint pt) { int px = qRound((qreal)pt.x() * m_DPR); @@ -832,6 +865,9 @@ void CPlotter::zoomStepX(float step, int x) return; } + qint64 old_min_freq = getMinFrequency(); + qint64 old_max_freq = getMaxFrequency(); + // calculate new range shown on FFT float new_span = std::min( (float)m_Span * (float)step, (float)m_SampleFreq); @@ -868,13 +904,14 @@ void CPlotter::zoomStepX(float step, int x) // Explicitly set m_Span instead of calling setSpanFreq(), which also calls // setFftCenterFreq() and updateOverlay() internally. Span needs to be set // before frequency limits can be checked in setFftCenterFreq(). - m_Span = new_span; + m_Span = new_span_int; setFftCenterFreq(qRound64((f_max + f_min) / 2.0f)); m_MaxHoldValid = false; m_MinHoldValid = false; m_histIIRValid = false; + moveWaterfall(old_min_freq, old_max_freq); updateOverlay(); double zoom = (double)m_SampleFreq / (double)m_Span; @@ -1937,8 +1974,8 @@ void CPlotter::drawOverlay() static const qreal nLevels = h / (levelHeight + slant); if (m_BookmarksEnabled) { - tags = Bookmarks::Get().getBookmarksInRange(m_CenterFreq + m_FftCenter - m_Span / 2, - m_CenterFreq + m_FftCenter + m_Span / 2); + tags = Bookmarks::Get().getBookmarksInRange(getMinFrequency(), + getMaxFrequency()); } else { @@ -1946,8 +1983,8 @@ void CPlotter::drawOverlay() } if (m_DXCSpotsEnabled) { - QList dxcspots = DXCSpots::Get().getDXCSpotsInRange(m_CenterFreq + m_FftCenter - m_Span / 2, - m_CenterFreq + m_FftCenter + m_Span / 2); + QList dxcspots = DXCSpots::Get().getDXCSpotsInRange(getMinFrequency(), + getMaxFrequency()); QListIterator iter(dxcspots); while(iter.hasNext()) { @@ -2009,8 +2046,8 @@ void CPlotter::drawOverlay() if (m_BandPlanEnabled) { - QList bands = BandPlan::Get().getBandsInRange(m_CenterFreq + m_FftCenter - m_Span / 2, - m_CenterFreq + m_FftCenter + m_Span / 2); + QList bands = BandPlan::Get().getBandsInRange(getMinFrequency(), + getMaxFrequency()); m_BandPlanHeight = metrics.height() + VER_MARGIN; for (auto & band : bands) @@ -2075,7 +2112,7 @@ void CPlotter::drawOverlay() } // Frequency grid - qint64 StartFreq = m_CenterFreq + m_FftCenter - m_Span / 2; + qint64 StartFreq = getMinFrequency(); QString label; label.setNum(float((StartFreq + m_Span) / m_FreqUnits), 'f', m_FreqDigits); calcDivSize(StartFreq, StartFreq + m_Span, @@ -2323,7 +2360,9 @@ void CPlotter::setCenterFreq(quint64 f) { if((quint64)m_CenterFreq == f) return; - + + qint64 old_min_freq = getMinFrequency(); + qint64 old_max_freq = getMaxFrequency(); qint64 offset = m_CenterFreq - m_DemodCenterFreq; m_CenterFreq = f; @@ -2334,6 +2373,7 @@ void CPlotter::setCenterFreq(quint64 f) m_histIIRValid = false; m_IIRValid = false; + moveWaterfall(old_min_freq, old_max_freq); updateOverlay(); } @@ -2347,32 +2387,41 @@ void CPlotter::updateOverlay() /** Reset horizontal zoom to 100% and centered around 0. */ void CPlotter::resetHorizontalZoom(void) { + qint64 old_min_freq = getMinFrequency(); + qint64 old_max_freq = getMaxFrequency(); setFftCenterFreq(0); setSpanFreq((qint32)m_SampleFreq); emit newZoomLevel(1.0); m_MaxHoldValid = false; m_MinHoldValid = false; m_histIIRValid = false; + moveWaterfall(old_min_freq, old_max_freq); updateOverlay(); } /** Center FFT plot around 0 (corresponds to center freq). */ void CPlotter::moveToCenterFreq() { + qint64 old_min_freq = getMinFrequency(); + qint64 old_max_freq = getMaxFrequency(); setFftCenterFreq(0); m_MaxHoldValid = false; m_MinHoldValid = false; m_histIIRValid = false; + moveWaterfall(old_min_freq, old_max_freq); updateOverlay(); } /** Center FFT plot around the demodulator frequency. */ void CPlotter::moveToDemodFreq() { + qint64 old_min_freq = getMinFrequency(); + qint64 old_max_freq = getMaxFrequency(); setFftCenterFreq(m_DemodCenterFreq-m_CenterFreq); m_MaxHoldValid = false; m_MinHoldValid = false; m_histIIRValid = false; + moveWaterfall(old_min_freq, old_max_freq); updateOverlay(); } diff --git a/src/qtgui/plotter.h b/src/qtgui/plotter.h index e6277df8a..22e3cd666 100644 --- a/src/qtgui/plotter.h +++ b/src/qtgui/plotter.h @@ -213,6 +213,15 @@ public slots: MARKER_B }; + qint64 getMinFrequency() const { + return m_CenterFreq + m_FftCenter - m_Span / 2; + } + + qint64 getMaxFrequency() const { + return m_CenterFreq + m_FftCenter + m_Span / 2; + } + + void moveWaterfall(qint64 old_min_freq, qint64 old_max_freq); void drawOverlay(); void makeFrequencyStrs(); int xFromFreq(qint64 freq);