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
References:
If anyone is facing a problem with the construction of a transformation matrix from a oriented bounding box or axis aligned bounding box in open3D, the transformation matrix can be constructed using the rotation matrix obtained from the bounding box using obb.R
and the first point in the array obb.get_box_points()
unlike the obb.get_min_bound()
point mentioned in the question.
The correct code to construct a transformation matrix which can then be used in Open3d is:
obb = point_cloud.get_oriented_bounding_box()
rotation_matrix = obb.R
X, Y, Z = np.asarray(obb.get_box_points())[0]
transformation_matrix = np.hstack((rotation_matrix, np.array([[X], [Y], [Z]])))