diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/remove_profile.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_profile.py index a6b05b2c3f..419dd93ae6 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/material/remove_profile.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_profile.py @@ -51,7 +51,7 @@ class Usecase: # Imagine a welded square along the length of the profile. welded_square = ifcopenshell.api.run("profile.add_arbitrary_profile", model, - profile=[(2.5, 2.5), (32.5, 2.5), (32.5, -2.5), (2.5, -2.5)]) + profile=[(.0025, .0025), (.0325, .0025), (.0325, -.0025), (.0025, -.0025), (.0025, .0025)]) weld_profile = ifcopenshell.api.run("material.add_profile", model, profile_set=material_set, material=steel, profile=welded_square) diff --git a/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py b/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py index 4867cad344..04060a1605 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py @@ -22,11 +22,68 @@ import ifcopenshell.api.owner.settings class Usecase: - def __init__(self, file, **settings): + def __init__(self, file, library=None, element=None): + """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. + + :param library: The file object containing the asset. + :type library: ifcopenshell.file.file + :param element: An element in the library file of the asset. It may be + an IfcTypeProduct, IfcProduct, IfcMaterial, IfcCostSchedule, or + IfcProfileDef. + :type library: ifcopenshell.entity_instance.entity_instance + :return: The appended element + :rtype: ifcopenshell.entity_instance.entity_instance + + Example:: + + # Programmatically generate a library. You could do this visually too. + library = ifcopenshell.api.run("project.create_file") + root = ifcopenshell.api.run("root.create_entity", library, ifc_class="IfcProject", name="Demo Library") + context = ifcopenshell.api.run("root.create_entity", library, + ifc_class="IfcProjectLibrary", name="Demo Library") + ifcopenshell.api.run("project.assign_declaration", library, definition=context, relating_context=root) + + # Assign units for our example library + unit = ifcopenshell.api.run("unit.add_si_unit", library, + unit_type="LENGTHUNIT", name="METRE", prefix="MILLI") + ifcopenshell.api.run("unit.assign_unit", library, units=[unit]) + + # Let's create a single asset of a 200mm thick concrete wall + wall_type = ifcopenshell.api.run("root.create_entity", library, ifc_class="IfcWallType", name="WAL01") + concrete = ifcopenshell.api.run("material.add_material", self.file, name="CON", category="concrete") + rel = ifcopenshell.api.run("material.assign_material", library, + product=wall_type, type="IfcMaterialLayerSet") + layer = ifcopenshell.api.run("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.run("project.assign_declaration", library, + definition=wall_type, relating_context=context) + + # Let's imagine we're starting a new project + model = ifcopenshell.api.run("project.create_file") + project = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcProject", name="Test") + + # Now we can easily append our wall type from our libary + wall_type = ifcopenshell.api.run("project.append_asset", model, library=library, element=wall_type) + """ self.file = file - self.settings = {"library": None, "element": None} - for key, value in settings.items(): - self.settings[key] = value + self.settings = {"library": library, "element": element} def execute(self): self.added_elements = {} diff --git a/src/ifcopenshell-python/ifcopenshell/api/project/assign_declaration.py b/src/ifcopenshell-python/ifcopenshell/api/project/assign_declaration.py index 5bfefc6054..5793673efa 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/project/assign_declaration.py +++ b/src/ifcopenshell-python/ifcopenshell/api/project/assign_declaration.py @@ -21,14 +21,66 @@ import ifcopenshell.api class Usecase: - def __init__(self, file, **settings): + def __init__(self, file, definition=None, relating_context=None): + """Declares an element to the project + + All data in a model must be directly or indirectly related to the + project. Most data is indirectly related, existing instead within the + spatial decomposition tree. Other data, such as types, may be declared + at the top level. + + Most of the time, the API handles declaration automatically for you. + There is one scenario where you might want to explicitly declare objects + to the project, and that's when you want to organise objects into + project libraries for future use (such as an assets library). Assigning + a declaration lets you say that an object belongs to a library. + + :param definition: The object you want to declare. Typically an asset. + :type definition: ifcopenshell.entity_instance.entity_instance + :param relating_context: The IfcProject, or more commonly the + IfcProjectLibrary that you want the object to be part of. + :type relating_context: ifcopenshell.entity_instance.entity_instance + :return: The new IfcRelDeclares relationship + :rtype: ifcopenshell.entity_instance.entity_instance + + Example:: + + # Programmatically generate a library. You could do this visually too. + library = ifcopenshell.api.run("project.create_file") + root = ifcopenshell.api.run("root.create_entity", library, ifc_class="IfcProject", name="Demo Library") + context = ifcopenshell.api.run("root.create_entity", library, + ifc_class="IfcProjectLibrary", name="Demo Library") + + # It's necessary to say our library is part of our project. + ifcopenshell.api.run("project.assign_declaration", library, definition=context, relating_context=root) + + # Assign units for our example library + unit = ifcopenshell.api.run("unit.add_si_unit", library, + unit_type="LENGTHUNIT", name="METRE", prefix="MILLI") + ifcopenshell.api.run("unit.assign_unit", library, units=[unit]) + + # Let's create a single asset of a 200mm thick concrete wall + wall_type = ifcopenshell.api.run("root.create_entity", library, ifc_class="IfcWallType", name="WAL01") + concrete = ifcopenshell.api.run("material.add_material", self.file, name="CON", category="concrete") + rel = ifcopenshell.api.run("material.assign_material", library, + product=wall_type, type="IfcMaterialLayerSet") + layer = ifcopenshell.api.run("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.run("project.assign_declaration", library, + definition=wall_type, relating_context=context) + + # All done, just for fun let's save our asset library to disk for later use. + library.write("/path/to/my-library.ifc") + """ self.file = file self.settings = { - "definition": None, - "relating_context": None, + "definition": definition, + "relating_context": relating_context, } - for key, value in settings.items(): - self.settings[key] = value def execute(self): declares = None diff --git a/src/ifcopenshell-python/ifcopenshell/api/project/create_file.py b/src/ifcopenshell-python/ifcopenshell/api/project/create_file.py index 7919d4c99d..d1f89fe11e 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/project/create_file.py +++ b/src/ifcopenshell-python/ifcopenshell/api/project/create_file.py @@ -38,6 +38,17 @@ class Usecase: :type version: str, optional :return: The created IFC file object. :rtype: ifcopenshell.file.file + + Example:: + + # Start a new model. + model = ifcopenshell.api.run("project.create_file") + + # It's currently a blank model, so typically the first thing we do + # is create a project in it. + project = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcProject", name="Test") + + # ... and off we go! """ self.settings = {"version": version} diff --git a/src/ifcopenshell-python/ifcopenshell/api/project/unassign_declaration.py b/src/ifcopenshell-python/ifcopenshell/api/project/unassign_declaration.py index 0e0cab829f..3b5d2e61c0 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/project/unassign_declaration.py +++ b/src/ifcopenshell-python/ifcopenshell/api/project/unassign_declaration.py @@ -21,14 +21,38 @@ import ifcopenshell.api class Usecase: - def __init__(self, file, **settings): + def __init__(self, file, definition=None, relating_context=None): + """Unassigns an object to a project or project library + + Typically used to remove an asset from a project library. + + :param definition: The object you want to undeclare. Typically an asset. + :type definition: ifcopenshell.entity_instance.entity_instance + :param relating_context: The IfcProject, or more commonly the + IfcProjectLibrary that you want the object to no longer be part of. + :type relating_context: ifcopenshell.entity_instance.entity_instance + :return: None + :rtype: None + + Example:: + + # Programmatically generate a library. You could do this visually too. + library = ifcopenshell.api.run("project.create_file") + root = ifcopenshell.api.run("root.create_entity", library, ifc_class="IfcProject", name="Demo Library") + context = ifcopenshell.api.run("root.create_entity", library, + ifc_class="IfcProjectLibrary", name="Demo Library") + + # It's necessary to say our library is part of our project. + ifcopenshell.api.run("project.assign_declaration", library, definition=context, relating_context=root) + + # Remove the library from our project + ifcopenshell.api.run("project.unassign_declaration", library, definition=context, relating_context=root) + """ self.file = file self.settings = { - "definition": None, - "relating_context": None, + "definition": definition, + "relating_context": relating_context, } - for key, value in settings.items(): - self.settings[key] = value def execute(self): if not self.settings["definition"].HasContext: