Add LinePosition: absolute dimension line placement gated on ForcePerpendicularToFace

- BBIM_Dimension.LinePosition (IfcLengthMeasure): holds the dimension line at
  a fixed global coordinate along cross(world_Z, dim_direction), independent of
  geometry movement
- regenerate_dimension applies LinePosition only when ForcePerpendicularToFace is
  also set (the two are semantically coupled); anchor["pt"] always stores the true
  surface hit so the measured length is unaffected
- BIMAnnotationProperties.line_position uses get/set callbacks instead of an update
  callback to avoid the 'Writing to ID classes in this context is not allowed' error
  that fires when Blender draws the tool header
- DimensionLinePositionWidget (BIM_GGT_dimension_line_position): gizmo group with
  two opposing GizmoCone handles at the curve midpoint; poll requires
  ForcePerpendicularToFace so the handles only appear when the feature is active
- UI: line_position field and gizmo are hidden when ForcePerpendicularToFace is off
- Psets_BBIM_Annotation.ifc: #40 LinePosition template added to BBIM_Dimension

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ryan Schultz
2026-05-16 19:16:02 -05:00
parent 8a186b3d01
commit d2d47efdd4
@@ -256,6 +256,11 @@ class AnnotationToolUI:
ptype = ifcopenshell.util.element.get_predefined_type(element) ptype = ifcopenshell.util.element.get_predefined_type(element)
if ptype in cls._DIMENSION_TYPES: if ptype in cls._DIMENSION_TYPES:
cls.layout.separator() cls.layout.separator()
ann_props = tool.Drawing.get_annotation_props()
if ann_props.force_perpendicular_to_face:
row = cls.layout.row(align=True)
row.prop(ann_props, "line_position")
cls.layout.separator()
row = cls.layout.row(align=True) row = cls.layout.row(align=True)
row.operator("bim.set_dimension_anchor", icon="PIVOT_CURSOR") row.operator("bim.set_dimension_anchor", icon="PIVOT_CURSOR")
op = row.operator("bim.regenerate_dimensions", icon="FILE_REFRESH", text="Regenerate") op = row.operator("bim.regenerate_dimensions", icon="FILE_REFRESH", text="Regenerate")