mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 01:11:40 +00:00
typing
This commit is contained in:
@@ -38,18 +38,17 @@ def depsgraph_update_pre_handler(scene):
|
||||
|
||||
def set_active_camera_resolution(scene: bpy.types.Scene) -> None:
|
||||
props = tool.Drawing.get_document_props()
|
||||
if not scene.camera or "/" not in scene.camera.name or not props.drawings:
|
||||
camera_obj = scene.camera
|
||||
if not camera_obj or "/" not in camera_obj.name or not props.drawings:
|
||||
return
|
||||
assert isinstance(scene.camera.data, bpy.types.Camera)
|
||||
props = scene.camera.data.BIMCameraProperties
|
||||
assert isinstance((camera := camera_obj.data), bpy.types.Camera)
|
||||
props = tool.Drawing.get_camera_props(camera)
|
||||
ortho_scale = max((props.width, props.height))
|
||||
aspect_ratio = props.width / props.height
|
||||
if (scene.camera.data.ortho_scale != ortho_scale) or (
|
||||
scene.render.resolution_x / scene.render.resolution_y != aspect_ratio
|
||||
):
|
||||
scene.camera.data.ortho_scale = ortho_scale
|
||||
if (camera.ortho_scale != ortho_scale) or (scene.render.resolution_x / scene.render.resolution_y != aspect_ratio):
|
||||
camera.ortho_scale = ortho_scale
|
||||
|
||||
diagram_scale = tool.Drawing.get_diagram_scale(scene.camera)
|
||||
diagram_scale = tool.Drawing.get_diagram_scale(camera_obj)
|
||||
scale_ratio = tool.Drawing.get_scale_ratio(diagram_scale["Scale"])
|
||||
|
||||
if props.width > props.height:
|
||||
@@ -61,5 +60,5 @@ def set_active_camera_resolution(scene: bpy.types.Scene) -> None:
|
||||
raster_x = ortho_scale * aspect_ratio * scale_ratio * props.dpi / 0.0254
|
||||
raster_y = ortho_scale * scale_ratio * props.dpi / 0.0254
|
||||
|
||||
scene.render.resolution_x = scene.camera.data.BIMCameraProperties.raster_x = int(raster_x)
|
||||
scene.render.resolution_y = scene.camera.data.BIMCameraProperties.raster_y = int(raster_y)
|
||||
scene.render.resolution_x = props.raster_x = int(raster_x)
|
||||
scene.render.resolution_y = props.raster_y = int(raster_y)
|
||||
|
||||
@@ -413,12 +413,13 @@ def get_project_collection(scene):
|
||||
return colls[0]
|
||||
|
||||
|
||||
def parse_diagram_scale(camera):
|
||||
def parse_diagram_scale(camera: bpy.types.Camera) -> float:
|
||||
"""Returns numeric value of scale"""
|
||||
if camera.BIMCameraProperties.diagram_scale == "CUSTOM":
|
||||
_, fraction = camera.BIMCameraProperties.custom_diagram_scale.split("|")
|
||||
props = tool.Drawing.get_camera_props(camera)
|
||||
if props.diagram_scale == "CUSTOM":
|
||||
_, fraction = props.custom_diagram_scale.split("|")
|
||||
else:
|
||||
_, fraction = camera.BIMCameraProperties.diagram_scale.split("|")
|
||||
_, fraction = props.diagram_scale.split("|")
|
||||
numerator, denominator = fraction.split("/")
|
||||
return float(numerator) / float(denominator)
|
||||
|
||||
@@ -431,12 +432,11 @@ def ortho_view_frame(
|
||||
Similar to `bpy.types.Camera.view_frame`
|
||||
|
||||
:arg camera: camera of drawing
|
||||
:type camera: bpy.types.Camera + BIMCameraProperties
|
||||
:arg margin: margins, in scene units
|
||||
:type margin: float
|
||||
:return: (xmin, xmax, ymin, ymax, zmin, zmax) in local camera coordinates
|
||||
"""
|
||||
aspect = camera.BIMCameraProperties.raster_y / camera.BIMCameraProperties.raster_x
|
||||
props = tool.Drawing.get_camera_props(camera)
|
||||
aspect = props.raster_y / props.raster_x
|
||||
size = camera.ortho_scale
|
||||
hwidth = size * 0.5
|
||||
hheight = size * 0.5 * aspect
|
||||
|
||||
@@ -228,7 +228,9 @@ class CreateDrawing(bpy.types.Operator):
|
||||
if not tool.Drawing.is_drawing_active():
|
||||
cls.poll_message_set("No active drawing.")
|
||||
return False
|
||||
if context.scene.camera.data.BIMCameraProperties.linework_mode == "FREESTYLE" and not hasattr(
|
||||
assert context.scene
|
||||
assert (camera_obj := context.scene.camera)
|
||||
if tool.Drawing.get_camera_props(camera_obj).linework_mode == "FREESTYLE" and not hasattr(
|
||||
context.scene, "svg_export"
|
||||
):
|
||||
cls.poll_message_set(
|
||||
@@ -248,6 +250,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
self.props = tool.Drawing.get_document_props()
|
||||
assert context.scene and context.scene.camera
|
||||
|
||||
active_drawing_id = tool.Blender.get_ifc_definition_id(context.scene.camera)
|
||||
if self.print_all:
|
||||
@@ -262,13 +265,14 @@ class CreateDrawing(bpy.types.Operator):
|
||||
bpy.ops.bim.activate_drawing(drawing=drawing_id, should_view_from_camera=False)
|
||||
|
||||
self.camera = context.scene.camera
|
||||
self.camera_element = tool.Ifc.get_entity(self.camera)
|
||||
assert (camera_element := tool.Ifc.get_entity(self.camera))
|
||||
self.camera_element = camera_element
|
||||
self.camera_document = tool.Drawing.get_drawing_document(self.camera_element)
|
||||
self.file = tool.Ifc.get()
|
||||
|
||||
with profile("Drawing generation process"):
|
||||
with profile("Initialize drawing generation process"):
|
||||
self.cprops = self.camera.data.BIMCameraProperties
|
||||
self.cprops = tool.Drawing.get_camera_props(self.camera)
|
||||
self.drawing = self.file.by_id(drawing_id)
|
||||
self.drawing_name = self.drawing.Name
|
||||
self.metadata = tool.Drawing.get_drawing_metadata(self.camera_element)
|
||||
@@ -297,11 +301,11 @@ class CreateDrawing(bpy.types.Operator):
|
||||
|
||||
with profile("Generate linework"):
|
||||
if tool.Drawing.is_camera_orthographic():
|
||||
if self.camera.data.BIMCameraProperties.linework_mode == "OPENCASCADE":
|
||||
if self.cprops.linework_mode == "OPENCASCADE":
|
||||
linework_svg = self.generate_linework(context)
|
||||
elif self.camera.data.BIMCameraProperties.linework_mode == "FREESTYLE":
|
||||
elif self.cprops.linework_mode == "FREESTYLE":
|
||||
linework_svg = self.generate_freestyle_linework(context)
|
||||
elif self.camera.data.BIMCameraProperties.linework_mode == "FREESTYLE":
|
||||
elif self.cprops.linework_mode == "FREESTYLE":
|
||||
linework_svg = self.generate_freestyle_linework(context)
|
||||
|
||||
with profile("Generate annotation"):
|
||||
@@ -876,19 +880,19 @@ class CreateDrawing(bpy.types.Operator):
|
||||
|
||||
return svg_path
|
||||
|
||||
if self.camera.data.BIMCameraProperties.cut_mode == "BISECT":
|
||||
if self.cprops.cut_mode == "BISECT":
|
||||
self.remove_cut_linework(root)
|
||||
self.generate_bisect_linework(context, root)
|
||||
self.generate_wall_layers(context, root)
|
||||
self.merge_linework_and_add_metadata(root)
|
||||
self.move_elements_to_top(root)
|
||||
elif self.camera.data.BIMCameraProperties.cut_mode == "OPENCASCADE":
|
||||
elif self.cprops.cut_mode == "OPENCASCADE":
|
||||
self.move_projection_to_bottom(root)
|
||||
self.generate_wall_layers(context, root)
|
||||
self.merge_linework_and_add_metadata(root)
|
||||
self.move_elements_to_top(root)
|
||||
|
||||
if self.camera.data.BIMCameraProperties.fill_mode == "SHAPELY":
|
||||
if self.cprops.fill_mode == "SHAPELY":
|
||||
# shapely variant
|
||||
group = root.find("{http://www.w3.org/2000/svg}g")
|
||||
|
||||
@@ -960,7 +964,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
path.set("class", " ".join(list(classes)))
|
||||
group.insert(0, path)
|
||||
|
||||
if self.camera.data.BIMCameraProperties.fill_mode == "SVGFILL":
|
||||
if self.cprops.fill_mode == "SVGFILL":
|
||||
results = etree.tostring(root).decode("utf8")
|
||||
svg_data_1 = results
|
||||
from xml.dom.minidom import parseString
|
||||
@@ -1449,10 +1453,9 @@ class CreateDrawing(bpy.types.Operator):
|
||||
g.set("class", " ".join(list(classes)))
|
||||
group.append(g)
|
||||
|
||||
def drawing_to_model_co(self, x, y):
|
||||
def drawing_to_model_co(self, x: float, y: float) -> Vector:
|
||||
camera_xy = np.array((x, -y)) / self.scale / 1000
|
||||
camera_props = self.camera.data.BIMCameraProperties
|
||||
camera_xy += np.array((camera_props.width / -2, camera_props.height / 2)) # top left offset
|
||||
camera_xy += np.array((self.cprops.width / -2, self.cprops.height / 2)) # top left offset
|
||||
return self.camera.matrix_world @ Vector(camera_xy).to_3d()
|
||||
|
||||
def pythonize(self, arr):
|
||||
@@ -2158,7 +2161,7 @@ class ActivateDrawingBase:
|
||||
|
||||
# Save drawing bounds to the .ifc file
|
||||
camera = context.scene.camera
|
||||
camera_props = camera.data.BIMCameraProperties
|
||||
camera_props = tool.Drawing.get_camera_props(camera)
|
||||
if camera_props.update_representation(camera):
|
||||
bpy.ops.bim.update_representation(obj=camera.name, ifc_representation_class="")
|
||||
# See 6452 and 6478.
|
||||
@@ -2298,7 +2301,8 @@ class ReloadDrawingStyles(bpy.types.Operator):
|
||||
if not DrawingsData.is_loaded:
|
||||
DrawingsData.load()
|
||||
drawing_pset_data = DrawingsData.data["active_drawing_pset_data"]
|
||||
camera_props = context.scene.camera.data.BIMCameraProperties
|
||||
assert context.scene and (camera := context.scene.camera)
|
||||
camera_props = tool.Drawing.get_camera_props(camera)
|
||||
|
||||
# added this part as a temporary fallback
|
||||
# TODO: should remove it a bit later when projects get more accommodated
|
||||
@@ -2365,12 +2369,14 @@ class AddDrawingStyle(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
assert context.scene and (camera_obj := context.scene.camera)
|
||||
props = tool.Drawing.get_document_props()
|
||||
drawing_styles = props.drawing_styles
|
||||
new = drawing_styles.add()
|
||||
# drawing style is saved to ifc on rename
|
||||
new.name = tool.Blender.ensure_unique_name("New Drawing Style", drawing_styles)
|
||||
context.scene.camera.data.BIMCameraProperties.active_drawing_style_index = len(drawing_styles) - 1
|
||||
camera_props = tool.Drawing.get_camera_props(camera_obj)
|
||||
camera_props.active_drawing_style_index = len(drawing_styles) - 1
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -2381,9 +2387,11 @@ class RemoveDrawingStyle(bpy.types.Operator, tool.Ifc.Operator):
|
||||
index: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
assert context.scene and (camera_obj := context.scene.camera)
|
||||
props = tool.Drawing.get_document_props()
|
||||
props.drawing_styles.remove(self.index)
|
||||
context.scene.camera.data.BIMCameraProperties.active_drawing_style_index = max(self.index - 1, 0)
|
||||
camera_props = tool.Drawing.get_camera_props(camera_obj)
|
||||
camera_props.active_drawing_style_index = max(self.index - 1, 0)
|
||||
bpy.ops.bim.save_drawing_styles_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -522,9 +522,34 @@ class BIMCameraProperties(PropertyGroup):
|
||||
exclude_filter_groups: CollectionProperty(type=BIMFilterGroup, name="Exclude Filter")
|
||||
update_props: BoolProperty(name="Enable Props Auto Update", default=True)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
linework_mode: Literal["OPENCASCADE", "FREESTYLE"]
|
||||
fill_mode: Literal["NONE", "SHAPELY", "SVGFILL"]
|
||||
cut_mode: Literal["BISECT", "OPENCASCADE"]
|
||||
has_underlay: bool
|
||||
has_linework: bool
|
||||
has_annotation: bool
|
||||
representation: str
|
||||
view_name: str
|
||||
diagram_scale: str
|
||||
custom_scale_numerator: str
|
||||
custom_scale_denominator: str
|
||||
raster_x: int
|
||||
raster_y: int
|
||||
dpi: int
|
||||
width: float
|
||||
height: float
|
||||
is_nts: bool
|
||||
active_drawing_style_index: int
|
||||
filter_mode: str
|
||||
include_filter_groups: bpy.types.bpy_prop_collection_idprop[BIMFilterGroup]
|
||||
exclude_filter_groups: bpy.types.bpy_prop_collection_idprop[BIMFilterGroup]
|
||||
update_props: bool
|
||||
|
||||
# For now, this JSON dump are all the parameters that determine a camera's "Block representation"
|
||||
# By checking this, you will know whether or not the camera IFC representation needs to be refreshed
|
||||
def update_representation(self, obj):
|
||||
def update_representation(self, obj: bpy.types.Object) -> bool:
|
||||
assert isinstance(obj.data, bpy.types.Camera)
|
||||
representation = json.dumps(
|
||||
{
|
||||
"matrix": [list(x) for x in obj.matrix_world],
|
||||
|
||||
@@ -1192,6 +1192,9 @@ class LinkIfc(bpy.types.Operator, ImportHelper):
|
||||
filepath: str
|
||||
files: list[bpy.types.OperatorFileListElement]
|
||||
directory: str
|
||||
filter_glob: str
|
||||
use_relative_path: bool
|
||||
use_cache: bool
|
||||
|
||||
def draw(self, context):
|
||||
pprops = tool.Project.get_project_props()
|
||||
|
||||
@@ -82,7 +82,7 @@ class Blender(bonsai.core.tool.Blender):
|
||||
@classmethod
|
||||
def activate_camera(cls, obj: bpy.types.Object) -> None:
|
||||
|
||||
area = tool.Blender.get_view3d_area()
|
||||
area = cls.get_view3d_area()
|
||||
is_local_view = area.spaces[0].local_view is not None
|
||||
|
||||
if is_local_view:
|
||||
@@ -206,7 +206,7 @@ class Blender(bonsai.core.tool.Blender):
|
||||
if context is None:
|
||||
context = bpy.context
|
||||
if obj_type == "Object":
|
||||
props = tool.Blender.get_object_bim_props(bpy.data.objects[obj])
|
||||
props = cls.get_object_bim_props(bpy.data.objects[obj])
|
||||
return props.ifc_definition_id
|
||||
elif obj_type == "Material":
|
||||
props = tool.Material.get_material_props()
|
||||
@@ -239,7 +239,7 @@ class Blender(bonsai.core.tool.Blender):
|
||||
|
||||
@classmethod
|
||||
def is_ifc_object(cls, obj: bpy.types.Object) -> bool:
|
||||
props = tool.Blender.get_object_bim_props(obj)
|
||||
props = cls.get_object_bim_props(obj)
|
||||
return bool(props.ifc_definition_id)
|
||||
|
||||
@classmethod
|
||||
@@ -338,7 +338,7 @@ class Blender(bonsai.core.tool.Blender):
|
||||
|
||||
@classmethod
|
||||
def set_viewport_tool(cls, tool_name: str) -> None:
|
||||
with bpy.context.temp_override(**tool.Blender.get_viewport_context()):
|
||||
with bpy.context.temp_override(**cls.get_viewport_context()):
|
||||
bpy.ops.wm.tool_set_by_id(name=tool_name)
|
||||
|
||||
@classmethod
|
||||
@@ -398,7 +398,7 @@ class Blender(bonsai.core.tool.Blender):
|
||||
|
||||
@classmethod
|
||||
def update_viewport(cls) -> None:
|
||||
tool.Blender.get_viewport_context()["area"].tag_redraw()
|
||||
cls.get_viewport_context()["area"].tag_redraw()
|
||||
|
||||
@classmethod
|
||||
def force_depsgraph_update(cls) -> None:
|
||||
@@ -711,7 +711,7 @@ class Blender(bonsai.core.tool.Blender):
|
||||
False if enum is still invalid (as there no enum items)
|
||||
and update callback was not triggered (may need to trigger it manually).
|
||||
"""
|
||||
current_value = tool.Blender.get_enum_safe(props, prop_name)
|
||||
current_value = cls.get_enum_safe(props, prop_name)
|
||||
if current_value is not None:
|
||||
# Value is valid, just trigger the update callback.
|
||||
setattr(props, prop_name, current_value)
|
||||
@@ -958,7 +958,7 @@ class Blender(bonsai.core.tool.Blender):
|
||||
@classmethod
|
||||
def get_layer_collection(cls, collection: bpy.types.Collection) -> Union[bpy.types.LayerCollection, None]:
|
||||
project = tool.Ifc.get_object(tool.Ifc.get().by_type("IfcProject")[0])
|
||||
project_collection = tool.Blender.get_object_bim_props(project).collection
|
||||
project_collection = cls.get_object_bim_props(project).collection
|
||||
for layer_collection in bpy.context.view_layer.layer_collection.children:
|
||||
if layer_collection.collection == project_collection:
|
||||
for layer_collection2 in layer_collection.children:
|
||||
@@ -1564,7 +1564,7 @@ class Blender(bonsai.core.tool.Blender):
|
||||
|
||||
@classmethod
|
||||
def get_user_data_dir(cls) -> Path:
|
||||
props = tool.Blender.get_bim_props()
|
||||
props = cls.get_bim_props()
|
||||
return Path(props.data_dir)
|
||||
|
||||
@classmethod
|
||||
@@ -1649,7 +1649,7 @@ class Blender(bonsai.core.tool.Blender):
|
||||
@classmethod
|
||||
def get_ifc_definition_id(cls, obj: IFC_CONNECTED_TYPE) -> int:
|
||||
if isinstance(obj, bpy.types.Object):
|
||||
return tool.Blender.get_object_bim_props(obj).ifc_definition_id
|
||||
return cls.get_object_bim_props(obj).ifc_definition_id
|
||||
return tool.Style.get_material_style_props(obj).ifc_definition_id
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -55,7 +55,13 @@ from typing import Optional, Union, Iterable, Any, Literal, Sequence, TYPE_CHECK
|
||||
from pathlib import Path
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.drawing.prop import DocProperties, Sheet, BIMAnnotationProperties, BIMTextProperties
|
||||
from bonsai.bim.module.drawing.prop import (
|
||||
DocProperties,
|
||||
Sheet,
|
||||
BIMAnnotationProperties,
|
||||
BIMTextProperties,
|
||||
BIMCameraProperties,
|
||||
)
|
||||
from bonsai.bim.module.drawing.prop import Drawing as DrawingProperties
|
||||
|
||||
|
||||
@@ -106,6 +112,17 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
def get_text_props(cls, obj: bpy.types.Object) -> BIMTextProperties:
|
||||
return obj.BIMTextProperties
|
||||
|
||||
@classmethod
|
||||
def get_camera_props(cls, camera: Union[bpy.types.Object, bpy.types.Camera]) -> BIMCameraProperties:
|
||||
"""
|
||||
:param camera: Camera object or camera.
|
||||
"""
|
||||
if isinstance(camera, bpy.types.Camera):
|
||||
data = camera
|
||||
else:
|
||||
assert isinstance(data := camera.data, bpy.types.Camera)
|
||||
return data.BIMCameraProperties
|
||||
|
||||
@classmethod
|
||||
def canonicalise_class_name(cls, name: str) -> str:
|
||||
return re.sub("[^0-9a-zA-Z]+", "", name)
|
||||
@@ -780,7 +797,7 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
from bonsai.bim.module.drawing.prop import get_diagram_scales
|
||||
|
||||
# Temporarily clear the definition id to prevent prop update callbacks to IFC.
|
||||
camera_props = camera.BIMCameraProperties
|
||||
camera_props = tool.Drawing.get_camera_props(camera)
|
||||
update_props = camera_props.update_props
|
||||
camera_props.update_props = False
|
||||
|
||||
@@ -2199,8 +2216,8 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
return float(numerator) / float(denominator)
|
||||
|
||||
@classmethod
|
||||
def get_diagram_scale(cls, obj: bpy.types.Object) -> dict[str, float]:
|
||||
props = obj.data.BIMCameraProperties
|
||||
def get_diagram_scale(cls, obj: bpy.types.Object) -> dict[str, str]:
|
||||
props = cls.get_camera_props(obj)
|
||||
scale = props.diagram_scale
|
||||
if scale != "CUSTOM":
|
||||
human_scale, scale = scale.split("|")
|
||||
|
||||
@@ -839,13 +839,14 @@ class Loader(bonsai.core.tool.Loader):
|
||||
camera = bpy.data.cameras.new(tool.Loader.get_mesh_name_from_shape(geometry))
|
||||
camera.type = camera_type
|
||||
camera.show_limits = True
|
||||
props = tool.Drawing.get_camera_props(camera)
|
||||
|
||||
if camera_type == "ORTHO":
|
||||
camera.clip_start = 0.002 # Technically 0, but Blender doesn't allow this, so 2mm it is!
|
||||
camera.clip_end = depth
|
||||
|
||||
camera.BIMCameraProperties.width = width
|
||||
camera.BIMCameraProperties.height = height
|
||||
props.width = width
|
||||
props.height = height
|
||||
elif camera_type == "PERSP":
|
||||
abs_min_z = abs(min(z))
|
||||
abs_max_z = abs(max(z))
|
||||
@@ -853,8 +854,8 @@ class Loader(bonsai.core.tool.Loader):
|
||||
camera.clip_end = abs_min_z
|
||||
max_res = 1000
|
||||
|
||||
camera.BIMCameraProperties.width = width
|
||||
camera.BIMCameraProperties.height = height
|
||||
props.width = width
|
||||
props.height = height
|
||||
|
||||
if width > height:
|
||||
fov = 2 * atan(width / (2 * abs_min_z))
|
||||
|
||||
@@ -51,9 +51,11 @@ class Search(bonsai.core.tool.Search):
|
||||
elif module == "diff":
|
||||
return tool.Blender.get_diff_props().filter_groups
|
||||
elif module == "drawing_include":
|
||||
return bpy.context.scene.camera.data.BIMCameraProperties.include_filter_groups
|
||||
assert (scene := bpy.context.scene) and (camera_obj := (scene.camera))
|
||||
return tool.Drawing.get_camera_props(camera_obj).include_filter_groups
|
||||
elif module == "drawing_exclude":
|
||||
return bpy.context.scene.camera.data.BIMCameraProperties.exclude_filter_groups
|
||||
assert (scene := bpy.context.scene) and (camera_obj := (scene.camera))
|
||||
return tool.Drawing.get_camera_props(camera_obj).exclude_filter_groups
|
||||
elif module.startswith("clash"):
|
||||
_, clash_set_index, ab, clash_source_index = module.split("_")
|
||||
props = tool.Clash.get_clash_props()
|
||||
|
||||
@@ -28,6 +28,7 @@ from typing import Union, Optional, Literal, Any, TYPE_CHECKING
|
||||
from ifcopenshell.util.shape_builder import ifc_safe_vector_type, VectorType
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.geometry.helper import Helper
|
||||
|
||||
|
||||
@@ -81,9 +82,11 @@ def add_representation(
|
||||
"""
|
||||
# lazy import Helper to avoid circular import
|
||||
if "Helper" not in globals():
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.geometry.helper import Helper
|
||||
|
||||
globals()["Helper"] = Helper
|
||||
globals()["tool"] = tool
|
||||
|
||||
usecase = Usecase()
|
||||
# TODO: This usecase currently depends on Blender's data model
|
||||
@@ -111,7 +114,7 @@ class Usecase:
|
||||
settings: dict[str, Any]
|
||||
ifc_vertices: list[ifcopenshell.entity_instance]
|
||||
coordinate_offset: Union[npt.NDArray[np.float64], None]
|
||||
geometry: Union[bpy.types.Mesh, bpy.types.Curve]
|
||||
geometry: Union[bpy.types.Mesh, bpy.types.Curve, bpy.types.Camera]
|
||||
blender_object: bpy.types.Object
|
||||
|
||||
def execute(self) -> Union[ifcopenshell.entity_instance, None]:
|
||||
@@ -319,8 +322,10 @@ class Usecase:
|
||||
return self.create_mesh_representation()
|
||||
|
||||
def create_camera_block_representation(self) -> ifcopenshell.entity_instance:
|
||||
raster_x = self.settings["geometry"].BIMCameraProperties.raster_x
|
||||
raster_y = self.settings["geometry"].BIMCameraProperties.raster_y
|
||||
assert isinstance(self.geometry, bpy.types.Camera)
|
||||
props = tool.Drawing.get_camera_props(self.geometry)
|
||||
raster_x = props.raster_x
|
||||
raster_y = props.raster_y
|
||||
|
||||
if self.is_camera_landscape():
|
||||
width = self.settings["geometry"].ortho_scale
|
||||
@@ -347,8 +352,10 @@ class Usecase:
|
||||
)
|
||||
|
||||
def create_camera_pyramid_representation(self) -> ifcopenshell.entity_instance:
|
||||
raster_x = self.settings["geometry"].BIMCameraProperties.raster_x
|
||||
raster_y = self.settings["geometry"].BIMCameraProperties.raster_y
|
||||
assert isinstance(self.geometry, bpy.types.Camera)
|
||||
props = tool.Drawing.get_camera_props(self.geometry)
|
||||
raster_x = props.raster_x
|
||||
raster_y = props.raster_y
|
||||
fov = self.settings["geometry"].angle
|
||||
|
||||
clip_end = self.settings["geometry"].clip_end
|
||||
@@ -389,10 +396,9 @@ class Usecase:
|
||||
)
|
||||
|
||||
def is_camera_landscape(self) -> bool:
|
||||
return (
|
||||
self.settings["geometry"].BIMCameraProperties.raster_x
|
||||
> self.settings["geometry"].BIMCameraProperties.raster_y
|
||||
)
|
||||
assert isinstance(self.geometry, bpy.types.Camera)
|
||||
props = tool.Drawing.get_camera_props(self.geometry)
|
||||
return props.raster_x > props.raster_y
|
||||
|
||||
def create_swept_disk_solid_representation(self) -> ifcopenshell.entity_instance:
|
||||
return self.file.createIfcShapeRepresentation(
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell
|
||||
import datetime
|
||||
import isodate
|
||||
from re import findall
|
||||
@@ -37,7 +38,7 @@ def timedelta2duration(timedelta):
|
||||
return isodate.Duration(**components)
|
||||
|
||||
|
||||
def ifc2datetime(element):
|
||||
def ifc2datetime(element: Union[str, int, ifcopenshell.entity_instance]):
|
||||
if isinstance(element, str) and "P" in element[0:2]: # IfcDuration
|
||||
duration = parse_duration(element)
|
||||
if isinstance(duration, datetime.timedelta):
|
||||
@@ -246,7 +247,7 @@ def parse_duration(value: Union[str, None]) -> Union[datetime.timedelta, None]:
|
||||
return None
|
||||
|
||||
|
||||
def canonicalise_time(time):
|
||||
def canonicalise_time(time: Union[datetime.datetime, None]) -> str:
|
||||
if not time:
|
||||
return "-"
|
||||
return time.strftime("%d/%m/%y")
|
||||
|
||||
Reference in New Issue
Block a user