Rotation of IfcElements based on its world center point instead of local placement at (0.0.0)
Hello all!
I'm trying to re-create geometry - in this case a wall and trying to rotate it to its initial position.
The problem is, the rotation is always conducted at (0.0.0) and not at the newly assigned location:
# Create our element type. Types do not have an object placement.
element = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class=element_type)
# Create a 4x4 identity matrix. This matrix is at the origin with no rotation.
matrix = np.eye(4)
# Relocate center point
center_point = center_point_x - (length/2), center_point_y - (width/2), center_point_z - (height/2)
# Set the X, Y, Z coordinates. Notice how we rotate first then translate.
# This is because the rotation origin is always at 0, 0, 0.
matrix[:,3][0:3] = center_point
# Set the rotation matrix
matrix[0, :3] =+ length_norm_vec
matrix[1, :3] =+ width_norm_vec
matrix[2, :3] =+ height_norm_vec
# Set our wall's Object Placement using our matrix.
run("geometry.edit_object_placement", ifc_file, product=element, matrix=matrix)
# Add a new wall-like body geometry
representation = run("geometry.add_wall_representation", ifc_file, context=body, length=length, height=height, thickness=width)
# Assign our new body geometry back to our wall
run("geometry.assign_representation", ifc_file, product=element, representation=representation)
I got an error when trying to rotate using ifcopenshell.util.placement.rotation:
# Rotate the matix 90 degrees anti-clockwise around the Z axis (i.e. in plan).
# Anti-clockwise is positive. Clockwise is negative.
matrix = ifcopenshell.util.placement.rotation(90, "Z") @ matrix
AttributeError: module 'ifcopenshell.util.placement' has no attribute 'rotation'
- ifcopenshell version: 0.8.0alpha1 - py311h9a73951_1
I'm working on a project which uses **open3d **in order to create ifcElements/Geometry from a point cloud.
This is very similiar to Innas' StackOverflow question:
She described it pretty clear:
"I'm working on a project where I need to apply rotation matrices obtained from Open3D to objects represented in IFC OpenShell. As per the documentations for the two: in Open3D, the rotation matrix represents rotation relative to the object's center, while in IFC OpenShell, rotation is defined based on two vectors: the local X axis and the local Z axis vector. I'm facing challenges in reconciling these differences and correctly applying the rotations.
Could someone provide guidance or code examples on how to convert rotation matrices from Open3D to the representation expected by IFC OpenShell, and how to apply these rotations to objects in IFC OpenShell?
Right now I am using the below code to extract the rotation matrix for a point cloud and then using the obtained parameters to create a wall like representation in IFC Open Shell. Here we're writing the rotation matrix to a txt file for simplicity.
In Open3D:
Code to extract the rotation matrix from the point cloud and save it in a file.
obb = point_cloud.get_oriented_bounding_box()
rotation_matrix = obb.R
min_x, min_y, min_z = obb.get_min_bound()
transformation_matrix = np.hstack((rotation_matrix, np.array([[min_x], [min_y], [min_z]])))
length = obb.extent[0]
width = obb.extent[1]
height = obb.extent[2]
f.write(f"{length}, {width}, {height}, ")
f.write(", ".join(map(str, transformation_matrix.flatten())))
f.write("\n")
In IFC OpenShell:
wall = run("root.create_entity", model, ifc_class="IfcWall")
run("geometry.edit_object_placement", model, product=wall, matrix=transformation_matrix)
representation = run("geometry.add_wall_representation", model, context=body, length=length, height=height, thickness=0.5)
run("geometry.assign_representation", model, product=wall, representation=representation)
run("spatial.assign_container", model, relating_structure=storey, product=wall)
Where: matrix: 4x4 transformation matrix for object placement length: Length of the wall height: Height of the wall thickness: Thickness of the wall"
Comments
This means you're using an outdated version of IfcOpenShell. Can you try the latest from PyPI (or ideally from source)? See https://docs.ifcopenshell.org/ifcopenshell-python/installation.html
Okay nice, after updating the ifcopenshell version the code: matrix = ifcopenshell.util.placement.rotation(90, "Z") @ matrix is working. Do you suggested to continue with this approach? What is the difference between: matrix = ifcopenshell.util.placement.rotation(90, "Z") @ matrix and setting the rotation matrix?
To visualize the problem, I took a screenshot:

The geometries are not identical..
It's getting closer, but not perfect at all.
Here my code for testing:
this is how it looks