Split railing representation into pure-compute + IFC wrapper

add_railing_representation now factors into two parts:

* compute_wall_mounted_handrail_geometry returns a pure-geometry
  WallMountedHandrailGeometry dataclass (handrail polyline + support
  list + terminal caps), no IFC mutation.
* add_railing_representation wraps that dataclass into an
  IfcShapeRepresentation as before.

Downstream consumers that want the same math without round-tripping
through an IFC file (Blender gizmo previews, viewport drafts) now
drive compute_X directly. Future add_X_representation work in the
geometry API is encouraged to follow the same shape — a sibling
compute_X function + thin IFC wrapper.

The railing_type parameter is dropped from the signature — only
WALL_MOUNTED_HANDRAIL was ever supported, so the kwarg was dead.
The Bonsai railing-modifier caller is updated in the same commit
to stop passing it; without that update Bonsai's
finish_editing_railing_path raises TypeError on the first edit.

RailingSupport and WallMountedHandrailGeometry use @dataclass(slots=True)
— they're constructed N-per-cap during arc sampling, so the per-instance
overhead matters.

Public symbols (RailingSupport, TERMINAL_TYPE,
WallMountedHandrailGeometry, compute_wall_mounted_handrail_geometry,
add_railing_representation) re-exported from ifcopenshell.api.geometry.
New test/api/geometry/test_add_railing_representation.py covers the
compute/wrap contract.

Generated with the assistance of an AI coding tool.
This commit is contained in:
Gorgious56
2026-05-26 23:09:14 +02:00
parent 3d81660dad
commit 4d4c5b4d51
4 changed files with 908 additions and 320 deletions
@@ -33,7 +33,20 @@ from .add_door_representation import add_door_representation
from .add_footprint_representation import add_footprint_representation
from .add_mesh_representation import add_mesh_representation
from .add_profile_representation import add_profile_representation
from .add_railing_representation import add_railing_representation
# add_railing_representation is the pilot for a "pure-compute + IFC-wrap" split:
# compute_wall_mounted_handrail_geometry returns a dataclass with the raw geometry,
# add_railing_representation wraps it into an IfcShapeRepresentation. The split lets
# downstream consumers (Blender gizmo previews, etc.) drive the same math without
# round-tripping through an IFC file. Future add_X_representation work is encouraged
# to follow the same shape — sibling compute_X_geometry function + thin IFC wrapper.
from .add_railing_representation import (
RailingSupport,
TERMINAL_TYPE,
WallMountedHandrailGeometry,
add_railing_representation,
compute_wall_mounted_handrail_geometry,
)
try:
from .add_representation import add_representation
@@ -72,8 +85,12 @@ __all__ = [
"add_door_representation",
"add_footprint_representation",
"add_mesh_representation",
"RailingSupport",
"TERMINAL_TYPE",
"WallMountedHandrailGeometry",
"add_profile_representation",
"add_railing_representation",
"compute_wall_mounted_handrail_geometry",
"add_representation",
"add_shape_aspect",
"add_slab_representation",