mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 02:47:48 +00:00
Add polyline tool for slabs.
No preview yet.
This commit is contained in:
@@ -100,6 +100,7 @@ classes = (
|
||||
roof.GenerateHippedRoof,
|
||||
slab.DisableEditingExtrusionProfile,
|
||||
slab.DisableEditingSketchExtrusionProfile,
|
||||
slab.DrawPolylineSlab,
|
||||
slab.EditExtrusionProfile,
|
||||
slab.EditSketchExtrusionProfile,
|
||||
slab.EnableEditingExtrusionProfile,
|
||||
|
||||
@@ -32,7 +32,8 @@ import bonsai.core.root
|
||||
import bonsai.tool as tool
|
||||
from mathutils import Vector, Matrix
|
||||
from bonsai.bim.module.geometry.helper import Helper
|
||||
from bonsai.bim.module.model.decorator import ProfileDecorator
|
||||
from bonsai.bim.module.model.decorator import ProfileDecorator, PolylineDecorator, ProductDecorator
|
||||
from bonsai.bim.module.model.polyline import PolylineOperator
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@@ -40,7 +41,7 @@ class DumbSlabGenerator:
|
||||
def __init__(self, relating_type: ifcopenshell.entity_instance):
|
||||
self.relating_type = relating_type
|
||||
|
||||
def generate(self):
|
||||
def generate(self, draw_from_polyline=False):
|
||||
self.file = tool.Ifc.get()
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
thicknesses = []
|
||||
@@ -60,6 +61,7 @@ class DumbSlabGenerator:
|
||||
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
|
||||
self.polyline = None
|
||||
self.container = None
|
||||
self.container_obj = None
|
||||
if container := tool.Root.get_default_container():
|
||||
@@ -72,7 +74,26 @@ class DumbSlabGenerator:
|
||||
self.rotation = 0
|
||||
self.location = Vector((0, 0, 0))
|
||||
self.x_angle = 0 if tool.Cad.is_x(props.x_angle, 0, tolerance=0.001) else props.x_angle
|
||||
return self.derive_from_cursor()
|
||||
|
||||
if draw_from_polyline:
|
||||
return self.derive_from_polyline()
|
||||
else:
|
||||
return self.derive_from_cursor()
|
||||
|
||||
def derive_from_polyline(self):
|
||||
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
|
||||
polyline_points = polyline_data[0].polyline_points if polyline_data else []
|
||||
self.location = Vector((polyline_points[0].x, polyline_points[0].y, self.container_obj.location.z))
|
||||
self.polyline = [Vector((p.x, p.y, 0.0)) - self.location for p in polyline_points]
|
||||
|
||||
if len(self.polyline) <= 2:
|
||||
return
|
||||
|
||||
# Always assume a closed polyline
|
||||
if self.polyline[0] != self.polyline[-1]:
|
||||
self.polyline.append(self.polyline[0])
|
||||
|
||||
return self.create_slab()
|
||||
|
||||
def derive_from_cursor(self):
|
||||
self.location = bpy.context.scene.cursor.location
|
||||
@@ -112,6 +133,7 @@ class DumbSlabGenerator:
|
||||
context=self.body_context,
|
||||
depth=self.depth,
|
||||
x_angle=self.x_angle,
|
||||
polyline=self.polyline,
|
||||
)
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", tool.Ifc.get(), product=element, representation=representation
|
||||
@@ -700,3 +722,102 @@ class SetArcIndex(bpy.types.Operator):
|
||||
group.add(selected_vertices, 1, "REPLACE")
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DrawPolylineSlab(bpy.types.Operator, PolylineOperator):
|
||||
bl_idname = "bim.draw_polyline_slab"
|
||||
bl_label = "Draw Polyline Slab"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.space_data.type == "VIEW_3D"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.relating_type = None
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
relating_type_id = props.relating_type_id
|
||||
if relating_type_id:
|
||||
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||
|
||||
def create_slab_from_polyline(self, context):
|
||||
if not self.relating_type:
|
||||
return {"FINISHED"}
|
||||
|
||||
DumbSlabGenerator(self.relating_type).generate(True)
|
||||
|
||||
def modal(self, context, event):
|
||||
if not self.relating_type:
|
||||
self.report({"WARNING"}, "You need to select a slab type.")
|
||||
PolylineDecorator.uninstall()
|
||||
tool.Blender.update_viewport()
|
||||
return {"FINISHED"}
|
||||
|
||||
PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0])
|
||||
tool.Blender.update_viewport()
|
||||
|
||||
self.handle_lock_axis(context, event)
|
||||
|
||||
if event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}:
|
||||
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 == "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
|
||||
# slab_config = f"""Direction: {props.direction_sense}
|
||||
# Offset Type: {props.offset_type}
|
||||
# Offset Value: {props.offset}
|
||||
# """
|
||||
|
||||
self.handle_instructions(context)
|
||||
|
||||
self.handle_mouse_move(context, event, should_round=True)
|
||||
|
||||
self.choose_axis(event)
|
||||
|
||||
self.handle_snap_selection(context, event)
|
||||
|
||||
if (
|
||||
not self.tool_state.is_input_on
|
||||
and event.value == "RELEASE"
|
||||
and event.type in {"RET", "NUMPAD_ENTER", "RIGHTMOUSE"}
|
||||
):
|
||||
self.create_slab_from_polyline(context)
|
||||
context.workspace.status_text_set(text=None)
|
||||
ProductDecorator.uninstall()
|
||||
PolylineDecorator.uninstall()
|
||||
tool.Polyline.clear_polyline()
|
||||
tool.Blender.update_viewport()
|
||||
return {"FINISHED"}
|
||||
|
||||
self.handle_keyboard_input(context, event)
|
||||
|
||||
self.handle_inserting_polyline(context, event)
|
||||
|
||||
cancel = self.handle_cancelation(context, event)
|
||||
if cancel is not None:
|
||||
ProductDecorator.uninstall()
|
||||
return cancel
|
||||
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
super().invoke(context, event)
|
||||
ProductDecorator.install(context)
|
||||
self.tool_state.use_default_container = True
|
||||
self.tool_state.plane_method = "XY"
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
@@ -935,6 +935,10 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
relating_type_id := tool.Blender.get_enum_safe(props, "relating_type_id")
|
||||
) and tool.Model.get_usage_type(tool.Ifc.get().by_id(int(relating_type_id))) == "LAYER2":
|
||||
bpy.ops.bim.draw_polyline_wall("INVOKE_DEFAULT")
|
||||
elif (
|
||||
relating_type_id := tool.Blender.get_enum_safe(props, "relating_type_id")
|
||||
) and tool.Model.get_usage_type(tool.Ifc.get().by_id(int(relating_type_id))) == "LAYER3":
|
||||
bpy.ops.bim.draw_polyline_slab("INVOKE_DEFAULT")
|
||||
else:
|
||||
bpy.ops.bim.add_occurrence("INVOKE_DEFAULT")
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import ifcopenshell.util.unit
|
||||
from ifcopenshell.util.data import Clipping
|
||||
from math import sin, cos
|
||||
from mathutils import Vector
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
|
||||
@@ -34,6 +35,7 @@ def add_slab_representation(
|
||||
# Planes are defined either by Clipping objects
|
||||
# or by dictionaries of arguments for `Clipping.parse`
|
||||
clippings: Optional[list[Union[Clipping, dict[str, Any]]]] = None,
|
||||
polyline: Optional[list[Vector]] = None,
|
||||
) -> ifcopenshell.entity_instance:
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
@@ -42,6 +44,7 @@ def add_slab_representation(
|
||||
"depth": depth,
|
||||
"x_angle": x_angle,
|
||||
"clippings": clippings if clippings is not None else [],
|
||||
"polyline": polyline,
|
||||
}
|
||||
return usecase.execute()
|
||||
|
||||
@@ -59,6 +62,8 @@ class Usecase:
|
||||
def create_item(self):
|
||||
size = self.convert_si_to_unit(1)
|
||||
points = ((0.0, 0.0), (size, 0.0), (size, size), (0.0, size), (0.0, 0.0))
|
||||
if self.settings["polyline"]:
|
||||
points = [(self.convert_si_to_unit(p[0]), self.convert_si_to_unit(p[1])) for p in self.settings["polyline"]]
|
||||
if self.file.schema == "IFC2X3":
|
||||
curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points])
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user