mirror of
https://github.com/OPM/ResInsight.git
synced 2026-11-02 20:30:46 -06:00
CellFilters: Add combined filter for mixing cell and property filters
Add RimCombinedFilter, a node placed under the Eclipse property-filter collection that holds child filters (cell or property) and combines their results with a user-chosen AND or OR mode. Supports nesting and is exposed to Python via the generated rips CombinedFilter class. To let the same evaluation machinery handle any filter type, introduce a unified applyToCellVisibility(cellVis, grid, timeStep) virtual on RimCellFilter with a default implementation that bridges the existing range/index dispatch. RimEclipsePropertyFilter overrides it with the body extracted from RivReservoirViewPartMgr::computePropertyVisibility, which collapses to a generic per-child call and preserves the prior behavior for ordinary property filters. Loosen RimEclipsePropertyFilterCollection::m_propertyFilters to PdmChildArrayField<RimCellFilter*>, keeping the XML tag "PropertyFilters" and the typed propertyFilters() accessor. Add recursive helpers (hasActiveEvaluatableDescendant, hasActiveDynamicPropertyDescendant, hasActiveFormationNamesPropertyDescendant) so hasActiveFilters, hasActiveDynamicFilters and isUsingFormationNames see property filters nested inside a combined filter. Bridge filter changes inside a combined filter to updateDisplayModelNotifyManagedViews, since the property-filter collection doesn't subscribe to filterChanged signals. The existing RicNew* cell-filter creation features now route the new child into a selected combined filter when one is selected, otherwise into the top-level cell-filter collection as before. The combined filter's context menu offers the full mixed set: property, polygon, range, index, user-defined, and nested combined filter.
This commit is contained in:
1 parent
b27199f4ba
commit
9d5a8c28f4
23 files changed
+1188
-119
No files matched your search
@@ -23,6 +23,7 @@
|
|||||||
#include "RimCase.h"
|
#include "RimCase.h"
|
||||||
#include "RimCellFilterCollection.h"
|
#include "RimCellFilterCollection.h"
|
||||||
#include "RimCellIndexFilter.h"
|
#include "RimCellIndexFilter.h"
|
||||||
|
#include "RimCombinedFilter.h"
|
||||||
#include "RimGeoMechCase.h"
|
#include "RimGeoMechCase.h"
|
||||||
#include "RimGridView.h"
|
#include "RimGridView.h"
|
||||||
#include "RimUserDefinedFilter.h"
|
#include "RimUserDefinedFilter.h"
|
||||||
@@ -53,15 +54,26 @@ bool RicNewCellIndexFilterFeature::isCommandEnabled() const
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RicNewCellIndexFilterFeature::onActionTriggered( bool isChecked )
|
void RicNewCellIndexFilterFeature::onActionTriggered( bool isChecked )
|
||||||
{
|
{
|
||||||
|
// If a combined filter is selected, add the new index filter inside it.
|
||||||
|
std::vector<RimCombinedFilter*> combined = caf::selectedObjectsByTypeStrict<RimCombinedFilter*>();
|
||||||
|
if ( !combined.empty() )
|
||||||
|
{
|
||||||
|
RimCombinedFilter* target = combined.front();
|
||||||
|
if ( RimCase* srcCase = target->firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase() )
|
||||||
|
{
|
||||||
|
RimCellIndexFilter* created = target->addNewCellIndexFilter( srcCase );
|
||||||
|
if ( created ) Riu3DMainWindowTools::selectAsCurrentItem( created );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the selected Cell Filter Collection
|
// Find the selected Cell Filter Collection
|
||||||
std::vector<RimCellFilterCollection*> colls = caf::selectedObjectsByTypeStrict<RimCellFilterCollection*>();
|
std::vector<RimCellFilterCollection*> colls = caf::selectedObjectsByTypeStrict<RimCellFilterCollection*>();
|
||||||
if ( colls.empty() ) return;
|
if ( colls.empty() ) return;
|
||||||
RimCellFilterCollection* filtColl = colls[0];
|
RimCellFilterCollection* filtColl = colls[0];
|
||||||
|
|
||||||
// and the case to use
|
// and the case to use
|
||||||
RimCase* sourceCase = filtColl->firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase();
|
if ( RimCase* sourceCase = filtColl->firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase() )
|
||||||
|
|
||||||
if ( sourceCase )
|
|
||||||
{
|
{
|
||||||
RimCellIndexFilter* lastCreatedOrUpdated = filtColl->addNewCellIndexFilter( sourceCase );
|
RimCellIndexFilter* lastCreatedOrUpdated = filtColl->addNewCellIndexFilter( sourceCase );
|
||||||
if ( lastCreatedOrUpdated )
|
if ( lastCreatedOrUpdated )
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "RimCase.h"
|
#include "RimCase.h"
|
||||||
#include "RimCellFilterCollection.h"
|
#include "RimCellFilterCollection.h"
|
||||||
|
#include "RimCombinedFilter.h"
|
||||||
#include "RimGridView.h"
|
#include "RimGridView.h"
|
||||||
#include "RimPolygonFilter.h"
|
#include "RimPolygonFilter.h"
|
||||||
|
|
||||||
@@ -57,6 +58,39 @@ void RicNewPolygonFilterFeature::onActionTriggered( bool isChecked )
|
|||||||
polygonDataSource = static_cast<RimPolygon*>( userData.value<void*>() );
|
polygonDataSource = static_cast<RimPolygon*>( userData.value<void*>() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<RimPolygon*> polygons;
|
||||||
|
if ( polygonDataSource )
|
||||||
|
{
|
||||||
|
polygons.push_back( polygonDataSource );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
polygons = selectedPolygons();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a combined filter is selected, add polygon filters as its children.
|
||||||
|
auto* combined = caf::SelectionManager::instance()->selectedItemOfType<RimCombinedFilter>();
|
||||||
|
if ( combined )
|
||||||
|
{
|
||||||
|
RimCase* srcCase = combined->firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase();
|
||||||
|
if ( !srcCase ) return;
|
||||||
|
|
||||||
|
RimPolygonFilter* lastItem = nullptr;
|
||||||
|
if ( polygons.empty() )
|
||||||
|
{
|
||||||
|
lastItem = combined->addNewPolygonFilter( srcCase, nullptr );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( auto polygon : polygons )
|
||||||
|
{
|
||||||
|
lastItem = combined->addNewPolygonFilter( srcCase, polygon );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( lastItem ) Riu3DMainWindowTools::selectAsCurrentItem( lastItem );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto cellFilterCollection = caf::SelectionManager::instance()->selectedItemOfType<RimCellFilterCollection>();
|
auto cellFilterCollection = caf::SelectionManager::instance()->selectedItemOfType<RimCellFilterCollection>();
|
||||||
if ( !cellFilterCollection )
|
if ( !cellFilterCollection )
|
||||||
{
|
{
|
||||||
@@ -71,17 +105,6 @@ void RicNewPolygonFilterFeature::onActionTriggered( bool isChecked )
|
|||||||
auto sourceCase = cellFilterCollection->firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase();
|
auto sourceCase = cellFilterCollection->firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase();
|
||||||
if ( !sourceCase ) return;
|
if ( !sourceCase ) return;
|
||||||
|
|
||||||
std::vector<RimPolygon*> polygons;
|
|
||||||
|
|
||||||
if ( polygonDataSource )
|
|
||||||
{
|
|
||||||
polygons.push_back( polygonDataSource );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
polygons = selectedPolygons();
|
|
||||||
}
|
|
||||||
|
|
||||||
RimPolygonFilter* lastItem = nullptr;
|
RimPolygonFilter* lastItem = nullptr;
|
||||||
|
|
||||||
if ( polygons.empty() )
|
if ( polygons.empty() )
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "RimCase.h"
|
#include "RimCase.h"
|
||||||
#include "RimCellFilterCollection.h"
|
#include "RimCellFilterCollection.h"
|
||||||
#include "RimCellRangeFilter.h"
|
#include "RimCellRangeFilter.h"
|
||||||
|
#include "RimCombinedFilter.h"
|
||||||
#include "RimEclipseCase.h"
|
#include "RimEclipseCase.h"
|
||||||
#include "RimEclipseView.h"
|
#include "RimEclipseView.h"
|
||||||
#include "RimGridView.h"
|
#include "RimGridView.h"
|
||||||
@@ -49,6 +50,20 @@ RicNewRangeFilterSliceFeature::RicNewRangeFilterSliceFeature( QString cmdText, Q
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RicNewRangeFilterSliceFeature::onActionTriggered( bool isChecked )
|
void RicNewRangeFilterSliceFeature::onActionTriggered( bool isChecked )
|
||||||
{
|
{
|
||||||
|
// If a combined filter is selected, add the new range filter inside it.
|
||||||
|
std::vector<RimCombinedFilter*> combined = caf::selectedObjectsByTypeStrict<RimCombinedFilter*>();
|
||||||
|
if ( !combined.empty() )
|
||||||
|
{
|
||||||
|
RimCombinedFilter* target = combined.front();
|
||||||
|
RimCase* srcCase = target->firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase();
|
||||||
|
if ( srcCase )
|
||||||
|
{
|
||||||
|
RimCellFilter* created = target->addNewCellRangeFilter( srcCase, 0, m_sliceDirection );
|
||||||
|
if ( created ) Riu3DMainWindowTools::selectAsCurrentItem( created );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RimCellFilterCollection* filterCollection = nullptr;
|
RimCellFilterCollection* filterCollection = nullptr;
|
||||||
RimCase* sourceCase = nullptr;
|
RimCase* sourceCase = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "Rim3dView.h"
|
#include "Rim3dView.h"
|
||||||
#include "RimCase.h"
|
#include "RimCase.h"
|
||||||
#include "RimCellFilterCollection.h"
|
#include "RimCellFilterCollection.h"
|
||||||
|
#include "RimCombinedFilter.h"
|
||||||
#include "RimUserDefinedFilter.h"
|
#include "RimUserDefinedFilter.h"
|
||||||
|
|
||||||
#include "Riu3DMainWindowTools.h"
|
#include "Riu3DMainWindowTools.h"
|
||||||
@@ -37,6 +38,19 @@ CAF_CMD_SOURCE_INIT( RicNewUserDefinedFilterFeature, "RicNewUserDefinedFilterFea
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RicNewUserDefinedFilterFeature::onActionTriggered( bool isChecked )
|
void RicNewUserDefinedFilterFeature::onActionTriggered( bool isChecked )
|
||||||
{
|
{
|
||||||
|
std::vector<RimCombinedFilter*> combined = caf::selectedObjectsByTypeStrict<RimCombinedFilter*>();
|
||||||
|
if ( !combined.empty() )
|
||||||
|
{
|
||||||
|
RimCombinedFilter* target = combined.front();
|
||||||
|
RimCase* srcCase = target->firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase();
|
||||||
|
if ( srcCase )
|
||||||
|
{
|
||||||
|
RimUserDefinedFilter* created = target->addNewUserDefinedFilter( srcCase );
|
||||||
|
if ( created ) Riu3DMainWindowTools::selectAsCurrentItem( created );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the selected Cell Filter Collection
|
// Find the selected Cell Filter Collection
|
||||||
std::vector<RimCellFilterCollection*> colls = caf::selectedObjectsByTypeStrict<RimCellFilterCollection*>();
|
std::vector<RimCellFilterCollection*> colls = caf::selectedObjectsByTypeStrict<RimCellFilterCollection*>();
|
||||||
if ( colls.empty() ) return;
|
if ( colls.empty() ) return;
|
||||||
|
|||||||
+14
@@ -21,6 +21,7 @@
|
|||||||
#include "Rim3dView.h"
|
#include "Rim3dView.h"
|
||||||
#include "RimCase.h"
|
#include "RimCase.h"
|
||||||
#include "RimCellFilterCollection.h"
|
#include "RimCellFilterCollection.h"
|
||||||
|
#include "RimCombinedFilter.h"
|
||||||
#include "RimUserDefinedIndexFilter.h"
|
#include "RimUserDefinedIndexFilter.h"
|
||||||
|
|
||||||
#include "Riu3DMainWindowTools.h"
|
#include "Riu3DMainWindowTools.h"
|
||||||
@@ -37,6 +38,19 @@ CAF_CMD_SOURCE_INIT( RicNewUserDefinedIndexFilterFeature, "RicNewUserDefinedInde
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RicNewUserDefinedIndexFilterFeature::onActionTriggered( bool isChecked )
|
void RicNewUserDefinedIndexFilterFeature::onActionTriggered( bool isChecked )
|
||||||
{
|
{
|
||||||
|
std::vector<RimCombinedFilter*> combined = caf::selectedObjectsByTypeStrict<RimCombinedFilter*>();
|
||||||
|
if ( !combined.empty() )
|
||||||
|
{
|
||||||
|
RimCombinedFilter* target = combined.front();
|
||||||
|
RimCase* srcCase = target->firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase();
|
||||||
|
if ( srcCase )
|
||||||
|
{
|
||||||
|
auto* created = target->addNewUserDefinedIndexFilter( srcCase );
|
||||||
|
if ( created ) Riu3DMainWindowTools::selectAsCurrentItem( created );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the selected Cell Filter Collection
|
// Find the selected Cell Filter Collection
|
||||||
std::vector<RimCellFilterCollection*> colls = caf::selectedObjectsByTypeStrict<RimCellFilterCollection*>();
|
std::vector<RimCellFilterCollection*> colls = caf::selectedObjectsByTypeStrict<RimCellFilterCollection*>();
|
||||||
if ( colls.empty() ) return;
|
if ( colls.empty() ) return;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RicAddGridCalculationFeature.h
|
${CMAKE_CURRENT_LIST_DIR}/RicAddGridCalculationFeature.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateGridCaseEnsemblesFromFilesFeature.h
|
${CMAKE_CURRENT_LIST_DIR}/RicCreateGridCaseEnsemblesFromFilesFeature.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RicAddLinkedEclipsePropertyFilterFeature.h
|
${CMAKE_CURRENT_LIST_DIR}/RicAddLinkedEclipsePropertyFilterFeature.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RicEclipseCombinedPropertyFilterNewFeature.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCE_GROUP_SOURCE_FILES
|
set(SOURCE_GROUP_SOURCE_FILES
|
||||||
@@ -50,6 +51,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RicAddGridCalculationFeature.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RicAddGridCalculationFeature.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateGridCaseEnsemblesFromFilesFeature.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RicCreateGridCaseEnsemblesFromFilesFeature.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RicAddLinkedEclipsePropertyFilterFeature.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RicAddLinkedEclipsePropertyFilterFeature.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RicEclipseCombinedPropertyFilterNewFeature.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||||
|
|||||||
+94
@@ -0,0 +1,94 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "RicEclipseCombinedPropertyFilterNewFeature.h"
|
||||||
|
|
||||||
|
#include "RicEclipsePropertyFilterFeatureImpl.h"
|
||||||
|
|
||||||
|
#include "Rim3dView.h"
|
||||||
|
#include "RimCase.h"
|
||||||
|
#include "RimCombinedFilter.h"
|
||||||
|
#include "RimEclipsePropertyFilterCollection.h"
|
||||||
|
|
||||||
|
#include "Riu3DMainWindowTools.h"
|
||||||
|
|
||||||
|
#include "cafSelectionManagerTools.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
|
||||||
|
CAF_CMD_SOURCE_INIT( RicEclipseCombinedPropertyFilterNewFeature, "RicEclipseCombinedPropertyFilterNewFeature" );
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RicEclipseCombinedPropertyFilterNewFeature::isCommandEnabled() const
|
||||||
|
{
|
||||||
|
// Enable on either the collection or a combined filter within the collection (for nesting).
|
||||||
|
auto combined = caf::selectedObjectsByTypeStrict<RimCombinedFilter*>();
|
||||||
|
if ( !combined.empty() && combined.front()->firstAncestorOrThisOfType<RimEclipsePropertyFilterCollection>() )
|
||||||
|
{
|
||||||
|
return RicEclipsePropertyFilterFeatureImpl::isPropertyFilterCommandAvailable( combined.front() );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto filterCollections = RicEclipsePropertyFilterFeatureImpl::selectedPropertyFilterCollections();
|
||||||
|
if ( filterCollections.size() == 1 )
|
||||||
|
{
|
||||||
|
return RicEclipsePropertyFilterFeatureImpl::isPropertyFilterCommandAvailable( filterCollections[0] );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RicEclipseCombinedPropertyFilterNewFeature::onActionTriggered( bool isChecked )
|
||||||
|
{
|
||||||
|
// Nested combined filter: add the new one inside the currently selected combined filter.
|
||||||
|
auto combined = caf::selectedObjectsByTypeStrict<RimCombinedFilter*>();
|
||||||
|
if ( !combined.empty() && combined.front()->firstAncestorOrThisOfType<RimEclipsePropertyFilterCollection>() )
|
||||||
|
{
|
||||||
|
RimCombinedFilter* parent = combined.front();
|
||||||
|
RimCase* srcCase = parent->firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase();
|
||||||
|
if ( srcCase )
|
||||||
|
{
|
||||||
|
RimCombinedFilter* created = parent->addNewCombinedFilter( srcCase );
|
||||||
|
parent->updateConnectedEditors();
|
||||||
|
if ( created ) Riu3DMainWindowTools::selectAsCurrentItem( created );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto filterCollections = RicEclipsePropertyFilterFeatureImpl::selectedPropertyFilterCollections();
|
||||||
|
if ( filterCollections.size() != 1 ) return;
|
||||||
|
|
||||||
|
RimCombinedFilter* created = filterCollections[0]->addNewCombinedFilter();
|
||||||
|
filterCollections[0]->updateConnectedEditors();
|
||||||
|
if ( created )
|
||||||
|
{
|
||||||
|
Riu3DMainWindowTools::selectAsCurrentItem( created );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RicEclipseCombinedPropertyFilterNewFeature::setupActionLook( QAction* actionToSetup )
|
||||||
|
{
|
||||||
|
actionToSetup->setIcon( QIcon( ":/CellFilter_Values.png" ) );
|
||||||
|
actionToSetup->setText( "New Combined Property Filter" );
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cafCmdFeature.h"
|
||||||
|
|
||||||
|
class RicEclipseCombinedPropertyFilterNewFeature : public caf::CmdFeature
|
||||||
|
{
|
||||||
|
CAF_CMD_HEADER_INIT;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool isCommandEnabled() const override;
|
||||||
|
void onActionTriggered( bool isChecked ) override;
|
||||||
|
void setupActionLook( QAction* actionToSetup ) override;
|
||||||
|
};
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "RiaResultNames.h"
|
#include "RiaResultNames.h"
|
||||||
|
|
||||||
#include "QuickAccess/RimQuickAccessCollection.h"
|
#include "QuickAccess/RimQuickAccessCollection.h"
|
||||||
|
#include "RimCombinedFilter.h"
|
||||||
#include "RimEclipseCellColors.h"
|
#include "RimEclipseCellColors.h"
|
||||||
#include "RimEclipsePropertyFilter.h"
|
#include "RimEclipsePropertyFilter.h"
|
||||||
#include "RimEclipsePropertyFilterCollection.h"
|
#include "RimEclipsePropertyFilterCollection.h"
|
||||||
@@ -71,6 +72,30 @@ void RicEclipsePropertyFilterFeatureImpl::addPropertyFilter( RimEclipsePropertyF
|
|||||||
propertyFilterCollection->onChildAdded( nullptr );
|
propertyFilterCollection->onChildAdded( nullptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RicEclipsePropertyFilterFeatureImpl::addPropertyFilterToCombinedFilter( RimCombinedFilter* combined )
|
||||||
|
{
|
||||||
|
if ( !combined ) return;
|
||||||
|
|
||||||
|
auto* propertyFilter = new RimEclipsePropertyFilter();
|
||||||
|
combined->addFilter( propertyFilter );
|
||||||
|
|
||||||
|
setDefaults( propertyFilter );
|
||||||
|
|
||||||
|
RimQuickAccessCollection::instance()->addQuickAccessFields( propertyFilter );
|
||||||
|
|
||||||
|
if ( RimEclipseView* view = combined->firstAncestorOrThisOfType<RimEclipseView>() )
|
||||||
|
{
|
||||||
|
view->scheduleGeometryRegen( PROPERTY_FILTERED );
|
||||||
|
view->scheduleCreateDisplayModelAndRedraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
combined->updateConnectedEditors();
|
||||||
|
Riu3DMainWindowTools::selectAsCurrentItem( propertyFilter, false );
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class RimCombinedFilter;
|
||||||
class RimEclipsePropertyFilter;
|
class RimEclipsePropertyFilter;
|
||||||
class RimEclipsePropertyFilterCollection;
|
class RimEclipsePropertyFilterCollection;
|
||||||
|
|
||||||
@@ -40,6 +41,7 @@ public:
|
|||||||
static std::vector<RimEclipsePropertyFilterCollection*> selectedPropertyFilterCollections();
|
static std::vector<RimEclipsePropertyFilterCollection*> selectedPropertyFilterCollections();
|
||||||
|
|
||||||
static void addPropertyFilter( RimEclipsePropertyFilterCollection* propertyFilterCollection );
|
static void addPropertyFilter( RimEclipsePropertyFilterCollection* propertyFilterCollection );
|
||||||
|
static void addPropertyFilterToCombinedFilter( RimCombinedFilter* combined );
|
||||||
static void insertPropertyFilter( RimEclipsePropertyFilterCollection* propertyFilterCollection, size_t index );
|
static void insertPropertyFilter( RimEclipsePropertyFilterCollection* propertyFilterCollection, size_t index );
|
||||||
|
|
||||||
static bool isPropertyFilterCommandAvailable( caf::PdmObjectHandle* object );
|
static bool isPropertyFilterCommandAvailable( caf::PdmObjectHandle* object );
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ void RicEclipsePropertyFilterInsertExec::redo()
|
|||||||
m_propertyFilter->firstAncestorOrThisOfTypeAsserted<RimEclipsePropertyFilterCollection>();
|
m_propertyFilter->firstAncestorOrThisOfTypeAsserted<RimEclipsePropertyFilterCollection>();
|
||||||
|
|
||||||
size_t index = propertyFilterCollection->propertyFiltersField().indexOf( m_propertyFilter );
|
size_t index = propertyFilterCollection->propertyFiltersField().indexOf( m_propertyFilter );
|
||||||
CVF_ASSERT( index < propertyFilterCollection->propertyFilters().size() );
|
CVF_ASSERT( index < propertyFilterCollection->propertyFiltersField().size() );
|
||||||
|
|
||||||
RicEclipsePropertyFilterFeatureImpl::insertPropertyFilter( propertyFilterCollection, index );
|
RicEclipsePropertyFilterFeatureImpl::insertPropertyFilter( propertyFilterCollection, index );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ void RicEclipsePropertyFilterNewExec::redo()
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RicEclipsePropertyFilterNewExec::undo()
|
void RicEclipsePropertyFilterNewExec::undo()
|
||||||
{
|
{
|
||||||
m_propertyFilterCollection->propertyFiltersField().erase( m_propertyFilterCollection->propertyFilters().size() - 1 );
|
m_propertyFilterCollection->propertyFiltersField().erase( m_propertyFilterCollection->propertyFiltersField().size() - 1 );
|
||||||
|
|
||||||
m_propertyFilterCollection->updateConnectedEditors();
|
m_propertyFilterCollection->updateConnectedEditors();
|
||||||
}
|
}
|
||||||
@@ -22,10 +22,12 @@
|
|||||||
#include "RicEclipsePropertyFilterFeatureImpl.h"
|
#include "RicEclipsePropertyFilterFeatureImpl.h"
|
||||||
#include "RicEclipsePropertyFilterNewExec.h"
|
#include "RicEclipsePropertyFilterNewExec.h"
|
||||||
|
|
||||||
|
#include "RimCombinedFilter.h"
|
||||||
#include "RimEclipsePropertyFilter.h"
|
#include "RimEclipsePropertyFilter.h"
|
||||||
#include "RimEclipsePropertyFilterCollection.h"
|
#include "RimEclipsePropertyFilterCollection.h"
|
||||||
|
|
||||||
#include "cafCmdExecCommandManager.h"
|
#include "cafCmdExecCommandManager.h"
|
||||||
|
#include "cafSelectionManagerTools.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
|
||||||
@@ -36,6 +38,13 @@ CAF_CMD_SOURCE_INIT( RicEclipsePropertyFilterNewFeature, "RicEclipsePropertyFilt
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
bool RicEclipsePropertyFilterNewFeature::isCommandEnabled() const
|
bool RicEclipsePropertyFilterNewFeature::isCommandEnabled() const
|
||||||
{
|
{
|
||||||
|
// Enabled if either a property-filter collection is selected, or a combined filter inside one is selected.
|
||||||
|
auto combined = caf::selectedObjectsByTypeStrict<RimCombinedFilter*>();
|
||||||
|
if ( !combined.empty() && combined.front()->firstAncestorOrThisOfType<RimEclipsePropertyFilterCollection>() )
|
||||||
|
{
|
||||||
|
return RicEclipsePropertyFilterFeatureImpl::isPropertyFilterCommandAvailable( combined.front() );
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<RimEclipsePropertyFilterCollection*> filterCollections =
|
std::vector<RimEclipsePropertyFilterCollection*> filterCollections =
|
||||||
RicEclipsePropertyFilterFeatureImpl::selectedPropertyFilterCollections();
|
RicEclipsePropertyFilterFeatureImpl::selectedPropertyFilterCollections();
|
||||||
if ( filterCollections.size() == 1 )
|
if ( filterCollections.size() == 1 )
|
||||||
@@ -51,6 +60,13 @@ bool RicEclipsePropertyFilterNewFeature::isCommandEnabled() const
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RicEclipsePropertyFilterNewFeature::onActionTriggered( bool isChecked )
|
void RicEclipsePropertyFilterNewFeature::onActionTriggered( bool isChecked )
|
||||||
{
|
{
|
||||||
|
auto combined = caf::selectedObjectsByTypeStrict<RimCombinedFilter*>();
|
||||||
|
if ( !combined.empty() && combined.front()->firstAncestorOrThisOfType<RimEclipsePropertyFilterCollection>() )
|
||||||
|
{
|
||||||
|
RicEclipsePropertyFilterFeatureImpl::addPropertyFilterToCombinedFilter( combined.front() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<RimEclipsePropertyFilterCollection*> filterCollections =
|
std::vector<RimEclipsePropertyFilterCollection*> filterCollections =
|
||||||
RicEclipsePropertyFilterFeatureImpl::selectedPropertyFilterCollections();
|
RicEclipsePropertyFilterFeatureImpl::selectedPropertyFilterCollections();
|
||||||
if ( filterCollections.size() == 1 )
|
if ( filterCollections.size() == 1 )
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "Rim3dOverlayInfoConfig.h"
|
#include "Rim3dOverlayInfoConfig.h"
|
||||||
#include "RimCellEdgeColors.h"
|
#include "RimCellEdgeColors.h"
|
||||||
|
#include "RimCellFilter.h"
|
||||||
#include "RimCellFilterCollection.h"
|
#include "RimCellFilterCollection.h"
|
||||||
#include "RimEclipseCase.h"
|
#include "RimEclipseCase.h"
|
||||||
#include "RimEclipseCellColors.h"
|
#include "RimEclipseCellColors.h"
|
||||||
@@ -853,92 +854,13 @@ void RivReservoirViewPartMgr::computePropertyVisibility( cvf::UByteArray*
|
|||||||
// Copy if not equal
|
// Copy if not equal
|
||||||
if ( cellVisibility != rangeFilterVisibility ) ( *cellVisibility ) = *rangeFilterVisibility;
|
if ( cellVisibility != rangeFilterVisibility ) ( *cellVisibility ) = *rangeFilterVisibility;
|
||||||
|
|
||||||
if ( propFilterColl->hasActiveFilters() )
|
if ( !propFilterColl->hasActiveFilters() ) return;
|
||||||
|
|
||||||
|
for ( RimCellFilter* filter : propFilterColl->filtersForEvaluation() )
|
||||||
{
|
{
|
||||||
for ( size_t i = 0; i < propFilterColl->propertyFilters().size(); i++ )
|
if ( filter && filter->isActive() )
|
||||||
{
|
{
|
||||||
RimEclipsePropertyFilter* propertyFilter = propFilterColl->propertyFilters()[i];
|
filter->applyToCellVisibility( cellVisibility, grid, timeStepIndex );
|
||||||
|
|
||||||
if ( propertyFilter->isActive() && propertyFilter->resultDefinition()->hasResult() )
|
|
||||||
{
|
|
||||||
propertyFilter->resultDefinition()->loadResult();
|
|
||||||
|
|
||||||
const RimCellFilter::FilterModeType filterType = propertyFilter->filterMode();
|
|
||||||
|
|
||||||
RigEclipseCaseData* eclipseCase = propFilterColl->reservoirView()->eclipseCase()->eclipseCaseData();
|
|
||||||
|
|
||||||
cvf::ref<RigResultAccessor> resultAccessor =
|
|
||||||
RigResultAccessorFactory::createFromResultDefinition( eclipseCase,
|
|
||||||
grid->gridIndex(),
|
|
||||||
timeStepIndex,
|
|
||||||
propertyFilter->resultDefinition() );
|
|
||||||
|
|
||||||
CVF_ASSERT( resultAccessor.notNull() );
|
|
||||||
|
|
||||||
if ( propertyFilter->isCategorySelectionActive() )
|
|
||||||
{
|
|
||||||
std::vector<int> integerVector = propertyFilter->selectedCategoryValues();
|
|
||||||
std::set<int> integerSet;
|
|
||||||
for ( auto val : integerVector )
|
|
||||||
{
|
|
||||||
integerSet.insert( val );
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( int cellIndex = 0; cellIndex < static_cast<int>( grid->cellCount() ); cellIndex++ )
|
|
||||||
{
|
|
||||||
if ( ( *cellVisibility )[cellIndex] )
|
|
||||||
{
|
|
||||||
size_t resultValueIndex = cellIndex;
|
|
||||||
|
|
||||||
double scalarValue = resultAccessor->cellScalar( resultValueIndex );
|
|
||||||
if ( integerSet.find( scalarValue ) != integerSet.end() )
|
|
||||||
{
|
|
||||||
if ( filterType == RimCellFilter::EXCLUDE )
|
|
||||||
{
|
|
||||||
( *cellVisibility )[cellIndex] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( filterType == RimCellFilter::INCLUDE )
|
|
||||||
{
|
|
||||||
( *cellVisibility )[cellIndex] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double lowerBound = 0.0;
|
|
||||||
double upperBound = 0.0;
|
|
||||||
propertyFilter->rangeValues( &lowerBound, &upperBound );
|
|
||||||
|
|
||||||
for ( int cellIndex = 0; cellIndex < static_cast<int>( grid->cellCount() ); cellIndex++ )
|
|
||||||
{
|
|
||||||
if ( ( *cellVisibility )[cellIndex] )
|
|
||||||
{
|
|
||||||
size_t resultValueIndex = cellIndex;
|
|
||||||
|
|
||||||
double scalarValue = resultAccessor->cellScalar( resultValueIndex );
|
|
||||||
if ( lowerBound <= scalarValue && scalarValue <= upperBound )
|
|
||||||
{
|
|
||||||
if ( filterType == RimCellFilter::EXCLUDE )
|
|
||||||
{
|
|
||||||
( *cellVisibility )[cellIndex] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( filterType == RimCellFilter::INCLUDE )
|
|
||||||
{
|
|
||||||
( *cellVisibility )[cellIndex] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RimCellFilter.h
|
${CMAKE_CURRENT_LIST_DIR}/RimCellFilter.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RimCellFilterCollection.h
|
${CMAKE_CURRENT_LIST_DIR}/RimCellFilterCollection.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RimCellRangeFilter.h
|
${CMAKE_CURRENT_LIST_DIR}/RimCellRangeFilter.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RimCombinedFilter.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RimPropertyFilter.h
|
${CMAKE_CURRENT_LIST_DIR}/RimPropertyFilter.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RimPropertyFilterCollection.h
|
${CMAKE_CURRENT_LIST_DIR}/RimPropertyFilterCollection.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RimEclipsePropertyFilter.h
|
${CMAKE_CURRENT_LIST_DIR}/RimEclipsePropertyFilter.h
|
||||||
@@ -19,6 +20,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RimCellFilter.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RimCellFilter.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RimCellFilterCollection.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RimCellFilterCollection.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RimCellRangeFilter.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RimCellRangeFilter.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RimCombinedFilter.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RimPropertyFilter.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RimPropertyFilter.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RimPropertyFilterCollection.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RimPropertyFilterCollection.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RimEclipsePropertyFilter.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RimEclipsePropertyFilter.cpp
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "RimCellFilter.h"
|
#include "RimCellFilter.h"
|
||||||
|
|
||||||
|
#include "RigGridBase.h"
|
||||||
#include "RigReservoirGridTools.h"
|
#include "RigReservoirGridTools.h"
|
||||||
#include "Rim3dView.h"
|
#include "Rim3dView.h"
|
||||||
#include "RimCase.h"
|
#include "RimCase.h"
|
||||||
@@ -302,6 +303,83 @@ QList<caf::PdmOptionItemInfo> RimCellFilter::calculateValueOptions( const caf::P
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCellFilter::applyToCellVisibility( cvf::UByteArray* cellVisibility, const RigGridBase* grid, size_t /*timeStepIndex*/ )
|
||||||
|
{
|
||||||
|
if ( cellVisibility == nullptr || grid == nullptr ) return;
|
||||||
|
|
||||||
|
const size_t n = cellVisibility->size();
|
||||||
|
if ( n == 0 ) return;
|
||||||
|
|
||||||
|
// Determine which cells are "in this filter's set" — independent of the filter's INCLUDE/EXCLUDE mode.
|
||||||
|
cvf::UByteArray inSet( n );
|
||||||
|
inSet.setAll( 0 );
|
||||||
|
|
||||||
|
const int gIndx = static_cast<int>( grid->gridIndex() );
|
||||||
|
|
||||||
|
if ( isRangeFilter() )
|
||||||
|
{
|
||||||
|
// updateCompundFilter is a no-op when the range filter targets a different grid than the
|
||||||
|
// one being evaluated. Skip the cellVisibility mutation entirely so LGR cells are not
|
||||||
|
// erroneously blanked by a main-grid-targeted filter (legacy: parentGridVisibilities).
|
||||||
|
if ( gridIndex() != gIndx ) return;
|
||||||
|
|
||||||
|
cvf::CellRangeFilter rf;
|
||||||
|
updateCompundFilter( &rf, gIndx );
|
||||||
|
|
||||||
|
const bool isSubGrid = !grid->isMainGrid();
|
||||||
|
|
||||||
|
for ( size_t cellIdx = 0; cellIdx < n; ++cellIdx )
|
||||||
|
{
|
||||||
|
size_t i = 0, j = 0, k = 0;
|
||||||
|
if ( grid->ijkFromCellIndex( cellIdx, &i, &j, &k ) )
|
||||||
|
{
|
||||||
|
// isCellVisible returns false when there are no include ranges (pure EXCLUDE
|
||||||
|
// mode), so also consult isCellExcluded to mark those cells as "in the set".
|
||||||
|
if ( rf.isCellVisible( i, j, k, isSubGrid ) || rf.isCellExcluded( i, j, k, isSubGrid ) )
|
||||||
|
{
|
||||||
|
inSet[cellIdx] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( isIndexFilter() )
|
||||||
|
{
|
||||||
|
// updateCellIndexFilter writes into include[] for INCLUDE-mode filters and exclude[] for
|
||||||
|
// EXCLUDE-mode filters. A cell is "in the set" iff either array was mutated at that index.
|
||||||
|
cvf::UByteArray incArr( n );
|
||||||
|
cvf::UByteArray excArr( n );
|
||||||
|
incArr.setAll( 0 );
|
||||||
|
excArr.setAll( 1 );
|
||||||
|
updateCellIndexFilter( &incArr, &excArr, gIndx );
|
||||||
|
for ( size_t i = 0; i < n; ++i )
|
||||||
|
{
|
||||||
|
if ( incArr[i] || !excArr[i] ) inSet[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unknown/property — subclass must override applyToCellVisibility. Default to no-op.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool isInclude = ( filterMode() == INCLUDE );
|
||||||
|
for ( size_t i = 0; i < n; ++i )
|
||||||
|
{
|
||||||
|
const bool in = ( inSet[i] != 0 );
|
||||||
|
if ( isInclude )
|
||||||
|
{
|
||||||
|
if ( !in ) ( *cellVisibility )[i] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( in ) ( *cellVisibility )[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class CellRangeFilter;
|
|||||||
class RimGeoMechCase;
|
class RimGeoMechCase;
|
||||||
class RimEclipseCase;
|
class RimEclipseCase;
|
||||||
class RimCase;
|
class RimCase;
|
||||||
|
class RigGridBase;
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
///
|
///
|
||||||
@@ -93,6 +94,11 @@ public:
|
|||||||
virtual QString fullName() const;
|
virtual QString fullName() const;
|
||||||
virtual void onGridChanged() {};
|
virtual void onGridChanged() {};
|
||||||
|
|
||||||
|
// Unified evaluation: take an incoming per-cell visibility mask and hide the cells that
|
||||||
|
// this filter rejects (respecting its own INCLUDE/EXCLUDE mode). The default implementation
|
||||||
|
// bridges the legacy range/index dispatch so existing subclasses do not need to override.
|
||||||
|
virtual void applyToCellVisibility( cvf::UByteArray* cellVisibility, const RigGridBase* grid, size_t timeStepIndex );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
caf::PdmFieldHandle* userDescriptionField() override;
|
caf::PdmFieldHandle* userDescriptionField() override;
|
||||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||||
|
|||||||
@@ -0,0 +1,538 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "RimCombinedFilter.h"
|
||||||
|
|
||||||
|
#include "RigGridBase.h"
|
||||||
|
#include "RigReservoirGridTools.h"
|
||||||
|
#include "RimCase.h"
|
||||||
|
#include "RimCellIndexFilter.h"
|
||||||
|
#include "RimCellRangeFilter.h"
|
||||||
|
#include "RimPolygonFilter.h"
|
||||||
|
#include "RimUserDefinedFilter.h"
|
||||||
|
#include "RimUserDefinedIndexFilter.h"
|
||||||
|
|
||||||
|
#include "Polygons/RimPolygon.h"
|
||||||
|
#include "Polygons/RimPolygonCollection.h"
|
||||||
|
#include "RiaResultNames.h"
|
||||||
|
#include "RimEclipsePropertyFilter.h"
|
||||||
|
#include "RimEclipsePropertyFilterCollection.h"
|
||||||
|
#include "RimEclipseResultDefinition.h"
|
||||||
|
#include "RimTools.h"
|
||||||
|
|
||||||
|
#include "cafCmdFeatureMenuBuilder.h"
|
||||||
|
#include "cafPdmFieldReorderCapability.h"
|
||||||
|
#include "cafPdmFieldScriptingCapability.h"
|
||||||
|
#include "cafPdmObjectScriptingCapability.h"
|
||||||
|
|
||||||
|
CAF_PDM_SOURCE_INIT( RimCombinedFilter, "CombinedFilter" );
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RimCombinedFilter::RimCombinedFilter()
|
||||||
|
: RimCellFilter( FilterDefinitionType::INDEX )
|
||||||
|
{
|
||||||
|
CAF_PDM_InitScriptableObject( "Combined Filter", ":/CellFilter.png" );
|
||||||
|
|
||||||
|
setName( "Combined Filter" );
|
||||||
|
|
||||||
|
CAF_PDM_InitScriptableFieldNoDefault( &m_filters, "Filters", "Filters" );
|
||||||
|
caf::PdmFieldReorderCapability::addToField( &m_filters );
|
||||||
|
|
||||||
|
CAF_PDM_InitScriptableFieldNoDefault( &m_combineMode, "CombineMode", "Combine Mode" );
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RimCombinedFilter::~RimCombinedFilter() = default;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::setCase( RimCase* srcCase )
|
||||||
|
{
|
||||||
|
RimCellFilter::setCase( srcCase );
|
||||||
|
for ( RimCellFilter* child : m_filters )
|
||||||
|
{
|
||||||
|
if ( child ) child->setCase( srcCase );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RimCombinedFilter::isFilterEnabled() const
|
||||||
|
{
|
||||||
|
if ( !isActive() ) return false;
|
||||||
|
|
||||||
|
for ( RimCellFilter* child : m_filters )
|
||||||
|
{
|
||||||
|
if ( child && child->isFilterEnabled() ) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::onGridChanged()
|
||||||
|
{
|
||||||
|
for ( RimCellFilter* child : m_filters )
|
||||||
|
{
|
||||||
|
if ( child ) child->onGridChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Evaluate each enabled child to its own per-cell mask (each child respects its own
|
||||||
|
/// INCLUDE/EXCLUDE mode inside applyToCellVisibility), AND/OR combine the masks, then apply this
|
||||||
|
/// combined filter's INCLUDE/EXCLUDE mode onto the incoming cellVisibility.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::applyToCellVisibility( cvf::UByteArray* cellVisibility, const RigGridBase* grid, size_t timeStepIndex )
|
||||||
|
{
|
||||||
|
if ( cellVisibility == nullptr || grid == nullptr ) return;
|
||||||
|
|
||||||
|
const size_t n = cellVisibility->size();
|
||||||
|
if ( n == 0 ) return;
|
||||||
|
|
||||||
|
std::vector<RimCellFilter*> enabledChildren;
|
||||||
|
for ( RimCellFilter* child : m_filters )
|
||||||
|
{
|
||||||
|
if ( child && child->isFilterEnabled() ) enabledChildren.push_back( child );
|
||||||
|
}
|
||||||
|
if ( enabledChildren.empty() ) return;
|
||||||
|
|
||||||
|
cvf::UByteArray combined( n );
|
||||||
|
combined.setAll( m_combineMode() == CombineMode::AND ? 1 : 0 );
|
||||||
|
|
||||||
|
for ( RimCellFilter* child : enabledChildren )
|
||||||
|
{
|
||||||
|
cvf::UByteArray childMask( n );
|
||||||
|
childMask.setAll( 1 );
|
||||||
|
child->applyToCellVisibility( &childMask, grid, timeStepIndex );
|
||||||
|
|
||||||
|
if ( m_combineMode() == CombineMode::AND )
|
||||||
|
{
|
||||||
|
for ( size_t i = 0; i < n; ++i )
|
||||||
|
combined[i] = combined[i] && childMask[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( size_t i = 0; i < n; ++i )
|
||||||
|
combined[i] = combined[i] || childMask[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool isInclude = ( filterMode() == INCLUDE );
|
||||||
|
for ( size_t i = 0; i < n; ++i )
|
||||||
|
{
|
||||||
|
if ( isInclude )
|
||||||
|
{
|
||||||
|
if ( !combined[i] ) ( *cellVisibility )[i] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( combined[i] ) ( *cellVisibility )[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Bridge for the cell-filter collection's legacy index-based dispatch. Combined filters normally
|
||||||
|
/// live under the property-filter collection, but this override exists to keep the class usable if
|
||||||
|
/// a future caller places one in the cell-filter collection. Builds a per-cell mask by running
|
||||||
|
/// applyToCellVisibility against an all-visible scratch array, then folds the result into the
|
||||||
|
/// collection's include/exclude arrays respecting this filter's INCLUDE/EXCLUDE mode.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::updateCellIndexFilter( cvf::UByteArray* includeVisibility, cvf::UByteArray* excludeVisibility, int gridIndex )
|
||||||
|
{
|
||||||
|
if ( includeVisibility == nullptr || excludeVisibility == nullptr ) return;
|
||||||
|
|
||||||
|
auto* sourceCase = m_srcCase();
|
||||||
|
if ( !sourceCase ) return;
|
||||||
|
|
||||||
|
const auto* structGrid = RigReservoirGridTools::gridByIndex( sourceCase, gridIndex );
|
||||||
|
const auto* grid = dynamic_cast<const RigGridBase*>( structGrid );
|
||||||
|
if ( grid == nullptr ) return;
|
||||||
|
|
||||||
|
const size_t n = includeVisibility->size();
|
||||||
|
if ( n == 0 ) return;
|
||||||
|
|
||||||
|
cvf::UByteArray scratch( n );
|
||||||
|
scratch.setAll( 1 );
|
||||||
|
applyToCellVisibility( &scratch, grid, 0 );
|
||||||
|
|
||||||
|
if ( filterMode() == INCLUDE )
|
||||||
|
{
|
||||||
|
for ( size_t i = 0; i < n; ++i )
|
||||||
|
if ( scratch[i] ) ( *includeVisibility )[i] = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( size_t i = 0; i < n; ++i )
|
||||||
|
if ( !scratch[i] ) ( *excludeVisibility )[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
QString RimCombinedFilter::fullName() const
|
||||||
|
{
|
||||||
|
const QString modeStr = ( m_combineMode() == CombineMode::AND ) ? "AND" : "OR";
|
||||||
|
return QString( "%1 [%2: %3]" ).arg( name() ).arg( modeStr ).arg( m_filters.size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::addFilter( RimCellFilter* child )
|
||||||
|
{
|
||||||
|
if ( !child ) return;
|
||||||
|
if ( wouldCreateCycle( child ) ) return;
|
||||||
|
m_filters.push_back( child );
|
||||||
|
child->setCase( m_srcCase() );
|
||||||
|
child->filterChanged.connect( this, &RimCombinedFilter::onChildFilterChanged );
|
||||||
|
updateConnectedEditors();
|
||||||
|
triggerFilterChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::removeFilter( RimCellFilter* child )
|
||||||
|
{
|
||||||
|
if ( !child ) return;
|
||||||
|
m_filters.removeChild( child );
|
||||||
|
triggerFilterChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
std::vector<RimCellFilter*> RimCombinedFilter::filters() const
|
||||||
|
{
|
||||||
|
return m_filters.childrenByType();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RimCellRangeFilter* RimCombinedFilter::addNewCellRangeFilter( RimCase* srcCase, int gridIndex, int sliceDirection, int defaultSlice )
|
||||||
|
{
|
||||||
|
auto* f = new RimCellRangeFilter();
|
||||||
|
addFilter( f );
|
||||||
|
f->setCase( srcCase );
|
||||||
|
f->setGridIndex( gridIndex );
|
||||||
|
f->setDefaultValues( sliceDirection, defaultSlice );
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RimPolygonFilter* RimCombinedFilter::addNewPolygonFilter( RimCase* srcCase, RimPolygon* polygon )
|
||||||
|
{
|
||||||
|
auto* f = new RimPolygonFilter();
|
||||||
|
addFilter( f );
|
||||||
|
f->setCase( srcCase );
|
||||||
|
f->setPolygon( polygon );
|
||||||
|
f->configurePolygonEditor();
|
||||||
|
if ( polygon )
|
||||||
|
{
|
||||||
|
f->enableFilter( true );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f->enablePicking( true );
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RimCellIndexFilter* RimCombinedFilter::addNewCellIndexFilter( RimCase* srcCase )
|
||||||
|
{
|
||||||
|
auto* f = new RimCellIndexFilter();
|
||||||
|
addFilter( f );
|
||||||
|
f->setCase( srcCase );
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RimUserDefinedFilter* RimCombinedFilter::addNewUserDefinedFilter( RimCase* srcCase )
|
||||||
|
{
|
||||||
|
auto* f = new RimUserDefinedFilter();
|
||||||
|
addFilter( f );
|
||||||
|
f->setCase( srcCase );
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RimUserDefinedIndexFilter* RimCombinedFilter::addNewUserDefinedIndexFilter( RimCase* srcCase, const std::vector<size_t>& defCellIndexes )
|
||||||
|
{
|
||||||
|
auto* f = new RimUserDefinedIndexFilter();
|
||||||
|
addFilter( f );
|
||||||
|
f->setCase( srcCase );
|
||||||
|
f->setCellIndexes( defCellIndexes );
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RimCombinedFilter* RimCombinedFilter::addNewCombinedFilter( RimCase* srcCase )
|
||||||
|
{
|
||||||
|
auto* f = new RimCombinedFilter();
|
||||||
|
addFilter( f );
|
||||||
|
f->setCase( srcCase );
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::setCombineMode( CombineMode mode )
|
||||||
|
{
|
||||||
|
m_combineMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RimCombinedFilter::CombineMode RimCombinedFilter::combineMode() const
|
||||||
|
{
|
||||||
|
return m_combineMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||||
|
{
|
||||||
|
uiOrdering.add( nameField() );
|
||||||
|
auto* group = uiOrdering.addNewGroup( "General" );
|
||||||
|
group->add( &m_filterMode );
|
||||||
|
group->add( &m_combineMode );
|
||||||
|
uiOrdering.skipRemainingFields( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
||||||
|
{
|
||||||
|
PdmObject::defineUiTreeOrdering( uiTreeOrdering, uiConfigName );
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
||||||
|
{
|
||||||
|
updateIconState();
|
||||||
|
triggerFilterChanged();
|
||||||
|
notifyHostCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Called by CAF when a new object is pushed into m_filters (e.g. via our factory methods or via
|
||||||
|
/// drag-and-drop). Propagate so the host collection regenerates geometry.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::onChildAdded( caf::PdmFieldHandle* /*containerForNewObject*/ )
|
||||||
|
{
|
||||||
|
triggerFilterChanged();
|
||||||
|
notifyHostCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Combined filters live only under the Eclipse property-filter collection, which triggers view
|
||||||
|
/// regen via an explicit updateDisplayModelNotifyManagedViews() call rather than by subscribing to
|
||||||
|
/// filterChanged. Call that API directly so our edits propagate.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::notifyHostCollection()
|
||||||
|
{
|
||||||
|
if ( auto* propColl = firstAncestorOrThisOfType<RimEclipsePropertyFilterCollection>() )
|
||||||
|
{
|
||||||
|
propColl->updateDisplayModelNotifyManagedViews( nullptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Called after reading from a project file. Re-wire child filterChanged signals so edits made to
|
||||||
|
/// deserialized children propagate up.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::initAfterRead()
|
||||||
|
{
|
||||||
|
RimCellFilter::initAfterRead();
|
||||||
|
for ( RimCellFilter* child : m_filters )
|
||||||
|
{
|
||||||
|
if ( child ) child->filterChanged.connect( this, &RimCombinedFilter::onChildFilterChanged );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Propagate a child's change up so the view re-renders.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::onChildFilterChanged( const caf::SignalEmitter* /*emitter*/ )
|
||||||
|
{
|
||||||
|
triggerFilterChanged();
|
||||||
|
notifyHostCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Any enabled child that the combined filter would actually evaluate. Property-filter children
|
||||||
|
/// also need a loaded result; other cell filters are always evaluatable when enabled.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RimCombinedFilter::hasActiveEvaluatableDescendant() const
|
||||||
|
{
|
||||||
|
for ( RimCellFilter* child : m_filters )
|
||||||
|
{
|
||||||
|
if ( !child || !child->isFilterEnabled() ) continue;
|
||||||
|
|
||||||
|
if ( auto* ep = dynamic_cast<RimEclipsePropertyFilter*>( child ) )
|
||||||
|
{
|
||||||
|
if ( ep->resultDefinition() && ep->resultDefinition()->hasResult() ) return true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( auto* nested = dynamic_cast<RimCombinedFilter*>( child ) )
|
||||||
|
{
|
||||||
|
if ( nested->hasActiveEvaluatableDescendant() ) return true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Range, polygon, index, user-defined — evaluatable whenever enabled.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// True if any active descendant is an Eclipse property filter backed by a dynamic result. Drives
|
||||||
|
/// per-time-step cell-visibility cache invalidation in RimGridView.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RimCombinedFilter::hasActiveDynamicPropertyDescendant() const
|
||||||
|
{
|
||||||
|
for ( RimCellFilter* child : m_filters )
|
||||||
|
{
|
||||||
|
if ( !child || !child->isFilterEnabled() ) continue;
|
||||||
|
|
||||||
|
if ( auto* ep = dynamic_cast<RimEclipsePropertyFilter*>( child ) )
|
||||||
|
{
|
||||||
|
if ( ep->resultDefinition() && ep->resultDefinition()->hasDynamicResult() ) return true;
|
||||||
|
}
|
||||||
|
else if ( auto* nested = dynamic_cast<RimCombinedFilter*>( child ) )
|
||||||
|
{
|
||||||
|
if ( nested->hasActiveDynamicPropertyDescendant() ) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// True if any active descendant is a formation-names property filter. Matches the collection-level
|
||||||
|
/// isUsingFormationNames() check.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RimCombinedFilter::hasActiveFormationNamesPropertyDescendant() const
|
||||||
|
{
|
||||||
|
for ( RimCellFilter* child : m_filters )
|
||||||
|
{
|
||||||
|
if ( !child || !child->isFilterEnabled() ) continue;
|
||||||
|
|
||||||
|
if ( auto* ep = dynamic_cast<RimEclipsePropertyFilter*>( child ) )
|
||||||
|
{
|
||||||
|
auto* rd = ep->resultDefinition();
|
||||||
|
if ( rd && rd->resultType() == RiaDefines::ResultCatType::FORMATION_NAMES &&
|
||||||
|
rd->resultVariable() != RiaResultNames::undefinedResultName() )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( auto* nested = dynamic_cast<RimCombinedFilter*>( child ) )
|
||||||
|
{
|
||||||
|
if ( nested->hasActiveFormationNamesPropertyDescendant() ) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Right-click "add child" menu on the combined filter. Since combined filters only live under the
|
||||||
|
/// Eclipse property-filter collection, the menu always offers the full mixed-type set: property
|
||||||
|
/// filter, polygon, ranges, index, user-defined, and a nested combined filter.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimCombinedFilter::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const
|
||||||
|
{
|
||||||
|
menuBuilder << "RicEclipsePropertyFilterNewFeature";
|
||||||
|
menuBuilder << "Separator";
|
||||||
|
|
||||||
|
menuBuilder.subMenuStart( "Polygon Filter", QIcon( ":/CellFilter_Polygon.png" ) );
|
||||||
|
{
|
||||||
|
auto polygonCollection = RimTools::polygonCollection();
|
||||||
|
if ( polygonCollection )
|
||||||
|
{
|
||||||
|
for ( auto p : polygonCollection->allPolygons() )
|
||||||
|
{
|
||||||
|
if ( !p ) continue;
|
||||||
|
menuBuilder.addCmdFeatureWithUserData( "RicNewPolygonFilterFeature", p->name(), QVariant::fromValue( static_cast<void*>( p ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menuBuilder.subMenuEnd();
|
||||||
|
|
||||||
|
menuBuilder << "RicNewPolygonFilterFeature";
|
||||||
|
menuBuilder << "Separator";
|
||||||
|
menuBuilder.subMenuStart( "Range Filter" );
|
||||||
|
menuBuilder << "RicNewRangeFilterSliceIFeature";
|
||||||
|
menuBuilder << "RicNewRangeFilterSliceJFeature";
|
||||||
|
menuBuilder << "RicNewRangeFilterSliceKFeature";
|
||||||
|
menuBuilder << "RicNewCellRangeFilterFeature";
|
||||||
|
menuBuilder.subMenuEnd();
|
||||||
|
menuBuilder << "RicNewCellIndexFilterFeature";
|
||||||
|
menuBuilder << "Separator";
|
||||||
|
menuBuilder << "RicNewUserDefinedFilterFeature";
|
||||||
|
menuBuilder << "RicNewUserDefinedIndexFilterFeature";
|
||||||
|
menuBuilder << "Separator";
|
||||||
|
menuBuilder << "RicEclipseCombinedPropertyFilterNewFeature";
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Refuse additions that would create a cycle: candidate must not be `this`, and if candidate is a
|
||||||
|
/// combined filter, `this` must not appear anywhere in its subtree.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RimCombinedFilter::wouldCreateCycle( RimCellFilter* candidate ) const
|
||||||
|
{
|
||||||
|
if ( candidate == this ) return true;
|
||||||
|
|
||||||
|
auto* candidateCombined = dynamic_cast<RimCombinedFilter*>( candidate );
|
||||||
|
if ( !candidateCombined ) return false;
|
||||||
|
|
||||||
|
for ( RimCellFilter* grandchild : candidateCombined->filters() )
|
||||||
|
{
|
||||||
|
if ( grandchild == this ) return true;
|
||||||
|
if ( auto* gcCombined = dynamic_cast<RimCombinedFilter*>( grandchild ) )
|
||||||
|
{
|
||||||
|
if ( wouldCreateCycle( gcCombined ) ) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "RimCellFilter.h"
|
||||||
|
#include "RimCellFilterCollection.h"
|
||||||
|
|
||||||
|
#include "cafAppEnum.h"
|
||||||
|
#include "cafPdmChildArrayField.h"
|
||||||
|
#include "cafPdmField.h"
|
||||||
|
|
||||||
|
class RimCellIndexFilter;
|
||||||
|
class RimCellRangeFilter;
|
||||||
|
class RimPolygon;
|
||||||
|
class RimPolygonFilter;
|
||||||
|
class RimUserDefinedFilter;
|
||||||
|
class RimUserDefinedIndexFilter;
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
/// A filter whose result is a boolean combination (AND / OR) of its child filters' results.
|
||||||
|
/// Child filters are evaluated to per-cell masks (each respecting its own INCLUDE/EXCLUDE mode),
|
||||||
|
/// then combined. The combined filter's own INCLUDE/EXCLUDE mode is applied to the output.
|
||||||
|
/// Nesting is supported — a combined filter may contain other combined filters. Lives only inside
|
||||||
|
/// RimEclipsePropertyFilterCollection; that's the one collection whose evaluation pipeline supplies
|
||||||
|
/// a time step, which is required for property-filter children.
|
||||||
|
//==================================================================================================
|
||||||
|
class RimCombinedFilter : public RimCellFilter
|
||||||
|
{
|
||||||
|
CAF_PDM_HEADER_INIT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using CombineMode = RimCellFilterCollection::CombineFilterModeType;
|
||||||
|
|
||||||
|
RimCombinedFilter();
|
||||||
|
~RimCombinedFilter() override;
|
||||||
|
|
||||||
|
void setCase( RimCase* srcCase ) override;
|
||||||
|
bool isFilterEnabled() const override;
|
||||||
|
void onGridChanged() override;
|
||||||
|
|
||||||
|
void applyToCellVisibility( cvf::UByteArray* cellVisibility, const RigGridBase* grid, size_t timeStepIndex ) override;
|
||||||
|
|
||||||
|
// Bridge from legacy collection dispatch: combined filter is declared INDEX-type, so the cell
|
||||||
|
// filter collection's evaluation path (if ever called) would route through updateCellIndexFilter.
|
||||||
|
void updateCompundFilter( cvf::CellRangeFilter*, int ) override {}
|
||||||
|
void updateCellIndexFilter( cvf::UByteArray* includeVisibility, cvf::UByteArray* excludeVisibility, int gridIndex ) override;
|
||||||
|
|
||||||
|
QString fullName() const override;
|
||||||
|
|
||||||
|
void addFilter( RimCellFilter* child );
|
||||||
|
void removeFilter( RimCellFilter* child );
|
||||||
|
std::vector<RimCellFilter*> filters() const;
|
||||||
|
|
||||||
|
// Recursive introspection helpers — used by the property-filter collection so that a combined
|
||||||
|
// filter sitting in that collection can report whether it has evaluation-worthy descendants.
|
||||||
|
bool hasActiveEvaluatableDescendant() const;
|
||||||
|
bool hasActiveDynamicPropertyDescendant() const;
|
||||||
|
bool hasActiveFormationNamesPropertyDescendant() const;
|
||||||
|
|
||||||
|
// Typed factory methods — mirror the ones on RimCellFilterCollection so features can add
|
||||||
|
// children of the correct type directly.
|
||||||
|
RimCellRangeFilter* addNewCellRangeFilter( RimCase* srcCase, int gridIndex, int sliceDirection = -1, int defaultSlice = -1 );
|
||||||
|
RimPolygonFilter* addNewPolygonFilter( RimCase* srcCase, RimPolygon* polygon );
|
||||||
|
RimCellIndexFilter* addNewCellIndexFilter( RimCase* srcCase );
|
||||||
|
RimUserDefinedFilter* addNewUserDefinedFilter( RimCase* srcCase );
|
||||||
|
RimUserDefinedIndexFilter* addNewUserDefinedIndexFilter( RimCase* srcCase, const std::vector<size_t>& defCellIndexes = {} );
|
||||||
|
RimCombinedFilter* addNewCombinedFilter( RimCase* srcCase );
|
||||||
|
|
||||||
|
void setCombineMode( CombineMode mode );
|
||||||
|
CombineMode combineMode() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||||
|
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName ) override;
|
||||||
|
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||||
|
void initAfterRead() override;
|
||||||
|
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
|
||||||
|
void onChildAdded( caf::PdmFieldHandle* containerForNewObject ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool wouldCreateCycle( RimCellFilter* candidate ) const;
|
||||||
|
void onChildFilterChanged( const caf::SignalEmitter* emitter );
|
||||||
|
|
||||||
|
// Combined filters only sit inside RimEclipsePropertyFilterCollection, which doesn't use
|
||||||
|
// filterChanged signals — it requires an explicit updateDisplayModelNotifyManagedViews() call
|
||||||
|
// to trigger a view regen. This helper performs that call.
|
||||||
|
void notifyHostCollection();
|
||||||
|
|
||||||
|
caf::PdmChildArrayField<RimCellFilter*> m_filters;
|
||||||
|
caf::PdmField<caf::AppEnum<CombineMode>> m_combineMode;
|
||||||
|
};
|
||||||
@@ -30,6 +30,9 @@
|
|||||||
#include "RigEclipseResultAddress.h"
|
#include "RigEclipseResultAddress.h"
|
||||||
#include "RigFlowDiagResults.h"
|
#include "RigFlowDiagResults.h"
|
||||||
#include "RigFormationNames.h"
|
#include "RigFormationNames.h"
|
||||||
|
#include "RigGridBase.h"
|
||||||
|
#include "RigResultAccessor.h"
|
||||||
|
#include "RigResultAccessorFactory.h"
|
||||||
|
|
||||||
#include "RimEclipseCase.h"
|
#include "RimEclipseCase.h"
|
||||||
#include "RimEclipsePropertyFilterCollection.h"
|
#include "RimEclipsePropertyFilterCollection.h"
|
||||||
@@ -698,6 +701,93 @@ void RimEclipsePropertyFilter::initAfterRead()
|
|||||||
updateIconState();
|
updateIconState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Evaluate this property filter against the incoming cell visibility mask. Only cells that
|
||||||
|
/// are currently visible are considered; non-matching cells are flipped to invisible according
|
||||||
|
/// to the INCLUDE/EXCLUDE mode. This is a generic hook the renderer uses to treat every filter
|
||||||
|
/// uniformly; the body is extracted from the former inline loop in
|
||||||
|
/// RivReservoirViewPartMgr::computePropertyVisibility.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimEclipsePropertyFilter::applyToCellVisibility( cvf::UByteArray* cellVisibility, const RigGridBase* grid, size_t timeStepIndex )
|
||||||
|
{
|
||||||
|
if ( cellVisibility == nullptr || grid == nullptr ) return;
|
||||||
|
if ( !isActive() || !resultDefinition()->hasResult() ) return;
|
||||||
|
|
||||||
|
resultDefinition()->loadResult();
|
||||||
|
|
||||||
|
auto* container = parentContainer();
|
||||||
|
if ( !container ) return;
|
||||||
|
auto* view = container->reservoirView();
|
||||||
|
if ( !view || !view->eclipseCase() ) return;
|
||||||
|
RigEclipseCaseData* eclipseCase = view->eclipseCase()->eclipseCaseData();
|
||||||
|
if ( !eclipseCase ) return;
|
||||||
|
|
||||||
|
cvf::ref<RigResultAccessor> resultAccessor =
|
||||||
|
RigResultAccessorFactory::createFromResultDefinition( eclipseCase, grid->gridIndex(), timeStepIndex, resultDefinition() );
|
||||||
|
|
||||||
|
CVF_ASSERT( resultAccessor.notNull() );
|
||||||
|
|
||||||
|
const RimCellFilter::FilterModeType filterType = filterMode();
|
||||||
|
|
||||||
|
if ( isCategorySelectionActive() )
|
||||||
|
{
|
||||||
|
std::vector<int> integerVector = selectedCategoryValues();
|
||||||
|
std::set<int> integerSet( integerVector.begin(), integerVector.end() );
|
||||||
|
|
||||||
|
for ( int cellIndex = 0; cellIndex < static_cast<int>( grid->cellCount() ); cellIndex++ )
|
||||||
|
{
|
||||||
|
if ( ( *cellVisibility )[cellIndex] )
|
||||||
|
{
|
||||||
|
size_t resultValueIndex = cellIndex;
|
||||||
|
double scalarValue = resultAccessor->cellScalar( resultValueIndex );
|
||||||
|
if ( integerSet.find( static_cast<int>( scalarValue ) ) != integerSet.end() )
|
||||||
|
{
|
||||||
|
if ( filterType == RimCellFilter::EXCLUDE )
|
||||||
|
{
|
||||||
|
( *cellVisibility )[cellIndex] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( filterType == RimCellFilter::INCLUDE )
|
||||||
|
{
|
||||||
|
( *cellVisibility )[cellIndex] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double lowerBound = 0.0;
|
||||||
|
double upperBound = 0.0;
|
||||||
|
rangeValues( &lowerBound, &upperBound );
|
||||||
|
|
||||||
|
for ( int cellIndex = 0; cellIndex < static_cast<int>( grid->cellCount() ); cellIndex++ )
|
||||||
|
{
|
||||||
|
if ( ( *cellVisibility )[cellIndex] )
|
||||||
|
{
|
||||||
|
size_t resultValueIndex = cellIndex;
|
||||||
|
double scalarValue = resultAccessor->cellScalar( resultValueIndex );
|
||||||
|
if ( lowerBound <= scalarValue && scalarValue <= upperBound )
|
||||||
|
{
|
||||||
|
if ( filterType == RimCellFilter::EXCLUDE )
|
||||||
|
{
|
||||||
|
( *cellVisibility )[cellIndex] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( filterType == RimCellFilter::INCLUDE )
|
||||||
|
{
|
||||||
|
( *cellVisibility )[cellIndex] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ public:
|
|||||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||||
void initAfterRead() override;
|
void initAfterRead() override;
|
||||||
|
|
||||||
|
void applyToCellVisibility( cvf::UByteArray* cellVisibility, const RigGridBase* grid, size_t timeStepIndex ) override;
|
||||||
|
|
||||||
void updateUiFieldsFromActiveResult();
|
void updateUiFieldsFromActiveResult();
|
||||||
|
|
||||||
std::map<QString, std::vector<caf::PdmFieldHandle*>> quickAccessFields() override;
|
std::map<QString, std::vector<caf::PdmFieldHandle*>> quickAccessFields() override;
|
||||||
|
|||||||
+85
-16
@@ -22,6 +22,9 @@
|
|||||||
|
|
||||||
#include "RiaResultNames.h"
|
#include "RiaResultNames.h"
|
||||||
|
|
||||||
|
#include "RimCellFilter.h"
|
||||||
|
#include "RimCombinedFilter.h"
|
||||||
|
#include "RimEclipseCase.h"
|
||||||
#include "RimEclipseCellColors.h"
|
#include "RimEclipseCellColors.h"
|
||||||
#include "RimEclipsePropertyFilter.h"
|
#include "RimEclipsePropertyFilter.h"
|
||||||
#include "RimEclipseResultDefinition.h"
|
#include "RimEclipseResultDefinition.h"
|
||||||
@@ -57,7 +60,7 @@ RimEclipseView* RimEclipsePropertyFilterCollection::reservoirView()
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RimEclipsePropertyFilterCollection::setIsDuplicatedFromLinkedView()
|
void RimEclipsePropertyFilterCollection::setIsDuplicatedFromLinkedView()
|
||||||
{
|
{
|
||||||
for ( RimEclipsePropertyFilter* propertyFilter : m_propertyFilters )
|
for ( RimEclipsePropertyFilter* propertyFilter : propertyFilters() )
|
||||||
{
|
{
|
||||||
propertyFilter->setIsDuplicatedFromLinkedView( true );
|
propertyFilter->setIsDuplicatedFromLinkedView( true );
|
||||||
}
|
}
|
||||||
@@ -68,23 +71,36 @@ void RimEclipsePropertyFilterCollection::setIsDuplicatedFromLinkedView()
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
std::vector<RimEclipsePropertyFilter*> RimEclipsePropertyFilterCollection::propertyFilters() const
|
std::vector<RimEclipsePropertyFilter*> RimEclipsePropertyFilterCollection::propertyFilters() const
|
||||||
{
|
{
|
||||||
return m_propertyFilters.childrenByType();
|
std::vector<RimEclipsePropertyFilter*> typed;
|
||||||
|
for ( RimCellFilter* f : m_propertyFilters )
|
||||||
|
{
|
||||||
|
if ( auto* ep = dynamic_cast<RimEclipsePropertyFilter*>( f ) ) typed.push_back( ep );
|
||||||
|
}
|
||||||
|
return typed;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
caf::PdmChildArrayField<RimEclipsePropertyFilter*>& RimEclipsePropertyFilterCollection::propertyFiltersField()
|
caf::PdmChildArrayField<RimCellFilter*>& RimEclipsePropertyFilterCollection::propertyFiltersField()
|
||||||
{
|
{
|
||||||
return m_propertyFilters;
|
return m_propertyFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
std::vector<RimCellFilter*> RimEclipsePropertyFilterCollection::filtersForEvaluation() const
|
||||||
|
{
|
||||||
|
return m_propertyFilters.childrenByType();
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RimEclipsePropertyFilterCollection::loadAndInitializePropertyFilters()
|
void RimEclipsePropertyFilterCollection::loadAndInitializePropertyFilters()
|
||||||
{
|
{
|
||||||
for ( RimEclipsePropertyFilter* propertyFilter : m_propertyFilters )
|
for ( RimEclipsePropertyFilter* propertyFilter : propertyFilters() )
|
||||||
{
|
{
|
||||||
propertyFilter->resultDefinition()->setEclipseCase( reservoirView()->eclipseCase() );
|
propertyFilter->resultDefinition()->setEclipseCase( reservoirView()->eclipseCase() );
|
||||||
propertyFilter->initAfterRead();
|
propertyFilter->initAfterRead();
|
||||||
@@ -111,24 +127,47 @@ bool RimEclipsePropertyFilterCollection::hasActiveFilters() const
|
|||||||
{
|
{
|
||||||
if ( !isActive ) return false;
|
if ( !isActive ) return false;
|
||||||
|
|
||||||
for ( RimEclipsePropertyFilter* propertyFilter : m_propertyFilters )
|
for ( RimCellFilter* filter : filtersForEvaluation() )
|
||||||
{
|
{
|
||||||
if ( propertyFilter->isActive() && propertyFilter->resultDefinition()->hasResult() ) return true;
|
if ( !filter || !filter->isFilterEnabled() ) continue;
|
||||||
|
|
||||||
|
if ( auto* ep = dynamic_cast<RimEclipsePropertyFilter*>( filter ) )
|
||||||
|
{
|
||||||
|
if ( ep->resultDefinition() && ep->resultDefinition()->hasResult() ) return true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( auto* comp = dynamic_cast<RimCombinedFilter*>( filter ) )
|
||||||
|
{
|
||||||
|
if ( comp->hasActiveEvaluatableDescendant() ) return true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Any other cell-filter subtype placed in this collection is evaluatable when enabled.
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
/// Returns whether any of the active property filters are based on a dynamic result
|
/// Returns whether any of the active property filters are based on a dynamic result. Includes
|
||||||
|
/// property filters nested inside compound filters so time-step updates invalidate correctly.
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
bool RimEclipsePropertyFilterCollection::hasActiveDynamicFilters() const
|
bool RimEclipsePropertyFilterCollection::hasActiveDynamicFilters() const
|
||||||
{
|
{
|
||||||
if ( !isActive ) return false;
|
if ( !isActive ) return false;
|
||||||
|
|
||||||
for ( RimEclipsePropertyFilter* propertyFilter : m_propertyFilters )
|
for ( RimCellFilter* filter : filtersForEvaluation() )
|
||||||
{
|
{
|
||||||
if ( propertyFilter->isActive() && propertyFilter->resultDefinition()->hasDynamicResult() ) return true;
|
if ( !filter || !filter->isFilterEnabled() ) continue;
|
||||||
|
|
||||||
|
if ( auto* ep = dynamic_cast<RimEclipsePropertyFilter*>( filter ) )
|
||||||
|
{
|
||||||
|
if ( ep->resultDefinition() && ep->resultDefinition()->hasDynamicResult() ) return true;
|
||||||
|
}
|
||||||
|
else if ( auto* comp = dynamic_cast<RimCombinedFilter*>( filter ) )
|
||||||
|
{
|
||||||
|
if ( comp->hasActiveDynamicPropertyDescendant() ) return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -141,11 +180,21 @@ bool RimEclipsePropertyFilterCollection::isUsingFormationNames() const
|
|||||||
{
|
{
|
||||||
if ( !isActive ) return false;
|
if ( !isActive ) return false;
|
||||||
|
|
||||||
for ( RimEclipsePropertyFilter* propertyFilter : m_propertyFilters )
|
for ( RimCellFilter* filter : filtersForEvaluation() )
|
||||||
{
|
{
|
||||||
if ( propertyFilter->isActive() && propertyFilter->resultDefinition()->resultType() == RiaDefines::ResultCatType::FORMATION_NAMES &&
|
if ( !filter || !filter->isFilterEnabled() ) continue;
|
||||||
propertyFilter->resultDefinition()->resultVariable() != RiaResultNames::undefinedResultName() )
|
|
||||||
return true;
|
if ( auto* ep = dynamic_cast<RimEclipsePropertyFilter*>( filter ) )
|
||||||
|
{
|
||||||
|
auto* rd = ep->resultDefinition();
|
||||||
|
if ( rd && rd->resultType() == RiaDefines::ResultCatType::FORMATION_NAMES &&
|
||||||
|
rd->resultVariable() != RiaResultNames::undefinedResultName() )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( auto* comp = dynamic_cast<RimCombinedFilter*>( filter ) )
|
||||||
|
{
|
||||||
|
if ( comp->hasActiveFormationNamesPropertyDescendant() ) return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -175,7 +224,7 @@ void RimEclipsePropertyFilterCollection::updateIconState()
|
|||||||
|
|
||||||
updateUiIconFromState( activeIcon );
|
updateUiIconFromState( activeIcon );
|
||||||
|
|
||||||
for ( RimEclipsePropertyFilter* cellFilter : m_propertyFilters )
|
for ( RimEclipsePropertyFilter* cellFilter : propertyFilters() )
|
||||||
{
|
{
|
||||||
cellFilter->updateActiveState();
|
cellFilter->updateActiveState();
|
||||||
cellFilter->updateIconState();
|
cellFilter->updateIconState();
|
||||||
@@ -187,7 +236,7 @@ void RimEclipsePropertyFilterCollection::updateIconState()
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RimEclipsePropertyFilterCollection::updateFromCurrentTimeStep()
|
void RimEclipsePropertyFilterCollection::updateFromCurrentTimeStep()
|
||||||
{
|
{
|
||||||
for ( RimEclipsePropertyFilter* cellFilter : m_propertyFilters() )
|
for ( RimEclipsePropertyFilter* cellFilter : propertyFilters() )
|
||||||
{
|
{
|
||||||
cellFilter->updateFromCurrentTimeStep();
|
cellFilter->updateFromCurrentTimeStep();
|
||||||
}
|
}
|
||||||
@@ -202,7 +251,7 @@ void RimEclipsePropertyFilterCollection::updateDefaultResult( const RimEclipseCe
|
|||||||
if ( m_propertyFilters.empty() ) return;
|
if ( m_propertyFilters.empty() ) return;
|
||||||
|
|
||||||
auto view = reservoirView();
|
auto view = reservoirView();
|
||||||
for ( auto filter : m_propertyFilters )
|
for ( RimEclipsePropertyFilter* filter : propertyFilters() )
|
||||||
{
|
{
|
||||||
if ( !filter->isLinkedWithCellResult() ) continue;
|
if ( !filter->isLinkedWithCellResult() ) continue;
|
||||||
|
|
||||||
@@ -243,4 +292,24 @@ void RimEclipsePropertyFilterCollection::appendMenuItems( caf::CmdFeatureMenuBui
|
|||||||
{
|
{
|
||||||
menuBuilder << "RicEclipsePropertyFilterNewFeature";
|
menuBuilder << "RicEclipsePropertyFilterNewFeature";
|
||||||
menuBuilder << "RicAddLinkedEclipsePropertyFilterFeature";
|
menuBuilder << "RicAddLinkedEclipsePropertyFilterFeature";
|
||||||
|
menuBuilder << "Separator";
|
||||||
|
menuBuilder << "RicEclipseCombinedPropertyFilterNewFeature";
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RimCombinedFilter* RimEclipsePropertyFilterCollection::addNewCombinedFilter()
|
||||||
|
{
|
||||||
|
auto* combined = new RimCombinedFilter();
|
||||||
|
|
||||||
|
auto view = reservoirView();
|
||||||
|
if ( view && view->eclipseCase() )
|
||||||
|
{
|
||||||
|
combined->setCase( view->eclipseCase() );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_propertyFilters.push_back( combined );
|
||||||
|
updateConnectedEditors();
|
||||||
|
return combined;
|
||||||
}
|
}
|
||||||
+10
-3
@@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include "cafPdmChildArrayField.h"
|
#include "cafPdmChildArrayField.h"
|
||||||
|
|
||||||
|
class RimCellFilter;
|
||||||
|
class RimCombinedFilter;
|
||||||
class RimEclipsePropertyFilter;
|
class RimEclipsePropertyFilter;
|
||||||
class RimEclipseView;
|
class RimEclipseView;
|
||||||
class RimEclipseCellColors;
|
class RimEclipseCellColors;
|
||||||
@@ -42,8 +44,12 @@ public:
|
|||||||
RimEclipseView* reservoirView();
|
RimEclipseView* reservoirView();
|
||||||
void setIsDuplicatedFromLinkedView();
|
void setIsDuplicatedFromLinkedView();
|
||||||
|
|
||||||
std::vector<RimEclipsePropertyFilter*> propertyFilters() const;
|
std::vector<RimEclipsePropertyFilter*> propertyFilters() const;
|
||||||
caf::PdmChildArrayField<RimEclipsePropertyFilter*>& propertyFiltersField();
|
caf::PdmChildArrayField<RimCellFilter*>& propertyFiltersField();
|
||||||
|
|
||||||
|
// Returns all children as RimCellFilter*, including compound filters. Used by the
|
||||||
|
// visualization pipeline to call applyToCellVisibility() uniformly.
|
||||||
|
std::vector<RimCellFilter*> filtersForEvaluation() const;
|
||||||
|
|
||||||
bool hasActiveFilters() const override;
|
bool hasActiveFilters() const override;
|
||||||
bool hasActiveDynamicFilters() const override;
|
bool hasActiveDynamicFilters() const override;
|
||||||
@@ -56,11 +62,12 @@ public:
|
|||||||
|
|
||||||
void updateDefaultResult( const RimEclipseCellColors* result );
|
void updateDefaultResult( const RimEclipseCellColors* result );
|
||||||
RimEclipsePropertyFilter* addFilterLinkedToCellResult();
|
RimEclipsePropertyFilter* addFilterLinkedToCellResult();
|
||||||
|
RimCombinedFilter* addNewCombinedFilter();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void initAfterRead() override;
|
void initAfterRead() override;
|
||||||
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
|
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
caf::PdmChildArrayField<RimEclipsePropertyFilter*> m_propertyFilters;
|
caf::PdmChildArrayField<RimCellFilter*> m_propertyFilters;
|
||||||
};
|
};
|
||||||
Reference in new issue
Block a user