ifcopenshell.api.project.append_asset

Module Contents

class ifcopenshell.api.project.append_asset.SafeRemovalContext(ifc_file: ifcopenshell.file, reuse_identities: dict[int, ifcopenshell.entity_instance], assume_asset_uniqueness_by_name: bool)

Context manager to ensure remove_deep won’t create invalid entities in reuse_identities leading to possible crashes.

Should be always used if removing an entity that was possibly added by file_add.

assume_asset_uniqueness_by_name: bool

If False, then all job is done by file.add and we don’t need to worry about invalid entities.

file: ifcopenshell.file
reuse_identities: dict[int, ifcopenshell.entity_instance]
class ifcopenshell.api.project.append_asset.Usecase
add_element(element: ifcopenshell.entity_instance) ifcopenshell.entity_instance | None

Add element and check all it’s subgraph inverses.

add_inverse_element(element: ifcopenshell.entity_instance) None

Add inverse element.

Inverse elements are requiring different method than file_add because they can reference many other assets that we are not interested in.

E.g. a IfcRelAssociatesMaterial referencing products unrelated to the current asset.

append_cost_schedule()
append_material()
append_presentation_style()
append_product()
append_profile_def()
append_type_product()
by_guid(guid: str) ifcopenshell.entity_instance | None
check_inverses(element: ifcopenshell.entity_instance) None

Add inverse elements for the whitelisted inverse attributes.

create_equivalent_context(added_context: ifcopenshell.entity_instance) ifcopenshell.entity_instance
execute()
file_add(element: ifcopenshell.entity_instance, conversion_factor: float | None = None) ifcopenshell.entity_instance

Reimplementation of file.add but taking into account that some elements (profiles, materials) are already existing (checking by their name) and shouldn’t be duplicated.

The problem with file.add it’s recursively adding element and all it’s attributes and there is no control to prevent it from adding certain type of elements.

get_equivalent_existing_context(added_context: ifcopenshell.entity_instance) ifcopenshell.entity_instance | None
get_existing_element(element: ifcopenshell.entity_instance) ifcopenshell.entity_instance | None

Get existing element for a library element.

Return element if it was already added with add_element or if it’s not necessary (model already has a replacement for it).

Note that if element is returned, it will be accepted as-is, it’s subgraph inverses won’t be checked.

Return None if element wasn’t added before and needs to be added.

has_whitelisted_inverses(element: ifcopenshell.entity_instance) bool
is_another_asset(element: ifcopenshell.entity_instance) bool

Is IFC entity from inverse attribute is another asset to append that should be skipped.

reuse_existing_contexts() None
added_elements: dict[int, ifcopenshell.entity_instance]

Elements added with add_element.

assume_asset_uniqueness_by_name: bool
file: ifcopenshell.file
reuse_identities: dict[int, ifcopenshell.entity_instance]

Mapping of old element ids to new elements, usually fiiled by file_add.

settings: dict[str, Any]
whitelisted_inverse_attributes: dict[str, list[str]]
ifcopenshell.api.project.append_asset.append_asset(file: ifcopenshell.file, library: ifcopenshell.file, element: ifcopenshell.entity_instance, reuse_identities: dict[int, ifcopenshell.entity_instance] | None = None, assume_asset_uniqueness_by_name: bool = True) ifcopenshell.entity_instance

Appends an asset from a library into the active project

A BIM library asset may be a type product (e.g. wall type), product (e.g. pump), material, profile, or cost schedule.

This copies the asset from the specified library file into the active project. It handles all details like ensuring that product materials, styles, properties, quantities, and so on are preserved.

If an asset contains geometry, the geometric contexts are also intelligentely transplanted such that existing equivalent contexts are reused.

Do not mix units.

Parameters:
  • library – The file object containing the asset.

  • element – An element in the library file of the asset. It may be an IfcTypeProduct, IfcProduct, IfcMaterial, IfcCostSchedule, or IfcProfileDef.

  • reuse_identities – Optional dictionary of mapped entities’ identities to the already created elements. It will be used to avoid creating duplicated inverse elements during multiple project.append_asset calls. If you want to add just 1 asset or if added assets won’t have any shared elements, then it can be left empty.

  • assume_asset_uniqueness_by_name – If True, checks if elements (profiles, materials, styles) with the same name already exist in the project and reuses them instead of appending new ones.

Returns:

The appended element

Example:

# Programmatically generate a library. You could do this visually too.
library = ifcopenshell.api.project.create_file()
root = ifcopenshell.api.root.create_entity(library, ifc_class="IfcProject", name="Demo Library")
context = ifcopenshell.api.root.create_entity(library,
    ifc_class="IfcProjectLibrary", name="Demo Library")
ifcopenshell.api.project.assign_declaration(library, definitions=[context], relating_context=root)

# Assign units for our example library
unit = ifcopenshell.api.unit.add_si_unit(library,
    unit_type="LENGTHUNIT", prefix="MILLI")
ifcopenshell.api.unit.assign_unit(library, units=[unit])

# Let's create a single asset of a 200mm thick concrete wall
wall_type = ifcopenshell.api.root.create_entity(library, ifc_class="IfcWallType", name="WAL01")
concrete = ifcopenshell.api.material.add_material(usecase.file, name="CON", category="concrete")
rel = ifcopenshell.api.material.assign_material(library,
    products=[wall_type], type="IfcMaterialLayerSet")
layer = ifcopenshell.api.material.add_layer(library,
    layer_set=rel.RelatingMaterial, material=concrete)
layer.Name = "Structure"
layer.LayerThickness = 200

# Mark our wall type as a reusable asset in our library.
ifcopenshell.api.project.assign_declaration(library,
    definitions=[wall_type], relating_context=context)

# Let's imagine we're starting a new project
model = ifcopenshell.api.project.create_file()
project = ifcopenshell.api.root.create_entity(model, ifc_class="IfcProject", name="Test")

# Now we can easily append our wall type from our library
wall_type = ifcopenshell.api.project.append_asset(model, library=library, element=wall_type)

Example of adding multiple assets and avoiding duplicated inverses:

# since occurrences of IfcWindow of the same type
# might have shared inverses (e.g. IfcStyledItem)
# we provide a dictionary that will be populated with newly created items
# and reused to avoid duplicated elements
reuse_identities = dict()

for element in ifcopenshell.util.selector.filter_elements(model, "IfcWindow"):
    ifcopenshell.api.project.append_asset(
        model, library=library,
        element=wall_type
        reuse_identities=reuse_identities
    )
ifcopenshell.api.project.append_asset.APPENDABLE_ASSET
ifcopenshell.api.project.append_asset.APPENDABLE_ASSET_TYPES