This commit is contained in:
Andrej730
2024-03-29 12:38:37 +05:00
parent 75e6147dbc
commit 232b4ec34d
3 changed files with 61 additions and 26 deletions
@@ -188,7 +188,6 @@ def format_distance(
feet += 1 feet += 1
inches = 0 inches = 0
if not isArea: if not isArea:
add_inches = bool(inches) or not suppress_zero_inches add_inches = bool(inches) or not suppress_zero_inches
tx_dist = "" tx_dist = ""
@@ -299,7 +298,9 @@ def parse_diagram_scale(camera):
return float(numerator) / float(denominator) return float(numerator) / float(denominator)
def ortho_view_frame(camera, margin=0.015): def ortho_view_frame(
camera: bpy.types.Camera, margin: float = 0.015
) -> tuple[float, float, float, float, float, float]:
"""Calculates 2d bounding box of camera view area. """Calculates 2d bounding box of camera view area.
Similar to `bpy.types.Camera.view_frame` Similar to `bpy.types.Camera.view_frame`
+52 -20
View File
@@ -34,9 +34,11 @@ import numpy as np
import blenderbim.core.tool import blenderbim.core.tool
import blenderbim.core.geometry import blenderbim.core.geometry
import blenderbim.tool as tool import blenderbim.tool as tool
import ifcopenshell.geom
import ifcopenshell.util.representation import ifcopenshell.util.representation
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.selector import ifcopenshell.util.selector
import blenderbim.bim.import_ifc
import blenderbim.bim.module.drawing.sheeter as sheeter import blenderbim.bim.module.drawing.sheeter as sheeter
import blenderbim.bim.module.drawing.scheduler as scheduler import blenderbim.bim.module.drawing.scheduler as scheduler
import blenderbim.bim.module.drawing.annotation as annotation import blenderbim.bim.module.drawing.annotation as annotation
@@ -44,7 +46,7 @@ import blenderbim.bim.module.drawing.helper as helper
from blenderbim.bim.module.drawing.data import FONT_SIZES, DecoratorData from blenderbim.bim.module.drawing.data import FONT_SIZES, DecoratorData
from blenderbim.bim.module.drawing.prop import get_diagram_scales, BOX_ALIGNMENT_POSITIONS, ANNOTATION_TYPES_DATA from blenderbim.bim.module.drawing.prop import get_diagram_scales, BOX_ALIGNMENT_POSITIONS, ANNOTATION_TYPES_DATA
from lxml import etree from lxml import etree
from mathutils import Vector from mathutils import Vector, Matrix
from fractions import Fraction from fractions import Fraction
import collections import collections
from typing import Optional, Union from typing import Optional, Union
@@ -366,7 +368,9 @@ class Drawing(blenderbim.core.tool.Drawing):
) )
@classmethod @classmethod
def get_annotation_context(cls, target_view, object_type=None): def get_annotation_context(
cls, target_view: str, object_type: Optional[str] = None
) -> Union[ifcopenshell.entity_instance, None]:
# checking PLAN target view and annotation type that doesn't require 3d # checking PLAN target view and annotation type that doesn't require 3d
if target_view in ("PLAN_VIEW", "REFLECTED_PLAN_VIEW") and object_type not in ( if target_view in ("PLAN_VIEW", "REFLECTED_PLAN_VIEW") and object_type not in (
"FALL", "FALL",
@@ -593,7 +597,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return rel.RelatingProduct return rel.RelatingProduct
@classmethod @classmethod
def import_annotations_in_group(cls, group): def import_annotations_in_group(cls, group: ifcopenshell.entity_instance) -> None:
elements = set( elements = set(
[e for e in cls.get_group_elements(group) if e.is_a("IfcAnnotation") and e.ObjectType != "DRAWING"] [e for e in cls.get_group_elements(group) if e.is_a("IfcAnnotation") and e.ObjectType != "DRAWING"]
) )
@@ -612,7 +616,7 @@ class Drawing(blenderbim.core.tool.Drawing):
# but BIMCameraProperties are only synced with EPsetDrawing at drawing import # but BIMCameraProperties are only synced with EPsetDrawing at drawing import
# therefore camera props can differ from pset if the user changed them from pset. # therefore camera props can differ from pset if the user changed them from pset.
@classmethod @classmethod
def import_drawing(cls, drawing): def import_drawing(cls, drawing: ifcopenshell.entity_instance) -> bpy.types.Object:
settings = ifcopenshell.geom.settings() settings = ifcopenshell.geom.settings()
settings.set(settings.STRICT_TOLERANCE, True) settings.set(settings.STRICT_TOLERANCE, True)
@@ -1051,7 +1055,9 @@ class Drawing(blenderbim.core.tool.Drawing):
shutil.copy(ootb_resource, resource_path) shutil.copy(ootb_resource, resource_path)
@classmethod @classmethod
def get_potential_reference_elements(cls, drawing): def get_potential_reference_elements(
cls, drawing: ifcopenshell.entity_instance
) -> list[ifcopenshell.entity_instance]:
elements = [] elements = []
existing_references = cls.get_group_elements(cls.get_drawing_group(drawing)) existing_references = cls.get_group_elements(cls.get_drawing_group(drawing))
for element in tool.Ifc.get().by_type("IfcAnnotation"): for element in tool.Ifc.get().by_type("IfcAnnotation"):
@@ -1072,7 +1078,9 @@ class Drawing(blenderbim.core.tool.Drawing):
return elements return elements
@classmethod @classmethod
def get_drawing_reference_annotation(cls, drawing, reference_element): def get_drawing_reference_annotation(
cls, drawing: ifcopenshell.entity_instance, reference_element: ifcopenshell.entity_instance
) -> Union[ifcopenshell.entity_instance, bool, None]:
if drawing == reference_element: if drawing == reference_element:
return True return True
for element in cls.get_group_elements(cls.get_drawing_group(drawing)): for element in cls.get_group_elements(cls.get_drawing_group(drawing)):
@@ -1088,7 +1096,12 @@ class Drawing(blenderbim.core.tool.Drawing):
return element return element
@classmethod @classmethod
def generate_reference_annotation(cls, drawing, reference_element, context): def generate_reference_annotation(
cls,
drawing: ifcopenshell.entity_instance,
reference_element: ifcopenshell.entity_instance,
context: ifcopenshell.entity_instance,
) -> ifcopenshell.entity_instance:
if reference_element.is_a("IfcGridAxis"): if reference_element.is_a("IfcGridAxis"):
return cls.generate_grid_axis_reference_annotation(drawing, reference_element, context) return cls.generate_grid_axis_reference_annotation(drawing, reference_element, context)
elif reference_element.is_a("IfcAnnotation") and reference_element.ObjectType == "DRAWING": elif reference_element.is_a("IfcAnnotation") and reference_element.ObjectType == "DRAWING":
@@ -1102,12 +1115,17 @@ class Drawing(blenderbim.core.tool.Drawing):
return cls.generate_storey_annotation(drawing, reference_element, context) return cls.generate_storey_annotation(drawing, reference_element, context)
@classmethod @classmethod
def generate_storey_annotation(cls, drawing, reference_element, context): def generate_storey_annotation(
cls,
drawing: ifcopenshell.entity_instance,
reference_element: ifcopenshell.entity_instance,
context: ifcopenshell.entity_instance,
) -> ifcopenshell.entity_instance:
camera = tool.Ifc.get_object(drawing) camera = tool.Ifc.get_object(drawing)
bounds = helper.ortho_view_frame(camera.data) if camera.data.type == "ORTHO" else None bounds = helper.ortho_view_frame(camera.data) if camera.data.type == "ORTHO" else None
reference_obj = tool.Ifc.get_object(reference_element) reference_obj = tool.Ifc.get_object(reference_element)
def to_camera_coords(camera, reference_obj): def to_camera_coords(camera: bpy.types.Object, reference_obj: bpy.types.Object) -> Matrix:
mat = reference_obj.matrix_world.copy() mat = reference_obj.matrix_world.copy()
xyz = camera.matrix_world.inverted() @ reference_obj.matrix_world.translation xyz = camera.matrix_world.inverted() @ reference_obj.matrix_world.translation
xyz[2] = 0 xyz[2] = 0
@@ -1162,13 +1180,18 @@ class Drawing(blenderbim.core.tool.Drawing):
return element return element
@classmethod @classmethod
def generate_section_reference_annotation(cls, drawing, reference_element, context): def generate_section_reference_annotation(
cls,
drawing: ifcopenshell.entity_instance,
reference_element: ifcopenshell.entity_instance,
context: ifcopenshell.entity_instance,
) -> ifcopenshell.entity_instance:
reference_obj = tool.Ifc.get_object(reference_element) reference_obj = tool.Ifc.get_object(reference_element)
reference_obj.matrix_world reference_obj.matrix_world
camera = tool.Ifc.get_object(drawing) camera = tool.Ifc.get_object(drawing)
bounds = helper.ortho_view_frame(camera.data) if camera.data.type == "ORTHO" else None bounds = helper.ortho_view_frame(camera.data) if camera.data.type == "ORTHO" else None
def to_camera_coords(camera, reference_obj): def to_camera_coords(camera: bpy.types.Object, reference_obj: bpy.types.Object) -> Matrix:
mat = reference_obj.matrix_world.copy() mat = reference_obj.matrix_world.copy()
xyz = camera.matrix_world.inverted() @ reference_obj.matrix_world.translation xyz = camera.matrix_world.inverted() @ reference_obj.matrix_world.translation
xyz[2] = 0 xyz[2] = 0
@@ -1240,12 +1263,17 @@ class Drawing(blenderbim.core.tool.Drawing):
return element return element
@classmethod @classmethod
def generate_elevation_reference_annotation(cls, drawing, reference_element, context): def generate_elevation_reference_annotation(
cls,
drawing: ifcopenshell.entity_instance,
reference_element: ifcopenshell.entity_instance,
context: ifcopenshell.entity_instance,
) -> ifcopenshell.entity_instance:
reference_obj = tool.Ifc.get_object(reference_element) reference_obj = tool.Ifc.get_object(reference_element)
reference_obj.matrix_world reference_obj.matrix_world
camera = tool.Ifc.get_object(drawing) camera = tool.Ifc.get_object(drawing)
def to_camera_coords(camera, reference_obj): def to_camera_coords(camera: bpy.types.Object, reference_obj: bpy.types.Object) -> Matrix:
mat = reference_obj.matrix_world.copy() mat = reference_obj.matrix_world.copy()
xyz = camera.matrix_world.inverted() @ reference_obj.matrix_world.translation xyz = camera.matrix_world.inverted() @ reference_obj.matrix_world.translation
xyz[2] = 0 xyz[2] = 0
@@ -1272,7 +1300,12 @@ class Drawing(blenderbim.core.tool.Drawing):
return element return element
@classmethod @classmethod
def generate_grid_axis_reference_annotation(cls, drawing, reference_element, context): def generate_grid_axis_reference_annotation(
cls,
drawing: ifcopenshell.entity_instance,
reference_element: ifcopenshell.entity_instance,
context: ifcopenshell.entity_instance,
) -> ifcopenshell.entity_instance:
target_view = tool.Drawing.get_drawing_target_view(drawing) target_view = tool.Drawing.get_drawing_target_view(drawing)
camera = tool.Ifc.get_object(drawing) camera = tool.Ifc.get_object(drawing)
@@ -1300,7 +1333,7 @@ class Drawing(blenderbim.core.tool.Drawing):
mesh.to_mesh(obj.data) mesh.to_mesh(obj.data)
return obj return obj
def to_camera_coords(obj, mesh): def to_camera_coords(obj: bpy.types.Object, mesh: bpy.types.Mesh) -> tuple[bpy.types.Object, bpy.types.Mesh]:
mesh.transform(camera.matrix_world.inverted() @ obj.matrix_world) mesh.transform(camera.matrix_world.inverted() @ obj.matrix_world)
obj.matrix_world = camera.matrix_world obj.matrix_world = camera.matrix_world
annotation_offset = mathutils.Vector((0, 0, -camera.data.clip_start - 0.05)) annotation_offset = mathutils.Vector((0, 0, -camera.data.clip_start - 0.05))
@@ -1357,7 +1390,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return element return element
@classmethod @classmethod
def is_perpendicular(cls, a, b): def is_perpendicular(cls, a: bpy.types.Object, b: bpy.types.Object) -> bool:
axes = [mathutils.Vector((1, 0, 0)), mathutils.Vector((0, 1, 0)), mathutils.Vector((0, 0, 1))] axes = [mathutils.Vector((1, 0, 0)), mathutils.Vector((0, 1, 0)), mathutils.Vector((0, 0, 1))]
a_quaternion = a.matrix_world.to_quaternion() a_quaternion = a.matrix_world.to_quaternion()
b_quaternion = b.matrix_world.to_quaternion() b_quaternion = b.matrix_world.to_quaternion()
@@ -1367,7 +1400,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return False return False
@classmethod @classmethod
def get_camera_block(cls, obj): def get_camera_block(cls, obj: bpy.types.Object) -> dict:
raster_x = obj.data.BIMCameraProperties.raster_x raster_x = obj.data.BIMCameraProperties.raster_x
raster_y = obj.data.BIMCameraProperties.raster_y raster_y = obj.data.BIMCameraProperties.raster_y
@@ -1400,7 +1433,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return {"verts": verts, "faces": faces} return {"verts": verts, "faces": faces}
@classmethod @classmethod
def is_intersecting(cls, a, b): def is_intersecting(cls, a: bpy.types.Object, b: bpy.types.Object) -> bool:
a_block = cls.get_camera_block(a) a_block = cls.get_camera_block(a)
a_tree = mathutils.bvhtree.BVHTree.FromPolygons(a_block["verts"], a_block["faces"]) a_tree = mathutils.bvhtree.BVHTree.FromPolygons(a_block["verts"], a_block["faces"])
b_block = cls.get_camera_block(b) b_block = cls.get_camera_block(b)
@@ -1622,7 +1655,7 @@ class Drawing(blenderbim.core.tool.Drawing):
bpy.ops.bim.activate_model() bpy.ops.bim.activate_model()
@classmethod @classmethod
def activate_drawing(cls, camera): def activate_drawing(cls, camera: bpy.types.Object) -> None:
area = tool.Blender.get_view3d_area() area = tool.Blender.get_view3d_area()
is_local_view = area.spaces[0].local_view is not None is_local_view = area.spaces[0].local_view is not None
if is_local_view: if is_local_view:
@@ -1704,7 +1737,6 @@ class Drawing(blenderbim.core.tool.Drawing):
if subcontext: if subcontext:
subcontexts.append(context_filter) subcontexts.append(context_filter)
# switch representations and hide elements without representations # switch representations and hide elements without representations
for element in filtered_elements: for element in filtered_elements:
obj = tool.Ifc.get_object(element) obj = tool.Ifc.get_object(element)
@@ -30,7 +30,7 @@ import functools
import subprocess import subprocess
import sys import sys
import time import time
from typing import Union, Any, Callable from typing import Union, Any, Callable, TypeVar
from . import ifcopenshell_wrapper from . import ifcopenshell_wrapper
from . import settings from . import settings
@@ -40,6 +40,8 @@ try:
except ImportError as e: except ImportError as e:
logging = type("logger", (object,), {"exception": staticmethod(lambda s: print(s))}) logging = type("logger", (object,), {"exception": staticmethod(lambda s: print(s))})
T = TypeVar("T")
def set_derived_attribute(*args): def set_derived_attribute(*args):
raise TypeError("Unable to set derived attribute") raise TypeError("Unable to set derived attribute")
@@ -272,16 +274,16 @@ class entity_instance(object):
""" """
return self.wrapped_data.get_argument_name(attr_idx) return self.wrapped_data.get_argument_name(attr_idx)
def __setattr__(self, key, value): def __setattr__(self, key: str, value: Any) -> None:
index = self.wrapped_data.get_argument_index(key) index = self.wrapped_data.get_argument_index(key)
self[index] = value self[index] = value
def __getitem__(self, key): def __getitem__(self, key: int) -> Any:
if key < 0 or key >= len(self): if key < 0 or key >= len(self):
raise IndexError("Attribute index {} out of range for instance of type {}".format(key, self.is_a())) raise IndexError("Attribute index {} out of range for instance of type {}".format(key, self.is_a()))
return entity_instance.wrap_value(self.wrapped_data.get_argument(key), self.wrapped_data.file) return entity_instance.wrap_value(self.wrapped_data.get_argument(key), self.wrapped_data.file)
def __setitem__(self, idx, value): def __setitem__(self, idx: int, value: T) -> T:
if self.wrapped_data.file and self.wrapped_data.file.transaction: if self.wrapped_data.file and self.wrapped_data.file.transaction:
self.wrapped_data.file.transaction.store_edit(self, idx, value) self.wrapped_data.file.transaction.store_edit(self, idx, value)