Polyline slab tool - You can now change offset and direction

As it was implemented in Polyline wall tool, the user can press "O" to
change offset and "F" to flip the direction
This commit is contained in:
Bruno Perdigão
2025-01-23 14:22:24 -03:00
parent 4f77df99a5
commit 5ec5594c69
3 changed files with 92 additions and 19 deletions
@@ -187,10 +187,23 @@ def get_wall_preview_data(context, relating_type):
def get_slab_preview_data(context, relating_type):
props = context.scene.BIMModelProperties
x_angle = 0 if tool.Cad.is_x(props.x_angle, 0, tolerance=0.001) else props.x_angle
model_props = context.scene.BIMModelProperties
direction_sense = model_props.direction_sense
direction = 1
if direction_sense == "NEGATIVE":
direction = -1
layers = tool.Model.get_material_layer_parameters(relating_type)
if not layers["thickness"]:
return
thickness = layers["thickness"]
thickness *= direction
offset_type = model_props.offset_type_horizontal
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
offset = model_props.offset * unit_scale
offset *= direction
data = {}
data["verts"] = []
# Verts
@@ -209,6 +222,8 @@ def get_slab_preview_data(context, relating_type):
transformed_vertices = [Vector((v.x, v.y * (1 / cos(x_angle)), v.z)) for v in local_vertices]
# Convert back to world origin
polyline_vertices = [v + Vector(polyline_vertices[0]) for v in transformed_vertices]
if offset != 0:
polyline_vertices = [v + Vector((0, 0, offset)) for v in polyline_vertices]
is_closed = True
if (
polyline_vertices[0].x == polyline_vertices[-1].x
@@ -891,6 +906,26 @@ class PolylineOperator:
t = props.tris.add()
t.value_3d = tri
def set_offset(self, context: bpy.types.Context, relating_type: ifcopenshell.entity_instance) -> None:
props = bpy.context.scene.BIMModelProperties
if tool.Model.get_usage_type(relating_type) == "LAYER2":
offset_type = "offset_type_vertical"
elif tool.Model.get_usage_type(relating_type) == "LAYER3":
offset_type = "offset_type_horizontal"
else:
return
layers = tool.Model.get_material_layer_parameters(relating_type)
thickness = layers["thickness"]
self.offset = 0
if getattr(props, offset_type) == "CENTER":
self.offset = -thickness / 2
elif getattr(props, offset_type) in {"INTERIOR", "TOP"}:
self.offset = -thickness
props.offset = self.offset / self.unit_scale
tool.Blender.update_viewport()
def modal(self, context: bpy.types.Context, event: bpy.types.Event) -> Union[set[str], None]:
PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0])
tool.Blender.update_viewport()
@@ -206,6 +206,12 @@ class BIMModelProperties(PropertyGroup):
default="EXTERIOR",
description="It's a convention that affects the offset to reference line",
)
offset_type_horizontal: bpy.props.EnumProperty(
items=[("TOP", "Top", ""), ("CENTER", "Center", ""), ("BOTTOM", "Bottom", "")],
name="Horizontal Layer Offset Type",
default="TOP",
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")
show_wall_axis: bpy.props.BoolProperty(
name="Show Wall Axis",
+51 -19
View File
@@ -30,6 +30,7 @@ import bonsai.core.type
import bonsai.core.geometry
import bonsai.core.root
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
from math import cos, radians
from mathutils import Vector, Matrix
from bonsai.bim.module.geometry.helper import Helper
@@ -290,6 +291,14 @@ class DumbSlabPlaner:
if material.LayerSetDirection == "AXIS3":
self.change_thickness(related_object, new_thickness)
def regenerate_from_occurence(self, element, material_set_usage):
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
layer_set = material_set_usage.ForLayerSet
total_thickness = sum([l.LayerThickness for l in layer_set.MaterialLayers])
if not total_thickness:
return
self.change_thickness(element, total_thickness)
def change_thickness(self, element: ifcopenshell.entity_instance, thickness: float) -> None:
layer_params = tool.Model.get_material_layer_parameters(element)
body_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
@@ -863,7 +872,25 @@ class DrawPolylineSlab(bpy.types.Operator, PolylineOperator):
if not self.relating_type:
return {"FINISHED"}
DumbSlabGenerator(self.relating_type).generate("POLYLINE")
slab = DumbSlabGenerator(self.relating_type).generate("POLYLINE")
model_props = context.scene.BIMModelProperties
direction_sense = model_props.direction_sense
offset = model_props.offset
model = IfcStore.get_file()
element = tool.Ifc.get_entity(slab)
material = ifcopenshell.util.element.get_material(element)
material_set_usage = model.by_id(material.id())
if not getattr(material_set_usage, "ForLayerSet", False):
return
attributes = {"OffsetFromReferenceLine": offset, "DirectionSense": direction_sense}
ifcopenshell.api.run(
"material.edit_layer_usage",
model,
**{"usage": material_set_usage, "attributes": attributes},
)
DumbSlabPlaner().regenerate_from_occurence(element, material_set_usage)
def modal(self, context, event):
if not self.relating_type:
@@ -881,27 +908,31 @@ class DrawPolylineSlab(bpy.types.Operator, PolylineOperator):
self.handle_mouse_move(context, event)
return {"PASS_THROUGH"}
# TODO Slab 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"
# )
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"
)
# 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)]
props = bpy.context.scene.BIMModelProperties
if event.value == "RELEASE" and event.type == "O":
items = ["TOP", "CENTER", "BOTTOM"]
index = items.index(props.offset_type_horizontal)
size = len(items)
props.offset_type_horizontal = items[((index + 1) % size)]
self.set_offset(context, self.relating_type)
# props = bpy.context.scene.BIMModelProperties
# slab_config = f"""Direction: {props.direction_sense}
# Offset Type: {props.offset_type}
# Offset Value: {props.offset}
# """
custom_instructions = {
'Choose Axis': {'icons':True, 'keys': ['EVENT_X', 'EVENT_Y']}
}
self.handle_instructions(context)
slab_config = [
f"Direction: {props.direction_sense}",
f"Offset Type: {props.offset_type_horizontal}",
f"Offset Value: {tool.Polyline.format_input_ui_units(props.offset * self.unit_scale)}",
]
self.handle_instructions(context, custom_instructions, slab_config)
self.handle_mouse_move(context, event, should_round=True)
@@ -940,6 +971,7 @@ class DrawPolylineSlab(bpy.types.Operator, PolylineOperator):
ProductDecorator.install(context)
self.tool_state.use_default_container = True
self.tool_state.plane_method = "XY"
self.set_offset(context, self.relating_type)
return {"RUNNING_MODAL"}