Files
RTT/histogramchart.cpp
2019-11-12 16:15:15 +01:00

141 lines
3.2 KiB
C++

#include "histogramchart.h"
#include <cmath>
#include <QPen>
#include <QPainter>
HistogramChart::HistogramChart(QQuickItem *parent)
: QQuickPaintedItem(parent)
{
}
void HistogramChart::paint(QPainter* painter)
{
const int leftPadding = 32;
const int bottomPadding = 32;
const int height = static_cast<int>(this->height());
const int width = static_cast<int>(this->width());
painter->fillRect(0, 0, width, height, Qt::white);
if (_histogram.empty()) {
return;
}
const qreal barHeight = height - bottomPadding;
const qreal barWidth = (width - leftPadding) / static_cast<qreal>(_histogram.size());
for (size_t i = 0; i < _histogram.size(); i++) {
int count = _histogram[i];
qreal h = (count / static_cast<qreal>(maxBinCount)) * barHeight;
qreal x = i * barWidth;
qreal y = barHeight - h;
const QColor darkBlue = QColor::fromRgb(32, 74, 135);
const QColor lightBlue = QColor::fromRgb(52, 101, 164);
const QColor lighterBlue = QColor::fromRgb(114, 159, 207);
QColor c = (lastUpdatedBinIndex == i) ? lighterBlue : lightBlue;
QRectF barRect(x + leftPadding, y, barWidth, h);
painter->fillRect(barRect, c);
if (i % 10 == 0) {
QRectF txtRect(x + leftPadding, barHeight, barWidth, 32);
std::string str(16, '\0');
std::snprintf(&str[0], str.size(), "%g", minValue + i*_binWidth);
painter->drawText(txtRect, Qt::AlignCenter | Qt::TextDontClip, QString::fromStdString(str));
}
}
}
void HistogramChart::pushData(qreal value)
{
if(_histogram.empty()) {
minValue = value;
maxValue = value;
_histogram.resize(1);
}
else if (value > maxValue) {
int newMaxIndex = binIndex(value);
Q_ASSERT(newMaxIndex >= 0);
if (newMaxIndex > 0) {
_histogram.resize(static_cast<size_t>(newMaxIndex + 1));
}
maxValue = value;
}
else if (value < minValue) {
int oldMinIndex = binIndex(minValue);
int newMinIndex = binIndex(value);
int diff = oldMinIndex - newMinIndex;
Q_ASSERT(diff > 0);
_histogram.insert(_histogram.begin(), static_cast<size_t>(diff), 0);
minValue = value;
}
int idx = binIndex(value);
int& count = _histogram.at(static_cast<size_t>(idx));
count++;
if (count >= maxBinCount) {
maxBinCount = count;
maxBinIndex = idx;
}
lastUpdatedBinIndex = static_cast<size_t>(idx);
stats.add(value);
update();
}
int HistogramChart::binIndex(qreal value) const
{
Q_ASSERT(!std::isnan(minValue));
return static_cast<int>( std::floor( (value-minValue) / _binWidth));
}
int HistogramChart::numberOfBins() const
{
Q_ASSERT(!std::isnan(minValue));
Q_ASSERT(!std::isnan(maxValue));
return static_cast<int>( std::ceil((maxValue - minValue)/_binWidth) );
}
void HistogramChart::clear()
{
std::fill(_histogram.begin(), _histogram.end(), 0);
maxBinCount = 0;
stats.clear();
}
void HistogramChart::reset()
{
_histogram.resize(0);
minValue = std::numeric_limits<qreal>::quiet_NaN();
maxValue = std::numeric_limits<qreal>::quiet_NaN();
maxBinCount = 0;
stats.clear();
}