For a simple 2D-case It seems like this rotation matrix is giving me the expected result:
import numpy as np
location_space = (1000,4000)
location_ref = (5000,5000)
refDir_space = (-1000,0)
refDir_ref = (3000, -1000)
def Transform(pt, v_from, v_to):
a = v_to
b = v_from
cos=np.dot(a,b)/np.linalg.norm(a)/np.linalg.norm(b)
sin=np.cross(a,b)/np.linalg.norm(a)/np.linalg.norm(b)
R = np.array(((cos, -sin), (sin, cos)))
return np.matmul(R,pt)
loc_space_trans = Transform(location_space, refDir_space, refDir_ref)
print(location_ref)
print(location_ref[0]+loc_space_trans[0], location_ref[1]+loc_space_trans[1])

But the same function implemented in the complete script widely scatters the model in Solibir:
ifc_path = r"C:\Users\eibre\OneDrive - Norconsult Group\Documents\NB3_ARK.ifc"
import numpy as np
def rotate_point(pt, v_from, v_to):
a = v_to
b = v_from
cos=np.dot(a,b)/np.linalg.norm(a)/np.linalg.norm(b)
sin=np.cross(a,b)/np.linalg.norm(a)/np.linalg.norm(b)
R = np.array(((cos, -sin), (sin, cos)))
return np.matmul(R,pt)
import ifcopenshell
f = ifcopenshell.open(ifc_path)
# Move element one level up in from space in spatial tree:
spaces = f.by_type('IfcSpace')
for space in spaces:
container = space.Decomposes[0].RelatingObject
if len(space.ContainsElements) > 0:
contained_elements = space.ContainsElements[0].RelatedElements
for contained_element in contained_elements:
contained_element.ContainedInStructure[0].RelatingStructure = container
# Edit placements and delete the ones that places spaces
local_placements = f.by_type('IfcLocalPlacement')
for lp in local_placements:
if lp.PlacesObject[0].is_a('IfcSpace'):
lp_space = lp
relative_placement = lp_space.RelativePlacement
referenced_by = lp_space.ReferencedByPlacements
location = (lp_space.RelativePlacement.Location.Coordinates[0],lp_space.RelativePlacement.Location.Coordinates[1])
refDir1 = (lp_space.RelativePlacement.RefDirection[0][0], lp_space.RelativePlacement.RefDirection[0][1])
for lp_ref in referenced_by:
refDir2 = (lp_ref.RelativePlacement.RefDirection[0][0], lp_ref.RelativePlacement.RefDirection[0][1])
new_point = rotate_point(location, refDir1, refDir2)
merged_location = (
float(lp_ref.RelativePlacement.Location.Coordinates[0] - new_point[0]),
float(lp_ref.RelativePlacement.Location.Coordinates[1] - new_point[1]),
float(lp_ref.RelativePlacement.Location.Coordinates[2] + lp_space.RelativePlacement.Location.Coordinates[2])
)
lp_ref.RelativePlacement.Location.Coordinates = merged_location
lp_ref.PlacementRelTo = lp_space.PlacementRelTo
f.remove(lp_space)
# Delete spaces
for space in f.by_type("ifcspace"):
f.remove(space)
# savne new file
f.write(ifc_path[:-4]+"-spaceREM.ifc")
