Selector: add rotation_x/y/z value keys #6262

Expose the Euler rotation of an element's placement in degrees through
get_element_value, alongside the existing x/y/z and easting/northing/
elevation keys. This makes element rotation exportable through ifccsv,
e.g. for placing oriented symbols in GIS.

Adopts the approach agreed in the review of the stale PR #6272 by
@TZwielehner: reuse util.shape_builder.np_matrix_to_euler and do the
degree conversion inside get_element_value.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit d4805387ef)
This commit is contained in:
Petru Conduraru
2026-07-05 20:25:05 +03:00
committed by Dion Moult
parent 21b5fa6b15
commit 6d0809c703
3 changed files with 29 additions and 2 deletions
@@ -36,6 +36,7 @@ import ifcopenshell.util.placement
import ifcopenshell.util.pset
import ifcopenshell.util.schema
import ifcopenshell.util.shape
import ifcopenshell.util.shape_builder
import ifcopenshell.util.system
import ifcopenshell.util.unit
@@ -497,6 +498,13 @@ def _get_element_value(element: ifcopenshell.entity_instance, keys: list[str]) -
value = enh[("easting", "northing", "elevation").index(key)]
else:
value = None
elif key in ("rotation_x", "rotation_y", "rotation_z") and hasattr(value, "ObjectPlacement"):
if getattr(value, "ObjectPlacement", None):
matrix = ifcopenshell.util.placement.get_local_placement(value.ObjectPlacement)
euler = ifcopenshell.util.shape_builder.np_matrix_to_euler(matrix)
value = float(np.degrees(euler[("rotation_x", "rotation_y", "rotation_z").index(key)]))
else:
value = None
elif isinstance(value, ifcopenshell.entity_instance):
if key == "Name" and value.is_a("IfcMaterialLayerSet"):
key = "LayerSetName" # This oddity in the IFC spec is annoying so we account for it.
@@ -705,9 +713,9 @@ def set_element_value(
return
elif key == "classification":
element = ifcopenshell.util.classification.get_references(element)
elif key in ("x", "y", "z", "easting", "northing", "elevation") and hasattr(element, "ObjectPlacement"):
elif key in ("x", "y", "z", "easting", "northing", "elevation", "rotation_x", "rotation_y", "rotation_z") and hasattr(element, "ObjectPlacement"):
# TODO: add support
if key in ("easting", "northing", "elevation"):
if key in ("easting", "northing", "elevation", "rotation_x", "rotation_y", "rotation_z"):
return
placement = element.ObjectPlacement