diff --git a/src/ifcopenshell-python/ifcopenshell/api/feature/remove_feature.py b/src/ifcopenshell-python/ifcopenshell/api/feature/remove_feature.py index ff847b39eb..100e886214 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/feature/remove_feature.py +++ b/src/ifcopenshell-python/ifcopenshell/api/feature/remove_feature.py @@ -22,11 +22,13 @@ import ifcopenshell.util.element def remove_feature(file: ifcopenshell.file, feature: ifcopenshell.entity_instance) -> None: - """Remove a feature + """Permanently delete a feature element and its void or projection relationship. - Fillings are retained as orphans. Featured elements remain. Features - cannot exist by themselves, so not only is the relationship removed, the - feature is also removed. + The feature entity (e.g. IfcOpeningElement) is removed from the model + along with its IfcRelVoidsElement or IfcRelProjectsElement relationship. + The host element (wall, slab, etc.) is unaffected. Any fillings (windows, + doors) that occupied the opening become orphaned and must be separately + deleted via root.remove_product. :param feature: The IfcFeatureElement to remove. diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_wall_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_wall_representation.py index ff62bae474..c542471896 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_wall_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_wall_representation.py @@ -47,7 +47,9 @@ def add_wall_representation( :param thickness: The thickness of the wall in meters. :param x_angle: The slope angle along the wall's X-axis, in radians. :param clippings: List of clipping definitions. Clippings can be `Clipping` objects - or dictionaries of arguments for `Clipping.parse`. + or dictionaries of arguments for `Clipping.parse`. Each clipping has a + ``normal`` that points toward the removed material (the discarded side), + not toward the kept material; see :func:`clip_solid` for details. :param booleans: List of any existing IfcBooleanResults. :return: IfcShapeRepresentation. """ diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/edit_object_placement.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/edit_object_placement.py index 7fbe44ce12..0d86b997f5 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/edit_object_placement.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/edit_object_placement.py @@ -52,10 +52,11 @@ def edit_object_placement( :param is_si: If True, the matrix is given in SI units. If false, in project units. :param should_transform_children: A child element is a nested element, - opening, filling, etc. If true, child elements will move along with the - parent. If false, child elements will stay where they are. Because most - placements in IFC are relative, this means that if a child moves, we - actually don't change their placement. + opening, filling, etc. If True, child elements move along with the + parent; pass True when moving an assembly (roof, furniture group, etc.) + and you want all children to follow. If False (default), child elements + keep their current world positions; their local placements are rewritten + to compensate for the parent move. :return: The new or updated IfcLocalPlacement entity """ usecase = Usecase() diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/regenerate_wall_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/regenerate_wall_representation.py index 9143577438..e59c6e1efa 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/regenerate_wall_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/regenerate_wall_representation.py @@ -69,6 +69,12 @@ def regenerate_wall_representation( additional extrusions are generated for each connection that boolean difference the base extrusion. + Clippings applied via :func:`geometry.clip_solid` or + :func:`geometry.clip_solid_bounded` are preserved only if the ``element`` + parameter was passed when creating them, which registers the result in the + ``BBIM_Boolean`` property set. Clippings created without that parameter + are silently discarded during regeneration. + This will also update the axis line representation (e.g. trim the axis line to any connections). diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_process.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_process.py index 302445483b..e7cca1dafa 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_process.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_process.py @@ -26,7 +26,7 @@ def assign_process( relating_process: ifcopenshell.entity_instance, related_object: ifcopenshell.entity_instance, ) -> ifcopenshell.entity_instance: - """Assigns an object to be related to a process, typically a construction task + """Assigns an object as an input, control, or resource of a process Processes work using the ICOM (Input, Controls, Outputs, Mechanisms) paradigm in IFC. This process model is commonly used in modeling @@ -63,6 +63,17 @@ def assign_process( For resources, any construction resource may be assigned to a task. + .. warning:: + + This function creates an **Input** relationship + (``IfcRelAssignsToProcess``), meaning the product is *consumed* or + *operated on* by the task — the typical case is demolition or + maintenance. + + If the task *constructs or installs* a product (e.g. erecting a wall + or fitting a window), use :func:`assign_product` instead, which + creates an **Output** relationship (``IfcRelAssignsToProduct``). + :param relating_process: The IfcProcess (typically IfcTask) that the input, control, or resource is related to. :param related_object: The IfcProduct (for input), IfcCostItem (for @@ -77,7 +88,7 @@ def assign_process( # need to be part of a work schedule. schedule = ifcopenshell.api.sequence.add_work_schedule(model, name="Construction Schedule A") - # Let's create a construction task. Note that the predefined type is + # Let's create a demolition task. Note that the predefined type is # important to distinguish types of tasks. task = ifcopenshell.api.sequence.add_task(model, work_schedule=schedule, name="Demolish existing", identification="A", predefined_type="DEMOLITION") @@ -85,8 +96,12 @@ def assign_process( # Let's say we have a wall somewhere. wall = ifcopenshell.api.root.create_entity(model, ifc_class="IfcWall") - # Let's demolish that wall! + # The wall is an INPUT to the demolition task (it will be consumed). ifcopenshell.api.sequence.assign_process(model, relating_process=task, related_object=wall) + + # For a construction task that BUILDS a wall, use assign_product instead: + # build_task = ifcopenshell.api.sequence.add_task(model, ..., predefined_type="CONSTRUCTION") + # ifcopenshell.api.sequence.assign_product(model, relating_product=wall, related_object=build_task) """ if related_object.HasAssignments: for assignment in related_object.HasAssignments: