Realization in Ensemble RFT-plot hover info + refactoring of point tracker functionality

* Add realization number to mouse over text for Ensemble RFT

* Refactor Curve Info Text Provider functionality

- Refactor provider implementation, to separate RiuWellLogTrack from the point tracker and text provider.
- Move creating of point tracker outside of RiuWellLogTrack.
- Makes it possible to override/write new CurveInfoTextProvider implementation when needed.

* Add guards for nullptr
This commit is contained in:
Jørgen Herje 2023-02-23 15:08:22 +01:00 committed by GitHub
parent 0601de4c18
commit 5c5e460025
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 240 additions and 137 deletions

View File

@ -46,6 +46,7 @@
#include "RimWellAllocationPlot.h"
#include "RimWellLogCurve.h"
#include "RimWellLogCurveCommonDataSource.h"
#include "RimWellLogCurveInfoTextProvider.h"
#include "RimWellLogPlotNameConfig.h"
#include "RimWellLogTrack.h"
#include "RimWellPath.h"
@ -55,6 +56,7 @@
#include "RiuPlotMainWindowTools.h"
#include "RiuQwtPlotWidget.h"
#include "RiuWellLogPlot.h"
#include "RiuWellLogTrack.h"
#include "cafPdmFieldReorderCapability.h"
#include "cafPdmFieldScriptingCapability.h"
@ -812,6 +814,11 @@ void RimDepthTrackPlot::recreatePlotWidgets()
plotVector[tIdx]->createPlotWidget();
m_viewer->addPlot( plotVector[tIdx]->plotWidget() );
}
for ( size_t idx = 0; idx < m_plots.size(); ++idx )
{
createAndSetCurveTextProvider( m_plots[idx] );
}
}
//--------------------------------------------------------------------------------------------------
@ -1300,6 +1307,29 @@ caf::PdmFieldHandle* RimDepthTrackPlot::userDescriptionField()
return &m_plotWindowTitle;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDepthTrackPlot::createAndSetCurveTextProvider( RimWellLogTrack* track )
{
if ( !track ) return;
auto* qwtPlotWidget = dynamic_cast<RiuQwtPlotWidget*>( track->plotWidget() );
if ( !qwtPlotWidget ) return;
new RiuWellLogCurvePointTracker( qwtPlotWidget->qwtPlot(), curveTextProvider(), track );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPlotCurveInfoTextProvider* RimDepthTrackPlot::curveTextProvider() const
{
static auto textProvider = RimWellLogCurveInfoTextProvider();
return &textProvider;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -27,6 +27,8 @@
#include "RimPlot.h"
#include "RimPlotWindow.h"
#include "RiuPlotCurveInfoTextProvider.h"
#include "cafAppEnum.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
@ -197,6 +199,9 @@ protected:
void updatePlots();
caf::PdmFieldHandle* userDescriptionField() override;
void createAndSetCurveTextProvider( RimWellLogTrack* track );
virtual RiuPlotCurveInfoTextProvider* curveTextProvider() const;
private:
void cleanupBeforeClose();
void updateSubPlotNames();

View File

@ -25,6 +25,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimWellLogWbsCurve.h
${CMAKE_CURRENT_LIST_DIR}/RimRftTools.h
${CMAKE_CURRENT_LIST_DIR}/RimRftTopologyCurve.h
${CMAKE_CURRENT_LIST_DIR}/RimWellLogCurveInfoTextProvider.h
)
set(SOURCE_GROUP_SOURCE_FILES
@ -54,6 +55,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleWellLogStatisticsCurve.cpp
${CMAKE_CURRENT_LIST_DIR}/RimRftTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RimRftTopologyCurve.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellLogCurveInfoTextProvider.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@ -0,0 +1,84 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimWellLogCurveInfoTextProvider.h"
#include "RimDepthTrackPlot.h"
#include "RimWellLogCurve.h"
#include "RiuPlotCurve.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogCurveInfoTextProvider::curveInfoText( RiuPlotCurve* riuCurve ) const
{
if ( riuCurve )
{
RimWellLogCurve* wlCurve = dynamic_cast<RimWellLogCurve*>( riuCurve->ownerRimCurve() );
if ( wlCurve )
{
return QString( "%1" ).arg( wlCurve->curveName() );
}
}
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogCurveInfoTextProvider::additionalText( RiuPlotCurve* curve, int sampleIndex ) const
{
if ( !curve ) return {};
std::vector<std::pair<QString, double>> propertyNameValues;
auto* sourceCurve = curve->ownerRimCurve();
if ( !sourceCurve ) return {};
auto annotationCurves = sourceCurve->additionalDataSources();
for ( auto annotationCurve : annotationCurves )
{
RimDepthTrackPlot* depthTrackPlot = nullptr;
annotationCurve->firstAncestorOfType( depthTrackPlot );
if ( depthTrackPlot )
{
auto [xValue, yValue] = curve->sample( sampleIndex );
auto depth = depthTrackPlot->depthOrientation() == RiaDefines::Orientation::VERTICAL ? yValue : xValue;
auto propertyValue = annotationCurve->closestYValueForX( depth );
// Use template to get as short label as possible. The default curve name will often
// contain too much and redundant information.
QString templateText = RiaDefines::namingVariableResultName() + ", " + RiaDefines::namingVariableResultType();
auto resultName = annotationCurve->createCurveNameFromTemplate( templateText );
propertyNameValues.push_back( std::make_pair( resultName, propertyValue ) );
}
}
QString txt;
for ( const auto& [name, value] : propertyNameValues )
{
txt += QString( "%1 : %2\n" ).arg( name ).arg( value );
}
return txt;
}

View File

@ -0,0 +1,35 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiuPlotCurveInfoTextProvider.h"
class RiuPlotCurve;
//==================================================================================================
//
//
//
//==================================================================================================
class RimWellLogCurveInfoTextProvider : public RiuPlotCurveInfoTextProvider
{
public:
QString curveInfoText( RiuPlotCurve* riuCurve ) const override;
QString additionalText( RiuPlotCurve* curve, int sampleIndex ) const override;
};

View File

@ -528,7 +528,11 @@ std::map<QString, QString> RimWellLogRftCurve::createCurveNameKeyValueMap() cons
{
caseText = m_eclipseResultCase->caseUserDescription();
}
else if ( m_ensemble ) // Summary RFT curves have both ensemble and summary set. Prioritize ensemble for name.
else if ( m_summaryCase && m_ensemble ) // Summary RFT curves have both ensemble and summary set
{
caseText = QString( "%1, %2" ).arg( m_ensemble->name() ).arg( m_summaryCase->displayCaseName() );
}
else if ( m_ensemble )
{
caseText = m_ensemble->name();
}

View File

@ -33,7 +33,7 @@
#include "RiuPlotAnnotationTool.h"
#include "RiuPlotCurve.h"
#include "RiuPlotCurveInfoTextProvider.h"
#include "RiuQwtCurvePointTracker.h"
#include "RiuQwtPlotTools.h"
#include "qwt_plot.h"
@ -45,139 +45,6 @@
#include <QWheelEvent>
class RiuWellLogCurvePointTracker : public RiuQwtCurvePointTracker
{
public:
RiuWellLogCurvePointTracker( QwtPlot* plot, RiuPlotCurveInfoTextProvider* curveInfoTextProvider, RimWellLogTrack* track )
: RiuQwtCurvePointTracker( plot, false, curveInfoTextProvider )
, m_wellLogTrack( track )
{
}
protected:
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QwtText trackerText( const QPoint& pos ) const override
{
QwtText txt;
if ( m_plot )
{
QwtAxisId relatedYAxis( QwtAxis::YLeft, 0 );
QwtAxisId relatedXAxis( QwtAxis::XTop, 0 );
QString curveInfoText;
QString depthAxisValueString;
QString xAxisValueString;
QPointF closestPoint =
closestCurvePoint( pos, &curveInfoText, &xAxisValueString, &depthAxisValueString, &relatedXAxis, &relatedYAxis );
if ( !closestPoint.isNull() )
{
QString str;
RimWellLogPlot* wlp = nullptr;
m_wellLogTrack->firstAncestorOfType( wlp );
if ( wlp && wlp->depthOrientation() == RiaDefines::Orientation::HORIZONTAL )
{
str = QString( "%1\nDepth: %2" ).arg( depthAxisValueString ).arg( xAxisValueString );
}
else
{
str = QString( "%1\nDepth: %2" ).arg( xAxisValueString ).arg( depthAxisValueString );
}
if ( !curveInfoText.isEmpty() )
{
str = QString( "%1:\n" ).arg( curveInfoText ) + str;
}
txt.setText( str );
}
updateClosestCurvePointMarker( closestPoint, relatedXAxis, relatedYAxis );
}
auto color = RiuGuiTheme::getColorByVariableName( "markerColor" );
txt.setColor( color );
return txt;
}
private:
caf::PdmPointer<RimWellLogTrack> m_wellLogTrack;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class WellLogCurveInfoTextProvider : public RiuPlotCurveInfoTextProvider
{
public:
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString curveInfoText( RiuPlotCurve* riuCurve ) const override
{
if ( riuCurve )
{
RimWellLogCurve* wlCurve = dynamic_cast<RimWellLogCurve*>( riuCurve->ownerRimCurve() );
if ( wlCurve )
{
return QString( "%1" ).arg( wlCurve->curveName() );
}
}
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString additionalText( RiuPlotCurve* curve, int sampleIndex ) const override
{
if ( !curve ) return {};
std::vector<std::pair<QString, double>> propertyNameValues;
auto* sourceCurve = curve->ownerRimCurve();
if ( !sourceCurve ) return {};
auto annotationCurves = sourceCurve->additionalDataSources();
for ( auto annotationCurve : annotationCurves )
{
RimDepthTrackPlot* depthTrackPlot = nullptr;
annotationCurve->firstAncestorOfType( depthTrackPlot );
if ( depthTrackPlot )
{
auto [xValue, yValue] = curve->sample( sampleIndex );
auto depth = depthTrackPlot->depthOrientation() == RiaDefines::Orientation::VERTICAL ? yValue : xValue;
auto propertyValue = annotationCurve->closestYValueForX( depth );
// Use template to get as short label as possible. The default curve name will often
// contain too much and redundant information.
QString templateText = RiaDefines::namingVariableResultName() + ", " +
RiaDefines::namingVariableResultType();
auto resultName = annotationCurve->createCurveNameFromTemplate( templateText );
propertyNameValues.push_back( std::make_pair( resultName, propertyValue ) );
}
}
QString txt;
for ( const auto& [name, value] : propertyNameValues )
{
txt += QString( "%1 : %2\n" ).arg( name ).arg( value );
}
return txt;
}
};
static WellLogCurveInfoTextProvider wellLogCurveInfoTextProvider;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -194,8 +61,6 @@ RiuWellLogTrack::RiuWellLogTrack( RimWellLogTrack* track, QWidget* parent /*= nu
setAxisEnabled( QwtAxis::XBottom, isVertical );
m_annotationTool = std::make_unique<RiuPlotAnnotationTool>();
new RiuWellLogCurvePointTracker( this->qwtPlot(), &wellLogCurveInfoTextProvider, track );
}
//--------------------------------------------------------------------------------------------------
@ -293,3 +158,63 @@ void RiuWellLogTrack::onMouseMoveEvent( QMouseEvent* mouseEvent )
if ( wellLogTrack ) wellLogTrack->updateDepthMarkerLine();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuWellLogCurvePointTracker::RiuWellLogCurvePointTracker( QwtPlot* plot,
RiuPlotCurveInfoTextProvider* curveInfoTextProvider,
RimWellLogTrack* track )
: RiuQwtCurvePointTracker( plot, false, curveInfoTextProvider )
, m_wellLogTrack( track )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QwtText RiuWellLogCurvePointTracker::trackerText( const QPoint& pos ) const
{
QwtText txt;
if ( m_plot )
{
QwtAxisId relatedYAxis( QwtAxis::YLeft, 0 );
QwtAxisId relatedXAxis( QwtAxis::XTop, 0 );
QString curveInfoText;
QString depthAxisValueString;
QString xAxisValueString;
QPointF closestPoint =
closestCurvePoint( pos, &curveInfoText, &xAxisValueString, &depthAxisValueString, &relatedXAxis, &relatedYAxis );
if ( !closestPoint.isNull() )
{
QString str;
RimWellLogPlot* wlp = nullptr;
m_wellLogTrack->firstAncestorOfType( wlp );
if ( wlp && wlp->depthOrientation() == RiaDefines::Orientation::HORIZONTAL )
{
str = QString( "%1\nDepth: %2" ).arg( depthAxisValueString ).arg( xAxisValueString );
}
else
{
str = QString( "%1\nDepth: %2" ).arg( xAxisValueString ).arg( depthAxisValueString );
}
if ( !curveInfoText.isEmpty() )
{
str = QString( "%1:\n" ).arg( curveInfoText ) + str;
}
txt.setText( str );
}
updateClosestCurvePointMarker( closestPoint, relatedXAxis, relatedYAxis );
}
auto color = RiuGuiTheme::getColorByVariableName( "markerColor" );
txt.setColor( color );
return txt;
}

View File

@ -18,6 +18,7 @@
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiuQwtCurvePointTracker.h"
#include "RiuQwtPlotWidget.h"
#include "qwt_plot.h"
@ -51,3 +52,20 @@ private:
private:
std::unique_ptr<RiuPlotAnnotationTool> m_annotationTool;
};
//==================================================================================================
//
//
//
//==================================================================================================
class RiuWellLogCurvePointTracker : public RiuQwtCurvePointTracker
{
public:
RiuWellLogCurvePointTracker( QwtPlot* plot, RiuPlotCurveInfoTextProvider* curveInfoTextProvider, RimWellLogTrack* track );
protected:
QwtText trackerText( const QPoint& pos ) const override;
private:
caf::PdmPointer<RimWellLogTrack> m_wellLogTrack;
};