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): def get_slab_preview_data(context, relating_type):
props = context.scene.BIMModelProperties props = context.scene.BIMModelProperties
x_angle = 0 if tool.Cad.is_x(props.x_angle, 0, tolerance=0.001) else props.x_angle 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) layers = tool.Model.get_material_layer_parameters(relating_type)
if not layers["thickness"]: if not layers["thickness"]:
return return
thickness = layers["thickness"] 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 = {}
data["verts"] = [] data["verts"] = []
# 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] transformed_vertices = [Vector((v.x, v.y * (1 / cos(x_angle)), v.z)) for v in local_vertices]
# Convert back to world origin # Convert back to world origin
polyline_vertices = [v + Vector(polyline_vertices[0]) for v in transformed_vertices] 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 is_closed = True
if ( if (
polyline_vertices[0].x == polyline_vertices[-1].x polyline_vertices[0].x == polyline_vertices[-1].x
@@ -891,6 +906,26 @@ class PolylineOperator:
t = props.tris.add() t = props.tris.add()
t.value_3d = tri 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]: 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]) PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0])
tool.Blender.update_viewport() tool.Blender.update_viewport()
@@ -206,6 +206,12 @@ class BIMModelProperties(PropertyGroup):
default="EXTERIOR", default="EXTERIOR",
description="It's a convention that affects the offset to reference line", 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") offset: bpy.props.FloatProperty(name="Offset", default=0.0, description="Material usage offset from reference line")
show_wall_axis: bpy.props.BoolProperty( show_wall_axis: bpy.props.BoolProperty(
name="Show Wall Axis", name="Show Wall Axis",
+51 -19
View File
@@ -30,6 +30,7 @@ import bonsai.core.type
import bonsai.core.geometry import bonsai.core.geometry
import bonsai.core.root import bonsai.core.root
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
from math import cos, radians from math import cos, radians
from mathutils import Vector, Matrix from mathutils import Vector, Matrix
from bonsai.bim.module.geometry.helper import Helper from bonsai.bim.module.geometry.helper import Helper
@@ -290,6 +291,14 @@ class DumbSlabPlaner:
if material.LayerSetDirection == "AXIS3": if material.LayerSetDirection == "AXIS3":
self.change_thickness(related_object, new_thickness) 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: def change_thickness(self, element: ifcopenshell.entity_instance, thickness: float) -> None:
layer_params = tool.Model.get_material_layer_parameters(element) layer_params = tool.Model.get_material_layer_parameters(element)
body_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW") 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: if not self.relating_type:
return {"FINISHED"} 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): def modal(self, context, event):
if not self.relating_type: if not self.relating_type:
@@ -881,27 +908,31 @@ class DrawPolylineSlab(bpy.types.Operator, PolylineOperator):
self.handle_mouse_move(context, event) self.handle_mouse_move(context, event)
return {"PASS_THROUGH"} return {"PASS_THROUGH"}
# TODO Slab settings if event.value == "RELEASE" and event.type == "F":
# if event.value == "RELEASE" and event.type == "F": direction_sense = context.scene.BIMModelProperties.direction_sense
# direction_sense = context.scene.BIMModelProperties.direction_sense context.scene.BIMModelProperties.direction_sense = (
# context.scene.BIMModelProperties.direction_sense = ( "NEGATIVE" if direction_sense == "POSITIVE" else "POSITIVE"
# "NEGATIVE" if direction_sense == "POSITIVE" else "POSITIVE" )
# )
# if event.value == "RELEASE" and event.type == "O": props = bpy.context.scene.BIMModelProperties
# offset_type = context.scene.BIMModelProperties.offset_type if event.value == "RELEASE" and event.type == "O":
# items = ["EXTERIOR", "CENTER", "INTERIOR"] items = ["TOP", "CENTER", "BOTTOM"]
# index = items.index(offset_type) index = items.index(props.offset_type_horizontal)
# size = len(items) size = len(items)
# context.scene.BIMModelProperties.offset_type = items[((index + 1) % size)] props.offset_type_horizontal = items[((index + 1) % size)]
self.set_offset(context, self.relating_type)
# props = bpy.context.scene.BIMModelProperties custom_instructions = {
# slab_config = f"""Direction: {props.direction_sense} 'Choose Axis': {'icons':True, 'keys': ['EVENT_X', 'EVENT_Y']}
# Offset Type: {props.offset_type} }
# Offset Value: {props.offset}
# """
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) self.handle_mouse_move(context, event, should_round=True)
@@ -940,6 +971,7 @@ class DrawPolylineSlab(bpy.types.Operator, PolylineOperator):
ProductDecorator.install(context) ProductDecorator.install(context)
self.tool_state.use_default_container = True self.tool_state.use_default_container = True
self.tool_state.plane_method = "XY" self.tool_state.plane_method = "XY"
self.set_offset(context, self.relating_type)
return {"RUNNING_MODAL"} return {"RUNNING_MODAL"}