#14367 Python: Add per-view polygon visibility API

This commit is contained in:
Kristian Bendiksen
2026-08-19 10:14:59 +02:00
committed by Magne Sjaastad
parent 5b62a84a12
commit 56fb7a660b
7 changed files with 207 additions and 0 deletions
@@ -92,6 +92,39 @@ std::vector<RimPolygonInView*> RimPolygonInViewCollection::allPolygonsInView() c
return polys;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimPolygonInViewCollection::setPolygonVisible( RimPolygon* polygon, bool visible )
{
updateFromPolygonCollection();
auto* polygonInView = findPolygonInView( polygon );
if ( !polygonInView ) return false;
polygonInView->setCheckState( visible );
polygonInView->updateConnectedEditors();
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPolygonInView* RimPolygonInViewCollection::findPolygonInView( const RimPolygon* polygon ) const
{
for ( auto polygonInView : m_itemsInView )
{
if ( polygonInView && polygonInView->polygon() == polygon ) return polygonInView;
}
for ( auto collection : m_collectionsInView )
{
if ( auto* polygonInView = collection->findPolygonInView( polygon ) ) return polygonInView;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -40,12 +40,16 @@ public:
std::vector<RimPolygonInView*> visiblePolygonsInView() const;
std::vector<RimPolygonInView*> allPolygonsInView() const;
bool setPolygonVisible( RimPolygon* polygon, bool visible );
protected:
std::vector<RimPolygonContainer*> sourceSubCollections() const override;
std::vector<RimPolygon*> sourceItems() const override;
RimPolygonInView* createItemInView( RimPolygon* source ) override;
private:
RimPolygonInView* findPolygonInView( const RimPolygon* polygon ) const;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
};
@@ -21,6 +21,9 @@
#include "RiaApplication.h"
#include "RiaKeyValueStoreUtil.h"
#include "Polygons/RimPolygon.h"
#include "Polygons/RimPolygonInViewCollection.h"
#include "Rim3dView.h"
#include "RimEclipseView.h"
#include "RimGridView.h"
@@ -29,6 +32,7 @@
#include "cvfArray.h"
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseView, RimcGridView_visibleCellsInternal, "visible_cells_internal" );
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( Rim3dView, RimcGridView_setPolygonVisible, "set_polygon_visible" );
//--------------------------------------------------------------------------------------------------
///
@@ -80,3 +84,40 @@ std::expected<caf::PdmObjectHandle*, QString> RimcGridView_visibleCellsInternal:
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcGridView_setPolygonVisible::RimcGridView_setPolygonVisible( caf::PdmObjectHandle* self )
: caf::PdmVoidObjectMethod( self )
{
CAF_PDM_InitObject( "Set Polygon Visible", "", "", "Set polygon visibility in this view" );
CAF_PDM_InitScriptableFieldNoDefault( &m_polygon, "Polygon", "Polygon" );
CAF_PDM_InitScriptableField( &m_visible, "Visible", true, "Visible" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimcGridView_setPolygonVisible::execute()
{
auto* gridView = self<RimGridView>();
if ( !gridView )
{
return std::unexpected( QString( "Polygon visibility is only supported for grid views." ) );
}
if ( !m_polygon() )
{
return std::unexpected( QString( "Polygon is null." ) );
}
if ( !gridView->polygonInViewCollection()->setPolygonVisible( m_polygon(), m_visible() ) )
{
return std::unexpected( QString( "Polygon '%1' is not available in this view." ).arg( m_polygon()->name() ) );
}
gridView->scheduleCreateDisplayModelAndRedraw();
return nullptr;
}
@@ -21,9 +21,12 @@
#include "cafPdmField.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmObjectMethod.h"
#include "cafPdmPtrField.h"
#include <QString>
class RimPolygon;
//==================================================================================================
///
//==================================================================================================
@@ -40,3 +43,20 @@ private:
caf::PdmField<QString> m_visibilityKey;
caf::PdmField<int> m_timeStep;
};
//==================================================================================================
///
//==================================================================================================
class RimcGridView_setPolygonVisible : public caf::PdmVoidObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimcGridView_setPolygonVisible( caf::PdmObjectHandle* self );
std::expected<caf::PdmObjectHandle*, QString> execute() override;
private:
caf::PdmPtrField<RimPolygon*> m_polygon;
caf::PdmField<bool> m_visible;
};
@@ -142,6 +142,7 @@ set(SOURCE_UNITTEST_FILES
${CMAKE_CURRENT_LIST_DIR}/RigVfpTables-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaResultName-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RigPolygonTools-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RimPolygonInViewCollection-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaNameUniquenessTools-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifVtkSurfaceImporter-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifVtkReader-Test.cpp
@@ -0,0 +1,81 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "gtest/gtest.h"
#include "Polygons/RimPolygon.h"
#include "Polygons/RimPolygonCollection.h"
#include "Polygons/RimPolygonInViewCollection.h"
#include <memory>
namespace
{
bool isPolygonVisible( const RimPolygonInViewCollection& collection, const RimPolygon* polygon )
{
for ( auto* polygonInView : collection.visiblePolygonsInView() )
{
if ( polygonInView->polygon() == polygon ) return polygonInView->showLines();
}
return false;
}
} // namespace
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RimPolygonInViewCollection, PolygonVisibilityIsIndependentPerView )
{
auto sourceCollection = std::make_unique<RimPolygonCollection>();
auto* rootPolygon = new RimPolygon();
rootPolygon->setName( "Root polygon" );
sourceCollection->addUserDefinedPolygon( rootPolygon );
auto* subCollection = new RimPolygonCollection();
subCollection->setCollectionName( "Folder" );
sourceCollection->addSubCollection( subCollection );
auto* nestedPolygon = new RimPolygon();
nestedPolygon->setName( "Nested polygon" );
subCollection->addUserDefinedPolygon( nestedPolygon );
RimPolygonInViewCollection firstViewCollection;
firstViewCollection.setSourceCollection( sourceCollection.get() );
firstViewCollection.updateFromPolygonCollection();
RimPolygonInViewCollection secondViewCollection;
secondViewCollection.setSourceCollection( sourceCollection.get() );
secondViewCollection.updateFromPolygonCollection();
EXPECT_TRUE( isPolygonVisible( firstViewCollection, rootPolygon ) );
EXPECT_TRUE( isPolygonVisible( firstViewCollection, nestedPolygon ) );
EXPECT_TRUE( isPolygonVisible( secondViewCollection, nestedPolygon ) );
EXPECT_TRUE( firstViewCollection.setPolygonVisible( nestedPolygon, false ) );
EXPECT_TRUE( isPolygonVisible( firstViewCollection, rootPolygon ) );
EXPECT_FALSE( isPolygonVisible( firstViewCollection, nestedPolygon ) );
EXPECT_TRUE( isPolygonVisible( secondViewCollection, nestedPolygon ) );
EXPECT_TRUE( firstViewCollection.setPolygonVisible( nestedPolygon, true ) );
EXPECT_TRUE( isPolygonVisible( firstViewCollection, nestedPolygon ) );
auto unrelatedPolygon = std::make_unique<RimPolygon>();
EXPECT_FALSE( firstViewCollection.setPolygonVisible( unrelatedPolygon.get(), false ) );
EXPECT_TRUE( isPolygonVisible( firstViewCollection, nestedPolygon ) );
}
@@ -36,6 +36,33 @@ def test_create_polygon(rips_instance, initialize_test):
assert math.isclose(e, a, rel_tol=1e-9, abs_tol=0.0)
def test_set_polygon_visible_in_view(rips_instance, initialize_test):
project = rips_instance.project.open(
dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp"
)
polygon_collection = project.descendants(rips.PolygonCollection)[0]
polygon = polygon_collection.create_polygon(
name="View polygon",
coordinates=[
[0.0, 0.0, -1000.0],
[100.0, 0.0, -1000.0],
[100.0, 100.0, -1000.0],
],
)
case = project.cases()[0]
first_view = case.views()[0]
second_view = case.create_view()
assert first_view.set_polygon_visible(polygon=polygon, visible=False) is None
assert second_view.set_polygon_visible(polygon=polygon, visible=True) is None
assert first_view.set_polygon_visible(polygon=polygon, visible=True) is None
with pytest.raises(rips.RipsError, match="Polygon is null"):
first_view.set_polygon_visible(polygon=None, visible=True)
def test_add_folders_and_polygons(rips_instance, initialize_test):
rips_instance.project.open(
dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp"