mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-11 22:31:55 +00:00
typing
This commit is contained in:
@@ -38,7 +38,7 @@ import bonsai.core.root
|
|||||||
import bonsai.core.drawing
|
import bonsai.core.drawing
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
import bonsai.bim.handler
|
import bonsai.bim.handler
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector, Matrix, Quaternion
|
||||||
from time import time
|
from time import time
|
||||||
from bonsai.bim.ifc import IfcStore
|
from bonsai.bim.ifc import IfcStore
|
||||||
from ifcopenshell.util.shape_builder import ShapeBuilder
|
from ifcopenshell.util.shape_builder import ShapeBuilder
|
||||||
@@ -1399,9 +1399,9 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
self.pset_name = "BBIM_Linked_Aggregate"
|
self.pset_name = "BBIM_Linked_Aggregate"
|
||||||
refresh_start_time = time()
|
refresh_start_time = time()
|
||||||
old_to_new = {}
|
old_to_new = {}
|
||||||
original_names = {}
|
original_names: dict[int, dict[int, str]] = {}
|
||||||
|
|
||||||
def delete_objects(element):
|
def delete_objects(element: ifcopenshell.entity_instance) -> None:
|
||||||
parts = ifcopenshell.util.element.get_parts(element)
|
parts = ifcopenshell.util.element.get_parts(element)
|
||||||
if parts:
|
if parts:
|
||||||
for part in parts:
|
for part in parts:
|
||||||
@@ -1412,7 +1412,7 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
tool.Geometry.delete_ifc_object(tool.Ifc.get_object(element))
|
tool.Geometry.delete_ifc_object(tool.Ifc.get_object(element))
|
||||||
|
|
||||||
def get_original_names(element):
|
def get_original_names(element: ifcopenshell.entity_instance) -> dict[int, dict[int, str]]:
|
||||||
group = [
|
group = [
|
||||||
r.RelatingGroup
|
r.RelatingGroup
|
||||||
for r in getattr(element, "HasAssignments", []) or []
|
for r in getattr(element, "HasAssignments", []) or []
|
||||||
@@ -1429,6 +1429,7 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
if parts:
|
if parts:
|
||||||
for part in parts:
|
for part in parts:
|
||||||
if part.is_a("IfcElementAssembly"):
|
if part.is_a("IfcElementAssembly"):
|
||||||
|
# TODO: missing assignment.
|
||||||
original_names | get_original_names(part)
|
original_names | get_original_names(part)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
@@ -1441,7 +1442,7 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
return original_names
|
return original_names
|
||||||
|
|
||||||
def set_original_name(obj, original_names):
|
def set_original_name(obj: bpy.types.Object, original_names: dict[int, dict[int, str]]) -> None:
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
aggregate = ifcopenshell.util.element.get_aggregate(element)
|
aggregate = ifcopenshell.util.element.get_aggregate(element)
|
||||||
if ifcopenshell.util.element.get_parts(
|
if ifcopenshell.util.element.get_parts(
|
||||||
@@ -1468,7 +1469,7 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
except:
|
except:
|
||||||
return
|
return
|
||||||
|
|
||||||
def get_element_assembly(element):
|
def get_element_assembly(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
if element.is_a("IfcElementAssembly"):
|
if element.is_a("IfcElementAssembly"):
|
||||||
return element
|
return element
|
||||||
elif element.Decomposes:
|
elif element.Decomposes:
|
||||||
@@ -1478,7 +1479,9 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def handle_selection(selected_objs):
|
def handle_selection(
|
||||||
|
selected_objs: list[bpy.types.Object],
|
||||||
|
) -> tuple[list[int], list[ifcopenshell.entity_instance]]:
|
||||||
selected_elements = [tool.Ifc.get_entity(selected_obj) for selected_obj in selected_objs]
|
selected_elements = [tool.Ifc.get_entity(selected_obj) for selected_obj in selected_objs]
|
||||||
if None in selected_elements:
|
if None in selected_elements:
|
||||||
self.report({"INFO"}, "Object has no Ifc Metadata.")
|
self.report({"INFO"}, "Object has no Ifc Metadata.")
|
||||||
@@ -1509,7 +1512,9 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
return list(set(linked_aggregate_groups)), selected_parents
|
return list(set(linked_aggregate_groups)), selected_parents
|
||||||
|
|
||||||
def get_original_matrix(element, base_instance):
|
def get_original_matrix(
|
||||||
|
element: ifcopenshell.entity_instance, base_instance: ifcopenshell.entity_instance
|
||||||
|
) -> tuple[Matrix, tuple[Vector, Quaternion, Vector]]:
|
||||||
selected_obj = tool.Ifc.get_object(base_instance)
|
selected_obj = tool.Ifc.get_object(base_instance)
|
||||||
selected_matrix = selected_obj.matrix_world
|
selected_matrix = selected_obj.matrix_world
|
||||||
object_duplicate = tool.Ifc.get_object(element)
|
object_duplicate = tool.Ifc.get_object(element)
|
||||||
@@ -1517,7 +1522,9 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
return selected_matrix, duplicate_matrix
|
return selected_matrix, duplicate_matrix
|
||||||
|
|
||||||
def set_new_matrix(selected_matrix, duplicate_matrix, old_to_new):
|
def set_new_matrix(
|
||||||
|
selected_matrix: Matrix, duplicate_matrix: tuple[Vector, Quaternion, Vector], old_to_new: dict
|
||||||
|
) -> None:
|
||||||
for old, new in old_to_new.items():
|
for old, new in old_to_new.items():
|
||||||
new_obj = tool.Ifc.get_object(new[0])
|
new_obj = tool.Ifc.get_object(new[0])
|
||||||
new_base_matrix = Matrix.LocRotScale(*duplicate_matrix)
|
new_base_matrix = Matrix.LocRotScale(*duplicate_matrix)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
import bpy
|
import bpy
|
||||||
import copy
|
import copy
|
||||||
import math
|
import math
|
||||||
@@ -46,6 +47,9 @@ class PolylineOperator:
|
|||||||
# TODO Fill doc strings
|
# TODO Fill doc strings
|
||||||
""" """
|
""" """
|
||||||
|
|
||||||
|
number_input: list[str]
|
||||||
|
input_type: tool.Polyline.InputType
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context: bpy.types.Context) -> bool:
|
def poll(cls, context: bpy.types.Context) -> bool:
|
||||||
return context.space_data.type == "VIEW_3D"
|
return context.space_data.type == "VIEW_3D"
|
||||||
@@ -81,7 +85,6 @@ class PolylineOperator:
|
|||||||
self.number_is_negative = False
|
self.number_is_negative = False
|
||||||
self.input_options = ["D", "A", "X", "Y"]
|
self.input_options = ["D", "A", "X", "Y"]
|
||||||
self.input_type = None
|
self.input_type = None
|
||||||
self.input_type = None
|
|
||||||
self.input_value_xy = [None, None]
|
self.input_value_xy = [None, None]
|
||||||
self.input_ui = tool.Polyline.create_input_ui()
|
self.input_ui = tool.Polyline.create_input_ui()
|
||||||
self.is_typing = False
|
self.is_typing = False
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ from mathutils import Vector, Matrix
|
|||||||
from bonsai.bim.module.model.opening import FilledOpeningGenerator
|
from bonsai.bim.module.model.opening import FilledOpeningGenerator
|
||||||
from bonsai.bim.module.model.decorator import PolylineDecorator, ProductDecorator
|
from bonsai.bim.module.model.decorator import PolylineDecorator, ProductDecorator
|
||||||
from bonsai.bim.module.model.polyline import PolylineOperator
|
from bonsai.bim.module.model.polyline import PolylineOperator
|
||||||
from typing import Optional, assert_never, TYPE_CHECKING, get_args, Literal
|
from typing import Optional, assert_never, TYPE_CHECKING, get_args, Literal, Union, Any
|
||||||
from lark import Lark, Transformer
|
from lark import Lark, Transformer
|
||||||
|
|
||||||
|
|
||||||
@@ -330,7 +330,7 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator):
|
|||||||
if relating_type_id:
|
if relating_type_id:
|
||||||
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||||
|
|
||||||
def create_walls_from_polyline(self, context):
|
def create_walls_from_polyline(self, context: bpy.types.Context) -> Union[set[str], None]:
|
||||||
if not self.relating_type:
|
if not self.relating_type:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
@@ -587,7 +587,7 @@ class DumbWallGenerator:
|
|||||||
and bpy.context.scene.grease_pencil.layers[0].active_frame.strokes
|
and bpy.context.scene.grease_pencil.layers[0].active_frame.strokes
|
||||||
)
|
)
|
||||||
|
|
||||||
def derive_from_polyline(self):
|
def derive_from_polyline(self) -> tuple[list[Union[dict[str, Any], None]], bool]:
|
||||||
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
|
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
|
||||||
polyline_points = polyline_data[0].polyline_points if polyline_data else []
|
polyline_points = polyline_data[0].polyline_points if polyline_data else []
|
||||||
is_polyline_closed = False
|
is_polyline_closed = False
|
||||||
@@ -658,7 +658,7 @@ class DumbWallGenerator:
|
|||||||
bpy.context.scene.grease_pencil.layers.remove(layer)
|
bpy.context.scene.grease_pencil.layers.remove(layer)
|
||||||
return objs
|
return objs
|
||||||
|
|
||||||
def create_wall_from_2_points(self, coords, should_round=False):
|
def create_wall_from_2_points(self, coords, should_round=False) -> Union[dict[str, Any], None]:
|
||||||
direction = coords[1] - coords[0]
|
direction = coords[1] - coords[0]
|
||||||
length = direction.length
|
length = direction.length
|
||||||
if round(length, 4) < 0.1:
|
if round(length, 4) < 0.1:
|
||||||
@@ -696,7 +696,7 @@ class DumbWallGenerator:
|
|||||||
def is_near(self, point1, point2):
|
def is_near(self, point1, point2):
|
||||||
return (point1 - point2).length < 0.1
|
return (point1 - point2).length < 0.1
|
||||||
|
|
||||||
def derive_from_cursor(self):
|
def derive_from_cursor(self) -> bpy.types.Object:
|
||||||
RAYCAST_PRECISION = 0.01
|
RAYCAST_PRECISION = 0.01
|
||||||
self.location = bpy.context.scene.cursor.location
|
self.location = bpy.context.scene.cursor.location
|
||||||
if self.container:
|
if self.container:
|
||||||
@@ -746,7 +746,7 @@ class DumbWallGenerator:
|
|||||||
break
|
break
|
||||||
return self.create_wall()
|
return self.create_wall()
|
||||||
|
|
||||||
def create_wall(self):
|
def create_wall(self) -> bpy.types.Object:
|
||||||
props = bpy.context.scene.BIMModelProperties
|
props = bpy.context.scene.BIMModelProperties
|
||||||
ifc_class = self.get_relating_type_class(self.relating_type)
|
ifc_class = self.get_relating_type_class(self.relating_type)
|
||||||
mesh = bpy.data.meshes.new("Dummy")
|
mesh = bpy.data.meshes.new("Dummy")
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ from dataclasses import dataclass
|
|||||||
from lark import Lark, Transformer
|
from lark import Lark, Transformer
|
||||||
from math import degrees, radians, sin, cos, tan
|
from math import degrees, radians, sin, cos, tan
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector, Matrix
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union, Literal
|
||||||
|
|
||||||
|
|
||||||
class Polyline(bonsai.core.tool.Polyline):
|
class Polyline(bonsai.core.tool.Polyline):
|
||||||
@@ -75,6 +75,8 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
else:
|
else:
|
||||||
return Polyline.format_input_ui_units(value)
|
return Polyline.format_input_ui_units(value)
|
||||||
|
|
||||||
|
InputType = Literal["D", "A", "X", "Y", None]
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ToolState:
|
class ToolState:
|
||||||
use_default_container: bool = None
|
use_default_container: bool = None
|
||||||
@@ -83,8 +85,8 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
lock_axis: bool = False
|
lock_axis: bool = False
|
||||||
# angle_axis_start: Vector
|
# angle_axis_start: Vector
|
||||||
# angle_axis_end: Vector
|
# angle_axis_end: Vector
|
||||||
axis_method: str = None
|
axis_method: Literal["X", "Y", "Z", None] = None
|
||||||
plane_method: str = None
|
plane_method: Literal["XY", "XZ", "YZ", None] = None
|
||||||
plane_origin: Vector = Vector((0.0, 0.0, 0.0))
|
plane_origin: Vector = Vector((0.0, 0.0, 0.0))
|
||||||
instructions: str = """TAB: Cycle Input
|
instructions: str = """TAB: Cycle Input
|
||||||
M: Modify Snap Point
|
M: Modify Snap Point
|
||||||
@@ -94,8 +96,8 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
L: Lock axis
|
L: Lock axis
|
||||||
"""
|
"""
|
||||||
snap_info: str = None
|
snap_info: str = None
|
||||||
mode: str = None
|
mode: Literal["Mouse", "Select", "Edit", None] = None
|
||||||
input_type: str = None
|
input_type: "Polyline.InputType" = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_input_ui(cls, init_z: bool = False, init_area: bool = False) -> PolylineUI:
|
def create_input_ui(cls, init_z: bool = False, init_area: bool = False) -> PolylineUI:
|
||||||
@@ -307,7 +309,13 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_input(cls, input_number, input_type) -> tuple[bool, str]:
|
def validate_input(cls, input_number: str, input_type: InputType) -> tuple[bool, str]:
|
||||||
|
"""
|
||||||
|
|
||||||
|
:return: Tuple with a boolean indicating if the input is valid
|
||||||
|
and the final string output.
|
||||||
|
Distance units converted to meters, angles input/output is in degrees.
|
||||||
|
"""
|
||||||
|
|
||||||
grammar_imperial = """
|
grammar_imperial = """
|
||||||
start: (FORMULA dim expr) | dim
|
start: (FORMULA dim expr) | dim
|
||||||
@@ -395,7 +403,7 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
elif op == "/":
|
elif op == "/":
|
||||||
return lambda x: x / value
|
return lambda x: x / value
|
||||||
|
|
||||||
def FORMULA(cls, args):
|
def FORMULA(self, args):
|
||||||
return args[0]
|
return args[0]
|
||||||
|
|
||||||
def start(self, args):
|
def start(self, args):
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ class Snap(bonsai.core.tool.Snap):
|
|||||||
return sorted_intersections
|
return sorted_intersections
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def detect_snapping_points(cls, context, event, objs_2d_bbox, tool_state):
|
def detect_snapping_points(cls, context: bpy.types.Context, event: bpy.types.Event, objs_2d_bbox, tool_state):
|
||||||
rv3d = context.region_data
|
rv3d = context.region_data
|
||||||
space = context.space_data
|
space = context.space_data
|
||||||
mouse_pos = event.mouse_region_x, event.mouse_region_y
|
mouse_pos = event.mouse_region_x, event.mouse_region_y
|
||||||
|
|||||||
Reference in New Issue
Block a user