diff --git a/src/bonsai/bonsai/bim/module/model/wall.py b/src/bonsai/bonsai/bim/module/model/wall.py index 9e552db553..b62a4e8917 100644 --- a/src/bonsai/bonsai/bim/module/model/wall.py +++ b/src/bonsai/bonsai/bim/module/model/wall.py @@ -24,10 +24,12 @@ import math import numpy as np import ifcopenshell import ifcopenshell.api +import ifcopenshell.api.geometry import ifcopenshell.util.unit import ifcopenshell.util.element import ifcopenshell.util.placement import ifcopenshell.util.representation +import ifcopenshell.util.shape_builder import ifcopenshell.util.type import mathutils.geometry import bonsai.core.type @@ -66,7 +68,7 @@ class ExtendWallsToUnderside(bpy.types.Operator, tool.Ifc.Operator): def _execute(self, context): slab = None - walls = [] + walls: list[bpy.types.Object] = [] if (obj := tool.Blender.get_active_object(is_selected=True)) and (element := tool.Ifc.get_entity(obj)): slab = obj for obj in tool.Blender.get_selected_objects(include_active=False): @@ -1192,14 +1194,14 @@ class DumbWallJoiner: self.set_axis(element1, intersect, p2) self.recreate_wall(element1, wall1) - def set_length(self, wall1, si_length): + def set_length(self, wall1: bpy.types.Object, si_length: float) -> None: element1 = tool.Ifc.get_entity(wall1) if not element1: return if tool.Ifc.is_moved(wall1): bonsai.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=wall1) - ifcopenshell.api.run("geometry.disconnect_path", tool.Ifc.get(), element=element1, connection_type="ATEND") + ifcopenshell.api.geometry.disconnect_path(tool.Ifc.get(), element=element1, connection_type="ATEND") unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) p1, p2 = ifcopenshell.util.representation.get_reference_line(element1) @@ -1207,7 +1209,7 @@ class DumbWallJoiner: self.set_axis(element1, p1, p2) self.recreate_wall(element1, wall1) - def join_T(self, wall1, wall2): + def join_T(self, wall1: bpy.types.Object, wall2: bpy.types.Object) -> None: element1 = tool.Ifc.get_entity(wall1) element2 = tool.Ifc.get_entity(wall2) axis1 = tool.Model.get_wall_axis(wall1) @@ -1219,8 +1221,7 @@ class DumbWallJoiner: return connection = "ATEND" if tool.Cad.edge_percent(intersect, axis1["reference"]) > 0.5 else "ATSTART" - ifcopenshell.api.run( - "geometry.connect_path", + ifcopenshell.api.geometry.connect_path( tool.Ifc.get(), related_element=element1, relating_element=element2, @@ -1231,7 +1232,7 @@ class DumbWallJoiner: self.recreate_wall(element1, wall1, axis1["reference"], axis1["reference"]) - def connect(self, obj1, obj2): + def connect(self, obj1: bpy.types.Object, obj2: bpy.types.Object) -> None: wall1 = tool.Ifc.get_entity(obj1) wall2 = tool.Ifc.get_entity(obj2) if tool.Ifc.is_moved(obj1): diff --git a/src/bonsai/bonsai/core/model.py b/src/bonsai/bonsai/core/model.py index 1621585065..0a741f92c8 100644 --- a/src/bonsai/bonsai/core/model.py +++ b/src/bonsai/bonsai/core/model.py @@ -16,11 +16,21 @@ # You should have received a copy of the GNU General Public License # along with Bonsai. If not, see . -import bonsai.core.tool as tool -from typing import Literal, Iterable +from __future__ import annotations +from typing import TYPE_CHECKING, Optional, Literal, Iterable + +if TYPE_CHECKING: + import bpy + import ifcopenshell + import bonsai.tool as tool + + from mathutils import Vector + from bonsai.bim.module.model.wall import DumbWallJoiner -def unjoin_walls(ifc: tool.Ifc, blender: tool.Blender, geometry: tool.Geometry, joiner, model: tool.Model) -> None: +def unjoin_walls( + ifc: tool.Ifc, blender: tool.Blender, geometry: tool.Geometry, joiner: DumbWallJoiner, model: tool.Model +) -> None: for obj in blender.get_selected_objects(): if not (element := ifc.get_entity(obj)) or model.get_usage_type(element) != "LAYER2": continue @@ -31,7 +41,12 @@ def unjoin_walls(ifc: tool.Ifc, blender: tool.Blender, geometry: tool.Geometry, def extend_walls( - ifc: tool.Ifc, blender: tool.Blender, geometry: tool.Geometry, joiner, model: tool.Model, target + ifc: tool.Ifc, + blender: tool.Blender, + geometry: tool.Geometry, + joiner: DumbWallJoiner, + model: tool.Model, + target: Vector, ) -> None: for obj in blender.get_selected_objects(): if not (element := ifc.get_entity(obj)) or model.get_usage_type(element) != "LAYER2": @@ -44,7 +59,7 @@ def join_walls_LV( ifc: tool.Ifc, blender: tool.Blender, geometry: tool.Geometry, - joiner, + joiner: DumbWallJoiner, model: tool.Model, join_type: Literal["L", "V"] = "L", ) -> None: @@ -66,7 +81,11 @@ def join_walls_LV( def extend_wall_to_slab( - ifc: tool.Ifc, geometry: tool.Geometry, model: tool.Model, slab_obj, wall_objs: Iterable + ifc: tool.Ifc, + geometry: tool.Geometry, + model: tool.Model, + slab_obj: bpy.types.Object, + wall_objs: list[bpy.types.Object], ) -> None: if not (clip := model.get_slab_clipping_bmesh(slab_obj)): return # Nothing to clip? @@ -80,7 +99,9 @@ def extend_wall_to_slab( model.reload_body_representation(wall_objs) -def join_walls_TZ(ifc: tool.Ifc, blender: tool.Blender, geometry: tool.Geometry, joiner, model: tool.Model) -> None: +def join_walls_TZ( + ifc: tool.Ifc, blender: tool.Blender, geometry: tool.Geometry, joiner: DumbWallJoiner, model: tool.Model +) -> None: selected_objs = [ o for o in blender.get_selected_objects() diff --git a/src/bonsai/bonsai/tool/debug.py b/src/bonsai/bonsai/tool/debug.py index 51008e04a4..5638436c8f 100644 --- a/src/bonsai/bonsai/tool/debug.py +++ b/src/bonsai/bonsai/tool/debug.py @@ -64,7 +64,7 @@ class Debug(bonsai.core.tool.Debug): pass @classmethod - def debug_bmesh(cls, bm: bpy.types.BMesh, name: str = "Debug") -> bpy.types.Object: + def debug_bmesh(cls, bm: bmesh.types.BMesh, name: str = "Debug") -> bpy.types.Object: mesh = bpy.data.meshes.new("Debug") bm.to_mesh(mesh) obj = bpy.data.objects.new(name, mesh) diff --git a/src/bonsai/bonsai/tool/model.py b/src/bonsai/bonsai/tool/model.py index a3dcc47f02..690498308b 100644 --- a/src/bonsai/bonsai/tool/model.py +++ b/src/bonsai/bonsai/tool/model.py @@ -34,6 +34,7 @@ import ifcopenshell.util.element import ifcopenshell.util.placement import ifcopenshell.util.representation import ifcopenshell.util.shape +import ifcopenshell.util.shape_builder import ifcopenshell.util.unit import bonsai.core.geometry import bonsai.core.tool @@ -2104,7 +2105,7 @@ class Model(bonsai.core.tool.Model): op.material_id = material_id_int @classmethod - def get_slab_clipping_bmesh(cls, obj: bpy.types.Object) -> bpy.types.BMesh | None: + def get_slab_clipping_bmesh(cls, obj: bpy.types.Object) -> bmesh.types.BMesh | None: unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) bm = bmesh.new() @@ -2136,7 +2137,7 @@ class Model(bonsai.core.tool.Model): return clipping_bm # clipping_bm is in project units @classmethod - def clip_wall_to_slab(cls, wall: ifcopenshell.entity_instance, clipping_bm: bpy.types.BMesh) -> None: + def clip_wall_to_slab(cls, wall: ifcopenshell.entity_instance, clipping_bm: bmesh.types.BMesh) -> None: matrix_i = np.linalg.inv(ifcopenshell.util.placement.get_local_placement(wall.ObjectPlacement)) bm = clipping_bm.copy() bmesh.ops.transform(bm, matrix=Matrix(matrix_i.tolist()), verts=bm.verts)