mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-10-02 04:59:52 +00:00
New profile engine now supports mitred profile joints.
This commit is contained in:
@@ -269,8 +269,11 @@ class ExtendProfile(bpy.types.Operator):
|
|||||||
if len(selected_objs) == 1:
|
if len(selected_objs) == 1:
|
||||||
joiner.join_E(context.active_object, context.scene.cursor.location)
|
joiner.join_E(context.active_object, context.scene.cursor.location)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
if len(selected_objs) == 2 and self.join_type == "L":
|
if len(selected_objs) == 2:
|
||||||
joiner.join_L([o for o in selected_objs if o != context.active_object][0], context.active_object)
|
if self.join_type == "L":
|
||||||
|
joiner.join_L([o for o in selected_objs if o != context.active_object][0], context.active_object)
|
||||||
|
elif self.join_type == "V":
|
||||||
|
joiner.join_V([o for o in selected_objs if o != context.active_object][0], context.active_object)
|
||||||
if len(selected_objs) < 2:
|
if len(selected_objs) < 2:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
if self.join_type == "T":
|
if self.join_type == "T":
|
||||||
@@ -335,10 +338,37 @@ class DumbProfileJoiner:
|
|||||||
relating_element=element2,
|
relating_element=element2,
|
||||||
relating_connection="ATPATH",
|
relating_connection="ATPATH",
|
||||||
related_connection=connection,
|
related_connection=connection,
|
||||||
|
description="BUTT",
|
||||||
)
|
)
|
||||||
|
|
||||||
self.recreate_profile(element1, profile1, axis1, axis1)
|
self.recreate_profile(element1, profile1, axis1, axis1)
|
||||||
|
|
||||||
|
def join_V(self, profile1, profile2):
|
||||||
|
element1 = tool.Ifc.get_entity(profile1)
|
||||||
|
element2 = tool.Ifc.get_entity(profile2)
|
||||||
|
axis1 = self.get_profile_axis(profile1)
|
||||||
|
axis2 = self.get_profile_axis(profile2)
|
||||||
|
intersect = tool.Cad.intersect_edges(axis1, axis2)
|
||||||
|
if intersect:
|
||||||
|
intersect, _ = intersect
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
profile1_end = "ATEND" if tool.Cad.edge_percent(intersect, axis1) > 0.5 else "ATSTART"
|
||||||
|
profile2_end = "ATEND" if tool.Cad.edge_percent(intersect, axis2) > 0.5 else "ATSTART"
|
||||||
|
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"geometry.connect_path",
|
||||||
|
tool.Ifc.get(),
|
||||||
|
relating_element=element1,
|
||||||
|
related_element=element2,
|
||||||
|
relating_connection=profile1_end,
|
||||||
|
related_connection=profile2_end,
|
||||||
|
description="MITRE",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.recreate_profile(element1, profile1, axis1, axis1)
|
||||||
|
self.recreate_profile(element2, profile2, axis2, axis2)
|
||||||
|
|
||||||
def join_L(self, profile1, profile2):
|
def join_L(self, profile1, profile2):
|
||||||
element1 = tool.Ifc.get_entity(profile1)
|
element1 = tool.Ifc.get_entity(profile1)
|
||||||
element2 = tool.Ifc.get_entity(profile2)
|
element2 = tool.Ifc.get_entity(profile2)
|
||||||
@@ -359,6 +389,7 @@ class DumbProfileJoiner:
|
|||||||
related_element=element2,
|
related_element=element2,
|
||||||
relating_connection=profile1_end,
|
relating_connection=profile1_end,
|
||||||
related_connection=profile2_end,
|
related_connection=profile2_end,
|
||||||
|
description="BUTT",
|
||||||
)
|
)
|
||||||
|
|
||||||
self.recreate_profile(element1, profile1, axis1, axis1)
|
self.recreate_profile(element1, profile1, axis1, axis1)
|
||||||
@@ -378,12 +409,16 @@ class DumbProfileJoiner:
|
|||||||
connection = rel.RelatingConnectionType
|
connection = rel.RelatingConnectionType
|
||||||
other = tool.Ifc.get_object(rel.RelatedElement)
|
other = tool.Ifc.get_object(rel.RelatedElement)
|
||||||
if connection not in ["ATPATH", "NOTDEFINED"]:
|
if connection not in ["ATPATH", "NOTDEFINED"]:
|
||||||
self.join(obj, other, connection, is_relating=True)
|
self.join(
|
||||||
|
obj, other, connection, rel.RelatedConnectionType, is_relating=True, description=rel.Description
|
||||||
|
)
|
||||||
for rel in element.ConnectedFrom:
|
for rel in element.ConnectedFrom:
|
||||||
connection = rel.RelatedConnectionType
|
connection = rel.RelatedConnectionType
|
||||||
other = tool.Ifc.get_object(rel.RelatingElement)
|
other = tool.Ifc.get_object(rel.RelatingElement)
|
||||||
if connection not in ["ATPATH", "NOTDEFINED"]:
|
if connection not in ["ATPATH", "NOTDEFINED"]:
|
||||||
self.join(obj, other, connection, is_relating=False)
|
self.join(
|
||||||
|
obj, other, connection, rel.RelatingConnectionType, is_relating=False, description=rel.Description
|
||||||
|
)
|
||||||
|
|
||||||
new_matrix = copy.deepcopy(obj.matrix_world)
|
new_matrix = copy.deepcopy(obj.matrix_world)
|
||||||
new_matrix.col[3] = self.body[0].to_4d()
|
new_matrix.col[3] = self.body[0].to_4d()
|
||||||
@@ -444,7 +479,7 @@ class DumbProfileJoiner:
|
|||||||
should_sync_changes_first=False,
|
should_sync_changes_first=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def join(self, profile1, profile2, connection, is_relating=True):
|
def join(self, profile1, profile2, connection1, connection2, is_relating=True, description="BUTT"):
|
||||||
element1 = tool.Ifc.get_entity(profile1)
|
element1 = tool.Ifc.get_entity(profile1)
|
||||||
element2 = tool.Ifc.get_entity(profile2)
|
element2 = tool.Ifc.get_entity(profile2)
|
||||||
axis1 = self.get_profile_axis(profile1)
|
axis1 = self.get_profile_axis(profile1)
|
||||||
@@ -456,19 +491,19 @@ class DumbProfileJoiner:
|
|||||||
|
|
||||||
intersect, _ = tool.Cad.intersect_edges(axis1, axis2)
|
intersect, _ = tool.Cad.intersect_edges(axis1, axis2)
|
||||||
|
|
||||||
proposed_axis = [self.axis[0], intersect] if connection == "ATEND" else [intersect, self.axis[1]]
|
proposed_axis = [self.axis[0], intersect] if connection1 == "ATEND" else [intersect, self.axis[1]]
|
||||||
|
|
||||||
if tool.Cad.is_x(tool.Cad.angle_edges(self.axis, proposed_axis, degrees=True), 180):
|
if tool.Cad.is_x(tool.Cad.angle_edges(self.axis, proposed_axis, degrees=True), 180):
|
||||||
# The user has moved the wall into an invalid position that cannot connect at the desired end
|
# The user has moved the wall into an invalid position that cannot connect at the desired end
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.axis[1 if connection == "ATEND" else 0] = intersect
|
self.axis[1 if connection1 == "ATEND" else 0] = intersect
|
||||||
|
|
||||||
# Work out body extents
|
# Work out body extents
|
||||||
|
|
||||||
if connection == "ATEND":
|
if connection1 == "ATEND":
|
||||||
axisl = (profile2.matrix_world.inverted() @ axis1[1]) - (profile2.matrix_world.inverted() @ axis1[0])
|
axisl = (profile2.matrix_world.inverted() @ axis1[1]) - (profile2.matrix_world.inverted() @ axis1[0])
|
||||||
elif connection == "ATSTART":
|
elif connection1 == "ATSTART":
|
||||||
axisl = (profile2.matrix_world.inverted() @ axis1[0]) - (profile2.matrix_world.inverted() @ axis1[1])
|
axisl = (profile2.matrix_world.inverted() @ axis1[0]) - (profile2.matrix_world.inverted() @ axis1[1])
|
||||||
xy_angle = math.degrees(Vector((1, 0)).angle_signed(axisl.normalized().to_2d()))
|
xy_angle = math.degrees(Vector((1, 0)).angle_signed(axisl.normalized().to_2d()))
|
||||||
if xy_angle >= -135 and xy_angle <= -45:
|
if xy_angle >= -135 and xy_angle <= -45:
|
||||||
@@ -486,32 +521,158 @@ class DumbProfileJoiner:
|
|||||||
|
|
||||||
is_orthogonal = tool.Cad.is_x(tool.Cad.angle_edges(axis1, axis2, degrees=True), 90, tolerance=0.001)
|
is_orthogonal = tool.Cad.is_x(tool.Cad.angle_edges(axis1, axis2, degrees=True), 90, tolerance=0.001)
|
||||||
|
|
||||||
if connection == "ATEND":
|
if description == "MITRE":
|
||||||
if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal:
|
# Mitre joints are an unofficial convention
|
||||||
plane = self.get_profile_plane(profile2, furthest_plane if is_relating else closest_plane)
|
|
||||||
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.col[3].to_3d(), plane.col[2].to_3d())
|
# Check the closest plane from the perspective of the other element
|
||||||
self.body[1] = intersect
|
if connection2 == "ATEND":
|
||||||
|
axisl = (profile1.matrix_world.inverted() @ axis2[1]) - (profile1.matrix_world.inverted() @ axis2[0])
|
||||||
|
elif connection2 == "ATSTART":
|
||||||
|
axisl = (profile1.matrix_world.inverted() @ axis2[0]) - (profile1.matrix_world.inverted() @ axis2[1])
|
||||||
|
xy_angle2 = math.degrees(Vector((1, 0)).angle_signed(axisl.normalized().to_2d()))
|
||||||
|
if xy_angle2 >= -135 and xy_angle2 <= -45:
|
||||||
|
closest_plane2 = "bottom"
|
||||||
|
furthest_plane2 = "top"
|
||||||
|
elif xy_angle2 >= 45 and xy_angle2 <= 135:
|
||||||
|
closest_plane2 = "top"
|
||||||
|
furthest_plane2 = "bottom"
|
||||||
|
elif xy_angle2 >= -45 and xy_angle2 <= 45:
|
||||||
|
closest_plane2 = "left"
|
||||||
|
furthest_plane2 = "right"
|
||||||
else:
|
else:
|
||||||
plane = self.get_profile_plane(
|
closest_plane2 = "right"
|
||||||
profile2, furthest_plane if is_relating else closest_plane, z_inwards=False if is_relating else True
|
furthest_plane2 = "left"
|
||||||
)
|
|
||||||
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.col[3].to_3d(), plane.col[2].to_3d())
|
if connection1 == "ATEND":
|
||||||
max_dim = self.get_max_bound_box_dimension(profile1)
|
if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal:
|
||||||
self.body[1] = intersect + profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim))
|
plane = self.get_profile_plane(profile2, furthest_plane)
|
||||||
self.clippings.append(plane)
|
intersect = mathutils.geometry.intersect_line_plane(
|
||||||
elif connection == "ATSTART":
|
*axis1, plane.col[3].to_3d(), plane.col[2].to_3d()
|
||||||
if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal:
|
)
|
||||||
plane = self.get_profile_plane(profile2, furthest_plane if is_relating else closest_plane)
|
self.body[1] = intersect
|
||||||
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.col[3].to_3d(), plane.col[2].to_3d())
|
else:
|
||||||
self.body[0] = intersect
|
plane = self.get_profile_plane(profile2, furthest_plane, z_inwards=False)
|
||||||
else:
|
intersect = mathutils.geometry.intersect_line_plane(
|
||||||
plane = self.get_profile_plane(
|
*axis1, plane.col[3].to_3d(), plane.col[2].to_3d()
|
||||||
profile2, furthest_plane if is_relating else closest_plane, z_inwards=False if is_relating else True
|
)
|
||||||
)
|
max_dim = self.get_max_bound_box_dimension(profile1)
|
||||||
intersect = mathutils.geometry.intersect_line_plane(*axis1, plane.col[3].to_3d(), plane.col[2].to_3d())
|
self.body[1] = intersect + profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim))
|
||||||
max_dim = self.get_max_bound_box_dimension(profile1)
|
|
||||||
self.body[0] = intersect - profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim))
|
# Mitre clip
|
||||||
self.clippings.append(plane)
|
if connection1 == connection2:
|
||||||
|
plane1 = self.get_profile_plane(profile1, furthest_plane2)
|
||||||
|
plane2 = self.get_profile_plane(profile2, furthest_plane)
|
||||||
|
clip1, direction1 = mathutils.geometry.intersect_plane_plane(
|
||||||
|
plane1.col[3].to_3d(), plane1.col[2].to_3d(), plane2.col[3].to_3d(), plane2.col[2].to_3d()
|
||||||
|
)
|
||||||
|
|
||||||
|
plane1 = self.get_profile_plane(profile1, closest_plane2)
|
||||||
|
plane2 = self.get_profile_plane(profile2, closest_plane)
|
||||||
|
clip2, direction2 = mathutils.geometry.intersect_plane_plane(
|
||||||
|
plane1.col[3].to_3d(), plane1.col[2].to_3d(), plane2.col[3].to_3d(), plane2.col[2].to_3d()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
plane1 = self.get_profile_plane(profile1, furthest_plane2)
|
||||||
|
plane2 = self.get_profile_plane(profile2, furthest_plane)
|
||||||
|
clip1, direction1 = mathutils.geometry.intersect_plane_plane(
|
||||||
|
plane1.col[3].to_3d(), plane1.col[2].to_3d(), plane2.col[3].to_3d(), plane2.col[2].to_3d()
|
||||||
|
)
|
||||||
|
|
||||||
|
plane1 = self.get_profile_plane(profile1, closest_plane2)
|
||||||
|
plane2 = self.get_profile_plane(profile2, closest_plane)
|
||||||
|
clip2, direction2 = mathutils.geometry.intersect_plane_plane(
|
||||||
|
plane1.col[3].to_3d(), plane1.col[2].to_3d(), plane2.col[3].to_3d(), plane2.col[2].to_3d()
|
||||||
|
)
|
||||||
|
|
||||||
|
y_axis = direction2
|
||||||
|
x_axis = (clip2 - clip1).normalized().to_3d()
|
||||||
|
z_axis = x_axis.cross(y_axis)
|
||||||
|
self.clippings.append(self.create_matrix(clip1, x_axis, y_axis, z_axis))
|
||||||
|
elif connection1 == "ATSTART":
|
||||||
|
if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal:
|
||||||
|
plane = self.get_profile_plane(profile2, furthest_plane)
|
||||||
|
intersect = mathutils.geometry.intersect_line_plane(
|
||||||
|
*axis1, plane.col[3].to_3d(), plane.col[2].to_3d()
|
||||||
|
)
|
||||||
|
self.body[0] = intersect
|
||||||
|
else:
|
||||||
|
plane = self.get_profile_plane(profile2, furthest_plane, z_inwards=False)
|
||||||
|
intersect = mathutils.geometry.intersect_line_plane(
|
||||||
|
*axis1, plane.col[3].to_3d(), plane.col[2].to_3d()
|
||||||
|
)
|
||||||
|
max_dim = self.get_max_bound_box_dimension(profile1)
|
||||||
|
self.body[0] = intersect - profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim))
|
||||||
|
|
||||||
|
if connection1 == connection2:
|
||||||
|
plane1 = self.get_profile_plane(profile1, furthest_plane2)
|
||||||
|
plane2 = self.get_profile_plane(profile2, furthest_plane)
|
||||||
|
clip1, direction1 = mathutils.geometry.intersect_plane_plane(
|
||||||
|
plane1.col[3].to_3d(), plane1.col[2].to_3d(), plane2.col[3].to_3d(), plane2.col[2].to_3d()
|
||||||
|
)
|
||||||
|
|
||||||
|
plane1 = self.get_profile_plane(profile1, closest_plane2)
|
||||||
|
plane2 = self.get_profile_plane(profile2, closest_plane)
|
||||||
|
clip2, direction2 = mathutils.geometry.intersect_plane_plane(
|
||||||
|
plane1.col[3].to_3d(), plane1.col[2].to_3d(), plane2.col[3].to_3d(), plane2.col[2].to_3d()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
plane1 = self.get_profile_plane(profile1, furthest_plane2)
|
||||||
|
plane2 = self.get_profile_plane(profile2, furthest_plane)
|
||||||
|
clip1, direction1 = mathutils.geometry.intersect_plane_plane(
|
||||||
|
plane1.col[3].to_3d(), plane1.col[2].to_3d(), plane2.col[3].to_3d(), plane2.col[2].to_3d()
|
||||||
|
)
|
||||||
|
|
||||||
|
plane1 = self.get_profile_plane(profile1, closest_plane2)
|
||||||
|
plane2 = self.get_profile_plane(profile2, closest_plane)
|
||||||
|
clip2, direction2 = mathutils.geometry.intersect_plane_plane(
|
||||||
|
plane1.col[3].to_3d(), plane1.col[2].to_3d(), plane2.col[3].to_3d(), plane2.col[2].to_3d()
|
||||||
|
)
|
||||||
|
|
||||||
|
y_axis = direction2
|
||||||
|
x_axis = (clip2 - clip1).normalized().to_3d()
|
||||||
|
z_axis = x_axis.cross(y_axis)
|
||||||
|
self.clippings.append(self.create_matrix(clip1, x_axis, y_axis, z_axis))
|
||||||
|
|
||||||
|
else:
|
||||||
|
# This is the standard L and T joints described by IFC
|
||||||
|
if connection1 == "ATEND":
|
||||||
|
if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal:
|
||||||
|
plane = self.get_profile_plane(profile2, furthest_plane if is_relating else closest_plane)
|
||||||
|
intersect = mathutils.geometry.intersect_line_plane(
|
||||||
|
*axis1, plane.col[3].to_3d(), plane.col[2].to_3d()
|
||||||
|
)
|
||||||
|
self.body[1] = intersect
|
||||||
|
else:
|
||||||
|
plane = self.get_profile_plane(
|
||||||
|
profile2,
|
||||||
|
furthest_plane if is_relating else closest_plane,
|
||||||
|
z_inwards=False if is_relating else True,
|
||||||
|
)
|
||||||
|
intersect = mathutils.geometry.intersect_line_plane(
|
||||||
|
*axis1, plane.col[3].to_3d(), plane.col[2].to_3d()
|
||||||
|
)
|
||||||
|
max_dim = self.get_max_bound_box_dimension(profile1)
|
||||||
|
self.body[1] = intersect + profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim))
|
||||||
|
self.clippings.append(plane)
|
||||||
|
elif connection1 == "ATSTART":
|
||||||
|
if tool.Cad.is_x(abs(xy_angle), (0, 90, 180), tolerance=0.001) and is_orthogonal:
|
||||||
|
plane = self.get_profile_plane(profile2, furthest_plane if is_relating else closest_plane)
|
||||||
|
intersect = mathutils.geometry.intersect_line_plane(
|
||||||
|
*axis1, plane.col[3].to_3d(), plane.col[2].to_3d()
|
||||||
|
)
|
||||||
|
self.body[0] = intersect
|
||||||
|
else:
|
||||||
|
plane = self.get_profile_plane(
|
||||||
|
profile2,
|
||||||
|
furthest_plane if is_relating else closest_plane,
|
||||||
|
z_inwards=False if is_relating else True,
|
||||||
|
)
|
||||||
|
intersect = mathutils.geometry.intersect_line_plane(
|
||||||
|
*axis1, plane.col[3].to_3d(), plane.col[2].to_3d()
|
||||||
|
)
|
||||||
|
max_dim = self.get_max_bound_box_dimension(profile1)
|
||||||
|
self.body[0] = intersect - profile1.matrix_world.to_quaternion() @ Vector((0, 0, max_dim))
|
||||||
|
self.clippings.append(plane)
|
||||||
|
|
||||||
def get_max_bound_box_dimension(self, obj):
|
def get_max_bound_box_dimension(self, obj):
|
||||||
x = [v[0] for v in obj.bound_box]
|
x = [v[0] for v in obj.bound_box]
|
||||||
|
|||||||
@@ -853,6 +853,7 @@ class DumbWallJoiner:
|
|||||||
related_element=element2,
|
related_element=element2,
|
||||||
relating_connection=wall1_end,
|
relating_connection=wall1_end,
|
||||||
related_connection=wall2_end,
|
related_connection=wall2_end,
|
||||||
|
description="BUTT",
|
||||||
)
|
)
|
||||||
|
|
||||||
self.recreate_wall(element1, wall1, axis1["reference"], axis1["reference"])
|
self.recreate_wall(element1, wall1, axis1["reference"], axis1["reference"])
|
||||||
@@ -955,12 +956,16 @@ class DumbWallJoiner:
|
|||||||
connection = rel.RelatingConnectionType
|
connection = rel.RelatingConnectionType
|
||||||
other = tool.Ifc.get_object(rel.RelatedElement)
|
other = tool.Ifc.get_object(rel.RelatedElement)
|
||||||
if connection not in ["ATPATH", "NOTDEFINED"]:
|
if connection not in ["ATPATH", "NOTDEFINED"]:
|
||||||
self.join(obj, other, connection, rel.RelatedConnectionType, is_relating=True, description=rel.Description)
|
self.join(
|
||||||
|
obj, other, connection, rel.RelatedConnectionType, is_relating=True, description=rel.Description
|
||||||
|
)
|
||||||
for rel in element.ConnectedFrom:
|
for rel in element.ConnectedFrom:
|
||||||
connection = rel.RelatedConnectionType
|
connection = rel.RelatedConnectionType
|
||||||
other = tool.Ifc.get_object(rel.RelatingElement)
|
other = tool.Ifc.get_object(rel.RelatingElement)
|
||||||
if connection not in ["ATPATH", "NOTDEFINED"]:
|
if connection not in ["ATPATH", "NOTDEFINED"]:
|
||||||
self.join(obj, other, connection, rel.RelatingConnectionType, is_relating=False, description=rel.Description)
|
self.join(
|
||||||
|
obj, other, connection, rel.RelatingConnectionType, is_relating=False, description=rel.Description
|
||||||
|
)
|
||||||
|
|
||||||
new_matrix = copy.deepcopy(obj.matrix_world)
|
new_matrix = copy.deepcopy(obj.matrix_world)
|
||||||
new_matrix.col[3] = self.body[0].to_4d()
|
new_matrix.col[3] = self.body[0].to_4d()
|
||||||
|
|||||||
@@ -190,6 +190,10 @@ class BimTool(WorkSpaceTool):
|
|||||||
row.label(text="", icon="EVENT_T")
|
row.label(text="", icon="EVENT_T")
|
||||||
row.operator("bim.hotkey", text="Butt").hotkey="S_T"
|
row.operator("bim.hotkey", text="Butt").hotkey="S_T"
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
|
row.label(text="", icon="EVENT_SHIFT")
|
||||||
|
row.label(text="", icon="EVENT_Y")
|
||||||
|
row.operator("bim.hotkey", text="Mitre").hotkey="S_Y"
|
||||||
|
row = layout.row(align=True)
|
||||||
row.operator("bim.extend_profile", icon="X", text="Disconnect").join_type = ""
|
row.operator("bim.extend_profile", icon="X", text="Disconnect").join_type = ""
|
||||||
|
|
||||||
if props.ifc_class in (
|
if props.ifc_class in (
|
||||||
@@ -309,6 +313,8 @@ class Hotkey(bpy.types.Operator):
|
|||||||
def hotkey_S_Y(self):
|
def hotkey_S_Y(self):
|
||||||
if self.props.ifc_class == "IfcWallType":
|
if self.props.ifc_class == "IfcWallType":
|
||||||
bpy.ops.bim.join_wall(join_type="V")
|
bpy.ops.bim.join_wall(join_type="V")
|
||||||
|
elif self.props.ifc_class in ["IfcColumnType", "IfcBeamType", "IfcMemberType"]:
|
||||||
|
bpy.ops.bim.extend_profile(join_type="V")
|
||||||
|
|
||||||
def hotkey_S_O(self):
|
def hotkey_S_O(self):
|
||||||
bpy.ops.bim.add_element_opening(voided_building_element="", filling_building_element="")
|
bpy.ops.bim.add_element_opening(voided_building_element="", filling_building_element="")
|
||||||
|
|||||||
Reference in New Issue
Block a user