138 lines
3.2 KiB
C++
138 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);
|
|
_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();
|
|
}
|