This commit is contained in:
Andrej730
2024-11-08 11:04:18 +05:00
parent 1d3ca475d9
commit fe8c396e12
4 changed files with 17 additions and 99 deletions
@@ -25,6 +25,7 @@ import shutil
import mathutils import mathutils
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
import svgwrite import svgwrite
import svgwrite.text
import ifcopenshell import ifcopenshell
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.representation import ifcopenshell.util.representation
@@ -774,7 +775,7 @@ class SvgWriter:
"text-anchor": text_anchor, "text-anchor": text_anchor,
} }
def add_fill_bg(self, element, copy=True): def add_fill_bg(self, element: svgwrite.text.Text, copy: bool = True) -> svgwrite.text.Text:
if copy: if copy:
element = element.copy() element = element.copy()
if hasattr(element, "xml"): if hasattr(element, "xml"):
+4 -2
View File
@@ -16,10 +16,12 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import bonsai.bim.helper import bonsai.bim.helper
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.resource.data import ResourceData from bonsai.bim.module.resource.data import ResourceData
from typing import Any
class BIM_PT_resources(Panel): class BIM_PT_resources(Panel):
@@ -287,7 +289,7 @@ class BIM_PT_resources(Panel):
if self.props.cost_value_editing_type == "ATTRIBUTES": if self.props.cost_value_editing_type == "ATTRIBUTES":
bonsai.bim.helper.draw_attributes(self.props.cost_value_attributes, self.layout.box()) bonsai.bim.helper.draw_attributes(self.props.cost_value_attributes, self.layout.box())
def draw_readonly_cost_value_ui(self, layout, cost_value): def draw_readonly_cost_value_ui(self, layout: bpy.types.UILayout, cost_value: dict[str, Any]) -> None:
if self.props.active_cost_value_id == cost_value["id"] and self.props.cost_value_editing_type == "FORMULA": if self.props.active_cost_value_id == cost_value["id"] and self.props.cost_value_editing_type == "FORMULA":
layout.prop(self.props, "cost_value_formula", text="") layout.prop(self.props, "cost_value_formula", text="")
else: else:
@@ -295,7 +297,7 @@ class BIM_PT_resources(Panel):
self.draw_cost_value_operator_ui(layout, cost_value["id"], self.props.active_resource_id) self.draw_cost_value_operator_ui(layout, cost_value["id"], self.props.active_resource_id)
def draw_cost_value_operator_ui(self, layout, cost_value_id, parent_id): def draw_cost_value_operator_ui(self, layout: bpy.types.UILayout, cost_value_id: int, parent_id: int) -> None:
if self.props.active_cost_value_id and self.props.active_cost_value_id == cost_value_id: if self.props.active_cost_value_id and self.props.active_cost_value_id == cost_value_id:
if self.props.cost_value_editing_type == "ATTRIBUTES": if self.props.cost_value_editing_type == "ATTRIBUTES":
op = layout.operator("bim.edit_resource_cost_value", text="", icon="CHECKMARK") op = layout.operator("bim.edit_resource_cost_value", text="", icon="CHECKMARK")
@@ -53,20 +53,13 @@ def get_pset(
occurrence, not the type's pset. occurrence, not the type's pset.
:param element: The IFC Element entity :param element: The IFC Element entity
:type element: ifcopenshell.entity_instance
:param name: The name of the pset :param name: The name of the pset
:type name: str
:param prop: The name of the property :param prop: The name of the property
:type prop: str,optional
:param psets_only: Default as False. Set to true if only property sets are needed. :param psets_only: Default as False. Set to true if only property sets are needed.
:type psets_only: bool,optional
:param qtos_only: Default as False. Set to true if only quantities are needed. :param qtos_only: Default as False. Set to true if only quantities are needed.
:type qtos_only: bool,optional
:param should_inherit: Default as True. Set to false if you don't want to inherit property sets from the Type. :param should_inherit: Default as True. Set to false if you don't want to inherit property sets from the Type.
:type should_inherit: bool,optional
:return: A dictionary of property names and values, or a single value if a :return: A dictionary of property names and values, or a single value if a
property is specified. property is specified.
:rtype: Union[Any, dict[str, Any]]
Example: Example:
@@ -157,17 +150,11 @@ def get_psets(
occurrence, not the type's pset. occurrence, not the type's pset.
:param element: The IFC Element entity :param element: The IFC Element entity
:type element: ifcopenshell.entity_instance
:param psets_only: Default as False. Set to true if only property sets are needed. :param psets_only: Default as False. Set to true if only property sets are needed.
:type psets_only: bool,optional
:param qtos_only: Default as False. Set to true if only quantities are needed. :param qtos_only: Default as False. Set to true if only quantities are needed.
:type qtos_only: bool,optional
:param should_inherit: Default as True. Set to false if you don't want to inherit property sets from the Type. :param should_inherit: Default as True. Set to false if you don't want to inherit property sets from the Type.
:type should_inherit: bool,optional
:param verbose: More detailed prop values, defaults to False. :param verbose: More detailed prop values, defaults to False.
:type verbose: bool,optional
:return: Key, value pair of psets' names and their properties' names & values :return: Key, value pair of psets' names and their properties' names & values
:rtype: dict[str, dict[str, Any]]
Example: Example:
@@ -471,9 +458,7 @@ def get_predefined_type(element: ifcopenshell.entity_instance) -> str:
considered first. considered first.
:param element: The IFC Element entity :param element: The IFC Element entity
:type element: ifcopenshell.entity_instance
:return: The predefined type of the element :return: The predefined type of the element
:rtype: str
Example: Example:
@@ -503,9 +488,7 @@ def get_type(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity
Note: `get_type(type_element) == type_element`. Note: `get_type(type_element) == type_element`.
:param element: The element occurrence (IfcObject) :param element: The element occurrence (IfcObject)
:type: ifcopenshell.entity_instance
:return: The related type element :return: The related type element
:rtype: Union[ifcopenshell.entity_instance, None]
Example: Example:
@@ -533,9 +516,7 @@ def get_types(type: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_in
"""Get all the occurrences of a type element """Get all the occurrences of a type element
:param type: The type element :param type: The type element
:type type: ifcopenshell.entity_instance
:return: A list of occurrences of that type :return: A list of occurrences of that type
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -588,17 +569,13 @@ def get_material(
constituent), or a material set usage. constituent), or a material set usage.
:param element: The element to get the material of. :param element: The element to get the material of.
:type element: ifcopenshell.entity_instance
:param should_skip_usage: If set to True, if the material is a material set :param should_skip_usage: If set to True, if the material is a material set
usage, the material set itself will be returned. Useful if you don't usage, the material set itself will be returned. Useful if you don't
care about occurrence usage parameters. If False, the usage will be care about occurrence usage parameters. If False, the usage will be
returned. returned.
:type should_skip_usage: bool
:param should_inherit: If True, any inherited materials from associated :param should_inherit: If True, any inherited materials from associated
types will be considered. types will be considered.
:type should_inherit: bool
:return: The associated material of the element or `None`. :return: The associated material of the element or `None`.
:rtype: Union[ifcopenshell.entity_instance, None]
Example: Example:
@@ -632,11 +609,9 @@ def get_materials(
returned as a list. returned as a list.
:param element: The element to get the materials of. :param element: The element to get the materials of.
:type element: ifcopenshell.entity_instance
:param should_inherit: If True, any inherited materials from associated :param should_inherit: If True, any inherited materials from associated
types will be considered. types will be considered.
:return: The associated materials of the element. :return: The associated materials of the element.
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -658,6 +633,8 @@ def get_materials(
return [c.Material for c in material.MaterialConstituents] return [c.Material for c in material.MaterialConstituents]
elif material.is_a("IfcMaterialList"): elif material.is_a("IfcMaterialList"):
return list(material.Materials) return list(material.Materials)
else:
assert False, f"Unexpected material type: {material.is_a()}"
def get_styles(element: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: def get_styles(element: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
@@ -666,9 +643,7 @@ def get_styles(element: ifcopenshell.entity_instance) -> list[ifcopenshell.entit
Styles may be retreived from the material or the body representation. Styles may be retreived from the material or the body representation.
:param element: The element to get the styles of. :param element: The element to get the styles of.
:type element: ifcopenshell.entity_instance
:return: A list of surface styles :return: A list of surface styles
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -749,15 +724,12 @@ def get_elements_by_material(
def get_elements_by_style( def get_elements_by_style(
ifc_file: ifcopenshell.file, style: ifcopenshell.entity_instance ifc_file: ifcopenshell.file, style: ifcopenshell.entity_instance
) -> list[ifcopenshell.entity_instance]: ) -> set[ifcopenshell.entity_instance]:
"""Retrieves the elements whose geometric representation uses a style """Retrieves the elements whose geometric representation uses a style
:param ifc_file: The IFC file :param ifc_file: The IFC file
:type ifc_file: ifcopenshell.file
:param style: The IfcPresentationStyle entity :param style: The IfcPresentationStyle entity
:type style: ifcopenshell.entity_instance
:return: The elements related to the style :return: The elements related to the style
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -804,11 +776,8 @@ def get_elements_by_representation(
"""Gets all elements using a geometric representation """Gets all elements using a geometric representation
:param ifc_file: The IFC file :param ifc_file: The IFC file
:type ifc_file: ifcopenshell.file
:param representation: The IfcShapeRepresentation representation :param representation: The IfcShapeRepresentation representation
:type representation: ifcopenshell.entity_instance
:return: The elements using the geometric representation :return: The elements using the geometric representation
:rtype: set[ifcopenshell.entity_instance]
Example: Example:
@@ -834,15 +803,12 @@ def get_elements_by_representation(
def get_elements_by_layer( def get_elements_by_layer(
ifc_file: ifcopenshell.file, layer: ifcopenshell.entity_instance ifc_file: ifcopenshell.file, layer: ifcopenshell.entity_instance
) -> list[ifcopenshell.entity_instance]: ) -> set[ifcopenshell.entity_instance]:
"""Get all the elements that are used by a presentation layer """Get all the elements that are used by a presentation layer
:param ifc_file: The IFC file :param ifc_file: The IFC file
:type ifc_file: ifcopenshell.file
:param layer: The IfcPresentationLayerAssignment layer :param layer: The IfcPresentationLayerAssignment layer
:type layer: ifcopenshell.entity_instance
:return: The elements using the geometric representation :return: The elements using the geometric representation
:rtype: list[ifcopenshell.entity_instance]
""" """
results = set() results = set()
for item in layer.AssignedItems or []: for item in layer.AssignedItems or []:
@@ -864,11 +830,8 @@ def get_layers(
traditional CAD presentation layer. traditional CAD presentation layer.
:param ifc_file: The IFC file object :param ifc_file: The IFC file object
:type ifc_file: ifcopenshell.file
:param element: The IFC element to interrogate :param element: The IFC element to interrogate
:type element: ifcopenshell.entity_instance
:return: A list of IfcPresentationLayerAssignment :return: A list of IfcPresentationLayerAssignment
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -902,18 +865,14 @@ def get_container(
Retrieves the spatial structure container of an element. Retrieves the spatial structure container of an element.
:param element: The IFC element :param element: The IFC element
:type element: ifcopenshell.entity_instance
:param should_get_direct: If True, a result is only returned if the element :param should_get_direct: If True, a result is only returned if the element
is directly contained in a spatial structure element. If False, an is directly contained in a spatial structure element. If False, an
indirect spatial container may be returned, such as if an element is a indirect spatial container may be returned, such as if an element is a
part of an aggregate, and then if that aggregate is contained in a part of an aggregate, and then if that aggregate is contained in a
spatial structure element. spatial structure element.
:type should_get_direct: bool
:param ifc_class: Optionally filter the type of container you're after. For :param ifc_class: Optionally filter the type of container you're after. For
example, you may be after the storey, not a space. example, you may be after the storey, not a space.
:type ifc_class: str, optional
:return: The direct or indirect container of the element or None. :return: The direct or indirect container of the element or None.
:rtype: Union[ifcopenshell.entity_instance, None]
Example: Example:
@@ -958,9 +917,7 @@ def get_referenced_structures(element: ifcopenshell.entity_instance) -> list[ifc
as stairs, doors, etc. as stairs, doors, etc.
:param element: The IFC element :param element: The IFC element
:type element: ifcopenshell.entity_instance
:return: A list of IfcSpatialElement :return: A list of IfcSpatialElement
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -976,9 +933,7 @@ def get_structure_referenced_elements(structure: ifcopenshell.entity_instance) -
"""Retreives a set of elements referenced by a structure """Retreives a set of elements referenced by a structure
:param structure: IfcSpatialElement :param structure: IfcSpatialElement
:type element: ifcopenshell.entity_instance
:return: A set of referenced elements, IfcSpatialReferenceSelect :return: A set of referenced elements, IfcSpatialReferenceSelect
:rtype: set[ifcopenshell.entity_instance]
Example: Example:
@@ -1000,9 +955,7 @@ def get_decomposition(element: ifcopenshell.entity_instance, is_recursive=True)
parts of an aggreate, all openings, and all fills of any openings. parts of an aggreate, all openings, and all fills of any openings.
:param element: The IFC element :param element: The IFC element
:type element: ifcopenshell.entity_instance
:return: The decomposition of the element :return: The decomposition of the element
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -1044,9 +997,7 @@ def get_grouped_by(element: ifcopenshell.entity_instance) -> list[ifcopenshell.e
"""Retrieves all subelements of an element based on the group. """Retrieves all subelements of an element based on the group.
:param element: IfcGroup entity :param element: IfcGroup entity
:type element: ifcopenshell.entity_instance
:return: All subelements of the group :return: All subelements of the group
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -1072,7 +1023,6 @@ def get_groups(element: ifcopenshell.entity_instance) -> list[ifcopenshell.entit
:param element: The IFC element :param element: The IFC element
:return: List of IfcGroups element is assigned to. :return: List of IfcGroups element is assigned to.
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -1105,9 +1055,7 @@ def get_parent(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.enti
- Voiding: the opening voids another physical element, such as a hole in a wall - Voiding: the opening voids another physical element, such as a hole in a wall
:param element: Any physical or spatial element in the tree :param element: Any physical or spatial element in the tree
:type element: ifcopenshell.entity_instance
:return: Its parent. This must exist for any valid file, or None if we've reached the IfcProject. :return: Its parent. This must exist for any valid file, or None if we've reached the IfcProject.
:rtype: Union[ifcopenshell.entity_instance, None]
Example: Example:
@@ -1131,9 +1079,7 @@ def get_filled_void(element: ifcopenshell.entity_instance) -> Union[ifcopenshell
Examples include windows and doors which fill a opening inside a wall. Examples include windows and doors which fill a opening inside a wall.
:param element: The building element, typically a window or door :param element: The building element, typically a window or door
:type element: ifcopenshell.entity_instance
:return: The IfcOpeningElement that it is filling :return: The IfcOpeningElement that it is filling
:rtype: Union[ifcopenshell.entity_instance, None]
Example: Example:
@@ -1152,9 +1098,7 @@ def get_voided_element(element: ifcopenshell.entity_instance) -> Union[ifcopensh
For all valid models, this should never return None. For all valid models, this should never return None.
:param element: The IfcOpeningElement :param element: The IfcOpeningElement
:type element: ifcopenshell.entity_instance
:return: The building element, such as a wall or slab :return: The building element, such as a wall or slab
:rtype: Union[ifcopenshell.entity_instance, None]
Example: Example:
@@ -1172,9 +1116,7 @@ def get_aggregate(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.e
Retrieves the aggregate parent of an element. Retrieves the aggregate parent of an element.
:param element: The IFC element :param element: The IFC element
:type element: ifcopenshell.entity_instance
:return: The aggregate of the element :return: The aggregate of the element
:rtype: Union[ifcopenshell.entity_instance, None]
Example: Example:
@@ -1193,9 +1135,7 @@ def get_nest(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity
Retrieves the nest parent of an element. Retrieves the nest parent of an element.
:param element: The IFC element :param element: The IFC element
:type element: ifcopenshell.entity_instance
:return: The nested whole of the element :return: The nested whole of the element
:rtype: Union[ifcopenshell.entity_instance, None]
Example: Example:
@@ -1217,9 +1157,7 @@ def get_parts(element: ifcopenshell.entity_instance) -> list[ifcopenshell.entity
Retrieves the parts of an element that have an aggregation relationship. Retrieves the parts of an element that have an aggregation relationship.
:param element: The IFC element :param element: The IFC element
:type element: ifcopenshell.entity_instance
:return: The parts of the element :return: The parts of the element
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -1239,9 +1177,7 @@ def get_contained(element: ifcopenshell.entity_instance) -> list[ifcopenshell.en
Retrieves the contained elements of spatial element. Retrieves the contained elements of spatial element.
:param element: The IFC element :param element: The IFC element
:type element: ifcopenshell.entity_instance
:return: The parts of the element :return: The parts of the element
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -1263,9 +1199,7 @@ def get_components(element: ifcopenshell.entity_instance, include_ports=False) -
:param element: The IFC element :param element: The IFC element
:param include_ports: Default as False. Set to true if you also want to get ports. :param include_ports: Default as False. Set to true if you also want to get ports.
:type include_ports: bool,optional
:return: The components of the element :return: The components of the element
:rtype: list[ifcopenshell.entity_instance]
Example: Example:
@@ -1314,9 +1248,7 @@ def get_referenced_elements(reference: ifcopenshell.entity_instance) -> set[ifco
"""Get all elements with assigned `reference` """Get all elements with assigned `reference`
:param reference: IfcExternalReference/IfcExternalInformation subtype reference :param reference: IfcExternalReference/IfcExternalInformation subtype reference
:type reference: ifcopenshell.entity_instance
:return: The elements with assigned `reference` :return: The elements with assigned `reference`
:rtype: set[ifcopenshell.entity_instance]
Example: Example:
@@ -1401,8 +1333,6 @@ def batch_remove_deep2(ifc_file: ifcopenshell.file) -> None:
on existing variables in memory. on existing variables in memory.
:param ifc_file: The IFC file object :param ifc_file: The IFC file object
:type ifc_file: ifcopenshell.file
:rtype: None
Example: Example:
@@ -1428,9 +1358,7 @@ def unbatch_remove_deep2(ifc_file: ifcopenshell.file) -> ifcopenshell.file:
See documentation for batch_remove_deep2. See documentation for batch_remove_deep2.
:param ifc_file: The IFC file object :param ifc_file: The IFC file object
:type ifc_file: ifcopenshell.file
:return: A newly loaded file with the elements removed. :return: A newly loaded file with the elements removed.
:rtype: ifcopenshell.file
""" """
ifc_string = ifc_file.to_string() ifc_string = ifc_file.to_string()
lines = iter(ifc_string.split("\n")) lines = iter(ifc_string.split("\n"))
@@ -1483,13 +1411,9 @@ def remove_deep2(
subgraph but are protected from deletion. subgraph but are protected from deletion.
:param ifc_file: The IFC file object :param ifc_file: The IFC file object
:type ifc_file: ifcopenshell.file
:param also_consider: elements to also consider as a part of a subgraph :param also_consider: elements to also consider as a part of a subgraph
:type also_consider: list[ifcopenshell.entity_instance], optional
:param do_not_delete: elements to protect from deletion :param do_not_delete: elements to protect from deletion
:type do_not_delete: list[ifcopenshell.entity_instance], optional
:param element: The starting element that defines the subgraph :param element: The starting element that defines the subgraph
:type element: ifcopenshell.entity_instance
""" """
# ifc_file.batch() # ifc_file.batch()
also_considered_inverses = 0 also_considered_inverses = 0
@@ -1554,11 +1478,8 @@ def copy(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance) ->
GlobalIds are regenerated. GlobalIds are regenerated.
:param ifc_file: The IFC file object :param ifc_file: The IFC file object
:type ifc_file: ifcopenshell.file
:param element: The IFC element to copy :param element: The IFC element to copy
:type element: ifcopenshell.entity_instance
:return: The newly copied element :return: The newly copied element
:rtype: ifcopenshell.entity_instance
""" """
new = ifc_file.create_entity(element.is_a()) new = ifc_file.create_entity(element.is_a())
for i, attribute in enumerate(element): for i, attribute in enumerate(element):
@@ -1584,22 +1505,16 @@ def copy_deep(
GlobalIds are regenerated. GlobalIds are regenerated.
:param ifc_file: The IFC file object :param ifc_file: The IFC file object
:type ifc_file: ifcopenshell.file
:param element: The IFC element to copy :param element: The IFC element to copy
:type element: ifcopenshell.entity_instance
:param exclude: An optional list of strings of IFC class names to not copy. :param exclude: An optional list of strings of IFC class names to not copy.
If any of the subelement is this class, it will not be copied and the If any of the subelement is this class, it will not be copied and the
original instance will be referenced. original instance will be referenced.
:type exclude: list[str],optional
:param exclude_callback: A callback to determine whether or not to exclude :param exclude_callback: A callback to determine whether or not to exclude
an entity or not. Returns True to exclude and False to exclude. an entity or not. Returns True to exclude and False to exclude.
:type exclude_callback: function,optional
:param copied_entities: A dictionary of IDs as keys and entities as values :param copied_entities: A dictionary of IDs as keys and entities as values
to reuse when coming across the same entity twice. This can typically to reuse when coming across the same entity twice. This can typically
be left as None. be left as None.
:type copied_entities: dict[int:ifcopenshell.entity_instance], optional
:return: The newly copied element :return: The newly copied element
:rtype: ifcopenshell.entity_instance
""" """
if copied_entities is None: if copied_entities is None:
copied_entities = {} copied_entities = {}
@@ -1653,11 +1568,8 @@ def has_property(product: ifcopenshell.entity_instance, property_name: str) -> b
Check if a product has a property with a given name. Check if a product has a property with a given name.
:param product: The IFC product :param product: The IFC product
:type product: ifcopenshell.entity_instance
:param property_name: The property name :param property_name: The property name
:type property_name: str
:return: True if the product has the property, False otherwise :return: True if the product has the property, False otherwise
:rtype: bool
Example: Example:
@@ -27,7 +27,9 @@ from logging import Logger
class Patcher: class Patcher:
def __init__(self, src: str, file: ifcopenshell.file, logger: Logger, filepaths: Union[str, ifcopenshell.file]): def __init__(
self, src: str, file: ifcopenshell.file, logger: Logger, filepaths: list[Union[str, ifcopenshell.file]]
):
"""Merge two or more IFC models into one """Merge two or more IFC models into one
Note that other than combining the two (or more) IfcProject elements into Note that other than combining the two (or more) IfcProject elements into
@@ -40,7 +42,7 @@ class Patcher:
:param filepaths: The filepath(s) of the second (, third, ...) IFC model :param filepaths: The filepath(s) of the second (, third, ...) IFC model
to merge into the first. The first model is already specified as the to merge into the first. The first model is already specified as the
input to IfcPatch. input to IfcPatch.
:type filepaths: Union[str, ifcopenshell.file] :type filepaths: list[Union[str, ifcopenshell.file]]
:filter_glob filepaths: *.ifc;*.ifczip;*.ifcxml :filter_glob filepaths: *.ifc;*.ifczip;*.ifcxml
Example: Example:
@@ -60,10 +62,11 @@ class Patcher:
other = filepath other = filepath
else: else:
other = ifcopenshell.open(filepath) other = ifcopenshell.open(filepath)
assert isinstance(other, ifcopenshell.file)
self.merge(other) self.merge(other)
def merge(self, other): def merge(self, other: ifcopenshell.file) -> None:
if (main_unit := self.get_unit_name(self.file)) != self.get_unit_name(other): if (main_unit := self.get_unit_name(self.file)) != self.get_unit_name(other):
other = ifcopenshell.util.unit.convert_file_length_units(other, main_unit) other = ifcopenshell.util.unit.convert_file_length_units(other, main_unit)
@@ -128,7 +131,7 @@ class Patcher:
length_unit = ifcopenshell.util.unit.get_project_unit(ifc_file, "LENGTHUNIT") length_unit = ifcopenshell.util.unit.get_project_unit(ifc_file, "LENGTHUNIT")
return ifcopenshell.util.unit.get_full_unit_name(length_unit) return ifcopenshell.util.unit.get_full_unit_name(length_unit)
def reuse_existing_contexts(self): def reuse_existing_contexts(self) -> None:
to_delete = set() to_delete = set()
for added_context in self.added_contexts: for added_context in self.added_contexts: