From e5fa4ae8c46947b7792c54afe9e0156b78f83a99 Mon Sep 17 00:00:00 2001 From: jonjenssen <69144954+jonjenssen@users.noreply.github.com> Date: Mon, 4 Sep 2023 15:48:08 +0200 Subject: [PATCH] Support filtering on element sets (#10570) * Add support for filtering on element sets in geomech cases --- .../CellFilterCommands/CMakeLists_files.cmake | 2 + .../RicNewCellIndexFilterFeature.cpp | 78 ++++++++ .../RicNewCellIndexFilterFeature.h | 34 ++++ .../GeoMech/GeoMechDataModel/RigFemPart.cpp | 44 ++++- .../GeoMech/GeoMechDataModel/RigFemPart.h | 7 + .../OdbReader/RifGeoMechReaderInterface.h | 4 +- .../GeoMech/OdbReader/RifOdbReader.cpp | 37 ++-- .../GeoMech/OdbReader/RifOdbReader.h | 4 +- .../CellFilters/CMakeLists_files.cmake | 2 + .../CellFilters/RimCellFilter.cpp | 62 ++++-- .../CellFilters/RimCellFilter.h | 11 ++ .../CellFilters/RimCellFilterCollection.cpp | 26 ++- .../CellFilters/RimCellFilterCollection.h | 2 + .../CellFilters/RimCellIndexFilter.cpp | 180 ++++++++++++++++++ .../CellFilters/RimCellIndexFilter.h | 52 +++++ .../CellFilters/RimCellRangeFilter.cpp | 9 +- .../CellFilters/RimCellRangeFilter.h | 9 +- .../CellFilters/RimPolygonFilter.cpp | 15 +- .../CellFilters/RimPolygonFilter.h | 2 - .../RimContextCommandBuilder.cpp | 1 + .../ProjectDataModel/RimTools.cpp | 73 +++++++ .../ProjectDataModel/RimTools.h | 5 + .../WellLog/RimWellLogExtractionCurve.cpp | 10 +- 23 files changed, 597 insertions(+), 72 deletions(-) create mode 100644 ApplicationLibCode/Commands/CellFilterCommands/RicNewCellIndexFilterFeature.cpp create mode 100644 ApplicationLibCode/Commands/CellFilterCommands/RicNewCellIndexFilterFeature.h create mode 100644 ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.h diff --git a/ApplicationLibCode/Commands/CellFilterCommands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/CellFilterCommands/CMakeLists_files.cmake index 812877b9aa..87b4eebf31 100644 --- a/ApplicationLibCode/Commands/CellFilterCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/CellFilterCommands/CMakeLists_files.cmake @@ -8,6 +8,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicNewRangeFilterSliceKFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewRangeFilterSlice3dviewFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewPolygonFilter3dviewFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicNewCellIndexFilterFeature.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -20,6 +21,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicNewRangeFilterSliceKFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewRangeFilterSlice3dviewFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewPolygonFilter3dviewFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewCellIndexFilterFeature.cpp ) list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/Commands/CellFilterCommands/RicNewCellIndexFilterFeature.cpp b/ApplicationLibCode/Commands/CellFilterCommands/RicNewCellIndexFilterFeature.cpp new file mode 100644 index 0000000000..95121dd465 --- /dev/null +++ b/ApplicationLibCode/Commands/CellFilterCommands/RicNewCellIndexFilterFeature.cpp @@ -0,0 +1,78 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicNewCellIndexFilterFeature.h" + +#include "RiaApplication.h" + +#include "RimCase.h" +#include "RimCellFilterCollection.h" +#include "RimCellIndexFilter.h" +#include "RimGeoMechCase.h" +#include "RimGridView.h" +#include "RimUserDefinedFilter.h" +#include "Riu3DMainWindowTools.h" + +#include "cafSelectionManagerTools.h" +#include "cafUtils.h" + +#include + +CAF_CMD_SOURCE_INIT( RicNewCellIndexFilterFeature, "RicNewCellIndexFilterFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewCellIndexFilterFeature::isCommandEnabled() const +{ + RimGridView* view = RiaApplication::instance()->activeGridView(); + if ( !view ) return false; + + RimGeoMechCase* gCase = dynamic_cast( view->ownerCase() ); + + return gCase != nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewCellIndexFilterFeature::onActionTriggered( bool isChecked ) +{ + // Find the selected Cell Filter Collection + std::vector colls = caf::selectedObjectsByTypeStrict(); + if ( colls.empty() ) return; + RimCellFilterCollection* filtColl = colls[0]; + + // and the case to use + RimCase* sourceCase = filtColl->firstAncestorOrThisOfTypeAsserted(); + + RimCellIndexFilter* lastCreatedOrUpdated = filtColl->addNewCellIndexFilter( sourceCase ); + if ( lastCreatedOrUpdated ) + { + Riu3DMainWindowTools::selectAsCurrentItem( lastCreatedOrUpdated ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewCellIndexFilterFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setIcon( QIcon( ":/CellFilter_UserDefined.png" ) ); + actionToSetup->setText( "New Element Set Filter" ); +} diff --git a/ApplicationLibCode/Commands/CellFilterCommands/RicNewCellIndexFilterFeature.h b/ApplicationLibCode/Commands/CellFilterCommands/RicNewCellIndexFilterFeature.h new file mode 100644 index 0000000000..813b392f08 --- /dev/null +++ b/ApplicationLibCode/Commands/CellFilterCommands/RicNewCellIndexFilterFeature.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicNewCellIndexFilterFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() const override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/GeoMech/GeoMechDataModel/RigFemPart.cpp b/ApplicationLibCode/GeoMech/GeoMechDataModel/RigFemPart.cpp index 7bd2c17882..ebe1038bd9 100644 --- a/ApplicationLibCode/GeoMech/GeoMechDataModel/RigFemPart.cpp +++ b/ApplicationLibCode/GeoMech/GeoMechDataModel/RigFemPart.cpp @@ -146,7 +146,7 @@ bool RigFemPart::fillElementCoordinates( size_t elementIdx, std::array& elementIds ) +{ + m_elementSetNames.push_back( name ); + + std::map idToIndex; + + for ( size_t i = 0; i < m_elementId.size(); i++ ) + { + idToIndex[m_elementId[i]] = i; + } + + std::vector elementIndexes; + elementIndexes.resize( elementIds.size() ); + + for ( size_t i = 0; i < elementIds.size(); i++ ) + { + elementIndexes[i] = idToIndex[elementIds[i] + 1]; + } + + m_elementIndexSets.push_back( elementIndexes ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigFemPart::elementSetNames() const +{ + return m_elementSetNames; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigFemPart::elementSet( int setIndex ) const +{ + if ( ( setIndex < 0 ) || ( setIndex >= (int)m_elementIndexSets.size() ) ) return {}; + return m_elementIndexSets[setIndex]; +} diff --git a/ApplicationLibCode/GeoMech/GeoMechDataModel/RigFemPart.h b/ApplicationLibCode/GeoMech/GeoMechDataModel/RigFemPart.h index 91b7ffa189..06aa53b17c 100644 --- a/ApplicationLibCode/GeoMech/GeoMechDataModel/RigFemPart.h +++ b/ApplicationLibCode/GeoMech/GeoMechDataModel/RigFemPart.h @@ -102,6 +102,10 @@ public: void setEnabled( bool enable ); bool enabled() const; + void addElementSet( std::string name, const std::vector& elementIds ); + std::vector elementSetNames() const; + std::vector elementSet( int setIndex ) const; + private: int m_elementPartId; std::string m_name; @@ -112,6 +116,9 @@ private: std::vector m_elementConnectivityStartIndices; std::vector m_allElementConnectivities; + std::vector m_elementSetNames; + std::vector> m_elementIndexSets; + RigFemPartNodes m_nodes; mutable cvf::ref m_structGrid; diff --git a/ApplicationLibCode/GeoMech/OdbReader/RifGeoMechReaderInterface.h b/ApplicationLibCode/GeoMech/OdbReader/RifGeoMechReaderInterface.h index 7671955b37..ed983ecd1e 100644 --- a/ApplicationLibCode/GeoMech/OdbReader/RifGeoMechReaderInterface.h +++ b/ApplicationLibCode/GeoMech/OdbReader/RifGeoMechReaderInterface.h @@ -47,8 +47,8 @@ public: virtual std::vector frameTimes( int stepIndex ) const = 0; virtual int frameCount( int stepIndex ) const = 0; - virtual std::vector elementSetNames( int partIndex ) = 0; - virtual std::vector elementSet( int partIndex, int setIndex ) = 0; + virtual std::vector elementSetNames( int partIndex, std::string partName ) = 0; + virtual std::vector elementSet( int partIndex, std::string partName, int setIndex ) = 0; virtual std::map> scalarNodeFieldAndComponentNames() = 0; virtual std::map> scalarElementNodeFieldAndComponentNames() = 0; diff --git a/ApplicationLibCode/GeoMech/OdbReader/RifOdbReader.cpp b/ApplicationLibCode/GeoMech/OdbReader/RifOdbReader.cpp index 18926c01ef..1b7ba02356 100644 --- a/ApplicationLibCode/GeoMech/OdbReader/RifOdbReader.cpp +++ b/ApplicationLibCode/GeoMech/OdbReader/RifOdbReader.cpp @@ -322,8 +322,8 @@ bool RifOdbReader::readFemParts( RigFemPartCollection* femParts ) caf::ProgressInfo modelProgress( instanceRepository.size() * (size_t)( 2 + 4 ), "Reading Odb Parts" ); - int instanceCount = 0; - for ( iter.first(); !iter.isDone(); iter.next(), instanceCount++ ) + int partIdx = 0; + for ( iter.first(); !iter.isDone(); iter.next(), partIdx++ ) { modelProgress.setProgressDescription( QString( iter.currentKey().cStr() ) + ": Reading Nodes" ); m_nodeIdToIdxMaps.push_back( std::map() ); @@ -404,7 +404,14 @@ bool RifOdbReader::readFemParts( RigFemPartCollection* femParts ) } } - femPart->setElementPartId( femParts->partCount() ); + // read element sets + auto setNames = elementSetNames( partIdx, femPart->name() ); + for ( int setIndex = 0; setIndex < (int)setNames.size(); setIndex++ ) + { + femPart->addElementSet( setNames[setIndex], elementSet( partIdx, femPart->name(), setIndex ) ); + } + + femPart->setElementPartId( partIdx ); femParts->addFemPart( femPart ); modelProgress.incrementProgress(); @@ -507,7 +514,7 @@ int RifOdbReader::frameCount( int stepIndex ) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RifOdbReader::elementSetNames( int partIndex ) +std::vector RifOdbReader::elementSetNames( int partIndex, std::string partInstanceName ) { CVF_ASSERT( m_odb != NULL ); @@ -533,7 +540,16 @@ std::vector RifOdbReader::elementSetNames( int partIndex ) for ( setIt.first(); !setIt.isDone(); setIt.next() ) { const odb_Set& set = setIt.currentValue(); - setNames.push_back( set.name().CStr() ); + + auto names = set.instanceNames(); + for ( int i = 0; i < names.size(); i++ ) + { + if ( names[i].CStr() == partInstanceName ) + { + setNames.push_back( set.name().CStr() ); + break; + } + } } break; @@ -549,17 +565,14 @@ std::vector RifOdbReader::elementSetNames( int partIndex ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RifOdbReader::elementSet( int partIndex, int setIndex ) +std::vector RifOdbReader::elementSet( int partIndex, std::string partName, int setIndex ) { CVF_ASSERT( m_odb != NULL ); - std::vector setNames = elementSetNames( partIndex ); - const odb_Assembly& rootAssembly = m_odb->constRootAssembly(); + const odb_Assembly& rootAssembly = m_odb->constRootAssembly(); + const odb_Set& set = rootAssembly.elementSets()[odb_String( m_partElementSetNames[partIndex][setIndex].c_str() )]; - const odb_Set& set = rootAssembly.elementSets()[odb_String( setNames[setIndex].c_str() )]; - odb_SequenceString instanceNames = set.instanceNames(); - - const odb_SequenceElement& setElements = set.elements( instanceNames[partIndex] ); + const odb_SequenceElement& setElements = set.elements( partName.c_str() ); int elementCount = setElements.size(); std::vector elementIndexes; diff --git a/ApplicationLibCode/GeoMech/OdbReader/RifOdbReader.h b/ApplicationLibCode/GeoMech/OdbReader/RifOdbReader.h index 615026b3b2..02193b43cf 100644 --- a/ApplicationLibCode/GeoMech/OdbReader/RifOdbReader.h +++ b/ApplicationLibCode/GeoMech/OdbReader/RifOdbReader.h @@ -49,8 +49,8 @@ public: std::vector frameTimes( int stepIndex ) const override; int frameCount( int stepIndex ) const override; - std::vector elementSetNames( int partIndex ) override; - std::vector elementSet( int partIndex, int setIndex ) override; + std::vector elementSetNames( int partIndex, std::string partName ) override; + std::vector elementSet( int partIndex, std::string partName, int setIndex ) override; std::map> scalarNodeFieldAndComponentNames() override; std::map> scalarElementNodeFieldAndComponentNames() override; diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/CellFilters/CMakeLists_files.cmake index c0ed2d0dc4..5f46fdfaa2 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/CMakeLists_files.cmake @@ -11,6 +11,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimPolygonFilter.h ${CMAKE_CURRENT_LIST_DIR}/RimUserDefinedFilter.h ${CMAKE_CURRENT_LIST_DIR}/RimCellFilterIntervalTool.h + ${CMAKE_CURRENT_LIST_DIR}/RimCellIndexFilter.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -26,6 +27,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimPolygonFilter.cpp ${CMAKE_CURRENT_LIST_DIR}/RimUserDefinedFilter.cpp ${CMAKE_CURRENT_LIST_DIR}/RimCellFilterIntervalTool.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimCellIndexFilter.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.cpp b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.cpp index ccf182f66c..0b1cdc212e 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.cpp +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.cpp @@ -21,8 +21,13 @@ #include "RigReservoirGridTools.h" #include "Rim3dView.h" #include "RimCase.h" +#include "RimEclipseCase.h" +#include "RimGeoMechCase.h" +#include "RimTools.h" #include "RimViewController.h" +#include "cafPdmUiComboBoxEditor.h" + #include "cvfStructGridGeometryGenerator.h" namespace caf @@ -52,9 +57,14 @@ RimCellFilter::RimCellFilter( FilterDefinitionType defType ) CAF_PDM_InitField( &m_isActive, "Active", true, "Active" ); m_isActive.uiCapability()->setUiHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_srcCase, "Case", "Case" ); + m_srcCase.uiCapability()->setUiHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_filterMode, "FilterType", "Filter Type" ); CAF_PDM_InitField( &m_gridIndex, "GridIndex", 0, "Grid" ); + m_gridIndex.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() ); + CAF_PDM_InitField( &m_propagateToSubGrids, "PropagateToSubGrids", true, "Apply to Subgrids" ); CAF_PDM_InitFieldNoDefault( &m_nameProxy, "NameProxy", "Name Proxy" ); @@ -147,6 +157,30 @@ bool RimCellFilter::isIndexFilter() const return m_filterDefinitionType == FilterDefinitionType::INDEX; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCellFilter::setCase( RimCase* srcCase ) +{ + m_srcCase = srcCase; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseCase* RimCellFilter::eclipseCase() const +{ + return dynamic_cast( m_srcCase() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimGeoMechCase* RimCellFilter::geoMechCase() const +{ + return dynamic_cast( m_srcCase() ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -226,6 +260,11 @@ void RimCellFilter::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering.add( &m_name ); auto group = uiOrdering.addNewGroup( "General" ); group->add( &m_filterMode ); + + if ( geoMechCase() != nullptr ) + { + m_gridIndex.uiCapability()->setUiName( "Part" ); + } group->add( &m_gridIndex ); bool readOnlyState = isFilterControlled(); @@ -269,27 +308,12 @@ QList RimCellFilter::calculateValueOptions( const caf::P { QList options; - if ( &m_gridIndex == fieldNeedingOptions ) + if ( fieldNeedingOptions == &m_gridIndex ) { - auto rimCase = firstAncestorOrThisOfTypeAsserted(); - - for ( int gIdx = 0; gIdx < RigReservoirGridTools::gridCount( rimCase ); ++gIdx ) - { - QString gridName; - - gridName += RigReservoirGridTools::gridName( rimCase, gIdx ); - if ( gIdx == 0 ) - { - if ( gridName.isEmpty() ) - gridName += "Main Grid"; - else - gridName += " (Main Grid)"; - } - - caf::PdmOptionItemInfo item( gridName, (int)gIdx ); - options.push_back( item ); - } + RimTools::eclipseGridOptionItems( &options, eclipseCase() ); + RimTools::geoMechPartOptionItems( &options, geoMechCase() ); } + return options; } diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.h b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.h index 3634bbdbb1..833960a7d6 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.h +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilter.h @@ -22,6 +22,7 @@ #include "cafPdmField.h" #include "cafPdmObject.h" #include "cafPdmProxyValueField.h" +#include "cafPdmPtrField.h" #include "cafSignal.h" #include "cvfArray.h" @@ -32,6 +33,10 @@ class StructGridInterface; class CellRangeFilter; } // namespace cvf +class RimGeoMechCase; +class RimEclipseCase; +class RimCase; + //================================================================================================== /// /// @@ -65,6 +70,8 @@ public: bool isActive() const; void setActive( bool active ); + virtual void setCase( RimCase* srcCase ); + bool isRangeFilter() const; bool isIndexFilter() const; @@ -91,6 +98,9 @@ protected: void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; bool isFilterControlled() const; + RimGeoMechCase* geoMechCase() const; + RimEclipseCase* eclipseCase() const; + const cvf::StructGridInterface* selectedGrid() const; QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; @@ -101,6 +111,7 @@ protected: caf::PdmField> m_filterMode; caf::PdmField m_gridIndex; caf::PdmField m_propagateToSubGrids; + caf::PdmPtrField m_srcCase; private: FilterDefinitionType m_filterDefinitionType; diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.cpp b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.cpp index 7b7eef8545..83e4e06b5c 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.cpp @@ -21,6 +21,7 @@ #include "Rim3dView.h" #include "RimCase.h" #include "RimCellFilter.h" +#include "RimCellIndexFilter.h" #include "RimCellRangeFilter.h" #include "RimPolygonFilter.h" #include "RimUserDefinedFilter.h" @@ -94,8 +95,7 @@ void RimCellFilterCollection::setCase( RimCase* theCase ) { for ( RimCellFilter* filter : m_cellFilters ) { - RimPolygonFilter* polyFilter = dynamic_cast( filter ); - if ( polyFilter ) polyFilter->setCase( theCase ); + filter->setCase( theCase ); } } @@ -125,8 +125,10 @@ void RimCellFilterCollection::initAfterRead() m_cellFilters.push_back( filter ); } + auto rimCase = firstAncestorOrThisOfTypeAsserted(); for ( const auto& filter : m_cellFilters ) { + filter->setCase( rimCase ); filter->filterChanged.connect( this, &RimCellFilterCollection::onFilterUpdated ); } } @@ -266,6 +268,7 @@ RimPolygonFilter* RimCellFilterCollection::addNewPolygonFilter( RimCase* srcCase RimUserDefinedFilter* RimCellFilterCollection::addNewUserDefinedFilter( RimCase* srcCase ) { RimUserDefinedFilter* pFilter = new RimUserDefinedFilter(); + pFilter->setCase( srcCase ); addFilter( pFilter ); onFilterUpdated( pFilter ); return pFilter; @@ -277,6 +280,7 @@ RimUserDefinedFilter* RimCellFilterCollection::addNewUserDefinedFilter( RimCase* RimCellRangeFilter* RimCellFilterCollection::addNewCellRangeFilter( RimCase* srcCase, int gridIndex, int sliceDirection, int defaultSlice ) { RimCellRangeFilter* pFilter = new RimCellRangeFilter(); + pFilter->setCase( srcCase ); addFilter( pFilter ); pFilter->setGridIndex( gridIndex ); pFilter->setDefaultValues( sliceDirection, defaultSlice ); @@ -284,6 +288,18 @@ RimCellRangeFilter* RimCellFilterCollection::addNewCellRangeFilter( RimCase* src return pFilter; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimCellIndexFilter* RimCellFilterCollection::addNewCellIndexFilter( RimCase* srcCase ) +{ + RimCellIndexFilter* pFilter = new RimCellIndexFilter(); + pFilter->setCase( srcCase ); + addFilter( pFilter ); + onFilterUpdated( pFilter ); + return pFilter; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -303,12 +319,14 @@ void RimCellFilterCollection::setAutoName( RimCellFilter* pFilter ) int nPolyFilters = 1; int nRangeFilters = 1; int nUserFilters = 1; + int nIndexFilters = 1; for ( RimCellFilter* filter : m_cellFilters ) { if ( dynamic_cast( filter ) ) nRangeFilters++; if ( dynamic_cast( filter ) ) nUserFilters++; if ( dynamic_cast( filter ) ) nPolyFilters++; + if ( dynamic_cast( filter ) ) nIndexFilters++; } if ( dynamic_cast( pFilter ) ) { @@ -322,6 +340,10 @@ void RimCellFilterCollection::setAutoName( RimCellFilter* pFilter ) { pFilter->setName( QString( "Polygon Filter %1" ).arg( QString::number( nPolyFilters ) ) ); } + else if ( dynamic_cast( pFilter ) ) + { + pFilter->setName( QString( "Index Filter %1" ).arg( QString::number( nIndexFilters ) ) ); + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.h b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.h index c7113bb046..0b39640881 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.h +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellFilterCollection.h @@ -26,6 +26,7 @@ #include "cvfArray.h" class RimCellFilter; +class RimCellIndexFilter; class RimCellRangeFilter; class RimPolygonFilter; class RimUserDefinedFilter; @@ -53,6 +54,7 @@ public: RimPolygonFilter* addNewPolygonFilter( RimCase* srcCase ); RimUserDefinedFilter* addNewUserDefinedFilter( RimCase* srcCase ); RimCellRangeFilter* addNewCellRangeFilter( RimCase* srcCase, int gridIndex, int sliceDirection = -1, int defaultSlice = -1 ); + RimCellIndexFilter* addNewCellIndexFilter( RimCase* srcCase ); void removeFilter( RimCellFilter* filter ); diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.cpp b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.cpp new file mode 100644 index 0000000000..0ec002fe0c --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.cpp @@ -0,0 +1,180 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimCellIndexFilter.h" + +#include "RimGeoMechCase.h" +#include "RimTools.h" + +#include "RigFemPart.h" +#include "RigFemPartCollection.h" +#include "RigGeoMechCaseData.h" + +#include "cafPdmUiComboBoxEditor.h" + +CAF_PDM_SOURCE_INIT( RimCellIndexFilter, "CellIndexFilter" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimCellIndexFilter::RimCellIndexFilter() + : RimCellFilter( RimCellFilter::INDEX ) +{ + CAF_PDM_InitObject( "Cell Index Filter", ":/CellFilter_UserDefined.png" ); + + CAF_PDM_InitField( &m_setId, "ElementSetId", 0, "Element Set" ); + m_setId.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() ); + + m_propagateToSubGrids = true; + + updateIconState(); + setDeletable( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimCellIndexFilter::~RimCellIndexFilter() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimCellIndexFilter::fullName() const +{ + return QString( "%1 [%2 cells]" ).arg( RimCellFilter::fullName(), QString::number( m_cells.size() ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCellIndexFilter::updateCellIndexFilter( cvf::UByteArray* includeVisibility, cvf::UByteArray* excludeVisibility, int gridIndex ) +{ + if ( gridIndex != m_gridIndex() ) return; + + if ( m_cells.size() == 0 ) + { + updateCells(); + } + + if ( m_filterMode == FilterModeType::INCLUDE ) + { + for ( auto cellIdx : m_cells ) + { + ( *includeVisibility )[cellIdx] = true; + } + } + else + { + for ( auto cellIdx : m_cells ) + { + ( *excludeVisibility )[cellIdx] = false; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCellIndexFilter::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + if ( changedField == &m_gridIndex ) + { + m_setId = 0; + } + + if ( changedField != &m_name ) + { + updateCells(); + filterChanged.send(); + updateIconState(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCellIndexFilter::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + m_gridIndex.uiCapability()->setUiName( "Part" ); + + auto group = uiOrdering.addNewGroup( "General" ); + group->add( &m_gridIndex ); + group->add( &m_setId ); + group->add( &m_filterMode ); + + uiOrdering.skipRemainingFields( true ); + + bool readOnlyState = isFilterControlled(); + + std::vector objFields = fields(); + for ( auto& objField : objFields ) + { + objField->uiCapability()->setUiReadOnly( readOnlyState ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimCellIndexFilter::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) +{ + QList options = RimCellFilter::calculateValueOptions( fieldNeedingOptions ); + + if ( fieldNeedingOptions == &m_setId ) + { + RimTools::geoMechElementSetOptionItems( &options, geoMechCase(), m_gridIndex() ); + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCellIndexFilter::updateCells() +{ + m_cells.clear(); + + auto gCase = geoMechCase(); + + if ( gCase && gCase->geoMechData() && gCase->geoMechData()->femParts() ) + { + auto parts = gCase->geoMechData()->femParts(); + + auto part = parts->part( m_gridIndex() ); + + auto setNames = part->elementSetNames(); + if ( m_setId() < (int)setNames.size() ) + { + m_name = QString::fromStdString( part->elementSetNames()[m_setId] ); + } + else + { + m_name = QString::fromStdString( part->name() ); + } + + auto cells = part->elementSet( m_setId() ); + + for ( auto c : cells ) + { + m_cells.push_back( c ); + } + } +} diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.h b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.h new file mode 100644 index 0000000000..76433e3766 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellIndexFilter.h @@ -0,0 +1,52 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCellFilter.h" + +#include "cafPdmField.h" +#include "cafPdmPtrField.h" + +class RimCase; +class RimGeoMechCase; + +class RimCellIndexFilter : public RimCellFilter +{ + CAF_PDM_HEADER_INIT; + +public: + RimCellIndexFilter(); + ~RimCellIndexFilter() override; + + void updateCellIndexFilter( cvf::UByteArray* includeVisibility, cvf::UByteArray* excludeVisibility, int gridIndex ) override; + +protected: + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; + + QString fullName() const override; + + void updateCells(); + +private: + std::vector m_cells; + + caf::PdmField m_setId; +}; diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.cpp b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.cpp index df08b381c3..f9142e3954 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.cpp +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.cpp @@ -25,6 +25,7 @@ #include "RigReservoirGridTools.h" #include "Rim3dView.h" #include "RimCase.h" +#include "RimTools.h" #include "cafPdmUiLabelEditor.h" #include "cafPdmUiSliderEditor.h" @@ -178,9 +179,8 @@ void RimCellRangeFilter::setDefaultValues( int sliceDirection, int defaultSlice auto rimView = firstAncestorOrThisOfType(); auto actCellInfo = RigReservoirGridTools::activeCellInfo( rimView ); - auto rimCase = firstAncestorOrThisOfTypeAsserted(); - const cvf::StructGridInterface* mainGrid = RigReservoirGridTools::mainGrid( rimCase ); + const cvf::StructGridInterface* mainGrid = RigReservoirGridTools::mainGrid( m_srcCase ); if ( grid == mainGrid && actCellInfo ) { @@ -271,12 +271,9 @@ void RimCellRangeFilter::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder { RimCellFilter::defineUiOrdering( uiConfigName, uiOrdering ); - m_gridIndex.uiCapability()->setUiReadOnly( true ); - const cvf::StructGridInterface* grid = selectedGrid(); - auto rimCase = firstAncestorOrThisOfTypeAsserted(); - const cvf::StructGridInterface* mainGrid = RigReservoirGridTools::mainGrid( rimCase ); + const cvf::StructGridInterface* mainGrid = RigReservoirGridTools::mainGrid( m_srcCase ); auto rimView = firstAncestorOrThisOfType(); auto actCellInfo = RigReservoirGridTools::activeCellInfo( rimView ); diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.h b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.h index 029e6cd216..5557169ff5 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.h +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.h @@ -60,10 +60,11 @@ public: void updateCompundFilter( cvf::CellRangeFilter* cellRangeFilter, int gridIndex ) override; protected: - void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; - void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; - void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; - void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName ) override; + QString fullName() const override; private: diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.cpp b/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.cpp index 6e531011e4..8281cc191c 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.cpp +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.cpp @@ -139,9 +139,6 @@ RimPolygonFilter::RimPolygonFilter() m_targets.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); m_targets.uiCapability()->setCustomContextMenuEnabled( true ); - CAF_PDM_InitFieldNoDefault( &m_srcCase, "Case", "Case" ); - m_srcCase.uiCapability()->setUiHidden( true ); - CAF_PDM_InitField( &m_showLines, "ShowLines", true, "Show Lines" ); CAF_PDM_InitField( &m_showSpheres, "ShowSpheres", false, "Show Spheres" ); @@ -204,14 +201,6 @@ void RimPolygonFilter::updateEditorsAndVisualization() updateVisualization(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimPolygonFilter::setCase( RimCase* srcCase ) -{ - m_srcCase = srcCase; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -840,8 +829,8 @@ void RimPolygonFilter::updateCells() // make sure first and last point is the same (req. by polygon methods used later) points.push_back( points.front() ); - RimEclipseCase* eCase = dynamic_cast( m_srcCase() ); - RimGeoMechCase* gCase = dynamic_cast( m_srcCase() ); + RimEclipseCase* eCase = eclipseCase(); + RimGeoMechCase* gCase = geoMechCase(); if ( eCase ) { diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.h b/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.h index 752b1101af..52975adf20 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.h +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimPolygonFilter.h @@ -73,7 +73,6 @@ public: RimPolygonFilter(); ~RimPolygonFilter() override; - void setCase( RimCase* srcCase ); void enableFilter( bool bEnable ); void enableKFilter( bool bEnable ); @@ -123,7 +122,6 @@ private: caf::PdmChildArrayField m_targets; caf::PdmField> m_polyFilterMode; caf::PdmField> m_polyIncludeType; - caf::PdmPtrField m_srcCase; caf::PdmField m_enableFiltering; caf::PdmField m_showLines; caf::PdmField m_showSpheres; diff --git a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp index 446137c388..eedabd3b0e 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -1035,6 +1035,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() { menuBuilder << "RicNewPolygonFilterFeature"; menuBuilder << "RicNewUserDefinedFilterFeature"; + menuBuilder << "RicNewCellIndexFilterFeature"; menuBuilder << "Separator"; menuBuilder << "RicNewCellRangeFilterFeature"; menuBuilder.subMenuStart( "Slice Filters" ); diff --git a/ApplicationLibCode/ProjectDataModel/RimTools.cpp b/ApplicationLibCode/ProjectDataModel/RimTools.cpp index 5fa1d9a760..3605bfded8 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTools.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimTools.cpp @@ -20,6 +20,11 @@ #include "RimTools.h" +#include "RigFemPart.h" +#include "RigFemPartCollection.h" +#include "RigGeoMechCaseData.h" +#include "RigReservoirGridTools.h" + #include "RimCase.h" #include "RimColorLegend.h" #include "RimColorLegendCollection.h" @@ -375,6 +380,74 @@ void RimTools::geoMechCaseOptionItems( QList* options ) } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTools::eclipseGridOptionItems( QList* options, RimEclipseCase* eCase ) +{ + if ( !options ) return; + + for ( int gIdx = 0; gIdx < RigReservoirGridTools::gridCount( eCase ); gIdx++ ) + { + QString gridName = RigReservoirGridTools::gridName( eCase, gIdx ); + if ( gIdx == 0 ) + { + if ( gridName.isEmpty() ) + gridName += "Main Grid"; + else + gridName += " (Main Grid)"; + } + + options->push_back( caf::PdmOptionItemInfo( gridName, gIdx ) ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTools::geoMechPartOptionItems( QList* options, RimGeoMechCase* gCase ) +{ + if ( !options ) return; + + if ( !gCase || !gCase->geoMechData() || !gCase->geoMechData()->femParts() ) return; + + const auto parts = gCase->geoMechData()->femParts(); + + for ( int i = 0; i < parts->partCount(); i++ ) + { + auto part = parts->part( i ); + if ( part != nullptr ) + { + options->push_back( caf::PdmOptionItemInfo( QString::fromStdString( part->name() ), i ) ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTools::geoMechElementSetOptionItems( QList* options, RimGeoMechCase* gCase, int partId ) +{ + if ( !options ) return; + + if ( !gCase || !gCase->geoMechData() || !gCase->geoMechData()->femParts() ) return; + + const auto parts = gCase->geoMechData()->femParts(); + + if ( partId >= parts->partCount() ) return; + + auto part = parts->part( partId ); + if ( part != nullptr ) + { + auto names = part->elementSetNames(); + + for ( int i = 0; i < (int)names.size(); i++ ) + { + options->push_back( caf::PdmOptionItemInfo( QString::fromStdString( names[i] ), i ) ); + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimTools.h b/ApplicationLibCode/ProjectDataModel/RimTools.h index 86723bccc2..4ae40e3656 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTools.h +++ b/ApplicationLibCode/ProjectDataModel/RimTools.h @@ -34,6 +34,8 @@ namespace caf class PdmOptionItemInfo; } +class RimGeoMechCase; +class RimEclipseCase; class RimWellPathCollection; class RimCase; class RimWellPath; @@ -59,7 +61,10 @@ public: static void wellPathWithFormations( std::vector* wellPaths ); static void caseOptionItems( QList* options ); static void eclipseCaseOptionItems( QList* options ); + static void eclipseGridOptionItems( QList* options, RimEclipseCase* eCase ); static void geoMechCaseOptionItems( QList* options ); + static void geoMechPartOptionItems( QList* options, RimGeoMechCase* gCase ); + static void geoMechElementSetOptionItems( QList* options, RimGeoMechCase* gCase, int partId ); static void colorLegendOptionItems( QList* options ); static void seismicDataOptionItems( QList* options, cvf::BoundingBox worldBBox, bool basicDataOnly = false ); static void seismicDataOptionItems( QList* options ); diff --git a/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogExtractionCurve.cpp b/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogExtractionCurve.cpp index a9cb27cf3f..edb55180ad 100644 --- a/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogExtractionCurve.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogExtractionCurve.cpp @@ -1003,15 +1003,7 @@ QList RimWellLogExtractionCurve::calculateValueOptions( } else if ( fieldNeedingOptions == &m_geomPartId && m_case ) { - RimGeoMechCase* geomCase = dynamic_cast( m_case.value() ); - if ( !geomCase || !geomCase->geoMechData() || !geomCase->geoMechData()->femParts() ) return options; - - const auto femParts = geomCase->geoMechData()->femParts(); - for ( int i = 0; i < femParts->partCount(); ++i ) - { - const auto name = femParts->part( i )->name(); - options.push_back( caf::PdmOptionItemInfo( QString::fromStdString( name ), i ) ); - } + RimTools::geoMechPartOptionItems( &options, dynamic_cast( m_case.value() ) ); } else if ( fieldNeedingOptions == &m_simWellName ) {