mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 01:11:40 +00:00
The align tool now works on any generic product, not just walls.
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user