Feat(prop): Added better property extraction (#8)

* Added better property extraction

* property sets naming
This commit is contained in:
Jedd Morgan
2025-07-09 10:06:15 +01:00
committed by GitHub
parent 6a4d3041b5
commit 308e1bb59d
6 changed files with 79 additions and 52 deletions
-2
View File
@@ -16,7 +16,6 @@ from speckleifc.importer import ImportJob
def cmd_line_import() -> None:
parser = ArgumentParser(
prog="speckleifc",
description="imports a file",
@@ -76,7 +75,6 @@ def open_and_convert_file(
model_id: str,
account: Account,
) -> Version:
start = time.time()
very_start = start
@@ -24,6 +24,5 @@ def data_object_to_speckle(
data_object["@elements"] = children
data_object["ifcType"] = step_element.is_a()
data_object["expressId"] = step_element.id()
data_object["description"] = cast(str | None, step_element.Description)
return data_object
@@ -70,15 +70,15 @@ def geometry_to_speckle(
i += 1
face_index += 3 # number of items in the faces list we just jumped over
mapped_index_counters[
mesh_index
] += 3 # number of verts we just added to the mesh.vertices i.e. the next index
mapped_faces_pointers[
mesh_index
] += 4 # number of item's we've just added to the mesh.faces list
mapped_vertices_pointers[
mesh_index
] += 9 # number of item's we've just added to the mesh.vertices list
mapped_index_counters[mesh_index] += (
3 # number of verts we just added to the mesh.vertices i.e. the next index
)
mapped_faces_pointers[mesh_index] += (
4 # number of item's we've just added to the mesh.faces list
)
mapped_vertices_pointers[mesh_index] += (
9 # number of item's we've just added to the mesh.vertices list
)
return mapped_meshes # type: ignore
@@ -13,9 +13,8 @@ def project_to_speckle(
project = Collection(applicationId=guid, name=name, elements=children)
project["expressId"] = step_element.id()
project["ifcType"] = step_element.is_a()
project["description"] = cast(str | None, step_element.Description)
project["description"] = step_element.Description
project["objectType"] = step_element.ObjectType
project["longName"] = step_element.LongName
project["phase"] = step_element.Phase
@@ -20,7 +20,6 @@ def spatial_element_to_speckle(
name = cast(str, step_element.Name or step_element.LongName or guid)
data_object = Collection(applicationId=guid, name=name, elements=all_children)
data_object["expressId"] = step_element.id()
data_object["ifcType"] = step_element.is_a()
return data_object
@@ -38,11 +37,6 @@ def _convert_as_data_object(
displayValue=display_value,
)
data_object["expressId"] = step_element.id()
data_object["ifcType"] = step_element.is_a()
data_object["description"] = cast(str | None, step_element.Description)
data_object["objectType"] = step_element.ObjectType
data_object["compositionType"] = step_element.CompositionType
data_object["longName"] = step_element.LongName
return data_object
+68 -31
View File
@@ -1,50 +1,87 @@
from typing import Any
from ifcopenshell.entity_instance import entity_instance
from ifcopenshell.util.element import get_type
def extract_properties(element: entity_instance) -> dict[str, object]:
properties: dict[str, object] = {
"Attributes": get_attributes(element),
"Property Sets": _get_ifc_object_properties(element),
}
if (ifc_type := get_type(element)) is not None:
properties["Element Type Property Sets"] = _get_ifc_element_type_properties(
ifc_type,
)
return properties
def get_attributes(element: entity_instance) -> dict[str, object]:
return element.get_info(True, False, scalar_only=True)
def _get_ifc_element_type_properties(element: entity_instance) -> dict[str, object]:
result: dict[str, object] = {}
for definition in element.HasPropertySets or []:
if not definition.is_a("IfcPropertySet"):
continue
result[definition.Name] = _get_properties(definition.HasProperties)
return result
def _get_ifc_object_properties(element: entity_instance) -> dict[str, object]:
result: dict[str, object] = {}
for rel in getattr(element, "IsDefinedBy", []):
if not rel.is_a("IfcRelDefinesByProperties"):
continue
prop_set = rel.RelatingPropertyDefinition
if not prop_set.is_a("IfcPropertySet"):
definition: entity_instance = rel.RelatingPropertyDefinition
if not definition.is_a("IfcPropertySet"):
continue
set_name = prop_set.Name
properties: dict[str, Any] = {}
for prop in prop_set.HasProperties:
name = prop.Name
if prop.is_a("IfcPropertySingleValue"):
val = prop.NominalValue
if val is not None:
properties[name] = (
val.wrappedValue if hasattr(val, "wrappedValue") else val
)
elif prop.is_a("IfcPropertyListValue"):
values = getattr(prop, "ListValues", None)
if values:
properties[name] = [
v.wrappedValue if hasattr(v, "wrappedValue") else v
for v in values
]
elif prop.is_a("IfcPropertyEnumeratedValue"):
values = getattr(prop, "EnumerationValues", None)
if values:
properties[name] = [
v.wrappedValue if hasattr(v, "wrappedValue") else v
for v in values
]
# elif prop.is_a("IfcPropertyTableValue"):
# properties[name] = #not sure if we want to support these...
set_name = definition.Name
properties = _get_properties(definition.HasProperties)
if properties:
result[set_name] = properties
return result
def _get_properties(properties: entity_instance) -> dict[str, Any]:
"""
There already exists a canonical way to get properties
`ifcopenshell.util.element.get_properties` but it's very verbose
and we don't want to bloat our selves with supporting complex property types
This is a slimmed down version, only supporting a couple of property types
"""
result: dict[str, Any] = {}
for prop in properties:
name = prop.Name
if prop.is_a("IfcPropertySingleValue"):
val = prop.NominalValue
if val is not None:
result[name] = val.wrappedValue if hasattr(val, "wrappedValue") else val
elif prop.is_a("IfcPropertyListValue"):
values = getattr(prop, "ListValues", None)
if values:
result[name] = [
v.wrappedValue if hasattr(v, "wrappedValue") else v for v in values
]
elif prop.is_a("IfcPropertyEnumeratedValue"):
values = getattr(prop, "EnumerationValues", None)
if values:
result[name] = [
v.wrappedValue if hasattr(v, "wrappedValue") else v for v in values
]
# elif prop.is_a("IfcPropertyTableValue"):
# properties[name] = #not sure if we want to support these...
return result