Merge branch 'v0.8.0' into fix-ifccircle-ifcellipse-processing

This commit is contained in:
Thomas Krijnen
2024-09-12 20:18:57 +02:00
committed by GitHub
91 changed files with 3282 additions and 1718 deletions
+2 -2
View File
@@ -52,8 +52,8 @@ ifeq ($(PLATFORM), win64)
PLATFORMTAG:=win_amd64
endif
IOS_URL:=https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-$(PYNUMBER)-v0.7.11-03935a9-$(PLATFORM).zip
IFCCONVERT_URL:=https://s3.amazonaws.com/ifcopenshell-builds/IfcConvert-v0.7.11-03935a9-$(PLATFORM).zip
IOS_URL:=https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-$(PYNUMBER)-v$(VERSION)-f5e02d1-$(PLATFORM).zip
IFCCONVERT_URL:=https://s3.amazonaws.com/ifcopenshell-builds/IfcConvert-v$(VERSION)-f5e02d1-$(PLATFORM).zip
.PHONY: test
test:
@@ -104,12 +104,14 @@ class Usecase:
if self.settings["prop_name"]:
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
for product in self.settings["products"]:
if not product.is_a("IfcElement"):
continue
self.assign_cost_control(related_object=product, cost_item=self.settings["cost_item"])
if self.settings["prop_name"]:
if (
self.settings["cost_item"].CostQuantities
and self.settings["cost_item"].CostQuantities[0].Name.lower() != self.settings["prop_name"].lower()
) or not product.is_a("IfcObject"):
):
continue
self.add_quantity_from_related_object(product)
if self.settings["prop_name"]:
@@ -102,9 +102,10 @@ def calculate_cost_item_resource_value(file: ifcopenshell.file, cost_item: ifcop
for resource in resources:
cost, unit = ifcopenshell.util.resource.get_cost(resource)
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.
# Concept to standardise - Not defined in schema, but this makes manual scheduling of resources 10x faster and less duplicate data.
parent_cost = ifcopenshell.util.resource.get_parent_cost(resource)
assert parent_cost
cost, unit = parent_cost
quantity = ifcopenshell.util.resource.get_quantity(resource)
if not cost or not quantity:
continue
@@ -42,6 +42,6 @@ def copy_profile(file: ifcopenshell.file, profile: ifcopenshell.entity_instance)
inverses = file.get_inverse(profile)
psets = [i for i in inverses if i.is_a("IfcProfileProperties")]
for pset in psets:
new_pset = ifcopenshell.util.element.copy_deep(file, pset, exclude=["IfcProfileDef"])
new_pset = ifcopenshell.util.element.copy(file, pset)
new_pset.ProfileDefinition = new_profile
return new_profile
@@ -167,6 +167,9 @@ def edit_pset(
class Usecase:
file: ifcopenshell.file
settings: dict[str, Any]
def execute(self) -> None:
self.update_pset_name()
self.load_pset_template()
@@ -378,7 +381,7 @@ class Usecase:
properties.append(self.file.create_entity("IfcPropertySingleValue", **args))
return properties
def assign_new_properties(self, props: ifcopenshell.entity_instance) -> None:
def assign_new_properties(self, props: list[ifcopenshell.entity_instance]) -> None:
if hasattr(self.settings["pset"], "HasProperties"):
self.settings["pset"].HasProperties = props
@@ -87,7 +87,8 @@ def unshare_pset(
for product in products:
# No need to consider about profile/material properties since
# they are assigned to 1 element directly and therefore cannot be shared.
pset_copy = ifcopenshell.util.element.copy_deep(file, pset)
# Don't copy_deep to keep it light - edit_pset supports unsharing shared props.
pset_copy = ifcopenshell.util.element.copy(file, pset)
pset_copies.append(pset_copy)
ifcopenshell.api.pset.assign_pset(file, [product], pset_copy)
@@ -445,7 +445,7 @@ def get_elements_by_pset(pset: ifcopenshell.entity_instance) -> set[ifcopenshell
"""Retrieve the elements (or element types) that are using the provided property set."""
is_ifc2x3 = pset.file.schema == "IFC2X3"
elements = set()
if pset.is_a("IfcPropertySet"):
if pset.is_a("IfcPropertySet") or pset.is_a("IfcQuantitySet"):
rels = pset.PropertyDefinitionOf if is_ifc2x3 else pset.DefinesOccurrence
for rel in rels:
elements.update(rel.RelatedObjects)
@@ -166,9 +166,9 @@ def get_quantity(resource: ifcopenshell.entity_instance) -> float:
return duration.total_seconds() / 3600
def get_parent_cost(resource: ifcopenshell.entity_instance) -> Union[None, tuple[float, Union[str, None]]]:
if not resource.Nests:
def get_parent_cost(resource: ifcopenshell.entity_instance) -> Union[tuple[float, Union[str, None]], None]:
if not (nests := resource.Nests):
return
else:
cost = get_cost(resource.Nests[0].RelatingObject)
cost = get_cost(nests[0].RelatingObject)
return cost
@@ -36,7 +36,18 @@ RECURRENCE_TYPE = Literal[
]
def derive_date(task, attribute_name, date=None, is_earliest=False, is_latest=False):
def derive_date(
task: ifcopenshell.entity_instance,
attribute_name: str,
date=None,
is_earliest: bool = False,
is_latest: bool = False,
):
"""
:param task: IfcTask.
"""
if task.TaskTime:
current_date = (
ifcopenshell.util.date.ifc2datetime(getattr(task.TaskTime, attribute_name))
@@ -268,7 +279,7 @@ def get_task_work_schedule(task: ifcopenshell.entity_instance) -> Union[ifcopens
def get_nested_tasks(task: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
return [object for rel in task.IsNestedBy or [] for object in rel.RelatedObjects]
return [object for rel in task.IsNestedBy or [] for object in rel.RelatedObjects if object.is_a("IfcTask")]
def get_parent_task(task: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
@@ -448,12 +459,9 @@ def get_related_products(
"""Gets the related products being output by a task
:param relating_product: One of the products already output by the task.
:type relating_product: ifcopenshell.entity_instance, optional
:param related_object: The IfcTask that you want to get all the related
products for.
:type related_object: ifcopenshell.entity_instance, optional
:return: A set of IfcProducts output by the IfcTask.
:rtype: set[ifcopenshell.entity_instance]
Example:
@@ -478,17 +486,18 @@ def get_related_products(
products = ifcopenshell.util.sequence.get_related_products(related_object=task)
"""
assert relating_product or related_object, "Either relating_product or related_object must be provided."
products = set()
related_object = None
if related_object:
related_object = related_object
elif relating_product:
if not related_object and relating_product:
for reference in relating_product.ReferencedBy:
if reference.is_a("IfcRelAssignsToProduct"):
related_object = reference.RelatedObjects[0]
if related_object:
assignments = related_object.HasAssignments
for assignment in assignments:
if assignment.is_a("IfcRelAssignsToProduct"):
products.add(assignment.RelatingProduct.id())
return products
@@ -368,6 +368,7 @@ class ShapeBuilder:
"ProfileType": profile_type,
"OuterCurve": outer_curve,
}
if self.file.schema == "IFC2X3":
kwargs["Position"] = self.create_axis2_placement_2d()