mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 09:32:37 +00:00
Generate functions for all API usecases for better static code features. See #2693.
This commit is contained in:
@@ -22,3 +22,6 @@ One common use is spatial elements, such as how a site has multiple buildings,
|
|||||||
and a building has multiple storeys. Another is for regular elements, such as
|
and a building has multiple storeys. Another is for regular elements, such as
|
||||||
how a wall is made out of members and coverings.
|
how a wall is made out of members and coverings.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from .assign_object import assign_object
|
||||||
|
from .unassign_object import unassign_object
|
||||||
|
|||||||
@@ -23,13 +23,11 @@ import ifcopenshell.util.placement
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def assign_object(
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
file: ifcopenshell.file,
|
file: ifcopenshell.file,
|
||||||
products: list[ifcopenshell.entity_instance],
|
products: list[ifcopenshell.entity_instance],
|
||||||
relating_object: ifcopenshell.entity_instance,
|
relating_object: ifcopenshell.entity_instance,
|
||||||
):
|
) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
"""Assigns object as an aggregate to the products
|
"""Assigns object as an aggregate to the products
|
||||||
|
|
||||||
All physical IFC model elements must be part of a hierarchical tree
|
All physical IFC model elements must be part of a hierarchical tree
|
||||||
@@ -85,18 +83,16 @@ class Usecase:
|
|||||||
# The site has a building
|
# The site has a building
|
||||||
ifcopenshell.api.run("aggregate.assign_object", model, products=[subelement], relating_object=element)
|
ifcopenshell.api.run("aggregate.assign_object", model, products=[subelement], relating_object=element)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {
|
||||||
self.settings = {
|
|
||||||
"products": products,
|
"products": products,
|
||||||
"relating_object": relating_object,
|
"relating_object": relating_object,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self) -> Union[ifcopenshell.entity_instance, None]:
|
if not settings["products"]:
|
||||||
if not self.settings["products"]:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
products = set(self.settings["products"])
|
products = set(settings["products"])
|
||||||
relating_object = self.settings["relating_object"]
|
relating_object = settings["relating_object"]
|
||||||
is_decomposed_by = next((i for i in relating_object.IsDecomposedBy if i.is_a("IfcRelAggregates")), None)
|
is_decomposed_by = next((i for i in relating_object.IsDecomposedBy if i.is_a("IfcRelAggregates")), None)
|
||||||
|
|
||||||
previous_aggregates_rels: set[ifcopenshell.entity_instance] = set()
|
previous_aggregates_rels: set[ifcopenshell.entity_instance] = set()
|
||||||
@@ -126,30 +122,30 @@ class Usecase:
|
|||||||
# can be either only aggregated or only contained at the same time
|
# can be either only aggregated or only contained at the same time
|
||||||
# some product might not be able to have a container
|
# some product might not be able to have a container
|
||||||
possibly_contained_products = [p for p in products_without_aggregates if hasattr(p, "ContainedInStructure")]
|
possibly_contained_products = [p for p in products_without_aggregates if hasattr(p, "ContainedInStructure")]
|
||||||
ifcopenshell.api.run("spatial.unassign_container", self.file, products=possibly_contained_products)
|
ifcopenshell.api.run("spatial.unassign_container", file, products=possibly_contained_products)
|
||||||
|
|
||||||
# unassign elements from previous aggregates
|
# unassign elements from previous aggregates
|
||||||
for decomposes in previous_aggregates_rels:
|
for decomposes in previous_aggregates_rels:
|
||||||
related_objects = set(decomposes.RelatedObjects) - products
|
related_objects = set(decomposes.RelatedObjects) - products
|
||||||
if related_objects:
|
if related_objects:
|
||||||
decomposes.RelatedObjects = list(related_objects)
|
decomposes.RelatedObjects = list(related_objects)
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": decomposes})
|
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": decomposes})
|
||||||
else:
|
else:
|
||||||
history = decomposes.OwnerHistory
|
history = decomposes.OwnerHistory
|
||||||
self.file.remove(decomposes)
|
file.remove(decomposes)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|
||||||
# assign elements to a new aggregate
|
# assign elements to a new aggregate
|
||||||
if is_decomposed_by:
|
if is_decomposed_by:
|
||||||
is_decomposed_by.RelatedObjects = list(set(is_decomposed_by.RelatedObjects) | products)
|
is_decomposed_by.RelatedObjects = list(set(is_decomposed_by.RelatedObjects) | products)
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": is_decomposed_by})
|
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": is_decomposed_by})
|
||||||
else:
|
else:
|
||||||
is_decomposed_by = self.file.create_entity(
|
is_decomposed_by = file.create_entity(
|
||||||
"IfcRelAggregates",
|
"IfcRelAggregates",
|
||||||
**{
|
**{
|
||||||
"GlobalId": ifcopenshell.guid.new(),
|
"GlobalId": ifcopenshell.guid.new(),
|
||||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", file),
|
||||||
"RelatedObjects": list(products),
|
"RelatedObjects": list(products),
|
||||||
"RelatingObject": relating_object,
|
"RelatingObject": relating_object,
|
||||||
}
|
}
|
||||||
@@ -161,7 +157,7 @@ class Usecase:
|
|||||||
if placement and placement.is_a("IfcLocalPlacement"):
|
if placement and placement.is_a("IfcLocalPlacement"):
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
"geometry.edit_object_placement",
|
"geometry.edit_object_placement",
|
||||||
self.file,
|
file,
|
||||||
product=product,
|
product=product,
|
||||||
matrix=ifcopenshell.util.placement.get_local_placement(product.ObjectPlacement),
|
matrix=ifcopenshell.util.placement.get_local_placement(product.ObjectPlacement),
|
||||||
is_si=False,
|
is_si=False,
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def unassign_object(file: ifcopenshell.file, products: list[ifcopenshell.entity_instance]) -> None:
|
||||||
def __init__(self, file: ifcopenshell.file, products: list[ifcopenshell.entity_instance]):
|
|
||||||
"""Unassigns products from their aggregate
|
"""Unassigns products from their aggregate
|
||||||
|
|
||||||
A product (i.e. a smaller part of a whole) may be aggregated into zero
|
A product (i.e. a smaller part of a whole) may be aggregated into zero
|
||||||
@@ -57,11 +56,9 @@ class Usecase:
|
|||||||
# nothing is returned, relationship is removed
|
# nothing is returned, relationship is removed
|
||||||
ifcopenshell.api.run("aggregate.unassign_object", model, products=[subelement2])
|
ifcopenshell.api.run("aggregate.unassign_object", model, products=[subelement2])
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"products": products}
|
||||||
self.settings = {"products": products}
|
|
||||||
|
|
||||||
def execute(self) -> None:
|
products = set(settings["products"])
|
||||||
products = set(self.settings["products"])
|
|
||||||
rels = set(
|
rels = set(
|
||||||
rel
|
rel
|
||||||
for product in products
|
for product in products
|
||||||
@@ -72,9 +69,9 @@ class Usecase:
|
|||||||
related_objects = set(rel.RelatedObjects) - products
|
related_objects = set(rel.RelatedObjects) - products
|
||||||
if related_objects:
|
if related_objects:
|
||||||
rel.RelatedObjects = list(related_objects)
|
rel.RelatedObjects = list(related_objects)
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel})
|
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": rel})
|
||||||
else:
|
else:
|
||||||
history = rel.OwnerHistory
|
history = rel.OwnerHistory
|
||||||
self.file.remove(rel)
|
file.remove(rel)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|||||||
@@ -15,3 +15,5 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .edit_attributes import edit_attributes
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_attributes(file, product=None, attributes=None) -> None:
|
||||||
def __init__(self, file, product=None, attributes=None):
|
|
||||||
"""Edit the attributes of a product
|
"""Edit the attributes of a product
|
||||||
|
|
||||||
All IFC entities have attributes. Normally they can be edited directly,
|
All IFC entities have attributes. Normally they can be edited directly,
|
||||||
@@ -44,39 +43,25 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("attribute.edit_attributes", model,
|
ifcopenshell.api.run("attribute.edit_attributes", model,
|
||||||
product=element, attributes={"Name": "Waldo"})
|
product=element, attributes={"Name": "Waldo"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"product": product, "attributes": attributes or {}}
|
||||||
self.settings = {"product": product, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["product"], name, value)
|
||||||
setattr(self.settings["product"], name, value)
|
if hasattr(settings["product"], "PredefinedType"):
|
||||||
if hasattr(self.settings["product"], "PredefinedType"):
|
if hasattr(settings["product"], "ElementType"):
|
||||||
if hasattr(self.settings["product"], "ElementType"):
|
if settings["product"].ElementType is None and settings["product"].PredefinedType == "USERDEFINED":
|
||||||
if (
|
settings["product"].PredefinedType = "NOTDEFINED"
|
||||||
self.settings["product"].ElementType is None
|
elif settings["product"].ElementType and settings["product"].PredefinedType != "USERDEFINED":
|
||||||
and self.settings["product"].PredefinedType == "USERDEFINED"
|
settings["product"].PredefinedType = "USERDEFINED"
|
||||||
):
|
elif hasattr(settings["product"], "ObjectType"):
|
||||||
self.settings["product"].PredefinedType = "NOTDEFINED"
|
relating_type = ifcopenshell.util.element.get_type(settings["product"])
|
||||||
elif (
|
|
||||||
self.settings["product"].ElementType
|
|
||||||
and self.settings["product"].PredefinedType != "USERDEFINED"
|
|
||||||
):
|
|
||||||
self.settings["product"].PredefinedType = "USERDEFINED"
|
|
||||||
elif hasattr(self.settings["product"], "ObjectType"):
|
|
||||||
relating_type = ifcopenshell.util.element.get_type(self.settings["product"])
|
|
||||||
# Allow for None due to https://github.com/buildingSMART/IFC4.3.x-development/issues/818
|
# Allow for None due to https://github.com/buildingSMART/IFC4.3.x-development/issues/818
|
||||||
if relating_type and relating_type.PredefinedType not in ("NOTDEFINED", None):
|
if relating_type and relating_type.PredefinedType not in ("NOTDEFINED", None):
|
||||||
self.settings["product"].ObjectType = None
|
settings["product"].ObjectType = None
|
||||||
self.settings["product"].PredefinedType = None
|
settings["product"].PredefinedType = None
|
||||||
elif (
|
elif settings["product"].ObjectType is None and settings["product"].PredefinedType == "USERDEFINED":
|
||||||
self.settings["product"].ObjectType is None
|
settings["product"].PredefinedType = "NOTDEFINED"
|
||||||
and self.settings["product"].PredefinedType == "USERDEFINED"
|
elif settings["product"].ObjectType and settings["product"].PredefinedType != "USERDEFINED":
|
||||||
):
|
settings["product"].PredefinedType = "USERDEFINED"
|
||||||
self.settings["product"].PredefinedType = "NOTDEFINED"
|
if hasattr(settings["product"], "OwnerHistory"):
|
||||||
elif (
|
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": settings["product"]})
|
||||||
self.settings["product"].ObjectType
|
|
||||||
and self.settings["product"].PredefinedType != "USERDEFINED"
|
|
||||||
):
|
|
||||||
self.settings["product"].PredefinedType = "USERDEFINED"
|
|
||||||
if hasattr(self.settings["product"], "OwnerHistory"):
|
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": self.settings["product"]})
|
|
||||||
|
|||||||
@@ -19,3 +19,8 @@
|
|||||||
"""Boundaries are primarily used for representing virtual interfaces between
|
"""Boundaries are primarily used for representing virtual interfaces between
|
||||||
spaces for energy analysis.
|
spaces for energy analysis.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from .assign_connection_geometry import assign_connection_geometry
|
||||||
|
from .copy_boundary import copy_boundary
|
||||||
|
from .edit_attributes import edit_attributes
|
||||||
|
from .remove_boundary import remove_boundary
|
||||||
|
|||||||
@@ -19,8 +19,16 @@
|
|||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def assign_connection_geometry(
|
||||||
def __init__(self, file, rel_space_boundary=None, outer_boundary=None, inner_boundaries=None, location=None, axis=None, ref_direction=None, unit_scale=None):
|
file,
|
||||||
|
rel_space_boundary=None,
|
||||||
|
outer_boundary=None,
|
||||||
|
inner_boundaries=None,
|
||||||
|
location=None,
|
||||||
|
axis=None,
|
||||||
|
ref_direction=None,
|
||||||
|
unit_scale=None,
|
||||||
|
) -> None:
|
||||||
"""Create and assign a connection geometry to a space boundary relationship
|
"""Create and assign a connection geometry to a space boundary relationship
|
||||||
|
|
||||||
A space boundary may optionally have a plane that represents how that
|
A space boundary may optionally have a plane that represents how that
|
||||||
@@ -71,16 +79,20 @@ class Usecase:
|
|||||||
location=[0., 0., 0.], axis=[1., 0., 0.], ref_direction=[0., 0., 1.],
|
location=[0., 0., 0.], axis=[1., 0., 0.], ref_direction=[0., 0., 1.],
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.rel_space_boundary = rel_space_boundary
|
usecase.file = file
|
||||||
self.outer_boundary = outer_boundary
|
usecase.rel_space_boundary = rel_space_boundary
|
||||||
self.inner_boundaries = inner_boundaries or ()
|
usecase.outer_boundary = outer_boundary
|
||||||
self.location = location
|
usecase.inner_boundaries = inner_boundaries or ()
|
||||||
self.axis = axis
|
usecase.location = location
|
||||||
self.ref_direction = ref_direction
|
usecase.axis = axis
|
||||||
self.unit_scale = unit_scale
|
usecase.ref_direction = ref_direction
|
||||||
self.ifc_vertices = []
|
usecase.unit_scale = unit_scale
|
||||||
|
usecase.ifc_vertices = []
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
if self.unit_scale is None:
|
if self.unit_scale is None:
|
||||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def copy_boundary(file, boundary=None) -> None:
|
||||||
def __init__(self, file, boundary=None):
|
|
||||||
"""Copies a space boundary
|
"""Copies a space boundary
|
||||||
|
|
||||||
:param boundary: The IfcRelSpaceBoundary you want to copy.
|
:param boundary: The IfcRelSpaceBoundary you want to copy.
|
||||||
@@ -37,11 +36,9 @@ class Usecase:
|
|||||||
# And now we have two
|
# And now we have two
|
||||||
boundary_copy = ifcopenshell.api.run("boundary.copy_boundary", model, boundary=boundary)
|
boundary_copy = ifcopenshell.api.run("boundary.copy_boundary", model, boundary=boundary)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"boundary": boundary}
|
||||||
self.settings = {"boundary": boundary}
|
|
||||||
|
|
||||||
def execute(self):
|
result = ifcopenshell.util.element.copy(file, settings["boundary"])
|
||||||
result = ifcopenshell.util.element.copy(self.file, self.settings["boundary"])
|
|
||||||
if result.ConnectionGeometry:
|
if result.ConnectionGeometry:
|
||||||
result.ConnectionGeometry = ifcopenshell.util.element.copy_deep(self.file, result.ConnectionGeometry)
|
result.ConnectionGeometry = ifcopenshell.util.element.copy_deep(file, result.ConnectionGeometry)
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -17,8 +17,14 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_attributes(
|
||||||
def __init__(self, file, entity=None, relating_space=None, related_building_element=None, parent_boundary=None, corresponding_boundary=None):
|
file,
|
||||||
|
entity=None,
|
||||||
|
relating_space=None,
|
||||||
|
related_building_element=None,
|
||||||
|
parent_boundary=None,
|
||||||
|
corresponding_boundary=None,
|
||||||
|
) -> None:
|
||||||
"""Modify the relationships of a space boundary relationship
|
"""Modify the relationships of a space boundary relationship
|
||||||
|
|
||||||
Currently this function is quite minimal and offers no advantage to
|
Currently this function is quite minimal and offers no advantage to
|
||||||
@@ -45,17 +51,15 @@ class Usecase:
|
|||||||
:return: None
|
:return: None
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
self.file = file
|
entity = entity
|
||||||
self.entity = entity
|
relating_space = relating_space
|
||||||
self.relating_space = relating_space
|
related_building_element = related_building_element
|
||||||
self.related_building_element = related_building_element
|
parent_boundary = parent_boundary
|
||||||
self.parent_boundary = parent_boundary
|
corresponding_boundary = corresponding_boundary
|
||||||
self.corresponding_boundary = corresponding_boundary
|
|
||||||
|
|
||||||
def execute(self):
|
entity.RelatingSpace = relating_space
|
||||||
self.entity.RelatingSpace = self.relating_space
|
entity.RelatedBuildingElement = related_building_element
|
||||||
self.entity.RelatedBuildingElement = self.related_building_element
|
if hasattr(entity, "ParentBoundary"):
|
||||||
if hasattr(self.entity, "ParentBoundary"):
|
entity.ParentBoundary = parent_boundary
|
||||||
self.entity.ParentBoundary = self.parent_boundary
|
if hasattr(entity, "CorrespondingBoundary"):
|
||||||
if hasattr(self.entity, "CorrespondingBoundary"):
|
entity.CorrespondingBoundary = corresponding_boundary
|
||||||
self.entity.CorrespondingBoundary = self.corresponding_boundary
|
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ import ifcopenshell
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_boundary(file, boundary=None) -> None:
|
||||||
def __init__(self, file, boundary=None):
|
|
||||||
"""Removes a space boundary
|
"""Removes a space boundary
|
||||||
|
|
||||||
The relating space or related building element is untouched. Only the
|
The relating space or related building element is untouched. Only the
|
||||||
@@ -41,15 +40,13 @@ class Usecase:
|
|||||||
# Let's remove it!
|
# Let's remove it!
|
||||||
ifcopenshell.api.run("boundary.remove_boundary", model, boundary=boundary)
|
ifcopenshell.api.run("boundary.remove_boundary", model, boundary=boundary)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"boundary": boundary}
|
||||||
self.settings = {"boundary": boundary}
|
|
||||||
|
|
||||||
def execute(self):
|
geometry = settings["boundary"].ConnectionGeometry
|
||||||
geometry = self.settings["boundary"].ConnectionGeometry
|
|
||||||
if geometry:
|
if geometry:
|
||||||
self.settings["boundary"].ConnectionGeometry = None
|
settings["boundary"].ConnectionGeometry = None
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, geometry)
|
ifcopenshell.util.element.remove_deep2(file, geometry)
|
||||||
history = self.settings["boundary"].OwnerHistory
|
history = settings["boundary"].OwnerHistory
|
||||||
self.file.remove(self.settings["boundary"])
|
file.remove(settings["boundary"])
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|||||||
@@ -15,3 +15,10 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .add_classification import add_classification
|
||||||
|
from .add_reference import add_reference
|
||||||
|
from .edit_classification import edit_classification
|
||||||
|
from .edit_reference import edit_reference
|
||||||
|
from .remove_classification import remove_classification
|
||||||
|
from .remove_reference import remove_reference
|
||||||
|
|||||||
@@ -22,8 +22,9 @@ import ifcopenshell.util.date
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_classification(
|
||||||
def __init__(self, file: ifcopenshell.file, classification: Union[str, ifcopenshell.entity_instance]):
|
file: ifcopenshell.file, classification: Union[str, ifcopenshell.entity_instance]
|
||||||
|
) -> ifcopenshell.entity_instance:
|
||||||
"""Adds a new classification system to the project
|
"""Adds a new classification system to the project
|
||||||
|
|
||||||
External classification systems such as Uniclass or Omniclass are
|
External classification systems such as Uniclass or Omniclass are
|
||||||
@@ -77,12 +78,16 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("classification.add_classification", model,
|
ifcopenshell.api.run("classification.add_classification", model,
|
||||||
classification=classification)
|
classification=classification)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"classification": classification,
|
"classification": classification,
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
def execute(self) -> ifcopenshell.entity_instance:
|
|
||||||
|
class Usecase:
|
||||||
|
def execute(self):
|
||||||
if isinstance(self.settings["classification"], str):
|
if isinstance(self.settings["classification"], str):
|
||||||
classification = self.file.createIfcClassification(Name=self.settings["classification"])
|
classification = self.file.createIfcClassification(Name=self.settings["classification"])
|
||||||
self.relate_to_project(classification)
|
self.relate_to_project(classification)
|
||||||
|
|||||||
@@ -23,9 +23,7 @@ import ifcopenshell.util.schema
|
|||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_reference(
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
file: ifcopenshell.file,
|
file: ifcopenshell.file,
|
||||||
products: list[ifcopenshell.entity_instance],
|
products: list[ifcopenshell.entity_instance],
|
||||||
reference: Optional[ifcopenshell.entity_instance] = None,
|
reference: Optional[ifcopenshell.entity_instance] = None,
|
||||||
@@ -33,7 +31,7 @@ class Usecase:
|
|||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
classification: Optional[ifcopenshell.entity_instance] = None,
|
classification: Optional[ifcopenshell.entity_instance] = None,
|
||||||
is_lightweight=True,
|
is_lightweight=True,
|
||||||
):
|
) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
"""Adds a new classification reference and assigns it to the list of products
|
"""Adds a new classification reference and assigns it to the list of products
|
||||||
|
|
||||||
A classification reference is a single entry such as "Pr_12_23_34" that
|
A classification reference is a single entry such as "Pr_12_23_34" that
|
||||||
@@ -123,8 +121,9 @@ class Usecase:
|
|||||||
products=[wall_type], classification=classification,
|
products=[wall_type], classification=classification,
|
||||||
reference=reference)
|
reference=reference)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"products": products,
|
"products": products,
|
||||||
"reference": reference,
|
"reference": reference,
|
||||||
"identification": identification,
|
"identification": identification,
|
||||||
@@ -132,8 +131,11 @@ class Usecase:
|
|||||||
"classification": classification,
|
"classification": classification,
|
||||||
"is_lightweight": is_lightweight,
|
"is_lightweight": is_lightweight,
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
def execute(self) -> Union[ifcopenshell.entity_instance, None]:
|
|
||||||
|
class Usecase:
|
||||||
|
def execute(self):
|
||||||
if not self.settings["products"]:
|
if not self.settings["products"]:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_classification(file, classification=None, attributes=None) -> None:
|
||||||
def __init__(self, file, classification=None, attributes=None):
|
|
||||||
"""Edits the attributes of an IfcClassification
|
"""Edits the attributes of an IfcClassification
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -40,9 +39,7 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("classification.edit_classification", model,
|
ifcopenshell.api.run("classification.edit_classification", model,
|
||||||
classification=classification, attributes={"Name": "Foo"})
|
classification=classification, attributes={"Name": "Foo"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"classification": classification, "attributes": attributes or {}}
|
||||||
self.settings = {"classification": classification, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["classification"], name, value)
|
||||||
setattr(self.settings["classification"], name, value)
|
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_reference(file, reference=None, attributes=None) -> None:
|
||||||
def __init__(self, file, reference=None, attributes=None):
|
|
||||||
"""Edits the attributes of an IfcClassificationReference
|
"""Edits the attributes of an IfcClassificationReference
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -40,9 +39,7 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("classification.edit_reference", model,
|
ifcopenshell.api.run("classification.edit_reference", model,
|
||||||
reference=reference, attributes={"Name": "Foo"})
|
reference=reference, attributes={"Name": "Foo"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"reference": reference, "attributes": attributes or {}}
|
||||||
self.settings = {"reference": reference, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["reference"], name, value)
|
||||||
setattr(self.settings["reference"], name, value)
|
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ import ifcopenshell
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_classification(file, classification=None) -> None:
|
||||||
def __init__(self, file, classification=None):
|
|
||||||
"""Removes an IfcClassification from the project and all references
|
"""Removes an IfcClassification from the project and all references
|
||||||
|
|
||||||
The classification and all of its relationships, children references,
|
The classification and all of its relationships, children references,
|
||||||
@@ -41,9 +40,13 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("classification.remove_classification", model,
|
ifcopenshell.api.run("classification.remove_classification", model,
|
||||||
classification=classification)
|
classification=classification)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {"classification": classification}
|
usecase.file = file
|
||||||
|
usecase.settings = {"classification": classification}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
references = self.get_references(self.settings["classification"])
|
references = self.get_references(self.settings["classification"])
|
||||||
for reference in references:
|
for reference in references:
|
||||||
|
|||||||
@@ -21,13 +21,11 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_reference(
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
file: ifcopenshell.file,
|
file: ifcopenshell.file,
|
||||||
reference: ifcopenshell.entity_instance,
|
reference: ifcopenshell.entity_instance,
|
||||||
products: list[ifcopenshell.entity_instance],
|
products: list[ifcopenshell.entity_instance],
|
||||||
):
|
) -> None:
|
||||||
"""Removes a classification reference from the list of products
|
"""Removes a classification reference from the list of products
|
||||||
|
|
||||||
If the classification reference is no longer associated to any products,
|
If the classification reference is no longer associated to any products,
|
||||||
@@ -58,13 +56,11 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("classification.remove_reference", model,
|
ifcopenshell.api.run("classification.remove_reference", model,
|
||||||
reference=reference, products=[wall_type])
|
reference=reference, products=[wall_type])
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"reference": reference, "products": products}
|
||||||
self.settings = {"reference": reference, "products": products}
|
|
||||||
|
|
||||||
def execute(self) -> None:
|
is_ifc2x3 = file.schema == "IFC2X3"
|
||||||
is_ifc2x3 = self.file.schema == "IFC2X3"
|
products = set(settings["products"])
|
||||||
products = set(self.settings["products"])
|
referenced = ifcopenshell.util.element.get_referenced_elements(settings["reference"])
|
||||||
referenced = ifcopenshell.util.element.get_referenced_elements(self.settings["reference"])
|
|
||||||
products -= products.difference(referenced)
|
products -= products.difference(referenced)
|
||||||
|
|
||||||
# all products are already unassigned from a reference
|
# all products are already unassigned from a reference
|
||||||
@@ -73,7 +69,7 @@ class Usecase:
|
|||||||
|
|
||||||
rooted_products: set[ifcopenshell.entity_instance] = set()
|
rooted_products: set[ifcopenshell.entity_instance] = set()
|
||||||
non_rooted_products: set[ifcopenshell.entity_instance] = set()
|
non_rooted_products: set[ifcopenshell.entity_instance] = set()
|
||||||
for product in self.settings["products"]:
|
for product in settings["products"]:
|
||||||
if product.is_a("IfcRoot"):
|
if product.is_a("IfcRoot"):
|
||||||
rooted_products.add(product)
|
rooted_products.add(product)
|
||||||
else:
|
else:
|
||||||
@@ -90,20 +86,19 @@ class Usecase:
|
|||||||
reference_rels = {
|
reference_rels = {
|
||||||
rel
|
rel
|
||||||
for rel in reference_rels
|
for rel in reference_rels
|
||||||
if rel.is_a("IfcRelAssociatesClassification")
|
if rel.is_a("IfcRelAssociatesClassification") and rel.RelatingClassification == settings["reference"]
|
||||||
and rel.RelatingClassification == self.settings["reference"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for rel in reference_rels:
|
for rel in reference_rels:
|
||||||
related_objects = set(rel.RelatedObjects) - rooted_products
|
related_objects = set(rel.RelatedObjects) - rooted_products
|
||||||
if related_objects:
|
if related_objects:
|
||||||
rel.RelatedObjects = list(related_objects)
|
rel.RelatedObjects = list(related_objects)
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel})
|
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": rel})
|
||||||
else:
|
else:
|
||||||
history = rel.OwnerHistory
|
history = rel.OwnerHistory
|
||||||
self.file.remove(rel)
|
file.remove(rel)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|
||||||
if non_rooted_products:
|
if non_rooted_products:
|
||||||
reference_rels: set[ifcopenshell.entity_instance] = set()
|
reference_rels: set[ifcopenshell.entity_instance] = set()
|
||||||
@@ -113,15 +108,15 @@ class Usecase:
|
|||||||
rels = getattr(product, "HasExternalReference", [])
|
rels = getattr(product, "HasExternalReference", [])
|
||||||
reference_rels.update(rels)
|
reference_rels.update(rels)
|
||||||
|
|
||||||
reference_rels = {rel for rel in reference_rels if rel.RelatingReference == self.settings["reference"]}
|
reference_rels = {rel for rel in reference_rels if rel.RelatingReference == settings["reference"]}
|
||||||
for rel in reference_rels:
|
for rel in reference_rels:
|
||||||
related_objects = set(rel.RelatedResourceObjects) - non_rooted_products
|
related_objects = set(rel.RelatedResourceObjects) - non_rooted_products
|
||||||
if related_objects:
|
if related_objects:
|
||||||
rel.RelatedResourceObjects = list(related_objects)
|
rel.RelatedResourceObjects = list(related_objects)
|
||||||
else:
|
else:
|
||||||
self.file.remove(rel)
|
file.remove(rel)
|
||||||
|
|
||||||
# TODO: we only handle lightweight classifications here
|
# TODO: we only handle lightweight classifications here
|
||||||
referenced_elements = ifcopenshell.util.element.get_referenced_elements(self.settings["reference"])
|
referenced_elements = ifcopenshell.util.element.get_referenced_elements(settings["reference"])
|
||||||
if not referenced_elements:
|
if not referenced_elements:
|
||||||
self.file.remove(self.settings["reference"])
|
file.remove(settings["reference"])
|
||||||
|
|||||||
@@ -15,3 +15,13 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .add_metric import add_metric
|
||||||
|
from .add_metric_reference import add_metric_reference
|
||||||
|
from .add_objective import add_objective
|
||||||
|
from .assign_constraint import assign_constraint
|
||||||
|
from .edit_metric import edit_metric
|
||||||
|
from .edit_objective import edit_objective
|
||||||
|
from .remove_constraint import remove_constraint
|
||||||
|
from .remove_metric import remove_metric
|
||||||
|
from .unassign_constraint import unassign_constraint
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_metric(file, objective=None) -> None:
|
||||||
def __init__(self, file, objective=None):
|
|
||||||
"""Add a new metric benchmark
|
"""Add a new metric benchmark
|
||||||
|
|
||||||
Qualitative constraints may have a series of quantitative benchmarks
|
Qualitative constraints may have a series of quantitative benchmarks
|
||||||
@@ -41,13 +40,11 @@ class Usecase:
|
|||||||
metric = ifcopenshell.api.run("constraint.add_metric", model,
|
metric = ifcopenshell.api.run("constraint.add_metric", model,
|
||||||
objective=objective)
|
objective=objective)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {
|
||||||
self.settings = {
|
|
||||||
"objective": objective,
|
"objective": objective,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self):
|
metric = file.create_entity(
|
||||||
metric = self.file.create_entity(
|
|
||||||
"IfcMetric",
|
"IfcMetric",
|
||||||
**{
|
**{
|
||||||
"Name": "Unnamed",
|
"Name": "Unnamed",
|
||||||
@@ -55,8 +52,8 @@ class Usecase:
|
|||||||
"Benchmark": "EQUALTO",
|
"Benchmark": "EQUALTO",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if self.settings["objective"]:
|
if settings["objective"]:
|
||||||
benchmark_values = list(self.settings["objective"].BenchmarkValues or [])
|
benchmark_values = list(settings["objective"].BenchmarkValues or [])
|
||||||
benchmark_values.append(metric)
|
benchmark_values.append(metric)
|
||||||
self.settings["objective"].BenchmarkValues = benchmark_values
|
settings["objective"].BenchmarkValues = benchmark_values
|
||||||
return metric
|
return metric
|
||||||
|
|||||||
@@ -18,28 +18,26 @@
|
|||||||
|
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
|
||||||
class Usecase:
|
|
||||||
def __init__(self, file, metric=None, reference_path=None):
|
def add_metric_reference(file, metric=None, reference_path=None) -> None:
|
||||||
"""
|
"""
|
||||||
Adds a chain of references to a metric. The reference path is a string of the form "attribute.attribute.attribute"
|
Adds a chain of references to a metric. The reference path is a string of the form "attribute.attribute.attribute"
|
||||||
Used to reference a value of an attribute of an instance through a metric objective entity.
|
Used to reference a value of an attribute of an instance through a metric objective entity.
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"metric": metric, "reference_path": reference_path}
|
||||||
self.settings = {"metric": metric, "reference_path": reference_path}
|
|
||||||
|
|
||||||
def execute(self):
|
if settings["reference_path"]:
|
||||||
if self.settings["reference_path"]:
|
attributes = settings["reference_path"].split(".")
|
||||||
attributes = self.settings["reference_path"].split(".")
|
|
||||||
references_created = []
|
references_created = []
|
||||||
for i in range(len(attributes)):
|
for i in range(len(attributes)):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
reference = self.file.create_entity("IfcReference")
|
reference = file.create_entity("IfcReference")
|
||||||
reference.AttributeIdentifier = attributes[i]
|
reference.AttributeIdentifier = attributes[i]
|
||||||
self.settings["metric"].ReferencePath = reference
|
settings["metric"].ReferencePath = reference
|
||||||
references_created.append(reference)
|
references_created.append(reference)
|
||||||
else:
|
else:
|
||||||
reference = self.file.create_entity("IfcReference")
|
reference = file.create_entity("IfcReference")
|
||||||
reference.AttributeIdentifier = attributes[i]
|
reference.AttributeIdentifier = attributes[i]
|
||||||
references_created[i-1].InnerReference = reference
|
references_created[i - 1].InnerReference = reference
|
||||||
references_created.append(reference)
|
references_created.append(reference)
|
||||||
return references_created
|
return references_created
|
||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_objective(file) -> None:
|
||||||
def __init__(self, file):
|
|
||||||
"""Add a new objective constraint
|
"""Add a new objective constraint
|
||||||
|
|
||||||
Parametric constraints may be defined by the user. The constraint is defined
|
Parametric constraints may be defined by the user. The constraint is defined
|
||||||
@@ -43,10 +42,8 @@ class Usecase:
|
|||||||
# Note: the objective right now is purely qualitative and for
|
# Note: the objective right now is purely qualitative and for
|
||||||
# information purposes. You may wish to add quantiative metrics.
|
# information purposes. You may wish to add quantiative metrics.
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {}
|
||||||
self.settings = {}
|
|
||||||
|
|
||||||
def execute(self):
|
return file.create_entity(
|
||||||
return self.file.create_entity(
|
|
||||||
"IfcObjective", **{"Name": "Unnamed", "ConstraintGrade": "NOTDEFINED", "ObjectiveQualifier": "NOTDEFINED"}
|
"IfcObjective", **{"Name": "Unnamed", "ConstraintGrade": "NOTDEFINED", "ObjectiveQualifier": "NOTDEFINED"}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,13 +21,11 @@ import ifcopenshell.api
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def assign_constraint(
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
file: ifcopenshell.file,
|
file: ifcopenshell.file,
|
||||||
products: list[ifcopenshell.entity_instance],
|
products: list[ifcopenshell.entity_instance],
|
||||||
constraint: ifcopenshell.entity_instance,
|
constraint: ifcopenshell.entity_instance,
|
||||||
):
|
) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
"""Assigns a constraint to a list of products
|
"""Assigns a constraint to a list of products
|
||||||
|
|
||||||
This assigns a relationship between a product and a constraint, so that
|
This assigns a relationship between a product and a constraint, so that
|
||||||
@@ -47,13 +45,17 @@ class Usecase:
|
|||||||
or `None` if `products` was an empty list.
|
or `None` if `products` was an empty list.
|
||||||
:rtype: ifcopenshell.entity_instance
|
:rtype: ifcopenshell.entity_instance
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"products": products,
|
"products": products,
|
||||||
"constraint": constraint,
|
"constraint": constraint,
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
def execute(self) -> Union[ifcopenshell.entity_instance, None]:
|
|
||||||
|
class Usecase:
|
||||||
|
def execute(self):
|
||||||
products = set(self.settings["products"])
|
products = set(self.settings["products"])
|
||||||
if not products:
|
if not products:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_metric(file, metric=None, attributes=None) -> None:
|
||||||
def __init__(self, file, metric=None, attributes=None):
|
|
||||||
"""Edit the attributes of a metric
|
"""Edit the attributes of a metric
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -41,9 +40,7 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("constraint.edit_metric", model,
|
ifcopenshell.api.run("constraint.edit_metric", model,
|
||||||
metric=metric, attributes={"ConstraintGrade": "HARD"})
|
metric=metric, attributes={"ConstraintGrade": "HARD"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"metric": metric, "attributes": attributes or {}}
|
||||||
self.settings = {"metric": metric, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["metric"], name, value)
|
||||||
setattr(self.settings["metric"], name, value)
|
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_objective(file, objective=None, attributes=None) -> None:
|
||||||
def __init__(self, file, objective=None, attributes=None):
|
|
||||||
"""Edit the attributes of a objective
|
"""Edit the attributes of a objective
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -39,9 +38,7 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("constraint.edit_objective", model,
|
ifcopenshell.api.run("constraint.edit_objective", model,
|
||||||
objective=objective, attributes={"ConstraintGrade": "HARD"})
|
objective=objective, attributes={"ConstraintGrade": "HARD"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"objective": objective, "attributes": attributes or {}}
|
||||||
self.settings = {"objective": objective, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["objective"], name, value)
|
||||||
setattr(self.settings["objective"], name, value)
|
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ import ifcopenshell
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_constraint(file, constraint=None) -> None:
|
||||||
def __init__(self, file, constraint=None):
|
|
||||||
"""Remove a constraint (typically an objective)
|
"""Remove a constraint (typically an objective)
|
||||||
|
|
||||||
Removes a constraint definition and all of its associations to any
|
Removes a constraint definition and all of its associations to any
|
||||||
@@ -42,14 +41,12 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("constraint.remove_constraint", model,
|
ifcopenshell.api.run("constraint.remove_constraint", model,
|
||||||
constraint=objective)
|
constraint=objective)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"constraint": constraint}
|
||||||
self.settings = {"constraint": constraint}
|
|
||||||
|
|
||||||
def execute(self):
|
file.remove(settings["constraint"])
|
||||||
self.file.remove(self.settings["constraint"])
|
for rel in file.by_type("IfcRelAssociatesConstraint"):
|
||||||
for rel in self.file.by_type("IfcRelAssociatesConstraint"):
|
|
||||||
if not rel.RelatingConstraint:
|
if not rel.RelatingConstraint:
|
||||||
history = rel.OwnerHistory
|
history = rel.OwnerHistory
|
||||||
self.file.remove(rel)
|
file.remove(rel)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_metric(file, metric=None) -> None:
|
||||||
def __init__(self, file, metric=None):
|
|
||||||
"""Remove a metric benchmark
|
"""Remove a metric benchmark
|
||||||
|
|
||||||
Removes a metric benchmark and all of its associations to any products
|
Removes a metric benchmark and all of its associations to any products
|
||||||
@@ -39,9 +38,13 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("constraint.remove_metric", model,
|
ifcopenshell.api.run("constraint.remove_metric", model,
|
||||||
metric=metric)
|
metric=metric)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {"metric": metric}
|
usecase.file = file
|
||||||
|
usecase.settings = {"metric": metric}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
if self.settings["metric"].ReferencePath:
|
if self.settings["metric"].ReferencePath:
|
||||||
reference = self.settings["metric"].ReferencePath
|
reference = self.settings["metric"].ReferencePath
|
||||||
|
|||||||
@@ -21,13 +21,11 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def unassign_constraint(
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
file: ifcopenshell.file,
|
file: ifcopenshell.file,
|
||||||
products: list[ifcopenshell.entity_instance],
|
products: list[ifcopenshell.entity_instance],
|
||||||
constraint: ifcopenshell.entity_instance,
|
constraint: ifcopenshell.entity_instance,
|
||||||
):
|
) -> None:
|
||||||
"""Unassigns a constraint from a list of products
|
"""Unassigns a constraint from a list of products
|
||||||
|
|
||||||
The constraint will not be deleted and is available to be assigned to
|
The constraint will not be deleted and is available to be assigned to
|
||||||
@@ -40,12 +38,16 @@ class Usecase:
|
|||||||
:return: None
|
:return: None
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"products": products,
|
"products": products,
|
||||||
"constraint": constraint,
|
"constraint": constraint,
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
products = set(self.settings["products"])
|
products = set(self.settings["products"])
|
||||||
if not products:
|
if not products:
|
||||||
|
|||||||
@@ -15,3 +15,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .add_context import add_context
|
||||||
|
from .edit_context import edit_context
|
||||||
|
from .remove_context import remove_context
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_context(file, context_type=None, context_identifier=None, target_view=None, parent=None) -> None:
|
||||||
def __init__(self, file, context_type=None, context_identifier=None, target_view=None, parent=None):
|
|
||||||
"""Adds a new geometric representation context
|
"""Adds a new geometric representation context
|
||||||
|
|
||||||
In IFC, physical objects may have zero, one, or multiple geometric
|
In IFC, physical objects may have zero, one, or multiple geometric
|
||||||
@@ -171,14 +170,18 @@ class Usecase:
|
|||||||
# Place our wall at the origin
|
# Place our wall at the origin
|
||||||
ifcopenshell.api.run("geometry.edit_object_placement", model, product=wall)
|
ifcopenshell.api.run("geometry.edit_object_placement", model, product=wall)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"context_type": context_type,
|
"context_type": context_type,
|
||||||
"parent": parent,
|
"parent": parent,
|
||||||
"context_identifier": context_identifier,
|
"context_identifier": context_identifier,
|
||||||
"target_view": target_view,
|
"target_view": target_view,
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
if not self.settings["parent"]:
|
if not self.settings["parent"]:
|
||||||
if self.settings["context_type"] == "Plan":
|
if self.settings["context_type"] == "Plan":
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_context(file, context, attributes) -> None:
|
||||||
def __init__(self, file, context, attributes):
|
|
||||||
"""Edits the attributes of an IfcGeometricRepresentationContext
|
"""Edits the attributes of an IfcGeometricRepresentationContext
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -45,9 +44,7 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("context.edit_context", model,
|
ifcopenshell.api.run("context.edit_context", model,
|
||||||
context=body, attributes={"ContextIdentifier": "Body"})
|
context=body, attributes={"ContextIdentifier": "Body"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"context": context, "attributes": attributes or {}}
|
||||||
self.settings = {"context": context, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["context"], name, value)
|
||||||
setattr(self.settings["context"], name, value)
|
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_context(file, context=None) -> None:
|
||||||
def __init__(self, file, context=None):
|
|
||||||
"""Removes an IfcGeometricRepresentationContext
|
"""Removes an IfcGeometricRepresentationContext
|
||||||
|
|
||||||
Any representation geometry that is assigned to the context is also
|
Any representation geometry that is assigned to the context is also
|
||||||
@@ -44,24 +43,22 @@ class Usecase:
|
|||||||
# Let's just get rid of it completely
|
# Let's just get rid of it completely
|
||||||
ifcopenshell.api.run("context.remove_context", model, context=body)
|
ifcopenshell.api.run("context.remove_context", model, context=body)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"context": context}
|
||||||
self.settings = {"context": context}
|
|
||||||
|
|
||||||
def execute(self):
|
for subcontext in settings["context"].HasSubContexts:
|
||||||
for subcontext in self.settings["context"].HasSubContexts:
|
ifcopenshell.api.run("context.remove_context", file, context=subcontext)
|
||||||
ifcopenshell.api.run("context.remove_context", self.file, context=subcontext)
|
|
||||||
|
|
||||||
if getattr(self.settings["context"], "ParentContext", None):
|
if getattr(settings["context"], "ParentContext", None):
|
||||||
new = self.settings["context"].ParentContext
|
new = settings["context"].ParentContext
|
||||||
for inverse in self.file.get_inverse(self.settings["context"]):
|
for inverse in file.get_inverse(settings["context"]):
|
||||||
if inverse.is_a("IfcCoordinateOperation"):
|
if inverse.is_a("IfcCoordinateOperation"):
|
||||||
inverse.SourceCRS = inverse.TargetCRS
|
inverse.SourceCRS = inverse.TargetCRS
|
||||||
ifcopenshell.util.element.remove_deep(self.file, inverse)
|
ifcopenshell.util.element.remove_deep(file, inverse)
|
||||||
else:
|
else:
|
||||||
ifcopenshell.util.element.replace_attribute(inverse, self.settings["context"], new)
|
ifcopenshell.util.element.replace_attribute(inverse, settings["context"], new)
|
||||||
self.file.remove(self.settings["context"])
|
file.remove(settings["context"])
|
||||||
else:
|
else:
|
||||||
representations_in_context = self.settings["context"].RepresentationsInContext
|
representations_in_context = settings["context"].RepresentationsInContext
|
||||||
self.file.remove(self.settings["context"])
|
file.remove(settings["context"])
|
||||||
for element in representations_in_context:
|
for element in representations_in_context:
|
||||||
ifcopenshell.api.run("geometry.remove_representation", self.file, representation=element)
|
ifcopenshell.api.run("geometry.remove_representation", file, representation=element)
|
||||||
|
|||||||
@@ -15,3 +15,6 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .assign_control import assign_control
|
||||||
|
from .unassign_control import unassign_control
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ import ifcopenshell
|
|||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def assign_control(file, relating_control=None, related_object=None) -> None:
|
||||||
def __init__(self, file, relating_control=None, related_object=None):
|
|
||||||
"""Assigns a planning control or constraint to an object
|
"""Assigns a planning control or constraint to an object
|
||||||
|
|
||||||
IFC can describe concepts that control other objects. For example, a
|
IFC can describe concepts that control other objects. For example, a
|
||||||
@@ -67,40 +66,35 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("control.assign_control", model,
|
ifcopenshell.api.run("control.assign_control", model,
|
||||||
relating_control=cost_item, related_object=wall)
|
relating_control=cost_item, related_object=wall)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {
|
||||||
self.settings = {
|
|
||||||
"relating_control": relating_control,
|
"relating_control": relating_control,
|
||||||
"related_object": related_object,
|
"related_object": related_object,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self):
|
if settings["related_object"].HasAssignments:
|
||||||
if self.settings["related_object"].HasAssignments:
|
for assignment in settings["related_object"].HasAssignments:
|
||||||
for assignment in self.settings["related_object"].HasAssignments:
|
if assignment.is_a("IfcRelAssignsToControl") and assignment.RelatingControl == settings["relating_control"]:
|
||||||
if (
|
|
||||||
assignment.is_a("IfcRelAssignsToControl")
|
|
||||||
and assignment.RelatingControl == self.settings["relating_control"]
|
|
||||||
):
|
|
||||||
return
|
return
|
||||||
|
|
||||||
controls = None
|
controls = None
|
||||||
if self.settings["relating_control"].Controls:
|
if settings["relating_control"].Controls:
|
||||||
controls = self.settings["relating_control"].Controls[0]
|
controls = settings["relating_control"].Controls[0]
|
||||||
|
|
||||||
if controls:
|
if controls:
|
||||||
if self.settings["related_object"] in controls.RelatedObjects:
|
if settings["related_object"] in controls.RelatedObjects:
|
||||||
return
|
return
|
||||||
related_objects = set(controls.RelatedObjects)
|
related_objects = set(controls.RelatedObjects)
|
||||||
related_objects.add(self.settings["related_object"])
|
related_objects.add(settings["related_object"])
|
||||||
controls.RelatedObjects = list(related_objects)
|
controls.RelatedObjects = list(related_objects)
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": controls})
|
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": controls})
|
||||||
else:
|
else:
|
||||||
controls = self.file.create_entity(
|
controls = file.create_entity(
|
||||||
"IfcRelAssignsToControl",
|
"IfcRelAssignsToControl",
|
||||||
**{
|
**{
|
||||||
"GlobalId": ifcopenshell.guid.new(),
|
"GlobalId": ifcopenshell.guid.new(),
|
||||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", file),
|
||||||
"RelatedObjects": [self.settings["related_object"]],
|
"RelatedObjects": [settings["related_object"]],
|
||||||
"RelatingControl": self.settings["relating_control"],
|
"RelatingControl": settings["relating_control"],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return controls
|
return controls
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def unassign_control(file, relating_control=None, related_object=None) -> None:
|
||||||
def __init__(self, file, relating_control=None, related_object=None):
|
|
||||||
"""Unassigns a planning control or constraint to an object
|
"""Unassigns a planning control or constraint to an object
|
||||||
|
|
||||||
:param relating_control: The IfcControl entity that is creating the
|
:param relating_control: The IfcControl entity that is creating the
|
||||||
@@ -51,24 +50,22 @@ class Usecase:
|
|||||||
relating_control=cost_item, related_object=wall)
|
relating_control=cost_item, related_object=wall)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.file = file
|
settings = {
|
||||||
self.settings = {
|
|
||||||
"relating_control": relating_control,
|
"relating_control": relating_control,
|
||||||
"related_object": related_object,
|
"related_object": related_object,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self):
|
for rel in settings["related_object"].HasAssignments or []:
|
||||||
for rel in self.settings["related_object"].HasAssignments or []:
|
if not rel.is_a("IfcRelAssignsToControl") or rel.RelatingControl != settings["relating_control"]:
|
||||||
if not rel.is_a("IfcRelAssignsToControl") or rel.RelatingControl != self.settings["relating_control"]:
|
|
||||||
continue
|
continue
|
||||||
if len(rel.RelatedObjects) == 1:
|
if len(rel.RelatedObjects) == 1:
|
||||||
history = rel.OwnerHistory
|
history = rel.OwnerHistory
|
||||||
self.file.remove(rel)
|
file.remove(rel)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
return
|
return
|
||||||
related_objects = list(rel.RelatedObjects)
|
related_objects = list(rel.RelatedObjects)
|
||||||
related_objects.remove(self.settings["related_object"])
|
related_objects.remove(settings["related_object"])
|
||||||
rel.RelatedObjects = related_objects
|
rel.RelatedObjects = related_objects
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel})
|
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": rel})
|
||||||
return rel
|
return rel
|
||||||
|
|||||||
@@ -15,3 +15,23 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .add_cost_item import add_cost_item
|
||||||
|
from .add_cost_item_quantity import add_cost_item_quantity
|
||||||
|
from .add_cost_schedule import add_cost_schedule
|
||||||
|
from .add_cost_value import add_cost_value
|
||||||
|
from .assign_cost_item_quantity import assign_cost_item_quantity
|
||||||
|
from .assign_cost_value import assign_cost_value
|
||||||
|
from .calculate_cost_item_resource_value import calculate_cost_item_resource_value
|
||||||
|
from .copy_cost_item import copy_cost_item
|
||||||
|
from .copy_cost_item_values import copy_cost_item_values
|
||||||
|
from .edit_cost_item import edit_cost_item
|
||||||
|
from .edit_cost_item_quantity import edit_cost_item_quantity
|
||||||
|
from .edit_cost_schedule import edit_cost_schedule
|
||||||
|
from .edit_cost_value import edit_cost_value
|
||||||
|
from .edit_cost_value_formula import edit_cost_value_formula
|
||||||
|
from .remove_cost_item import remove_cost_item
|
||||||
|
from .remove_cost_item_quantity import remove_cost_item_quantity
|
||||||
|
from .remove_cost_schedule import remove_cost_schedule
|
||||||
|
from .remove_cost_value import remove_cost_value
|
||||||
|
from .unassign_cost_item_quantity import unassign_cost_item_quantity
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_cost_item(file, cost_schedule=None, cost_item=None) -> None:
|
||||||
def __init__(self, file, cost_schedule=None, cost_item=None):
|
|
||||||
"""Add a new cost item
|
"""Add a new cost item
|
||||||
|
|
||||||
A cost item represents a single line item in a cost schedule. Cost items
|
A cost item represents a single line item in a cost schedule. Cost items
|
||||||
@@ -50,24 +49,22 @@ class Usecase:
|
|||||||
# Alternatively you may add them as subitems
|
# Alternatively you may add them as subitems
|
||||||
item2 = ifcopenshell.api.run("cost.add_cost_item", model, cost_item=item1)
|
item2 = ifcopenshell.api.run("cost.add_cost_item", model, cost_item=item1)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"cost_schedule": cost_schedule, "cost_item": cost_item}
|
||||||
self.settings = {"cost_schedule": cost_schedule, "cost_item": cost_item}
|
|
||||||
|
|
||||||
def execute(self):
|
cost_item = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcCostItem")
|
||||||
cost_item = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcCostItem")
|
|
||||||
|
|
||||||
if self.settings["cost_schedule"]:
|
if settings["cost_schedule"]:
|
||||||
self.file.create_entity(
|
file.create_entity(
|
||||||
"IfcRelAssignsToControl",
|
"IfcRelAssignsToControl",
|
||||||
**{
|
**{
|
||||||
"GlobalId": ifcopenshell.guid.new(),
|
"GlobalId": ifcopenshell.guid.new(),
|
||||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", file),
|
||||||
"RelatedObjects": [cost_item],
|
"RelatedObjects": [cost_item],
|
||||||
"RelatingControl": self.settings["cost_schedule"],
|
"RelatingControl": settings["cost_schedule"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
elif self.settings["cost_item"]:
|
elif settings["cost_item"]:
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
"nest.assign_object", self.file, related_objects=[cost_item], relating_object=self.settings["cost_item"]
|
"nest.assign_object", file, related_objects=[cost_item], relating_object=settings["cost_item"]
|
||||||
)
|
)
|
||||||
return cost_item
|
return cost_item
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_cost_item_quantity(file, cost_item=None, ifc_class="IfcQuantityCount") -> None:
|
||||||
def __init__(self, file, cost_item=None, ifc_class="IfcQuantityCount"):
|
|
||||||
"""Adds a new quantity associated with a cost item
|
"""Adds a new quantity associated with a cost item
|
||||||
|
|
||||||
Cost items calculate their subtotal by multiplying the sum of the cost
|
Cost items calculate their subtotal by multiplying the sum of the cost
|
||||||
@@ -72,20 +71,18 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("cost.add_cost_item_quantity", model,
|
ifcopenshell.api.run("cost.add_cost_item_quantity", model,
|
||||||
cost_item=item, ifc_class="IfcQuantityCount")
|
cost_item=item, ifc_class="IfcQuantityCount")
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"cost_item": cost_item, "ifc_class": ifc_class}
|
||||||
self.settings = {"cost_item": cost_item, "ifc_class": ifc_class}
|
|
||||||
|
|
||||||
def execute(self):
|
quantity = file.create_entity(settings["ifc_class"], Name="Unnamed")
|
||||||
quantity = self.file.create_entity(self.settings["ifc_class"], Name="Unnamed")
|
|
||||||
quantity[3] = 0.0
|
quantity[3] = 0.0
|
||||||
# This is a bold assumption
|
# This is a bold assumption
|
||||||
# https://forums.buildingsmart.org/t/how-does-a-cost-item-know-that-it-is-counting-a-controlled-product/3564
|
# https://forums.buildingsmart.org/t/how-does-a-cost-item-know-that-it-is-counting-a-controlled-product/3564
|
||||||
if self.settings["ifc_class"] == "IfcQuantityCount" and self.settings["cost_item"].Controls:
|
if settings["ifc_class"] == "IfcQuantityCount" and settings["cost_item"].Controls:
|
||||||
count = 0
|
count = 0
|
||||||
for rel in self.settings["cost_item"].Controls:
|
for rel in settings["cost_item"].Controls:
|
||||||
count += len(rel.RelatedObjects)
|
count += len(rel.RelatedObjects)
|
||||||
quantity[3] = count
|
quantity[3] = count
|
||||||
quantities = list(self.settings["cost_item"].CostQuantities or [])
|
quantities = list(settings["cost_item"].CostQuantities or [])
|
||||||
quantities.append(quantity)
|
quantities.append(quantity)
|
||||||
self.settings["cost_item"].CostQuantities = quantities
|
settings["cost_item"].CostQuantities = quantities
|
||||||
return quantity
|
return quantity
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import ifcopenshell.util.date
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_cost_schedule(file, name=None, predefined_type="NOTDEFINED") -> None:
|
||||||
def __init__(self, file, name=None, predefined_type="NOTDEFINED"):
|
|
||||||
"""Add a new cost schedule
|
"""Add a new cost schedule
|
||||||
|
|
||||||
A cost schedule is a group of cost items which typically represent a
|
A cost schedule is a group of cost items which typically represent a
|
||||||
@@ -53,16 +52,14 @@ class Usecase:
|
|||||||
# Now that we have a cost schedule, we may add cost items to it
|
# Now that we have a cost schedule, we may add cost items to it
|
||||||
item = ifcopenshell.api.run("cost.add_cost_item", model, cost_schedule=schedule)
|
item = ifcopenshell.api.run("cost.add_cost_item", model, cost_schedule=schedule)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"name": name, "predefined_type": predefined_type}
|
||||||
self.settings = {"name": name, "predefined_type": predefined_type}
|
|
||||||
|
|
||||||
def execute(self):
|
|
||||||
cost_schedule = ifcopenshell.api.run(
|
cost_schedule = ifcopenshell.api.run(
|
||||||
"root.create_entity",
|
"root.create_entity",
|
||||||
self.file,
|
file,
|
||||||
ifc_class="IfcCostSchedule",
|
ifc_class="IfcCostSchedule",
|
||||||
predefined_type=self.settings["predefined_type"],
|
predefined_type=settings["predefined_type"],
|
||||||
name=self.settings["name"],
|
name=settings["name"],
|
||||||
)
|
)
|
||||||
cost_schedule.UpdateDate = ifcopenshell.util.date.datetime2ifc(datetime.now(), "IfcDateTime")
|
cost_schedule.UpdateDate = ifcopenshell.util.date.datetime2ifc(datetime.now(), "IfcDateTime")
|
||||||
return cost_schedule
|
return cost_schedule
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_cost_value(file, parent=None) -> None:
|
||||||
def __init__(self, file, parent=None):
|
|
||||||
"""Adds a new value or subvalue to a cost item
|
"""Adds a new value or subvalue to a cost item
|
||||||
|
|
||||||
A cost item's subtotal can be specified in two ways.
|
A cost item's subtotal can be specified in two ways.
|
||||||
@@ -91,21 +90,19 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("cost.edit_cost_value", model,
|
ifcopenshell.api.run("cost.edit_cost_value", model,
|
||||||
cost_value=subvalue2, attributes={"AppliedValue": 3.0})
|
cost_value=subvalue2, attributes={"AppliedValue": 3.0})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"parent": parent}
|
||||||
self.settings = {"parent": parent}
|
|
||||||
|
|
||||||
def execute(self):
|
value = file.create_entity("IfcCostValue")
|
||||||
value = self.file.create_entity("IfcCostValue")
|
if settings["parent"].is_a("IfcCostItem"):
|
||||||
if self.settings["parent"].is_a("IfcCostItem"):
|
values = list(settings["parent"].CostValues or [])
|
||||||
values = list(self.settings["parent"].CostValues or [])
|
|
||||||
values.append(value)
|
values.append(value)
|
||||||
self.settings["parent"].CostValues = values
|
settings["parent"].CostValues = values
|
||||||
elif self.settings["parent"].is_a("IfcConstructionResource"):
|
elif settings["parent"].is_a("IfcConstructionResource"):
|
||||||
values = list(self.settings["parent"].BaseCosts or [])
|
values = list(settings["parent"].BaseCosts or [])
|
||||||
values.append(value)
|
values.append(value)
|
||||||
self.settings["parent"].BaseCosts = values
|
settings["parent"].BaseCosts = values
|
||||||
elif self.settings["parent"].is_a("IfcCostValue"):
|
elif settings["parent"].is_a("IfcCostValue"):
|
||||||
values = list(self.settings["parent"].Components or [])
|
values = list(settings["parent"].Components or [])
|
||||||
values.append(value)
|
values.append(value)
|
||||||
self.settings["parent"].Components = values
|
settings["parent"].Components = values
|
||||||
return value
|
return value
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def assign_cost_item_quantity(file, cost_item=None, products=None, prop_name="") -> None:
|
||||||
def __init__(self, file, cost_item=None, products=None, prop_name=""):
|
|
||||||
"""Adds a cost item quantity that is parametrically connected to a product
|
"""Adds a cost item quantity that is parametrically connected to a product
|
||||||
|
|
||||||
A cost item may have its subtotal calculated by multiplying a unit value
|
A cost item may have its subtotal calculated by multiplying a unit value
|
||||||
@@ -76,25 +75,26 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("cost.assign_cost_item_quantity", model,
|
ifcopenshell.api.run("cost.assign_cost_item_quantity", model,
|
||||||
cost_item=item, products=[slab], prop_name="NetVolume")
|
cost_item=item, products=[slab], prop_name="NetVolume")
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"cost_item": cost_item,
|
"cost_item": cost_item,
|
||||||
"products": products or [],
|
"products": products or [],
|
||||||
"prop_name": prop_name,
|
"prop_name": prop_name,
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
if self.settings["prop_name"]:
|
if self.settings["prop_name"]:
|
||||||
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
|
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
|
||||||
for product in self.settings["products"]:
|
for product in self.settings["products"]:
|
||||||
self.assign_cost_control(
|
self.assign_cost_control(related_object=product, cost_item=self.settings["cost_item"])
|
||||||
related_object=product, cost_item=self.settings["cost_item"]
|
|
||||||
)
|
|
||||||
if self.settings["prop_name"]:
|
if self.settings["prop_name"]:
|
||||||
if (
|
if (
|
||||||
self.settings["cost_item"].CostQuantities
|
self.settings["cost_item"].CostQuantities
|
||||||
and self.settings["cost_item"].CostQuantities[0].Name.lower()
|
and self.settings["cost_item"].CostQuantities[0].Name.lower() != self.settings["prop_name"].lower()
|
||||||
!= self.settings["prop_name"].lower()
|
|
||||||
) or not product.is_a("IfcObject"):
|
) or not product.is_a("IfcObject"):
|
||||||
continue
|
continue
|
||||||
self.add_quantity_from_related_object(product)
|
self.add_quantity_from_related_object(product)
|
||||||
@@ -120,10 +120,7 @@ class Usecase:
|
|||||||
if not qto.is_a("IfcElementQuantity"):
|
if not qto.is_a("IfcElementQuantity"):
|
||||||
return
|
return
|
||||||
for prop in qto.Quantities:
|
for prop in qto.Quantities:
|
||||||
if (
|
if prop.is_a("IfcPhysicalSimpleQuantity") and prop.Name.lower() == self.settings["prop_name"].lower():
|
||||||
prop.is_a("IfcPhysicalSimpleQuantity")
|
|
||||||
and prop.Name.lower() == self.settings["prop_name"].lower()
|
|
||||||
):
|
|
||||||
self.quantities.add(prop)
|
self.quantities.add(prop)
|
||||||
|
|
||||||
def update_cost_item_count(self):
|
def update_cost_item_count(self):
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def assign_cost_value(file, cost_item=None, cost_rate=None) -> None:
|
||||||
def __init__(self, file, cost_item=None, cost_rate=None):
|
|
||||||
"""Assigns a cost value to a cost item from a schedule of rates
|
"""Assigns a cost value to a cost item from a schedule of rates
|
||||||
|
|
||||||
Instead of assigning cost values from scratch for each cost item in a
|
Instead of assigning cost values from scratch for each cost item in a
|
||||||
@@ -60,19 +59,17 @@ class Usecase:
|
|||||||
# Now the cost item has the same rate as the one from the schedule of rate's item
|
# Now the cost item has the same rate as the one from the schedule of rate's item
|
||||||
ifcopenshell.api.run("cost.assign_cost_value", model, cost_item=item, cost_rate=rate)
|
ifcopenshell.api.run("cost.assign_cost_value", model, cost_item=item, cost_rate=rate)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"cost_item": cost_item, "cost_rate": cost_rate}
|
||||||
self.settings = {"cost_item": cost_item, "cost_rate": cost_rate}
|
|
||||||
|
|
||||||
def execute(self):
|
if settings["cost_item"].CostValues:
|
||||||
if self.settings["cost_item"].CostValues:
|
|
||||||
[
|
[
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
"cost.remove_cost_value",
|
"cost.remove_cost_value",
|
||||||
self.file,
|
file,
|
||||||
parent=self.settings["cost_item"],
|
parent=settings["cost_item"],
|
||||||
cost_value=cost_value,
|
cost_value=cost_value,
|
||||||
)
|
)
|
||||||
for cost_value in self.settings["cost_item"].CostValues
|
for cost_value in settings["cost_item"].CostValues
|
||||||
]
|
]
|
||||||
# This is an assumption, and not part of the official IFC documentation
|
# This is an assumption, and not part of the official IFC documentation
|
||||||
self.settings["cost_item"].CostValues = self.settings["cost_rate"].CostValues
|
settings["cost_item"].CostValues = settings["cost_rate"].CostValues
|
||||||
|
|||||||
+10
-13
@@ -21,8 +21,7 @@ import ifcopenshell.util.date
|
|||||||
import ifcopenshell.util.resource
|
import ifcopenshell.util.resource
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def calculate_cost_item_resource_value(file, cost_item=None) -> None:
|
||||||
def __init__(self, file, cost_item=None):
|
|
||||||
"""Calculates the total cost of all resources associated with a cost item
|
"""Calculates the total cost of all resources associated with a cost item
|
||||||
|
|
||||||
A cost item may have construction resources (e.g. equipment, material,
|
A cost item may have construction resources (e.g. equipment, material,
|
||||||
@@ -84,17 +83,13 @@ class Usecase:
|
|||||||
# (42 * 200) + 50000 = 58400 is our calculated cost
|
# (42 * 200) + 50000 = 58400 is our calculated cost
|
||||||
ifcopenshell.api.run("cost.calculate_cost_item_resource_value", model, cost_item=item)
|
ifcopenshell.api.run("cost.calculate_cost_item_resource_value", model, cost_item=item)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"cost_item": cost_item}
|
||||||
self.settings = {"cost_item": cost_item}
|
|
||||||
|
|
||||||
def execute(self):
|
for cost_value in settings["cost_item"].CostValues or []:
|
||||||
for cost_value in self.settings["cost_item"].CostValues or []:
|
ifcopenshell.api.run("cost.remove_cost_value", file, parent=settings["cost_item"], cost_value=cost_value)
|
||||||
ifcopenshell.api.run(
|
|
||||||
"cost.remove_cost_value", self.file, parent=self.settings["cost_item"], cost_value=cost_value
|
|
||||||
)
|
|
||||||
|
|
||||||
resources = []
|
resources = []
|
||||||
for rel in self.settings["cost_item"].Controls or []:
|
for rel in settings["cost_item"].Controls or []:
|
||||||
for related_object in rel.RelatedObjects:
|
for related_object in rel.RelatedObjects:
|
||||||
if related_object.is_a("IfcConstructionResource"):
|
if related_object.is_a("IfcConstructionResource"):
|
||||||
resources.append(related_object)
|
resources.append(related_object)
|
||||||
@@ -107,7 +102,9 @@ class Usecase:
|
|||||||
for resource in resources:
|
for resource in resources:
|
||||||
cost, unit = ifcopenshell.util.resource.get_cost(resource)
|
cost, unit = ifcopenshell.util.resource.get_cost(resource)
|
||||||
if not cost:
|
if not cost:
|
||||||
cost, unit = ifcopenshell.util.resource.get_parent_cost(resource) # Concept to standardise - Not defined in schema, but this makes manual scheduling of resources 10x faster and less duplicate data.
|
cost, unit = ifcopenshell.util.resource.get_parent_cost(
|
||||||
|
resource
|
||||||
|
) # Concept to standardise - Not defined in schema, but this makes manual scheduling of resources 10x faster and less duplicate data.
|
||||||
quantity = ifcopenshell.util.resource.get_quantity(resource)
|
quantity = ifcopenshell.util.resource.get_quantity(resource)
|
||||||
if not cost or not quantity:
|
if not cost or not quantity:
|
||||||
continue
|
continue
|
||||||
@@ -115,6 +112,6 @@ class Usecase:
|
|||||||
quantity = quantity / 8 # Assume 8 hour working day - TODO implement resource calendar
|
quantity = quantity / 8 # Assume 8 hour working day - TODO implement resource calendar
|
||||||
quantity = round(quantity, 2)
|
quantity = round(quantity, 2)
|
||||||
formula = "{}*{}".format(cost, quantity)
|
formula = "{}*{}".format(cost, quantity)
|
||||||
cost_value = ifcopenshell.api.run("cost.add_cost_value", self.file, parent=self.settings["cost_item"])
|
cost_value = ifcopenshell.api.run("cost.add_cost_value", file, parent=settings["cost_item"])
|
||||||
cost_value.Name = resource.Name
|
cost_value.Name = resource.Name
|
||||||
ifcopenshell.api.run("cost.edit_cost_value_formula", self.file, cost_value=cost_value, formula=formula)
|
ifcopenshell.api.run("cost.edit_cost_value_formula", file, cost_value=cost_value, formula=formula)
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def copy_cost_item(file, cost_item=None) -> None:
|
||||||
def __init__(self, file, cost_item=None):
|
|
||||||
"""Copies all cost items and related relationships
|
"""Copies all cost items and related relationships
|
||||||
|
|
||||||
The following relationships are also duplicated:
|
The following relationships are also duplicated:
|
||||||
@@ -47,9 +46,13 @@ class Usecase:
|
|||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {"cost_item": cost_item}
|
usecase.file = file
|
||||||
|
usecase.settings = {"cost_item": cost_item}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
self.new_cost_items = []
|
self.new_cost_items = []
|
||||||
self.duplicate_cost_item(self.settings["cost_item"])
|
self.duplicate_cost_item(self.settings["cost_item"])
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ import ifcopenshell.util.element
|
|||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def copy_cost_item_values(file, source=None, destination=None) -> None:
|
||||||
def __init__(self, file, source=None, destination=None):
|
|
||||||
"""Copies all cost values from one cost item to another
|
"""Copies all cost values from one cost item to another
|
||||||
|
|
||||||
Any previously existing values will be removed. The entire value is
|
Any previously existing values will be removed. The entire value is
|
||||||
@@ -52,13 +51,11 @@ class Usecase:
|
|||||||
# Let's copy the value from one item to another
|
# Let's copy the value from one item to another
|
||||||
ifcopenshell.api.run("cost.copy_cost_item_values", model, source=item1, destination=item2)
|
ifcopenshell.api.run("cost.copy_cost_item_values", model, source=item1, destination=item2)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"source": source, "destination": destination}
|
||||||
self.settings = {"source": source, "destination": destination}
|
|
||||||
|
|
||||||
def execute(self):
|
for cost_value in settings["destination"].CostValues or []:
|
||||||
for cost_value in self.settings["destination"].CostValues or []:
|
ifcopenshell.api.run("cost.remove_cost_item_value", file, cost_value=cost_value)
|
||||||
ifcopenshell.api.run("cost.remove_cost_item_value", self.file, cost_value=cost_value)
|
|
||||||
copied_cost_values = []
|
copied_cost_values = []
|
||||||
for cost_value in self.settings["source"].CostValues or []:
|
for cost_value in settings["source"].CostValues or []:
|
||||||
copied_cost_values.append(ifcopenshell.util.element.copy_deep(self.file, cost_value))
|
copied_cost_values.append(ifcopenshell.util.element.copy_deep(file, cost_value))
|
||||||
self.settings["destination"].CostValues = copied_cost_values
|
settings["destination"].CostValues = copied_cost_values
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_cost_item(file, cost_item=None, attributes=None) -> None:
|
||||||
def __init__(self, file, cost_item=None, attributes=None):
|
|
||||||
"""Edits the attributes of an IfcCostItem
|
"""Edits the attributes of an IfcCostItem
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -39,9 +38,7 @@ class Usecase:
|
|||||||
item = ifcopenshell.api.run("cost.add_cost_item", model, cost_schedule=schedule)
|
item = ifcopenshell.api.run("cost.add_cost_item", model, cost_schedule=schedule)
|
||||||
ifcopenshell.api.run("cost.edit_cost_item", model, cost_item=item, attributes={"Name": "Foo"})
|
ifcopenshell.api.run("cost.edit_cost_item", model, cost_item=item, attributes={"Name": "Foo"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"cost_item": cost_item, "attributes": attributes or {}}
|
||||||
self.settings = {"cost_item": cost_item, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["cost_item"], name, value)
|
||||||
setattr(self.settings["cost_item"], name, value)
|
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_cost_item_quantity(file, physical_quantity=None, attributes=None) -> None:
|
||||||
def __init__(self, file, physical_quantity=None, attributes=None):
|
|
||||||
"""Edits the attributes of an IfcPhysicalQuantity
|
"""Edits the attributes of an IfcPhysicalQuantity
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -47,9 +46,7 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("cost.edit_cost_item_quantity", model,
|
ifcopenshell.api.run("cost.edit_cost_item_quantity", model,
|
||||||
physical_quantity=quantity, "attributes": {"VolumeValue": 3.0})
|
physical_quantity=quantity, "attributes": {"VolumeValue": 3.0})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"physical_quantity": physical_quantity, "attributes": attributes or {}}
|
||||||
self.settings = {"physical_quantity": physical_quantity, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["physical_quantity"], name, value)
|
||||||
setattr(self.settings["physical_quantity"], name, value)
|
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_cost_schedule(file, cost_schedule=None, attributes=None) -> None:
|
||||||
def __init__(self, file, cost_schedule=None, attributes=None):
|
|
||||||
"""Edits the attributes of an IfcCostSchedule
|
"""Edits the attributes of an IfcCostSchedule
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -40,9 +39,7 @@ class Usecase:
|
|||||||
cost_schedule=schedule, attributes={"Name": "Foo"})
|
cost_schedule=schedule, attributes={"Name": "Foo"})
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.file = file
|
settings = {"cost_schedule": cost_schedule, "attributes": attributes or {}}
|
||||||
self.settings = {"cost_schedule": cost_schedule, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["cost_schedule"], name, value)
|
||||||
setattr(self.settings["cost_schedule"], name, value)
|
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import ifcopenshell.util.unit
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_cost_value(file, cost_value=None, attributes=None) -> None:
|
||||||
def __init__(self, file, cost_value=None, attributes=None):
|
|
||||||
"""Edits the attributes of an IfcCostValue
|
"""Edits the attributes of an IfcCostValue
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -47,22 +46,20 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("cost.edit_cost_value", model, cost_value=value,
|
ifcopenshell.api.run("cost.edit_cost_value", model, cost_value=value,
|
||||||
attributes={"AppliedValue": 42.0})
|
attributes={"AppliedValue": 42.0})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"cost_value": cost_value, "attributes": attributes or {}}
|
||||||
self.settings = {"cost_value": cost_value, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
|
||||||
if name == "AppliedValue" and value is not None:
|
if name == "AppliedValue" and value is not None:
|
||||||
# TODO: support all applied value select types
|
# TODO: support all applied value select types
|
||||||
value = self.file.createIfcMonetaryMeasure(value)
|
value = file.createIfcMonetaryMeasure(value)
|
||||||
elif name == "UnitBasis":
|
elif name == "UnitBasis":
|
||||||
old_unit_basis = self.settings["cost_value"].UnitBasis
|
old_unit_basis = settings["cost_value"].UnitBasis
|
||||||
if value:
|
if value:
|
||||||
value_component = self.file.create_entity(
|
value_component = file.create_entity(
|
||||||
ifcopenshell.util.unit.get_unit_measure_class(value["UnitComponent"].UnitType),
|
ifcopenshell.util.unit.get_unit_measure_class(value["UnitComponent"].UnitType),
|
||||||
value["ValueComponent"],
|
value["ValueComponent"],
|
||||||
)
|
)
|
||||||
value = self.file.create_entity("IfcMeasureWithUnit", value_component, value["UnitComponent"])
|
value = file.create_entity("IfcMeasureWithUnit", value_component, value["UnitComponent"])
|
||||||
if old_unit_basis and len(self.file.get_inverse(old_unit_basis)) == 0:
|
if old_unit_basis and len(file.get_inverse(old_unit_basis)) == 0:
|
||||||
ifcopenshell.util.element.remove_deep(self.file, old_unit_basis)
|
ifcopenshell.util.element.remove_deep(file, old_unit_basis)
|
||||||
setattr(self.settings["cost_value"], name, value)
|
setattr(settings["cost_value"], name, value)
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ import ifcopenshell.util.unit
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_cost_value_formula(file, cost_value=None, formula=None) -> None:
|
||||||
def __init__(self, file, cost_value=None, formula=None):
|
|
||||||
"""Sets a cost value based on a formula, similar to formulas in spreadsheets
|
"""Sets a cost value based on a formula, similar to formulas in spreadsheets
|
||||||
|
|
||||||
Costs may be made up of many components (e.g. labour, material, waste
|
Costs may be made up of many components (e.g. labour, material, waste
|
||||||
@@ -50,9 +49,13 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("cost.edit_cost_value_formula", model, cost_value=value,
|
ifcopenshell.api.run("cost.edit_cost_value_formula", model, cost_value=value,
|
||||||
formula="5000 * 1.19")
|
formula="5000 * 1.19")
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {"cost_value": cost_value, "formula": formula or {}}
|
usecase.file = file
|
||||||
|
usecase.settings = {"cost_value": cost_value, "formula": formula or {}}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
try:
|
try:
|
||||||
data = ifcopenshell.util.cost.unserialise_cost_value(self.settings["formula"], self.settings["cost_value"])
|
data = ifcopenshell.util.cost.unserialise_cost_value(self.settings["formula"], self.settings["cost_value"])
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_cost_item(file, cost_item=None) -> None:
|
||||||
def __init__(self, file, cost_item=None):
|
|
||||||
"""Removes a cost item
|
"""Removes a cost item
|
||||||
|
|
||||||
All associated relationships with the cost item are also removed,
|
All associated relationships with the cost item are also removed,
|
||||||
@@ -42,27 +41,25 @@ class Usecase:
|
|||||||
item = ifcopenshell.api.run("cost.add_cost_item", model, cost_schedule=schedule)
|
item = ifcopenshell.api.run("cost.add_cost_item", model, cost_schedule=schedule)
|
||||||
ifcopenshell.api.run("cost.remove_cost_item", model, cost_item=item)
|
ifcopenshell.api.run("cost.remove_cost_item", model, cost_item=item)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"cost_item": cost_item}
|
||||||
self.settings = {"cost_item": cost_item}
|
|
||||||
|
|
||||||
def execute(self):
|
|
||||||
# TODO: do a deep purge
|
# TODO: do a deep purge
|
||||||
for inverse in self.file.get_inverse(self.settings["cost_item"]):
|
for inverse in file.get_inverse(settings["cost_item"]):
|
||||||
if inverse.is_a("IfcRelNests"):
|
if inverse.is_a("IfcRelNests"):
|
||||||
if inverse.RelatingObject == self.settings["cost_item"]:
|
if inverse.RelatingObject == settings["cost_item"]:
|
||||||
for related_object in inverse.RelatedObjects:
|
for related_object in inverse.RelatedObjects:
|
||||||
ifcopenshell.api.run("cost.remove_cost_item", self.file, cost_item=related_object)
|
ifcopenshell.api.run("cost.remove_cost_item", file, cost_item=related_object)
|
||||||
elif inverse.RelatedObjects == (self.settings["cost_item"],):
|
elif inverse.RelatedObjects == (settings["cost_item"],):
|
||||||
history = inverse.OwnerHistory
|
history = inverse.OwnerHistory
|
||||||
self.file.remove(inverse)
|
file.remove(inverse)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
elif inverse.is_a("IfcRelAssignsToControl"):
|
elif inverse.is_a("IfcRelAssignsToControl"):
|
||||||
history = inverse.OwnerHistory
|
history = inverse.OwnerHistory
|
||||||
self.file.remove(inverse)
|
file.remove(inverse)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
history = self.settings["cost_item"].OwnerHistory
|
history = settings["cost_item"].OwnerHistory
|
||||||
self.file.remove(self.settings["cost_item"])
|
file.remove(settings["cost_item"])
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_cost_item_quantity(file, cost_item=None, physical_quantity=None) -> None:
|
||||||
def __init__(self, file, cost_item=None, physical_quantity=None):
|
|
||||||
"""Removes a quantity assigned to a cost item
|
"""Removes a quantity assigned to a cost item
|
||||||
|
|
||||||
If the quantity is part of a product (e.g. wall), then the quantity will
|
If the quantity is part of a product (e.g. wall), then the quantity will
|
||||||
@@ -44,13 +43,11 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("cost.remove_cost_item", model,
|
ifcopenshell.api.run("cost.remove_cost_item", model,
|
||||||
cost_item=item, physical_quantity=quantity)
|
cost_item=item, physical_quantity=quantity)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"cost_item": cost_item, "physical_quantity": physical_quantity}
|
||||||
self.settings = {"cost_item": cost_item, "physical_quantity": physical_quantity}
|
|
||||||
|
|
||||||
def execute(self):
|
if len(file.get_inverse(settings["physical_quantity"])) == 1:
|
||||||
if len(self.file.get_inverse(self.settings["physical_quantity"])) == 1:
|
file.remove(settings["physical_quantity"])
|
||||||
self.file.remove(self.settings["physical_quantity"])
|
|
||||||
return
|
return
|
||||||
quantities = list(self.settings["cost_item"].CostQuantities or [])
|
quantities = list(settings["cost_item"].CostQuantities or [])
|
||||||
quantities.remove(self.settings["physical_quantity"])
|
quantities.remove(settings["physical_quantity"])
|
||||||
self.settings["cost_item"].CostQuantities = quantities
|
settings["cost_item"].CostQuantities = quantities
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_cost_schedule(file, cost_schedule=None) -> None:
|
||||||
def __init__(self, file, cost_schedule=None):
|
|
||||||
"""Removes a cost schedule
|
"""Removes a cost schedule
|
||||||
|
|
||||||
All associated relationships with the cost schedule are also removed,
|
All associated relationships with the cost schedule are also removed,
|
||||||
@@ -41,21 +40,17 @@ class Usecase:
|
|||||||
item = ifcopenshell.api.run("cost.add_cost_item", model, cost_schedule=schedule)
|
item = ifcopenshell.api.run("cost.add_cost_item", model, cost_schedule=schedule)
|
||||||
ifcopenshell.api.run("cost.remove_cost_schedule", model, cost_schedule=schedule)
|
ifcopenshell.api.run("cost.remove_cost_schedule", model, cost_schedule=schedule)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"cost_schedule": cost_schedule}
|
||||||
self.settings = {"cost_schedule": cost_schedule}
|
|
||||||
|
|
||||||
def execute(self):
|
|
||||||
# TODO: do a deep purge
|
# TODO: do a deep purge
|
||||||
for inverse in self.file.get_inverse(self.settings["cost_schedule"]):
|
for inverse in file.get_inverse(settings["cost_schedule"]):
|
||||||
if inverse.is_a("IfcRelAssignsToControl"):
|
if inverse.is_a("IfcRelAssignsToControl"):
|
||||||
[
|
[
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run("cost.remove_cost_item", file, cost_item=related_object)
|
||||||
"cost.remove_cost_item", self.file, cost_item=related_object
|
|
||||||
)
|
|
||||||
for related_object in inverse.RelatedObjects
|
for related_object in inverse.RelatedObjects
|
||||||
if related_object.is_a("IfcCostItem")
|
if related_object.is_a("IfcCostItem")
|
||||||
]
|
]
|
||||||
history = self.settings["cost_schedule"].OwnerHistory
|
history = settings["cost_schedule"].OwnerHistory
|
||||||
self.file.remove(self.settings["cost_schedule"])
|
file.remove(settings["cost_schedule"])
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_cost_value(file, parent=None, cost_value=None) -> None:
|
||||||
def __init__(self, file, parent=None, cost_value=None):
|
|
||||||
"""Removes a cost value
|
"""Removes a cost value
|
||||||
|
|
||||||
The cost value may be assigned either to a cost item, a construction
|
The cost value may be assigned either to a cost item, a construction
|
||||||
@@ -46,22 +45,20 @@ class Usecase:
|
|||||||
|
|
||||||
ifcopenshell.api.run("cost.remove_cost_value", model, parent=item, cost_value=value)
|
ifcopenshell.api.run("cost.remove_cost_value", model, parent=item, cost_value=value)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"parent": parent, "cost_value": cost_value}
|
||||||
self.settings = {"parent": parent, "cost_value": cost_value}
|
|
||||||
|
|
||||||
def execute(self):
|
if len(file.get_inverse(settings["cost_value"])) == 1:
|
||||||
if len(self.file.get_inverse(self.settings["cost_value"])) == 1:
|
file.remove(settings["cost_value"])
|
||||||
self.file.remove(self.settings["cost_value"])
|
|
||||||
# TODO deep purge
|
# TODO deep purge
|
||||||
elif self.settings["parent"].is_a("IfcCostItem"):
|
elif settings["parent"].is_a("IfcCostItem"):
|
||||||
values = list(self.settings["parent"].CostValues)
|
values = list(settings["parent"].CostValues)
|
||||||
values.remove(self.settings["cost_value"])
|
values.remove(settings["cost_value"])
|
||||||
self.settings["parent"].CostValues = values if values else None
|
settings["parent"].CostValues = values if values else None
|
||||||
elif self.settings["parent"].is_a("IfcConstructionResource"):
|
elif settings["parent"].is_a("IfcConstructionResource"):
|
||||||
values = list(self.settings["parent"].BaseCosts)
|
values = list(settings["parent"].BaseCosts)
|
||||||
values.remove(self.settings["cost_value"])
|
values.remove(settings["cost_value"])
|
||||||
self.settings["parent"].BaseCosts = values if values else None
|
settings["parent"].BaseCosts = values if values else None
|
||||||
elif self.settings["parent"].is_a("IfcCostValue"):
|
elif settings["parent"].is_a("IfcCostValue"):
|
||||||
components = list(self.settings["parent"].Components)
|
components = list(settings["parent"].Components)
|
||||||
components.remove(self.settings["cost_value"])
|
components.remove(settings["cost_value"])
|
||||||
self.settings["parent"].Components = components if components else None
|
settings["parent"].Components = components if components else None
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def unassign_cost_item_quantity(file, cost_item=None, products=None) -> None:
|
||||||
def __init__(self, file, cost_item=None, products=None):
|
|
||||||
"""Removes quantities of a cost item that are calculated on products
|
"""Removes quantities of a cost item that are calculated on products
|
||||||
|
|
||||||
A cost item may have quantities that are parametrically calculated on
|
A cost item may have quantities that are parametrically calculated on
|
||||||
@@ -66,9 +65,13 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("cost.unassign_cost_item_quantity", model,
|
ifcopenshell.api.run("cost.unassign_cost_item_quantity", model,
|
||||||
cost_item=item, products=[slab])
|
cost_item=item, products=[slab])
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {"cost_item": cost_item, "products": products or []}
|
usecase.file = file
|
||||||
|
usecase.settings = {"cost_item": cost_item, "products": products or []}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
|
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
|
||||||
for quantity in self.settings["cost_item"].CostQuantities or []:
|
for quantity in self.settings["cost_item"].CostQuantities or []:
|
||||||
|
|||||||
@@ -15,3 +15,12 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .add_information import add_information
|
||||||
|
from .add_reference import add_reference
|
||||||
|
from .assign_document import assign_document
|
||||||
|
from .edit_information import edit_information
|
||||||
|
from .edit_reference import edit_reference
|
||||||
|
from .remove_information import remove_information
|
||||||
|
from .remove_reference import remove_reference
|
||||||
|
from .unassign_document import unassign_document
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_information(file, parent=None) -> None:
|
||||||
def __init__(self, file, parent=None):
|
|
||||||
"""Adds a new document information to the project
|
"""Adds a new document information to the project
|
||||||
|
|
||||||
An IFC document information is a document associated with the project.
|
An IFC document information is a document associated with the project.
|
||||||
@@ -53,22 +52,18 @@ class Usecase:
|
|||||||
attributes={"Identification": "A-GA-6100", "Name": "Overall Plan",
|
attributes={"Identification": "A-GA-6100", "Name": "Overall Plan",
|
||||||
"Location": "A-GA-6100 - Overall Plan.pdf"})
|
"Location": "A-GA-6100 - Overall Plan.pdf"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"parent": parent}
|
||||||
self.settings = {"parent": parent}
|
|
||||||
|
|
||||||
def execute(self):
|
id_attribute = "DocumentId" if file.schema == "IFC2X3" else "Identification"
|
||||||
id_attribute = "DocumentId" if self.file.schema == "IFC2X3" else "Identification"
|
information = file.create_entity("IfcDocumentInformation", **{id_attribute: "X", "Name": "Unnamed"})
|
||||||
information = self.file.create_entity(
|
parent = settings["parent"]
|
||||||
"IfcDocumentInformation", **{id_attribute: "X", "Name": "Unnamed"}
|
if not parent and file.by_type("IfcProject"):
|
||||||
)
|
parent = file.by_type("IfcProject")[0]
|
||||||
parent = self.settings["parent"]
|
|
||||||
if not parent and self.file.by_type("IfcProject"):
|
|
||||||
parent = self.file.by_type("IfcProject")[0]
|
|
||||||
if parent.is_a("IfcProject") or parent.is_a("IfcContext"):
|
if parent.is_a("IfcProject") or parent.is_a("IfcContext"):
|
||||||
self.file.create_entity(
|
file.create_entity(
|
||||||
"IfcRelAssociatesDocument",
|
"IfcRelAssociatesDocument",
|
||||||
GlobalId=ifcopenshell.guid.new(),
|
GlobalId=ifcopenshell.guid.new(),
|
||||||
OwnerHistory=ifcopenshell.api.run("owner.create_owner_history", self.file),
|
OwnerHistory=ifcopenshell.api.run("owner.create_owner_history", file),
|
||||||
RelatingDocument=information,
|
RelatingDocument=information,
|
||||||
RelatedObjects=[parent],
|
RelatedObjects=[parent],
|
||||||
)
|
)
|
||||||
@@ -79,9 +74,7 @@ class Usecase:
|
|||||||
documents.add(information)
|
documents.add(information)
|
||||||
rel.RelatedDocuments = list(documents)
|
rel.RelatedDocuments = list(documents)
|
||||||
else:
|
else:
|
||||||
self.file.create_entity(
|
file.create_entity(
|
||||||
"IfcDocumentInformationRelationship",
|
"IfcDocumentInformationRelationship", RelatingDocument=parent, RelatedDocuments=[information]
|
||||||
RelatingDocument=parent,
|
|
||||||
RelatedDocuments=[information]
|
|
||||||
)
|
)
|
||||||
return information
|
return information
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_reference(file: ifcopenshell.file, information: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||||
def __init__(self, file: ifcopenshell.file, information: ifcopenshell.entity_instance):
|
|
||||||
"""Creates a new reference to a document to assign to products
|
"""Creates a new reference to a document to assign to products
|
||||||
|
|
||||||
A document may be associated with physical products, tasks, cost items,
|
A document may be associated with physical products, tasks, cost items,
|
||||||
@@ -64,17 +63,13 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("document.edit_reference", model,
|
ifcopenshell.api.run("document.edit_reference", model,
|
||||||
reference=reference2, attributes={"Identification": "2.1.15"})
|
reference=reference2, attributes={"Identification": "2.1.15"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"information": information}
|
||||||
self.settings = {"information": information}
|
|
||||||
|
|
||||||
def execute(self) -> ifcopenshell.entity_instance:
|
if file.schema == "IFC2X3":
|
||||||
if self.file.schema == "IFC2X3":
|
reference = file.create_entity("IfcDocumentReference", ItemReference="X")
|
||||||
reference = self.file.create_entity("IfcDocumentReference", ItemReference="X")
|
if settings["information"]:
|
||||||
if self.settings["information"]:
|
references = list(settings["information"].DocumentReferences or [])
|
||||||
references = list(self.settings["information"].DocumentReferences or [])
|
|
||||||
references.append(reference)
|
references.append(reference)
|
||||||
self.settings["information"].DocumentReferences = references
|
settings["information"].DocumentReferences = references
|
||||||
return reference
|
return reference
|
||||||
return self.file.create_entity(
|
return file.create_entity("IfcDocumentReference", ReferencedDocument=settings["information"], Identification="X")
|
||||||
"IfcDocumentReference", ReferencedDocument=self.settings["information"], Identification="X"
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -22,13 +22,11 @@ import ifcopenshell.util.element
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def assign_document(
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
file: ifcopenshell.file,
|
file: ifcopenshell.file,
|
||||||
products: list[ifcopenshell.entity_instance],
|
products: list[ifcopenshell.entity_instance],
|
||||||
document: ifcopenshell.entity_instance,
|
document: ifcopenshell.entity_instance,
|
||||||
):
|
) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
"""Assigns a document to a list of products
|
"""Assigns a document to a list of products
|
||||||
|
|
||||||
An object may be assigned to zero, one, or multiple documents. Almost
|
An object may be assigned to zero, one, or multiple documents. Almost
|
||||||
@@ -66,49 +64,43 @@ class Usecase:
|
|||||||
# Let's imagine storey represents an IfcBuildingStorey for the ground floor
|
# Let's imagine storey represents an IfcBuildingStorey for the ground floor
|
||||||
ifcopenshell.api.run("document.assign_document", model, products=[storey], document=reference)
|
ifcopenshell.api.run("document.assign_document", model, products=[storey], document=reference)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {
|
||||||
self.settings = {
|
|
||||||
"products": products,
|
"products": products,
|
||||||
"document": document,
|
"document": document,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self) -> Union[ifcopenshell.entity_instance, None]:
|
|
||||||
# TODO: do we need to support non-ifcroot elements like we do in classification.add_reference?
|
# TODO: do we need to support non-ifcroot elements like we do in classification.add_reference?
|
||||||
# NOTE: reuses code from `library.assign_reference`
|
# NOTE: reuses code from `library.assign_reference`
|
||||||
|
|
||||||
referenced_elements = ifcopenshell.util.element.get_referenced_elements(self.settings["document"])
|
referenced_elements = ifcopenshell.util.element.get_referenced_elements(settings["document"])
|
||||||
products: set[ifcopenshell.entity_instance] = set(self.settings["products"])
|
products: set[ifcopenshell.entity_instance] = set(settings["products"])
|
||||||
products = products - referenced_elements
|
products = products - referenced_elements
|
||||||
|
|
||||||
if not products:
|
if not products:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.file.schema == "IFC2X3":
|
if file.schema == "IFC2X3":
|
||||||
rel = next(
|
rel = next(
|
||||||
(
|
(r for r in file.by_type("IfcRelAssociatesDocument") if r.RelatingDocument == settings["document"]),
|
||||||
r
|
|
||||||
for r in self.file.by_type("IfcRelAssociatesDocument")
|
|
||||||
if r.RelatingDocument == self.settings["document"]
|
|
||||||
),
|
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ifc_class = self.settings["document"].is_a()
|
ifc_class = settings["document"].is_a()
|
||||||
if ifc_class == "IfcDocumentReference":
|
if ifc_class == "IfcDocumentReference":
|
||||||
rel = next(iter(self.settings["document"].DocumentRefForObjects), None)
|
rel = next(iter(settings["document"].DocumentRefForObjects), None)
|
||||||
elif ifc_class == "IfcDocumentInformation":
|
elif ifc_class == "IfcDocumentInformation":
|
||||||
rel = next(iter(self.settings["document"].DocumentInfoForObjects), None)
|
rel = next(iter(settings["document"].DocumentInfoForObjects), None)
|
||||||
|
|
||||||
if not rel:
|
if not rel:
|
||||||
return self.file.create_entity(
|
return file.create_entity(
|
||||||
"IfcRelAssociatesDocument",
|
"IfcRelAssociatesDocument",
|
||||||
GlobalId=ifcopenshell.guid.new(),
|
GlobalId=ifcopenshell.guid.new(),
|
||||||
OwnerHistory=ifcopenshell.api.run("owner.create_owner_history", self.file),
|
OwnerHistory=ifcopenshell.api.run("owner.create_owner_history", file),
|
||||||
RelatedObjects=list(products),
|
RelatedObjects=list(products),
|
||||||
RelatingDocument=self.settings["document"],
|
RelatingDocument=settings["document"],
|
||||||
)
|
)
|
||||||
|
|
||||||
related_objects = set(rel.RelatedObjects) | products
|
related_objects = set(rel.RelatedObjects) | products
|
||||||
rel.RelatedObjects = list(related_objects)
|
rel.RelatedObjects = list(related_objects)
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, element=rel)
|
ifcopenshell.api.run("owner.update_owner_history", file, element=rel)
|
||||||
return rel
|
return rel
|
||||||
|
|||||||
@@ -19,13 +19,11 @@ import ifcopenshell
|
|||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_information(
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
file: ifcopenshell.file,
|
file: ifcopenshell.file,
|
||||||
information: ifcopenshell.entity_instance,
|
information: ifcopenshell.entity_instance,
|
||||||
attributes: Optional[dict[str, Any]] = None,
|
attributes: Optional[dict[str, Any]] = None,
|
||||||
):
|
) -> None:
|
||||||
"""Edits the attributes of an IfcDocumentInformation
|
"""Edits the attributes of an IfcDocumentInformation
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -48,9 +46,7 @@ class Usecase:
|
|||||||
attributes={"Identification": "A-GA-6100", "Name": "Overall Plan",
|
attributes={"Identification": "A-GA-6100", "Name": "Overall Plan",
|
||||||
"Location": "A-GA-6100 - Overall Plan.pdf"})
|
"Location": "A-GA-6100 - Overall Plan.pdf"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"information": information, "attributes": attributes or {}}
|
||||||
self.settings = {"information": information, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self) -> None:
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["information"], name, value)
|
||||||
setattr(self.settings["information"], name, value)
|
|
||||||
|
|||||||
@@ -19,13 +19,11 @@ import ifcopenshell
|
|||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_reference(
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
file: ifcopenshell.file,
|
file: ifcopenshell.file,
|
||||||
reference: ifcopenshell.entity_instance,
|
reference: ifcopenshell.entity_instance,
|
||||||
attributes: Optional[dict[str, Any]] = None,
|
attributes: Optional[dict[str, Any]] = None,
|
||||||
):
|
) -> None:
|
||||||
"""Edits the attributes of an IfcDocumentReference
|
"""Edits the attributes of an IfcDocumentReference
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -51,9 +49,7 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("document.edit_reference", model,
|
ifcopenshell.api.run("document.edit_reference", model,
|
||||||
reference=reference, attributes={"Identification": "2.1.15"})
|
reference=reference, attributes={"Identification": "2.1.15"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"reference": reference, "attributes": attributes or {}}
|
||||||
self.settings = {"reference": reference, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self) -> None:
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["reference"], name, value)
|
||||||
setattr(self.settings["reference"], name, value)
|
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_information(file, information=None) -> None:
|
||||||
def __init__(self, file, information=None):
|
|
||||||
"""Removes a document information
|
"""Removes a document information
|
||||||
|
|
||||||
All references and associations are also removed.
|
All references and associations are also removed.
|
||||||
@@ -42,25 +41,23 @@ class Usecase:
|
|||||||
# ... and remove it!
|
# ... and remove it!
|
||||||
ifcopenshell.api.run("document.remove_information", model, information=document)
|
ifcopenshell.api.run("document.remove_information", model, information=document)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"information": information}
|
||||||
self.settings = {"information": information}
|
|
||||||
|
|
||||||
def execute(self):
|
for reference in settings["information"].HasDocumentReferences or []:
|
||||||
for reference in self.settings["information"].HasDocumentReferences or []:
|
ifcopenshell.api.run("document.remove_reference", file, reference=reference)
|
||||||
ifcopenshell.api.run("document.remove_reference", self.file, reference=reference)
|
|
||||||
|
|
||||||
for rel in self.settings["information"].IsPointer or []:
|
for rel in settings["information"].IsPointer or []:
|
||||||
for information in rel.RelatedDocuments:
|
for information in rel.RelatedDocuments:
|
||||||
ifcopenshell.api.run("document.remove_information", self.file, information=information)
|
ifcopenshell.api.run("document.remove_information", file, information=information)
|
||||||
|
|
||||||
for rel in self.settings["information"].IsPointedTo or []:
|
for rel in settings["information"].IsPointedTo or []:
|
||||||
if rel.RelatedDocuments == (self.settings["information"],):
|
if rel.RelatedDocuments == (settings["information"],):
|
||||||
# This relationship is non-rooted
|
# This relationship is non-rooted
|
||||||
self.file.remove(rel)
|
file.remove(rel)
|
||||||
|
|
||||||
for rel in self.settings["information"].DocumentInfoForObjects or []:
|
for rel in settings["information"].DocumentInfoForObjects or []:
|
||||||
history = rel.OwnerHistory
|
history = rel.OwnerHistory
|
||||||
self.file.remove(rel)
|
file.remove(rel)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
self.file.remove(self.settings["information"])
|
file.remove(settings["information"])
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ import ifcopenshell
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_reference(file: ifcopenshell.file, reference: ifcopenshell.entity_instance) -> None:
|
||||||
def __init__(self, file: ifcopenshell.file, reference: ifcopenshell.entity_instance):
|
|
||||||
"""Remove a document reference
|
"""Remove a document reference
|
||||||
|
|
||||||
All associations with objects are removed.
|
All associations with objects are removed.
|
||||||
@@ -39,13 +38,11 @@ class Usecase:
|
|||||||
reference = ifcopenshell.api.run("document.add_reference", model, information=document)
|
reference = ifcopenshell.api.run("document.add_reference", model, information=document)
|
||||||
ifcopenshell.api.run("document.remove_reference", model, reference=reference)
|
ifcopenshell.api.run("document.remove_reference", model, reference=reference)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"reference": reference}
|
||||||
self.settings = {"reference": reference}
|
|
||||||
|
|
||||||
def execute(self) -> None:
|
for rel in settings["reference"].DocumentRefForObjects or []:
|
||||||
for rel in self.settings["reference"].DocumentRefForObjects or []:
|
|
||||||
history = rel.OwnerHistory
|
history = rel.OwnerHistory
|
||||||
self.file.remove(rel)
|
file.remove(rel)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
self.file.remove(self.settings["reference"])
|
file.remove(settings["reference"])
|
||||||
|
|||||||
@@ -21,13 +21,11 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def unassign_document(
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
file: ifcopenshell.file,
|
file: ifcopenshell.file,
|
||||||
products: list[ifcopenshell.entity_instance],
|
products: list[ifcopenshell.entity_instance],
|
||||||
document: ifcopenshell.entity_instance,
|
document: ifcopenshell.entity_instance,
|
||||||
):
|
) -> None:
|
||||||
"""Unassigns a document and an association to the list of products
|
"""Unassigns a document and an association to the list of products
|
||||||
|
|
||||||
:param product: The list of objects that the document reference or information is
|
:param product: The list of objects that the document reference or information is
|
||||||
@@ -56,34 +54,32 @@ class Usecase:
|
|||||||
# Now let's change our mind and remove the association
|
# Now let's change our mind and remove the association
|
||||||
ifcopenshell.api.run("document.unassign_document", model, products=[storey], document=reference)
|
ifcopenshell.api.run("document.unassign_document", model, products=[storey], document=reference)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {
|
||||||
self.settings = {
|
|
||||||
"products": products,
|
"products": products,
|
||||||
"document": document,
|
"document": document,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self):
|
|
||||||
# TODO: do we need to support non-ifcroot elements like we do in classification.add_reference?
|
# TODO: do we need to support non-ifcroot elements like we do in classification.add_reference?
|
||||||
# NOTE: reuses code from `library.un assign_reference`
|
# NOTE: reuses code from `library.un assign_reference`
|
||||||
|
|
||||||
reference_rels: set[ifcopenshell.entity_instance] = set()
|
reference_rels: set[ifcopenshell.entity_instance] = set()
|
||||||
products = set(self.settings["products"])
|
products = set(settings["products"])
|
||||||
for product in products:
|
for product in products:
|
||||||
reference_rels.update(product.HasAssociations)
|
reference_rels.update(product.HasAssociations)
|
||||||
|
|
||||||
reference_rels = {
|
reference_rels = {
|
||||||
rel
|
rel
|
||||||
for rel in reference_rels
|
for rel in reference_rels
|
||||||
if rel.is_a("IfcRelAssociatesDocument") and rel.RelatingDocument == self.settings["document"]
|
if rel.is_a("IfcRelAssociatesDocument") and rel.RelatingDocument == settings["document"]
|
||||||
}
|
}
|
||||||
|
|
||||||
for rel in reference_rels:
|
for rel in reference_rels:
|
||||||
related_objects = set(rel.RelatedObjects) - products
|
related_objects = set(rel.RelatedObjects) - products
|
||||||
if related_objects:
|
if related_objects:
|
||||||
rel.RelatedObjects = list(related_objects)
|
rel.RelatedObjects = list(related_objects)
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel})
|
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": rel})
|
||||||
else:
|
else:
|
||||||
history = rel.OwnerHistory
|
history = rel.OwnerHistory
|
||||||
self.file.remove(rel)
|
file.remove(rel)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|||||||
@@ -15,3 +15,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .assign_product import assign_product
|
||||||
|
from .edit_text_literal import edit_text_literal
|
||||||
|
from .unassign_product import unassign_product
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ import ifcopenshell
|
|||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def assign_product(file, relating_product=None, related_object=None) -> None:
|
||||||
def __init__(self, file, relating_product=None, related_object=None):
|
|
||||||
"""Associates a product and an object, typically for annotation
|
"""Associates a product and an object, typically for annotation
|
||||||
|
|
||||||
Warning: this is an experimental API.
|
Warning: this is an experimental API.
|
||||||
@@ -58,54 +57,52 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("drawing.assign_product", model,
|
ifcopenshell.api.run("drawing.assign_product", model,
|
||||||
relating_product=furniture, related_object=annotation)
|
relating_product=furniture, related_object=annotation)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {
|
||||||
self.settings = {
|
|
||||||
"relating_product": relating_product,
|
"relating_product": relating_product,
|
||||||
"related_object": related_object,
|
"related_object": related_object,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self):
|
is_grid_axis = settings["relating_product"].is_a("IfcGridAxis")
|
||||||
is_grid_axis = self.settings["relating_product"].is_a("IfcGridAxis")
|
|
||||||
|
|
||||||
if is_grid_axis:
|
if is_grid_axis:
|
||||||
if self.settings["related_object"].HasAssignments:
|
if settings["related_object"].HasAssignments:
|
||||||
for rel in self.settings["related_object"].HasAssignments:
|
for rel in settings["related_object"].HasAssignments:
|
||||||
if rel.is_a("IfcRelAssignsToProduct") and rel.Name == self.settings["relating_product"].AxisTag:
|
if rel.is_a("IfcRelAssignsToProduct") and rel.Name == settings["relating_product"].AxisTag:
|
||||||
return
|
return
|
||||||
elif self.settings["related_object"].HasAssignments:
|
elif settings["related_object"].HasAssignments:
|
||||||
for rel in self.settings["related_object"].HasAssignments:
|
for rel in settings["related_object"].HasAssignments:
|
||||||
if rel.is_a("IfcRelAssignsToProduct") and rel.RelatingProduct == self.settings["relating_product"]:
|
if rel.is_a("IfcRelAssignsToProduct") and rel.RelatingProduct == settings["relating_product"]:
|
||||||
return
|
return
|
||||||
|
|
||||||
referenced_by = None
|
referenced_by = None
|
||||||
|
|
||||||
if is_grid_axis:
|
if is_grid_axis:
|
||||||
axis = self.settings["relating_product"]
|
axis = settings["relating_product"]
|
||||||
grid = None
|
grid = None
|
||||||
for attribute in ("PartOfW", "PartOfV", "PartOfU"):
|
for attribute in ("PartOfW", "PartOfV", "PartOfU"):
|
||||||
if getattr(axis, attribute, None):
|
if getattr(axis, attribute, None):
|
||||||
grid = getattr(axis, attribute)[0]
|
grid = getattr(axis, attribute)[0]
|
||||||
self.settings["relating_product"] = grid
|
settings["relating_product"] = grid
|
||||||
for rel in grid.ReferencedBy:
|
for rel in grid.ReferencedBy:
|
||||||
if rel.Name == axis.AxisTag:
|
if rel.Name == axis.AxisTag:
|
||||||
referenced_by = rel
|
referenced_by = rel
|
||||||
break
|
break
|
||||||
elif self.settings["relating_product"].ReferencedBy:
|
elif settings["relating_product"].ReferencedBy:
|
||||||
referenced_by = self.settings["relating_product"].ReferencedBy[0]
|
referenced_by = settings["relating_product"].ReferencedBy[0]
|
||||||
|
|
||||||
if referenced_by:
|
if referenced_by:
|
||||||
related_objects = list(referenced_by.RelatedObjects)
|
related_objects = list(referenced_by.RelatedObjects)
|
||||||
related_objects.append(self.settings["related_object"])
|
related_objects.append(settings["related_object"])
|
||||||
referenced_by.RelatedObjects = related_objects
|
referenced_by.RelatedObjects = related_objects
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": referenced_by})
|
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": referenced_by})
|
||||||
else:
|
else:
|
||||||
referenced_by = self.file.create_entity(
|
referenced_by = file.create_entity(
|
||||||
"IfcRelAssignsToProduct",
|
"IfcRelAssignsToProduct",
|
||||||
**{
|
**{
|
||||||
"GlobalId": ifcopenshell.guid.new(),
|
"GlobalId": ifcopenshell.guid.new(),
|
||||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", file),
|
||||||
"RelatedObjects": [self.settings["related_object"]],
|
"RelatedObjects": [settings["related_object"]],
|
||||||
"RelatingProduct": self.settings["relating_product"],
|
"RelatingProduct": settings["relating_product"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_text_literal(file, text_literal=None, attributes=None) -> None:
|
||||||
def __init__(self, file, text_literal=None, attributes=None):
|
|
||||||
"""Edits the attributes of an IfcTextLiteral
|
"""Edits the attributes of an IfcTextLiteral
|
||||||
|
|
||||||
For more information about the attributes and data types of an
|
For more information about the attributes and data types of an
|
||||||
@@ -39,9 +38,7 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("drawing.edit_text_literal", model,
|
ifcopenshell.api.run("drawing.edit_text_literal", model,
|
||||||
text_literal=text, attributes={"Literal": "MY ANNOTATION"})
|
text_literal=text, attributes={"Literal": "MY ANNOTATION"})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"text_literal": text_literal, "attributes": attributes or {}}
|
||||||
self.settings = {"text_literal": text_literal, "attributes": attributes or {}}
|
|
||||||
|
|
||||||
def execute(self):
|
for name, value in settings["attributes"].items():
|
||||||
for name, value in self.settings["attributes"].items():
|
setattr(settings["text_literal"], name, value)
|
||||||
setattr(self.settings["text_literal"], name, value)
|
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def unassign_product(file, relating_product=None, related_object=None) -> None:
|
||||||
def __init__(self, file, relating_product=None, related_object=None):
|
|
||||||
"""Unassigns a product and an object (typically an annotation)
|
"""Unassigns a product and an object (typically an annotation)
|
||||||
|
|
||||||
Smart annotation objects can be associated with products so that they
|
Smart annotation objects can be associated with products so that they
|
||||||
@@ -51,24 +50,22 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("drawing.unassign_product", model,
|
ifcopenshell.api.run("drawing.unassign_product", model,
|
||||||
relating_product=furniture, related_object=annotation)
|
relating_product=furniture, related_object=annotation)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {
|
||||||
self.settings = {
|
|
||||||
"relating_product": relating_product,
|
"relating_product": relating_product,
|
||||||
"related_object": related_object,
|
"related_object": related_object,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self):
|
for rel in settings["related_object"].HasAssignments or []:
|
||||||
for rel in self.settings["related_object"].HasAssignments or []:
|
if not rel.is_a("IfcRelAssignsToProduct") or rel.RelatingProduct != settings["relating_product"]:
|
||||||
if not rel.is_a("IfcRelAssignsToProduct") or rel.RelatingProduct != self.settings["relating_product"]:
|
|
||||||
continue
|
continue
|
||||||
if len(rel.RelatedObjects) == 1:
|
if len(rel.RelatedObjects) == 1:
|
||||||
history = rel.OwnerHistory
|
history = rel.OwnerHistory
|
||||||
self.file.remove(rel)
|
file.remove(rel)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
return
|
return
|
||||||
related_objects = list(rel.RelatedObjects)
|
related_objects = list(rel.RelatedObjects)
|
||||||
related_objects.remove(self.settings["related_object"])
|
related_objects.remove(settings["related_object"])
|
||||||
rel.RelatedObjects = related_objects
|
rel.RelatedObjects = related_objects
|
||||||
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel})
|
ifcopenshell.api.run("owner.update_owner_history", file, **{"element": rel})
|
||||||
return rel
|
return rel
|
||||||
|
|||||||
@@ -15,3 +15,30 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .add_axis_representation import add_axis_representation
|
||||||
|
from .add_boolean import add_boolean
|
||||||
|
from .add_door_representation import add_door_representation
|
||||||
|
from .add_footprint_representation import add_footprint_representation
|
||||||
|
from .add_mesh_representation import add_mesh_representation
|
||||||
|
from .add_profile_representation import add_profile_representation
|
||||||
|
from .add_railing_representation import add_railing_representation
|
||||||
|
|
||||||
|
try:
|
||||||
|
from .add_representation import add_representation
|
||||||
|
except ModuleNotFoundError as e:
|
||||||
|
print(f"Note: API not available due to missing dependencies: geometry.add_representation - {e}")
|
||||||
|
from .add_slab_representation import add_slab_representation
|
||||||
|
from .add_wall_representation import add_wall_representation
|
||||||
|
from .add_window_representation import add_window_representation
|
||||||
|
from .assign_representation import assign_representation
|
||||||
|
from .connect_element import connect_element
|
||||||
|
from .connect_path import connect_path
|
||||||
|
from .create_2pt_wall import create_2pt_wall
|
||||||
|
from .disconnect_element import disconnect_element
|
||||||
|
from .disconnect_path import disconnect_path
|
||||||
|
from .edit_object_placement import edit_object_placement
|
||||||
|
from .map_representation import map_representation
|
||||||
|
from .remove_boolean import remove_boolean
|
||||||
|
from .remove_representation import remove_representation
|
||||||
|
from .unassign_representation import unassign_representation
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_axis_representation(file, context=None, axis=None) -> None:
|
||||||
def __init__(self, file, context=None, axis=None):
|
|
||||||
"""Adds a new axis representation
|
"""Adds a new axis representation
|
||||||
|
|
||||||
Certain objects are typically "axis-based", such as walls, beams,
|
Certain objects are typically "axis-based", such as walls, beams,
|
||||||
@@ -68,12 +67,16 @@ class Usecase:
|
|||||||
axis = ifcopenshell.api.run("geometry.add_axis_representation", model,
|
axis = ifcopenshell.api.run("geometry.add_axis_representation", model,
|
||||||
context=context, axis=[(0.0, 0.0), (1.0, 0.0)])
|
context=context, axis=[(0.0, 0.0), (1.0, 0.0)])
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"context": context,
|
"context": context,
|
||||||
"axis": axis or [],
|
"axis": axis or [],
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
is_2d = len(self.settings["axis"][0]) == 2
|
is_2d = len(self.settings["axis"][0]) == 2
|
||||||
@@ -82,9 +85,13 @@ class Usecase:
|
|||||||
curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points])
|
curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points])
|
||||||
else:
|
else:
|
||||||
if is_2d:
|
if is_2d:
|
||||||
curve = self.file.createIfcIndexedPolyCurve(self.file.createIfcCartesianPointList2D(points), None, False)
|
curve = self.file.createIfcIndexedPolyCurve(
|
||||||
|
self.file.createIfcCartesianPointList2D(points), None, False
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
curve = self.file.createIfcIndexedPolyCurve(self.file.createIfcCartesianPointList3D(points), None, False)
|
curve = self.file.createIfcIndexedPolyCurve(
|
||||||
|
self.file.createIfcCartesianPointList3D(points), None, False
|
||||||
|
)
|
||||||
return self.file.createIfcShapeRepresentation(
|
return self.file.createIfcShapeRepresentation(
|
||||||
self.settings["context"],
|
self.settings["context"],
|
||||||
self.settings["context"].ContextIdentifier,
|
self.settings["context"].ContextIdentifier,
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ import ifcopenshell.util.unit
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_boolean(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
self.settings = {
|
usecase.settings = {
|
||||||
"representation": None,
|
"representation": None,
|
||||||
"operator": "DIFFERENCE",
|
"operator": "DIFFERENCE",
|
||||||
# IfcHalfSpaceSolid, Mesh
|
# IfcHalfSpaceSolid, Mesh
|
||||||
@@ -35,9 +35,12 @@ class Usecase:
|
|||||||
"should_force_faceted_brep": False,
|
"should_force_faceted_brep": False,
|
||||||
"should_force_triangulation": False,
|
"should_force_triangulation": False,
|
||||||
}
|
}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
if self.settings["type"] == "IfcHalfSpaceSolid":
|
if self.settings["type"] == "IfcHalfSpaceSolid":
|
||||||
|
|||||||
@@ -63,11 +63,7 @@ def create_ifc_door_lining(
|
|||||||
|
|
||||||
points = [p.xz for p in points]
|
points = [p.xz for p in points]
|
||||||
door_lining = builder.polyline(points, closed=True)
|
door_lining = builder.polyline(points, closed=True)
|
||||||
door_lining = builder.extrude(
|
door_lining = builder.extrude(door_lining, size.y, **builder.extrude_kwargs("Y"))
|
||||||
door_lining,
|
|
||||||
size.y,
|
|
||||||
**builder.extrude_kwargs("Y")
|
|
||||||
)
|
|
||||||
builder.translate(door_lining, position)
|
builder.translate(door_lining, position)
|
||||||
|
|
||||||
return door_lining
|
return door_lining
|
||||||
@@ -79,20 +75,20 @@ def create_ifc_box(builder: ShapeBuilder, size: Vector, position: Vector = V(0,
|
|||||||
return box
|
return box
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_door_representation(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
"""units in usecase_settings expected to be in ifc project units"""
|
||||||
"""units in settings expected to be in ifc project units"""
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDoor.htm
|
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDoor.htm
|
||||||
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDoorTypeOperationEnum.htm
|
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDoorTypeOperationEnum.htm
|
||||||
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDoorLiningProperties.htm
|
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDoorLiningProperties.htm
|
||||||
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDoorPanelProperties.htm
|
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDoorPanelProperties.htm
|
||||||
self.settings = {"unit_scale": ifcopenshell.util.unit.calculate_unit_scale(self.file)}
|
usecase.settings = {"unit_scale": ifcopenshell.util.unit.calculate_unit_scale(usecase.file)}
|
||||||
self.settings.update(
|
usecase.settings.update(
|
||||||
{
|
{
|
||||||
"context": None, # IfcGeometricRepresentationContext
|
"context": None, # IfcGeometricRepresentationContext
|
||||||
"overall_height": self.convert_si_to_unit(2.0),
|
"overall_height": usecase.convert_si_to_unit(2.0),
|
||||||
"overall_width": self.convert_si_to_unit(0.9),
|
"overall_width": usecase.convert_si_to_unit(0.9),
|
||||||
# DOUBLE_DOOR_DOUBLE_SWING, DOUBLE_DOOR_FOLDING, DOUBLE_DOOR_LIFTING_VERTICAL,
|
# DOUBLE_DOOR_DOUBLE_SWING, DOUBLE_DOOR_FOLDING, DOUBLE_DOOR_LIFTING_VERTICAL,
|
||||||
# DOUBLE_DOOR_SINGLE_SWING, DOUBLE_DOOR_SINGLE_SWING_OPPOSITE_LEFT,
|
# DOUBLE_DOOR_SINGLE_SWING, DOUBLE_DOOR_SINGLE_SWING_OPPOSITE_LEFT,
|
||||||
# DOUBLE_DOOR_SINGLE_SWING_OPPOSITE_RIGHT, DOUBLE_DOOR_SLIDING,
|
# DOUBLE_DOOR_SINGLE_SWING_OPPOSITE_RIGHT, DOUBLE_DOOR_SLIDING,
|
||||||
@@ -103,39 +99,39 @@ class Usecase:
|
|||||||
# SLIDING_TO_RIGHT, SWING_FIXED_LEFT, SWING_FIXED_RIGHT
|
# SLIDING_TO_RIGHT, SWING_FIXED_LEFT, SWING_FIXED_RIGHT
|
||||||
"operation_type": "SINGLE_SWING_LEFT", # door type
|
"operation_type": "SINGLE_SWING_LEFT", # door type
|
||||||
"lining_properties": {
|
"lining_properties": {
|
||||||
"LiningDepth": self.convert_si_to_unit(0.050),
|
"LiningDepth": usecase.convert_si_to_unit(0.050),
|
||||||
"LiningThickness": self.convert_si_to_unit(0.050),
|
"LiningThickness": usecase.convert_si_to_unit(0.050),
|
||||||
# offset from the outer side of the wall (by Y-axis)
|
# offset from the outer side of the wall (by Y-axis)
|
||||||
"LiningOffset": self.convert_si_to_unit(0.0),
|
"LiningOffset": usecase.convert_si_to_unit(0.0),
|
||||||
# offset from the wall
|
# offset from the wall
|
||||||
"LiningToPanelOffsetX": self.convert_si_to_unit(0.025),
|
"LiningToPanelOffsetX": usecase.convert_si_to_unit(0.025),
|
||||||
# offset from the X-axis (unlike windows)
|
# offset from the X-axis (unlike windows)
|
||||||
"LiningToPanelOffsetY": self.convert_si_to_unit(0.025),
|
"LiningToPanelOffsetY": usecase.convert_si_to_unit(0.025),
|
||||||
# transom - vertical distance between door and window panels
|
# transom - vertical distance between door and window panels
|
||||||
"TransomThickness": self.convert_si_to_unit(0.000),
|
"TransomThickness": usecase.convert_si_to_unit(0.000),
|
||||||
# TransomOffset - distance from the bottom door opening
|
# TransomOffset - distance from the bottom door opening
|
||||||
# to the beginning of the transom
|
# to the beginning of the transom
|
||||||
# unlike windows TransomOffset which goes to the center of the transom
|
# unlike windows TransomOffset which goes to the center of the transom
|
||||||
"TransomOffset": self.convert_si_to_unit(1.525),
|
"TransomOffset": usecase.convert_si_to_unit(1.525),
|
||||||
"ShapeAspectStyle": None, # DEPRECATED
|
"ShapeAspectStyle": None, # DEPRECATED
|
||||||
# Casing cover wall faces around the opening
|
# Casing cover wall faces around the opening
|
||||||
# on the left, right and upper sides
|
# on the left, right and upper sides
|
||||||
# Casing should be either on both sides of the wall or no casing
|
# Casing should be either on both sides of the wall or no casing
|
||||||
# If `LiningOffset` is present then therefore casing is not possible on outer wall
|
# If `LiningOffset` is present then therefore casing is not possible on outer wall
|
||||||
# therefore there will be no casing on inner wall either
|
# therefore there will be no casing on inner wall either
|
||||||
"CasingDepth": self.convert_si_to_unit(0.005),
|
"CasingDepth": usecase.convert_si_to_unit(0.005),
|
||||||
"CasingThickness": self.convert_si_to_unit(0.075), # by Z-axis
|
"CasingThickness": usecase.convert_si_to_unit(0.075), # by Z-axis
|
||||||
# Threshold covers the bottom side of the opening
|
# Threshold covers the bottom side of the opening
|
||||||
"ThresholdDepth": self.convert_si_to_unit(0.1),
|
"ThresholdDepth": usecase.convert_si_to_unit(0.1),
|
||||||
"ThresholdThickness": self.convert_si_to_unit(0.025), # by Z-axis
|
"ThresholdThickness": usecase.convert_si_to_unit(0.025), # by Z-axis
|
||||||
# offset by Y-axis
|
# offset by Y-axis
|
||||||
"ThresholdOffset": self.convert_si_to_unit(0.000),
|
"ThresholdOffset": usecase.convert_si_to_unit(0.000),
|
||||||
},
|
},
|
||||||
"panel_properties": {
|
"panel_properties": {
|
||||||
"PanelDepth": self.convert_si_to_unit(0.035), # by Y
|
"PanelDepth": usecase.convert_si_to_unit(0.035), # by Y
|
||||||
"PanelWidth": 1.0, # as ratio to the clear door opening
|
"PanelWidth": 1.0, # as ratio to the clear door opening
|
||||||
"FrameDepth": self.convert_si_to_unit(0.035), # by Y
|
"FrameDepth": usecase.convert_si_to_unit(0.035), # by Y
|
||||||
"FrameThickness": self.convert_si_to_unit(0.035), # by X
|
"FrameThickness": usecase.convert_si_to_unit(0.035), # by X
|
||||||
# LEFT, MIDDLE, RIGHT, NOTDEFINED
|
# LEFT, MIDDLE, RIGHT, NOTDEFINED
|
||||||
"PanelPosition": ..., # NEVER USED
|
"PanelPosition": ..., # NEVER USED
|
||||||
# defines the basic ways to describe how door panels operate
|
# defines the basic ways to describe how door panels operate
|
||||||
@@ -145,9 +141,12 @@ class Usecase:
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
builder = ShapeBuilder(self.file)
|
builder = ShapeBuilder(self.file)
|
||||||
overall_height = self.settings["overall_height"]
|
overall_height = self.settings["overall_height"]
|
||||||
|
|||||||
@@ -19,20 +19,17 @@
|
|||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_footprint_representation(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
settings = {
|
||||||
self.file = file
|
|
||||||
self.settings = {
|
|
||||||
"context": None, # IfcGeometricRepresentationContext
|
"context": None, # IfcGeometricRepresentationContext
|
||||||
"curves": [], # A list of IFC curves to include in the curve set
|
"curves": [], # A list of IFC curves to include in the curve set
|
||||||
}
|
}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
settings[key] = value
|
||||||
|
|
||||||
def execute(self):
|
return file.createIfcShapeRepresentation(
|
||||||
return self.file.createIfcShapeRepresentation(
|
settings["context"],
|
||||||
self.settings["context"],
|
settings["context"].ContextIdentifier,
|
||||||
self.settings["context"].ContextIdentifier,
|
|
||||||
"GeometricCurveSet",
|
"GeometricCurveSet",
|
||||||
[self.file.createIfcGeometricCurveSet(self.settings["curves"])],
|
[file.createIfcGeometricCurveSet(settings["curves"])],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -19,10 +19,10 @@
|
|||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_mesh_representation(file: ifcopenshell.file, **usecase_settings) -> None:
|
||||||
def __init__(self, file: ifcopenshell.file, **settings):
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
self.settings = {
|
usecase.settings = {
|
||||||
"context": None, # IfcGeometricRepresentationContext
|
"context": None, # IfcGeometricRepresentationContext
|
||||||
# Vertices, edges, and faces are given in the form of: [item1, item2, item3, ...]
|
# Vertices, edges, and faces are given in the form of: [item1, item2, item3, ...]
|
||||||
# ... where itemN = [(0., 0., 0.), (1., 1., 1.), (x, y, z), ...]
|
# ... where itemN = [(0., 0., 0.), (1., 1., 1.), (x, y, z), ...]
|
||||||
@@ -35,9 +35,12 @@ class Usecase:
|
|||||||
"unit_scale": None, # A scale factor to apply for all vectors in case the unit is different
|
"unit_scale": None, # A scale factor to apply for all vectors in case the unit is different
|
||||||
"force_faceted_brep": False, # Force using IfcFacetedBreps instead of IfcPolygonalFaceSets
|
"force_faceted_brep": False, # Force using IfcFacetedBreps instead of IfcPolygonalFaceSets
|
||||||
}
|
}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
if self.settings["unit_scale"] is None:
|
if self.settings["unit_scale"] is None:
|
||||||
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ import ifcopenshell.util.unit
|
|||||||
from ifcopenshell.util.data import Clipping
|
from ifcopenshell.util.data import Clipping
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_profile_representation(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
self.settings = {
|
usecase.settings = {
|
||||||
"context": None, # IfcGeometricRepresentationContext
|
"context": None, # IfcGeometricRepresentationContext
|
||||||
"profile": None,
|
"profile": None,
|
||||||
"depth": 1.0,
|
"depth": 1.0,
|
||||||
@@ -34,9 +34,12 @@ class Usecase:
|
|||||||
"clippings": [], # A list of planes that define clipping half space solids
|
"clippings": [], # A list of planes that define clipping half space solids
|
||||||
"placement_zx_axes": (None, None),
|
"placement_zx_axes": (None, None),
|
||||||
}
|
}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
self.settings["clippings"] = [Clipping.parse(c) for c in self.settings["clippings"]]
|
self.settings["clippings"] = [Clipping.parse(c) for c in self.settings["clippings"]]
|
||||||
|
|||||||
@@ -31,39 +31,42 @@ def mm(x):
|
|||||||
return x / 1000
|
return x / 1000
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_railing_representation(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
|
||||||
"""
|
"""
|
||||||
units in settings expected to be in ifc project units
|
units in usecase_settings expected to be in ifc project units
|
||||||
|
|
||||||
`railing_path` is a list of point coordinates for the railing path,
|
`railing_path` is a list of point coordinates for the railing path,
|
||||||
coordinates are expected to be at the top of the railing, not at the center
|
coordinates are expected to be at the top of the railing, not at the center
|
||||||
|
|
||||||
`railing_path` is expected to be a list of Vector objects
|
`railing_path` is expected to be a list of Vector objects
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {"unit_scale": ifcopenshell.util.unit.calculate_unit_scale(self.file)}
|
usecase.file = file
|
||||||
self.settings.update(
|
usecase.settings = {"unit_scale": ifcopenshell.util.unit.calculate_unit_scale(usecase.file)}
|
||||||
|
usecase.settings.update(
|
||||||
{
|
{
|
||||||
"context": None, # IfcGeometricRepresentationContext
|
"context": None, # IfcGeometricRepresentationContext
|
||||||
"railing_type": "WALL_MOUNTED_HANDRAIL",
|
"railing_type": "WALL_MOUNTED_HANDRAIL",
|
||||||
"railing_path": self.path_si_to_units([V(0, 0, 1), V(1, 0, 1), V(2, 0, 1)]),
|
"railing_path": usecase.path_si_to_units([V(0, 0, 1), V(1, 0, 1), V(2, 0, 1)]),
|
||||||
"use_manual_supports": False,
|
"use_manual_supports": False,
|
||||||
"support_spacing": self.convert_si_to_unit(mm(1000)),
|
"support_spacing": usecase.convert_si_to_unit(mm(1000)),
|
||||||
"railing_diameter": self.convert_si_to_unit(mm(50)),
|
"railing_diameter": usecase.convert_si_to_unit(mm(50)),
|
||||||
"clear_width": self.convert_si_to_unit(mm(40)),
|
"clear_width": usecase.convert_si_to_unit(mm(40)),
|
||||||
"terminal_type": "180",
|
"terminal_type": "180",
|
||||||
"height": self.convert_si_to_unit(mm(1000)),
|
"height": usecase.convert_si_to_unit(mm(1000)),
|
||||||
"looped_path": False,
|
"looped_path": False,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
|
||||||
if self.settings["railing_type"] != "WALL_MOUNTED_HANDRAIL":
|
if usecase.settings["railing_type"] != "WALL_MOUNTED_HANDRAIL":
|
||||||
raise Exception('Only "WALL_MOUNTED_HANDRAIL" railing_type is supported at the moment.')
|
raise Exception('Only "WALL_MOUNTED_HANDRAIL" railing_type is supported at the moment.')
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
arc_points = []
|
arc_points = []
|
||||||
items_3d = []
|
items_3d = []
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ X_AXIS = Vector((1, 0, 0))
|
|||||||
EPSILON = 1e-6
|
EPSILON = 1e-6
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_representation(file: ifcopenshell.file, **usecase_settings) -> ifcopenshell.entity_instance:
|
||||||
def __init__(self, file: ifcopenshell.file, **settings):
|
usecase = Usecase()
|
||||||
# TODO: This usecase currently depends on Blender's data model
|
# TODO: This usecase currently depends on Blender's data model
|
||||||
self.file = file
|
usecase.file = file
|
||||||
self.settings = {
|
usecase.settings = {
|
||||||
"context": None, # IfcGeometricRepresentationContext
|
"context": None, # IfcGeometricRepresentationContext
|
||||||
"blender_object": None, # This is (currently) a Blender object, hence this depends on Blender now
|
"blender_object": None, # This is (currently) a Blender object, hence this depends on Blender now
|
||||||
"geometry": None, # This is (currently) a Blender data object, hence this depends on Blender now
|
"geometry": None, # This is (currently) a Blender data object, hence this depends on Blender now
|
||||||
@@ -54,11 +54,14 @@ class Usecase:
|
|||||||
"profile_set_usage": None, # The material profile set if the extrusion requires it
|
"profile_set_usage": None, # The material profile set if the extrusion requires it
|
||||||
"text_literal": None, # The text literal if the representation requires it
|
"text_literal": None, # The text literal if the representation requires it
|
||||||
}
|
}
|
||||||
self.ifc_vertices = []
|
usecase.ifc_vertices = []
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
def execute(self) -> ifcopenshell.entity_instance:
|
|
||||||
|
class Usecase:
|
||||||
|
def execute(self):
|
||||||
self.is_manifold = None
|
self.is_manifold = None
|
||||||
if (
|
if (
|
||||||
isinstance(self.settings["geometry"], bpy.types.Mesh)
|
isinstance(self.settings["geometry"], bpy.types.Mesh)
|
||||||
@@ -374,10 +377,12 @@ class Usecase:
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
def create_plane(self, polygon):
|
def create_plane(self, polygon):
|
||||||
return self.file.createIfcPlane(Position=self.file.createIfcAxis2Placement3D(
|
return self.file.createIfcPlane(
|
||||||
|
Position=self.file.createIfcAxis2Placement3D(
|
||||||
Location=self.file.createIfcCartesianPoint(polygon.center),
|
Location=self.file.createIfcCartesianPoint(polygon.center),
|
||||||
Axis=self.file.createIfcDirection(polygon.normal),
|
Axis=self.file.createIfcDirection(polygon.normal),
|
||||||
))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def create_annotation_fill_areas(self, is_2d=False) -> list[ifcopenshell.entity_instance]:
|
def create_annotation_fill_areas(self, is_2d=False) -> list[ifcopenshell.entity_instance]:
|
||||||
items = []
|
items = []
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ import ifcopenshell.util.unit
|
|||||||
from math import sin, cos
|
from math import sin, cos
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_slab_representation(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
self.settings = {
|
usecase.settings = {
|
||||||
"context": None, # IfcGeometricRepresentationContext
|
"context": None, # IfcGeometricRepresentationContext
|
||||||
"depth": 0.2,
|
"depth": 0.2,
|
||||||
"x_angle": 0, # Radians
|
"x_angle": 0, # Radians
|
||||||
@@ -31,9 +31,12 @@ class Usecase:
|
|||||||
# or by dictionaries of arguments for `Clipping.parse`
|
# or by dictionaries of arguments for `Clipping.parse`
|
||||||
"clippings": [], # A list of planes that define clipping half space solids
|
"clippings": [], # A list of planes that define clipping half space solids
|
||||||
}
|
}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
return self.file.createIfcShapeRepresentation(
|
return self.file.createIfcShapeRepresentation(
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ from math import sin, cos
|
|||||||
from ifcopenshell.util.data import Clipping
|
from ifcopenshell.util.data import Clipping
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_wall_representation(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
self.settings = {
|
usecase.settings = {
|
||||||
"context": None, # IfcGeometricRepresentationContext
|
"context": None, # IfcGeometricRepresentationContext
|
||||||
"length": 1.0,
|
"length": 1.0,
|
||||||
"height": 3.0,
|
"height": 3.0,
|
||||||
@@ -37,9 +37,12 @@ class Usecase:
|
|||||||
"clippings": [], # A list of planes that define clipping half space solids
|
"clippings": [], # A list of planes that define clipping half space solids
|
||||||
"booleans": [], # Any existing IfcBooleanResults
|
"booleans": [], # Any existing IfcBooleanResults
|
||||||
}
|
}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
self.settings["clippings"] = [Clipping.parse(c) for c in self.settings["clippings"]]
|
self.settings["clippings"] = [Clipping.parse(c) for c in self.settings["clippings"]]
|
||||||
|
|||||||
@@ -56,12 +56,7 @@ def create_ifc_window_frame_simple(
|
|||||||
th_left, th_up, th_right, th_bottom = thickness
|
th_left, th_up, th_right, th_bottom = thickness
|
||||||
|
|
||||||
def get_extruded_profile(profile):
|
def get_extruded_profile(profile):
|
||||||
return builder.extrude(
|
return builder.extrude(profile, size.y, position=position, **builder.extrude_kwargs("Y"))
|
||||||
profile,
|
|
||||||
size.y,
|
|
||||||
position=position,
|
|
||||||
**builder.extrude_kwargs("Y")
|
|
||||||
)
|
|
||||||
|
|
||||||
# if all lining sides are present then we can just use two rectangles
|
# if all lining sides are present then we can just use two rectangles
|
||||||
# as inner and outer curves of the profile
|
# as inner and outer curves of the profile
|
||||||
@@ -207,12 +202,7 @@ def create_ifc_window(
|
|||||||
|
|
||||||
glass_position = frame_position + V(0, frame_size.y / 2 - glass_thickness / 2, 0)
|
glass_position = frame_position + V(0, frame_size.y / 2 - glass_thickness / 2, 0)
|
||||||
glass_rect = builder.deep_copy(frame_extruded_items[0].SweptArea.InnerCurves[0])
|
glass_rect = builder.deep_copy(frame_extruded_items[0].SweptArea.InnerCurves[0])
|
||||||
glass = builder.extrude(
|
glass = builder.extrude(glass_rect, glass_thickness, position=glass_position, **builder.extrude_kwargs("Y"))
|
||||||
glass_rect,
|
|
||||||
glass_thickness,
|
|
||||||
position=glass_position,
|
|
||||||
**builder.extrude_kwargs("Y")
|
|
||||||
)
|
|
||||||
|
|
||||||
output_items = [lining_items, frame_extruded_items, [glass]]
|
output_items = [lining_items, frame_extruded_items, [glass]]
|
||||||
builder.translate(chain(*output_items), position)
|
builder.translate(chain(*output_items), position)
|
||||||
@@ -220,58 +210,58 @@ def create_ifc_window(
|
|||||||
return output_items
|
return output_items
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_window_representation(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
"""units in usecase_settings expected to be in ifc project units"""
|
||||||
"""units in settings expected to be in ifc project units"""
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindow.htm
|
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindow.htm
|
||||||
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindowTypePartitioningEnum.htm
|
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindowTypePartitioningEnum.htm
|
||||||
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindowLiningProperties.htm
|
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindowLiningProperties.htm
|
||||||
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindowPanelProperties.htm
|
# http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcWindowPanelProperties.htm
|
||||||
self.settings = {"unit_scale": ifcopenshell.util.unit.calculate_unit_scale(self.file)}
|
usecase.settings = {"unit_scale": ifcopenshell.util.unit.calculate_unit_scale(usecase.file)}
|
||||||
self.settings.update(
|
usecase.settings.update(
|
||||||
{
|
{
|
||||||
"context": None, # IfcGeometricRepresentationContext
|
"context": None, # IfcGeometricRepresentationContext
|
||||||
# SINGLE_PANEL, DOUBLE_PANEL_HORIZONTAL, DOUBLE_PANEL_VERTICAL,
|
# SINGLE_PANEL, DOUBLE_PANEL_HORIZONTAL, DOUBLE_PANEL_VERTICAL,
|
||||||
# TRIPLE_PANEL_BOTTOM, TRIPLE_PANEL_HORIZONTAL, TRIPLE_PANEL_LEFT,
|
# TRIPLE_PANEL_BOTTOM, TRIPLE_PANEL_HORIZONTAL, TRIPLE_PANEL_LEFT,
|
||||||
# TRIPLE_PANEL_RIGHT, TRIPLE_PANEL_TOP, TRIPLE_PANEL_VERTICAL
|
# TRIPLE_PANEL_RIGHT, TRIPLE_PANEL_TOP, TRIPLE_PANEL_VERTICAL
|
||||||
"partition_type": "SINGLE_PANEL",
|
"partition_type": "SINGLE_PANEL",
|
||||||
"overall_height": self.convert_si_to_unit(0.9),
|
"overall_height": usecase.convert_si_to_unit(0.9),
|
||||||
"overall_width": self.convert_si_to_unit(0.6),
|
"overall_width": usecase.convert_si_to_unit(0.6),
|
||||||
"lining_properties": {
|
"lining_properties": {
|
||||||
"LiningDepth": self.convert_si_to_unit(0.050),
|
"LiningDepth": usecase.convert_si_to_unit(0.050),
|
||||||
"LiningThickness": self.convert_si_to_unit(0.050),
|
"LiningThickness": usecase.convert_si_to_unit(0.050),
|
||||||
"LiningOffset": self.convert_si_to_unit(0.050), # offset to the wall
|
"LiningOffset": usecase.convert_si_to_unit(0.050), # offset to the wall
|
||||||
# offset from the wall
|
# offset from the wall
|
||||||
"LiningToPanelOffsetX": self.convert_si_to_unit(0.025),
|
"LiningToPanelOffsetX": usecase.convert_si_to_unit(0.025),
|
||||||
# offset from the lining
|
# offset from the lining
|
||||||
# that way it allows you to define overall_depth constant between all panels
|
# that way it allows you to define overall_depth constant between all panels
|
||||||
# and still have panels with different size:
|
# and still have panels with different size:
|
||||||
# overall_depth = lining_depth + offset_y
|
# overall_depth = lining_depth + offset_y
|
||||||
# full offset from X axis = overall_depth - frame_depth
|
# full offset from X axis = overall_depth - frame_depth
|
||||||
"LiningToPanelOffsetY": self.convert_si_to_unit(0.025),
|
"LiningToPanelOffsetY": usecase.convert_si_to_unit(0.025),
|
||||||
# applies to DoublePanelVertical, TriplePanelBottom, TriplePanelTop,
|
# applies to DoublePanelVertical, TriplePanelBottom, TriplePanelTop,
|
||||||
# TriplePanelLeft, TriplePanelRight
|
# TriplePanelLeft, TriplePanelRight
|
||||||
# mullion - horizontal distance between panels
|
# mullion - horizontal distance between panels
|
||||||
"MullionThickness": self.convert_si_to_unit(0.050),
|
"MullionThickness": usecase.convert_si_to_unit(0.050),
|
||||||
# distance from the first lining to the mullion center
|
# distance from the first lining to the mullion center
|
||||||
"FirstMullionOffset": self.convert_si_to_unit(0.3),
|
"FirstMullionOffset": usecase.convert_si_to_unit(0.3),
|
||||||
# applies to TriplePanelVertical
|
# applies to TriplePanelVertical
|
||||||
# distance from the first lining to the second mullion center
|
# distance from the first lining to the second mullion center
|
||||||
"SecondMullionOffset": self.convert_si_to_unit(0.45),
|
"SecondMullionOffset": usecase.convert_si_to_unit(0.45),
|
||||||
# applies to DoublePanelHorizontal, TriplePanelBottom, TriplePanelTop,
|
# applies to DoublePanelHorizontal, TriplePanelBottom, TriplePanelTop,
|
||||||
# TriplePanelLeft, TriplePanelRight
|
# TriplePanelLeft, TriplePanelRight
|
||||||
# works similar way to mullion
|
# works similar way to mullion
|
||||||
"TransomThickness": self.convert_si_to_unit(0.050),
|
"TransomThickness": usecase.convert_si_to_unit(0.050),
|
||||||
"FirstTransomOffset": self.convert_si_to_unit(0.3),
|
"FirstTransomOffset": usecase.convert_si_to_unit(0.3),
|
||||||
# applies to TriplePanelHorizontal
|
# applies to TriplePanelHorizontal
|
||||||
"SecondTransomOffset": self.convert_si_to_unit(0.6),
|
"SecondTransomOffset": usecase.convert_si_to_unit(0.6),
|
||||||
"ShapeAspectStyle": None, # DEPRECATED
|
"ShapeAspectStyle": None, # DEPRECATED
|
||||||
},
|
},
|
||||||
"panel_properties": [
|
"panel_properties": [
|
||||||
{
|
{
|
||||||
"FrameDepth": self.convert_si_to_unit(0.035), # by Y
|
"FrameDepth": usecase.convert_si_to_unit(0.035), # by Y
|
||||||
"FrameThickness": self.convert_si_to_unit(0.035), # by X
|
"FrameThickness": usecase.convert_si_to_unit(0.035), # by X
|
||||||
# BOTTOM, LEFT, MIDDLE, RIGHT, TOP
|
# BOTTOM, LEFT, MIDDLE, RIGHT, TOP
|
||||||
"PanelPosition": ..., # NEVER USED
|
"PanelPosition": ..., # NEVER USED
|
||||||
# defines the basic ways to describe how window panels operate
|
# defines the basic ways to describe how window panels operate
|
||||||
@@ -283,10 +273,13 @@ class Usecase:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
self.settings["panel_schema"] = DEFAULT_PANEL_SCHEMAS[self.settings["partition_type"]]
|
usecase.settings["panel_schema"] = DEFAULT_PANEL_SCHEMAS[usecase.settings["partition_type"]]
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
builder = ShapeBuilder(self.file)
|
builder = ShapeBuilder(self.file)
|
||||||
overall_height = self.settings["overall_height"]
|
overall_height = self.settings["overall_height"]
|
||||||
|
|||||||
@@ -20,13 +20,16 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def assign_representation(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
self.settings = {"product": None, "representation": None}
|
usecase.settings = {"product": None, "representation": None}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
if self.settings["product"].is_a("IfcProduct"):
|
if self.settings["product"].is_a("IfcProduct"):
|
||||||
product_type = ifcopenshell.util.element.get_type(self.settings["product"])
|
product_type = ifcopenshell.util.element.get_type(self.settings["product"])
|
||||||
|
|||||||
@@ -21,44 +21,41 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def connect_element(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
settings = {
|
||||||
self.file = file
|
|
||||||
self.settings = {
|
|
||||||
"relating_element": None,
|
"relating_element": None,
|
||||||
"related_element": None,
|
"related_element": None,
|
||||||
"description": None,
|
"description": None,
|
||||||
}
|
}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
settings[key] = value
|
||||||
|
|
||||||
def execute(self):
|
|
||||||
incompatible_connections = []
|
incompatible_connections = []
|
||||||
|
|
||||||
for rel in self.settings["relating_element"].ConnectedFrom:
|
for rel in settings["relating_element"].ConnectedFrom:
|
||||||
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatingElement == self.settings["related_element"]:
|
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatingElement == settings["related_element"]:
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
|
|
||||||
for rel in self.settings["related_element"].ConnectedTo:
|
for rel in settings["related_element"].ConnectedTo:
|
||||||
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatedElement == self.settings["relating_element"]:
|
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatedElement == settings["relating_element"]:
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
|
|
||||||
if incompatible_connections:
|
if incompatible_connections:
|
||||||
for connection in set(incompatible_connections):
|
for connection in set(incompatible_connections):
|
||||||
history = connection.OwnerHistory
|
history = connection.OwnerHistory
|
||||||
self.file.remove(connection)
|
file.remove(connection)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|
||||||
for rel in self.settings["relating_element"].ConnectedTo:
|
for rel in settings["relating_element"].ConnectedTo:
|
||||||
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatedElement == self.settings["related_element"]:
|
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatedElement == settings["related_element"]:
|
||||||
rel.Description = self.settings["description"]
|
rel.Description = settings["description"]
|
||||||
return rel
|
return rel
|
||||||
|
|
||||||
return self.file.createIfcRelConnectsElements(
|
return file.createIfcRelConnectsElements(
|
||||||
ifcopenshell.guid.new(),
|
ifcopenshell.guid.new(),
|
||||||
OwnerHistory=ifcopenshell.api.run("owner.create_owner_history", self.file),
|
OwnerHistory=ifcopenshell.api.run("owner.create_owner_history", file),
|
||||||
Description=self.settings["description"],
|
Description=settings["description"],
|
||||||
RelatingElement=self.settings["relating_element"],
|
RelatingElement=settings["relating_element"],
|
||||||
RelatedElement=self.settings["related_element"],
|
RelatedElement=settings["related_element"],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,76 +21,73 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def connect_path(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
settings = {
|
||||||
self.file = file
|
|
||||||
self.settings = {
|
|
||||||
"relating_element": None,
|
"relating_element": None,
|
||||||
"related_element": None,
|
"related_element": None,
|
||||||
"relating_connection": "NOTDEFINED",
|
"relating_connection": "NOTDEFINED",
|
||||||
"related_connection": "NOTDEFINED",
|
"related_connection": "NOTDEFINED",
|
||||||
"description": None,
|
"description": None,
|
||||||
}
|
}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
settings[key] = value
|
||||||
|
|
||||||
def execute(self):
|
|
||||||
incompatible_connections = []
|
incompatible_connections = []
|
||||||
for rel in self.settings["relating_element"].ConnectedTo:
|
for rel in settings["relating_element"].ConnectedTo:
|
||||||
if not rel.is_a("IfcRelConnectsPathElements"):
|
if not rel.is_a("IfcRelConnectsPathElements"):
|
||||||
continue
|
continue
|
||||||
if rel.RelatedElement == self.settings["related_element"]:
|
if rel.RelatedElement == settings["related_element"]:
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
elif (
|
elif (
|
||||||
rel.RelatingConnectionType in ["ATSTART", "ATEND"]
|
rel.RelatingConnectionType in ["ATSTART", "ATEND"]
|
||||||
and rel.RelatingConnectionType == self.settings["relating_connection"]
|
and rel.RelatingConnectionType == settings["relating_connection"]
|
||||||
):
|
):
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
|
|
||||||
for rel in self.settings["relating_element"].ConnectedFrom:
|
for rel in settings["relating_element"].ConnectedFrom:
|
||||||
if not rel.is_a("IfcRelConnectsPathElements"):
|
if not rel.is_a("IfcRelConnectsPathElements"):
|
||||||
continue
|
continue
|
||||||
if (
|
if (
|
||||||
rel.RelatedConnectionType in ["ATSTART", "ATEND"]
|
rel.RelatedConnectionType in ["ATSTART", "ATEND"]
|
||||||
and rel.RelatedConnectionType == self.settings["relating_connection"]
|
and rel.RelatedConnectionType == settings["relating_connection"]
|
||||||
):
|
):
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
|
|
||||||
for rel in self.settings["related_element"].ConnectedFrom:
|
for rel in settings["related_element"].ConnectedFrom:
|
||||||
if not rel.is_a("IfcRelConnectsPathElements"):
|
if not rel.is_a("IfcRelConnectsPathElements"):
|
||||||
continue
|
continue
|
||||||
if (
|
if (
|
||||||
rel.RelatedConnectionType in ["ATSTART", "ATEND"]
|
rel.RelatedConnectionType in ["ATSTART", "ATEND"]
|
||||||
and rel.RelatedConnectionType == self.settings["related_connection"]
|
and rel.RelatedConnectionType == settings["related_connection"]
|
||||||
):
|
):
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
|
|
||||||
for rel in self.settings["related_element"].ConnectedTo:
|
for rel in settings["related_element"].ConnectedTo:
|
||||||
if not rel.is_a("IfcRelConnectsPathElements"):
|
if not rel.is_a("IfcRelConnectsPathElements"):
|
||||||
continue
|
continue
|
||||||
if rel.RelatedElement == self.settings["relating_element"]:
|
if rel.RelatedElement == settings["relating_element"]:
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
elif (
|
elif (
|
||||||
rel.RelatingConnectionType in ["ATSTART", "ATEND"]
|
rel.RelatingConnectionType in ["ATSTART", "ATEND"]
|
||||||
and rel.RelatingConnectionType == self.settings["related_connection"]
|
and rel.RelatingConnectionType == settings["related_connection"]
|
||||||
):
|
):
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
|
|
||||||
if incompatible_connections:
|
if incompatible_connections:
|
||||||
for connection in set(incompatible_connections):
|
for connection in set(incompatible_connections):
|
||||||
history = connection.OwnerHistory
|
history = connection.OwnerHistory
|
||||||
self.file.remove(connection)
|
file.remove(connection)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|
||||||
return self.file.createIfcRelConnectsPathElements(
|
return file.createIfcRelConnectsPathElements(
|
||||||
ifcopenshell.guid.new(),
|
ifcopenshell.guid.new(),
|
||||||
OwnerHistory=ifcopenshell.api.run("owner.create_owner_history", self.file),
|
OwnerHistory=ifcopenshell.api.run("owner.create_owner_history", file),
|
||||||
Description=self.settings["description"],
|
Description=settings["description"],
|
||||||
RelatingElement=self.settings["relating_element"],
|
RelatingElement=settings["relating_element"],
|
||||||
RelatedElement=self.settings["related_element"],
|
RelatedElement=settings["related_element"],
|
||||||
RelatingConnectionType=self.settings["relating_connection"],
|
RelatingConnectionType=settings["relating_connection"],
|
||||||
RelatedConnectionType=self.settings["related_connection"],
|
RelatedConnectionType=settings["related_connection"],
|
||||||
RelatingPriorities=[],
|
RelatingPriorities=[],
|
||||||
RelatedPriorities=[],
|
RelatedPriorities=[],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def create_2pt_wall(
|
||||||
def __init__(self, file, element=None, context=None, p1=None, p2=None, elevation=None, height=None, thickness=None, is_si=True):
|
file, element=None, context=None, p1=None, p2=None, elevation=None, height=None, thickness=None, is_si=True
|
||||||
self.file = file
|
) -> None:
|
||||||
self.settings = {
|
usecase = Usecase()
|
||||||
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"element": element,
|
"element": element,
|
||||||
"context": context,
|
"context": context,
|
||||||
"p1": p1,
|
"p1": p1,
|
||||||
@@ -32,9 +34,12 @@ class Usecase:
|
|||||||
"elevation": elevation,
|
"elevation": elevation,
|
||||||
"height": height,
|
"height": height,
|
||||||
"thickness": thickness,
|
"thickness": thickness,
|
||||||
"is_si": is_si
|
"is_si": is_si,
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
|
|
||||||
@@ -44,9 +49,9 @@ class Usecase:
|
|||||||
length = float(np.linalg.norm(self.settings["p2"] - self.settings["p1"]))
|
length = float(np.linalg.norm(self.settings["p2"] - self.settings["p1"]))
|
||||||
|
|
||||||
if not self.settings["is_si"]:
|
if not self.settings["is_si"]:
|
||||||
length=self.convert_unit_to_si(length)
|
length = self.convert_unit_to_si(length)
|
||||||
self.settings["height"]=self.convert_unit_to_si(self.settings["height"])
|
self.settings["height"] = self.convert_unit_to_si(self.settings["height"])
|
||||||
self.settings["thickness"]=self.convert_unit_to_si(self.settings["thickness"])
|
self.settings["thickness"] = self.convert_unit_to_si(self.settings["thickness"])
|
||||||
self.settings["p1"][0] = self.convert_unit_to_si(self.settings["p1"][0])
|
self.settings["p1"][0] = self.convert_unit_to_si(self.settings["p1"][0])
|
||||||
self.settings["p1"][1] = self.convert_unit_to_si(self.settings["p1"][1])
|
self.settings["p1"][1] = self.convert_unit_to_si(self.settings["p1"][1])
|
||||||
self.settings["elevation"] = self.convert_unit_to_si(self.settings["elevation"])
|
self.settings["elevation"] = self.convert_unit_to_si(self.settings["elevation"])
|
||||||
|
|||||||
@@ -20,38 +20,35 @@ import ifcopenshell
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def disconnect_element(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
settings = {
|
||||||
self.file = file
|
|
||||||
self.settings = {
|
|
||||||
"relating_element": None,
|
"relating_element": None,
|
||||||
"related_element": None,
|
"related_element": None,
|
||||||
}
|
}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
settings[key] = value
|
||||||
|
|
||||||
def execute(self):
|
|
||||||
incompatible_connections = []
|
incompatible_connections = []
|
||||||
|
|
||||||
for rel in self.settings["relating_element"].ConnectedTo:
|
for rel in settings["relating_element"].ConnectedTo:
|
||||||
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatedElement == self.settings["related_element"]:
|
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatedElement == settings["related_element"]:
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
|
|
||||||
for rel in self.settings["relating_element"].ConnectedFrom:
|
for rel in settings["relating_element"].ConnectedFrom:
|
||||||
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatingElement == self.settings["related_element"]:
|
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatingElement == settings["related_element"]:
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
|
|
||||||
for rel in self.settings["related_element"].ConnectedTo:
|
for rel in settings["related_element"].ConnectedTo:
|
||||||
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatedElement == self.settings["relating_element"]:
|
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatedElement == settings["relating_element"]:
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
|
|
||||||
for rel in self.settings["related_element"].ConnectedFrom:
|
for rel in settings["related_element"].ConnectedFrom:
|
||||||
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatingElement == self.settings["relating_element"]:
|
if rel.is_a() == "IfcRelConnectsElements" and rel.RelatingElement == settings["relating_element"]:
|
||||||
incompatible_connections.append(rel)
|
incompatible_connections.append(rel)
|
||||||
|
|
||||||
if incompatible_connections:
|
if incompatible_connections:
|
||||||
for connection in set(incompatible_connections):
|
for connection in set(incompatible_connections):
|
||||||
history = connection.OwnerHistory
|
history = connection.OwnerHistory
|
||||||
self.file.remove(connection)
|
file.remove(connection)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|||||||
@@ -21,38 +21,35 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def disconnect_path(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
settings = {
|
||||||
self.file = file
|
|
||||||
self.settings = {
|
|
||||||
"relating_element": None,
|
"relating_element": None,
|
||||||
"related_element": None,
|
"related_element": None,
|
||||||
"element": None,
|
"element": None,
|
||||||
"connection_type": None,
|
"connection_type": None,
|
||||||
}
|
}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
settings[key] = value
|
||||||
|
|
||||||
def execute(self):
|
if settings["connection_type"] and settings["element"]:
|
||||||
if self.settings["connection_type"] and self.settings["element"]:
|
|
||||||
connections = [
|
connections = [
|
||||||
r
|
r
|
||||||
for r in self.settings["element"].ConnectedTo
|
for r in settings["element"].ConnectedTo
|
||||||
if r.is_a("IfcRelConnectsPathElements") and r.RelatingConnectionType == self.settings["connection_type"]
|
if r.is_a("IfcRelConnectsPathElements") and r.RelatingConnectionType == settings["connection_type"]
|
||||||
] + [
|
] + [
|
||||||
r
|
r
|
||||||
for r in self.settings["element"].ConnectedFrom
|
for r in settings["element"].ConnectedFrom
|
||||||
if r.is_a("IfcRelConnectsPathElements") and r.RelatedConnectionType == self.settings["connection_type"]
|
if r.is_a("IfcRelConnectsPathElements") and r.RelatedConnectionType == settings["connection_type"]
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
connections = [
|
connections = [
|
||||||
r
|
r
|
||||||
for r in self.settings["relating_element"].ConnectedTo
|
for r in settings["relating_element"].ConnectedTo
|
||||||
if r.is_a("IfcRelConnectsPathElements") and r.RelatedElement == self.settings["related_element"]
|
if r.is_a("IfcRelConnectsPathElements") and r.RelatedElement == settings["related_element"]
|
||||||
]
|
]
|
||||||
|
|
||||||
for connection in set(connections):
|
for connection in set(connections):
|
||||||
history = connection.OwnerHistory
|
history = connection.OwnerHistory
|
||||||
self.file.remove(connection)
|
file.remove(connection)
|
||||||
if history:
|
if history:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, history)
|
ifcopenshell.util.element.remove_deep2(file, history)
|
||||||
|
|||||||
@@ -27,24 +27,26 @@ from typing import Optional, Union
|
|||||||
NPArrayOfFloats = npt.NDArray[np.float64]
|
NPArrayOfFloats = npt.NDArray[np.float64]
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_object_placement(
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
file: ifcopenshell.file,
|
file: ifcopenshell.file,
|
||||||
product: ifcopenshell.entity_instance,
|
product: ifcopenshell.entity_instance,
|
||||||
matrix: Optional[NPArrayOfFloats] = None,
|
matrix: Optional[NPArrayOfFloats] = None,
|
||||||
is_si=True,
|
is_si=True,
|
||||||
should_transform_children=False,
|
should_transform_children=False,
|
||||||
):
|
) -> ifcopenshell.entity_instance:
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"product": product,
|
"product": product,
|
||||||
"matrix": matrix if matrix is not None else np.eye(4),
|
"matrix": matrix if matrix is not None else np.eye(4),
|
||||||
"is_si": is_si,
|
"is_si": is_si,
|
||||||
"should_transform_children": should_transform_children,
|
"should_transform_children": should_transform_children,
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
def execute(self) -> ifcopenshell.entity_instance:
|
|
||||||
|
class Usecase:
|
||||||
|
def execute(self):
|
||||||
if not hasattr(self.settings["product"], "ObjectPlacement"):
|
if not hasattr(self.settings["product"], "ObjectPlacement"):
|
||||||
return
|
return
|
||||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
|
|||||||
@@ -17,14 +17,17 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def map_representation(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
self.settings = {"representation": None}
|
usecase.settings = {"representation": None}
|
||||||
self.ifc_vertices = []
|
usecase.ifc_vertices = []
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
mapping_source = self.get_mapping_source()
|
mapping_source = self.get_mapping_source()
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,16 @@
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_boolean(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
self.settings = {"item": None}
|
usecase.settings = {"item": None}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
item = None
|
item = None
|
||||||
for inverse in self.file.get_inverse(self.settings["item"]):
|
for inverse in self.file.get_inverse(self.settings["item"]):
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_representation(file: ifcopenshell.file, representation: ifcopenshell.entity_instance) -> None:
|
||||||
def __init__(self, file: ifcopenshell.file, representation: ifcopenshell.entity_instance):
|
|
||||||
"""Remove a representation.
|
"""Remove a representation.
|
||||||
|
|
||||||
Also purges representation items and their related elements
|
Also purges representation items and their related elements
|
||||||
@@ -34,22 +33,18 @@ class Usecase:
|
|||||||
:return: None
|
:return: None
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"representation": representation}
|
||||||
self.settings = {"representation": representation}
|
|
||||||
|
|
||||||
def execute(self) -> None:
|
|
||||||
styled_items = set()
|
styled_items = set()
|
||||||
presentation_layer_assignments = set()
|
presentation_layer_assignments = set()
|
||||||
textures = set()
|
textures = set()
|
||||||
colours = set()
|
colours = set()
|
||||||
for subelement in self.file.traverse(self.settings["representation"]):
|
for subelement in file.traverse(settings["representation"]):
|
||||||
if subelement.is_a("IfcRepresentationItem"):
|
if subelement.is_a("IfcRepresentationItem"):
|
||||||
[styled_items.add(s) for s in subelement.StyledByItem or []]
|
[styled_items.add(s) for s in subelement.StyledByItem or []]
|
||||||
# IFC2X3 is using LayerAssignments
|
# IFC2X3 is using LayerAssignments
|
||||||
for s in (
|
for s in (
|
||||||
subelement.LayerAssignment
|
subelement.LayerAssignment if hasattr(subelement, "LayerAssignment") else subelement.LayerAssignments
|
||||||
if hasattr(subelement, "LayerAssignment")
|
|
||||||
else subelement.LayerAssignments
|
|
||||||
):
|
):
|
||||||
presentation_layer_assignments.add(s)
|
presentation_layer_assignments.add(s)
|
||||||
# IfcTessellatedFaceSet inverses
|
# IfcTessellatedFaceSet inverses
|
||||||
@@ -60,21 +55,21 @@ class Usecase:
|
|||||||
presentation_layer_assignments.add(layer)
|
presentation_layer_assignments.add(layer)
|
||||||
|
|
||||||
ifcopenshell.util.element.remove_deep2(
|
ifcopenshell.util.element.remove_deep2(
|
||||||
self.file,
|
file,
|
||||||
self.settings["representation"],
|
settings["representation"],
|
||||||
also_consider=list(styled_items | presentation_layer_assignments | colours),
|
also_consider=list(styled_items | presentation_layer_assignments | colours),
|
||||||
do_not_delete=self.file.by_type("IfcGeometricRepresentationContext"),
|
do_not_delete=file.by_type("IfcGeometricRepresentationContext"),
|
||||||
)
|
)
|
||||||
|
|
||||||
for texture in textures:
|
for texture in textures:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, texture)
|
ifcopenshell.util.element.remove_deep2(file, texture)
|
||||||
for colour in colours:
|
for colour in colours:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, colour)
|
ifcopenshell.util.element.remove_deep2(file, colour)
|
||||||
|
|
||||||
to_delete = getattr(self.file, "to_delete", ())
|
to_delete = getattr(file, "to_delete", ())
|
||||||
for element in styled_items:
|
for element in styled_items:
|
||||||
if not element.Item or element.Item in to_delete:
|
if not element.Item or element.Item in to_delete:
|
||||||
self.file.remove(element)
|
file.remove(element)
|
||||||
for element in presentation_layer_assignments:
|
for element in presentation_layer_assignments:
|
||||||
if all(item in to_delete for item in element.AssignedItems):
|
if all(item in to_delete for item in element.AssignedItems):
|
||||||
self.file.remove(element)
|
file.remove(element)
|
||||||
|
|||||||
@@ -20,13 +20,16 @@ import ifcopenshell.api
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def unassign_representation(file, **usecase_settings) -> None:
|
||||||
def __init__(self, file, **settings):
|
usecase = Usecase()
|
||||||
self.file = file
|
usecase.file = file
|
||||||
self.settings = {"product": None, "representation": None}
|
usecase.settings = {"product": None, "representation": None}
|
||||||
for key, value in settings.items():
|
for key, value in usecase_settings.items():
|
||||||
self.settings[key] = value
|
usecase.settings[key] = value
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
if self.settings["product"].is_a("IfcProduct"):
|
if self.settings["product"].is_a("IfcProduct"):
|
||||||
self.unassign_product_representation(self.settings["product"], self.settings["representation"])
|
self.unassign_product_representation(self.settings["product"], self.settings["representation"])
|
||||||
|
|||||||
@@ -15,3 +15,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .add_georeferencing import add_georeferencing
|
||||||
|
from .edit_georeferencing import edit_georeferencing
|
||||||
|
from .remove_georeferencing import remove_georeferencing
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_georeferencing(file) -> None:
|
||||||
def __init__(self, file):
|
|
||||||
"""Add empty georeferencing entities to a model
|
"""Add empty georeferencing entities to a model
|
||||||
|
|
||||||
By default, models are not georeferenced. Georeferencing requires two
|
By default, models are not georeferenced. Georeferencing requires two
|
||||||
@@ -41,18 +40,16 @@ class Usecase:
|
|||||||
|
|
||||||
ifcopenshell.api.run("georeference.add_georeferencing", model)
|
ifcopenshell.api.run("georeference.add_georeferencing", model)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
|
||||||
|
|
||||||
def execute(self):
|
|
||||||
source_crs = None
|
source_crs = None
|
||||||
for context in self.file.by_type("IfcGeometricRepresentationContext", include_subtypes=False):
|
for context in file.by_type("IfcGeometricRepresentationContext", include_subtypes=False):
|
||||||
if context.ContextType == "Model":
|
if context.ContextType == "Model":
|
||||||
source_crs = context
|
source_crs = context
|
||||||
break
|
break
|
||||||
if not source_crs:
|
if not source_crs:
|
||||||
return
|
return
|
||||||
projected_crs = self.file.create_entity("IfcProjectedCRS", **{"Name": ""})
|
projected_crs = file.create_entity("IfcProjectedCRS", **{"Name": ""})
|
||||||
self.file.create_entity(
|
file.create_entity(
|
||||||
"IfcMapConversion",
|
"IfcMapConversion",
|
||||||
**{
|
**{
|
||||||
"SourceCRS": source_crs,
|
"SourceCRS": source_crs,
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def edit_georeferencing(file, map_conversion=None, projected_crs=None, true_north=None) -> None:
|
||||||
def __init__(self, file, map_conversion=None, projected_crs=None, true_north=None):
|
|
||||||
"""Edits the attributes of a map conversion, projected CRS, and true north
|
"""Edits the attributes of a map conversion, projected CRS, and true north
|
||||||
|
|
||||||
Setting the correct georeferencing parameters is a complex topic and
|
Setting the correct georeferencing parameters is a complex topic and
|
||||||
@@ -81,13 +80,17 @@ class Usecase:
|
|||||||
"Scale": 0.99956, # Ask your surveyor for your site's average combined scale factor!
|
"Scale": 0.99956, # Ask your surveyor for your site's average combined scale factor!
|
||||||
})
|
})
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"map_conversion": map_conversion or {},
|
"map_conversion": map_conversion or {},
|
||||||
"projected_crs": projected_crs or {},
|
"projected_crs": projected_crs or {},
|
||||||
"true_north": true_north or [],
|
"true_north": true_north or [],
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
map_conversion = self.file.by_type("IfcMapConversion")[0]
|
map_conversion = self.file.by_type("IfcMapConversion")[0]
|
||||||
projected_crs = self.file.by_type("IfcProjectedCRS")[0]
|
projected_crs = self.file.by_type("IfcProjectedCRS")[0]
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_georeferencing(file) -> None:
|
||||||
def __init__(self, file):
|
|
||||||
"""Remove georeferencing data
|
"""Remove georeferencing data
|
||||||
|
|
||||||
All georeferencing parameters such as projected CRS and map conversion
|
All georeferencing parameters such as projected CRS and map conversion
|
||||||
@@ -33,13 +32,11 @@ class Usecase:
|
|||||||
# Let's change our mind
|
# Let's change our mind
|
||||||
ifcopenshell.api.run("georeference.remove_georeferencing", model)
|
ifcopenshell.api.run("georeference.remove_georeferencing", model)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
|
||||||
|
|
||||||
def execute(self):
|
map_conversion = file.by_type("IfcMapConversion")[0]
|
||||||
map_conversion = self.file.by_type("IfcMapConversion")[0]
|
projected_crs = file.by_type("IfcProjectedCRS")[0]
|
||||||
projected_crs = self.file.by_type("IfcProjectedCRS")[0]
|
if projected_crs.MapUnit and len(file.get_inverse(projected_crs.MapUnit)) == 1:
|
||||||
if projected_crs.MapUnit and len(self.file.get_inverse(projected_crs.MapUnit)) == 1:
|
|
||||||
# TODO: go deeper for conversion units
|
# TODO: go deeper for conversion units
|
||||||
self.file.remove(projected_crs.MapUnit)
|
file.remove(projected_crs.MapUnit)
|
||||||
self.file.remove(projected_crs)
|
file.remove(projected_crs)
|
||||||
self.file.remove(map_conversion)
|
file.remove(map_conversion)
|
||||||
|
|||||||
@@ -15,3 +15,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .create_axis_curve import create_axis_curve
|
||||||
|
from .create_grid_axis import create_grid_axis
|
||||||
|
from .remove_grid_axis import remove_grid_axis
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ import ifcopenshell.util.placement
|
|||||||
from mathutils import Matrix # For now, we depend on Blender
|
from mathutils import Matrix # For now, we depend on Blender
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def create_axis_curve(file, axis_curve=None, grid_axis=None) -> None:
|
||||||
def __init__(self, file, axis_curve=None, grid_axis=None):
|
|
||||||
"""Adds curve geometry to a grid axis to represent the axis extents
|
"""Adds curve geometry to a grid axis to represent the axis extents
|
||||||
|
|
||||||
This currently depends on the Blender geometry kernel to function.
|
This currently depends on the Blender geometry kernel to function.
|
||||||
@@ -56,12 +55,16 @@ class Usecase:
|
|||||||
ifcopenshell.api.run("grid.create_axis_curve", model, axis_curve=obj1, grid_axis=axis_a)
|
ifcopenshell.api.run("grid.create_axis_curve", model, axis_curve=obj1, grid_axis=axis_a)
|
||||||
ifcopenshell.api.run("grid.create_axis_curve", model, axis_curve=obj2, grid_axis=axis_1)
|
ifcopenshell.api.run("grid.create_axis_curve", model, axis_curve=obj2, grid_axis=axis_1)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
usecase = Usecase()
|
||||||
self.settings = {
|
usecase.file = file
|
||||||
|
usecase.settings = {
|
||||||
"axis_curve": axis_curve, # A Blender object
|
"axis_curve": axis_curve, # A Blender object
|
||||||
"grid_axis": grid_axis,
|
"grid_axis": grid_axis,
|
||||||
}
|
}
|
||||||
|
return usecase.execute()
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
existing_curve = self.settings["grid_axis"].AxisCurve
|
existing_curve = self.settings["grid_axis"].AxisCurve
|
||||||
if existing_curve and len(self.file.get_inverse(existing_curve)) == 1:
|
if existing_curve and len(self.file.get_inverse(existing_curve)) == 1:
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def create_grid_axis(file, axis_tag=None, same_sense=None, uvw_axes=None, grid=None) -> None:
|
||||||
def __init__(self, file, axis_tag=None, same_sense=None, uvw_axes=None, grid=None):
|
|
||||||
"""Adds a new grid axis to a grid
|
"""Adds a new grid axis to a grid
|
||||||
|
|
||||||
An IFC grid will typically have a minimum of two axes which will be
|
An IFC grid will typically have a minimum of two axes which will be
|
||||||
@@ -67,19 +66,17 @@ class Usecase:
|
|||||||
axis_1 = ifcopenshell.api.run("grid.create_grid_axis", model,
|
axis_1 = ifcopenshell.api.run("grid.create_grid_axis", model,
|
||||||
axis_tag="1", uvw_axes="VAxes", grid=grid)
|
axis_tag="1", uvw_axes="VAxes", grid=grid)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {
|
||||||
self.settings = {
|
|
||||||
"axis_tag": axis_tag or "A",
|
"axis_tag": axis_tag or "A",
|
||||||
"same_sense": same_sense or True,
|
"same_sense": same_sense or True,
|
||||||
"uvw_axes": uvw_axes or "UAxes", # Choose which axes
|
"uvw_axes": uvw_axes or "UAxes", # Choose which axes
|
||||||
"grid": grid,
|
"grid": grid,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self):
|
element = file.create_entity(
|
||||||
element = self.file.create_entity(
|
"IfcGridAxis", **{"AxisTag": settings["axis_tag"], "SameSense": settings["same_sense"]}
|
||||||
"IfcGridAxis", **{"AxisTag": self.settings["axis_tag"], "SameSense": self.settings["same_sense"]}
|
|
||||||
)
|
)
|
||||||
axes = list(getattr(self.settings["grid"], self.settings["uvw_axes"]) or [])
|
axes = list(getattr(settings["grid"], settings["uvw_axes"]) or [])
|
||||||
axes.append(element)
|
axes.append(element)
|
||||||
setattr(self.settings["grid"], self.settings["uvw_axes"], axes)
|
setattr(settings["grid"], settings["uvw_axes"], axes)
|
||||||
return element
|
return element
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def remove_grid_axis(file, axis=None) -> None:
|
||||||
def __init__(self, file, axis=None):
|
|
||||||
"""Removes a grid axis from a grid
|
"""Removes a grid axis from a grid
|
||||||
|
|
||||||
:param axis: The IfcGridAxis you want to remove.
|
:param axis: The IfcGridAxis you want to remove.
|
||||||
@@ -44,11 +43,9 @@ class Usecase:
|
|||||||
# Let's remove it!
|
# Let's remove it!
|
||||||
ifcopenshell.api.run("grid.remove_grid_axis", model, axis=axis_2)
|
ifcopenshell.api.run("grid.remove_grid_axis", model, axis=axis_2)
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {"axis": axis}
|
||||||
self.settings = {"axis": axis}
|
|
||||||
|
|
||||||
def execute(self):
|
if len(file.get_inverse(settings["axis"].AxisCurve)) == 1:
|
||||||
if len(self.file.get_inverse(self.settings["axis"].AxisCurve)) == 1:
|
ifcopenshell.util.element.remove_deep(file, settings["axis"].AxisCurve)
|
||||||
ifcopenshell.util.element.remove_deep(self.file, self.settings["axis"].AxisCurve)
|
file.remove(settings["axis"].AxisCurve)
|
||||||
self.file.remove(self.settings["axis"].AxisCurve)
|
file.remove(settings["axis"])
|
||||||
self.file.remove(self.settings["axis"])
|
|
||||||
|
|||||||
@@ -15,3 +15,10 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .add_group import add_group
|
||||||
|
from .assign_group import assign_group
|
||||||
|
from .edit_group import edit_group
|
||||||
|
from .remove_group import remove_group
|
||||||
|
from .unassign_group import unassign_group
|
||||||
|
from .update_group_products import update_group_products
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ import ifcopenshell
|
|||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
|
||||||
|
|
||||||
class Usecase:
|
def add_group(file, Name="Unnamed", Description=None) -> None:
|
||||||
def __init__(self, file, Name="Unnamed", Description=None):
|
|
||||||
"""Adds a new group
|
"""Adds a new group
|
||||||
|
|
||||||
An IFC group is an arbitrary collection of products, which are typically
|
An IFC group is an arbitrary collection of products, which are typically
|
||||||
@@ -45,19 +44,17 @@ class Usecase:
|
|||||||
|
|
||||||
ifcopenshell.api.run("group.add_group", model, Name="Unit 1A")
|
ifcopenshell.api.run("group.add_group", model, Name="Unit 1A")
|
||||||
"""
|
"""
|
||||||
self.file = file
|
settings = {
|
||||||
self.settings = {
|
|
||||||
"Name": Name or "Unnamed",
|
"Name": Name or "Unnamed",
|
||||||
"Description": Description,
|
"Description": Description,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self):
|
return file.create_entity(
|
||||||
return self.file.create_entity(
|
|
||||||
"IfcGroup",
|
"IfcGroup",
|
||||||
**{
|
**{
|
||||||
"GlobalId": ifcopenshell.guid.new(),
|
"GlobalId": ifcopenshell.guid.new(),
|
||||||
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
|
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", file),
|
||||||
"Name": self.settings["Name"],
|
"Name": settings["Name"],
|
||||||
"Description": self.settings["Description"],
|
"Description": settings["Description"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user