Add tests and implement boundary smoothing and cutout functionality

- Introduced tests for boundary smoothing in `test_boundary_smoothing.py`, verifying that smoothing reduces stair-step artifacts while preserving boundary integrity.
- Added tests for cutout boundary behavior in `test_cutout_boundary.py`, ensuring proper handling of boundary triangles and normal blending.
- Created `test_temporary_attributes.py` to check the cleanup of temporary attributes across depth modifier branches, ensuring no warnings are raised.
- Implemented point culling functionality in `test_validity.py`, confirming that invalid points are removed without affecting adjacent geometry.
- Developed boundary smoothing logic in `boundary_smoothing.py`, allowing for depth smoothing while maintaining edge integrity.
- Added cutout boundary management in `cutout_boundary.py`, including functions for removing boundary triangles and tapering thickness profiles.
- Implemented validity checks in `validity.py` to ensure proper deletion of invalid vertices and associated wire edges.
This commit is contained in:
2026-09-11 20:37:20 +08:00
parent e8129fe495
commit 31074bd511
85 changed files with 2501 additions and 1451 deletions

View File

@@ -187,7 +187,11 @@ def test_cutout_presets_load_three_direct_modifier_assets():
assert inputs["Mode"].default_value == "Balloon"
assert inputs["Smooth"].default_value == 0
assert inputs["Smooth Weight"].default_value == 1
assert "Edge Smooth" not in inputs
if shape == "DEPTH_SOLID":
assert inputs["Boundary Smooth"].default_value == 5
assert inputs["Boundary Smooth"].parent.name == "Options"
else:
assert "Boundary Smooth" not in inputs
assert not any(node.bl_idname == "GeometryNodeRepeatInput" and node.inputs["Iterations"].default_value == 8 for node in group.nodes)
assert next(item for item in groups["DEPTH_BALLOON"].interface.items_tree if item.name == "Double Sided").default_value
@@ -424,17 +428,17 @@ def test_depth_surface_keeps_continuous_points_across_zero_validity_edge():
assert np.ptp(positions[:, 2]) < 1e-4
def test_depth_surface_split_removes_isolated_triangle_without_loose_geometry():
def test_depth_surface_removes_boundary_ears_without_loose_geometry():
bpy.ops.wm.read_factory_settings(use_empty=True)
obj, modifier = _depth_surface_step_object()
split_id = object_data.modifier_input_identifier(modifier.node_group, "Split Threshold")
# The raised corner becomes an isolated triangle after separation.
for value, expected in ((0., (9, 8)), (.5, (8, 7)), (1., (8, 7))):
# Both outer ears have three boundary vertices, including the raised corner.
for value in (0., .5, 1.):
object_data.set_modifier_input(modifier, split_id, value)
obj.update_tag(refresh={"DATA"})
bpy.context.view_layer.update()
vertices, faces, loose_edges, loose_points = _evaluated_topology(obj)
assert (vertices, faces) == expected
assert (vertices, faces) == (7, 6)
assert not loose_edges and not loose_points