mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 06:58:56 +00:00
Make Door / Window Tool place doors on the correct side of a wall (#6986)
This commit is contained in:
@@ -40,7 +40,7 @@ import bonsai.core.geometry
|
|||||||
import bonsai.bim.import_ifc as import_ifc
|
import bonsai.bim.import_ifc as import_ifc
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from math import pi, radians
|
from math import pi, radians
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector, Matrix, Euler
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy.types import SpaceView3D
|
from bpy.types import SpaceView3D
|
||||||
from bpy.props import FloatProperty
|
from bpy.props import FloatProperty
|
||||||
@@ -92,11 +92,19 @@ class FilledOpeningGenerator:
|
|||||||
layers = tool.Model.get_material_layer_parameters(element)
|
layers = tool.Model.get_material_layer_parameters(element)
|
||||||
if layers["layer_set_direction"] == "AXIS2":
|
if layers["layer_set_direction"] == "AXIS2":
|
||||||
opening_thickness_si = layers["thickness"] * 2
|
opening_thickness_si = layers["thickness"] * 2
|
||||||
axis = tool.Model.get_wall_axis(voided_obj, layers=layers)["base"]
|
axes = tool.Model.get_wall_axis(voided_obj, layers=layers)
|
||||||
|
axis_base = axes["base"]
|
||||||
|
axis_side = axes["side"]
|
||||||
new_matrix = voided_obj.matrix_world.copy()
|
new_matrix = voided_obj.matrix_world.copy()
|
||||||
point_on_axis = tool.Cad.point_on_edge(target, axis)
|
point_on_base_axis = tool.Cad.point_on_edge(target, axis_base)
|
||||||
new_matrix.translation.x = point_on_axis.x
|
point_on_side_axis = tool.Cad.point_on_edge(target, axis_side)
|
||||||
new_matrix.translation.y = point_on_axis.y
|
if (point_on_base_axis - target).length <= (point_on_side_axis - target).length:
|
||||||
|
new_matrix.translation.x = point_on_base_axis.x
|
||||||
|
new_matrix.translation.y = point_on_base_axis.y
|
||||||
|
else:
|
||||||
|
new_matrix.translation.x = point_on_side_axis.x
|
||||||
|
new_matrix.translation.y = point_on_side_axis.y
|
||||||
|
new_matrix = new_matrix @ Matrix.Rotation(radians(180.0), 4, "Z")
|
||||||
|
|
||||||
if should_set_z_level:
|
if should_set_z_level:
|
||||||
if filling.is_a("IfcDoor"):
|
if filling.is_a("IfcDoor"):
|
||||||
@@ -433,7 +441,44 @@ class FlipFill(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
if not element or not element.FillsVoids:
|
if not element or not element.FillsVoids:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
filled_opening = element.FillsVoids[0].RelatingOpeningElement
|
||||||
|
filled_element = filled_opening.VoidsElements[0].RelatingBuildingElement
|
||||||
|
filled_object = tool.Ifc.get_object(filled_element)
|
||||||
|
|
||||||
|
if filled_element.is_a() in ["IfcWall", "IfcWallStandardCase"]:
|
||||||
|
# if the filled element is a wall, move the filling in such a way
|
||||||
|
# that it will have the same relative position, but to the other
|
||||||
|
# side of the wall
|
||||||
|
#
|
||||||
|
# For example, if a door frame protudes 1cm out of the wall,
|
||||||
|
# it will produde 1cm out of the other side of the wall.
|
||||||
|
|
||||||
|
layers = tool.Model.get_material_layer_parameters(filled_element)
|
||||||
|
axes = tool.Model.get_wall_axis(filled_object, layers=layers)
|
||||||
|
|
||||||
|
center_axis = [(axes["base"][0] + axes["side"][0]) * 0.5, (axes["base"][1] + axes["side"][1]) * 0.5]
|
||||||
|
|
||||||
|
original_pos = obj.matrix_world.translation
|
||||||
|
bb = tool.Blender.get_object_bounding_box(obj)
|
||||||
|
min_y = min(bb["min_y"], 0)
|
||||||
|
max_y = max(bb["max_y"], 0)
|
||||||
|
|
||||||
|
point_on_center_axis = tool.Cad.point_on_edge(original_pos, center_axis)
|
||||||
|
offset_to_center_axis = point_on_center_axis - original_pos
|
||||||
|
offset_to_center_axis.z = 0
|
||||||
|
depth_offset = max_y + min_y
|
||||||
|
depth_correction_vec = offset_to_center_axis.normalized() * depth_offset
|
||||||
|
|
||||||
|
mirrored_point = original_pos + offset_to_center_axis * 2.0 - depth_correction_vec
|
||||||
|
|
||||||
|
obj.matrix_world.translation = mirrored_point
|
||||||
|
bonsai.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj)
|
||||||
|
|
||||||
tool.Geometry.flip_object(obj, "XY")
|
tool.Geometry.flip_object(obj, "XY")
|
||||||
|
ifcopenshell.api.geometry.edit_object_placement(tool.Ifc.get(), filled_opening, obj.matrix_world)
|
||||||
|
tool.Geometry.reload_representation(filled_object)
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -541,8 +541,21 @@ def get_generic_product_preview_data(context, relating_type):
|
|||||||
snap_obj = bpy.data.objects.get(snap_prop.snap_object)
|
snap_obj = bpy.data.objects.get(snap_prop.snap_object)
|
||||||
snap_element = tool.Ifc.get_entity(snap_obj)
|
snap_element = tool.Ifc.get_entity(snap_obj)
|
||||||
rot_mat = Quaternion()
|
rot_mat = Quaternion()
|
||||||
if snap_element and snap_element.is_a("IfcWall"):
|
if relating_type.is_a() in ["IfcDoorType", "IfcWindowType"] and snap_element and snap_element.is_a("IfcWall"):
|
||||||
rot_mat = snap_obj.matrix_world.to_quaternion()
|
layers = tool.Model.get_material_layer_parameters(snap_element)
|
||||||
|
axes = tool.Model.get_wall_axis(snap_obj, layers=layers)
|
||||||
|
axis_base = axes["base"]
|
||||||
|
axis_side = axes["side"]
|
||||||
|
point_on_base_axis = tool.Cad.point_on_edge(mouse_point, axis_base)
|
||||||
|
point_on_side_axis = tool.Cad.point_on_edge(mouse_point, axis_side)
|
||||||
|
if (point_on_base_axis - mouse_point).length_squared <= (point_on_side_axis - mouse_point).length_squared:
|
||||||
|
# mouse is snapped to the base axis, the preview looks exactly like the placed door / window
|
||||||
|
rot_mat = snap_obj.matrix_world.to_quaternion()
|
||||||
|
else:
|
||||||
|
# mouse is snapped to the side axis, the preview is inverted, rotate it now and correct x position later
|
||||||
|
rot_mat = snap_obj.matrix_world.to_quaternion() @ Quaternion(Vector((0, 0, 1)), radians(180))
|
||||||
|
|
||||||
|
mouse_point.z = snap_obj.matrix_world.translation.z
|
||||||
|
|
||||||
obj_type = tool.Ifc.get_object(relating_type)
|
obj_type = tool.Ifc.get_object(relating_type)
|
||||||
if obj_type.data:
|
if obj_type.data:
|
||||||
|
|||||||
Reference in New Issue
Block a user