mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 03:14:23 +00:00
cobie24 - implement Coordinate tab #5926
This commit is contained in:
@@ -49,6 +49,7 @@ __version__ = version = "0.0.0"
|
||||
|
||||
|
||||
ParserPreset = Literal["basic", "cobie24", "cobie24legacy"]
|
||||
GetElementDataCallBack = Callable[[ifcopenshell.file, ifcopenshell.entity_instance], dict[str, Any]]
|
||||
_parser_presets_configs = {}
|
||||
|
||||
|
||||
@@ -69,9 +70,7 @@ def get_presets_configs() -> dict[ParserPreset, dict[str, Any]]:
|
||||
class Parser:
|
||||
config: dict[str, Any]
|
||||
categories: defaultdict[str, dict[str, Any]]
|
||||
get_custom_element_data: dict[
|
||||
str, Union[Callable[[ifcopenshell.file, ifcopenshell.entity_instance], dict[str, Any]], dict[str, Any]]
|
||||
]
|
||||
get_custom_element_data: dict[str, Union[GetElementDataCallBack, dict[str, Any]]]
|
||||
duplicate_keys: list[tuple[dict[str, Any], dict[str, Any]]]
|
||||
|
||||
def __init__(self, preset: Union[str, ParserPreset, dict[str, Any]] = "basic"):
|
||||
@@ -93,6 +92,7 @@ class Parser:
|
||||
def parse(self, ifc_file: ifcopenshell.file, name=None):
|
||||
for category_name, category_config in self.config["categories"].items():
|
||||
for element in category_config["get_category_elements"](ifc_file):
|
||||
get_element_data: Union[GetElementDataCallBack, dict[str, Any]]
|
||||
get_element_data = category_config["get_element_data"]
|
||||
|
||||
if isinstance(get_element_data, dict):
|
||||
|
||||
+103
-6
@@ -17,13 +17,16 @@
|
||||
# along with IfcFM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.geom
|
||||
import ifcopenshell.util.classification
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.fm
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.shape
|
||||
import ifcopenshell.util.system
|
||||
from typing import Any, Union, Optional
|
||||
from ifcopenshell.util.shape_builder import np_matrix_to_euler
|
||||
from typing import Any, Union, Optional, Generator
|
||||
|
||||
|
||||
# The original BIMServer plugin has a function called ifcToCOBie:
|
||||
@@ -163,7 +166,7 @@ def get_documents(
|
||||
|
||||
|
||||
def get_attributes(ifc_file: ifcopenshell.file) -> list[dict[str, Any]]:
|
||||
results = []
|
||||
results: list[dict[str, Any]] = []
|
||||
history = get_history(ifc_file)
|
||||
created_by = get_email_from_history(history) if history else None
|
||||
created_on = ifcopenshell.util.date.ifc2datetime(history.CreationDate).isoformat() if history else None
|
||||
@@ -850,12 +853,81 @@ def get_document_data(ifc_file: ifcopenshell.file, element: ifcopenshell.entity_
|
||||
}
|
||||
|
||||
|
||||
def get_attribute_data(
|
||||
ifc_file: ifcopenshell.file, element: ifcopenshell.entity_instance
|
||||
) -> ifcopenshell.entity_instance:
|
||||
def pass_category_elements_as_data(ifc_file: ifcopenshell.file, element: dict[str, Any]) -> dict[str, Any]:
|
||||
return element
|
||||
|
||||
|
||||
def get_coordinate_elements(ifc_file: ifcopenshell.file) -> list[dict[str, Any]]:
|
||||
elements = get_floors(ifc_file) + get_spaces(ifc_file)
|
||||
results: list[dict[str, Any]] = []
|
||||
for element in elements:
|
||||
for data in get_coordinate_data_(element):
|
||||
results.append(data)
|
||||
return results
|
||||
|
||||
|
||||
def get_coordinate_data_(element: ifcopenshell.entity_instance) -> Generator[dict[str, Any], None, None]:
|
||||
M_TRANSLATION = (slice(0, 3), 3)
|
||||
element_name = val(element.Name)
|
||||
element_class = element.is_a()
|
||||
|
||||
base_data = {
|
||||
"CreatedBy": get_created_by(element),
|
||||
"CreatedOn": get_created_on(element),
|
||||
"RowName": element_name,
|
||||
"ExtSystem": "IfcFm",
|
||||
"ExtObject": element_class,
|
||||
"ExtIdentifier": element.GlobalId,
|
||||
}
|
||||
|
||||
if element_class == "IfcBuildingStorey":
|
||||
matrix = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
|
||||
categories = ("points",)
|
||||
rotation = np_matrix_to_euler(matrix)
|
||||
translation = matrix[M_TRANSLATION]
|
||||
# Rotation axes as explained in https://www.nibs.org/nbims/v3/cobie.
|
||||
points_data = {
|
||||
"Name": element_name,
|
||||
"Category": "point",
|
||||
"SheetName": "Floor",
|
||||
"CoordinateXAxis": translation[0],
|
||||
"CoordinateYAxis": translation[1],
|
||||
"CoordinateZAxis": translation[2],
|
||||
"ClockwiseRotation": rotation[2] * 180,
|
||||
"ElevationalRotation": rotation[0] * 180,
|
||||
"YawRotation": rotation[1] * 180,
|
||||
}
|
||||
yield base_data | points_data
|
||||
return
|
||||
|
||||
# IfcSpaces.
|
||||
if element.Representation is None:
|
||||
return
|
||||
|
||||
settings = ifcopenshell.geom.settings()
|
||||
shape: ifcopenshell.geom.ShapeElementType
|
||||
shape = ifcopenshell.geom.create_shape(settings, element)
|
||||
verts = ifcopenshell.util.shape.get_shape_vertices(shape, shape.geometry)
|
||||
categories = ("box-lowerleft", "box-upperright")
|
||||
bbox = ifcopenshell.util.shape.get_bbox(verts)
|
||||
base_data = base_data | {
|
||||
"Category": "point",
|
||||
"SheetName": "Space",
|
||||
# Spaces don't need rotation as box points are already in world space.
|
||||
"ClockwiseRotation": None,
|
||||
"ElevationalRotation": None,
|
||||
"YawRotation": None,
|
||||
}
|
||||
for category, point in zip(categories, bbox):
|
||||
box_point_data = {
|
||||
"Name": element_name + category,
|
||||
"CoordinateXAxis": point[0],
|
||||
"CoordinateYAxis": point[1],
|
||||
"CoordinateZAxis": point[2],
|
||||
}
|
||||
yield base_data | box_point_data
|
||||
|
||||
|
||||
def get_unit_type_name(ifc_file: ifcopenshell.file, unit_type: str) -> Union[str, None]:
|
||||
for unit in ifc_file.by_type("IfcUnitAssignment")[0].Units:
|
||||
if unit.is_a("IfcNamedUnit") and unit.UnitType == unit_type:
|
||||
@@ -936,6 +1008,7 @@ def get_facility_parent(
|
||||
|
||||
|
||||
def val(x: Any) -> Any:
|
||||
"""Replace n/a and empty strings with `None`."""
|
||||
return x if x not in ("", "n/a") else None
|
||||
|
||||
|
||||
@@ -1428,7 +1501,31 @@ config = {
|
||||
"colours": "ririiirreeeoo",
|
||||
"sort": [{"name": "Category", "order": "ASC"}, {"name": "Name", "order": "ASC"}],
|
||||
"get_category_elements": get_attributes,
|
||||
"get_element_data": get_attribute_data,
|
||||
"get_element_data": pass_category_elements_as_data,
|
||||
},
|
||||
"Coordinate": {
|
||||
"keys": ["Name", "SheetName", "RowName"],
|
||||
"headers": (
|
||||
"Name",
|
||||
"CreatedBy",
|
||||
"CreatedOn",
|
||||
"Category",
|
||||
"SheetName",
|
||||
"RowName",
|
||||
"CoordinateXAxis",
|
||||
"CoordinateYAxis",
|
||||
"CoordinateZAxis",
|
||||
"ExtSystem",
|
||||
"ExtObject",
|
||||
"ExtIdentifier",
|
||||
"ClockwiseRotation",
|
||||
"ElevationalRotation",
|
||||
"YawRotation",
|
||||
),
|
||||
"colours": "ririiirrreeerrr",
|
||||
"sort": [{"name": "Category", "order": "ASC"}, {"name": "Name", "order": "ASC"}],
|
||||
"get_category_elements": get_coordinate_elements,
|
||||
"get_element_data": pass_category_elements_as_data,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user