#13682 Python: Expose polygon appearance properties to Python API

Make RimPolygonAppearance scriptable so polygon visual properties
(colors, line thickness, spheres, closed state, plane lock) can be
controlled from the Python API.
This commit is contained in:
Kristian Bendiksen committed 2026-03-12 08:30:52 +01:00
1 parent 576c2179da
commit 614acc664a
4 files changed
+147 -11

No files matched your search

@@ -54,7 +54,7 @@ RimPolygon::RimPolygon()
CAF_PDM_InitField( &m_editPolygonButton, "EditPolygonButton", false, "Edit" );
caf::PdmUiPushButtonEditor::configureEditorLabelHidden( &m_editPolygonButton );
CAF_PDM_InitFieldNoDefault( &m_appearance, "Appearance", "Appearance" );
CAF_PDM_InitScriptableFieldNoDefault( &m_appearance, "Appearance", "Appearance" );
m_appearance = new RimPolygonAppearance;
m_appearance.uiCapability()->setUiTreeChildrenHidden( true );
@@ -26,6 +26,8 @@
#include "RiaNumericalTools.h"
#include "RiaStdStringTools.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cafPdmUiLineEditor.h"
@@ -77,20 +79,20 @@ RimPolygonAppearance::RimPolygonAppearance()
: objectChanged( this )
{
CAF_PDM_InitObject( "Polygon", ":/PolylinesFromFile16x16.png" );
CAF_PDM_InitScriptableObject( "Polygon", ":/PolylinesFromFile16x16.png" );
CAF_PDM_InitField( &m_isClosed, "IsClosed", true, "Closed Polygon" );
CAF_PDM_InitField( &m_showLines, "ShowLines", true, "Show Lines" );
CAF_PDM_InitField( &m_showSpheres, "ShowSpheres", false, "Show Spheres" );
CAF_PDM_InitScriptableField( &m_isClosed, "IsClosed", true, "Closed Polygon" );
CAF_PDM_InitScriptableField( &m_showLines, "ShowLines", true, "Show Lines" );
CAF_PDM_InitScriptableField( &m_showSpheres, "ShowSpheres", false, "Show Spheres" );
CAF_PDM_InitField( &m_lineThickness, "LineThickness", 3, "Line Thickness" );
CAF_PDM_InitField( &m_sphereRadiusFactor, "SphereRadiusFactor", 0.15, "Sphere Radius Factor" );
CAF_PDM_InitScriptableField( &m_lineThickness, "LineThickness", 3, "Line Thickness" );
CAF_PDM_InitScriptableField( &m_sphereRadiusFactor, "SphereRadiusFactor", 0.15, "Sphere Radius Factor" );
CAF_PDM_InitField( &m_lineColor, "LineColor", cvf::Color3f( cvf::Color3f::ORANGE ), "Line Color" );
CAF_PDM_InitField( &m_sphereColor, "SphereColor", cvf::Color3f( cvf::Color3f::ORANGE ), "Sphere Color" );
CAF_PDM_InitScriptableField( &m_lineColor, "LineColor", cvf::Color3f( cvf::Color3f::ORANGE ), "Line Color" );
CAF_PDM_InitScriptableField( &m_sphereColor, "SphereColor", cvf::Color3f( cvf::Color3f::ORANGE ), "Sphere Color" );
CAF_PDM_InitField( &m_polygonPlaneDepth, "PolygonPlaneDepth", 0.0, "Polygon Plane Depth" );
CAF_PDM_InitField( &m_lockPolygonToPlane, "LockPolygon", false, "Lock Polygon to Plane" );
CAF_PDM_InitScriptableField( &m_polygonPlaneDepth, "PolygonPlaneDepth", 0.0, "Polygon Plane Depth" );
CAF_PDM_InitScriptableField( &m_lockPolygonToPlane, "LockPolygon", false, "Lock Polygon to Plane" );
m_polygonPlaneDepth.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
m_polygonPlaneDepth.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosition::TOP );
@@ -33,3 +33,17 @@ if resinsight is not None:
print("Coordinates for {}:".format(p.name))
for coord in p.coordinates:
print(coord)
# Customize appearance
appearance = p.appearance()
if appearance is not None:
appearance.line_color = "#ff0000"
appearance.line_thickness = 5
appearance.show_spheres = True
appearance.sphere_color = "#0000ff"
appearance.update()
print(
"Appearance updated: line_color={}, line_thickness={}".format(
appearance.line_color, appearance.line_thickness
)
)
@@ -0,0 +1,120 @@
"""
Tests for polygon appearance functionality.
These tests verify that polygon appearance properties can be read and modified
via the Python API.
"""
import os
import sys
import pytest
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import rips
@pytest.fixture
def project(rips_instance):
"""Get the current project."""
return rips_instance.project
class TestPolygonAppearance:
"""Tests for PolygonAppearance functionality."""
@pytest.fixture
def polygon(self, project):
"""Create a test polygon."""
polygon_collection = project.descendants(rips.PolygonCollection)[0]
coordinates = [
[100.0, 200.0, 300.0],
[200.0, 200.0, 300.0],
[200.0, 300.0, 300.0],
[100.0, 300.0, 300.0],
]
p = polygon_collection.create_polygon(
name="Test Polygon", coordinates=coordinates
)
return p
def test_access_appearance(self, polygon):
"""Test that appearance child object is accessible."""
appearance = polygon.appearance()
assert appearance is not None, "Appearance should be accessible"
def test_default_values(self, polygon):
"""Test that default appearance values are correct."""
appearance = polygon.appearance()
assert appearance.is_closed is True
assert appearance.show_lines is True
assert appearance.show_spheres is False
assert appearance.line_thickness == 3
assert appearance.lock_polygon is False
def test_set_line_color(self, polygon):
"""Test setting line color."""
appearance = polygon.appearance()
appearance.line_color = "#ff0000"
appearance.update()
# Re-read to verify persistence
appearance2 = polygon.appearance()
assert appearance2.line_color == "#ff0000"
def test_set_sphere_color(self, polygon):
"""Test setting sphere color."""
appearance = polygon.appearance()
appearance.sphere_color = "#00ff00"
appearance.update()
appearance2 = polygon.appearance()
assert appearance2.sphere_color == "#00ff00"
def test_set_line_thickness(self, polygon):
"""Test setting line thickness."""
appearance = polygon.appearance()
appearance.line_thickness = 5
appearance.update()
appearance2 = polygon.appearance()
assert appearance2.line_thickness == 5
def test_set_show_spheres(self, polygon):
"""Test toggling sphere visibility."""
appearance = polygon.appearance()
appearance.show_spheres = True
appearance.update()
appearance2 = polygon.appearance()
assert appearance2.show_spheres is True
def test_set_sphere_radius_factor(self, polygon):
"""Test setting sphere radius factor."""
appearance = polygon.appearance()
appearance.sphere_radius_factor = 0.5
appearance.update()
appearance2 = polygon.appearance()
assert abs(appearance2.sphere_radius_factor - 0.5) < 1e-6
def test_set_is_closed(self, polygon):
"""Test setting closed polygon state."""
appearance = polygon.appearance()
appearance.is_closed = False
appearance.update()
appearance2 = polygon.appearance()
assert appearance2.is_closed is False
def test_set_lock_polygon(self, polygon):
"""Test setting lock polygon to plane."""
appearance = polygon.appearance()
appearance.lock_polygon = True
appearance.polygon_plane_depth = 500.0
appearance.update()
appearance2 = polygon.appearance()
assert appearance2.lock_polygon is True
assert abs(appearance2.polygon_plane_depth - 500.0) < 1e-6