mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
statistics: implement a bar series
Implement a bar series, which can plot stacked, grouped and single bar charts in horizontal or vertical ways. On hovering over a bar, an information is shown. The shown information depends on whether the chart is count or value based, or is a multi-bin chart. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
99f98ea6d4
commit
ca572acb0d
3 changed files with 564 additions and 0 deletions
140
stats/barseries.h
Normal file
140
stats/barseries.h
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
// A small custom bar series, which displays information
|
||||
// when hovering over a bar. The QtCharts bar series were
|
||||
// too inflexible with respect to placement of the bars.
|
||||
#ifndef BAR_SERIES_H
|
||||
#define BAR_SERIES_H
|
||||
|
||||
#include "statsseries.h"
|
||||
#include "statsvariables.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <QGraphicsRectItem>
|
||||
|
||||
namespace QtCharts {
|
||||
class QAbstractAxis;
|
||||
}
|
||||
class InformationBox;
|
||||
class StatsVariable;
|
||||
|
||||
class BarSeries : public StatsSeries {
|
||||
public:
|
||||
// There are three versions of creating bar series: for value-based (mean, etc) charts, for counts
|
||||
// based charts and for stacked bar charts with multiple items.
|
||||
struct CountItem {
|
||||
double lowerBound, upperBound;
|
||||
int count;
|
||||
std::vector<QString> label;
|
||||
QString binName;
|
||||
int total;
|
||||
};
|
||||
struct ValueItem {
|
||||
double lowerBound, upperBound;
|
||||
double value;
|
||||
std::vector<QString> label;
|
||||
QString binName;
|
||||
StatsOperationResults res;
|
||||
};
|
||||
struct MultiItem {
|
||||
double lowerBound, upperBound;
|
||||
std::vector<std::pair<int, std::vector<QString>>> countLabels;
|
||||
QString binName;
|
||||
};
|
||||
|
||||
// If the horizontal flag is true, independent variable is plotted on the y-axis.
|
||||
// A non-empty valueBinNames vector flags that this is a stacked bar chart.
|
||||
// In that case, a valueVariable must also be provided.
|
||||
// For count-based bar series in one variable, valueVariable is null.
|
||||
// Note: this expects that all items are added with increasing pos
|
||||
// and that no bar is inside another bar, i.e. lowerBound and upperBound
|
||||
// are ordered identically.
|
||||
BarSeries(QtCharts::QChart *chart, StatsAxis *xAxis, StatsAxis *yAxis,
|
||||
bool horizontal, const QString &categoryName,
|
||||
const std::vector<CountItem> &items);
|
||||
BarSeries(QtCharts::QChart *chart, StatsAxis *xAxis, StatsAxis *yAxis,
|
||||
bool horizontal, const QString &categoryName, const StatsVariable *valueVariable,
|
||||
const std::vector<ValueItem> &items);
|
||||
BarSeries(QtCharts::QChart *chart, StatsAxis *xAxis, StatsAxis *yAxis,
|
||||
bool horizontal, bool stacked, const QString &categoryName, const StatsVariable *valueVariable,
|
||||
std::vector<QString> valueBinNames,
|
||||
const std::vector<MultiItem> &items);
|
||||
~BarSeries();
|
||||
|
||||
void updatePositions() override;
|
||||
bool hover(QPointF pos) override;
|
||||
void unhighlight() override;
|
||||
private:
|
||||
BarSeries(QtCharts::QChart *chart, StatsAxis *xAxis, StatsAxis *yAxis,
|
||||
bool horizontal, bool stacked, const QString &categoryName, const StatsVariable *valueVariable,
|
||||
std::vector<QString> valueBinNames);
|
||||
|
||||
struct Index {
|
||||
int bar;
|
||||
int subitem;
|
||||
Index();
|
||||
Index(int bar, int subitem);
|
||||
bool operator==(const Index &i2) const;
|
||||
};
|
||||
|
||||
// Get item under mouse pointer, or -1 if none
|
||||
Index getItemUnderMouse(const QPointF &f) const;
|
||||
|
||||
// A label that is composed of multiple lines
|
||||
struct BarLabel {
|
||||
std::vector<std::unique_ptr<QGraphicsSimpleTextItem>> items;
|
||||
double totalWidth, totalHeight; // Size of the item
|
||||
bool isOutside; // Is shown outside of bar
|
||||
BarLabel(QtCharts::QChart *chart, const std::vector<QString> &labels, int bin_nr, int binCount);
|
||||
void setVisible(bool visible);
|
||||
void updatePosition(QtCharts::QChart *chart, QtCharts::QAbstractSeries *series,
|
||||
bool horizontal, bool center, const QRectF &rect, int bin_nr, int binCount);
|
||||
void highlight(bool highlight, int bin_nr, int binCount);
|
||||
};
|
||||
|
||||
struct SubItem {
|
||||
std::unique_ptr<QGraphicsRectItem> item;
|
||||
std::unique_ptr<BarLabel> label;
|
||||
double value_from;
|
||||
double value_to;
|
||||
int bin_nr;
|
||||
void updatePosition(QtCharts::QChart *chart, BarSeries *series, bool horizontal, bool stacked,
|
||||
double from, double to, int binCount);
|
||||
void highlight(bool highlight, int binCount);
|
||||
};
|
||||
|
||||
struct Item {
|
||||
double lowerBound, upperBound;
|
||||
std::vector<SubItem> subitems;
|
||||
QRectF rect;
|
||||
const QString binName;
|
||||
StatsOperationResults res;
|
||||
int total;
|
||||
Item(QtCharts::QChart *chart, BarSeries *series, double lowerBound, double upperBound,
|
||||
std::vector<SubItem> subitems,
|
||||
const QString &binName, const StatsOperationResults &res, int total, bool horizontal,
|
||||
bool stacked, int binCount);
|
||||
void updatePosition(QtCharts::QChart *chart, BarSeries *series, bool horizontal, bool stacked, int binCount);
|
||||
void highlight(int subitem, bool highlight, int binCount);
|
||||
int getSubItemUnderMouse(const QPointF &f, bool horizontal, bool stacked) const;
|
||||
};
|
||||
|
||||
std::unique_ptr<InformationBox> information;
|
||||
std::vector<Item> items;
|
||||
std::vector<BarLabel> barLabels;
|
||||
bool horizontal;
|
||||
bool stacked;
|
||||
QString categoryName;
|
||||
const StatsVariable *valueVariable; // null: this is count based
|
||||
std::vector<QString> valueBinNames;
|
||||
Index highlighted;
|
||||
std::vector<SubItem> makeSubItems(double value, const std::vector<QString> &label) const;
|
||||
std::vector<SubItem> makeSubItems(const std::vector<std::pair<double, std::vector<QString>>> &values) const;
|
||||
void add_item(double lowerBound, double upperBound, std::vector<SubItem> subitems,
|
||||
const QString &binName, const StatsOperationResults &res, int total, bool horizontal,
|
||||
bool stacked);
|
||||
std::vector<QString> makeInfo(const Item &item, int subitem) const;
|
||||
int binCount() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue