From 0434dfad15f61372a7c6a136feebf78f6c575487 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 27 May 2026 12:14:08 +0200 Subject: [PATCH 1/3] #13890 Faults: Add FAULTDIST result for a user-selected subset of faults The existing FAULTDIST result always considered every fault in the main grid. Users with many faults need to compute distance fields against a named subset, so this adds a Fault Distance Results collection under each view's Faults node. Each entry holds a multiselect of faults and a name (FAULTDIST1, FAULTDIST2, ...) and publishes the result into the Generated cell-result category. The per-cell BVH-based distance loop was extracted from RigFaultDistanceResultCalculator into a reusable utility that accepts the subset of faults to include; the original all-faults entry point delegates to the same utility and keeps the static-native FAULTDIST behavior unchanged. --- .../EclipseCommands/CMakeLists_files.cmake | 1 + .../RicNewFaultDistanceResultFeature.cpp | 109 ++++++++++ .../RicNewFaultDistanceResultFeature.h | 34 ++++ .../Faults/CMakeLists_files.cmake | 2 + .../Faults/RimFaultDistanceResult.cpp | 190 ++++++++++++++++++ .../Faults/RimFaultDistanceResult.h | 61 ++++++ .../RimFaultDistanceResultCollection.cpp | 79 ++++++++ .../Faults/RimFaultDistanceResultCollection.h | 42 ++++ .../Faults/RimFaultInViewCollection.cpp | 17 ++ .../Faults/RimFaultInViewCollection.h | 6 +- .../RimContextCommandBuilder.cpp | 15 ++ .../ResultCalculators/CMakeLists_files.cmake | 2 + .../RigFaultDistanceCalculator.cpp | 134 ++++++++++++ .../RigFaultDistanceCalculator.h | 36 ++++ .../RigFaultDistanceResultCalculator.cpp | 94 +-------- ...gSelectedFaultDistanceResultCalculator.cpp | 65 ++++++ ...RigSelectedFaultDistanceResultCalculator.h | 35 ++++ 17 files changed, 833 insertions(+), 89 deletions(-) create mode 100644 ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.cpp create mode 100644 ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.h create mode 100644 ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.h create mode 100644 ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.h create mode 100644 ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceCalculator.cpp create mode 100644 ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceCalculator.h create mode 100644 ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigSelectedFaultDistanceResultCalculator.cpp create mode 100644 ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigSelectedFaultDistanceResultCalculator.h diff --git a/ApplicationLibCode/Commands/EclipseCommands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/EclipseCommands/CMakeLists_files.cmake index 405d7430a9d..5ee3bf68927 100644 --- a/ApplicationLibCode/Commands/EclipseCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/EclipseCommands/CMakeLists_files.cmake @@ -18,6 +18,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicEclipsePropertyFilterNewInViewFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicEclipseHideFaultFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicEclipseShowOnlyFaultFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewFaultDistanceResultFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicRenameCaseFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicImportRoffCaseFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicAddGridCalculationFeature.cpp diff --git a/ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.cpp b/ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.cpp new file mode 100644 index 00000000000..70112f15635 --- /dev/null +++ b/ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.cpp @@ -0,0 +1,109 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 "RicNewFaultDistanceResultFeature.h" + +#include "RimFaultDistanceResult.h" +#include "RimFaultDistanceResultCollection.h" +#include "RimFaultInView.h" +#include "RimFaultInViewCollection.h" + +#include "Riu3DMainWindowTools.h" + +#include "cafSelectionManager.h" + +#include + +CAF_CMD_SOURCE_INIT( RicNewFaultDistanceResultFeature, "RicNewFaultDistanceResultFeature" ); + +namespace +{ +RimFaultInViewCollection* findHostCollection() +{ + const auto faultCollections = caf::SelectionManager::instance()->objectsByType(); + if ( !faultCollections.empty() ) return faultCollections.front(); + + const auto distanceCollections = caf::SelectionManager::instance()->objectsByType(); + if ( !distanceCollections.empty() ) + { + return distanceCollections.front()->firstAncestorOrThisOfType(); + } + + const auto distanceResults = caf::SelectionManager::instance()->objectsByType(); + if ( !distanceResults.empty() ) + { + return distanceResults.front()->firstAncestorOrThisOfType(); + } + + const auto faults = caf::SelectionManager::instance()->objectsByType(); + if ( !faults.empty() ) + { + return faults.front()->firstAncestorOrThisOfType(); + } + + return nullptr; +} +} // namespace + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewFaultDistanceResultFeature::isCommandEnabled() const +{ + return findHostCollection() != nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFaultDistanceResultFeature::onActionTriggered( bool isChecked ) +{ + RimFaultInViewCollection* hostCollection = findHostCollection(); + if ( !hostCollection ) return; + + RimFaultDistanceResultCollection* distanceCollection = hostCollection->faultDistanceResults(); + if ( !distanceCollection ) return; + + const auto selectedFaultPointers = caf::SelectionManager::instance()->objectsByType(); + std::vector selectedFaults( selectedFaultPointers.begin(), selectedFaultPointers.end() ); + + RimFaultDistanceResult* newResult = distanceCollection->addResult(); + if ( !newResult ) return; + + if ( !selectedFaults.empty() ) + { + newResult->setSelectedFaults( selectedFaults ); + } + else + { + newResult->setSelectedFaults( hostCollection->faults() ); + } + + hostCollection->updateConnectedEditors(); + distanceCollection->updateConnectedEditors(); + Riu3DMainWindowTools::selectAsCurrentItem( newResult ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFaultDistanceResultFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "New Fault Distance Result" ); + actionToSetup->setIcon( QIcon( ":/draw_style_faults_24x24.png" ) ); +} diff --git a/ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.h b/ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.h new file mode 100644 index 00000000000..f4e25a3f8ed --- /dev/null +++ b/ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 RicNewFaultDistanceResultFeature : 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/ProjectDataModel/Faults/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake index 735ff2aa04e..89ce932cffc 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake @@ -1,4 +1,6 @@ set(SOURCE_GROUP_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RimFaultDistanceResult.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFaultDistanceResultCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFaultInView.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFaultInViewCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModel.cpp diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp new file mode 100644 index 00000000000..1ce953fef2f --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp @@ -0,0 +1,190 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 "RimFaultDistanceResult.h" + +#include "RiaDefines.h" + +#include "RigCaseCellResultsData.h" +#include "RigEclipseCaseData.h" +#include "RigEclipseResultAddress.h" +#include "RigFault.h" +#include "RigSelectedFaultDistanceResultCalculator.h" + +#include "RimEclipseCase.h" +#include "RimEclipseView.h" +#include "RimFaultInView.h" +#include "RimFaultInViewCollection.h" + +#include "cafPdmUiTreeSelectionEditor.h" + +CAF_PDM_SOURCE_INIT( RimFaultDistanceResult, "RimFaultDistanceResult" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultDistanceResult::RimFaultDistanceResult() +{ + CAF_PDM_InitObject( "Fault Distance Result", ":/draw_style_faults_24x24.png" ); + + CAF_PDM_InitFieldNoDefault( &m_resultName, "ResultName", "Name" ); + + CAF_PDM_InitFieldNoDefault( &m_faults, "SelectedFaults", "Faults" ); + m_faults.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFaultDistanceResult::resultName() const +{ + return m_resultName(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultDistanceResult::setResultName( const QString& name ) +{ + m_resultName = name; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultDistanceResult::setSelectedFaults( const std::vector& faults ) +{ + m_faults.setValue( faults ); + compute(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimFaultDistanceResult::selectedRigFaults() const +{ + std::vector rigFaults; + for ( RimFaultInView* fault : m_faults ) + { + if ( fault && fault->faultGeometry() ) rigFaults.push_back( fault->faultGeometry() ); + } + return rigFaults; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultDistanceResult::compute() +{ + if ( m_resultName().isEmpty() ) return; + + auto eclipseView = firstAncestorOrThisOfType(); + if ( !eclipseView ) return; + + RimEclipseCase* eclipseCase = eclipseView->eclipseCase(); + if ( !eclipseCase ) return; + + RigEclipseCaseData* caseData = eclipseCase->eclipseCaseData(); + if ( !caseData ) return; + + RigSelectedFaultDistanceResultCalculator::compute( caseData, m_resultName(), selectedRigFaults() ); + + eclipseView->scheduleCreateDisplayModelAndRedraw(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultDistanceResult::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + if ( changedField == &m_resultName ) + { + const QString previousName = oldValue.toString(); + if ( !previousName.isEmpty() && previousName != m_resultName() ) + { + removeGeneratedResult( previousName ); + } + compute(); + } + else if ( changedField == &m_faults ) + { + compute(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimFaultDistanceResult::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) +{ + QList options; + + if ( fieldNeedingOptions == &m_faults ) + { + auto faultCollection = firstAncestorOrThisOfType(); + if ( faultCollection ) + { + for ( RimFaultInView* fault : faultCollection->faults() ) + { + if ( fault ) options.push_back( caf::PdmOptionItemInfo( fault->name(), fault ) ); + } + } + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimFaultDistanceResult::userDescriptionField() +{ + return &m_resultName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultDistanceResult::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + uiOrdering.add( &m_resultName ); + uiOrdering.add( &m_faults ); + uiOrdering.skipRemainingFields( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultDistanceResult::removeGeneratedResult( const QString& name ) +{ + if ( name.isEmpty() ) return; + + auto eclipseView = firstAncestorOrThisOfType(); + if ( !eclipseView ) return; + + RimEclipseCase* eclipseCase = eclipseView->eclipseCase(); + if ( !eclipseCase ) return; + + RigEclipseCaseData* caseData = eclipseCase->eclipseCaseData(); + if ( !caseData ) return; + + RigCaseCellResultsData* resultsData = caseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL ); + if ( !resultsData ) return; + + resultsData->clearScalarResult( RiaDefines::ResultCatType::GENERATED, name ); +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.h new file mode 100644 index 00000000000..df4821f5f1d --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.h @@ -0,0 +1,61 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPtrArrayField.h" + +#include + +#include + +class RigFault; +class RimFaultInView; + +//================================================================================================== +/// +//================================================================================================== +class RimFaultDistanceResult : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimFaultDistanceResult(); + + QString resultName() const; + void setResultName( const QString& name ); + + void setSelectedFaults( const std::vector& faults ); + std::vector selectedRigFaults() const; + + void compute(); + +protected: + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; + caf::PdmFieldHandle* userDescriptionField() override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + +private: + void removeGeneratedResult( const QString& name ); + + caf::PdmPtrArrayField m_faults; + caf::PdmField m_resultName; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.cpp new file mode 100644 index 00000000000..3167afc7e39 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.cpp @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 "RimFaultDistanceResultCollection.h" + +#include "RimFaultDistanceResult.h" + +#include "cafPdmUiTreeOrdering.h" + +#include + +CAF_PDM_SOURCE_INIT( RimFaultDistanceResultCollection, "RimFaultDistanceResultCollection" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultDistanceResultCollection::RimFaultDistanceResultCollection() +{ + CAF_PDM_InitObject( "Fault Distance Results", ":/draw_style_faults_24x24.png" ); + + CAF_PDM_InitFieldNoDefault( &m_items, "FaultDistanceResults", "" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultDistanceResult* RimFaultDistanceResultCollection::addResult() +{ + auto* newResult = new RimFaultDistanceResult(); + newResult->setResultName( nextDefaultName() ); + addItem( newResult ); + return newResult; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFaultDistanceResultCollection::nextDefaultName() const +{ + QRegularExpression pattern( "^FAULTDIST(\\d+)$" ); + int maxIndex = 0; + for ( RimFaultDistanceResult* result : items() ) + { + if ( !result ) continue; + const QRegularExpressionMatch match = pattern.match( result->resultName() ); + if ( match.hasMatch() ) + { + maxIndex = std::max( maxIndex, match.captured( 1 ).toInt() ); + } + } + return QString( "FAULTDIST%1" ).arg( maxIndex + 1 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultDistanceResultCollection::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName ) +{ + for ( RimFaultDistanceResult* result : items() ) + { + uiTreeOrdering.add( result ); + } + uiTreeOrdering.skipRemainingChildren( true ); +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.h new file mode 100644 index 00000000000..f5faa811fd7 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.h @@ -0,0 +1,42 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 "cafPdmObjectCollection.h" + +#include + +class RimFaultDistanceResult; + +//================================================================================================== +/// +//================================================================================================== +class RimFaultDistanceResultCollection : public caf::PdmObjectCollection +{ + CAF_PDM_HEADER_INIT; + +public: + RimFaultDistanceResultCollection(); + + RimFaultDistanceResult* addResult(); + QString nextDefaultName() const; + +private: + void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName ) override; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp index 43c774ee346..5d9242647bf 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp @@ -27,6 +27,7 @@ #include "RimEclipseFaultColors.h" #include "RimEclipseView.h" +#include "RimFaultDistanceResultCollection.h" #include "RimFaultInView.h" #include "RimIntersectionCollection.h" #include "RimProject.h" @@ -98,6 +99,9 @@ RimFaultInViewCollection::RimFaultInViewCollection() CAF_PDM_InitFieldNoDefault( &m_faults, "Faults", "Faults" ); + CAF_PDM_InitFieldNoDefault( &m_distanceResults, "FaultDistanceResults", "" ); + m_distanceResults = new RimFaultDistanceResultCollection; + CAF_PDM_InitField( &m_showFaultsOutsideFilters_obsolete, "ShowFaultsOutsideFilters", true, "Show Faults Outside Filters" ); m_showFaultsOutsideFilters_obsolete.xmlCapability()->setIOWritable( false ); m_showFaultsOutsideFilters_obsolete.uiCapability()->setUiHidden( true ); @@ -391,6 +395,11 @@ void RimFaultInViewCollection::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiT uiTreeOrdering.appendChild( uiTree ); } + if ( m_distanceResults() && !m_distanceResults()->isEmpty() ) + { + uiTreeOrdering.add( m_distanceResults() ); + } + for ( const auto& fault : m_faults ) { uiTreeOrdering.add( fault ); @@ -407,6 +416,14 @@ RimEclipseView* RimFaultInViewCollection::parentView() const return firstAncestorOrThisOfTypeAsserted(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultDistanceResultCollection* RimFaultInViewCollection::faultDistanceResults() const +{ + return m_distanceResults(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.h index 0514b1da69d..1c61f2d8759 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.h @@ -21,6 +21,7 @@ #include "cafAppEnum.h" #include "cafPdmChildArrayField.h" +#include "cafPdmChildField.h" #include "cafPdmField.h" #include "cafPdmObject.h" @@ -32,6 +33,7 @@ #include class RimEclipseView; +class RimFaultDistanceResultCollection; class RimFaultInView; //================================================================================================== @@ -57,6 +59,7 @@ class RimFaultInViewCollection : public caf::PdmObject void setActive( bool bActive ); std::vector faults() const; + RimFaultDistanceResultCollection* faultDistanceResults() const; cvf::Color3f faultLabelColor() const; caf::AppEnum faultResult() const; bool showFaultFaces() const; @@ -105,7 +108,8 @@ class RimFaultInViewCollection : public caf::PdmObject caf::PdmField> m_faultResult; - caf::PdmChildArrayField m_faults; + caf::PdmChildArrayField m_faults; + caf::PdmChildField m_distanceResults; caf::PdmField m_showFaultsOutsideFilters_obsolete; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp index 83d87b57b77..77ce60dd4b6 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -68,7 +68,10 @@ #include "RimEnsembleCurveSetCollection.h" #include "RimEnsembleFractureStatisticsCollection.h" #include "RimExtrudedCurveIntersection.h" +#include "RimFaultDistanceResult.h" +#include "RimFaultDistanceResultCollection.h" #include "RimFaultInView.h" +#include "RimFaultInViewCollection.h" #include "RimFaultReactivationModel.h" #include "RimFileWellPath.h" #include "RimFishbones.h" @@ -846,6 +849,12 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() else if ( dynamic_cast( firstUiItem ) ) { menuBuilder << "RicExportFaultsFeature"; + menuBuilder << "RicNewFaultDistanceResultFeature"; + } + else if ( dynamic_cast( firstUiItem ) || + dynamic_cast( firstUiItem ) || dynamic_cast( firstUiItem ) ) + { + menuBuilder << "RicNewFaultDistanceResultFeature"; } else if ( dynamic_cast( firstUiItem ) ) { @@ -1186,6 +1195,12 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() else if ( dynamic_cast( firstUiItem ) ) { menuBuilder << "RicExportFaultsFeature"; + menuBuilder << "RicNewFaultDistanceResultFeature"; + } + else if ( dynamic_cast( firstUiItem ) || + dynamic_cast( firstUiItem ) || dynamic_cast( firstUiItem ) ) + { + menuBuilder << "RicNewFaultDistanceResultFeature"; } else if ( dynamic_cast( firstUiItem ) ) { diff --git a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/CMakeLists_files.cmake b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/CMakeLists_files.cmake index 5951329c404..e128fe78eb7 100644 --- a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/CMakeLists_files.cmake +++ b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/CMakeLists_files.cmake @@ -2,7 +2,9 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RigEclipseResultCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigSoilResultCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigSwatResultCalculator.cpp + ${CMAKE_CURRENT_LIST_DIR}/RigFaultDistanceCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigFaultDistanceResultCalculator.cpp + ${CMAKE_CURRENT_LIST_DIR}/RigSelectedFaultDistanceResultCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigMobilePoreVolumeResultCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigIndexIjkResultCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigOilVolumeResultCalculator.cpp diff --git a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceCalculator.cpp new file mode 100644 index 00000000000..4a8e46f36f9 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceCalculator.cpp @@ -0,0 +1,134 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 "RigFaultDistanceCalculator.h" + +#include "RigActiveCellInfo.h" +#include "RigCell.h" +#include "RigFault.h" +#include "RigMainGrid.h" + +#include "cvfBoundingBoxTree.h" + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFaultDistanceCalculator::computeFaultDistances( const RigMainGrid* mainGrid, + const RigActiveCellInfo* activeCellInfo, + const std::vector& faultsToInclude, + std::vector& resultValues ) +{ + if ( !mainGrid || !activeCellInfo ) return; + + const auto activeCells = activeCellInfo->activeReservoirCellIndices(); + if ( activeCells.empty() ) return; + + if ( resultValues.size() < activeCells.size() ) + { + resultValues.resize( activeCells.size(), std::numeric_limits::infinity() ); + } + + // Collect fault face centers from the requested subset of faults. + std::vector faultFaceCenters; + for ( const RigFault* fault : faultsToInclude ) + { + if ( !fault ) continue; + for ( const RigFault::FaultFace& faultFace : fault->faultFaces() ) + { + if ( faultFace.m_nativeReservoirCellIndex >= mainGrid->cellCount() ) continue; + const RigCell& cell = mainGrid->cell( faultFace.m_nativeReservoirCellIndex ); + if ( cell.isInvalid() ) continue; + faultFaceCenters.push_back( cell.faceCenter( faultFace.m_nativeFace ) ); + } + } + + if ( faultFaceCenters.empty() ) return; + + // Create bounding box tree for all face centers + cvf::BoundingBoxTree searchTree; + { + std::vector faceIndicesForBoundingBoxes; + std::vector faceBBs; + + size_t faceCenterIndex = 0; + for ( const auto& faultFaceCenter : faultFaceCenters ) + { + cvf::BoundingBox bb; + bb.add( faultFaceCenter ); + faceBBs.push_back( bb ); + faceIndicesForBoundingBoxes.push_back( faceCenterIndex++ ); + } + searchTree.buildTreeFromBoundingBoxes( faceBBs, &faceIndicesForBoundingBoxes ); + } + + const auto nodes = mainGrid->nodes(); + const auto mainGridBB = mainGrid->boundingBox(); + +#pragma omp parallel for + for ( int activeIndex = 0; activeIndex < static_cast( activeCells.size() ); activeIndex++ ) + { + auto cellIdx = activeCells[activeIndex]; + if ( cellIdx.value() == cvf::UNDEFINED_SIZE_T ) continue; + + const RigCell& cell = mainGrid->cell( cellIdx.value() ); + if ( cell.isInvalid() ) continue; + + std::vector candidateFaceIndices; + { + cvf::BoundingBox bb; + const auto& cellIndices = cell.cornerIndices(); + for ( const auto& i : cellIndices ) + { + bb.add( nodes[i] ); + } + + searchTree.findIntersections( bb, &candidateFaceIndices ); + + bool bbIsBelowThreshold = true; + while ( candidateFaceIndices.empty() && bbIsBelowThreshold ) + { + if ( bb.extent().x() > mainGridBB.extent().x() * 2 ) + { + bbIsBelowThreshold = false; + break; + } + if ( bb.extent().y() > mainGridBB.extent().y() * 2 ) + { + bbIsBelowThreshold = false; + break; + } + + bb.expand( bb.extent().x() ); + searchTree.findIntersections( bb, &candidateFaceIndices ); + } + } + + // Find closest fault face + double shortestDistance = std::numeric_limits::infinity(); + + for ( const auto& faultFaceIndex : candidateFaceIndices ) + { + const cvf::Vec3d& faultFaceCenter = faultFaceCenters[faultFaceIndex]; + shortestDistance = std::min( cell.center().pointDistance( faultFaceCenter ), shortestDistance ); + } + + resultValues[activeIndex] = shortestDistance; + } +} diff --git a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceCalculator.h b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceCalculator.h new file mode 100644 index 00000000000..e8d65695f8d --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceCalculator.h @@ -0,0 +1,36 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 + +class RigActiveCellInfo; +class RigFault; +class RigMainGrid; + +//================================================================================================== +/// +//================================================================================================== +namespace RigFaultDistanceCalculator +{ +void computeFaultDistances( const RigMainGrid* mainGrid, + const RigActiveCellInfo* activeCellInfo, + const std::vector& faultsToInclude, + std::vector& resultValues ); +} diff --git a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceResultCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceResultCalculator.cpp index fbceff65910..5c4a177bcda 100644 --- a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceResultCalculator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigFaultDistanceResultCalculator.cpp @@ -22,12 +22,11 @@ #include "RiaResultNames.h" #include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" -#include "RigCell.h" #include "RigEclipseResultInfo.h" +#include "RigFault.h" +#include "RigFaultDistanceCalculator.h" #include "RigMainGrid.h" -#include "cvfBoundingBoxTree.h" - //================================================================================================== /// //================================================================================================== @@ -80,92 +79,11 @@ void RigFaultDistanceResultCalculator::calculate( const RigEclipseResultAddress& const auto mainGrid = m_resultsData->m_ownerMainGrid; - std::vector faceTypes = cvf::StructGridInterface::validFaceTypes(); - - // Preprocessing: create vector of all fault face centers. - std::vector faultFaceCenters; - const auto activeCells = m_resultsData->activeCellInfo()->activeReservoirCellIndices(); - for ( auto cellIdx : activeCells ) + std::vector allFaults; + for ( size_t i = 0; i < mainGrid->faults().size(); ++i ) { - const RigCell& cell = mainGrid->cell( cellIdx.value() ); - if ( cell.isInvalid() ) continue; - for ( auto faceType : faceTypes ) - { - if ( m_resultsData->m_ownerMainGrid->findFaultFromCellIndexAndCellFace( cellIdx.value(), faceType ) ) - faultFaceCenters.push_back( cell.faceCenter( faceType ) ); - } + allFaults.push_back( mainGrid->faults().at( i ) ); } - if ( faultFaceCenters.empty() ) return; - - // Create bounding box tree for all face centers - auto searchTree = new cvf::BoundingBoxTree; - { - std::vector faceIndicesForBoundingBoxes; - std::vector faceBBs; - - size_t faceCenterIndex = 0; - for ( const auto& faultFaceCenter : faultFaceCenters ) - { - cvf::BoundingBox bb; - bb.add( faultFaceCenter ); - faceBBs.push_back( bb ); - faceIndicesForBoundingBoxes.push_back( faceCenterIndex++ ); - } - searchTree->buildTreeFromBoundingBoxes( faceBBs, &faceIndicesForBoundingBoxes ); - } - - const auto nodes = m_resultsData->m_ownerMainGrid->nodes(); - const auto mainGridBB = m_resultsData->m_ownerMainGrid->boundingBox(); - -#pragma omp parallel for - for ( int activeIndex = 0; activeIndex < static_cast( activeCells.size() ); activeIndex++ ) - { - auto cellIdx = activeCells[activeIndex]; - if ( cellIdx.value() == cvf::UNDEFINED_SIZE_T ) continue; - - const RigCell& cell = mainGrid->cell( cellIdx.value() ); - if ( cell.isInvalid() ) continue; - - std::vector candidateFaceIndices; - { - cvf::BoundingBox bb; - const auto& cellIndices = cell.cornerIndices(); - for ( const auto& i : cellIndices ) - { - bb.add( nodes[i] ); - } - - searchTree->findIntersections( bb, &candidateFaceIndices ); - - bool bbIsBelowThreshold = true; - while ( candidateFaceIndices.empty() && bbIsBelowThreshold ) - { - if ( bb.extent().x() > mainGridBB.extent().x() * 2 ) - { - bbIsBelowThreshold = false; - break; - } - if ( bb.extent().y() > mainGridBB.extent().y() * 2 ) - { - bbIsBelowThreshold = false; - break; - } - - bb.expand( bb.extent().x() ); - searchTree->findIntersections( bb, &candidateFaceIndices ); - } - } - - // Find closest fault face - double shortestDistance = std::numeric_limits::infinity(); - - for ( const auto& faultFaceIndex : candidateFaceIndices ) - { - const cvf::Vec3d& faultFaceCenter = faultFaceCenters[faultFaceIndex]; - shortestDistance = std::min( cell.center().pointDistance( faultFaceCenter ), shortestDistance ); - } - - result[0][activeIndex] = shortestDistance; - } + RigFaultDistanceCalculator::computeFaultDistances( mainGrid, m_resultsData->activeCellInfo(), allFaults, result[0] ); } diff --git a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigSelectedFaultDistanceResultCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigSelectedFaultDistanceResultCalculator.cpp new file mode 100644 index 00000000000..a0696f3c17e --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigSelectedFaultDistanceResultCalculator.cpp @@ -0,0 +1,65 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 "RigSelectedFaultDistanceResultCalculator.h" + +#include "RiaDefines.h" + +#include "RigActiveCellInfo.h" +#include "RigCaseCellResultsData.h" +#include "RigEclipseCaseData.h" +#include "RigEclipseResultAddress.h" +#include "RigFaultDistanceCalculator.h" +#include "RigMainGrid.h" + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigSelectedFaultDistanceResultCalculator::compute( RigEclipseCaseData* caseData, + const QString& resultName, + const std::vector& selectedFaults ) +{ + if ( !caseData || resultName.isEmpty() ) return; + + RigCaseCellResultsData* resultsData = caseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL ); + if ( !resultsData ) return; + + const RigActiveCellInfo* activeCellInfo = resultsData->activeCellInfo(); + if ( !activeCellInfo ) return; + + const size_t activeCellCount = activeCellInfo->reservoirActiveCellCount(); + if ( activeCellCount == 0 ) return; + + RigEclipseResultAddress resultAddress( RiaDefines::ResultCatType::GENERATED, resultName ); + + if ( !resultsData->hasResultEntry( resultAddress ) ) + { + resultsData->addStaticScalarResult( RiaDefines::ResultCatType::GENERATED, resultName, false, activeCellCount ); + } + + std::vector* resultVector = resultsData->modifiableCellScalarResult( resultAddress, 0 ); + if ( !resultVector ) return; + + resultVector->assign( activeCellCount, std::numeric_limits::infinity() ); + + RigFaultDistanceCalculator::computeFaultDistances( caseData->mainGrid(), activeCellInfo, selectedFaults, *resultVector ); + + resultsData->recalculateStatistics( resultAddress ); +} diff --git a/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigSelectedFaultDistanceResultCalculator.h b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigSelectedFaultDistanceResultCalculator.h new file mode 100644 index 00000000000..f207a6ed305 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/ResultCalculators/RigSelectedFaultDistanceResultCalculator.h @@ -0,0 +1,35 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 + +#include + +class RigEclipseCaseData; +class RigFault; + +//================================================================================================== +/// +//================================================================================================== +class RigSelectedFaultDistanceResultCalculator +{ +public: + static void compute( RigEclipseCaseData* caseData, const QString& resultName, const std::vector& selectedFaults ); +}; From c0aa89ec5f662aaf226947160a1d07ef8d1bf6d2 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 27 May 2026 12:59:19 +0200 Subject: [PATCH 2/3] #13890 Python: Add scriptable API for selected-fault FAULTDIST Expose the new RimFaultDistanceResult facility to Python by marking the relevant PDM classes and fields scriptable. RimEclipseView's m_faultCollection, RimFaultInViewCollection, RimFaultInView, RimFaultDistanceResult, and RimFaultDistanceResultCollection are now scriptable, so faults can be enumerated from Python via view.fault_collection().faults(). A new Rimc method add_fault_distance_result on RimFaultInViewCollection takes a name and a list of fault objects, creates the result (auto-numbered FAULTDIST when the name is empty), and returns the new RimFaultDistanceResult. An empty fault list falls back to every fault in the view, matching the static-native FAULTDIST behaviour. Add a Python test exercising both a subset call and a parity check that asserts the all-faults result matches the existing static-native FAULTDIST cell-for-cell. --- .../Faults/RimFaultDistanceResult.cpp | 13 +++- .../RimFaultDistanceResultCollection.cpp | 11 ++- .../Faults/RimFaultInView.cpp | 14 +++- .../Faults/RimFaultInViewCollection.cpp | 13 +++- .../ProjectDataModel/RimEclipseView.cpp | 2 +- .../CMakeLists_files.cmake | 1 + .../RimcFaultInViewCollection.cpp | 76 +++++++++++++++++++ .../RimcFaultInViewCollection.h | 46 +++++++++++ .../rips/tests/test_fault_distance_result.py | 55 ++++++++++++++ 9 files changed, 219 insertions(+), 12 deletions(-) create mode 100644 ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.cpp create mode 100644 ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.h create mode 100644 GrpcInterface/Python/rips/tests/test_fault_distance_result.py diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp index 1ce953fef2f..257e066fc76 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp @@ -31,6 +31,8 @@ #include "RimFaultInView.h" #include "RimFaultInViewCollection.h" +#include "cafPdmFieldScriptingCapability.h" +#include "cafPdmObjectScriptingCapability.h" #include "cafPdmUiTreeSelectionEditor.h" CAF_PDM_SOURCE_INIT( RimFaultDistanceResult, "RimFaultDistanceResult" ); @@ -40,11 +42,16 @@ CAF_PDM_SOURCE_INIT( RimFaultDistanceResult, "RimFaultDistanceResult" ); //-------------------------------------------------------------------------------------------------- RimFaultDistanceResult::RimFaultDistanceResult() { - CAF_PDM_InitObject( "Fault Distance Result", ":/draw_style_faults_24x24.png" ); + CAF_PDM_InitScriptableObjectWithNameAndComment( "Fault Distance Result", + ":/draw_style_faults_24x24.png", + "", + "", + "FaultDistanceResult", + "Per-cell distance to a selected subset of faults" ); - CAF_PDM_InitFieldNoDefault( &m_resultName, "ResultName", "Name" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_resultName, "ResultName", "Name" ); - CAF_PDM_InitFieldNoDefault( &m_faults, "SelectedFaults", "Faults" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_faults, "SelectedFaults", "Faults" ); m_faults.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); } diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.cpp index 3167afc7e39..c79d0eb28b1 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResultCollection.cpp @@ -20,6 +20,8 @@ #include "RimFaultDistanceResult.h" +#include "cafPdmFieldScriptingCapability.h" +#include "cafPdmObjectScriptingCapability.h" #include "cafPdmUiTreeOrdering.h" #include @@ -31,9 +33,14 @@ CAF_PDM_SOURCE_INIT( RimFaultDistanceResultCollection, "RimFaultDistanceResultCo //-------------------------------------------------------------------------------------------------- RimFaultDistanceResultCollection::RimFaultDistanceResultCollection() { - CAF_PDM_InitObject( "Fault Distance Results", ":/draw_style_faults_24x24.png" ); + CAF_PDM_InitScriptableObjectWithNameAndComment( "Fault Distance Results", + ":/draw_style_faults_24x24.png", + "", + "", + "FaultDistanceResultCollection", + "Collection of named, subset-based FAULTDIST results" ); - CAF_PDM_InitFieldNoDefault( &m_items, "FaultDistanceResults", "" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_items, "FaultDistanceResults", "" ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInView.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInView.cpp index a99d51fe27f..86be01b15a6 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInView.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInView.cpp @@ -24,6 +24,9 @@ #include "RimEclipseView.h" #include "RimIntersectionCollection.h" +#include "cafPdmFieldScriptingCapability.h" +#include "cafPdmObjectScriptingCapability.h" + CAF_PDM_SOURCE_INIT( RimFaultInView, "Fault" ); //-------------------------------------------------------------------------------------------------- @@ -31,9 +34,14 @@ CAF_PDM_SOURCE_INIT( RimFaultInView, "Fault" ); //-------------------------------------------------------------------------------------------------- RimFaultInView::RimFaultInView() { - CAF_PDM_InitObject( "RimFault", ":/draw_style_faults_24x24.png" ); - - CAF_PDM_InitFieldNoDefault( &name, "FaultName", "Name" ); + CAF_PDM_InitScriptableObjectWithNameAndComment( "RimFault", + ":/draw_style_faults_24x24.png", + "", + "", + "FaultInView", + "A fault belonging to a view's fault collection" ); + + CAF_PDM_InitScriptableFieldNoDefault( &name, "FaultName", "Name" ); name.uiCapability()->setUiHidden( true ); name.uiCapability()->setUiReadOnly( true ); diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp index 5d9242647bf..636e9f07245 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp @@ -36,6 +36,8 @@ #include "cafAppEnum.h" #include "cafPdmFieldCvfColor.h" +#include "cafPdmFieldScriptingCapability.h" +#include "cafPdmObjectScriptingCapability.h" #include "cafPdmUiCheckBoxEditor.h" #include "cafPdmUiLineEditor.h" #include "cafPdmUiTreeOrdering.h" @@ -59,7 +61,12 @@ CAF_PDM_SOURCE_INIT( RimFaultInViewCollection, "Faults" ); //-------------------------------------------------------------------------------------------------- RimFaultInViewCollection::RimFaultInViewCollection() { - CAF_PDM_InitObject( "Faults", ":/draw_style_faults_24x24.png" ); + CAF_PDM_InitScriptableObjectWithNameAndComment( "Faults", + ":/draw_style_faults_24x24.png", + "", + "", + "FaultInViewCollection", + "Per-view fault collection" ); CAF_PDM_InitField( &m_showFaultCollection, "Active", true, "Active" ); m_showFaultCollection.uiCapability()->setUiHidden( true ); @@ -97,9 +104,9 @@ RimFaultInViewCollection::RimFaultInViewCollection() "Hide NNC Geometry if No NNC Result is Available" ); caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_hideNNCsWhenNoResultIsAvailable ); - CAF_PDM_InitFieldNoDefault( &m_faults, "Faults", "Faults" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_faults, "Faults", "Faults" ); - CAF_PDM_InitFieldNoDefault( &m_distanceResults, "FaultDistanceResults", "" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_distanceResults, "FaultDistanceResults", "" ); m_distanceResults = new RimFaultDistanceResultCollection; CAF_PDM_InitField( &m_showFaultsOutsideFilters_obsolete, "ShowFaultsOutsideFilters", true, "Show Faults Outside Filters" ); diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index ccfe9c9556d..c19f5dfdfa4 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -198,7 +198,7 @@ RimEclipseView::RimEclipseView() CAF_PDM_InitFieldNoDefault( &m_wellCollection, "WellCollection", "Simulation Wells" ); m_wellCollection = new RimSimWellInViewCollection; - CAF_PDM_InitFieldNoDefault( &m_faultCollection, "FaultCollection", "Faults" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_faultCollection, "FaultCollection", "Faults" ); m_faultCollection = new RimFaultInViewCollection; CAF_PDM_InitFieldNoDefault( &m_faultReactivationModelCollection, "FaultReactivationModelCollection", "Fault Reactivation Models" ); diff --git a/ApplicationLibCode/ProjectDataModelCommands/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModelCommands/CMakeLists_files.cmake index 5080c3b43c4..86060f573ca 100644 --- a/ApplicationLibCode/ProjectDataModelCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModelCommands/CMakeLists_files.cmake @@ -31,6 +31,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimcGridView.cpp ${CMAKE_CURRENT_LIST_DIR}/RimcIdenticalGridCaseGroup.cpp ${CMAKE_CURRENT_LIST_DIR}/RimcPressureTable.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimcFaultInViewCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimcFishbonesCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimcPolygonCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimcDataFilterCollection.cpp diff --git a/ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.cpp b/ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.cpp new file mode 100644 index 00000000000..f643064a90d --- /dev/null +++ b/ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.cpp @@ -0,0 +1,76 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 "RimcFaultInViewCollection.h" + +#include "RimFaultDistanceResult.h" +#include "RimFaultDistanceResultCollection.h" +#include "RimFaultInView.h" +#include "RimFaultInViewCollection.h" + +#include "cafPdmAbstractFieldScriptingCapability.h" +#include "cafPdmFieldScriptingCapability.h" + +CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimFaultInViewCollection, RimcFaultInViewCollection_addFaultDistanceResult, "add_fault_distance_result" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimcFaultInViewCollection_addFaultDistanceResult::RimcFaultInViewCollection_addFaultDistanceResult( caf::PdmObjectHandle* self ) + : caf::PdmObjectCreationMethod( self ) +{ + CAF_PDM_InitObject( "Add Fault Distance Result", "", "", "Create a FAULTDIST cell result for a chosen subset of faults" ); + + CAF_PDM_InitScriptableFieldNoDefault( &m_resultName, "Name", "Name (default FAULTDIST if empty)" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_faults, "Faults", "Faults to include (empty = all)" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::expected RimcFaultInViewCollection_addFaultDistanceResult::execute() +{ + auto* hostCollection = self(); + if ( !hostCollection ) return std::unexpected( QString( "No fault collection" ) ); + + auto* distanceCollection = hostCollection->faultDistanceResults(); + if ( !distanceCollection ) return std::unexpected( QString( "No fault distance results collection" ) ); + + auto* newResult = distanceCollection->addResult(); + if ( !newResult ) return std::unexpected( QString( "Failed to create fault distance result" ) ); + + if ( !m_resultName().isEmpty() ) newResult->setResultName( m_resultName() ); + + std::vector selected = m_faults.ptrReferencedObjectsByType(); + if ( selected.empty() ) selected = hostCollection->faults(); + + newResult->setSelectedFaults( selected ); + + hostCollection->updateConnectedEditors(); + distanceCollection->updateConnectedEditors(); + + return newResult; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimcFaultInViewCollection_addFaultDistanceResult::classKeywordReturnedType() const +{ + return RimFaultDistanceResult::classKeywordStatic(); +} diff --git a/ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.h b/ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.h new file mode 100644 index 00000000000..5599d70bb95 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.h @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- 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 "cafPdmField.h" +#include "cafPdmObjectHandle.h" +#include "cafPdmObjectMethod.h" +#include "cafPdmPtrArrayField.h" + +#include + +class RimFaultInView; + +//================================================================================================== +/// +//================================================================================================== +class RimcFaultInViewCollection_addFaultDistanceResult : public caf::PdmObjectCreationMethod +{ + CAF_PDM_HEADER_INIT; + +public: + RimcFaultInViewCollection_addFaultDistanceResult( caf::PdmObjectHandle* self ); + + std::expected execute() override; + QString classKeywordReturnedType() const override; + +private: + caf::PdmField m_resultName; + caf::PdmPtrArrayField m_faults; +}; diff --git a/GrpcInterface/Python/rips/tests/test_fault_distance_result.py b/GrpcInterface/Python/rips/tests/test_fault_distance_result.py new file mode 100644 index 00000000000..9a291bb0fef --- /dev/null +++ b/GrpcInterface/Python/rips/tests/test_fault_distance_result.py @@ -0,0 +1,55 @@ +import math +import os +import sys + +sys.path.insert(1, os.path.join(sys.path[0], "../../")) + +import dataroot +import rips + + +GRID_PATH = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID" + + +def _get_view(case): + views = case.views() + if views: + return views[0] + return case.create_view() + + +def test_add_fault_distance_result_subset(rips_instance, initialize_test): + case = rips_instance.project.load_case(GRID_PATH) + view = _get_view(case) + fault_collection = view.fault_collection() + faults = fault_collection.faults() + assert len(faults) > 0 + + result = fault_collection.add_fault_distance_result("PY_FAULTDIST", faults[:1]) + assert result is not None + assert result.result_name == "PY_FAULTDIST" + + +def test_add_fault_distance_result_all_matches_static(rips_instance, initialize_test): + """Passing every fault into add_fault_distance_result must reproduce the + static-native FAULTDIST values cell-for-cell.""" + case = rips_instance.project.load_case(GRID_PATH) + view = _get_view(case) + fault_collection = view.fault_collection() + all_faults = fault_collection.faults() + assert len(all_faults) > 0 + + static_values = case.active_cell_property( + rips.PropertyType.STATIC_NATIVE, "FAULTDIST", 0 + ) + + fault_collection.add_fault_distance_result("PY_FAULTDIST_ALL", all_faults) + + generated_values = case.active_cell_property( + rips.PropertyType.GENERATED, "PY_FAULTDIST_ALL", 0 + ) + + assert len(static_values) == len(generated_values) + assert len(static_values) > 0 + for s, g in zip(static_values, generated_values): + assert math.isclose(s, g, abs_tol=1e-6) From 81de2fc85de0aef893f3ad2386ff12ccceb50ff5 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Fri, 29 May 2026 12:55:30 +0200 Subject: [PATCH 3/3] #13890 Faults: Move fault distance results collection to the view Reparent RimFaultDistanceResultCollection so it is owned directly by RimEclipseView instead of RimFaultInViewCollection, and show it as a top-level node next to the Faults node in the project tree. RimFaultDistanceResult::calculateValueOptions now reaches the fault list through the view (the fault collection is a sibling rather than an ancestor after the move). RicNewFaultDistanceResultFeature resolves the view from the selection and takes both the distance collection and the all-faults fallback from it. The scriptable API moves with the collection: add_fault_distance_result is now exposed on RimEclipseView (view.add_fault_distance_result(...)) via the new RimcEclipseView, replacing RimcFaultInViewCollection. --- .../RicNewFaultDistanceResultFeature.cpp | 33 +++++++------------ .../Faults/RimFaultDistanceResult.cpp | 3 +- .../Faults/RimFaultInViewCollection.cpp | 17 ---------- .../Faults/RimFaultInViewCollection.h | 5 +-- .../ProjectDataModel/RimEclipseView.cpp | 14 ++++++++ .../ProjectDataModel/RimEclipseView.h | 3 ++ .../CMakeLists_files.cmake | 2 +- ...ViewCollection.cpp => RimcEclipseView.cpp} | 20 +++++------ ...ltInViewCollection.h => RimcEclipseView.h} | 4 +-- .../rips/tests/test_fault_distance_result.py | 4 +-- 10 files changed, 47 insertions(+), 58 deletions(-) rename ApplicationLibCode/ProjectDataModelCommands/{RimcFaultInViewCollection.cpp => RimcEclipseView.cpp} (75%) rename ApplicationLibCode/ProjectDataModelCommands/{RimcFaultInViewCollection.h => RimcEclipseView.h} (89%) diff --git a/ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.cpp b/ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.cpp index 70112f15635..a59568480a0 100644 --- a/ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.cpp +++ b/ApplicationLibCode/Commands/EclipseCommands/RicNewFaultDistanceResultFeature.cpp @@ -18,6 +18,7 @@ #include "RicNewFaultDistanceResultFeature.h" +#include "RimEclipseView.h" #include "RimFaultDistanceResult.h" #include "RimFaultDistanceResultCollection.h" #include "RimFaultInView.h" @@ -33,28 +34,19 @@ CAF_CMD_SOURCE_INIT( RicNewFaultDistanceResultFeature, "RicNewFaultDistanceResul namespace { -RimFaultInViewCollection* findHostCollection() +RimEclipseView* findHostView() { const auto faultCollections = caf::SelectionManager::instance()->objectsByType(); - if ( !faultCollections.empty() ) return faultCollections.front(); + if ( !faultCollections.empty() ) return faultCollections.front()->firstAncestorOrThisOfType(); const auto distanceCollections = caf::SelectionManager::instance()->objectsByType(); - if ( !distanceCollections.empty() ) - { - return distanceCollections.front()->firstAncestorOrThisOfType(); - } + if ( !distanceCollections.empty() ) return distanceCollections.front()->firstAncestorOrThisOfType(); const auto distanceResults = caf::SelectionManager::instance()->objectsByType(); - if ( !distanceResults.empty() ) - { - return distanceResults.front()->firstAncestorOrThisOfType(); - } + if ( !distanceResults.empty() ) return distanceResults.front()->firstAncestorOrThisOfType(); const auto faults = caf::SelectionManager::instance()->objectsByType(); - if ( !faults.empty() ) - { - return faults.front()->firstAncestorOrThisOfType(); - } + if ( !faults.empty() ) return faults.front()->firstAncestorOrThisOfType(); return nullptr; } @@ -65,7 +57,7 @@ RimFaultInViewCollection* findHostCollection() //-------------------------------------------------------------------------------------------------- bool RicNewFaultDistanceResultFeature::isCommandEnabled() const { - return findHostCollection() != nullptr; + return findHostView() != nullptr; } //-------------------------------------------------------------------------------------------------- @@ -73,10 +65,10 @@ bool RicNewFaultDistanceResultFeature::isCommandEnabled() const //-------------------------------------------------------------------------------------------------- void RicNewFaultDistanceResultFeature::onActionTriggered( bool isChecked ) { - RimFaultInViewCollection* hostCollection = findHostCollection(); - if ( !hostCollection ) return; + RimEclipseView* eclipseView = findHostView(); + if ( !eclipseView ) return; - RimFaultDistanceResultCollection* distanceCollection = hostCollection->faultDistanceResults(); + RimFaultDistanceResultCollection* distanceCollection = eclipseView->faultDistanceResults(); if ( !distanceCollection ) return; const auto selectedFaultPointers = caf::SelectionManager::instance()->objectsByType(); @@ -89,12 +81,11 @@ void RicNewFaultDistanceResultFeature::onActionTriggered( bool isChecked ) { newResult->setSelectedFaults( selectedFaults ); } - else + else if ( eclipseView->faultCollection() ) { - newResult->setSelectedFaults( hostCollection->faults() ); + newResult->setSelectedFaults( eclipseView->faultCollection()->faults() ); } - hostCollection->updateConnectedEditors(); distanceCollection->updateConnectedEditors(); Riu3DMainWindowTools::selectAsCurrentItem( newResult ); } diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp index 257e066fc76..2c3d979e702 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultDistanceResult.cpp @@ -143,7 +143,8 @@ QList RimFaultDistanceResult::calculateValueOptions( con if ( fieldNeedingOptions == &m_faults ) { - auto faultCollection = firstAncestorOrThisOfType(); + auto eclipseView = firstAncestorOrThisOfType(); + auto faultCollection = eclipseView ? eclipseView->faultCollection() : nullptr; if ( faultCollection ) { for ( RimFaultInView* fault : faultCollection->faults() ) diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp index 636e9f07245..0ca2471d9c4 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.cpp @@ -27,7 +27,6 @@ #include "RimEclipseFaultColors.h" #include "RimEclipseView.h" -#include "RimFaultDistanceResultCollection.h" #include "RimFaultInView.h" #include "RimIntersectionCollection.h" #include "RimProject.h" @@ -106,9 +105,6 @@ RimFaultInViewCollection::RimFaultInViewCollection() CAF_PDM_InitScriptableFieldNoDefault( &m_faults, "Faults", "Faults" ); - CAF_PDM_InitScriptableFieldNoDefault( &m_distanceResults, "FaultDistanceResults", "" ); - m_distanceResults = new RimFaultDistanceResultCollection; - CAF_PDM_InitField( &m_showFaultsOutsideFilters_obsolete, "ShowFaultsOutsideFilters", true, "Show Faults Outside Filters" ); m_showFaultsOutsideFilters_obsolete.xmlCapability()->setIOWritable( false ); m_showFaultsOutsideFilters_obsolete.uiCapability()->setUiHidden( true ); @@ -402,11 +398,6 @@ void RimFaultInViewCollection::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiT uiTreeOrdering.appendChild( uiTree ); } - if ( m_distanceResults() && !m_distanceResults()->isEmpty() ) - { - uiTreeOrdering.add( m_distanceResults() ); - } - for ( const auto& fault : m_faults ) { uiTreeOrdering.add( fault ); @@ -423,14 +414,6 @@ RimEclipseView* RimFaultInViewCollection::parentView() const return firstAncestorOrThisOfTypeAsserted(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimFaultDistanceResultCollection* RimFaultInViewCollection::faultDistanceResults() const -{ - return m_distanceResults(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.h index 1c61f2d8759..17aa32ebeeb 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultInViewCollection.h @@ -33,7 +33,6 @@ #include class RimEclipseView; -class RimFaultDistanceResultCollection; class RimFaultInView; //================================================================================================== @@ -59,7 +58,6 @@ class RimFaultInViewCollection : public caf::PdmObject void setActive( bool bActive ); std::vector faults() const; - RimFaultDistanceResultCollection* faultDistanceResults() const; cvf::Color3f faultLabelColor() const; caf::AppEnum faultResult() const; bool showFaultFaces() const; @@ -108,8 +106,7 @@ class RimFaultInViewCollection : public caf::PdmObject caf::PdmField> m_faultResult; - caf::PdmChildArrayField m_faults; - caf::PdmChildField m_distanceResults; + caf::PdmChildArrayField m_faults; caf::PdmField m_showFaultsOutsideFilters_obsolete; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index c19f5dfdfa4..5bf97f81699 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -66,6 +66,7 @@ #include "RimEclipseResultDefinition.h" #include "RimElementVectorResult.h" #include "RimExtrudedCurveIntersection.h" +#include "RimFaultDistanceResultCollection.h" #include "RimFaultInViewCollection.h" #include "RimFaultReactivationModelCollection.h" #include "RimFilterInViewCollection.h" @@ -201,6 +202,9 @@ RimEclipseView::RimEclipseView() CAF_PDM_InitScriptableFieldNoDefault( &m_faultCollection, "FaultCollection", "Faults" ); m_faultCollection = new RimFaultInViewCollection; + CAF_PDM_InitFieldNoDefault( &m_faultDistanceResultCollection, "FaultDistanceResultCollection", "Fault Distance Results" ); + m_faultDistanceResultCollection = new RimFaultDistanceResultCollection; + CAF_PDM_InitFieldNoDefault( &m_faultReactivationModelCollection, "FaultReactivationModelCollection", "Fault Reactivation Models" ); m_faultReactivationModelCollection = new RimFaultReactivationModelCollection; @@ -353,6 +357,14 @@ RimFaultInViewCollection* RimEclipseView::faultCollection() const return m_faultCollection; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultDistanceResultCollection* RimEclipseView::faultDistanceResults() const +{ + return m_faultDistanceResultCollection; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2116,6 +2128,8 @@ void RimEclipseView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin uiTreeOrdering.add( faultCollection() ); + if ( faultDistanceResults() && !faultDistanceResults()->isEmpty() ) uiTreeOrdering.add( faultDistanceResults() ); + if ( faultReactivationModelCollection()->shouldBeVisibleInTree() ) uiTreeOrdering.add( faultReactivationModelCollection() ); uiTreeOrdering.add( intersectionCollection() ); diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.h b/ApplicationLibCode/ProjectDataModel/RimEclipseView.h index eb4f1d3ebad..2f5295ce396 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.h @@ -53,6 +53,7 @@ class RimEclipseCellColors; class RimEclipseFaultColors; class RimEclipsePropertyFilter; class RimEclipsePropertyFilterCollection; +class RimFaultDistanceResultCollection; class RimFaultInViewCollection; class RimFilterInViewCollection; class RimReservoirCellResultsStorage; @@ -114,6 +115,7 @@ class RimEclipseView : public RimGridView, public RimFieldQuickAccessInterface RimStimPlanColors* fractureColors() const; RimSimWellInViewCollection* wellCollection() const; RimFaultInViewCollection* faultCollection() const; + RimFaultDistanceResultCollection* faultDistanceResults() const; RimVirtualPerforationResults* virtualPerforationResult() const; RimStreamlineInViewCollection* streamlineCollection() const; RimFaultReactivationModelCollection* faultReactivationModelCollection() const; @@ -270,6 +272,7 @@ class RimEclipseView : public RimGridView, public RimFieldQuickAccessInterface caf::PdmChildField m_wellCollection; caf::PdmChildField m_faultCollection; + caf::PdmChildField m_faultDistanceResultCollection; caf::PdmChildField m_faultReactivationModelCollection; caf::PdmChildField m_streamlineCollection; diff --git a/ApplicationLibCode/ProjectDataModelCommands/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModelCommands/CMakeLists_files.cmake index 86060f573ca..92eb0b1a268 100644 --- a/ApplicationLibCode/ProjectDataModelCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModelCommands/CMakeLists_files.cmake @@ -31,7 +31,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimcGridView.cpp ${CMAKE_CURRENT_LIST_DIR}/RimcIdenticalGridCaseGroup.cpp ${CMAKE_CURRENT_LIST_DIR}/RimcPressureTable.cpp - ${CMAKE_CURRENT_LIST_DIR}/RimcFaultInViewCollection.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimcEclipseView.cpp ${CMAKE_CURRENT_LIST_DIR}/RimcFishbonesCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimcPolygonCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimcDataFilterCollection.cpp diff --git a/ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.cpp b/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseView.cpp similarity index 75% rename from ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.cpp rename to ApplicationLibCode/ProjectDataModelCommands/RimcEclipseView.cpp index f643064a90d..97c872b6b31 100644 --- a/ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.cpp +++ b/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseView.cpp @@ -16,8 +16,9 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RimcFaultInViewCollection.h" +#include "RimcEclipseView.h" +#include "RimEclipseView.h" #include "RimFaultDistanceResult.h" #include "RimFaultDistanceResultCollection.h" #include "RimFaultInView.h" @@ -26,12 +27,12 @@ #include "cafPdmAbstractFieldScriptingCapability.h" #include "cafPdmFieldScriptingCapability.h" -CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimFaultInViewCollection, RimcFaultInViewCollection_addFaultDistanceResult, "add_fault_distance_result" ); +CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseView, RimcEclipseView_addFaultDistanceResult, "add_fault_distance_result" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimcFaultInViewCollection_addFaultDistanceResult::RimcFaultInViewCollection_addFaultDistanceResult( caf::PdmObjectHandle* self ) +RimcEclipseView_addFaultDistanceResult::RimcEclipseView_addFaultDistanceResult( caf::PdmObjectHandle* self ) : caf::PdmObjectCreationMethod( self ) { CAF_PDM_InitObject( "Add Fault Distance Result", "", "", "Create a FAULTDIST cell result for a chosen subset of faults" ); @@ -43,12 +44,12 @@ RimcFaultInViewCollection_addFaultDistanceResult::RimcFaultInViewCollection_addF //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::expected RimcFaultInViewCollection_addFaultDistanceResult::execute() +std::expected RimcEclipseView_addFaultDistanceResult::execute() { - auto* hostCollection = self(); - if ( !hostCollection ) return std::unexpected( QString( "No fault collection" ) ); + auto* eclipseView = self(); + if ( !eclipseView ) return std::unexpected( QString( "No view" ) ); - auto* distanceCollection = hostCollection->faultDistanceResults(); + auto* distanceCollection = eclipseView->faultDistanceResults(); if ( !distanceCollection ) return std::unexpected( QString( "No fault distance results collection" ) ); auto* newResult = distanceCollection->addResult(); @@ -57,11 +58,10 @@ std::expected RimcFaultInViewCollection_addFault if ( !m_resultName().isEmpty() ) newResult->setResultName( m_resultName() ); std::vector selected = m_faults.ptrReferencedObjectsByType(); - if ( selected.empty() ) selected = hostCollection->faults(); + if ( selected.empty() && eclipseView->faultCollection() ) selected = eclipseView->faultCollection()->faults(); newResult->setSelectedFaults( selected ); - hostCollection->updateConnectedEditors(); distanceCollection->updateConnectedEditors(); return newResult; @@ -70,7 +70,7 @@ std::expected RimcFaultInViewCollection_addFault //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimcFaultInViewCollection_addFaultDistanceResult::classKeywordReturnedType() const +QString RimcEclipseView_addFaultDistanceResult::classKeywordReturnedType() const { return RimFaultDistanceResult::classKeywordStatic(); } diff --git a/ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.h b/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseView.h similarity index 89% rename from ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.h rename to ApplicationLibCode/ProjectDataModelCommands/RimcEclipseView.h index 5599d70bb95..c81a0f815eb 100644 --- a/ApplicationLibCode/ProjectDataModelCommands/RimcFaultInViewCollection.h +++ b/ApplicationLibCode/ProjectDataModelCommands/RimcEclipseView.h @@ -30,12 +30,12 @@ class RimFaultInView; //================================================================================================== /// //================================================================================================== -class RimcFaultInViewCollection_addFaultDistanceResult : public caf::PdmObjectCreationMethod +class RimcEclipseView_addFaultDistanceResult : public caf::PdmObjectCreationMethod { CAF_PDM_HEADER_INIT; public: - RimcFaultInViewCollection_addFaultDistanceResult( caf::PdmObjectHandle* self ); + RimcEclipseView_addFaultDistanceResult( caf::PdmObjectHandle* self ); std::expected execute() override; QString classKeywordReturnedType() const override; diff --git a/GrpcInterface/Python/rips/tests/test_fault_distance_result.py b/GrpcInterface/Python/rips/tests/test_fault_distance_result.py index 9a291bb0fef..186e687798d 100644 --- a/GrpcInterface/Python/rips/tests/test_fault_distance_result.py +++ b/GrpcInterface/Python/rips/tests/test_fault_distance_result.py @@ -25,7 +25,7 @@ def test_add_fault_distance_result_subset(rips_instance, initialize_test): faults = fault_collection.faults() assert len(faults) > 0 - result = fault_collection.add_fault_distance_result("PY_FAULTDIST", faults[:1]) + result = view.add_fault_distance_result("PY_FAULTDIST", faults[:1]) assert result is not None assert result.result_name == "PY_FAULTDIST" @@ -43,7 +43,7 @@ def test_add_fault_distance_result_all_matches_static(rips_instance, initialize_ rips.PropertyType.STATIC_NATIVE, "FAULTDIST", 0 ) - fault_collection.add_fault_distance_result("PY_FAULTDIST_ALL", all_faults) + view.add_fault_distance_result("PY_FAULTDIST_ALL", all_faults) generated_values = case.active_cell_property( rips.PropertyType.GENERATED, "PY_FAULTDIST_ALL", 0