From eb97ee0de8fa6f6381f0bdd932bb7ec6986515a7 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen <kristian.bendiksen@gmail.com> Date: Thu, 27 Feb 2020 13:35:14 +0100 Subject: [PATCH 1/2] #5583 Add data model object and ui for RimElementVectorResult. --- .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../ProjectDataModel/RimEclipseView.cpp | 26 ++ .../ProjectDataModel/RimEclipseView.h | 3 + .../RimElementVectorResult.cpp | 412 ++++++++++++++++++ .../ProjectDataModel/RimElementVectorResult.h | 112 +++++ 5 files changed, 555 insertions(+) create mode 100644 ApplicationCode/ProjectDataModel/RimElementVectorResult.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimElementVectorResult.h diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 061a931b4f..dd554c5096 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -151,6 +151,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementFilter.h ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementInViewCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementInView.h ${CMAKE_CURRENT_LIST_DIR}/RimWellDiskConfig.h +${CMAKE_CURRENT_LIST_DIR}/RimElementVectorResult.h ) @@ -306,6 +307,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementFilter.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementInViewCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellMeasurementInView.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellDiskConfig.cpp +${CMAKE_CURRENT_LIST_DIR}/RimElementVectorResult.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationCode/ProjectDataModel/RimEclipseView.cpp index a8713cec14..82d0f58784 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseView.cpp @@ -51,6 +51,7 @@ #include "RimEclipsePropertyFilter.h" #include "RimEclipsePropertyFilterCollection.h" #include "RimEclipseResultDefinition.h" +#include "RimElementVectorResult.h" #include "RimExtrudedCurveIntersection.h" #include "RimFaultInViewCollection.h" #include "RimFlowCharacteristicsPlot.h" @@ -137,6 +138,15 @@ RimEclipseView::RimEclipseView() m_cellEdgeResult = new RimCellEdgeColors(); m_cellEdgeResult.uiCapability()->setUiHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_elementVectorResult, + "ElementVectorResult", + "Element Vector Result", + ":/CellResult.png", + "", + "" ); + m_elementVectorResult = new RimElementVectorResult; + m_elementVectorResult.uiCapability()->setUiHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_faultResultSettings, "FaultResultSettings", "Separate Fault Result", "", "", "" ); m_faultResultSettings = new RimEclipseFaultColors(); m_faultResultSettings.uiCapability()->setUiHidden( true ); @@ -198,6 +208,7 @@ RimEclipseView::~RimEclipseView() delete this->faultResultSettings(); delete this->cellResult(); delete this->cellEdgeResult(); + delete this->elementVectorResult(); delete m_propertyFilterCollection; delete wellCollection(); @@ -225,6 +236,14 @@ RimCellEdgeColors* RimEclipseView::cellEdgeResult() const return m_cellEdgeResult; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimElementVectorResult* RimEclipseView::elementVectorResult() const +{ + return m_elementVectorResult; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1305,6 +1324,12 @@ void RimEclipseView::onUpdateLegends() } } + if ( this->elementVectorResult()->showResult() ) + { + this->elementVectorResult()->updateLegendRangesTextAndVisibility( nativeOrOverrideViewer(), + isUsingOverrideViewer() ); + } + { bool hasAnyVisibleFractures = false; { @@ -1757,6 +1782,7 @@ void RimEclipseView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin uiTreeOrdering.add( cellResult() ); uiTreeOrdering.add( cellEdgeResult() ); + uiTreeOrdering.add( elementVectorResult() ); uiTreeOrdering.add( faultResultSettings() ); uiTreeOrdering.add( &m_intersectionResultDefCollection ); uiTreeOrdering.add( &m_surfaceResultDefCollection ); diff --git a/ApplicationCode/ProjectDataModel/RimEclipseView.h b/ApplicationCode/ProjectDataModel/RimEclipseView.h index 9835a2d3f6..bce9b202fa 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseView.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseView.h @@ -62,6 +62,7 @@ class RivReservoirViewPartMgr; class RimRegularLegendConfig; class RimTernaryLegendConfig; class RimEclipseResultDefinition; +class RimElementVectorResult; namespace cvf { @@ -85,6 +86,7 @@ public: RimEclipseCellColors* cellResult() const; RimCellEdgeColors* cellEdgeResult() const; + RimElementVectorResult* elementVectorResult() const; RimEclipseFaultColors* faultResultSettings() const; RimStimPlanColors* fractureColors() const; RimSimWellInViewCollection* wellCollection() const; @@ -202,6 +204,7 @@ private: caf::PdmChildField<RimEclipseCellColors*> m_cellResult; caf::PdmChildField<RimCellEdgeColors*> m_cellEdgeResult; + caf::PdmChildField<RimElementVectorResult*> m_elementVectorResult; caf::PdmChildField<RimEclipseFaultColors*> m_faultResultSettings; caf::PdmChildField<RimStimPlanColors*> m_fractureColors; caf::PdmChildField<RimVirtualPerforationResults*> m_virtualPerforationResult; diff --git a/ApplicationCode/ProjectDataModel/RimElementVectorResult.cpp b/ApplicationCode/ProjectDataModel/RimElementVectorResult.cpp new file mode 100644 index 0000000000..fd17f70409 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimElementVectorResult.cpp @@ -0,0 +1,412 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020- 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 "RimElementVectorResult.h" + +#include "RigCaseCellResultsData.h" +#include "RigEclipseCaseData.h" +#include "RigEclipseResultAddress.h" + +#include "Rim3dView.h" +#include "RimEclipseCase.h" +#include "RimEclipseView.h" + +#include "RiuViewer.h" + +#include "cafAppEnum.h" +#include "cafPdmUiListEditor.h" +#include "cafPdmUiTreeOrdering.h" + +CAF_PDM_SOURCE_INIT( RimElementVectorResult, "RimElementVectorResult" ); + +namespace caf +{ +template <> +void AppEnum<RimElementVectorResult::TensorColors>::setUp() +{ + addItem( RimElementVectorResult::RESULT_COLORS, "RESULT_COLORS", "Result Colors" ); + addItem( RimElementVectorResult::UNIFORM_COLOR, "UNIFORM_COLOR", "Uniform" ); + + setDefault( RimElementVectorResult::RESULT_COLORS ); +} + +template <> +void AppEnum<RimElementVectorResult::ScaleMethod>::setUp() +{ + addItem( RimElementVectorResult::RESULT, "RESULT", "Result" ); + addItem( RimElementVectorResult::CONSTANT, "CONSTANT", "Constant" ); + + setDefault( RimElementVectorResult::RESULT ); +} +} // namespace caf + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimElementVectorResult::RimElementVectorResult() +{ + CAF_PDM_InitObject( "Element Vector Result", ":/CellResult.png", "", "" ); + + CAF_PDM_InitFieldNoDefault( &m_legendConfig, "LegendDefinition", "Color Legend", "", "", "" ); + m_legendConfig = new RimRegularLegendConfig(); + m_legendConfig.uiCapability()->setUiHidden( true ); + + CAF_PDM_InitField( &m_resultName, "ResultVariable", QString( "Oil" ), "Value", "", "", "" ); + m_resultName.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() ); + m_resultName.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); + + CAF_PDM_InitField( &m_showResult, "ShowResult", false, "", "", "", "" ); + + CAF_PDM_InitField( &m_showVectorI, "ShowVectorI", true, "I", "", "", "" ); + CAF_PDM_InitField( &m_showVectorJ, "ShowVectorJ", true, "J", "", "", "" ); + CAF_PDM_InitField( &m_showVectorK, "ShowVectorK", true, "K", "", "", "" ); + CAF_PDM_InitField( &m_threshold, "Threshold", 0.0f, "Threshold", "", "", "" ); + + CAF_PDM_InitFieldNoDefault( &m_vectorColor, "VectorColor", "Color", "", "", "" ); + cvf::Color3f defaultUniformColor = cvf::Color3f::BLACK; + CAF_PDM_InitField( &m_uniformVectorColor, "UniformVectorColor", defaultUniformColor, "Uniform Vector Color", "", "", "" ); + + CAF_PDM_InitFieldNoDefault( &m_scaleMethod, "ScaleMethod", "Scale Method", "", "", "" ); + CAF_PDM_InitField( &m_sizeScale, "SizeScale", 1.0f, "Size Scale", "", "", "" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimElementVectorResult::~RimElementVectorResult() +{ + delete m_legendConfig; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimElementVectorResult::setShowResult( bool enableResult ) +{ + m_showResult = enableResult; + + updateConnectedEditors(); + updateUiIconFromState( enableResult ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimElementVectorResult::showResult() const +{ + return m_showResult(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimElementVectorResult::showVectorI() const +{ + return m_showVectorI(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimElementVectorResult::showVectorJ() const +{ + return m_showVectorJ(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + +bool RimElementVectorResult::showVectorK() const +{ + return m_showVectorK(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +float RimElementVectorResult::threshold() const +{ + return m_threshold(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +float RimElementVectorResult::sizeScale() const +{ + return m_sizeScale(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimElementVectorResult::TensorColors RimElementVectorResult::vectorColors() const +{ + return m_vectorColor(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimElementVectorResult::ScaleMethod RimElementVectorResult::scaleMethod() const +{ + return m_scaleMethod(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const cvf::Color3f& RimElementVectorResult::getUniformVectorColor() const +{ + return m_uniformVectorColor(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimElementVectorResult::mappingRange( double& min, double& max ) const +{ + min = cvf::UNDEFINED_DOUBLE; + max = cvf::UNDEFINED_DOUBLE; + + Rim3dView* view = nullptr; + firstAncestorOrThisOfType( view ); + + int currentTimeStep = view->currentTimeStep(); + + RigEclipseResultAddress resVarAddr = resultAddressCombined(); + if ( !resVarAddr.isValid() ) return; + + RimEclipseView* eclipseView = dynamic_cast<RimEclipseView*>( view ); + RigCaseCellResultsData* resultsData = + eclipseView->eclipseCase()->eclipseCaseData()->results( RiaDefines::MATRIX_MODEL ); + + resultsData->ensureKnownResultLoaded( resVarAddr ); + + if ( m_legendConfig->rangeMode() == RimRegularLegendConfig::AUTOMATIC_ALLTIMESTEPS ) + { + resultsData->minMaxCellScalarValues( resVarAddr, min, max ); + } + else if ( m_legendConfig->rangeMode() == RimRegularLegendConfig::AUTOMATIC_CURRENT_TIMESTEP ) + { + resultsData->minMaxCellScalarValues( resVarAddr, currentTimeStep, min, max ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimElementVectorResult::updateLegendRangesTextAndVisibility( RiuViewer* nativeOrOverrideViewer, + bool isUsingOverrideViewer ) +{ + m_legendConfig->setTitle( QString( "Element Vector Result: \n" ) + resultName() ); + + double minResultValue; + double maxResultValue; + mappingRange( minResultValue, maxResultValue ); + m_legendConfig->setAutomaticRanges( minResultValue, maxResultValue, minResultValue, maxResultValue ); + + double posClosestToZero = HUGE_VAL; + double negClosestToZero = -HUGE_VAL; + m_legendConfig->setClosestToZeroValues( posClosestToZero, negClosestToZero, posClosestToZero, negClosestToZero ); + nativeOrOverrideViewer->addColorLegendToBottomLeftCorner( m_legendConfig->titledOverlayFrame(), isUsingOverrideViewer ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const RimRegularLegendConfig* RimElementVectorResult::legendConfig() const +{ + return m_legendConfig(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimElementVectorResult::resultName() const +{ + return m_resultName(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector<std::string> RimElementVectorResult::getResultMetaDataForUIFieldSetting() +{ + std::vector<std::string> fieldNames; + fieldNames.push_back( "Oil" ); + fieldNames.push_back( "Water" ); + fieldNames.push_back( "Gas" ); + + return fieldNames; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimElementVectorResult::fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) +{ + if ( changedField == &m_showResult ) + { + setShowResult( m_showResult ); + } + + RimEclipseView* view; + firstAncestorOrThisOfType( view ); + view->loadDataAndUpdate(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimElementVectorResult::objectToggleField() +{ + return &m_showResult; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList<caf::PdmOptionItemInfo> + RimElementVectorResult::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly ) +{ + QList<caf::PdmOptionItemInfo> options; + *useOptionsOnly = true; + + if ( fieldNeedingOptions == &m_resultName ) + { + std::vector<std::string> fieldCompNames = getResultMetaDataForUIFieldSetting(); + + for ( size_t oIdx = 0; oIdx < fieldCompNames.size(); ++oIdx ) + { + options.push_back( caf::PdmOptionItemInfo( QString::fromStdString( fieldCompNames[oIdx] ), + QString::fromStdString( fieldCompNames[oIdx] ) ) ); + } + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimElementVectorResult::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + uiOrdering.add( &m_resultName ); + + caf::PdmUiGroup* visibilityGroup = uiOrdering.addNewGroup( "Visibility" ); + visibilityGroup->add( &m_showVectorI ); + visibilityGroup->add( &m_showVectorJ ); + visibilityGroup->add( &m_showVectorK ); + visibilityGroup->add( &m_threshold ); + + caf::PdmUiGroup* vectorColorsGroup = uiOrdering.addNewGroup( "Vector Colors" ); + vectorColorsGroup->add( &m_vectorColor ); + if ( m_vectorColor == UNIFORM_COLOR ) + { + vectorColorsGroup->add( &m_uniformVectorColor ); + } + + caf::PdmUiGroup* vectorSizeGroup = uiOrdering.addNewGroup( "Vector Size" ); + vectorSizeGroup->add( &m_sizeScale ); + vectorSizeGroup->add( &m_scaleMethod ); + + uiOrdering.skipRemainingFields( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimElementVectorResult::defineEditorAttribute( const caf::PdmFieldHandle* field, + QString uiConfigName, + caf::PdmUiEditorAttribute* attribute ) +{ + if ( field == &m_resultName ) + { + caf::PdmUiListEditorAttribute* listEditAttr = dynamic_cast<caf::PdmUiListEditorAttribute*>( attribute ); + if ( listEditAttr ) + { + listEditAttr->m_heightHint = 50; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigEclipseResultAddress RimElementVectorResult::resultAddressCombined() const +{ + if ( resultName() == "Oil" ) + { + return RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, RiaDefines::combinedOilFluxResultName() ); + } + else if ( resultName() == "Gas" ) + { + return RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, RiaDefines::combinedGasFluxResultName() ); + } + else if ( resultName() == "Water" ) + { + return RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, RiaDefines::combinedWaterFluxResultName() ); + } + + return RigEclipseResultAddress(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimElementVectorResult::resultAddressIJK( std::vector<RigEclipseResultAddress>& addresses ) const +{ + addresses.clear(); + + // TODO: use enum?? + if ( resultName() == "Oil" ) + { + addresses.push_back( RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "FLROILI+" ) ); + addresses.push_back( RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "FLROILJ+" ) ); + addresses.push_back( RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "FLROILK+" ) ); + return true; + } + else if ( resultName() == "Gas" ) + { + addresses.push_back( RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "FLRGASI+" ) ); + addresses.push_back( RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "FLRGASJ+" ) ); + addresses.push_back( RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "FLRGASK+" ) ); + return true; + } + else if ( resultName() == "Water" ) + { + addresses.push_back( RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "FLRWATI+" ) ); + addresses.push_back( RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "FLRWATJ+" ) ); + addresses.push_back( RigEclipseResultAddress( RiaDefines::DYNAMIC_NATIVE, "FLRWATK+" ) ); + return true; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimElementVectorResult::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName ) +{ + uiTreeOrdering.add( &m_legendConfig ); + uiTreeOrdering.skipRemainingChildren(); +} diff --git a/ApplicationCode/ProjectDataModel/RimElementVectorResult.h b/ApplicationCode/ProjectDataModel/RimElementVectorResult.h new file mode 100644 index 0000000000..d772ff4fd6 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimElementVectorResult.h @@ -0,0 +1,112 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020- 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 "cafPdmChildField.h" +#include "cafPdmField.h" +#include "cafPdmFieldCvfColor.h" // Include to make Pdm work for cvf::Color +#include "cafPdmObject.h" + +#include "RigEclipseResultAddress.h" + +#include "RimRegularLegendConfig.h" + +#include <QList> + +#include <vector> + +class RimRegularLegendConfig; + +class RiuViewer; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimElementVectorResult : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + enum TensorColors + { + UNIFORM_COLOR, + RESULT_COLORS + }; + + enum ScaleMethod + { + RESULT, + CONSTANT + }; + +public: + RimElementVectorResult(); + ~RimElementVectorResult() override; + + void setShowResult( bool enableResult ); + bool showResult() const; + bool showVectorI() const; + bool showVectorJ() const; + bool showVectorK() const; + float threshold() const; + float sizeScale() const; + TensorColors vectorColors() const; + ScaleMethod scaleMethod() const; + + const cvf::Color3f& getUniformVectorColor() const; + const RimRegularLegendConfig* legendConfig() const; + + void mappingRange( double& min, double& max ) const; + + RigEclipseResultAddress resultAddressCombined() const; + bool resultAddressIJK( std::vector<RigEclipseResultAddress>& addresses ) const; + + QString resultName() const; + + void updateLegendRangesTextAndVisibility( RiuViewer* nativeOrOverrideViewer, bool isUsingOverrideViewer ); + +private: + std::vector<std::string> getResultMetaDataForUIFieldSetting(); + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + caf::PdmFieldHandle* objectToggleField() override; + QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void defineEditorAttribute( const caf::PdmFieldHandle* field, + QString uiConfigName, + caf::PdmUiEditorAttribute* attribute ) override; + void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; + + static QString fieldNameFromUi( const QString& uiFieldName ); + +private: + caf::PdmField<bool> m_showResult; + caf::PdmField<QString> m_resultName; + caf::PdmField<bool> m_showVectorI; + caf::PdmField<bool> m_showVectorJ; + caf::PdmField<bool> m_showVectorK; + caf::PdmField<float> m_threshold; + caf::PdmField<caf::AppEnum<TensorColors>> m_vectorColor; + caf::PdmField<cvf::Color3f> m_uniformVectorColor; + caf::PdmField<caf::AppEnum<ScaleMethod>> m_scaleMethod; + caf::PdmField<float> m_sizeScale; + caf::PdmField<RimRegularLegendConfig::RangeModeEnum> m_rangeMode; + caf::PdmChildField<RimRegularLegendConfig*> m_legendConfig; +}; From c464664c401420b7985b141b26f7ea5354a915bc Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen <kristian.bendiksen@gmail.com> Date: Mon, 2 Mar 2020 08:55:45 +0100 Subject: [PATCH 2/2] #5583 Add visualization for fluxes. --- .../ModelVisualization/CMakeLists_files.cmake | 2 + .../RivElementVectorResultPartMgr.cpp | 321 ++++++++++++++++++ .../RivElementVectorResultPartMgr.h | 84 +++++ .../RivReservoirPartMgr.cpp | 20 +- .../ModelVisualization/RivReservoirPartMgr.h | 9 +- .../RivReservoirViewPartMgr.cpp | 19 ++ .../RivReservoirViewPartMgr.h | 5 + .../ProjectDataModel/RimEclipseView.cpp | 33 ++ .../ProjectDataModel/RimEclipseView.h | 1 + 9 files changed, 491 insertions(+), 3 deletions(-) create mode 100644 ApplicationCode/ModelVisualization/RivElementVectorResultPartMgr.cpp create mode 100644 ApplicationCode/ModelVisualization/RivElementVectorResultPartMgr.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 22f34001ff..f4f9769204 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -57,6 +57,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RivMeasurementPartMgr.h ${CMAKE_CURRENT_LIST_DIR}/RivTextLabelSourceInfo.h ${CMAKE_CURRENT_LIST_DIR}/RivDiskGeometryGenerator.h ${CMAKE_CURRENT_LIST_DIR}/RivWellDiskPartMgr.h +${CMAKE_CURRENT_LIST_DIR}/RivElementVectorResultPartMgr.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -112,6 +113,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RivMeasurementPartMgr.cpp ${CMAKE_CURRENT_LIST_DIR}/RivTextLabelSourceInfo.cpp ${CMAKE_CURRENT_LIST_DIR}/RivDiskGeometryGenerator.cpp ${CMAKE_CURRENT_LIST_DIR}/RivWellDiskPartMgr.cpp +${CMAKE_CURRENT_LIST_DIR}/RivElementVectorResultPartMgr.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivElementVectorResultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivElementVectorResultPartMgr.cpp new file mode 100644 index 0000000000..2a13817747 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivElementVectorResultPartMgr.cpp @@ -0,0 +1,321 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020- 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 "RivElementVectorResultPartMgr.h" + +#include "RimEclipseCase.h" +#include "RimEclipseView.h" +#include "RimElementVectorResult.h" +#include "RimRegularLegendConfig.h" + +#include "RigActiveCellInfo.h" +#include "RigCaseCellResultsData.h" +#include "RigCell.h" +#include "RigEclipseCaseData.h" +#include "RigEclipseResultAddress.h" +#include "RigMainGrid.h" + +#include "cafEffectGenerator.h" + +#include "cvfDrawableGeo.h" +#include "cvfModelBasicList.h" +#include "cvfPart.h" +#include "cvfPrimitiveSetIndexedUInt.h" +#include "cvfShaderProgram.h" +#include "cvfStructGrid.h" +#include "cvfStructGridGeometryGenerator.h" + +#include <cmath> + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivElementVectorResultPartMgr::RivElementVectorResultPartMgr( RimEclipseView* reservoirView ) +{ + m_rimReservoirView = reservoirView; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivElementVectorResultPartMgr::~RivElementVectorResultPartMgr() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivElementVectorResultPartMgr::setTransform( cvf::Transform* scaleTransform ) +{ + m_scaleTransform = scaleTransform; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivElementVectorResultPartMgr::appendDynamicGeometryPartsToModel( cvf::ModelBasicList* model, size_t timeStepIndex ) +{ + CVF_ASSERT( model ); + + if ( m_rimReservoirView.isNull() ) return; + + RimEclipseCase* eclipseCase = m_rimReservoirView->eclipseCase(); + if ( !eclipseCase ) return; + + RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData(); + if ( !eclipseCaseData ) return; + + RimElementVectorResult* result = m_rimReservoirView->elementVectorResult(); + if ( !result ) return; + + if ( !result->showResult() ) return; + + std::vector<ElementVectorResultVisualization> tensorVisualizations; + + double characteristicCellSize = eclipseCase->characteristicCellSize(); + float arrowConstantScaling = 0.5 * result->sizeScale() * characteristicCellSize; + + double min, max; + result->mappingRange( min, max ); + + double maxAbsResult = 1.0; + if ( min != cvf::UNDEFINED_DOUBLE && max != cvf::UNDEFINED_DOUBLE ) + { + maxAbsResult = std::max( cvf::Math::abs( max ), cvf::Math::abs( min ) ); + } + + float arrowScaling = arrowConstantScaling; + if ( result->scaleMethod() == RimElementVectorResult::RESULT ) + { + arrowScaling = arrowConstantScaling / maxAbsResult; + } + + std::vector<RigEclipseResultAddress> addresses; + result->resultAddressIJK( addresses ); + + std::vector<cvf::StructGridInterface::FaceType> directions; + std::vector<RigEclipseResultAddress> resultAddresses; + if ( result->showVectorI() ) + { + directions.push_back( cvf::StructGridInterface::POS_I ); + resultAddresses.push_back( addresses[0] ); + } + if ( result->showVectorJ() ) + { + directions.push_back( cvf::StructGridInterface::POS_J ); + resultAddresses.push_back( addresses[1] ); + } + if ( result->showVectorK() ) + { + directions.push_back( cvf::StructGridInterface::POS_K ); + resultAddresses.push_back( addresses[2] ); + } + + RigCaseCellResultsData* resultsData = eclipseCaseData->results( RiaDefines::MATRIX_MODEL ); + RigActiveCellInfo* activeCellInfo = eclipseCaseData->activeCellInfo( RiaDefines::MATRIX_MODEL ); + + const cvf::Vec3d offset = eclipseCase->mainGrid()->displayModelOffset(); + + const std::vector<RigCell>& cells = eclipseCase->mainGrid()->globalCellArray(); + for ( int gcIdx = 0; gcIdx < static_cast<int>( cells.size() ); ++gcIdx ) + { + if ( !cells[gcIdx].isInvalid() && activeCellInfo->isActive( gcIdx ) ) + { + for ( int dir = 0; dir < static_cast<int>( directions.size() ); dir++ ) + { + size_t resultIdx = activeCellInfo->cellResultIndex( gcIdx ); + double resultValue = resultsData->cellScalarResults( resultAddresses[dir], timeStepIndex ).at( resultIdx ); + + if ( std::abs( resultValue ) >= result->threshold() ) + { + cvf::Vec3d faceCenter = cells[gcIdx].faceCenter( directions[dir] ) - offset; + cvf::Vec3d cellCenter = cells[gcIdx].center() - offset; + cvf::Vec3d faceNormal = ( faceCenter - cellCenter ).getNormalized() * arrowScaling; + + if ( result->scaleMethod() == RimElementVectorResult::RESULT ) + { + faceNormal *= std::abs( resultValue ); + } + + tensorVisualizations.push_back( + ElementVectorResultVisualization( faceCenter, faceNormal, resultValue ) ); + } + } + } + } + + if ( !tensorVisualizations.empty() ) + { + cvf::ref<cvf::Part> partIdx = createPart( *result, tensorVisualizations ); + partIdx->setTransform( m_scaleTransform.p() ); + partIdx->updateBoundingBox(); + model->addPart( partIdx.p() ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref<cvf::Part> + RivElementVectorResultPartMgr::createPart( const RimElementVectorResult& result, + const std::vector<ElementVectorResultVisualization>& tensorVisualizations ) const +{ + std::vector<uint> indices; + indices.reserve( tensorVisualizations.size() * 5 ); + + std::vector<cvf::Vec3f> vertices; + vertices.reserve( tensorVisualizations.size() * 5 ); + + uint counter = 0; + for ( ElementVectorResultVisualization tensor : tensorVisualizations ) + { + for ( const cvf::Vec3f& vertex : createArrowVertices( tensor ) ) + { + vertices.push_back( vertex ); + } + + for ( const uint& index : createArrowIndices( counter ) ) + { + indices.push_back( index ); + } + + counter += 5; + } + + cvf::ref<cvf::PrimitiveSetIndexedUInt> indexedUInt = new cvf::PrimitiveSetIndexedUInt( cvf::PrimitiveType::PT_LINES ); + cvf::ref<cvf::UIntArray> indexArray = new cvf::UIntArray( indices ); + + cvf::ref<cvf::DrawableGeo> drawable = new cvf::DrawableGeo(); + + indexedUInt->setIndices( indexArray.p() ); + drawable->addPrimitiveSet( indexedUInt.p() ); + + cvf::ref<cvf::Vec3fArray> vertexArray = new cvf::Vec3fArray( vertices ); + drawable->setVertexArray( vertexArray.p() ); + + cvf::ref<cvf::Vec2fArray> lineTexCoords = const_cast<cvf::Vec2fArray*>( drawable->textureCoordArray() ); + + if ( lineTexCoords.isNull() ) + { + lineTexCoords = new cvf::Vec2fArray; + } + + const cvf::ScalarMapper* activeScalerMapper = nullptr; + + cvf::ref<cvf::Effect> effect; + + auto vectorColors = result.vectorColors(); + if ( vectorColors == RimElementVectorResult::RESULT_COLORS ) + { + activeScalerMapper = result.legendConfig()->scalarMapper(); + createResultColorTextureCoords( lineTexCoords.p(), tensorVisualizations, activeScalerMapper ); + + caf::ScalarMapperMeshEffectGenerator meshEffGen( activeScalerMapper ); + effect = meshEffGen.generateCachedEffect(); + } + else + { + caf::SurfaceEffectGenerator surfaceGen( result.getUniformVectorColor(), caf::PO_1 ); + surfaceGen.enableLighting( !m_rimReservoirView->isLightingDisabled() ); + effect = surfaceGen.generateCachedEffect(); + } + + drawable->setTextureCoordArray( lineTexCoords.p() ); + + cvf::ref<cvf::Part> part = new cvf::Part; + part->setDrawable( drawable.p() ); + part->setEffect( effect.p() ); + + return part; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivElementVectorResultPartMgr::createResultColorTextureCoords( + cvf::Vec2fArray* textureCoords, + const std::vector<ElementVectorResultVisualization>& elementVectorResultVisualizations, + const cvf::ScalarMapper* mapper ) +{ + CVF_ASSERT( textureCoords ); + CVF_ASSERT( mapper ); + + size_t vertexCount = elementVectorResultVisualizations.size() * 5; + if ( textureCoords->size() != vertexCount ) textureCoords->reserve( vertexCount ); + + for ( auto evrViz : elementVectorResultVisualizations ) + { + for ( size_t vxIdx = 0; vxIdx < 5; ++vxIdx ) + { + cvf::Vec2f texCoord = mapper->mapToTextureCoord( evrViz.result ); + textureCoords->add( texCoord ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::array<cvf::Vec3f, 5> + RivElementVectorResultPartMgr::createArrowVertices( const ElementVectorResultVisualization& evrViz ) const +{ + std::array<cvf::Vec3f, 5> vertices; + + cvf::Vec3f headTop = evrViz.faceCenter + evrViz.faceNormal; + cvf::Vec3f shaftStart = evrViz.faceCenter; + + // Flip arrow for negative results + if ( evrViz.result < 0 ) + { + std::swap( headTop, shaftStart ); + } + + float headWidth = 0.05 * evrViz.faceNormal.length(); + + cvf::Vec3f headBottom = headTop - ( headTop - shaftStart ) * 0.2f; + + cvf::Vec3f headBottomDirection = evrViz.faceNormal ^ evrViz.faceCenter; + cvf::Vec3f arrowBottomSegment = headBottomDirection.getNormalized() * headWidth; + + vertices[0] = shaftStart; + vertices[1] = headBottom; + vertices[2] = headBottom + arrowBottomSegment; + vertices[3] = headBottom - arrowBottomSegment; + vertices[4] = headTop; + + return vertices; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::array<uint, 8> RivElementVectorResultPartMgr::createArrowIndices( uint startIndex ) const +{ + std::array<uint, 8> indices; + + indices[0] = startIndex; + indices[1] = startIndex + 1; + indices[2] = startIndex + 2; + indices[3] = startIndex + 3; + indices[4] = startIndex + 3; + indices[5] = startIndex + 4; + indices[6] = startIndex + 4; + indices[7] = startIndex + 2; + + return indices; +} diff --git a/ApplicationCode/ModelVisualization/RivElementVectorResultPartMgr.h b/ApplicationCode/ModelVisualization/RivElementVectorResultPartMgr.h new file mode 100644 index 0000000000..4d1f6bc720 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivElementVectorResultPartMgr.h @@ -0,0 +1,84 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020- 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 "cvfArray.h" +#include "cvfObject.h" +#include "cvfTransform.h" +#include "cvfVector3.h" + +#include "cafPdmPointer.h" +#include "cafTensor3.h" + +#include "RimTensorResults.h" + +#include <array> +#include <vector> + +namespace cvf +{ +class ModelBasicList; +class Part; +class ScalarMapper; +class ScalarMapperDiscreteLinear; +} // namespace cvf + +class RimEclipseView; +class RimElementVectorResult; + +class RivElementVectorResultPartMgr : public cvf::Object +{ +public: + RivElementVectorResultPartMgr( RimEclipseView* reservoirView ); + ~RivElementVectorResultPartMgr() override; + + void appendDynamicGeometryPartsToModel( cvf::ModelBasicList* model, size_t timeStepIndex ); + void setTransform( cvf::Transform* scaleTransform ); + +private: + struct ElementVectorResultVisualization + { + ElementVectorResultVisualization( cvf::Vec3d faceCenter, cvf::Vec3d faceNormal, double result ) + : faceCenter( faceCenter ) + , faceNormal( faceNormal ) + , result( result ) + { + } + + cvf::Vec3f faceCenter; + cvf::Vec3f faceNormal; + double result; + }; + +private: + cvf::ref<cvf::Part> createPart( const RimElementVectorResult& result, + const std::vector<ElementVectorResultVisualization>& tensorVisualizations ) const; + + static void + createResultColorTextureCoords( cvf::Vec2fArray* textureCoords, + const std::vector<ElementVectorResultVisualization>& elementVectorResultVisualizations, + const cvf::ScalarMapper* mapper ); + + std::array<cvf::Vec3f, 5> createArrowVertices( const ElementVectorResultVisualization& tensorVisualization ) const; + std::array<uint, 8> createArrowIndices( uint startIndex ) const; + +private: + caf::PdmPointer<RimEclipseView> m_rimReservoirView; + cvf::ref<cvf::Transform> m_scaleTransform; +}; diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp index 010351ccb4..654e76913d 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp @@ -24,6 +24,7 @@ #include "RimEclipseCase.h" +#include "RivElementVectorResultPartMgr.h" #include "RivGridPartMgr.h" #include "RivReservoirFaultsPartMgr.h" @@ -52,7 +53,8 @@ void RivReservoirPartMgr::clearAndSetReservoir( RivCellSetEnum cellSetType, if ( eclipseCase->mainGrid() ) { // Faults read from file are present only on main grid - m_faultsPartMgr = new RivReservoirFaultsPartMgr( eclipseCase->mainGrid(), reservoirView ); + m_faultsPartMgr = new RivReservoirFaultsPartMgr( eclipseCase->mainGrid(), reservoirView ); + m_elementVectorResultMgr = new RivElementVectorResultPartMgr( reservoirView ); } } } @@ -71,6 +73,11 @@ void RivReservoirPartMgr::setTransform( cvf::Transform* scaleTransform ) { m_faultsPartMgr->setTransform( scaleTransform ); } + + if ( m_elementVectorResultMgr.notNull() ) + { + m_elementVectorResultMgr->setTransform( scaleTransform ); + } } //-------------------------------------------------------------------------------------------------- @@ -163,6 +170,17 @@ void RivReservoirPartMgr::appendGridPartsToModel( cvf::ModelBasicList* model, co } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivReservoirPartMgr::appendElementVectorResultPartsToModel( cvf::ModelBasicList* model, size_t timeStepIndex ) +{ + if ( m_elementVectorResultMgr.notNull() ) + { + m_elementVectorResultMgr->appendDynamicGeometryPartsToModel( model, timeStepIndex ); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h index c3206cebfd..5b04a703a0 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h @@ -38,6 +38,7 @@ class RigEclipseCaseData; class RimEclipseView; class RivReservoirFaultsPartMgr; class RivGridPartMgr; +class RivElementVectorResultPartMgr; //================================================================================================== /// @@ -76,9 +77,13 @@ public: void appendFaultPartsToModel( cvf::ModelBasicList* model ); void appendFaultLabelPartsToModel( cvf::ModelBasicList* model ); + // Element Vector Result + void appendElementVectorResultPartsToModel( cvf::ModelBasicList* model, size_t timeStepIndex ); + private: - cvf::Collection<RivGridPartMgr> m_allGrids; // Main grid and all LGR's - cvf::ref<RivReservoirFaultsPartMgr> m_faultsPartMgr; + cvf::Collection<RivGridPartMgr> m_allGrids; // Main grid and all LGR's + cvf::ref<RivElementVectorResultPartMgr> m_elementVectorResultMgr; + cvf::ref<RivReservoirFaultsPartMgr> m_faultsPartMgr; RivCellSetEnum m_cellSetType; }; diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index b6446126b8..125071728a 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -43,6 +43,7 @@ #include "RimViewController.h" #include "RimViewLinker.h" +#include "RivElementVectorResultPartMgr.h" #include "RivGridPartMgr.h" #include "RivReservoirFaultsPartMgr.h" @@ -1174,6 +1175,24 @@ void RivReservoirViewPartMgr::appendFaultLabelsDynamicGeometryPartsToModel( cvf: m_propFilteredGeometryFrames[frameIndex]->appendFaultLabelPartsToModel( model ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivReservoirViewPartMgr::appendElementVectorResultDynamicGeometryPartsToModel( cvf::ModelBasicList* model, + RivCellSetEnum geometryType, + size_t frameIndex ) +{ + ensureDynamicGeometryPartsCreated( geometryType, frameIndex ); + if ( geometryType == PROPERTY_FILTERED ) + { + m_propFilteredGeometryFrames[frameIndex]->appendElementVectorResultPartsToModel( model, frameIndex ); + } + else if ( geometryType == PROPERTY_FILTERED_WELL_CELLS ) + { + m_propFilteredWellGeometryFrames[frameIndex]->appendElementVectorResultPartsToModel( model, frameIndex ); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h index 2c5c42a7e2..41ea7510db 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h @@ -90,6 +90,11 @@ public: RivCellSetEnum geometryType, size_t frameIndex ); + // Element Vector Result + void appendElementVectorResultDynamicGeometryPartsToModel( cvf::ModelBasicList* model, + RivCellSetEnum geometryType, + size_t frameIndex ); + void forceWatertightGeometryOnForType( RivCellSetEnum geometryType ); void clearWatertightGeometryFlags(); diff --git a/ApplicationCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationCode/ProjectDataModel/RimEclipseView.cpp index 82d0f58784..89a6a5f58e 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseView.cpp @@ -657,6 +657,8 @@ void RimEclipseView::onUpdateDisplayModelForCurrentTimeStep() appendWellsAndFracturesToModel(); + appendElementVectorResultToModel(); + m_overlayInfoConfig()->update3DInfo(); // Invisible Wells are marked as read only when "show wells intersecting visible cells" is enabled @@ -910,6 +912,37 @@ void RimEclipseView::appendWellsAndFracturesToModel() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseView::appendElementVectorResultToModel() +{ + if ( nativeOrOverrideViewer() ) + { + cvf::Scene* frameScene = nativeOrOverrideViewer()->frame( m_currentTimeStep, isUsingOverrideViewer() ); + if ( frameScene ) + { + // Element Vector Results + cvf::String name = "ElementVectorModelMod"; + this->removeModelByName( frameScene, name ); + + cvf::ref<cvf::ModelBasicList> frameParts = new cvf::ModelBasicList; + frameParts->setName( name ); + + m_reservoirGridPartManager->appendElementVectorResultDynamicGeometryPartsToModel( frameParts.p(), + PROPERTY_FILTERED, + m_currentTimeStep ); + + // TODO: should this be ACTIVE? + m_reservoirGridPartManager->appendElementVectorResultDynamicGeometryPartsToModel( frameParts.p(), + PROPERTY_FILTERED_WELL_CELLS, + m_currentTimeStep ); + + frameScene->addModel( frameParts.p() ); + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimEclipseView.h b/ApplicationCode/ProjectDataModel/RimEclipseView.h index bce9b202fa..1868eebb90 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseView.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseView.h @@ -160,6 +160,7 @@ protected: void onUpdateDisplayModelForCurrentTimeStep() override; void updateVisibleGeometriesAndCellColors(); void appendWellsAndFracturesToModel(); + void appendElementVectorResultToModel(); void onCreateDisplayModel() override; RimPropertyFilterCollection* nativePropertyFilterCollection();