Improve visual appearance for ensemble curves (#9016)

* Ensemble Curves : Improve visual appearance
Set line thickness to 1
If ensemble curves are bright, use a high saturation color for the highlight curve
Increase line thickness for highlighted curve
* Use color by summary vector phase for ensemble curves
* Do not create curves for non-existing history vectors
This commit is contained in:
Magne Sjaastad 2022-06-13 15:08:15 +02:00 committed by GitHub
parent ccbda23b96
commit fe0d009b25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 165 additions and 34 deletions

View File

@ -1703,6 +1703,7 @@ void RimEnsembleCurveSet::updateEnsembleCurves( const std::vector<RimSummaryCase
curve->setSummaryCaseY( sumCase ); curve->setSummaryCaseY( sumCase );
curve->setSummaryAddressYAndApplyInterpolation( addr->address() ); curve->setSummaryAddressYAndApplyInterpolation( addr->address() );
curve->setResampling( m_resampling() ); curve->setResampling( m_resampling() );
curve->setLineThickness( 1 );
addCurve( curve ); addCurve( curve );

View File

@ -362,6 +362,31 @@ void RimSummaryCurveAppearanceCalculator::assignColorByPhase( RimSummaryCurve* c
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimSummaryCurveAppearanceCalculator::assignColorByPhase( const RifEclipseSummaryAddress& address )
{
char secondChar = 0;
std::string vectorName = address.vectorName();
if ( vectorName.size() > 1 )
{
secondChar = vectorName[1];
if ( !isExcplicitHandled( secondChar ) )
{
secondChar = 0; // Consider all others as one group for coloring
}
}
if ( secondChar == 'W' ) return cycledBlueColor( 0 );
if ( secondChar == 'O' ) return cycledGreenColor( 0 );
if ( secondChar == 'G' ) return cycledRedColor( 0 );
if ( secondChar == 'V' ) return cycledBrownColor( 0 );
return cycledNoneRGBBrColor( 0 );
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -60,6 +60,8 @@ public:
void setupCurveLook( RimSummaryCurve* curve ); void setupCurveLook( RimSummaryCurve* curve );
static cvf::Color3f assignColorByPhase( const RifEclipseSummaryAddress& address );
void assignColorByPhase( RimSummaryCurve* curve, int colorIndex ); void assignColorByPhase( RimSummaryCurve* curve, int colorIndex );
static cvf::Color3f cycledPaletteColor( int colorIndex ); static cvf::Color3f cycledPaletteColor( int colorIndex );

View File

@ -19,6 +19,7 @@
#include "RimSummaryPlot.h" #include "RimSummaryPlot.h"
#include "RiaColorTables.h" #include "RiaColorTables.h"
#include "RiaColorTools.h"
#include "RiaDefines.h" #include "RiaDefines.h"
#include "RiaFieldHandleTools.h" #include "RiaFieldHandleTools.h"
#include "RiaPlotDefines.h" #include "RiaPlotDefines.h"
@ -30,6 +31,7 @@
#include "RiaSummaryCurveDefinition.h" #include "RiaSummaryCurveDefinition.h"
#include "RiaSummaryTools.h" #include "RiaSummaryTools.h"
#include "RiaTimeHistoryCurveResampler.h" #include "RiaTimeHistoryCurveResampler.h"
#include "RifReaderEclipseSummary.h" #include "RifReaderEclipseSummary.h"
#include "RicfCommandObject.h" #include "RicfCommandObject.h"
@ -763,7 +765,20 @@ void RimSummaryPlot::applyDefaultCurveAppearances()
for ( auto& curveSet : this->ensembleCurveSetCollection()->curveSets() ) for ( auto& curveSet : this->ensembleCurveSetCollection()->curveSets() )
{ {
if ( curveSet->colorMode() != RimEnsembleCurveSet::ColorMode::SINGLE_COLOR ) continue; if ( curveSet->colorMode() != RimEnsembleCurveSet::ColorMode::SINGLE_COLOR ) continue;
curveSet->setColor( RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f( colorIndex++ ) );
cvf::Color3f curveColor;
if ( RiaPreferencesSummary::current()->colorCurvesByPhase() )
{
auto basePhaseColor = RimSummaryCurveAppearanceCalculator::assignColorByPhase( curveSet->summaryAddress() );
curveColor = RiaColorTools::blendCvfColors( basePhaseColor, cvf::Color3f::WHITE, 1, 3 );
}
else
{
curveColor = RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f( colorIndex++ );
}
curveSet->setColor( curveColor );
} }
} }
@ -1942,7 +1957,11 @@ std::pair<int, std::vector<RimSummaryCurve*>> RimSummaryPlot::handleSummaryCaseD
{ {
auto historyAddr = addr; auto historyAddr = addr;
historyAddr.setVectorName( addr.vectorName() + RifReaderEclipseSummary::historyIdentifier() ); historyAddr.setVectorName( addr.vectorName() + RifReaderEclipseSummary::historyIdentifier() );
dataVectorMap[historyAddr].insert( curve->summaryCaseY() );
if ( summaryCase->summaryReader() && summaryCase->summaryReader()->hasAddress( historyAddr ) )
{
dataVectorMap[historyAddr].insert( curve->summaryCaseY() );
}
} }
} }
@ -2044,13 +2063,21 @@ std::pair<int, std::vector<RimSummaryCurve*>>
if ( curveDef.ensemble() ) if ( curveDef.ensemble() )
{ {
addNewEnsembleCurveY( curveDef.summaryAddress(), curveDef.ensemble() ); auto addresses = curveDef.ensemble()->ensembleSummaryAddresses();
newCurves++; if ( addresses.find( curveDef.summaryAddress() ) != addresses.end() )
{
addNewEnsembleCurveY( curveDef.summaryAddress(), curveDef.ensemble() );
newCurves++;
}
} }
else if ( curveDef.summaryCase() ) else if ( curveDef.summaryCase() )
{ {
curves.push_back( addNewCurveY( curveDef.summaryAddress(), curveDef.summaryCase() ) ); if ( curveDef.summaryCase()->summaryReader() &&
newCurves++; curveDef.summaryCase()->summaryReader()->hasAddress( curveDef.summaryAddress() ) )
{
curves.push_back( addNewCurveY( curveDef.summaryAddress(), curveDef.summaryCase() ) );
newCurves++;
}
} }
} }
@ -2089,8 +2116,10 @@ std::pair<int, std::vector<RimSummaryCurve*>> RimSummaryPlot::handleSummaryAddre
{ {
for ( const auto& droppedAddress : newCurveAddresses ) for ( const auto& droppedAddress : newCurveAddresses )
{ {
bool skipAddress = false; auto addresses = ensemble->ensembleSummaryAddresses();
if ( addresses.find( droppedAddress ) == addresses.end() ) continue;
bool skipAddress = false;
if ( dataVectorMap.count( droppedAddress ) > 0 ) if ( dataVectorMap.count( droppedAddress ) > 0 )
{ {
skipAddress = ( dataVectorMap[droppedAddress].count( ensemble ) > 0 ); skipAddress = ( dataVectorMap[droppedAddress].count( ensemble ) > 0 );
@ -2119,6 +2148,9 @@ std::pair<int, std::vector<RimSummaryCurve*>> RimSummaryPlot::handleSummaryAddre
{ {
for ( const auto& droppedAddress : newCurveAddresses ) for ( const auto& droppedAddress : newCurveAddresses )
{ {
if ( !summaryCase->summaryReader() || !summaryCase->summaryReader()->hasAddress( droppedAddress ) )
continue;
bool skipAddress = false; bool skipAddress = false;
if ( dataVectorMap.count( droppedAddress ) > 0 ) if ( dataVectorMap.count( droppedAddress ) > 0 )
@ -2192,14 +2224,6 @@ void RimSummaryPlot::handleDroppedObjects( const std::vector<caf::PdmObjectHandl
{ {
applyDefaultCurveAppearances( curvesToUpdate ); applyDefaultCurveAppearances( curvesToUpdate );
// Ensemble curve sets
int colorIndex = 0;
for ( auto& curveSet : this->ensembleCurveSetCollection()->curveSets() )
{
if ( curveSet->colorMode() != RimEnsembleCurveSet::ColorMode::SINGLE_COLOR ) continue;
curveSet->setColor( RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f( colorIndex++ ) );
}
loadDataAndUpdate(); loadDataAndUpdate();
curvesChanged.send(); curvesChanged.send();
@ -2230,6 +2254,21 @@ void RimSummaryPlot::addNewEnsembleCurveY( const RifEclipseSummaryAddress& addre
curveSet->setSummaryCaseCollection( ensemble ); curveSet->setSummaryCaseCollection( ensemble );
curveSet->setSummaryAddress( address ); curveSet->setSummaryAddress( address );
cvf::Color3f curveColor;
if ( RiaPreferencesSummary::current()->colorCurvesByPhase() )
{
auto basePhaseColor = RimSummaryCurveAppearanceCalculator::assignColorByPhase( curveSet->summaryAddress() );
curveColor = RiaColorTools::blendCvfColors( basePhaseColor, cvf::Color3f::WHITE, 1, 3 );
}
else
{
curveColor = RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f(
ensembleCurveSetCollection()->curveSetCount() );
}
curveSet->setColor( curveColor );
ensembleCurveSetCollection()->addCurveSet( curveSet ); ensembleCurveSetCollection()->addCurveSet( curveSet );
} }

View File

@ -827,6 +827,14 @@ void RiuQwtPlotWidget::recalculateAxisExtents( RiuPlotAxis axis )
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuQwtPlotWidget::highlightItemWidthAdjustment()
{
return 2;
}
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -967,13 +975,57 @@ void RiuQwtPlotWidget::replot()
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::highlightPlotItems( const std::set<const QwtPlotItem*>& closestItems ) void RiuQwtPlotWidget::highlightPlotItems( const std::set<const QwtPlotItem*>& closestItems )
{ {
if ( closestItems.size() == 1 )
{
auto* constPlotCurve = dynamic_cast<const QwtPlotCurve*>( *closestItems.begin() );
auto* plotCurve = const_cast<QwtPlotCurve*>( constPlotCurve );
if ( plotCurve )
{
auto curveColor = plotCurve->pen().color();
if ( RiaColorTools::isBrightnessAboveThreshold( RiaColorTools::fromQColorTo3f( curveColor ) ) )
{
// The brightness of selected curve is above threshold. Modify the saturation, and leave the other
// curves unchanged
QColor symbolColor;
QColor symbolLineColor;
auto* symbol = const_cast<QwtSymbol*>( plotCurve->symbol() );
if ( symbol )
{
symbolColor = symbol->brush().color();
symbolLineColor = symbol->pen().color();
}
double zValue = plotCurve->z();
plotCurve->setZ( zValue + 100.0 );
highlightPlotAxes( plotCurve->xAxis(), plotCurve->yAxis() );
auto hightlightColor = curveColor;
qreal h, s, v;
hightlightColor.getHsvF( &h, &s, &v );
hightlightColor.setHsvF( h, 0.95, v );
auto curveWidth = plotCurve->pen().width();
plotCurve->setPen( hightlightColor,
plotCurve->pen().width() + highlightItemWidthAdjustment(),
plotCurve->pen().style() );
CurveProperties properties = { curveColor, symbolColor, symbolLineColor, curveWidth };
m_originalCurveProperties.insert( std::make_pair( plotCurve, properties ) );
m_originalZValues.insert( std::make_pair( plotCurve, zValue ) );
return;
}
}
}
// NB! Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list // NB! Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list
// plotCurve->setZ() causes the ordering of items in the list to change // plotCurve->setZ() causes the ordering of items in the list to change
auto plotItemList = m_plot->itemList(); auto plotItemList = m_plot->itemList();
for ( QwtPlotItem* plotItem : plotItemList ) for ( QwtPlotItem* plotItem : plotItemList )
{ {
auto* plotCurve = dynamic_cast<QwtPlotCurve*>( plotItem ); auto* plotCurve = dynamic_cast<QwtPlotCurve*>( plotItem );
auto* plotShapeItem = dynamic_cast<QwtPlotShapeItem*>( plotItem );
if ( plotCurve ) if ( plotCurve )
{ {
QPen existingPen = plotCurve->pen(); QPen existingPen = plotCurve->pen();
@ -982,6 +1034,7 @@ void RiuQwtPlotWidget::highlightPlotItems( const std::set<const QwtPlotItem*>& c
QColor curveColor = existingPen.color(); QColor curveColor = existingPen.color();
QColor symbolColor; QColor symbolColor;
QColor symbolLineColor; QColor symbolLineColor;
auto penWidth = existingPen.width();
auto* symbol = const_cast<QwtSymbol*>( plotCurve->symbol() ); auto* symbol = const_cast<QwtSymbol*>( plotCurve->symbol() );
if ( symbol ) if ( symbol )
@ -993,6 +1046,8 @@ void RiuQwtPlotWidget::highlightPlotItems( const std::set<const QwtPlotItem*>& c
double zValue = plotCurve->z(); double zValue = plotCurve->z();
if ( closestItems.count( plotCurve ) > 0 ) if ( closestItems.count( plotCurve ) > 0 )
{ {
existingPen.setWidth( penWidth + highlightItemWidthAdjustment() );
plotCurve->setPen( existingPen );
plotCurve->setZ( zValue + 100.0 ); plotCurve->setZ( zValue + 100.0 );
highlightPlotAxes( plotCurve->xAxis(), plotCurve->yAxis() ); highlightPlotAxes( plotCurve->xAxis(), plotCurve->yAxis() );
} }
@ -1009,12 +1064,15 @@ void RiuQwtPlotWidget::highlightPlotItems( const std::set<const QwtPlotItem*>& c
symbol->setPen( blendedSymbolLineColor, symbol->pen().width(), symbol->pen().style() ); symbol->setPen( blendedSymbolLineColor, symbol->pen().width(), symbol->pen().style() );
} }
} }
CurveColors curveColors = { curveColor, symbolColor, symbolLineColor }; CurveProperties properties = { curveColor, symbolColor, symbolLineColor, penWidth };
m_originalCurveColors.insert( std::make_pair( plotCurve, curveColors ) ); m_originalCurveProperties.insert( std::make_pair( plotCurve, properties ) );
m_originalCurveColors.insert( std::make_pair( plotCurve, curveColors ) );
m_originalZValues.insert( std::make_pair( plotCurve, zValue ) ); m_originalZValues.insert( std::make_pair( plotCurve, zValue ) );
continue;
} }
else if ( plotShapeItem && closestItems.count( plotItem ) > 0 )
auto* plotShapeItem = dynamic_cast<QwtPlotShapeItem*>( plotItem );
if ( plotShapeItem && closestItems.count( plotItem ) > 0 )
{ {
QPen pen = plotShapeItem->pen(); QPen pen = plotShapeItem->pen();
pen.setColor( QColor( Qt::green ) ); pen.setColor( QColor( Qt::green ) );
@ -1035,24 +1093,27 @@ void RiuQwtPlotWidget::resetPlotItemHighlighting()
auto plotItemList = m_plot->itemList(); auto plotItemList = m_plot->itemList();
for ( QwtPlotItem* plotItem : plotItemList ) for ( QwtPlotItem* plotItem : plotItemList )
{ {
auto* plotCurve = dynamic_cast<QwtPlotCurve*>( plotItem ); auto* plotCurve = dynamic_cast<QwtPlotCurve*>( plotItem );
auto* plotShapeItem = dynamic_cast<QwtPlotShapeItem*>( plotItem ); if ( plotCurve && m_originalCurveProperties.count( plotCurve ) )
if ( plotCurve && m_originalCurveColors.count( plotCurve ) )
{ {
const QPen& existingPen = plotCurve->pen(); const QPen& existingPen = plotCurve->pen();
auto colors = m_originalCurveColors[plotCurve]; auto properties = m_originalCurveProperties[plotCurve];
double zValue = m_originalZValues[plotCurve]; double zValue = m_originalZValues[plotCurve];
plotCurve->setPen( colors.lineColor, existingPen.width(), existingPen.style() ); plotCurve->setPen( properties.lineColor, properties.lineWidth, existingPen.style() );
plotCurve->setZ( zValue ); plotCurve->setZ( zValue );
auto* symbol = const_cast<QwtSymbol*>( plotCurve->symbol() ); auto* symbol = const_cast<QwtSymbol*>( plotCurve->symbol() );
if ( symbol ) if ( symbol )
{ {
symbol->setColor( colors.symbolColor ); symbol->setColor( properties.symbolColor );
symbol->setPen( colors.symbolLineColor, symbol->pen().width(), symbol->pen().style() ); symbol->setPen( properties.symbolLineColor, symbol->pen().width(), symbol->pen().style() );
} }
continue;
} }
else if ( plotShapeItem )
auto* plotShapeItem = dynamic_cast<QwtPlotShapeItem*>( plotItem );
if ( plotShapeItem )
{ {
QPen pen = plotShapeItem->pen(); QPen pen = plotShapeItem->pen();
@ -1064,7 +1125,7 @@ void RiuQwtPlotWidget::resetPlotItemHighlighting()
plotShapeItem->setZ( plotShapeItem->z() - 100.0 ); plotShapeItem->setZ( plotShapeItem->z() - 100.0 );
} }
} }
m_originalCurveColors.clear(); m_originalCurveProperties.clear();
m_originalZValues.clear(); m_originalZValues.clear();
resetPlotAxisHighlighting(); resetPlotAxisHighlighting();

View File

@ -216,17 +216,20 @@ private:
void onAxisSelected( QwtScaleWidget* scale, bool toggleItemInSelection ); void onAxisSelected( QwtScaleWidget* scale, bool toggleItemInSelection );
void recalculateAxisExtents( RiuPlotAxis axis ); void recalculateAxisExtents( RiuPlotAxis axis );
static int highlightItemWidthAdjustment();
private: private:
struct CurveColors struct CurveProperties
{ {
QColor lineColor; QColor lineColor;
QColor symbolColor; QColor symbolColor;
QColor symbolLineColor; QColor symbolLineColor;
int lineWidth;
}; };
std::map<QwtPlotCurve*, CurveColors> m_originalCurveColors; std::map<QwtPlotCurve*, CurveProperties> m_originalCurveProperties;
std::map<QwtPlotCurve*, double> m_originalZValues; std::map<QwtPlotCurve*, double> m_originalZValues;
std::map<RiuPlotAxis, QwtAxisId> m_axisMapping; std::map<RiuPlotAxis, QwtAxisId> m_axisMapping;
QPointer<QwtPlot> m_plot; QPointer<QwtPlot> m_plot;
}; };