summaryrefslogtreecommitdiffstats
path: root/stats/chartitem.cpp
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2021-01-17 21:07:57 +0100
committerGravatar bstoeger <32835590+bstoeger@users.noreply.github.com>2021-01-20 08:47:18 +0100
commit409f159e1d8875f72f50d371860d4aef1975f065 (patch)
treef7a5a3c140ef318b48bb09b74429c8c79239e6f0 /stats/chartitem.cpp
parent5d5ebfcf3c737aa8c36192eb7bf7d7dee6b33099 (diff)
downloadsubsurface-409f159e1d8875f72f50d371860d4aef1975f065.tar.gz
statistics: convert box-and-whiskers plot to QSG
This is lazy: Derive from the bar chart item and add whiskers in the subclassed render() function. The code is ugly, because the base class function clears the dirty flags and therefore the derived class has to remember them. Oh well. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'stats/chartitem.cpp')
-rw-r--r--stats/chartitem.cpp74
1 files changed, 74 insertions, 0 deletions
diff --git a/stats/chartitem.cpp b/stats/chartitem.cpp
index ce5e6860c..67cfb4937 100644
--- a/stats/chartitem.cpp
+++ b/stats/chartitem.cpp
@@ -279,3 +279,77 @@ QRectF ChartBarItem::getRect() const
{
return rect;
}
+
+ChartBoxItem::ChartBoxItem(StatsView &v, ChartZValue z, double borderWidth) :
+ ChartBarItem(v, z, borderWidth, false) // Only support for vertical boxes
+{
+}
+
+ChartBoxItem::~ChartBoxItem()
+{
+}
+
+void ChartBoxItem::render()
+{
+ // Remember old dirty values, since ChartBarItem::render() will clear them
+ bool oldPositionDirty = positionDirty;
+ bool oldColorDirty = colorDirty;
+ ChartBarItem::render(); // This will create the base node, so no need to check for that.
+ if (!whiskersNode) {
+ whiskersGeometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 10));
+ whiskersGeometry->setDrawingMode(QSGGeometry::DrawLines);
+ whiskersGeometry->setLineWidth(static_cast<float>(borderWidth));
+ whiskersMaterial.reset(new QSGFlatColorMaterial);
+ whiskersNode.reset(new QSGGeometryNode);
+ whiskersNode->setGeometry(whiskersGeometry.get());
+ whiskersNode->setMaterial(whiskersMaterial.get());
+
+ node->node->appendChildNode(whiskersNode.get());
+ // If this is the first time, make sure to update the geometry.
+ oldPositionDirty = oldColorDirty = true;
+ }
+
+ if (oldColorDirty) {
+ whiskersMaterial->setColor(borderColor);
+ whiskersNode->markDirty(QSGNode::DirtyMaterial);
+ }
+
+ if (oldPositionDirty) {
+ auto vertices = whiskersGeometry->vertexDataAsPoint2D();
+ double left = rect.left();
+ double right = rect.right();
+ double mid = (left + right) / 2.0;
+ // top bar
+ setPoint(vertices[0], QPointF(left, max));
+ setPoint(vertices[1], QPointF(right, max));
+ // top whisker
+ setPoint(vertices[2], QPointF(mid, max));
+ setPoint(vertices[3], QPointF(mid, rect.top()));
+ // bottom bar
+ setPoint(vertices[4], QPointF(left, min));
+ setPoint(vertices[5], QPointF(right, min));
+ // bottom whisker
+ setPoint(vertices[6], QPointF(mid, min));
+ setPoint(vertices[7], QPointF(mid, rect.bottom()));
+ // median indicator
+ setPoint(vertices[8], QPointF(left, median));
+ setPoint(vertices[9], QPointF(right, median));
+ whiskersNode->markDirty(QSGNode::DirtyGeometry);
+ }
+}
+
+void ChartBoxItem::setBox(const QRectF &rect, double minIn, double maxIn, double medianIn)
+{
+ min = minIn;
+ max = maxIn;
+ median = medianIn;
+ setRect(rect);
+}
+
+QRectF ChartBoxItem::getRect() const
+{
+ QRectF res = rect;
+ res.setTop(min);
+ res.setBottom(max);
+ return rect;
+}