Skip to content

Commit f75d865

Browse files
committed
#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.
1 parent 09d4e42 commit f75d865

17 files changed

Lines changed: 833 additions & 89 deletions

ApplicationLibCode/Commands/EclipseCommands/CMakeLists_files.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ set(SOURCE_GROUP_SOURCE_FILES
1818
${CMAKE_CURRENT_LIST_DIR}/RicEclipsePropertyFilterNewInViewFeature.cpp
1919
${CMAKE_CURRENT_LIST_DIR}/RicEclipseHideFaultFeature.cpp
2020
${CMAKE_CURRENT_LIST_DIR}/RicEclipseShowOnlyFaultFeature.cpp
21+
${CMAKE_CURRENT_LIST_DIR}/RicNewFaultDistanceResultFeature.cpp
2122
${CMAKE_CURRENT_LIST_DIR}/RicRenameCaseFeature.cpp
2223
${CMAKE_CURRENT_LIST_DIR}/RicImportRoffCaseFeature.cpp
2324
${CMAKE_CURRENT_LIST_DIR}/RicAddGridCalculationFeature.cpp
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/////////////////////////////////////////////////////////////////////////////////
2+
//
3+
// Copyright (C) 2026- Equinor ASA
4+
//
5+
// ResInsight is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE.
13+
//
14+
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
15+
// for more details.
16+
//
17+
/////////////////////////////////////////////////////////////////////////////////
18+
19+
#include "RicNewFaultDistanceResultFeature.h"
20+
21+
#include "RimFaultDistanceResult.h"
22+
#include "RimFaultDistanceResultCollection.h"
23+
#include "RimFaultInView.h"
24+
#include "RimFaultInViewCollection.h"
25+
26+
#include "Riu3DMainWindowTools.h"
27+
28+
#include "cafSelectionManager.h"
29+
30+
#include <QAction>
31+
32+
CAF_CMD_SOURCE_INIT( RicNewFaultDistanceResultFeature, "RicNewFaultDistanceResultFeature" );
33+
34+
namespace
35+
{
36+
RimFaultInViewCollection* findHostCollection()
37+
{
38+
const auto faultCollections = caf::SelectionManager::instance()->objectsByType<RimFaultInViewCollection>();
39+
if ( !faultCollections.empty() ) return faultCollections.front();
40+
41+
const auto distanceCollections = caf::SelectionManager::instance()->objectsByType<RimFaultDistanceResultCollection>();
42+
if ( !distanceCollections.empty() )
43+
{
44+
return distanceCollections.front()->firstAncestorOrThisOfType<RimFaultInViewCollection>();
45+
}
46+
47+
const auto distanceResults = caf::SelectionManager::instance()->objectsByType<RimFaultDistanceResult>();
48+
if ( !distanceResults.empty() )
49+
{
50+
return distanceResults.front()->firstAncestorOrThisOfType<RimFaultInViewCollection>();
51+
}
52+
53+
const auto faults = caf::SelectionManager::instance()->objectsByType<RimFaultInView>();
54+
if ( !faults.empty() )
55+
{
56+
return faults.front()->firstAncestorOrThisOfType<RimFaultInViewCollection>();
57+
}
58+
59+
return nullptr;
60+
}
61+
} // namespace
62+
63+
//--------------------------------------------------------------------------------------------------
64+
///
65+
//--------------------------------------------------------------------------------------------------
66+
bool RicNewFaultDistanceResultFeature::isCommandEnabled() const
67+
{
68+
return findHostCollection() != nullptr;
69+
}
70+
71+
//--------------------------------------------------------------------------------------------------
72+
///
73+
//--------------------------------------------------------------------------------------------------
74+
void RicNewFaultDistanceResultFeature::onActionTriggered( bool isChecked )
75+
{
76+
RimFaultInViewCollection* hostCollection = findHostCollection();
77+
if ( !hostCollection ) return;
78+
79+
RimFaultDistanceResultCollection* distanceCollection = hostCollection->faultDistanceResults();
80+
if ( !distanceCollection ) return;
81+
82+
const auto selectedFaultPointers = caf::SelectionManager::instance()->objectsByType<RimFaultInView>();
83+
std::vector<RimFaultInView*> selectedFaults( selectedFaultPointers.begin(), selectedFaultPointers.end() );
84+
85+
RimFaultDistanceResult* newResult = distanceCollection->addResult();
86+
if ( !newResult ) return;
87+
88+
if ( !selectedFaults.empty() )
89+
{
90+
newResult->setSelectedFaults( selectedFaults );
91+
}
92+
else
93+
{
94+
newResult->setSelectedFaults( hostCollection->faults() );
95+
}
96+
97+
hostCollection->updateConnectedEditors();
98+
distanceCollection->updateConnectedEditors();
99+
Riu3DMainWindowTools::selectAsCurrentItem( newResult );
100+
}
101+
102+
//--------------------------------------------------------------------------------------------------
103+
///
104+
//--------------------------------------------------------------------------------------------------
105+
void RicNewFaultDistanceResultFeature::setupActionLook( QAction* actionToSetup )
106+
{
107+
actionToSetup->setText( "New Fault Distance Result" );
108+
actionToSetup->setIcon( QIcon( ":/draw_style_faults_24x24.png" ) );
109+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/////////////////////////////////////////////////////////////////////////////////
2+
//
3+
// Copyright (C) 2026- Equinor ASA
4+
//
5+
// ResInsight is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE.
13+
//
14+
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
15+
// for more details.
16+
//
17+
/////////////////////////////////////////////////////////////////////////////////
18+
19+
#pragma once
20+
21+
#include "cafCmdFeature.h"
22+
23+
//==================================================================================================
24+
///
25+
//==================================================================================================
26+
class RicNewFaultDistanceResultFeature : public caf::CmdFeature
27+
{
28+
CAF_CMD_HEADER_INIT;
29+
30+
protected:
31+
bool isCommandEnabled() const override;
32+
void onActionTriggered( bool isChecked ) override;
33+
void setupActionLook( QAction* actionToSetup ) override;
34+
};

ApplicationLibCode/ProjectDataModel/Faults/CMakeLists_files.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
set(SOURCE_GROUP_SOURCE_FILES
2+
${CMAKE_CURRENT_LIST_DIR}/RimFaultDistanceResult.cpp
3+
${CMAKE_CURRENT_LIST_DIR}/RimFaultDistanceResultCollection.cpp
24
${CMAKE_CURRENT_LIST_DIR}/RimFaultInView.cpp
35
${CMAKE_CURRENT_LIST_DIR}/RimFaultInViewCollection.cpp
46
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModel.cpp
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/////////////////////////////////////////////////////////////////////////////////
2+
//
3+
// Copyright (C) 2026- Equinor ASA
4+
//
5+
// ResInsight is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE.
13+
//
14+
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
15+
// for more details.
16+
//
17+
/////////////////////////////////////////////////////////////////////////////////
18+
19+
#include "RimFaultDistanceResult.h"
20+
21+
#include "RiaDefines.h"
22+
23+
#include "RigCaseCellResultsData.h"
24+
#include "RigEclipseCaseData.h"
25+
#include "RigEclipseResultAddress.h"
26+
#include "RigFault.h"
27+
#include "RigSelectedFaultDistanceResultCalculator.h"
28+
29+
#include "RimEclipseCase.h"
30+
#include "RimEclipseView.h"
31+
#include "RimFaultInView.h"
32+
#include "RimFaultInViewCollection.h"
33+
34+
#include "cafPdmUiTreeSelectionEditor.h"
35+
36+
CAF_PDM_SOURCE_INIT( RimFaultDistanceResult, "RimFaultDistanceResult" );
37+
38+
//--------------------------------------------------------------------------------------------------
39+
///
40+
//--------------------------------------------------------------------------------------------------
41+
RimFaultDistanceResult::RimFaultDistanceResult()
42+
{
43+
CAF_PDM_InitObject( "Fault Distance Result", ":/draw_style_faults_24x24.png" );
44+
45+
CAF_PDM_InitFieldNoDefault( &m_resultName, "ResultName", "Name" );
46+
47+
CAF_PDM_InitFieldNoDefault( &m_faults, "SelectedFaults", "Faults" );
48+
m_faults.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
49+
}
50+
51+
//--------------------------------------------------------------------------------------------------
52+
///
53+
//--------------------------------------------------------------------------------------------------
54+
QString RimFaultDistanceResult::resultName() const
55+
{
56+
return m_resultName();
57+
}
58+
59+
//--------------------------------------------------------------------------------------------------
60+
///
61+
//--------------------------------------------------------------------------------------------------
62+
void RimFaultDistanceResult::setResultName( const QString& name )
63+
{
64+
m_resultName = name;
65+
}
66+
67+
//--------------------------------------------------------------------------------------------------
68+
///
69+
//--------------------------------------------------------------------------------------------------
70+
void RimFaultDistanceResult::setSelectedFaults( const std::vector<RimFaultInView*>& faults )
71+
{
72+
m_faults.setValue( faults );
73+
compute();
74+
}
75+
76+
//--------------------------------------------------------------------------------------------------
77+
///
78+
//--------------------------------------------------------------------------------------------------
79+
std::vector<const RigFault*> RimFaultDistanceResult::selectedRigFaults() const
80+
{
81+
std::vector<const RigFault*> rigFaults;
82+
for ( RimFaultInView* fault : m_faults )
83+
{
84+
if ( fault && fault->faultGeometry() ) rigFaults.push_back( fault->faultGeometry() );
85+
}
86+
return rigFaults;
87+
}
88+
89+
//--------------------------------------------------------------------------------------------------
90+
///
91+
//--------------------------------------------------------------------------------------------------
92+
void RimFaultDistanceResult::compute()
93+
{
94+
if ( m_resultName().isEmpty() ) return;
95+
96+
auto eclipseView = firstAncestorOrThisOfType<RimEclipseView>();
97+
if ( !eclipseView ) return;
98+
99+
RimEclipseCase* eclipseCase = eclipseView->eclipseCase();
100+
if ( !eclipseCase ) return;
101+
102+
RigEclipseCaseData* caseData = eclipseCase->eclipseCaseData();
103+
if ( !caseData ) return;
104+
105+
RigSelectedFaultDistanceResultCalculator::compute( caseData, m_resultName(), selectedRigFaults() );
106+
107+
eclipseView->scheduleCreateDisplayModelAndRedraw();
108+
}
109+
110+
//--------------------------------------------------------------------------------------------------
111+
///
112+
//--------------------------------------------------------------------------------------------------
113+
void RimFaultDistanceResult::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
114+
{
115+
if ( changedField == &m_resultName )
116+
{
117+
const QString previousName = oldValue.toString();
118+
if ( !previousName.isEmpty() && previousName != m_resultName() )
119+
{
120+
removeGeneratedResult( previousName );
121+
}
122+
compute();
123+
}
124+
else if ( changedField == &m_faults )
125+
{
126+
compute();
127+
}
128+
}
129+
130+
//--------------------------------------------------------------------------------------------------
131+
///
132+
//--------------------------------------------------------------------------------------------------
133+
QList<caf::PdmOptionItemInfo> RimFaultDistanceResult::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
134+
{
135+
QList<caf::PdmOptionItemInfo> options;
136+
137+
if ( fieldNeedingOptions == &m_faults )
138+
{
139+
auto faultCollection = firstAncestorOrThisOfType<RimFaultInViewCollection>();
140+
if ( faultCollection )
141+
{
142+
for ( RimFaultInView* fault : faultCollection->faults() )
143+
{
144+
if ( fault ) options.push_back( caf::PdmOptionItemInfo( fault->name(), fault ) );
145+
}
146+
}
147+
}
148+
149+
return options;
150+
}
151+
152+
//--------------------------------------------------------------------------------------------------
153+
///
154+
//--------------------------------------------------------------------------------------------------
155+
caf::PdmFieldHandle* RimFaultDistanceResult::userDescriptionField()
156+
{
157+
return &m_resultName;
158+
}
159+
160+
//--------------------------------------------------------------------------------------------------
161+
///
162+
//--------------------------------------------------------------------------------------------------
163+
void RimFaultDistanceResult::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
164+
{
165+
uiOrdering.add( &m_resultName );
166+
uiOrdering.add( &m_faults );
167+
uiOrdering.skipRemainingFields( true );
168+
}
169+
170+
//--------------------------------------------------------------------------------------------------
171+
///
172+
//--------------------------------------------------------------------------------------------------
173+
void RimFaultDistanceResult::removeGeneratedResult( const QString& name )
174+
{
175+
if ( name.isEmpty() ) return;
176+
177+
auto eclipseView = firstAncestorOrThisOfType<RimEclipseView>();
178+
if ( !eclipseView ) return;
179+
180+
RimEclipseCase* eclipseCase = eclipseView->eclipseCase();
181+
if ( !eclipseCase ) return;
182+
183+
RigEclipseCaseData* caseData = eclipseCase->eclipseCaseData();
184+
if ( !caseData ) return;
185+
186+
RigCaseCellResultsData* resultsData = caseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
187+
if ( !resultsData ) return;
188+
189+
resultsData->clearScalarResult( RiaDefines::ResultCatType::GENERATED, name );
190+
}

0 commit comments

Comments
 (0)