- Introduced `frames.py` to manage field complex calculations and their arrangement within node groups. - Added functionality to create and remove field frames based on node arrangements. - Developed `passages.py` to find unobstructed paths for connections around calculation frames. - Implemented `references.py` to route shared results on peripheral tracks, ensuring efficient distribution of outputs. - Created `sections.py` to reserve space for field calculations adjacent to geometry consumers. - Added `sources.py` to position shared calculation sources effectively beside their distribution channels. - Enhanced outline smoothing with `outline_smoothing.py` to adapt camera depth along original outlines.
44 lines
2.4 KiB
Python
44 lines
2.4 KiB
Python
"""Clean cutout boundary triangles and taper the split thickness profile."""
|
|
|
|
from .depth_surface import _math
|
|
from .nodes import evaluate_field, group_input, read_float_attribute, sample_field, store_float_attribute
|
|
from .smoothing import edge_boundary_field
|
|
from .boundary_smoothing import boundary_influence
|
|
|
|
|
|
def remove_boundary_triangles(group, geometry):
|
|
"""Remove all-boundary triangles once on the current topology."""
|
|
nodes, links = group.nodes, group.links
|
|
rim = evaluate_field(group, edge_boundary_field(nodes, links), "FLOAT", "POINT")
|
|
all_boundary = _math(group, "GREATER_THAN", evaluate_field(group, rim, "FLOAT", "FACE"), 0.99999)
|
|
count = nodes.new("GeometryNodeInputMeshFaceNeighbors").outputs["Vertex Count"]
|
|
selected = _math(group, "MULTIPLY", all_boundary, _math(group, "COMPARE", count, 3))
|
|
delete = nodes.new("GeometryNodeDeleteGeometry")
|
|
delete.domain, delete.mode = "FACE", "ALL"
|
|
links.new(geometry, delete.inputs["Geometry"])
|
|
links.new(selected, delete.inputs["Selection"])
|
|
return delete.outputs["Geometry"]
|
|
|
|
|
|
def taper_split_profile(group, original, geometry):
|
|
"""Taper balloon thickness through the shared two-ring influence builder."""
|
|
nodes, links = group.nodes, group.links
|
|
uv = nodes.new("GeometryNodeInputNamedAttribute")
|
|
uv.data_type = "FLOAT_VECTOR"
|
|
uv.inputs["Name"].default_value = "UVMap"
|
|
original_uv = nodes.new("GeometryNodeSetPosition")
|
|
links.new(original, original_uv.inputs["Geometry"])
|
|
links.new(uv.outputs["Attribute"], original_uv.inputs["Position"])
|
|
nearest = nodes.new("GeometryNodeSampleNearest")
|
|
nearest.domain = "POINT"
|
|
links.new(original_uv.outputs["Geometry"], nearest.inputs["Geometry"])
|
|
links.new(uv.outputs["Attribute"], nearest.inputs["Sample Position"])
|
|
rim = evaluate_field(group, edge_boundary_field(nodes, links), "FLOAT", "POINT")
|
|
protected = sample_field(group, original, rim, "FLOAT", index=nearest.outputs["Index"])
|
|
influence = boundary_influence(group, protected)
|
|
controls = group_input(nodes, {"Split Threshold"})
|
|
band = _math(group, "MULTIPLY", influence, _math(group, "GREATER_THAN", controls.outputs["Split Threshold"], 0))
|
|
retained = _math(group, "SQRT", _math(group, "MAXIMUM", _math(group, "SUBTRACT", 1, band), 0))
|
|
profile = _math(group, "MULTIPLY", read_float_attribute(group, "o_balloon"), retained)
|
|
return store_float_attribute(group, geometry, "o_balloon", profile)
|