From ddb38b2ea011a9c5e4a343121e8cd7ad2dbaedc0 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 31 Jan 2022 18:28:31 +1100 Subject: [PATCH] The IfcOpenShell API now supports adding a distribution port. --- .../ifcopenshell/api/system/add_port.py | 36 +++++ .../test/api/root/test_remove_product.py | 132 ++++++++++++++++++ .../test/api/system/test_add_port.py | 31 ++++ 3 files changed, 199 insertions(+) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/system/add_port.py create mode 100644 src/ifcopenshell-python/test/api/root/test_remove_product.py create mode 100644 src/ifcopenshell-python/test/api/system/test_add_port.py diff --git a/src/ifcopenshell-python/ifcopenshell/api/system/add_port.py b/src/ifcopenshell-python/ifcopenshell/api/system/add_port.py new file mode 100644 index 0000000000..d6196231ee --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/system/add_port.py @@ -0,0 +1,36 @@ +# IfcOpenShell - IFC toolkit and geometry engine +# Copyright (C) 2022 Dion Moult +# +# This file is part of IfcOpenShell. +# +# IfcOpenShell is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcOpenShell is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with IfcOpenShell. If not, see . + +import ifcopenshell +import ifcopenshell.api + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = { + "element": None, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + port = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcDistributionPort") + if self.settings["element"]: + ifcopenshell.api.run("system.assign_port", self.file, element=self.settings["element"], port=port) + return port diff --git a/src/ifcopenshell-python/test/api/root/test_remove_product.py b/src/ifcopenshell-python/test/api/root/test_remove_product.py new file mode 100644 index 0000000000..7bfaef0243 --- /dev/null +++ b/src/ifcopenshell-python/test/api/root/test_remove_product.py @@ -0,0 +1,132 @@ +# IfcOpenShell - IFC toolkit and geometry engine +# Copyright (C) 2022 Dion Moult +# +# This file is part of IfcOpenShell. +# +# IfcOpenShell is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcOpenShell is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with IfcOpenShell. If not, see . + +import test.bootstrap +import ifcopenshell.api + + +class TestRemoveProduct(test.bootstrap.IFC4): + def test_removing_an_element_by_itself(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + ifcopenshell.api.run("root.remove_product", self.file, product=element) + assert len(self.file.by_type("IfcWall")) == 0 + + def test_removing_all_representations_of_an_element(self): + ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject") + ifcopenshell.api.run("unit.assign_unit", self.file) + context = ifcopenshell.api.run("context.add_context", self.file, context_type="Model") + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + element.Representation = self.file.createIfcProductDefinitionShape( + Representations=[ + self.file.createIfcShapeRepresentation( + ContextOfItems=context, Items=[self.file.createIfcExtrudedAreaSolid()] + ) + ] + ) + total_entities = len(list(self.file)) + ifcopenshell.api.run("root.remove_product", self.file, product=element) + assert len(list(self.file)) == total_entities - 4 + assert len(self.file.by_type("IfcProductDefinitionShape")) == 0 + assert len(self.file.by_type("IfcShapeRepresentation")) == 0 + assert len(self.file.by_type("IfcExtrudedAreaSolid")) == 0 + assert len(self.file.by_type("IfcWall")) == 0 + + def test_unassigning_but_not_removing_mapped_representations_of_an_element(self): + ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject") + ifcopenshell.api.run("unit.assign_unit", self.file) + context = ifcopenshell.api.run("context.add_context", self.file, context_type="Model") + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + ifcopenshell.api.run("type.assign_type", self.file, related_object=element, relating_type=element_type) + rep_map = self.file.createIfcRepresentationMap( + MappingOrigin=self.file.createIfcAxis2Placement3D(), + MappedRepresentation=self.file.createIfcShapeRepresentation( + ContextOfItems=context, Items=[self.file.createIfcExtrudedAreaSolid()] + ), + ) + element_type.RepresentationMaps = [rep_map] + element.Representation = self.file.createIfcProductDefinitionShape( + Representations=[ + self.file.createIfcShapeRepresentation( + ContextOfItems=context, + RepresentationType="MappedRepresentation", + Items=[ + self.file.createIfcMappedItem( + MappingSource=rep_map, MappingTarget=self.file.createIfcCartesianTransformationOperator3D() + ) + ], + ) + ] + ) + total_entities = len(list(self.file)) + assert len(self.file.by_type("IfcShapeRepresentation")) == 2 + ifcopenshell.api.run("root.remove_product", self.file, product=element) + assert len(list(self.file)) == total_entities - 5 + assert len(self.file.by_type("IfcProductDefinitionShape")) == 0 + assert len(self.file.by_type("IfcShapeRepresentation")) == 1 + assert len(self.file.by_type("IfcMappedItem")) == 0 + assert len(self.file.by_type("IfcCartesianTransformationOperator3D")) == 0 + assert len(self.file.by_type("IfcWall")) == 0 + + def test_removing_an_element_type_by_itself(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + ifcopenshell.api.run("root.remove_product", self.file, product=element) + assert len(self.file.by_type("IfcWallType")) == 0 + + def test_removing_all_openings_of_an_element(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + opening = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcOpeningElement") + ifcopenshell.api.run("void.add_opening", self.file, opening=opening, element=element) + total_entities = len(list(self.file)) + ifcopenshell.api.run("root.remove_product", self.file, product=element) + assert len(list(self.file)) == total_entities - 3 + assert len(self.file.by_type("IfcWall")) == 0 + assert len(self.file.by_type("IfcOpeningElement")) == 0 + assert len(self.file.by_type("IfcRelVoidsElement")) == 0 + + def test_removing_axes_of_a_grid(self): + grid = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcGrid") + axis = ifcopenshell.api.run("grid.create_grid_axis", self.file, uvw_axes="UAxes", grid=grid) + axis.AxisCurve = self.file.createIfcPolyline() + axis = ifcopenshell.api.run("grid.create_grid_axis", self.file, uvw_axes="VAxes", grid=grid) + axis.AxisCurve = self.file.createIfcPolyline() + total_entities = len(list(self.file)) + ifcopenshell.api.run("root.remove_product", self.file, product=grid) + assert len(list(self.file)) == 0 + + def test_removing_all_void_relationships_of_an_opening(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + opening = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcOpeningElement") + ifcopenshell.api.run("void.add_opening", self.file, opening=opening, element=element) + total_entities = len(list(self.file)) + ifcopenshell.api.run("root.remove_product", self.file, product=opening) + assert len(list(self.file)) == total_entities - 2 + assert len(self.file.by_type("IfcOpeningElement")) == 0 + assert len(self.file.by_type("IfcRelVoidsElement")) == 0 + + def test_removing_all_fill_relationships_of_a_filling(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + opening = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcOpeningElement") + filling = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcDoor") + ifcopenshell.api.run("void.add_opening", self.file, opening=opening, element=element) + ifcopenshell.api.run("void.add_filling", self.file, opening=opening, element=filling) + total_entities = len(list(self.file)) + ifcopenshell.api.run("root.remove_product", self.file, product=filling) + assert len(list(self.file)) == total_entities - 2 + assert len(self.file.by_type("IfcDoor")) == 0 + assert len(self.file.by_type("IfcRelFillsElement")) == 0 diff --git a/src/ifcopenshell-python/test/api/system/test_add_port.py b/src/ifcopenshell-python/test/api/system/test_add_port.py new file mode 100644 index 0000000000..e1d74be2e9 --- /dev/null +++ b/src/ifcopenshell-python/test/api/system/test_add_port.py @@ -0,0 +1,31 @@ +# IfcOpenShell - IFC toolkit and geometry engine +# Copyright (C) 2022 Dion Moult +# +# This file is part of IfcOpenShell. +# +# IfcOpenShell is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcOpenShell is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with IfcOpenShell. If not, see . + +import test.bootstrap +import ifcopenshell.api +import ifcopenshell.util.system + + +class TestAddPort(test.bootstrap.IFC4): + def test_run(self): + assert ifcopenshell.api.run("system.add_port", self.file).is_a("IfcDistributionPort") + + def test_assigning_a_port_as_well_if_an_element_is_specified(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcChiller") + port = ifcopenshell.api.run("system.add_port", self.file, element=element) + assert ifcopenshell.util.system.get_ports(element) == [port]