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:
|
def cmd_line_import() -> None:
|
||||||
|
|
||||||
parser = ArgumentParser(
|
parser = ArgumentParser(
|
||||||
prog="speckleifc",
|
prog="speckleifc",
|
||||||
description="imports a file",
|
description="imports a file",
|
||||||
@@ -76,7 +75,6 @@ def open_and_convert_file(
|
|||||||
model_id: str,
|
model_id: str,
|
||||||
account: Account,
|
account: Account,
|
||||||
) -> Version:
|
) -> Version:
|
||||||
|
|
||||||
start = time.time()
|
start = time.time()
|
||||||
very_start = start
|
very_start = start
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,5 @@ def data_object_to_speckle(
|
|||||||
|
|
||||||
data_object["@elements"] = children
|
data_object["@elements"] = children
|
||||||
data_object["ifcType"] = step_element.is_a()
|
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
|
return data_object
|
||||||
|
|||||||
@@ -70,15 +70,15 @@ def geometry_to_speckle(
|
|||||||
i += 1
|
i += 1
|
||||||
face_index += 3 # number of items in the faces list we just jumped over
|
face_index += 3 # number of items in the faces list we just jumped over
|
||||||
|
|
||||||
mapped_index_counters[
|
mapped_index_counters[mesh_index] += (
|
||||||
mesh_index
|
3 # number of verts we just added to the mesh.vertices i.e. the next index
|
||||||
] += 3 # number of verts we just added to the mesh.vertices i.e. the next index
|
)
|
||||||
mapped_faces_pointers[
|
mapped_faces_pointers[mesh_index] += (
|
||||||
mesh_index
|
4 # number of item's we've just added to the mesh.faces list
|
||||||
] += 4 # number of item's we've just added to the mesh.faces list
|
)
|
||||||
mapped_vertices_pointers[
|
mapped_vertices_pointers[mesh_index] += (
|
||||||
mesh_index
|
9 # number of item's we've just added to the mesh.vertices list
|
||||||
] += 9 # number of item's we've just added to the mesh.vertices list
|
)
|
||||||
|
|
||||||
return mapped_meshes # type: ignore
|
return mapped_meshes # type: ignore
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,8 @@ def project_to_speckle(
|
|||||||
|
|
||||||
project = Collection(applicationId=guid, name=name, elements=children)
|
project = Collection(applicationId=guid, name=name, elements=children)
|
||||||
|
|
||||||
project["expressId"] = step_element.id()
|
|
||||||
project["ifcType"] = step_element.is_a()
|
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["objectType"] = step_element.ObjectType
|
||||||
project["longName"] = step_element.LongName
|
project["longName"] = step_element.LongName
|
||||||
project["phase"] = step_element.Phase
|
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)
|
name = cast(str, step_element.Name or step_element.LongName or guid)
|
||||||
|
|
||||||
data_object = Collection(applicationId=guid, name=name, elements=all_children)
|
data_object = Collection(applicationId=guid, name=name, elements=all_children)
|
||||||
data_object["expressId"] = step_element.id()
|
|
||||||
data_object["ifcType"] = step_element.is_a()
|
data_object["ifcType"] = step_element.is_a()
|
||||||
|
|
||||||
return data_object
|
return data_object
|
||||||
@@ -38,11 +37,6 @@ def _convert_as_data_object(
|
|||||||
displayValue=display_value,
|
displayValue=display_value,
|
||||||
)
|
)
|
||||||
|
|
||||||
data_object["expressId"] = step_element.id()
|
|
||||||
data_object["ifcType"] = step_element.is_a()
|
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
|
return data_object
|
||||||
|
|||||||
@@ -1,50 +1,87 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from ifcopenshell.entity_instance import entity_instance
|
from ifcopenshell.entity_instance import entity_instance
|
||||||
|
from ifcopenshell.util.element import get_type
|
||||||
|
|
||||||
|
|
||||||
def extract_properties(element: entity_instance) -> dict[str, object]:
|
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] = {}
|
result: dict[str, object] = {}
|
||||||
|
|
||||||
for rel in getattr(element, "IsDefinedBy", []):
|
for rel in getattr(element, "IsDefinedBy", []):
|
||||||
if not rel.is_a("IfcRelDefinesByProperties"):
|
if not rel.is_a("IfcRelDefinesByProperties"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
prop_set = rel.RelatingPropertyDefinition
|
definition: entity_instance = rel.RelatingPropertyDefinition
|
||||||
if not prop_set.is_a("IfcPropertySet"):
|
|
||||||
|
if not definition.is_a("IfcPropertySet"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
set_name = prop_set.Name
|
set_name = definition.Name
|
||||||
properties: dict[str, Any] = {}
|
properties = _get_properties(definition.HasProperties)
|
||||||
|
|
||||||
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...
|
|
||||||
|
|
||||||
if properties:
|
if properties:
|
||||||
result[set_name] = properties
|
result[set_name] = properties
|
||||||
|
|
||||||
return result
|
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