mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 10:06:47 +00:00
typing
This commit is contained in:
@@ -19,8 +19,10 @@
|
||||
import bpy
|
||||
import json
|
||||
import logging
|
||||
import ifcdiff
|
||||
import ifcopenshell
|
||||
import blenderbim.bim.handler
|
||||
import blenderbim.bim.import_ifc
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
@@ -175,7 +177,7 @@ class ExecuteIfcDiff(bpy.types.Operator):
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
def load_changed_elements(self, ifc_diff):
|
||||
def load_changed_elements(self, ifc_diff: ifcdiff.IfcDiff):
|
||||
if not tool.Ifc.get() or self.props.active_file == "NONE" or not self.props.should_load_changed_elements:
|
||||
return
|
||||
|
||||
|
||||
@@ -17,25 +17,26 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING, Optional, Union
|
||||
from typing import TYPE_CHECKING, Optional, Union, Literal
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.cost
|
||||
import blenderbim.tool as tool
|
||||
|
||||
|
||||
def add_cost_schedule(ifc: tool.Ifc, name, predefined_type):
|
||||
def add_cost_schedule(ifc: tool.Ifc, name: str, predefined_type: str) -> None:
|
||||
ifc.run("cost.add_cost_schedule", name=name, predefined_type=predefined_type)
|
||||
|
||||
|
||||
def edit_cost_schedule(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance):
|
||||
def edit_cost_schedule(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
attributes = cost.get_cost_schedule_attributes()
|
||||
ifc.run("cost.edit_cost_schedule", cost_schedule=cost_schedule, attributes=attributes)
|
||||
cost.disable_editing_cost_schedule()
|
||||
|
||||
|
||||
def disable_editing_cost_schedule(cost: tool.Cost):
|
||||
def disable_editing_cost_schedule(cost: tool.Cost) -> None:
|
||||
cost.disable_editing_cost_schedule()
|
||||
|
||||
|
||||
@@ -44,67 +45,67 @@ def remove_cost_schedule(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopens
|
||||
cost.remove_stored_schedule_columns(cost_schedule)
|
||||
|
||||
|
||||
def enable_editing_cost_schedule_attributes(cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance):
|
||||
def enable_editing_cost_schedule_attributes(cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
cost.load_cost_schedule_attributes(cost_schedule)
|
||||
cost.enable_editing_cost_schedule_attributes(cost_schedule)
|
||||
|
||||
|
||||
def enable_editing_cost_items(cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance):
|
||||
def enable_editing_cost_items(cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
cost.enable_editing_cost_items(cost_schedule)
|
||||
cost.load_active_schedule_columns()
|
||||
cost.load_cost_schedule_tree()
|
||||
cost.play_sound()
|
||||
|
||||
|
||||
def add_summary_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance):
|
||||
def add_summary_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
ifc.run("cost.add_cost_item", cost_schedule=cost_schedule)
|
||||
cost.load_cost_schedule_tree()
|
||||
# cost.play_sound()
|
||||
|
||||
|
||||
def add_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance):
|
||||
def add_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
ifc.run("cost.add_cost_item", cost_item=cost_item)
|
||||
cost.load_cost_schedule_tree()
|
||||
# cost.enable_editing_cost_schedule_attributes(cost_schedule)
|
||||
|
||||
|
||||
def expand_cost_item(cost: tool.Cost, cost_item: ifcopenshell.entity_instance):
|
||||
def expand_cost_item(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
cost.expand_cost_item(cost_item)
|
||||
cost.load_cost_schedule_tree()
|
||||
|
||||
|
||||
def expand_cost_items(cost: tool.Cost):
|
||||
def expand_cost_items(cost: tool.Cost) -> None:
|
||||
cost.expand_cost_items()
|
||||
cost.load_cost_schedule_tree()
|
||||
|
||||
|
||||
def contract_cost_item(cost: tool.Cost, cost_item: ifcopenshell.entity_instance):
|
||||
def contract_cost_item(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
cost.contract_cost_item(cost_item)
|
||||
cost.load_cost_schedule_tree()
|
||||
|
||||
|
||||
def contract_cost_items(cost: tool.Cost):
|
||||
def contract_cost_items(cost: tool.Cost) -> None:
|
||||
cost.contract_cost_items()
|
||||
cost.load_cost_schedule_tree()
|
||||
|
||||
|
||||
def remove_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_item_id: int):
|
||||
def remove_cost_item(ifc: tool.Ifc, cost: tool.Cost, cost_item_id: int) -> None:
|
||||
cost_item = ifc.get().by_id(cost_item_id)
|
||||
ifc.run("cost.remove_cost_item", cost_item=cost_item)
|
||||
cost.clean_up_cost_item_tree(cost_item_id)
|
||||
cost.load_cost_schedule_tree()
|
||||
|
||||
|
||||
def enable_editing_cost_item_attributes(cost: tool.Cost, cost_item: ifcopenshell.entity_instance):
|
||||
def enable_editing_cost_item_attributes(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
cost.enable_editing_cost_item_attributes(cost_item)
|
||||
cost.load_cost_item_attributes(cost_item)
|
||||
|
||||
|
||||
def disable_editing_cost_item(cost: tool.Cost):
|
||||
def disable_editing_cost_item(cost: tool.Cost) -> None:
|
||||
cost.disable_editing_cost_item()
|
||||
|
||||
|
||||
def edit_cost_item(ifc: tool.Ifc, cost: tool.Cost):
|
||||
def edit_cost_item(ifc: tool.Ifc, cost: tool.Cost) -> None:
|
||||
attributes = cost.get_cost_item_attributes()
|
||||
ifc.run("cost.edit_cost_item", cost_item=cost.get_active_cost_item(), attributes=attributes)
|
||||
cost.disable_editing_cost_item()
|
||||
@@ -148,85 +149,104 @@ def unassign_cost_item_type(
|
||||
return product_types
|
||||
|
||||
|
||||
def load_cost_item_types(cost: tool.Cost):
|
||||
def load_cost_item_types(cost: tool.Cost) -> None:
|
||||
cost_item = cost.get_active_cost_item()
|
||||
cost.load_cost_item_types(cost_item)
|
||||
|
||||
|
||||
def assign_cost_item_quantity(
|
||||
ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance, related_object_type, prop_name
|
||||
):
|
||||
ifc: tool.Ifc,
|
||||
cost: tool.Cost,
|
||||
cost_item: ifcopenshell.entity_instance,
|
||||
related_object_type: tool.Cost.RELATED_OBJECT_TYPE,
|
||||
prop_name: str,
|
||||
) -> None:
|
||||
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)
|
||||
cost.load_cost_item_quantity_assignments(cost_item, related_object_type=related_object_type)
|
||||
|
||||
|
||||
def load_cost_item_quantities(cost: tool.Cost):
|
||||
def load_cost_item_quantities(cost: tool.Cost) -> None:
|
||||
cost.load_cost_item_quantities()
|
||||
|
||||
|
||||
def load_cost_item_element_quantities(cost: tool.Cost):
|
||||
def load_cost_item_element_quantities(cost: tool.Cost) -> None:
|
||||
cost_item = cost.get_highlighted_cost_item()
|
||||
cost.load_cost_item_quantity_assignments(cost_item, related_object_type="PRODUCT")
|
||||
|
||||
|
||||
def load_cost_item_task_quantities(cost: tool.Cost):
|
||||
def load_cost_item_task_quantities(cost: tool.Cost) -> None:
|
||||
cost_item = cost.get_highlighted_cost_item()
|
||||
cost.load_cost_item_quantity_assignments(cost_item, related_object_type="PROCESS")
|
||||
|
||||
|
||||
def load_cost_item_resource_quantities(cost: tool.Cost):
|
||||
def load_cost_item_resource_quantities(cost: tool.Cost) -> None:
|
||||
cost_item = cost.get_highlighted_cost_item()
|
||||
cost.load_cost_item_quantity_assignments(cost_item, related_object_type="RESOURCE")
|
||||
|
||||
|
||||
def assign_cost_value(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, cost_rate):
|
||||
def assign_cost_value(
|
||||
ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, cost_rate: ifcopenshell.entity_instance
|
||||
) -> None:
|
||||
ifc.run("cost.assign_cost_value", cost_item=cost_item, cost_rate=cost_rate)
|
||||
|
||||
|
||||
def load_schedule_of_rates(cost: tool.Cost, schedule_of_rates):
|
||||
def load_schedule_of_rates(cost: tool.Cost, schedule_of_rates: ifcopenshell.entity_instance) -> None:
|
||||
cost.load_schedule_of_rates_tree(schedule_of_rates)
|
||||
|
||||
|
||||
def unassign_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance, products):
|
||||
def unassign_cost_item_quantity(
|
||||
ifc: tool.Ifc,
|
||||
cost: tool.Cost,
|
||||
cost_item: ifcopenshell.entity_instance,
|
||||
products: list[ifcopenshell.entity_instance],
|
||||
) -> None:
|
||||
ifc.run("cost.unassign_cost_item_quantity", cost_item=cost_item, products=products)
|
||||
cost.load_cost_item_quantities()
|
||||
|
||||
|
||||
def enable_editing_cost_item_quantities(cost: tool.Cost, cost_item: ifcopenshell.entity_instance):
|
||||
def enable_editing_cost_item_quantities(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
cost.enable_editing_cost_item_quantities(cost_item)
|
||||
|
||||
|
||||
def enable_editing_cost_item_values(cost: tool.Cost, cost_item: ifcopenshell.entity_instance):
|
||||
def enable_editing_cost_item_values(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
cost.enable_editing_cost_item_values(cost_item)
|
||||
|
||||
|
||||
def add_cost_item_quantity(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, ifc_class):
|
||||
def add_cost_item_quantity(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, ifc_class: str) -> None:
|
||||
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: ifcopenshell.entity_instance, physical_quantity):
|
||||
def remove_cost_item_quantity(
|
||||
ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, physical_quantity: ifcopenshell.entity_instance
|
||||
) -> None:
|
||||
ifc.run("cost.remove_cost_item_quantity", cost_item=cost_item, physical_quantity=physical_quantity)
|
||||
|
||||
|
||||
def enable_editing_cost_item_quantity(cost: tool.Cost, physical_quantity):
|
||||
def enable_editing_cost_item_quantity(cost: tool.Cost, physical_quantity: ifcopenshell.entity_instance) -> None:
|
||||
cost.load_cost_item_quantity_attributes(physical_quantity)
|
||||
cost.enable_editing_cost_item_quantity(physical_quantity)
|
||||
|
||||
|
||||
def disable_editing_cost_item_quantity(cost: tool.Cost):
|
||||
def disable_editing_cost_item_quantity(cost: tool.Cost) -> None:
|
||||
cost.disable_editing_cost_item_quantity()
|
||||
|
||||
|
||||
def edit_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, physical_quantity):
|
||||
def edit_cost_item_quantity(ifc: tool.Ifc, cost: tool.Cost, physical_quantity: ifcopenshell.entity_instance) -> None:
|
||||
attributes = cost.get_cost_item_quantity_attributes()
|
||||
ifc.run("cost.edit_cost_item_quantity", physical_quantity=physical_quantity, attributes=attributes)
|
||||
cost.disable_editing_cost_item_quantity()
|
||||
cost.load_cost_item_quantities()
|
||||
|
||||
|
||||
def add_cost_value(ifc: tool.Ifc, cost: tool.Cost, parent, cost_type, cost_category):
|
||||
def add_cost_value(
|
||||
ifc: tool.Ifc,
|
||||
cost: tool.Cost,
|
||||
parent: ifcopenshell.entity_instance,
|
||||
cost_type: Literal["FIXED", "SUM", "CATEGORY"],
|
||||
cost_category: Optional[str] = None,
|
||||
) -> None:
|
||||
value = ifc.run("cost.add_cost_value", parent=parent)
|
||||
ifc.run(
|
||||
"cost.edit_cost_value",
|
||||
@@ -235,84 +255,95 @@ def add_cost_value(ifc: tool.Ifc, cost: tool.Cost, parent, cost_type, cost_categ
|
||||
)
|
||||
|
||||
|
||||
def remove_cost_value(ifc: tool.Ifc, parent, cost_value):
|
||||
def remove_cost_value(
|
||||
ifc: tool.Ifc, parent: ifcopenshell.entity_instance, cost_value: ifcopenshell.entity_instance
|
||||
) -> None:
|
||||
ifc.run("cost.remove_cost_value", parent=parent, cost_value=cost_value)
|
||||
|
||||
|
||||
def enable_editing_cost_item_value(cost: tool.Cost, cost_value):
|
||||
def enable_editing_cost_item_value(cost: tool.Cost, cost_value: ifcopenshell.entity_instance) -> None:
|
||||
cost.load_cost_item_value_attributes(cost_value)
|
||||
cost.enable_editing_cost_item_value(cost_value)
|
||||
|
||||
|
||||
def disable_editing_cost_item_value(cost: tool.Cost):
|
||||
def disable_editing_cost_item_value(cost: tool.Cost) -> None:
|
||||
cost.disable_editing_cost_item_value()
|
||||
|
||||
|
||||
def enable_editing_cost_item_value_formula(cost: tool.Cost, cost_value):
|
||||
def enable_editing_cost_item_value_formula(cost: tool.Cost, cost_value: ifcopenshell.entity_instance) -> None:
|
||||
cost.load_cost_item_value_formula_attributes(cost_value)
|
||||
cost.enable_editing_cost_item_value_formula(cost_value)
|
||||
|
||||
|
||||
def edit_cost_item_value_formula(ifc: tool.Ifc, cost: tool.Cost, cost_value):
|
||||
def edit_cost_item_value_formula(ifc: tool.Ifc, cost: tool.Cost, cost_value: ifcopenshell.entity_instance) -> None:
|
||||
formula = cost.get_cost_item_value_formula()
|
||||
ifc.run("cost.edit_cost_value_formula", cost_value=cost_value, formula=formula)
|
||||
cost.disable_editing_cost_item_value()
|
||||
|
||||
|
||||
def edit_cost_value(ifc: tool.Ifc, cost: tool.Cost, cost_value):
|
||||
def edit_cost_value(ifc: tool.Ifc, cost: tool.Cost, cost_value: ifcopenshell.entity_instance) -> None:
|
||||
attributes = cost.get_cost_value_attributes()
|
||||
ifc.run("cost.edit_cost_value", cost_value=cost_value, attributes=attributes)
|
||||
cost.disable_editing_cost_item_value()
|
||||
# cost.load_cost_item_values(cost.get_highlighted_cost_item())
|
||||
|
||||
|
||||
def copy_cost_item_values(ifc: tool.Ifc, cost: tool.Cost, source, destination):
|
||||
def copy_cost_item_values(
|
||||
ifc: tool.Ifc, cost: tool.Cost, source: ifcopenshell.entity_instance, destination: ifcopenshell.entity_instance
|
||||
) -> None:
|
||||
ifc.run("cost.copy_cost_item_values", source=source, destination=destination)
|
||||
|
||||
|
||||
def select_cost_item_products(cost: tool.Cost, spatial: tool.Spatial, cost_item: ifcopenshell.entity_instance):
|
||||
def select_cost_item_products(cost: tool.Cost, spatial: tool.Spatial, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
is_deep = cost.show_nested_cost_item_elements()
|
||||
products = cost.get_cost_item_products(cost_item, is_deep)
|
||||
spatial.select_products(products)
|
||||
|
||||
|
||||
def select_cost_schedule_products(cost: tool.Cost, spatial: tool.Spatial, cost_schedule: ifcopenshell.entity_instance):
|
||||
def select_cost_schedule_products(
|
||||
cost: tool.Cost, spatial: tool.Spatial, cost_schedule: ifcopenshell.entity_instance
|
||||
) -> None:
|
||||
products = cost.get_cost_schedule_products(cost_schedule)
|
||||
spatial.select_products(products)
|
||||
|
||||
|
||||
def import_cost_schedule_csv(cost: tool.Cost, file_path, is_schedule_of_rates):
|
||||
def import_cost_schedule_csv(cost: tool.Cost, file_path: str, is_schedule_of_rates: bool) -> None:
|
||||
cost.import_cost_schedule_csv(file_path, is_schedule_of_rates)
|
||||
|
||||
|
||||
def add_cost_column(cost: tool.Cost, name):
|
||||
def add_cost_column(cost: tool.Cost, name: str) -> None:
|
||||
cost.add_cost_column(name)
|
||||
|
||||
|
||||
def remove_cost_column(cost: tool.Cost, name):
|
||||
def remove_cost_column(cost: tool.Cost, name: str) -> None:
|
||||
cost.remove_cost_column(name)
|
||||
|
||||
|
||||
def expand_cost_item_rate(cost: tool.Cost, cost_item: ifcopenshell.entity_instance):
|
||||
def expand_cost_item_rate(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
cost.expand_cost_item_rate(cost_item)
|
||||
|
||||
|
||||
def contract_cost_item_rate(cost: tool.Cost, cost_item: ifcopenshell.entity_instance):
|
||||
def contract_cost_item_rate(cost: tool.Cost, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
cost.contract_cost_item_rate(cost_item)
|
||||
|
||||
|
||||
def calculate_cost_item_resource_value(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance):
|
||||
def calculate_cost_item_resource_value(ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
ifc.run("cost.calculate_cost_item_resource_value", cost_item=cost_item)
|
||||
|
||||
|
||||
def export_cost_schedules(cost: tool.Cost, filepath: str, format: str, cost_schedule=None):
|
||||
def export_cost_schedules(
|
||||
cost: tool.Cost, filepath: str, format: str, cost_schedule: Union[ifcopenshell.entity_instance, None] = None
|
||||
) -> Union[str, None]:
|
||||
cost.play_sound()
|
||||
return cost.export_cost_schedules(filepath, format, cost_schedule)
|
||||
|
||||
|
||||
def clear_cost_item_assignments(
|
||||
ifc: tool.Ifc, cost: tool.Cost, cost_item: ifcopenshell.entity_instance, related_object_type
|
||||
):
|
||||
ifc: tool.Ifc,
|
||||
cost: tool.Cost,
|
||||
cost_item: ifcopenshell.entity_instance,
|
||||
related_object_type: ifcopenshell.util.cost.FILTER_BY_TYPE,
|
||||
) -> None:
|
||||
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)
|
||||
@@ -320,7 +351,7 @@ def clear_cost_item_assignments(
|
||||
cost.load_cost_schedule_tree()
|
||||
|
||||
|
||||
def select_unassigned_products(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial):
|
||||
def select_unassigned_products(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spatial) -> None:
|
||||
spatial.deselect_objects()
|
||||
products = ifc.get().by_type("IfcElement")
|
||||
cost_schedule = cost.get_active_cost_schedule()
|
||||
@@ -328,11 +359,13 @@ def select_unassigned_products(ifc: tool.Ifc, cost: tool.Cost, spatial: tool.Spa
|
||||
spatial.select_products(selection)
|
||||
|
||||
|
||||
def load_product_cost_items(cost: tool.Cost, product):
|
||||
def load_product_cost_items(cost: tool.Cost, product: ifcopenshell.entity_instance) -> None:
|
||||
cost.load_product_cost_items(product)
|
||||
|
||||
|
||||
def highlight_product_cost_item(spatial: tool.Spatial, cost: tool.Cost, cost_item: ifcopenshell.entity_instance):
|
||||
def highlight_product_cost_item(
|
||||
spatial: tool.Spatial, cost: tool.Cost, cost_item: ifcopenshell.entity_instance
|
||||
) -> Union[str, None]:
|
||||
cost_schedule = cost.get_cost_schedule(cost_item)
|
||||
is_cost_schedule_active = cost.is_cost_schedule_active(cost_schedule)
|
||||
if is_cost_schedule_active:
|
||||
@@ -341,7 +374,7 @@ def highlight_product_cost_item(spatial: tool.Spatial, cost: tool.Cost, cost_ite
|
||||
return "Cost schedule is not active"
|
||||
|
||||
|
||||
def change_parent_cost_item(ifc: tool.Ifc, cost: tool.Cost, new_parent):
|
||||
def change_parent_cost_item(ifc: tool.Ifc, cost: tool.Cost, new_parent) -> Union[str, None]:
|
||||
cost_item = cost.get_active_cost_item()
|
||||
if cost_item and cost.is_root_cost_item(cost_item):
|
||||
return "Cannot change root cost item"
|
||||
@@ -351,7 +384,7 @@ def change_parent_cost_item(ifc: tool.Ifc, cost: tool.Cost, new_parent):
|
||||
cost.load_cost_schedule_tree()
|
||||
|
||||
|
||||
def copy_cost_item(ifc: tool.Ifc, cost: tool.Cost):
|
||||
def copy_cost_item(ifc: tool.Ifc, cost: tool.Cost) -> None:
|
||||
cost_item = cost.get_highlighted_cost_item()
|
||||
if cost_item:
|
||||
cost_item = ifc.run("cost.copy_cost_item", cost_item=cost_item)
|
||||
@@ -359,7 +392,7 @@ def copy_cost_item(ifc: tool.Ifc, cost: tool.Cost):
|
||||
cost.load_cost_schedule_tree()
|
||||
|
||||
|
||||
def add_currency(ifc: tool.Ifc, cost: tool.Cost):
|
||||
def add_currency(ifc: tool.Ifc, cost: tool.Cost) -> ifcopenshell.entity_instance:
|
||||
unit = ifc.run("unit.add_monetary_unit")
|
||||
attributes = cost.get_currency_attributes()
|
||||
ifc.run("unit.edit_monetary_unit", unit=unit, attributes=attributes)
|
||||
|
||||
@@ -9,17 +9,20 @@ import ifcopenshell.util.cost
|
||||
import ifcopenshell.util.unit
|
||||
import blenderbim.bim.helper
|
||||
import json
|
||||
from typing import Optional, Any, Generator, Union
|
||||
from typing import Optional, Any, Generator, Union, Literal
|
||||
|
||||
|
||||
class Cost(blenderbim.core.tool.Cost):
|
||||
|
||||
RELATED_OBJECT_TYPE = Literal["PRODUCT", "PROCESS", "RESOURCE"]
|
||||
|
||||
@classmethod
|
||||
def get_cost_schedule_attributes(cls):
|
||||
def get_cost_schedule_attributes(cls) -> dict[str, Any]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
return blenderbim.bim.helper.export_attributes(props.cost_schedule_attributes)
|
||||
|
||||
@classmethod
|
||||
def disable_editing_cost_schedule(cls):
|
||||
def disable_editing_cost_schedule(cls) -> None:
|
||||
cls.store_active_schedule_columns()
|
||||
bpy.context.scene.BIMCostProperties.active_cost_schedule_id = 0
|
||||
cls.disable_editing_cost_item()
|
||||
@@ -74,12 +77,12 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
storage.remove(storage_col_i)
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_schedule_attributes(cls, cost_schedule):
|
||||
def enable_editing_cost_schedule_attributes(cls, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
bpy.context.scene.BIMCostProperties.active_cost_schedule_id = cost_schedule.id()
|
||||
bpy.context.scene.BIMCostProperties.is_editing = "COST_SCHEDULE_ATTRIBUTES"
|
||||
|
||||
@classmethod
|
||||
def load_cost_schedule_attributes(cls, cost_schedule):
|
||||
def load_cost_schedule_attributes(cls, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
def special_import(name, prop, data):
|
||||
if name in ["SubmittedOn", "UpdateDate"]:
|
||||
prop.string_value = "" if prop.is_null else ifcopenshell.util.date.ifc2datetime(data[name]).isoformat()
|
||||
@@ -96,12 +99,12 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
props.is_editing = "COST_ITEMS"
|
||||
|
||||
@classmethod
|
||||
def play_sound(cls):
|
||||
def play_sound(cls) -> None:
|
||||
if tool.Blender.get_addon_preferences().should_play_chaching_sound:
|
||||
cls.play_chaching_sound() # lol
|
||||
|
||||
@classmethod
|
||||
def play_chaching_sound(cls):
|
||||
def play_chaching_sound(cls) -> None:
|
||||
# TODO: make pitch higher as costs rise
|
||||
try:
|
||||
import aud
|
||||
@@ -118,7 +121,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
pass # ah well
|
||||
|
||||
@classmethod
|
||||
def load_cost_schedule_tree(cls):
|
||||
def load_cost_schedule_tree(cls) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props.is_cost_update_enabled = False
|
||||
cost_schedule = tool.Ifc.get().by_id(props.active_cost_schedule_id)
|
||||
@@ -132,7 +135,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
props.is_cost_update_enabled = True
|
||||
|
||||
@classmethod
|
||||
def expand_cost_item(cls, cost_item):
|
||||
def expand_cost_item(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
if not hasattr(cls, "contracted_cost_items"):
|
||||
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||
@@ -141,7 +144,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
|
||||
|
||||
@classmethod
|
||||
def expand_cost_items(cls):
|
||||
def expand_cost_items(cls) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||
for cost_item in props.cost_items:
|
||||
@@ -150,7 +153,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
|
||||
|
||||
@classmethod
|
||||
def contract_cost_item(cls, cost_item):
|
||||
def contract_cost_item(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
if not hasattr(cls, "contracted_cost_items"):
|
||||
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||
@@ -158,7 +161,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
|
||||
|
||||
@classmethod
|
||||
def contract_cost_items(cls):
|
||||
def contract_cost_items(cls) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
if not hasattr(cls, "contracted_cost_items"):
|
||||
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||
@@ -168,7 +171,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
props.contracted_cost_items = json.dumps(cls.contracted_cost_items)
|
||||
|
||||
@classmethod
|
||||
def clean_up_cost_item_tree(cls, cost_item_id):
|
||||
def clean_up_cost_item_tree(cls, cost_item_id: int) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
if not hasattr(cls, "contracted_cost_items"):
|
||||
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||
@@ -180,23 +183,23 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
cls.enable_editing_cost_items(cost_schedule=tool.Ifc.get().by_id(props.active_cost_schedule_id))
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_item_attributes(cls, cost_item):
|
||||
def enable_editing_cost_item_attributes(cls, cost_item: ifcopenshell.entity_instance):
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_id = cost_item.id()
|
||||
bpy.context.scene.BIMCostProperties.cost_item_editing_type = "ATTRIBUTES"
|
||||
|
||||
@classmethod
|
||||
def load_cost_item_attributes(cls, cost_item):
|
||||
def load_cost_item_attributes(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props.cost_item_attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes2(cost_item, props.cost_item_attributes)
|
||||
|
||||
@classmethod
|
||||
def disable_editing_cost_item(cls):
|
||||
def disable_editing_cost_item(cls) -> None:
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_id = 0
|
||||
bpy.context.scene.BIMCostProperties.change_cost_item_parent = False
|
||||
|
||||
@classmethod
|
||||
def get_cost_item_attributes(cls):
|
||||
def get_cost_item_attributes(cls) -> dict[str, Any]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
return blenderbim.bim.helper.export_attributes(props.cost_item_attributes)
|
||||
|
||||
@@ -208,7 +211,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
return tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_item_id)
|
||||
|
||||
@classmethod
|
||||
def get_highlighted_cost_item(cls):
|
||||
def get_highlighted_cost_item(cls) -> Union[ifcopenshell.entity_instance, None]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
if not props.active_cost_schedule_id:
|
||||
return
|
||||
@@ -240,7 +243,9 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
new.name = related_object.Name or "Unnamed"
|
||||
|
||||
@classmethod
|
||||
def load_cost_item_quantity_assignments(cls, cost_item: ifcopenshell.entity_instance, related_object_type):
|
||||
def load_cost_item_quantity_assignments(
|
||||
cls, cost_item: ifcopenshell.entity_instance, related_object_type: RELATED_OBJECT_TYPE
|
||||
) -> None:
|
||||
def create_list_items(collection, cost_item, is_deep):
|
||||
products = cls.get_cost_item_assignments(cost_item, filter_by_type=related_object_type, is_deep=False)
|
||||
for product in products:
|
||||
@@ -291,9 +296,9 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
return selected_quantitites, unit
|
||||
|
||||
@classmethod
|
||||
def get_products(cls, related_object_type=None):
|
||||
def get_products(cls, related_object_type: RELATED_OBJECT_TYPE) -> list[ifcopenshell.entity_instance]:
|
||||
if related_object_type == "PRODUCT":
|
||||
products = tool.Spatial.get_selected_products()
|
||||
products = list(tool.Spatial.get_selected_products())
|
||||
elif related_object_type == "PROCESS":
|
||||
products = [tool.Sequence.get_highlighted_task()]
|
||||
elif related_object_type == "RESOURCE":
|
||||
@@ -301,17 +306,17 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
return products or []
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_item_quantities(cls, cost_item=None):
|
||||
def enable_editing_cost_item_quantities(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props.active_cost_item_id = cost_item.id()
|
||||
props.cost_item_editing_type = "QUANTITIES"
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_item_quantity(cls, physical_quantity=None):
|
||||
def enable_editing_cost_item_quantity(cls, physical_quantity: ifcopenshell.entity_instance) -> None:
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_quantity_id = physical_quantity.id()
|
||||
|
||||
@classmethod
|
||||
def load_cost_item_quantity_attributes(cls, physical_quantity=None):
|
||||
def load_cost_item_quantity_attributes(cls, physical_quantity: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props.quantity_attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes2(physical_quantity, props.quantity_attributes)
|
||||
@@ -323,16 +328,18 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
props.cost_item_editing_type = "VALUES"
|
||||
|
||||
@classmethod
|
||||
def disable_editing_cost_item_quantity(cls):
|
||||
def disable_editing_cost_item_quantity(cls) -> None:
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_quantity_id = 0
|
||||
|
||||
@classmethod
|
||||
def get_cost_item_quantity_attributes(cls):
|
||||
def get_cost_item_quantity_attributes(cls) -> dict[str, Any]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
return blenderbim.bim.helper.export_attributes(props.quantity_attributes)
|
||||
|
||||
@classmethod
|
||||
def get_attributes_for_cost_value(cls, cost_type, cost_category):
|
||||
def get_attributes_for_cost_value(
|
||||
cls, cost_type: Literal["FIXED", "SUM", "CATEGORY"], cost_category: Optional[str] = None
|
||||
) -> dict[str, Any]:
|
||||
if cost_type == "FIXED":
|
||||
category = None
|
||||
attributes = {"AppliedValue": bpy.context.scene.BIMCostProperties.fixed_cost_value}
|
||||
@@ -429,7 +436,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
props.cost_value_editing_type = "FORMULA"
|
||||
|
||||
@classmethod
|
||||
def get_cost_item_value_formula(cls):
|
||||
def get_cost_item_value_formula(cls) -> str:
|
||||
return bpy.context.scene.BIMCostProperties.cost_value_formula
|
||||
|
||||
@classmethod
|
||||
@@ -469,7 +476,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def show_nested_cost_item_elements(cls):
|
||||
def show_nested_cost_item_elements(cls) -> bool:
|
||||
return bpy.context.scene.BIMCostProperties.show_nested_elements
|
||||
|
||||
@classmethod
|
||||
@@ -532,7 +539,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
props.columns.remove(props.columns.find(name))
|
||||
|
||||
@classmethod
|
||||
def expand_cost_item_rate(cls, cost_item):
|
||||
def expand_cost_item_rate(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
|
||||
contracted_cost_item_rates.remove(cost_item)
|
||||
@@ -540,7 +547,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
cls.load_schedule_of_rates_tree(schedule_of_rates=tool.Ifc.get().by_id(int(props.schedule_of_rates)))
|
||||
|
||||
@classmethod
|
||||
def contract_cost_item_rate(cls, cost_item):
|
||||
def contract_cost_item_rate(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
|
||||
contracted_cost_item_rates.append(cost_item)
|
||||
@@ -571,7 +578,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def load_schedule_of_rates_tree(cls, schedule_of_rates):
|
||||
def load_schedule_of_rates_tree(cls, schedule_of_rates: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props.is_cost_update_enabled = False
|
||||
props.cost_item_rates.clear()
|
||||
@@ -585,7 +592,9 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
props.is_cost_update_enabled = True
|
||||
|
||||
@classmethod
|
||||
def export_cost_schedules(cls, filepath: str, format: str, cost_schedule=None):
|
||||
def export_cost_schedules(
|
||||
cls, filepath: str, format: str, cost_schedule: Optional[ifcopenshell.entity_instance] = None
|
||||
) -> Union[str, None]:
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
@@ -624,7 +633,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
return "Could not open file location"
|
||||
|
||||
@classmethod
|
||||
def get_units(cls):
|
||||
def get_units(cls) -> dict[int, str]:
|
||||
units = {}
|
||||
for unit in tool.Ifc.get().by_type("IfcNamedUnit"):
|
||||
if unit.get_info().get("UnitType", None) in [
|
||||
@@ -639,7 +648,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
return units
|
||||
|
||||
@staticmethod
|
||||
def format_unit(unit):
|
||||
def format_unit(unit: ifcopenshell.entity_instance) -> str:
|
||||
if unit.is_a("IfcContextDependentUnit"):
|
||||
return f"{unit.UnitType} / {unit.Name}"
|
||||
else:
|
||||
@@ -649,7 +658,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
return f"{unit.UnitType} / {name}"
|
||||
|
||||
@classmethod
|
||||
def get_cost_schedule(cls, cost_item):
|
||||
def get_cost_schedule(cls, cost_item: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||
for rel in cost_item.HasAssignments or []:
|
||||
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcCostSchedule"):
|
||||
return rel.RelatingControl
|
||||
@@ -657,17 +666,17 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
return cls.get_cost_schedule(rel.RelatingObject)
|
||||
|
||||
@classmethod
|
||||
def is_cost_schedule_active(cls, cost_schedule):
|
||||
def is_cost_schedule_active(cls, cost_schedule: ifcopenshell.entity_instance) -> bool:
|
||||
return True if cost_schedule.id() == bpy.context.scene.BIMCostProperties.active_cost_schedule_id else False
|
||||
|
||||
@classmethod
|
||||
def get_active_cost_schedule(cls):
|
||||
def get_active_cost_schedule(cls) -> Union[ifcopenshell.entity_instance, None]:
|
||||
if not bpy.context.scene.BIMCostProperties.active_cost_schedule_id:
|
||||
return None
|
||||
return tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_schedule_id)
|
||||
|
||||
@classmethod
|
||||
def highlight_cost_item(cls, cost_item):
|
||||
def highlight_cost_item(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
def expand_ancestors(cost_item):
|
||||
cls.expand_cost_item(cost_item)
|
||||
for rel in cost_item.Nests or []:
|
||||
@@ -685,11 +694,13 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_index = cost_item_index
|
||||
|
||||
@classmethod
|
||||
def get_cost_items_for_product(cls, product):
|
||||
def get_cost_items_for_product(cls, product: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
|
||||
return ifcopenshell.util.cost.get_cost_items_for_product(product)
|
||||
|
||||
@classmethod
|
||||
def has_cost_assignments(cls, product, cost_schedule=None):
|
||||
def has_cost_assignments(
|
||||
cls, product: ifcopenshell.entity_instance, cost_schedule: Optional[ifcopenshell.entity_instance] = None
|
||||
) -> bool:
|
||||
cost_items = ifcopenshell.util.cost.get_cost_items_for_product(product)
|
||||
if cost_schedule:
|
||||
cost_items = [
|
||||
@@ -714,7 +725,7 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
new.total_cost_quantity = ifcopenshell.util.cost.get_total_quantity(cost_item)
|
||||
|
||||
@classmethod
|
||||
def get_quantity_unit_symbol(cls, quantity):
|
||||
def get_quantity_unit_symbol(cls, quantity: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
unit = ifcopenshell.util.unit.get_property_unit(quantity, tool.Ifc.get())
|
||||
if unit:
|
||||
return ifcopenshell.util.unit.get_unit_symbol(unit)
|
||||
@@ -722,14 +733,15 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def is_root_cost_item(cls, cost_item):
|
||||
def is_root_cost_item(cls, cost_item: ifcopenshell.entity_instance) -> bool:
|
||||
if cost_item.HasAssignments:
|
||||
for rel in cost_item.HasAssignments:
|
||||
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcCostSchedule"):
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def toggle_cost_item_parent_change(cls, cost_item=None):
|
||||
def toggle_cost_item_parent_change(cls, cost_item: Optional[ifcopenshell.entity_instance] = None) -> None:
|
||||
if not cost_item:
|
||||
return
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
@@ -740,16 +752,18 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
cls.disable_editing_cost_item_parent()
|
||||
|
||||
@classmethod
|
||||
def change_parent_cost_item(cls, cost_item, new_parent):
|
||||
def change_parent_cost_item(
|
||||
cls, cost_item: ifcopenshell.entity_instance, new_parent: ifcopenshell.entity_instance
|
||||
) -> None:
|
||||
ifcopenshell.api.run("nest.change_nest", tool.Ifc.get(), item=cost_item, new_parent=new_parent)
|
||||
|
||||
@classmethod
|
||||
def disable_editing_cost_item_parent(cls):
|
||||
def disable_editing_cost_item_parent(cls) -> None:
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_id = 0
|
||||
bpy.context.scene.BIMCostProperties.change_cost_item_parent = False
|
||||
|
||||
@classmethod
|
||||
def load_cost_item_quantities(cls, cost_item=None):
|
||||
def load_cost_item_quantities(cls, cost_item: Optional[ifcopenshell.entity_instance] = None) -> None:
|
||||
if not cost_item:
|
||||
cost_item = cls.get_highlighted_cost_item()
|
||||
if not cost_item:
|
||||
@@ -759,7 +773,9 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
cls.load_cost_item_quantity_assignments(cost_item, related_object_type="RESOURCE")
|
||||
|
||||
@classmethod
|
||||
def update_cost_items(cls, product=None, pset=None):
|
||||
def update_cost_items(
|
||||
cls, product: Optional[ifcopenshell.entity_instance] = None, pset: Optional[ifcopenshell.entity_instance] = None
|
||||
) -> None:
|
||||
cost_items = []
|
||||
if product:
|
||||
cost_items = ifcopenshell.util.cost.get_cost_items_for_product(product)
|
||||
@@ -779,11 +795,11 @@ class Cost(blenderbim.core.tool.Cost):
|
||||
cls.load_cost_item_quantity_assignments(cost_item, related_object_type="PRODUCT")
|
||||
|
||||
@classmethod
|
||||
def has_schedules(cls):
|
||||
def has_schedules(cls) -> bool:
|
||||
return bool(tool.Ifc.get().by_type("IfcCostSchedule"))
|
||||
|
||||
@classmethod
|
||||
def get_currency_attributes(cls):
|
||||
def get_currency_attributes(cls) -> dict[str, str]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
currency = props.currency
|
||||
if currency == "CUSTOM":
|
||||
|
||||
+33
-15
@@ -35,30 +35,29 @@ import ifcopenshell.util.classification
|
||||
import ifcopenshell.util.representation
|
||||
from deepdiff import DeepDiff
|
||||
from ordered_set import OrderedSet
|
||||
from typing import Optional, Union, Literal, Any
|
||||
|
||||
|
||||
__version__ = version = "0.0.0"
|
||||
|
||||
|
||||
RELATIONSHIP_TYPE = Literal["geometry", "attributes", "type", "property", "container", "aggregate", "classification"]
|
||||
|
||||
|
||||
class IfcDiff:
|
||||
"""Main IfcDiff application
|
||||
|
||||
If you are using IfcDiff as a library, this is the class you should use.
|
||||
|
||||
:param old: IFC file object for the old model
|
||||
:type old: ifcopenshell.file.file
|
||||
:param new: IFC file object for the new model
|
||||
:type new: ifcopenshell.file.file
|
||||
:param relationships: List of relationships to check. None means that only
|
||||
geometry is compared.
|
||||
:type relationships: list[string]
|
||||
geometry is compared. See RELATIONSHIP_TYPE for available relationships.
|
||||
:param is_shallow: True if you want only the first difference to be listed.
|
||||
False if you want all differences to be checked. Choosing False means
|
||||
that comparisons will take longer.
|
||||
:type is_shallow: bool
|
||||
:param filter_elements: An IFC filter query if you only want to compare a
|
||||
subset of elements. For example: ``IfcWall`` to only compare walls.
|
||||
:type filter_elements: string
|
||||
|
||||
Example::
|
||||
|
||||
@@ -70,7 +69,19 @@ class IfcDiff:
|
||||
ifc_diff.export()
|
||||
"""
|
||||
|
||||
def __init__(self, old, new, relationships=None, is_shallow=True, filter_elements=None):
|
||||
added_elements: set[ifcopenshell.entity_instance]
|
||||
deleted_elements: set[ifcopenshell.entity_instance]
|
||||
# GlobalIds to changes dictionary.
|
||||
change_register: dict[str, dict[str, Any]]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
old: ifcopenshell.file,
|
||||
new: ifcopenshell.file,
|
||||
relationships: Optional[list[RELATIONSHIP_TYPE]] = None,
|
||||
is_shallow: bool = True,
|
||||
filter_elements: Optional[str] = None,
|
||||
):
|
||||
self.old = old
|
||||
self.new = new
|
||||
self.change_register = {}
|
||||
@@ -80,7 +91,7 @@ class IfcDiff:
|
||||
self.is_shallow = is_shallow
|
||||
self.filter_elements = filter_elements
|
||||
|
||||
def diff(self):
|
||||
def diff(self) -> None:
|
||||
logging.disable(logging.CRITICAL)
|
||||
|
||||
self.precision = self.get_precision()
|
||||
@@ -187,7 +198,9 @@ class IfcDiff:
|
||||
|
||||
logging.disable(logging.NOTSET)
|
||||
|
||||
def summarise_shapes(self, ifc, elements):
|
||||
def summarise_shapes(
|
||||
self, ifc: ifcopenshell.file, elements: list[ifcopenshell.entity_instance]
|
||||
) -> dict[str, dict[str, Any]]:
|
||||
shapes = {}
|
||||
iterator = ifcopenshell.geom.iterator(
|
||||
self.get_settings(ifc), ifc, multiprocessing.cpu_count(), include=elements
|
||||
@@ -215,7 +228,7 @@ class IfcDiff:
|
||||
break
|
||||
return shapes
|
||||
|
||||
def get_settings(self, ifc):
|
||||
def get_settings(self, ifc: ifcopenshell.file) -> ifcopenshell.geom.settings:
|
||||
settings = ifcopenshell.geom.settings()
|
||||
# Are you feeling lucky?
|
||||
settings.set(settings.DISABLE_BOOLEAN_RESULT, True)
|
||||
@@ -246,7 +259,7 @@ class IfcDiff:
|
||||
return list(obj)
|
||||
return json.JSONEncoder.default(None, obj)
|
||||
|
||||
def export(self, path):
|
||||
def export(self, path: str) -> None:
|
||||
with open(path, "w", encoding="utf-8") as diff_file:
|
||||
json.dump(
|
||||
{
|
||||
@@ -259,7 +272,7 @@ class IfcDiff:
|
||||
default=self.json_dump_default,
|
||||
)
|
||||
|
||||
def get_precision(self):
|
||||
def get_precision(self) -> float:
|
||||
contexts = [c for c in self.new.by_type("IfcGeometricRepresentationContext") if c.ContextType == "Model"]
|
||||
if contexts:
|
||||
return contexts[0].Precision or 1e-4
|
||||
@@ -356,7 +369,7 @@ class IfcDiff:
|
||||
# self.representation_ids[new_rep_id] = result
|
||||
# return result
|
||||
|
||||
def diff_representation(self, old_rep_id, new_rep_id):
|
||||
def diff_representation(self, old_rep_id: int, new_rep_id: int) -> bool:
|
||||
old_rep = self.old.by_id(old_rep_id)
|
||||
new_rep = self.new.by_id(new_rep_id)
|
||||
if len(old_rep.Items) != len(new_rep.Items):
|
||||
@@ -365,8 +378,11 @@ class IfcDiff:
|
||||
result = self.diff_representation_item(old_item, new_rep.Items[i])
|
||||
if result is True:
|
||||
return True
|
||||
return False
|
||||
|
||||
def diff_representation_item(self, old_item, new_item):
|
||||
def diff_representation_item(
|
||||
self, old_item: ifcopenshell.entity_instance, new_item: ifcopenshell.entity_instance
|
||||
) -> bool:
|
||||
if old_item.is_a() != new_item.is_a():
|
||||
return True
|
||||
try:
|
||||
@@ -381,8 +397,9 @@ class IfcDiff:
|
||||
return True
|
||||
if diff:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_representation_id(self, element):
|
||||
def get_representation_id(self, element: ifcopenshell.entity_instance) -> Union[int, None]:
|
||||
if not element.Representation:
|
||||
return
|
||||
for representation in element.Representation.Representations:
|
||||
@@ -404,6 +421,7 @@ class DiffTerminator:
|
||||
def give_up_diffing(self, level, diff_instance) -> bool:
|
||||
if any(diff_instance.tree.values()):
|
||||
raise Exception("Terminated")
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user