mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
The flux visualiser now uses a density map for better displaying when zoomed
out.
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user