The align tool now works on any generic product, not just walls.

This commit is contained in:
Dion Moult
2021-07-17 21:36:03 +10:00
parent 1bf136e93c
commit 02dc7b5274
3 changed files with 87 additions and 28 deletions
@@ -3,7 +3,8 @@ from . import handler, prop, ui, grid, product, wall, slab, stair, door, window,
classes = (
product.AddTypeInstance,
workspace.HotkeyE,
product.AlignProduct,
workspace.Hotkey,
wall.JoinWall,
wall.AlignWall,
wall.FlipWall,
@@ -1,4 +1,5 @@
import bpy
import mathutils
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.util.element
@@ -6,7 +7,7 @@ import ifcopenshell.util.representation
from . import wall, slab, column
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.pset.data import Data as PsetData
from mathutils import Vector
from mathutils import Vector, Matrix
class AddTypeInstance(bpy.types.Operator):
@@ -73,6 +74,52 @@ class AddTypeInstance(bpy.types.Operator):
return {"FINISHED"}
class AlignProduct(bpy.types.Operator):
bl_idname = "bim.align_product"
bl_label = "Align Wall"
bl_options = {"REGISTER", "UNDO"}
align_type: bpy.props.StringProperty()
def execute(self, context):
selected_objs = context.selected_objects
if len(selected_objs) < 2 or not context.active_object:
return {"FINISHED"}
if self.align_type == "CENTERLINE":
point = context.active_object.matrix_world @ (
Vector(context.active_object.bound_box[0]) + (context.active_object.dimensions / 2)
)
elif self.align_type == "POSITIVE":
point = context.active_object.matrix_world @ Vector(context.active_object.bound_box[6])
elif self.align_type == "NEGATIVE":
point = context.active_object.matrix_world @ Vector(context.active_object.bound_box[0])
active_x_axis = context.active_object.matrix_world.to_quaternion() @ Vector((1, 0, 0))
active_y_axis = context.active_object.matrix_world.to_quaternion() @ Vector((0, 1, 0))
active_z_axis = context.active_object.matrix_world.to_quaternion() @ Vector((0, 0, 1))
x_distances = self.get_axis_distances(point, active_x_axis)
y_distances = self.get_axis_distances(point, active_y_axis)
if abs(sum(x_distances)) < abs(sum(y_distances)):
for i, obj in enumerate(selected_objs):
obj.matrix_world = Matrix.Translation(active_x_axis * -x_distances[i]) @ obj.matrix_world
else:
for i, obj in enumerate(selected_objs):
obj.matrix_world = Matrix.Translation(active_y_axis * -y_distances[i]) @ obj.matrix_world
return {"FINISHED"}
def get_axis_distances(self, point, axis):
results = []
for obj in bpy.context.selected_objects:
if self.align_type == "CENTERLINE":
obj_point = obj.matrix_world @ (Vector(obj.bound_box[0]) + (obj.dimensions / 2))
elif self.align_type == "POSITIVE":
obj_point = obj.matrix_world @ Vector(obj.bound_box[6])
elif self.align_type == "NEGATIVE":
obj_point = obj.matrix_world @ Vector(obj.bound_box[0])
results.append(mathutils.geometry.distance_point_to_plane(obj_point, point, axis))
return results
def generate_box(usecase_path, ifc_file, settings):
box_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Box", "MODEL_VIEW")
if not box_context:
@@ -18,26 +18,14 @@ class BimTool(WorkSpaceTool):
# ("bim.wall_tool_op", {"type": 'MOUSEMOVE', "value": 'ANY'}, {"properties": []}),
# ("mesh.add_wall", {"type": 'LEFTMOUSE', "value": 'PRESS'}, {"properties": []}),
("bim.add_type_instance", {"type": "A", "value": "PRESS", "shift": True}, {"properties": []}),
("bim.hotkey_e", {"type": "E", "value": "PRESS", "shift": True}, {"properties": []}),
("bim.hotkey", {"type": "E", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "E")]}),
("bim.join_wall", {"type": "T", "value": "PRESS", "shift": True}, {"properties": [("join_type", "L")]}),
("bim.join_wall", {"type": "Y", "value": "PRESS", "shift": True}, {"properties": [("join_type", "V")]}),
("bim.flip_wall", {"type": "F", "value": "PRESS", "shift": True}, {"properties": []}),
("bim.split_wall", {"type": "S", "value": "PRESS", "shift": True}, {"properties": []}),
(
"bim.align_wall",
{"type": "X", "value": "PRESS", "shift": True},
{"properties": [("align_type", "EXTERIOR")]},
),
(
"bim.align_wall",
{"type": "C", "value": "PRESS", "shift": True},
{"properties": [("align_type", "CENTERLINE")]},
),
(
"bim.align_wall",
{"type": "V", "value": "PRESS", "shift": True},
{"properties": [("align_type", "INTERIOR")]},
),
("bim.hotkey", {"type": "X", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "X")]}),
("bim.hotkey", {"type": "C", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "C")]}),
("bim.hotkey", {"type": "V", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "V")]}),
)
def draw_settings(context, layout, tool):
@@ -57,22 +45,45 @@ class BimTool(WorkSpaceTool):
row.label(text="Mitre", icon="EVENT_Y")
row.label(text="Flip", icon="EVENT_F")
row.label(text="Split", icon="EVENT_S")
row.label(text="", icon="EVENT_X")
row.label(text="", icon="EVENT_C")
row.label(text="", icon="EVENT_V")
row.label(text="Align")
row.label(text="", icon="EVENT_X")
row.label(text="", icon="EVENT_C")
row.label(text="", icon="EVENT_V")
row.label(text="Align")
class HotkeyE(bpy.types.Operator):
bl_idname = "bim.hotkey_e"
bl_label = "Hotkey E"
class Hotkey(bpy.types.Operator):
bl_idname = "bim.hotkey"
bl_label = "Hotkey"
bl_options = {"REGISTER", "UNDO"}
hotkey: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
props = context.scene.BIMTypeProperties
if props.ifc_class == "IfcWallType":
bpy.ops.bim.join_wall(join_type="T")
self.props = context.scene.BIMTypeProperties
getattr(self, f"hotkey_{self.hotkey}")()
return {"FINISHED"}
def hotkey_C(self):
if self.props.ifc_class == "IfcWallType":
bpy.ops.bim.align_wall(align_type="CENTERLINE")
else:
bpy.ops.bim.align_product(align_type="CENTERLINE")
def hotkey_E(self):
if self.props.ifc_class == "IfcWallType":
bpy.ops.bim.join_wall(join_type="T")
def hotkey_V(self):
if self.props.ifc_class == "IfcWallType":
bpy.ops.bim.align_wall(align_type="INTERIOR")
else:
bpy.ops.bim.align_product(align_type="POSITIVE")
def hotkey_X(self):
if self.props.ifc_class == "IfcWallType":
bpy.ops.bim.align_wall(align_type="EXTERIOR")
else:
bpy.ops.bim.align_product(align_type="NEGATIVE")