From 7544053f0b731cd75ce73849094611f6ea7e2b19 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Tue, 22 Oct 2024 15:11:58 +0500 Subject: [PATCH] bim.generate_space not to fail silently --- src/bonsai/bonsai/bim/module/model/space.py | 4 +-- .../bonsai/bim/module/spatial/workspace.py | 4 +-- src/bonsai/bonsai/core/covering.py | 6 ++--- src/bonsai/bonsai/core/spatial.py | 26 ++++++++++++++----- src/bonsai/bonsai/tool/spatial.py | 8 +++++- 5 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/model/space.py b/src/bonsai/bonsai/bim/module/model/space.py index 875025e2ef..cfe8b367fb 100644 --- a/src/bonsai/bonsai/bim/module/model/space.py +++ b/src/bonsai/bonsai/bim/module/model/space.py @@ -42,8 +42,8 @@ class GenerateSpace(bpy.types.Operator, tool.Ifc.Operator): try: core.generate_space(tool.Ifc, tool.Model, tool.Root, tool.Spatial, tool.Type) - except core.NoDefaultContainer: - return self.report({"ERROR"}, "Please set a default container to create the space in.") + except core.SpaceGenerationError as e: + return self.report({"ERROR"}, str(e)) class GenerateSpacesFromWalls(bpy.types.Operator, tool.Ifc.Operator): diff --git a/src/bonsai/bonsai/bim/module/spatial/workspace.py b/src/bonsai/bonsai/bim/module/spatial/workspace.py index a550e000a0..57a18641d3 100644 --- a/src/bonsai/bonsai/bim/module/spatial/workspace.py +++ b/src/bonsai/bonsai/bim/module/spatial/workspace.py @@ -156,8 +156,8 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator): else: try: bonsai.core.spatial.generate_space(tool.Ifc, tool.Model, tool.Root, tool.Spatial, tool.Type) - except bonsai.core.spatial.NoDefaultContainer: - return self.report({"ERROR"}, "Please set a default container to create the space in.") + except bonsai.core.spatial.SpaceGenerationError as e: + return self.report({"ERROR"}, str(e)) def hotkey_S_B(self): bpy.ops.bim.add_boundary() diff --git a/src/bonsai/bonsai/core/covering.py b/src/bonsai/bonsai/core/covering.py index 3e7ffd525c..d26780c0c5 100644 --- a/src/bonsai/bonsai/core/covering.py +++ b/src/bonsai/bonsai/core/covering.py @@ -46,7 +46,7 @@ def add_instance_flooring_covering_from_cursor(ifc: tool.Ifc, root: tool.Root, s space_polygon = spatial.get_space_polygon_from_context_visible_objects(x, y) - if not space_polygon: + if isinstance(space_polygon, str): return bm = spatial.get_bmesh_from_polygon(space_polygon, h=0) @@ -91,7 +91,7 @@ def add_instance_ceiling_covering_from_cursor( space_polygon = spatial.get_space_polygon_from_context_visible_objects(x, y) - if not space_polygon: + if isinstance(space_polygon, str): return bm = spatial.get_bmesh_from_polygon(space_polygon, h=0) @@ -123,7 +123,7 @@ def regen_selected_covering_object(root: tool.Root, spatial: tool.Spatial) -> No space_polygon = spatial.get_space_polygon_from_context_visible_objects(x, y) - if not space_polygon: + if isinstance(space_polygon, str): return bm = spatial.get_bmesh_from_polygon(space_polygon, h=0) diff --git a/src/bonsai/bonsai/core/spatial.py b/src/bonsai/bonsai/core/spatial.py index 43e680cb74..eff50ec2a3 100644 --- a/src/bonsai/bonsai/core/spatial.py +++ b/src/bonsai/bonsai/core/spatial.py @@ -17,7 +17,7 @@ # along with Bonsai. If not, see . from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Union +from typing import TYPE_CHECKING, Optional, Union, assert_never if TYPE_CHECKING: import bpy @@ -152,9 +152,14 @@ def select_decomposed_element(ifc: tool.Ifc, spatial: tool.Spatial, element: ifc spatial.set_active_object(ifc.get_object(element)) -def generate_space(ifc: tool.Ifc, model: tool.Model, root: tool.Root, spatial: tool.Spatial, type: tool.Type) -> None: +def generate_space( + ifc: tool.Ifc, model: tool.Model, root: tool.Root, spatial: tool.Spatial, type: tool.Type +) -> Union[None, str]: + """ + :return: None if successful, error message string if not. + """ if not root.get_default_container(): - raise NoDefaultContainer() + raise SpaceGenerationError("Please set a default container to create the space in.") active_obj = spatial.get_active_obj() selected_objects = spatial.get_selected_objects() @@ -175,8 +180,17 @@ def generate_space(ifc: tool.Ifc, model: tool.Model, root: tool.Root, spatial: t space_polygon = spatial.get_space_polygon_from_context_visible_objects(x, y) - if not space_polygon: - return + if isinstance(space_polygon, str): + if space_polygon == "NO POLYGONS FOUND": + raise SpaceGenerationError( + "Couldn't find any polygons to form the space shape. Perhaps, RL value need to be adjusted." + ) + elif space_polygon == "NO POLYGON FOR POINT": + raise SpaceGenerationError( + f"Couldn't find any polygons containing the position ({x}, {y}). Perhaps, RL value need to be adjusted." + ) + else: + assert space_polygon bm = spatial.get_bmesh_from_polygon(space_polygon, h=h, polygon_is_si=True) @@ -244,5 +258,5 @@ def set_default_container(spatial: tool.Spatial, container: ifcopenshell.entity_ spatial.set_default_container(container) -class NoDefaultContainer(Exception): +class SpaceGenerationError(Exception): pass diff --git a/src/bonsai/bonsai/tool/spatial.py b/src/bonsai/bonsai/tool/spatial.py index ae8de506ac..51224441ed 100644 --- a/src/bonsai/bonsai/tool/spatial.py +++ b/src/bonsai/bonsai/tool/spatial.py @@ -628,14 +628,20 @@ class Spatial(bonsai.core.tool.Spatial): return False @classmethod - def get_space_polygon_from_context_visible_objects(cls, x: float, y: float) -> Union[shapely.Polygon, None]: + def get_space_polygon_from_context_visible_objects( + cls, x: float, y: float + ) -> Union[shapely.Polygon, Literal["NO POLYGONS FOUND", "NO POLYGON FOR POINT"]]: boundary_lines = cls.get_boundary_lines_from_context_visible_objects() unioned_boundaries = shapely.union_all(shapely.GeometryCollection(boundary_lines)) closed_polygons = shapely.polygonize(unioned_boundaries.geoms) + if not closed_polygons: + return "NO POLYGONS FOUND" space_polygon = None for polygon in closed_polygons.geoms: if shapely.contains_xy(polygon, x, y): space_polygon = shapely.force_3d(polygon) + if space_polygon is None: + return "NO POLYGON FOR POINT" return space_polygon @classmethod