mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
Polyline wall ability to switch axis while drawing.
While drawing the polyline the user can press: - F to flip the wall. Changes the direction sense. - O to change the offset type between Exterior, Center and Interior. This will change the offset from reference line. Those attributes can be verified in the Object Materials panels of each wall after they are created.
This commit is contained in:
@@ -165,13 +165,13 @@ class PolylineOperator:
|
|||||||
self.tool_state.axis_method = None
|
self.tool_state.axis_method = None
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
|
|
||||||
def handle_instructions(self, context):
|
def handle_instructions(self, context, custom_instructions):
|
||||||
self.snap_info = f"""|
|
self.snap_info = f"""|
|
||||||
Axis: {self.tool_state.axis_method}
|
Axis: {self.tool_state.axis_method}
|
||||||
Plane: {self.tool_state.plane_method}
|
Plane: {self.tool_state.plane_method}
|
||||||
Snap: {self.snapping_points[0][1]}
|
Snap: {self.snapping_points[0][1]}
|
||||||
"""
|
"""
|
||||||
context.workspace.status_text_set(self.instructions + self.snap_info)
|
context.workspace.status_text_set(self.instructions + custom_instructions + self.snap_info)
|
||||||
|
|
||||||
def handle_lock_axis(self, context, event):
|
def handle_lock_axis(self, context, event):
|
||||||
if event.value == "RELEASE" and event.type == "L":
|
if event.value == "RELEASE" and event.type == "L":
|
||||||
|
|||||||
@@ -149,6 +149,18 @@ class BIMModelProperties(PropertyGroup):
|
|||||||
type_page: bpy.props.IntProperty(name="Type Page", default=1, update=update_type_page)
|
type_page: bpy.props.IntProperty(name="Type Page", default=1, update=update_type_page)
|
||||||
type_name: bpy.props.StringProperty(name="Name", default="TYPEX")
|
type_name: bpy.props.StringProperty(name="Name", default="TYPEX")
|
||||||
boundary_class: bpy.props.EnumProperty(items=get_boundary_class, name="Boundary Class")
|
boundary_class: bpy.props.EnumProperty(items=get_boundary_class, name="Boundary Class")
|
||||||
|
direction_sense: bpy.props.EnumProperty(
|
||||||
|
items=[("POSITIVE", "Positive", ""), ("NEGATIVE", "Negative", "")],
|
||||||
|
name="Material Usage Direction Sense",
|
||||||
|
default="POSITIVE"
|
||||||
|
)
|
||||||
|
offset_type: bpy.props.EnumProperty(
|
||||||
|
items=[("EXTERIOR", "Exterior", ""), ("CENTER", "Center", ""), ("INTERIOR", "Interior", "")],
|
||||||
|
name="Layer Offset Type",
|
||||||
|
default="EXTERIOR",
|
||||||
|
description="It's a convention that affects the offset to reference line"
|
||||||
|
)
|
||||||
|
offset: bpy.props.FloatProperty(name="Offset", default=0.0, description="Material usage offset from reference line")
|
||||||
|
|
||||||
|
|
||||||
class BIMArrayProperties(PropertyGroup):
|
class BIMArrayProperties(PropertyGroup):
|
||||||
|
|||||||
@@ -297,7 +297,8 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.relating_type = None
|
self.relating_type = None
|
||||||
relating_type_id = bpy.context.scene.BIMModelProperties.relating_type_id
|
props = bpy.context.scene.BIMModelProperties
|
||||||
|
relating_type_id = props.relating_type_id
|
||||||
if relating_type_id:
|
if relating_type_id:
|
||||||
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||||
|
|
||||||
@@ -305,7 +306,25 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator):
|
|||||||
if not self.relating_type:
|
if not self.relating_type:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
model_props = context.scene.BIMModelProperties
|
||||||
|
direction_sense = model_props.direction_sense
|
||||||
|
offset = model_props.offset
|
||||||
|
|
||||||
walls, is_polyline_closed = DumbWallGenerator(self.relating_type).generate(True)
|
walls, is_polyline_closed = DumbWallGenerator(self.relating_type).generate(True)
|
||||||
|
for wall in walls:
|
||||||
|
model = IfcStore.get_file()
|
||||||
|
element = tool.Ifc.get_entity(wall["obj"])
|
||||||
|
material = ifcopenshell.util.element.get_material(element)
|
||||||
|
material_set_usage = model.by_id(material.id())
|
||||||
|
# if material.is_a("IfcMaterialLayerSetUsage"):
|
||||||
|
attributes = {"OffsetFromReferenceLine": offset, "DirectionSense": direction_sense}
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"material.edit_layer_usage",
|
||||||
|
model,
|
||||||
|
**{"usage": material_set_usage, "attributes": attributes},
|
||||||
|
)
|
||||||
|
DumbWallRecalculator().recalculate([wall["obj"]])
|
||||||
|
|
||||||
if walls:
|
if walls:
|
||||||
if is_polyline_closed:
|
if is_polyline_closed:
|
||||||
for wall1, wall2 in zip(walls, walls[1:] + [walls[0]]):
|
for wall1, wall2 in zip(walls, walls[1:] + [walls[0]]):
|
||||||
@@ -330,7 +349,28 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator):
|
|||||||
self.handle_mouse_move(context, event)
|
self.handle_mouse_move(context, event)
|
||||||
return {"PASS_THROUGH"}
|
return {"PASS_THROUGH"}
|
||||||
|
|
||||||
self.handle_instructions(context)
|
# Wall axis settings
|
||||||
|
if event.value == "RELEASE" and event.type == "F":
|
||||||
|
direction_sense = context.scene.BIMModelProperties.direction_sense
|
||||||
|
context.scene.BIMModelProperties.direction_sense = (
|
||||||
|
"NEGATIVE" if direction_sense == "POSITIVE" else "POSITIVE"
|
||||||
|
)
|
||||||
|
tool.Polyline.create_wall_preview_vertices(context, self.relating_type)
|
||||||
|
|
||||||
|
if event.value == "RELEASE" and event.type == "O":
|
||||||
|
offset_type = context.scene.BIMModelProperties.offset_type
|
||||||
|
items = ["EXTERIOR", "CENTER", "INTERIOR"]
|
||||||
|
index = items.index(offset_type)
|
||||||
|
size = len(items)
|
||||||
|
context.scene.BIMModelProperties.offset_type = items[((index + 1) % size)]
|
||||||
|
tool.Polyline.create_wall_preview_vertices(context, self.relating_type)
|
||||||
|
|
||||||
|
props = bpy.context.scene.BIMModelProperties
|
||||||
|
wall_config = f"""Direction: {props.direction_sense}
|
||||||
|
Offset Type: {props.offset_type}
|
||||||
|
Offset Value: {props.offset}
|
||||||
|
"""
|
||||||
|
self.handle_instructions(context, wall_config)
|
||||||
|
|
||||||
self.handle_mouse_move(context, event, should_round=True)
|
self.handle_mouse_move(context, event, should_round=True)
|
||||||
|
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
def create_bmesh_from_vertices(vertices):
|
def create_bmesh_from_vertices(vertices):
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
|
|
||||||
new_verts = [bm.verts.new(v) for v in base_vertices]
|
new_verts = [bm.verts.new(v) for v in polyline_vertices]
|
||||||
if is_closed:
|
if is_closed:
|
||||||
new_edges = [bm.edges.new((new_verts[i], new_verts[i + 1])) for i in range(len(new_verts) - 1)]
|
new_edges = [bm.edges.new((new_verts[i], new_verts[i + 1])) for i in range(len(new_verts) - 1)]
|
||||||
new_edges.append(
|
new_edges.append(
|
||||||
@@ -327,36 +327,61 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
if not layers["thickness"]:
|
if not layers["thickness"]:
|
||||||
return
|
return
|
||||||
thickness = layers["thickness"]
|
thickness = layers["thickness"]
|
||||||
|
model_props = context.scene.BIMModelProperties
|
||||||
|
direction_sense = model_props.direction_sense
|
||||||
|
direction = 1
|
||||||
|
if direction_sense == "NEGATIVE":
|
||||||
|
direction = -1
|
||||||
|
offset_type = model_props.offset_type
|
||||||
|
offset = 0
|
||||||
|
if offset_type == "CENTER":
|
||||||
|
offset = -thickness/2
|
||||||
|
elif offset_type == "INTERIOR":
|
||||||
|
offset = -thickness
|
||||||
|
|
||||||
height = float(context.scene.BIMModelProperties.extrusion_depth)
|
unit_system = tool.Drawing.get_unit_system()
|
||||||
rl = float(context.scene.BIMModelProperties.rl1)
|
factor = 1
|
||||||
x_angle = float(context.scene.BIMModelProperties.x_angle)
|
if unit_system == "IMPERIAL":
|
||||||
|
factor = 3.048
|
||||||
|
if unit_system == "METRIC":
|
||||||
|
unit_length = bpy.context.scene.unit_settings.length_unit
|
||||||
|
if unit_length == "MILLIMETERS":
|
||||||
|
factor = 1000
|
||||||
|
|
||||||
|
# For the model properties, the offset value should just be converted
|
||||||
|
# However, for the wall preview logic that follows, offset and thickness must change direction
|
||||||
|
model_props.offset = offset * factor
|
||||||
|
thickness *= direction
|
||||||
|
offset *= direction
|
||||||
|
|
||||||
|
height = float(model_props.extrusion_depth)
|
||||||
|
rl = float(model_props.rl1)
|
||||||
|
x_angle = float(model_props.x_angle)
|
||||||
angle_distortion = height * tan(x_angle)
|
angle_distortion = height * tan(x_angle)
|
||||||
|
|
||||||
base_vertices = []
|
polyline_vertices = []
|
||||||
top_vertices = []
|
|
||||||
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
|
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
|
||||||
polyline_points = polyline_data[0].polyline_points if polyline_data else []
|
polyline_points = polyline_data[0].polyline_points if polyline_data else []
|
||||||
if len(polyline_points) < 2:
|
if len(polyline_points) < 2:
|
||||||
context.scene.BIMPolylineProperties.product_preview.clear()
|
context.scene.BIMPolylineProperties.product_preview.clear()
|
||||||
return
|
return
|
||||||
for point in polyline_points:
|
for point in polyline_points:
|
||||||
base_vertices.append(Vector((point.x, point.y, point.z)))
|
polyline_vertices.append(Vector((point.x, point.y, point.z)))
|
||||||
|
|
||||||
is_closed = False
|
is_closed = False
|
||||||
if (
|
if (
|
||||||
base_vertices[0].x == base_vertices[-1].x
|
polyline_vertices[0].x == polyline_vertices[-1].x
|
||||||
and base_vertices[0].y == base_vertices[-1].y
|
and polyline_vertices[0].y == polyline_vertices[-1].y
|
||||||
and base_vertices[0].z == base_vertices[-1].z
|
and polyline_vertices[0].z == polyline_vertices[-1].z
|
||||||
):
|
):
|
||||||
is_closed = True
|
is_closed = True
|
||||||
base_vertices.pop(-1) # Remove the last point. The edges are going to inform that the shape is closed.
|
polyline_vertices.pop(-1) # Remove the last point. The edges are going to inform that the shape is closed.
|
||||||
|
|
||||||
bm_base = create_bmesh_from_vertices(base_vertices)
|
bm_base = create_bmesh_from_vertices(polyline_vertices)
|
||||||
|
base_vertices = tool.Cad.offset_edges(bm_base, offset)
|
||||||
offset_base_verts = tool.Cad.offset_edges(bm_base, thickness)
|
offset_base_verts = tool.Cad.offset_edges(bm_base, thickness + offset)
|
||||||
top_vertices = tool.Cad.offset_edges(bm_base, angle_distortion)
|
top_vertices = tool.Cad.offset_edges(bm_base, angle_distortion + offset)
|
||||||
offset_top_verts = tool.Cad.offset_edges(bm_base, angle_distortion + thickness)
|
offset_top_verts = tool.Cad.offset_edges(bm_base, angle_distortion + thickness + offset)
|
||||||
|
|
||||||
if is_closed:
|
if is_closed:
|
||||||
base_vertices.append(base_vertices[0])
|
base_vertices.append(base_vertices[0])
|
||||||
@@ -367,10 +392,11 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
if offset_base_verts is not None:
|
if offset_base_verts is not None:
|
||||||
context.scene.BIMPolylineProperties.product_preview.clear()
|
context.scene.BIMPolylineProperties.product_preview.clear()
|
||||||
for v in base_vertices:
|
for v in base_vertices:
|
||||||
|
new_v = Vector((v.co.x, v.co.y, v.co.z))
|
||||||
prop = context.scene.BIMPolylineProperties.product_preview.add()
|
prop = context.scene.BIMPolylineProperties.product_preview.add()
|
||||||
prop.x = v.x
|
prop.x = new_v.x
|
||||||
prop.y = v.y
|
prop.y = new_v.y
|
||||||
prop.z = v.z + rl
|
prop.z = new_v.z + rl
|
||||||
|
|
||||||
for v in offset_base_verts[::-1]:
|
for v in offset_base_verts[::-1]:
|
||||||
new_v = Vector((v.co.x, v.co.y, v.co.z))
|
new_v = Vector((v.co.x, v.co.y, v.co.z))
|
||||||
|
|||||||
Reference in New Issue
Block a user