Histogram implementation
This commit is contained in:
137
histogramchart.cpp
Normal file
137
histogramchart.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#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();
|
||||
}
|
||||
Reference in New Issue
Block a user