#8451 Qt Charts: show fewer curve symbols.

The "Symbol Skip Distance" is used to space the symbols.

Fixes #8451.
This commit is contained in:
Kristian Bendiksen
2022-03-02 13:46:06 +01:00
committed by Magne Sjaastad
parent 2e9c6e7a64
commit 7a954804ef
9 changed files with 175 additions and 32 deletions

View File

@@ -892,8 +892,8 @@ void RimPlotCurve::updateCurveAppearance()
curveColor,
fillBrush );
m_plotCurve->setSymbol( symbol );
m_plotCurve->setSymbolSkipPixelDistance( m_curveAppearance->symbolSkipDistance() );
m_plotCurve->setSymbol( symbol );
// Make sure the legend lines are long enough to distinguish between line types.
// Standard width in Qwt is 8 which is too short.

View File

@@ -1590,6 +1590,7 @@ void RimSummaryPlot::updateZoomInParentPlot()
plotWidget()->updateAxes();
updateZoomFromParentPlot();
plotWidget()->updateZoomDependentCurveProperties();
plotWidget()->scheduleReplot();
}
}

View File

@@ -226,6 +226,7 @@ if(RESINSIGHT_USE_QT_CHARTS)
list(APPEND QT_MOC_HEADERS ${CMAKE_CURRENT_LIST_DIR}/RiuQtChartsPlotWidget.h
${CMAKE_CURRENT_LIST_DIR}/RiuSummaryQtChartsPlot.h
${CMAKE_CURRENT_LIST_DIR}/RiuQtChartsPlotCurve.h
)
endif()

View File

@@ -323,3 +323,10 @@ int RiuPlotWidget::defaultMinimumWidth()
{
return 80;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPlotWidget::updateZoomDependentCurveProperties()
{
}

View File

@@ -183,6 +183,8 @@ public:
virtual std::pair<RiuPlotCurve*, int> findClosestCurve( const QPoint& pos, double& distanceToClick ) const = 0;
virtual void updateZoomDependentCurveProperties();
protected:
void updateOverlayFrameLayout();

View File

@@ -28,6 +28,8 @@
#include <QLegend>
#include <QLegendMarker>
#include <QtCharts/QChartView>
#include <QtCharts/QDateTimeAxis>
#include <QtCharts/QValueAxis>
#include <limits>
@@ -202,8 +204,7 @@ void RiuQtChartsPlotCurve::setSamplesInPlot( const std::vector<double>& xValues,
CAF_ASSERT( xValues.size() == yValues.size() );
QtCharts::QLineSeries* line = lineSeries();
QtCharts::QScatterSeries* scatter = scatterSeries();
QtCharts::QLineSeries* line = lineSeries();
QVector<QPointF> values( static_cast<int>( xValues.size() ) );
@@ -213,7 +214,88 @@ void RiuQtChartsPlotCurve::setSamplesInPlot( const std::vector<double>& xValues,
}
line->replace( values );
scatter->replace( values );
updateScatterSeries();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQtChartsPlotCurve::updateScatterSeries()
{
double minX = std::numeric_limits<double>::max();
double maxX = -std::numeric_limits<double>::max();
QVector<QPointF> points = lineSeries()->pointsVector();
auto axes = lineSeries()->attachedAxes();
bool foundAxis = false;
for ( auto axis : axes )
{
if ( axis->orientation() == Qt::Orientation::Horizontal )
{
QtCharts::QValueAxis* valueAxis = dynamic_cast<QtCharts::QValueAxis*>( axis );
QtCharts::QDateTimeAxis* dateTimeAxis = dynamic_cast<QtCharts::QDateTimeAxis*>( axis );
if ( valueAxis )
{
minX = valueAxis->min();
maxX = valueAxis->max();
foundAxis = true;
}
else if ( dateTimeAxis )
{
minX = dateTimeAxis->min().toMSecsSinceEpoch();
maxX = dateTimeAxis->max().toMSecsSinceEpoch();
foundAxis = true;
}
}
}
if ( !foundAxis )
{
for ( auto p : points )
{
minX = std::min( minX, p.x() );
maxX = std::max( maxX, p.x() );
}
}
QVector<QPointF> scatterValues;
if ( !points.empty() )
{
double range = maxX - minX;
double displaySize = 1400;
if ( m_plotWidget && m_plotWidget->qtChart() )
{
// Use the max size since plot area can be small before the widget is shown
displaySize = std::max( displaySize, m_plotWidget->qtChart()->plotArea().width() );
}
double rangePerPixel = range / displaySize;
double skipDistance = rangePerPixel * m_symbolSkipPixelDistance;
// Always have symbol on first point
scatterValues << points[0];
int lastDrawnIndex = 0;
for ( int i = 1; i < static_cast<int>( points.size() ); i++ )
{
// Skip points until skip distance is reached
double diff = points[i].x() - points[lastDrawnIndex].x();
// Always add last point.
bool isLastPoint = i == points.size() - 1;
if ( diff > skipDistance || isLastPoint )
{
scatterValues << points[i];
lastDrawnIndex = i;
}
}
}
scatterSeries()->replace( scatterValues );
}
//--------------------------------------------------------------------------------------------------
@@ -255,8 +337,8 @@ void RiuQtChartsPlotCurve::setXAxis( RiuPlotAxis axis )
m_axisX = axis;
if ( m_plotWidget )
{
m_plotWidget->setXAxis( axis, lineSeries() );
m_plotWidget->setXAxis( axis, scatterSeries() );
m_plotWidget->setXAxis( axis, lineSeries(), this );
m_plotWidget->setXAxis( axis, scatterSeries(), this );
}
}
@@ -268,8 +350,8 @@ void RiuQtChartsPlotCurve::setYAxis( RiuPlotAxis axis )
m_axisY = axis;
if ( m_plotWidget )
{
m_plotWidget->setYAxis( axis, lineSeries() );
m_plotWidget->setYAxis( axis, scatterSeries() );
m_plotWidget->setYAxis( axis, lineSeries(), this );
m_plotWidget->setYAxis( axis, scatterSeries(), this );
}
}
@@ -335,8 +417,8 @@ void RiuQtChartsPlotCurve::setVisibleInLegend( bool isVisibleInLegend )
CAF_ASSERT( m_plotWidget->qtChart() );
CAF_ASSERT( m_plotWidget->qtChart()->legend() );
// The markers can be set visible independent to the visibility state of the containing legend. Use the visibility
// state of the legend to override the visibility flag
// The markers can be set visible independent to the visibility state of the containing legend. Use the
// visibility state of the legend to override the visibility flag
if ( !m_plotWidget->qtChart()->legend()->isAttachedToChart() ) isVisibleInLegend = false;
if ( !m_plotWidget->qtChart()->legend()->isVisible() ) isVisibleInLegend = false;
@@ -395,6 +477,7 @@ void RiuQtChartsPlotCurve::setSymbol( RiuPlotCurveSymbol* symbol )
if ( scatterSeries() )
{
qtChartsSymbol->applyToScatterSeries( scatterSeries() );
updateScatterSeries();
}
}
else
@@ -435,3 +518,11 @@ QPixmap RiuQtChartsPlotCurve::legendIcon( const QSizeF& iconSize ) const
{
return QPixmap();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQtChartsPlotCurve::axisRangeChanged()
{
updateScatterSeries();
}

View File

@@ -32,8 +32,9 @@ class RiuPlotCurveSymbol;
//==================================================================================================
//
//==================================================================================================
class RiuQtChartsPlotCurve : public RiuPlotCurve
class RiuQtChartsPlotCurve : public QObject, public RiuPlotCurve
{
Q_OBJECT
public:
explicit RiuQtChartsPlotCurve( RimPlotCurve* ownerRimCurve, const QString& title = QString() );
~RiuQtChartsPlotCurve() override;
@@ -77,6 +78,11 @@ public:
RiuPlotCurveSymbol* createSymbol( RiuPlotCurveSymbol::PointSymbolEnum symbol ) const override;
void updateScatterSeries();
public slots:
void axisRangeChanged();
private:
void setSamplesInPlot( const std::vector<double>&, const std::vector<double>& ) override;

View File

@@ -612,6 +612,18 @@ void RiuQtChartsPlotWidget::replot()
qtChart()->update();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQtChartsPlotWidget::updateZoomDependentCurveProperties()
{
for ( auto it : m_scatterSeriesMap )
{
auto plotCurve = dynamic_cast<RiuQtChartsPlotCurve*>( it.first );
if ( plotCurve ) plotCurve->updateScatterSeries();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -782,22 +794,24 @@ void RiuQtChartsPlotWidget::attach( RiuPlotCurve* plotCurve,
RiuPlotAxis xAxis,
RiuPlotAxis yAxis )
{
auto addToChart = [this]( std::map<const RiuPlotCurve*, QtCharts::QAbstractSeries*>& curveSeriesMap,
auto plotCurve,
auto series,
auto xAxis,
auto yAxis ) {
auto addToChart = [this]( std::map<RiuPlotCurve*, QtCharts::QAbstractSeries*>& curveSeriesMap,
auto plotCurve,
auto series,
auto xAxis,
auto yAxis,
RiuQtChartsPlotCurve* qtChartsPlotCurve ) {
if ( !series->chart() )
{
curveSeriesMap[plotCurve] = series;
qtChart()->addSeries( series );
setXAxis( xAxis, series );
setXAxis( yAxis, series );
setXAxis( xAxis, series, qtChartsPlotCurve );
setYAxis( yAxis, series, qtChartsPlotCurve );
}
};
addToChart( m_lineSeriesMap, plotCurve, lineSeries, xAxis, yAxis );
addToChart( m_scatterSeriesMap, plotCurve, scatterSeries, xAxis, yAxis );
auto qtChartsPlotCurve = dynamic_cast<RiuQtChartsPlotCurve*>( plotCurve );
addToChart( m_lineSeriesMap, plotCurve, lineSeries, xAxis, yAxis, qtChartsPlotCurve );
addToChart( m_scatterSeriesMap, plotCurve, scatterSeries, xAxis, yAxis, qtChartsPlotCurve );
}
//--------------------------------------------------------------------------------------------------
@@ -805,7 +819,7 @@ void RiuQtChartsPlotWidget::attach( RiuPlotCurve* plotCurve,
//--------------------------------------------------------------------------------------------------
QtCharts::QAbstractSeries* RiuQtChartsPlotWidget::getLineSeries( const RiuPlotCurve* plotCurve ) const
{
auto series = m_lineSeriesMap.find( plotCurve );
auto series = m_lineSeriesMap.find( const_cast<RiuPlotCurve*>( plotCurve ) );
if ( series != m_lineSeriesMap.end() )
return series->second;
else
@@ -817,7 +831,7 @@ QtCharts::QAbstractSeries* RiuQtChartsPlotWidget::getLineSeries( const RiuPlotCu
//--------------------------------------------------------------------------------------------------
QtCharts::QAbstractSeries* RiuQtChartsPlotWidget::getScatterSeries( const RiuPlotCurve* plotCurve ) const
{
auto series = m_scatterSeriesMap.find( plotCurve );
auto series = m_scatterSeriesMap.find( const_cast<RiuPlotCurve*>( plotCurve ) );
if ( series != m_scatterSeriesMap.end() )
return series->second;
else
@@ -846,17 +860,17 @@ void RiuQtChartsPlotWidget::detachItems( RiuPlotWidget::PlotItemType plotItemTyp
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQtChartsPlotWidget::setXAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series )
void RiuQtChartsPlotWidget::setXAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series, RiuQtChartsPlotCurve* plotCurve )
{
attachSeriesToAxis( axis, series );
attachSeriesToAxis( axis, series, plotCurve );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQtChartsPlotWidget::setYAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series )
void RiuQtChartsPlotWidget::setYAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series, RiuQtChartsPlotCurve* plotCurve )
{
attachSeriesToAxis( axis, series );
attachSeriesToAxis( axis, series, plotCurve );
}
//--------------------------------------------------------------------------------------------------
@@ -873,7 +887,9 @@ void RiuQtChartsPlotWidget::ensureAxisIsCreated( RiuPlotAxis axis )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQtChartsPlotWidget::attachSeriesToAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series )
void RiuQtChartsPlotWidget::attachSeriesToAxis( RiuPlotAxis axis,
QtCharts::QAbstractSeries* series,
RiuQtChartsPlotCurve* plotCurve )
{
// Make sure the axis we are about to set exists.
ensureAxisIsCreated( axis );
@@ -896,6 +912,14 @@ void RiuQtChartsPlotWidget::attachSeriesToAxis( RiuPlotAxis axis, QtCharts::QAbs
if ( qobject_cast<QValueAxis*>( newAxis ) || qobject_cast<QLogValueAxis*>( newAxis ) )
{
connect( newAxis, SIGNAL( rangeChanged( double, double ) ), this, SLOT( axisRangeChanged() ), Qt::UniqueConnection );
if ( plotCurve )
{
connect( newAxis,
SIGNAL( rangeChanged( double, double ) ),
plotCurve,
SLOT( axisRangeChanged() ),
Qt::UniqueConnection );
}
}
else if ( qobject_cast<QDateTimeAxis*>( newAxis ) )
{
@@ -904,6 +928,14 @@ void RiuQtChartsPlotWidget::attachSeriesToAxis( RiuPlotAxis axis, QtCharts::QAbs
this,
SLOT( axisRangeChanged() ),
Qt::UniqueConnection );
if ( plotCurve )
{
connect( newAxis,
SIGNAL( rangeChanged( QDateTime, QDateTime ) ),
plotCurve,
SLOT( axisRangeChanged() ),
Qt::UniqueConnection );
}
}
}
}

View File

@@ -34,6 +34,7 @@
class RiaPlotWindowRedrawScheduler;
class RimPlot;
class RiuPlotCurve;
class RiuQtChartsPlotCurve;
class QEvent;
class QLabel;
@@ -165,8 +166,8 @@ public:
QtCharts::QAbstractSeries* getLineSeries( const RiuPlotCurve* plotCurve ) const;
QtCharts::QAbstractSeries* getScatterSeries( const RiuPlotCurve* plotCurve ) const;
void setXAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series );
void setYAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series );
void setXAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series, RiuQtChartsPlotCurve* plotCurve );
void setYAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series, RiuQtChartsPlotCurve* plotCurve );
const QColor& backgroundColor() const override;
@@ -174,8 +175,10 @@ public:
std::pair<RiuPlotCurve*, int> findClosestCurve( const QPoint& pos, double& distanceToClick ) const override;
void updateZoomDependentCurveProperties() override;
protected:
void attachSeriesToAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series );
void attachSeriesToAxis( RiuPlotAxis axis, QtCharts::QAbstractSeries* series, RiuQtChartsPlotCurve* plotCurve );
void resizeEvent( QResizeEvent* event ) override;
void keyPressEvent( QKeyEvent* event ) override;
@@ -217,6 +220,6 @@ private:
std::map<RiuPlotAxis, bool> m_axesEnabled;
std::map<RiuPlotAxis, bool> m_axesAutoScale;
std::map<const RiuPlotCurve*, QtCharts::QAbstractSeries*> m_lineSeriesMap;
std::map<const RiuPlotCurve*, QtCharts::QAbstractSeries*> m_scatterSeriesMap;
std::map<RiuPlotCurve*, QtCharts::QAbstractSeries*> m_lineSeriesMap;
std::map<RiuPlotCurve*, QtCharts::QAbstractSeries*> m_scatterSeriesMap;
};