Feat(prop): Added better property extraction (#8)
* Added better property extraction * property sets naming
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user