The flux visualiser now uses a density map for better displaying when zoomed

out.
This commit is contained in:
David Given
2022-08-06 18:41:08 +02:00
parent 9a5c66a311
commit 4f8c68c40d
2 changed files with 98 additions and 20 deletions

View File

@@ -13,8 +13,9 @@ DECLARE_COLOUR(FOREGROUND, 0, 0, 0);
DECLARE_COLOUR(FLUX, 64, 64, 255); DECLARE_COLOUR(FLUX, 64, 64, 255);
DECLARE_COLOUR(RECORD, 255, 255, 255); DECLARE_COLOUR(RECORD, 255, 255, 255);
const int BORDER = 10; const int BORDER = 4;
const int MINIMUM_TICK_DISTANCE = 10; const int MINIMUM_TICK_DISTANCE = 10;
const double RENDER_LIMIT = 3000.0;
FluxViewerControl::FluxViewerControl(wxWindow* parent, FluxViewerControl::FluxViewerControl(wxWindow* parent,
wxWindowID id, wxWindowID id,
@@ -50,15 +51,48 @@ void FluxViewerControl::SetFlux(std::shared_ptr<const TrackFlux> flux)
auto size = GetSize(); auto size = GetSize();
_nanosecondsPerPixel = (double)_totalDuration / (double)size.GetWidth(); _nanosecondsPerPixel = (double)_totalDuration / (double)size.GetWidth();
ResizeScrollbar(); UpdateScale();
Refresh(); Refresh();
} }
void FluxViewerControl::ResizeScrollbar() void FluxViewerControl::UpdateScale()
{ {
auto size = GetSize(); auto size = GetSize();
nanoseconds_t thumbSize = size.GetWidth() * _nanosecondsPerPixel; nanoseconds_t thumbSize = size.GetWidth() * _nanosecondsPerPixel;
_scrollbar->SetScrollbar(_scrollPosition/1000, thumbSize/1000, _totalDuration/1000, thumbSize/2000); _scrollbar->SetScrollbar(_scrollPosition/1000, thumbSize/1000, _totalDuration/1000, thumbSize/2000);
int totalPixels = (_totalDuration / _nanosecondsPerPixel) + 1;
if ((totalPixels != _densityMap.size()) && (_nanosecondsPerPixel > RENDER_LIMIT))
{
_densityMap.resize(totalPixels);
std::fill(_densityMap.begin(), _densityMap.end(), 0.0);
int i = 0;
for (const auto& trackdata : _flux->trackDatas)
{
FluxmapReader fmr(*trackdata->fluxmap);
while (!fmr.eof())
{
unsigned ticks;
if (!fmr.findEvent(F_BIT_PULSE, ticks))
break;
int fx = fmr.tell().ns() / _nanosecondsPerPixel;
_densityMap.at(i + fx)++;
}
i += trackdata->fluxmap->duration() / _nanosecondsPerPixel;
}
double max = *std::max_element(_densityMap.begin(), _densityMap.end());
for (auto& d : _densityMap)
d /= max;
}
}
static int interpolate(int lo, int hi, float factor)
{
float range = hi - lo;
return lo + range*factor;
} }
void FluxViewerControl::OnPaint(wxPaintEvent&) void FluxViewerControl::OnPaint(wxPaintEvent&)
@@ -128,6 +162,20 @@ void FluxViewerControl::OnPaint(wxPaintEvent&)
tickCount++; tickCount++;
} }
if (x <= 0)
dc.DrawText(
fmt::format("{}us", (int)(_scrollPosition / 1000LL)),
{ BORDER, t3y + ch2/2 }
);
if ((x+fw) >= w)
{
wxString text = fmt::format(
"{}us", (int)((_scrollPosition + (w * _nanosecondsPerPixel)) / 1000LL));
auto size = dc.GetTextExtent(text);
dc.DrawText(text, { w - size.GetWidth() - BORDER, t3y + ch2/2 });
}
/* Sector blocks. */ /* Sector blocks. */
for (const auto& sector : trackdata->sectors) for (const auto& sector : trackdata->sectors)
@@ -155,26 +203,55 @@ void FluxViewerControl::OnPaint(wxPaintEvent&)
/* Flux chart. */ /* Flux chart. */
dc.SetPen(FLUX_PEN); dc.SetPen(FLUX_PEN);
dc.DrawLine({x, t4y}, {x+fw, t4y}); if (_nanosecondsPerPixel > RENDER_LIMIT)
FluxmapReader fmr(*trackdata->fluxmap);
while (!fmr.eof())
{ {
int event; /* Draw using density map. */
unsigned ticks;
fmr.getNextEvent(event, ticks);
int fx = fmr.tell().ns() / _nanosecondsPerPixel; dc.SetPen(*wxTRANSPARENT_PEN);
for (int fx = 0; fx < _densityMap.size(); fx++)
if (event & F_BIT_INDEX)
{ {
dc.SetPen(INDEX_SEPARATOR_PEN); if (((x+fx) > 0) && ((x+fx) < w))
dc.DrawLine({x+fx, 0}, {x+fx, h}); {
dc.SetPen(FLUX_PEN); float density = _densityMap[fx];
wxColour colour(
interpolate(BACKGROUND_COLOUR.Red(), FLUX_COLOUR.Red(), density),
interpolate(BACKGROUND_COLOUR.Green(), FLUX_COLOUR.Green(), density),
interpolate(BACKGROUND_COLOUR.Blue(), FLUX_COLOUR.Blue(), density));
wxBrush brush(colour);
dc.SetBrush(brush);
dc.DrawRectangle({x+fx, t4y - ch2}, {1, ch});
}
} }
if (event & F_BIT_PULSE)
dc.DrawLine({x+fx, t4y - ch2}, {x+fx, t4y + ch2});
} }
else
{
/* Draw discrete pulses. */
FluxmapReader fmr(*trackdata->fluxmap);
while (!fmr.eof())
{
int event;
unsigned ticks;
fmr.getNextEvent(event, ticks);
int fx = fmr.tell().ns() / _nanosecondsPerPixel;
if (((x+fx) > 0) && ((x+fx) < w))
{
if (event & F_BIT_INDEX)
{
dc.SetPen(INDEX_SEPARATOR_PEN);
dc.DrawLine({x+fx, 0}, {x+fx, h});
dc.SetPen(FLUX_PEN);
}
if (event & F_BIT_PULSE)
dc.DrawLine({x+fx, t4y - ch2}, {x+fx, t4y + ch2});
}
}
}
dc.SetPen(FLUX_PEN);
dc.DrawLine({x, t4y}, {x+fw, t4y});
} }
x += w; x += w;
@@ -193,7 +270,7 @@ void FluxViewerControl::OnMouseWheel(wxMouseEvent& event)
_nanosecondsPerPixel *= 1.2; _nanosecondsPerPixel *= 1.2;
_scrollPosition -= x * _nanosecondsPerPixel; _scrollPosition -= x * _nanosecondsPerPixel;
ResizeScrollbar(); UpdateScale();
Refresh(); Refresh();
} }

View File

@@ -21,7 +21,7 @@ public:
void SetFlux(std::shared_ptr<const TrackFlux> flux); void SetFlux(std::shared_ptr<const TrackFlux> flux);
private: private:
void ResizeScrollbar(); void UpdateScale();
private: private:
void OnPaint(wxPaintEvent&); void OnPaint(wxPaintEvent&);
@@ -34,6 +34,7 @@ private:
nanoseconds_t _scrollPosition; nanoseconds_t _scrollPosition;
nanoseconds_t _totalDuration; nanoseconds_t _totalDuration;
double _nanosecondsPerPixel; double _nanosecondsPerPixel;
std::vector<float> _densityMap;
wxDECLARE_EVENT_TABLE(); wxDECLARE_EVENT_TABLE();
}; };