This commit is contained in:
Andrej730
2024-05-21 11:50:05 +05:00
parent 1b74a99667
commit 221dd9a7a2
12 changed files with 164 additions and 91 deletions
@@ -19,10 +19,13 @@
import bpy
import ifcopenshell
import ifcopenshell.util.cost
import ifcopenshell.util.date
import ifcopenshell.util.element
import ifcopenshell.util.unit
import blenderbim.tool as tool
import blenderbim.bim.schema
from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
from typing import Any
def refresh():
@@ -34,6 +37,7 @@ def refresh():
class CostSchedulesData:
data = {}
is_loaded = False
_cost_values: dict[int, dict[str, Any]]
@classmethod
def load(cls):
@@ -44,6 +44,7 @@ from bpy.types import SpaceView3D
from bpy.props import FloatProperty
from bpy_extras.object_utils import AddObjectHelper, object_data_add
from gpu_extras.batch import batch_for_shader
from typing import Union, Optional, Any
class AddFilledOpening(bpy.types.Operator, tool.Ifc.Operator):
@@ -59,7 +60,12 @@ class AddFilledOpening(bpy.types.Operator, tool.Ifc.Operator):
class FilledOpeningGenerator:
def generate(self, filling_obj, voided_obj, target=None):
def generate(
self,
filling_obj: Union[bpy.types.Object, None],
voided_obj: Union[bpy.types.Object, None],
target: Optional[Vector] = None,
) -> None:
props = bpy.context.scene.BIMModelProperties
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
@@ -187,7 +193,7 @@ class FilledOpeningGenerator:
should_sync_changes_first=False,
)
def regenerate_from_type(self, usecase_path, ifc_file, settings):
def regenerate_from_type(self, usecase_path: str, ifc_file: ifcopenshell.file, settings: dict[str, Any]) -> None:
relating_type = settings["relating_type"]
for related_object in settings["related_objects"]:
@@ -252,7 +258,9 @@ class FilledOpeningGenerator:
should_sync_changes_first=False,
)
def generate_opening_from_filling(self, filling, filling_obj):
def generate_opening_from_filling(
self, filling: ifcopenshell.entity_instance, filling_obj: bpy.types.Object
) -> ifcopenshell.entity_instance:
# Since openings are reused later, we give a default thickness of 1.2m
# which should cover the majority of curved, or super thick walls.
thickness = 1.2
@@ -346,7 +354,9 @@ class FilledOpeningGenerator:
return True
return False
def get_existing_opening_occurrence_if_any(self, filling):
def get_existing_opening_occurrence_if_any(
self, filling: ifcopenshell.entity_instance
) -> Union[ifcopenshell.entity_instance, None]:
filling_type = ifcopenshell.util.element.get_type(filling)
if filling_type:
filling_occurrences = ifcopenshell.util.element.get_types(filling_type)
@@ -21,6 +21,7 @@ import bpy
import pathlib
import ifcopenshell
import ifcopenshell.util.attribute
import ifcopenshell.util.doc
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore
+16 -8
View File
@@ -109,7 +109,9 @@ def edit_cost_item(ifc: tool.Ifc, cost: tool.Cost):
cost.load_cost_schedule_tree()
def assign_cost_item_type(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item, prop_name):
def assign_cost_item_type(
ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item: ifcopenshell.entity_instance, prop_name
):
product_types = spatial.get_selected_product_types()
[
ifc.run("control.assign_control", relating_control=cost_item, related_object=product_type)
@@ -118,7 +120,9 @@ def assign_cost_item_type(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial,
cost.load_cost_item_types(cost_item)
def unassign_cost_item_type(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item, product_types):
def unassign_cost_item_type(
ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial, cost_item: ifcopenshell.entity_instance, product_types
):
if not product_types:
product_types = spatial.get_selected_product_types()
[
@@ -133,7 +137,9 @@ def load_cost_item_types(cost: tool.Cost):
cost.load_cost_item_types(cost_item)
def assign_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, cost_item, related_object_type, prop_name):
def assign_cost_item_quantity(
ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance, related_object_type, prop_name
):
products = cost.get_products(related_object_type)
if products:
ifc.run("cost.assign_cost_item_quantity", cost_item=cost_item, products=products, prop_name=prop_name)
@@ -159,7 +165,7 @@ def load_cost_item_resource_quantities(cost: tool.Cost):
cost.load_cost_item_quantity_assignments(cost_item, related_object_type="RESOURCE")
def assign_cost_value(ifc: tool.Ifc, cost_item, cost_rate):
def assign_cost_value(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, cost_rate):
ifc.run("cost.assign_cost_value", cost_item=cost_item, cost_rate=cost_rate)
@@ -167,7 +173,7 @@ def load_schedule_of_rates(cost: tool.Cost, schedule_of_rates):
cost.load_schedule_of_rates_tree(schedule_of_rates)
def unassign_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, cost_item, products):
def unassign_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance, products):
ifc.run("cost.unassign_cost_item_quantity", cost_item=cost_item, products=products)
cost.load_cost_item_quantities()
@@ -180,11 +186,11 @@ def enable_editing_cost_item_values(cost: tool.Cost, cost_item: ifcopenshell.ent
cost.enable_editing_cost_item_values(cost_item)
def add_cost_item_quantity(ifc: tool.Ifc, cost_item, ifc_class):
def add_cost_item_quantity(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, ifc_class):
ifc.run("cost.add_cost_item_quantity", cost_item=cost_item, ifc_class=ifc_class)
def remove_cost_item_quantity(ifc: tool.Ifc, cost_item, physical_quantity):
def remove_cost_item_quantity(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, physical_quantity):
ifc.run("cost.remove_cost_item_quantity", cost_item=cost_item, physical_quantity=physical_quantity)
@@ -288,7 +294,9 @@ def export_cost_schedules(cost: tool.Cost, filepath, format, cost_schedule=None)
return cost.export_cost_schedules(filepath, format, cost_schedule)
def clear_cost_item_assignments(ifc: tool.Ifc, cost: tool.Cost, cost_item, related_object_type):
def clear_cost_item_assignments(
ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance, related_object_type
):
products = cost.get_cost_item_assignments(cost_item, filter_by_type=related_object_type)
if products:
ifc.run("cost.unassign_cost_item_quantity", cost_item=cost_item, products=products)
+71 -35
View File
@@ -16,36 +16,44 @@
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
from pathlib import Path
import ifcopenshell
from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
import bpy
import ifcopenshell
import blenderbim.tool as tool
def enable_editing_text(drawing, obj=None):
def enable_editing_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.enable_editing_text(obj)
drawing.import_text_attributes(obj)
def disable_editing_text(drawing, obj=None):
def disable_editing_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.disable_editing_text(obj)
def edit_text(drawing, obj=None):
def edit_text(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.synchronise_ifc_and_text_attributes(obj)
drawing.update_text_size_pset(obj)
drawing.update_text_value(obj)
drawing.disable_editing_text(obj)
def enable_editing_assigned_product(drawing, obj=None):
def enable_editing_assigned_product(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.enable_editing_assigned_product(obj)
drawing.import_assigned_product(obj)
def disable_editing_assigned_product(drawing, obj=None):
def disable_editing_assigned_product(drawing: tool.Drawing, obj: bpy.types.Object) -> None:
drawing.disable_editing_assigned_product(obj)
def edit_assigned_product(ifc, drawing, obj=None, product=None):
def edit_assigned_product(
ifc: tool.Ifc, drawing: tool.Drawing, obj: bpy.types.Object, product: Optional[ifcopenshell.entity_instance] = None
) -> None:
element = ifc.get_entity(obj)
existing_product = drawing.get_assigned_product(element)
if existing_product != product:
@@ -58,16 +66,16 @@ def edit_assigned_product(ifc, drawing, obj=None, product=None):
drawing.disable_editing_assigned_product(obj)
def load_sheets(drawing):
def load_sheets(drawing: tool.Drawing) -> None:
drawing.import_sheets()
drawing.enable_editing_sheets()
def disable_editing_sheets(drawing):
def disable_editing_sheets(drawing: tool.Drawing) -> None:
drawing.disable_editing_sheets()
def add_sheet(ifc, drawing, titleblock: ifcopenshell.entity_instance):
def add_sheet(ifc: tool.Ifc, drawing, titleblock: ifcopenshell.entity_instance) -> None:
sheet = ifc.run("document.add_information")
layout = ifc.run("document.add_reference", information=sheet)
titleblock_reference = ifc.run("document.add_reference", information=sheet)
@@ -93,7 +101,7 @@ def add_sheet(ifc, drawing, titleblock: ifcopenshell.entity_instance):
drawing.import_sheets()
def regenerate_sheet(drawing, sheet=None):
def regenerate_sheet(drawing: tool.Drawing, sheet: ifcopenshell.entity_instance) -> None:
titleblock_uri = drawing.get_document_uri(sheet, "TITLEBLOCK")
drawing.create_svg_sheet(sheet, drawing.sanitise_filename(Path(titleblock_uri).stem))
try:
@@ -104,11 +112,11 @@ def regenerate_sheet(drawing, sheet=None):
drawing.delete_file(path_layout)
def open_sheet(drawing, sheet=None):
def open_sheet(drawing: tool.Drawing, sheet: ifcopenshell.entity_instance) -> None:
drawing.open_layout_svg(drawing.get_document_uri(sheet, "LAYOUT"))
def remove_sheet(ifc, drawing, sheet=None):
def remove_sheet(ifc: tool.Ifc, drawing: tool.Drawing, sheet: ifcopenshell.entity_instance) -> None:
for reference in drawing.get_document_references(sheet):
if drawing.get_reference_description(reference) in ("LAYOUT", "SHEET", "REVISION", "RASTER"):
uri = ifc.resolve_uri(drawing.get_document_uri(reference))
@@ -118,7 +126,7 @@ def remove_sheet(ifc, drawing, sheet=None):
drawing.import_sheets()
def rename_sheet(ifc, drawing, sheet: ifcopenshell.entity_instance, identification: str, name: str) -> None:
def rename_sheet(ifc: tool.Ifc, drawing, sheet: ifcopenshell.entity_instance, identification: str, name: str) -> None:
if ifc.get_schema() == "IFC2X3":
attributes = {"DocumentId": identification, "Name": name}
else:
@@ -144,30 +152,32 @@ def rename_sheet(ifc, drawing, sheet: ifcopenshell.entity_instance, identificati
drawing.move_file(old_location, ifc.resolve_uri(new_location))
def rename_reference(ifc, drawing, reference=None, identification=None):
def rename_reference(
ifc: tool.Ifc, drawing: tool.Drawing, reference: ifcopenshell.entity_instance, identification: str
) -> None:
attributes = drawing.generate_reference_attributes(reference, Identification=identification)
ifc.run("document.edit_reference", reference=reference, attributes=attributes)
def load_schedules(drawing):
def load_schedules(drawing: tool.Drawing) -> None:
drawing.import_documents("SCHEDULE")
drawing.enable_editing_schedules()
def load_references(drawing):
def load_references(drawing: tool.Drawing) -> None:
drawing.import_documents("REFERENCE")
drawing.enable_editing_references()
def disable_editing_schedules(drawing):
def disable_editing_schedules(drawing: tool.Drawing) -> None:
drawing.disable_editing_schedules()
def disable_editing_references(drawing):
def disable_editing_references(drawing: tool.Drawing) -> None:
drawing.disable_editing_references()
def add_document(ifc, drawing, document_type, uri=None):
def add_document(ifc: tool.Ifc, drawing: tool.Drawing, document_type: tool.Drawing.DOCUMENT_TYPE, uri: str) -> None:
document = ifc.run("document.add_information")
reference = ifc.run("document.add_reference", information=document)
name = drawing.get_path_filename(uri)
@@ -180,34 +190,43 @@ def add_document(ifc, drawing, document_type, uri=None):
drawing.import_documents(document_type)
def remove_document(ifc, drawing, document_type, document=None):
def remove_document(
ifc: tool.Ifc,
drawing: tool.Drawing,
document_type: tool.Drawing.DOCUMENT_TYPE,
document: ifcopenshell.entity_instance,
) -> None:
ifc.run("document.remove_information", information=document)
drawing.import_documents(document_type)
def open_schedule(drawing, schedule=None):
def open_schedule(drawing: tool.Drawing, schedule: ifcopenshell.entity_instance) -> None:
drawing.open_spreadsheet(drawing.get_document_uri(schedule))
def open_reference(drawing, reference=None):
def open_reference(drawing: tool.Drawing, reference: ifcopenshell.entity_instance) -> None:
drawing.open_svg(drawing.get_document_uri(reference))
def update_document_name(ifc, drawing, document=None, name=None):
def update_document_name(
ifc: tool.Ifc, drawing: tool.Drawing, document: ifcopenshell.entity_instance, name=None
) -> None:
if drawing.get_name(document) != name:
ifc.run("document.edit_information", information=document, attributes={"Name": name})
def load_drawings(drawing):
def load_drawings(drawing: tool.Drawing) -> None:
drawing.import_drawings()
drawing.enable_editing_drawings()
def disable_editing_drawings(drawing):
def disable_editing_drawings(drawing: tool.Drawing) -> None:
drawing.disable_editing_drawings()
def add_drawing(ifc, collector, drawing, target_view=None, location_hint=None):
def add_drawing(
ifc: tool.Ifc, collector: tool.Collector, drawing: tool.Drawing, target_view=None, location_hint=None
) -> None:
drawing_name = drawing.ensure_unique_drawing_name(drawing.generate_drawing_name(target_view, location_hint))
drawing_matrix = drawing.generate_drawing_matrix(target_view, location_hint)
camera = drawing.create_camera(drawing_name, drawing_matrix, location_hint)
@@ -265,7 +284,12 @@ def add_drawing(ifc, collector, drawing, target_view=None, location_hint=None):
drawing.import_drawings()
def duplicate_drawing(ifc, drawing_tool, drawing=None, should_duplicate_annotations=False):
def duplicate_drawing(
ifc: tool.Ifc,
drawing_tool: tool.Drawing,
drawing: ifcopenshell.entity_instance,
should_duplicate_annotations: bool = False,
) -> ifcopenshell.entity_instance:
drawing_name = drawing_tool.ensure_unique_drawing_name(drawing_tool.get_name(drawing))
new_drawing = ifc.run("root.copy_class", product=drawing)
drawing_tool.copy_representation(drawing, new_drawing)
@@ -302,7 +326,7 @@ def duplicate_drawing(ifc, drawing_tool, drawing=None, should_duplicate_annotati
return new_drawing
def remove_drawing(ifc, drawing_tool, drawing=None):
def remove_drawing(ifc: tool.Ifc, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance) -> None:
if drawing_tool.is_active_drawing(drawing):
drawing_tool.run_drawing_activate_model()
@@ -330,7 +354,9 @@ def remove_drawing(ifc, drawing_tool, drawing=None):
drawing_tool.import_drawings()
def update_drawing_name(ifc, drawing_tool, drawing=None, name=None):
def update_drawing_name(
ifc: tool.Ifc, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance, name=None
) -> None:
if drawing_tool.get_name(drawing) != name:
ifc.run("attribute.edit_attributes", product=drawing, attributes={"Name": name})
group = drawing_tool.get_drawing_group(drawing)
@@ -364,7 +390,13 @@ def update_drawing_name(ifc, drawing_tool, drawing=None, name=None):
drawing_tool.import_sheets()
def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None):
def add_annotation(
ifc: tool.Ifc,
collector: tool.Collector,
drawing_tool: tool.Drawing,
drawing: ifcopenshell.entity_instance,
object_type: str,
) -> None:
target_view = drawing_tool.get_drawing_target_view(drawing)
context = drawing_tool.get_annotation_context(target_view, object_type)
if not context:
@@ -387,12 +419,14 @@ def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None)
drawing_tool.enable_editing(obj)
def build_schedule(drawing, schedule=None):
def build_schedule(drawing: tool.Drawing, schedule: ifcopenshell.entity_instance) -> None:
drawing.create_svg_schedule(schedule)
drawing.open_svg(drawing.get_path_with_ext(drawing.get_document_uri(schedule), "svg"))
def sync_references(ifc, collector, drawing_tool, drawing=None):
def sync_references(
ifc: tool.Ifc, collector: tool.Collector, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance
) -> None:
if not drawing_tool.has_annotation(drawing):
return
@@ -437,11 +471,13 @@ def sync_references(ifc, collector, drawing_tool, drawing=None):
drawing_tool.sync_object_representation(reference_obj)
def select_assigned_product(drawing, context):
def select_assigned_product(drawing: tool.Drawing, context: bpy.types.Context) -> None:
drawing.select_assigned_product(context)
def activate_drawing_view(ifc, blender, drawing_tool, drawing):
def activate_drawing_view(
ifc: tool.Ifc, blender: tool.Blender, drawing_tool: tool.Drawing, drawing: ifcopenshell.entity_instance
) -> None:
camera = ifc.get_object(drawing)
if not camera:
camera = drawing_tool.import_drawing(drawing)
+1 -1
View File
@@ -468,7 +468,7 @@ class Blender(blenderbim.core.tool.Blender):
active_object.select_set(True)
@classmethod
def enum_property_has_valid_index(cls, props, prop_name: str, enum_items: tuple) -> bool:
def enum_property_has_valid_index(cls, props: bpy.types.PropertyGroup, prop_name: str, enum_items: tuple) -> bool:
"""method created for readibility and to avoid console warnings like
`pyrna_enum_to_py: current value '17' matches no enum in 'BIMModelProperties', '', 'relating_type_id'`
"""
+3 -1
View File
@@ -1,11 +1,13 @@
import os
import bpy
import blenderbim.core.tool
import blenderbim.tool as tool
import ifcopenshell.util.date
import ifcopenshell.util.cost
import ifcopenshell.util.unit
import blenderbim.bim.helper
import json
from typing import Optional
class Cost(blenderbim.core.tool.Cost):
@@ -163,7 +165,7 @@ class Cost(blenderbim.core.tool.Cost):
return
@classmethod
def load_cost_item_types(cls, cost_item=None):
def load_cost_item_types(cls, cost_item: Optional[ifcopenshell.entity_instance] = None) -> None:
if not cost_item:
cost_item = cls.get_highlighted_cost_item()
if not cost_item:
+31 -27
View File
@@ -51,11 +51,14 @@ from blenderbim.bim.module.drawing.prop import get_diagram_scales, BOX_ALIGNMENT
from lxml import etree
from mathutils import Vector, Matrix
from fractions import Fraction
from typing import Optional, Union, Iterable, Any
from typing import Optional, Union, Iterable, Any, Literal
from pathlib import Path
class Drawing(blenderbim.core.tool.Drawing):
ANNOTATION_DATA_TYPE = Literal["empty", "curve", "mesh"]
DOCUMENT_TYPE = Literal["SCHEDULE", "REFERENCE"]
@classmethod
def canonicalise_class_name(cls, name):
return re.sub("[^0-9a-zA-Z]+", "", name)
@@ -68,11 +71,11 @@ class Drawing(blenderbim.core.tool.Drawing):
)
@classmethod
def get_annotation_data_type(cls, object_type):
def get_annotation_data_type(cls, object_type: str) -> ANNOTATION_DATA_TYPE:
return ANNOTATION_TYPES_DATA[object_type][3]
@classmethod
def create_annotation_object(cls, drawing, object_type):
def create_annotation_object(cls, drawing: ifcopenshell.entity_instance, object_type: str) -> bpy.types.Object:
data_type = cls.get_annotation_data_type(object_type)
obj = annotation.Annotator.get_annotation_obj(drawing, object_type, data_type)
if object_type == "FILL_AREA":
@@ -298,15 +301,15 @@ class Drawing(blenderbim.core.tool.Drawing):
bpy.context.scene.DocProperties.is_editing_sheets = False
@classmethod
def disable_editing_text(cls, obj):
def disable_editing_text(cls, obj: bpy.types.Object) -> None:
obj.BIMTextProperties.is_editing = False
@classmethod
def disable_editing_assigned_product(cls, obj):
def disable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
obj.BIMAssignedProductProperties.is_editing_product = False
@classmethod
def enable_editing(cls, obj):
def enable_editing(cls, obj: bpy.types.Object) -> None:
bpy.ops.object.select_all(action="DESELECT")
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
@@ -330,11 +333,11 @@ class Drawing(blenderbim.core.tool.Drawing):
bpy.context.scene.DocProperties.is_editing_sheets = True
@classmethod
def enable_editing_text(cls, obj):
def enable_editing_text(cls, obj: bpy.types.Object) -> None:
obj.BIMTextProperties.is_editing = True
@classmethod
def enable_editing_assigned_product(cls, obj):
def enable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
obj.BIMAssignedProductProperties.is_editing_product = True
@classmethod
@@ -428,7 +431,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return location
@classmethod
def get_path_filename(cls, path):
def get_path_filename(cls, path: str) -> str:
return os.path.splitext(os.path.basename(path))[0]
@classmethod
@@ -483,7 +486,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return ""
@classmethod
def get_name(cls, element):
def get_name(cls, element: ifcopenshell.entity_instance) -> Union[str, None]:
return element.Name
@classmethod
@@ -563,7 +566,7 @@ class Drawing(blenderbim.core.tool.Drawing):
ifcopenshell.util.element.remove_deep2(ifc_file, literal)
@classmethod
def synchronise_ifc_and_text_attributes(cls, obj):
def synchronise_ifc_and_text_attributes(cls, obj: bpy.types.Object) -> None:
literals = cls.get_text_literal(obj, return_list=True)
literals_attributes = cls.export_text_literal_attributes(obj)
defined_ifc_ids = [l.ifc_definition_id for l in obj.BIMTextProperties.literals]
@@ -784,7 +787,7 @@ class Drawing(blenderbim.core.tool.Drawing):
new.ifc_definition_id = drawing.id() # Last, to prevent unnecessary prop callbacks
@classmethod
def import_documents(cls, document_type):
def import_documents(cls, document_type: DOCUMENT_TYPE) -> None:
dprops = bpy.context.scene.DocProperties
if document_type == "SCHEDULE":
documents_collection = dprops.schedules
@@ -845,7 +848,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return next(s for s in props.sheets[: props.active_sheet_index + 1][::-1] if s.is_sheet)
@classmethod
def import_text_attributes(cls, obj):
def import_text_attributes(cls, obj: bpy.types.Object) -> None:
props = obj.BIMTextProperties
props.literals.clear()
@@ -863,7 +866,7 @@ class Drawing(blenderbim.core.tool.Drawing):
props.font_size = str(text_data["FontSize"])
@classmethod
def import_assigned_product(cls, obj):
def import_assigned_product(cls, obj: bpy.types.Object) -> None:
element = tool.Ifc.get_entity(obj)
product = cls.get_assigned_product(element)
if product:
@@ -934,7 +937,7 @@ class Drawing(blenderbim.core.tool.Drawing):
bpy.context.scene.DocProperties.should_draw_decorations = True
@classmethod
def update_text_value(cls, obj):
def update_text_value(cls, obj: bpy.types.Object) -> None:
props = obj.BIMTextProperties
literals = cls.get_text_literal(obj, return_list=True)
cls.import_text_attributes(obj)
@@ -943,7 +946,7 @@ class Drawing(blenderbim.core.tool.Drawing):
props.literals[i].value = cls.replace_text_literal_variables(literal.Literal, product)
@classmethod
def update_text_size_pset(cls, obj):
def update_text_size_pset(cls, obj: bpy.types.Object) -> None:
"""updates pset `EPset_Annotation.Classes` value
based on current font size from `obj.BIMTextProperties.font_size`
"""
@@ -1522,7 +1525,7 @@ class Drawing(blenderbim.core.tool.Drawing):
tool.Geometry.record_object_position(obj)
@classmethod
def get_document_references(cls, document):
def get_document_references(cls, document: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
if tool.Ifc.get_schema() == "IFC2X3":
return document.DocumentReferences or []
return document.HasDocumentReferences or []
@@ -1553,7 +1556,9 @@ class Drawing(blenderbim.core.tool.Drawing):
return reference.Description
@classmethod
def generate_reference_attributes(cls, reference: ifcopenshell.entity_instance, **attributes: Any) -> dict[str, Any]:
def generate_reference_attributes(
cls, reference: ifcopenshell.entity_instance, **attributes: Any
) -> dict[str, Any]:
"""will automatically convert attributes below for IFC2X3 compatibility:
- Identification -> ItemReference
@@ -1635,23 +1640,22 @@ class Drawing(blenderbim.core.tool.Drawing):
base_elements = set(ifc_file.by_type("IfcElement") + ifc_file.by_type("IfcSpatialElement"))
elements = {e for e in (elements & base_elements) if e.is_a() != "IfcSpace"}
updated_set = set()
for i in elements:
# exclude annotations to avoid including annotations from other drawings
if not i.is_a("IfcAnnotation"):
if not i.is_a("IfcAnnotation"):
updated_set.add(i)
#add aggregate too, if element is host by one
# add aggregate too, if element is host by one
if i.Decomposes:
aggregate = i.Decomposes[0].RelatingObject
#remove IfcProject for class iterator. See https://github.com/IfcOpenShell/IfcOpenShell/issues/4361#issuecomment-2081223615
if not aggregate.is_a("IfcProject"):
# remove IfcProject for class iterator. See https://github.com/IfcOpenShell/IfcOpenShell/issues/4361#issuecomment-2081223615
if not aggregate.is_a("IfcProject"):
updated_set.add(aggregate)
# After the iteration is complete, update elements with updated set
# After the iteration is complete, update elements with updated set
elements.update(updated_set)
# add annotations from the current drawing
annotations = tool.Drawing.get_group_elements(tool.Drawing.get_drawing_group(drawing))
elements.update(annotations)
@@ -1694,7 +1698,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return reference.ReferencedDocument
@classmethod
def select_assigned_product(cls, context):
def select_assigned_product(cls, context: bpy.types.Context) -> None:
obj = context.active_object
element = tool.Ifc.get_entity(obj)
product = cls.get_assigned_product(element)
@@ -1713,7 +1717,7 @@ class Drawing(blenderbim.core.tool.Drawing):
return True if (camera and camera.data.type == "ORTHO") else False
@classmethod
def is_active_drawing(cls, drawing):
def is_active_drawing(cls, drawing: ifcopenshell.entity_instance) -> bool:
return drawing.id() == bpy.context.scene.DocProperties.active_drawing_id
@classmethod
+1 -1
View File
@@ -90,7 +90,7 @@ class Geometry(blenderbim.core.tool.Geometry):
bpy.data.meshes.remove(data)
@classmethod
def delete_ifc_object(cls, obj):
def delete_ifc_object(cls, obj: bpy.types.Object) -> None:
element = tool.Ifc.get_entity(obj)
if not element:
return
+2 -1
View File
@@ -23,6 +23,7 @@ import collections
import collections.abc
import numpy as np
import ifcopenshell
import ifcopenshell.util.element
import ifcopenshell.util.unit
import ifcopenshell.util.placement
import ifcopenshell.util.representation
@@ -468,7 +469,7 @@ class Model(blenderbim.core.tool.Model):
has_deleted_opening = True
@classmethod
def get_material_layer_parameters(cls, element):
def get_material_layer_parameters(cls, element: ifcopenshell.entity_instance) -> dict[str, Any]:
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
layer_set_direction = "AXIS2"
offset = 0.0
+3 -2
View File
@@ -31,6 +31,7 @@ import json
from math import pi
from mathutils import Vector, Matrix
from shapely import Polygon, MultiPolygon
from typing import Generator
class Spatial(blenderbim.core.tool.Spatial):
@@ -187,14 +188,14 @@ class Spatial(blenderbim.core.tool.Spatial):
]
@classmethod
def get_selected_products(cls):
def get_selected_products(cls) -> Generator[ifcopenshell.entity_instance, None, None]:
for obj in bpy.context.selected_objects:
entity = tool.Ifc.get_entity(obj)
if entity and entity.is_a("IfcProduct"):
yield entity
@classmethod
def get_selected_product_types(cls):
def get_selected_product_types(cls) -> Generator[ifcopenshell.entity_instance, None, None]:
for obj in bpy.context.selected_objects:
entity = tool.Ifc.get_entity(obj)
if entity and entity.is_a("IfcTypeProduct"):
@@ -17,13 +17,15 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import lark
import ifcopenshell
from typing import Optional, Union
arithmetic_operator_symbols = {"ADD": "+", "DIVIDE": "/", "MULTIPLY": "*", "SUBTRACT": "-"}
symbol_arithmetic_operators = {"+": "ADD", "/": "DIVIDE", "*": "MULTIPLY", "-": "SUBTRACT"}
def get_primitive_applied_value(applied_value):
def get_primitive_applied_value(applied_value: Union[ifcopenshell.entity_instance, float, None]) -> float:
if not applied_value:
return 0.0
elif isinstance(applied_value, float):
@@ -32,17 +34,21 @@ def get_primitive_applied_value(applied_value):
return applied_value.wrappedValue
elif applied_value.is_a("IfcMeasureWithUnit"):
return applied_value.ValueComponent
assert False, "Applied value {applied_value} not implemented"
assert False, f"Applied value {applied_value} not implemented"
def get_total_quantity(root_element):
def get_total_quantity(root_element: ifcopenshell.entity_instance) -> Union[float, None]:
# 3 IfcPhysicalQuantity Value
if root_element.is_a("IfcCostItem"):
return sum([q[3] for q in root_element.CostQuantities or []]) or None
elif root_element.is_a("IfcConstructionResource"):
return root_element.BaseQuantity[3] if root_element.BaseQuantity else 1.0
quantity = root_element.BaseQuantity
return quantity[3] if quantity else 1.0
def calculate_applied_value(root_element, cost_value, category_filter=None):
def calculate_applied_value(
root_element: ifcopenshell.entity_instance, cost_value: ifcopenshell.entity_instance, category_filter=None
) -> float:
if cost_value.ArithmeticOperator and cost_value.Components:
component_values = []
for component in cost_value.Components:
@@ -75,11 +81,11 @@ def calculate_applied_value(root_element, cost_value, category_filter=None):
return sum_child_root_elements(root_element, category_filter=cost_value.Category)
else:
return get_primitive_applied_value(cost_value.AppliedValue)
return 0
return 0.0
def sum_child_root_elements(root_element, category_filter=None):
result = 0
def sum_child_root_elements(root_element: ifcopenshell.entity_instance, category_filter: Optional[str] = None) -> float:
result = 0.0
for rel in root_element.IsNestedBy:
for child_root_element in rel.RelatedObjects:
if root_element.is_a("IfcCostItem"):
@@ -99,14 +105,14 @@ def sum_child_root_elements(root_element, category_filter=None):
return result
def serialise_cost_value(cost_value):
def serialise_cost_value(cost_value: ifcopenshell.entity_instance) -> str:
result = _serialise_cost_value(cost_value)
if result and result[0] == "(" and result[-1] == ")":
return result[1:-1]
return result
def _serialise_cost_value(cost_value):
def _serialise_cost_value(cost_value: ifcopenshell.entity_instance) -> str:
value = ""
if cost_value.ArithmeticOperator and cost_value.Components:
operator = arithmetic_operator_symbols[cost_value.ArithmeticOperator]
@@ -133,7 +139,7 @@ def _serialise_cost_value(cost_value):
return value
def serialise_applied_value(applied_value):
def serialise_applied_value(applied_value: ifcopenshell.entity_instance) -> str:
if applied_value.is_a("IfcMonetaryMeasure"):
return str(applied_value.wrappedValue)
return "?"