#2659 Ensemble statistics. Add labels to symbols on the statistic curves

This commit is contained in:
Bjørn Erik Jensen
2018-06-14 14:10:37 +02:00
parent 17bbed20c0
commit b5ad3681cc
5 changed files with 107 additions and 35 deletions

View File

@@ -27,6 +27,7 @@
#include "RimSummaryPlot.h"
#include "RiuRimQwtPlotCurve.h"
#include "RiuLineSegmentQwtPlotCurve.h"
#include "cafPdmUiComboBoxEditor.h"
@@ -421,7 +422,7 @@ void RimPlotCurve::updateCurveAppearance()
}
// QwtPlotCurve will take ownership of the symbol
symbol = new QwtSymbol(style);
symbol = new RiuCurveQwtSymbol(style, m_symbolLabel);
symbol->setSize(6, 6);
symbol->setColor(curveColor);
@@ -545,6 +546,14 @@ void RimPlotCurve::setSymbolSkipDinstance(float distance)
m_symbolSkipPixelDistance = distance;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPlotCurve::setSymbolLabel(const QString& label)
{
m_symbolLabel = label;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -81,6 +81,7 @@ public:
void setSymbol(PointSymbolEnum symbolStyle);
PointSymbolEnum symbol();
void setSymbolSkipDinstance(float distance);
void setSymbolLabel(const QString& label);
void setLineThickness(int thickness);
void resetAppearance();
@@ -131,6 +132,7 @@ protected:
caf::PdmField<QString> m_curveName;
caf::PdmField<QString> m_customCurveName;
caf::PdmField<bool> m_showLegend;
QString m_symbolLabel;
caf::PdmField<bool> m_isUsingAutoName;
caf::PdmField<cvf::Color3f> m_curveColor;

View File

@@ -969,6 +969,7 @@ void RimEnsembleCurveSet::updateStatisticsCurves(bool calculate = true)
m_curves.push_back(curve);
curve->setSymbol(RimPlotCurve::SYMBOL_ELLIPSE);
curve->setSymbolSkipDinstance(50);
curve->setSymbolLabel(QString::fromStdString(address.ensembleStatisticsQuantityName()));
curve->setLineStyle(RimPlotCurve::STYLE_SOLID);
curve->setSummaryCaseY(m_ensembleStatCase.get());
curve->setSummaryAddressY(address);

View File

@@ -179,51 +179,69 @@ void RiuLineSegmentQwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
const QRectF &canvasRect, int from, int to) const
{
if (m_symbolSkipPixelDistance <= 0)
{
QwtPlotCurve::drawSymbols(painter, symbol, xMap, yMap, canvasRect, from, to);
return;
}
QwtPointMapper mapper;
mapper.setFlag(QwtPointMapper::RoundPoints,
QwtPainter::roundingAlignment(painter));
mapper.setFlag(QwtPointMapper::WeedOutPoints,
testPaintAttribute(QwtPlotCurve::FilterPoints));
mapper.setBoundingRect(canvasRect);
bool filterSymbols = m_symbolSkipPixelDistance > 0;
const QPolygonF points = mapper.toPointsF(xMap, yMap,
data(), from, to);
int pointCount = points.size();
QPolygonF filteredPoints;
QPointF lastDrawnSymbolPos;
if (pointCount > 0)
if (filterSymbols)
{
filteredPoints.push_back(points[0]);
lastDrawnSymbolPos = points[0];
mapper.setFlag(QwtPointMapper::RoundPoints,
QwtPainter::roundingAlignment(painter));
mapper.setFlag(QwtPointMapper::WeedOutPoints,
testPaintAttribute(QwtPlotCurve::FilterPoints));
mapper.setBoundingRect(canvasRect);
}
float sqSkipDist = m_symbolSkipPixelDistance*m_symbolSkipPixelDistance;
const QPolygonF points = mapper.toPointsF(xMap, yMap, data(), from, to);
int pointCount = points.size();
QPolygonF pointsToDisplay;
for(int pIdx = 1; pIdx < pointCount -1 ; ++pIdx)
if (filterSymbols)
{
QPointF diff = points[pIdx] - lastDrawnSymbolPos;
float sqDistBetweenSymbols = diff.x()*diff.x() + diff.y()*diff.y();
QPointF lastDrawnSymbolPos;
if(sqDistBetweenSymbols > sqSkipDist)
if (pointCount > 0)
{
filteredPoints.push_back(points[pIdx]);
lastDrawnSymbolPos = points[pIdx];
pointsToDisplay.push_back(points[0]);
lastDrawnSymbolPos = points[0];
}
float sqSkipDist = m_symbolSkipPixelDistance * m_symbolSkipPixelDistance;
for (int pIdx = 1; pIdx < pointCount - 1; ++pIdx)
{
QPointF diff = points[pIdx] - lastDrawnSymbolPos;
float sqDistBetweenSymbols = diff.x()*diff.x() + diff.y()*diff.y();
if (sqDistBetweenSymbols > sqSkipDist)
{
pointsToDisplay.push_back(points[pIdx]);
lastDrawnSymbolPos = points[pIdx];
}
}
if (pointCount > 1) pointsToDisplay.push_back(points.back());
}
else
{
pointsToDisplay = points;
}
if (pointsToDisplay.size() > 0)
{
symbol.drawSymbols(painter, pointsToDisplay);
const RiuCurveQwtSymbol* sym = dynamic_cast<const RiuCurveQwtSymbol*>(&symbol);
if (sym && !sym->label().isEmpty())
{
for (auto& pt : pointsToDisplay)
{
int width = painter->fontMetrics().width(sym->label());
painter->drawText(pt.x() - width / 2, pt.y() - 5, sym->label());
}
}
}
if(pointCount > 1) filteredPoints.push_back(points.back());
if(filteredPoints.size() > 0)
symbol.drawSymbols(painter, filteredPoints);
}
//--------------------------------------------------------------------------------------------------
@@ -322,3 +340,25 @@ std::vector<double> RiuLineSegmentQwtPlotCurve::fromTime_t(const std::vector<tim
return doubleValues;
}
//--------------------------------------------------------------------------------------------------
/// Internal class to support labels on symbols
//--------------------------------------------------------------------------------------------------
RiuCurveQwtSymbol::RiuCurveQwtSymbol(QwtSymbol::Style style, const QString& label) : QwtSymbol(style), m_label(label)
{
}
void RiuCurveQwtSymbol::renderSymbols(QPainter *painter, const QPointF *points, int numPoints) const
{
QwtSymbol::renderSymbols(painter, points, numPoints);
if (!m_label.isEmpty())
{
for (int i = 0; i < numPoints; i++)
{
auto pt = points[i];
int width = painter->fontMetrics().width(m_label);
painter->drawText(pt.x() - width / 2, pt.y() - 5, m_label);
}
}
}

View File

@@ -19,6 +19,7 @@
#pragma once
#include "qwt_symbol.h"
#include "qwt_plot_curve.h"
#include "qwt_plot_intervalcurve.h"
@@ -106,3 +107,22 @@ private:
QwtPlotIntervalCurve* m_errorBars;
QwtPlot* m_attachedToPlot;
};
//--------------------------------------------------------------------------------------------------
/// This class overrides renderSymbols to draw symbols and labels.
/// The label is only visible in the legend, while it is clipped in the plot.
/// Therefore the method RiuLineSegmentQwtPlotCurve::drawSymbols also draw labels to have labels
/// in the plot as well.
//--------------------------------------------------------------------------------------------------
class RiuCurveQwtSymbol : public QwtSymbol
{
public:
RiuCurveQwtSymbol(QwtSymbol::Style style, const QString& label);
virtual void renderSymbols(QPainter *painter, const QPointF *points, int numPoints) const override;
QString label() const { return m_label; }
private:
QString m_label;
};