This commit is contained in:
Andrej730
2025-09-05 10:50:34 +05:00
parent f457a7d831
commit 062bf8e60b
4 changed files with 40 additions and 8 deletions
@@ -73,6 +73,7 @@ class BIM_PT_classifications(Panel):
self.draw_ui(classification) self.draw_ui(classification)
def draw_add_manual_ui(self, context): def draw_add_manual_ui(self, context):
assert self.layout
if self.props.is_adding: if self.props.is_adding:
bonsai.bim.helper.draw_attributes(self.props.classification_attributes, self.layout) bonsai.bim.helper.draw_attributes(self.props.classification_attributes, self.layout)
row = self.layout.row(align=True) row = self.layout.row(align=True)
@@ -83,10 +84,12 @@ class BIM_PT_classifications(Panel):
row.operator("bim.enable_adding_manual_classification", text="Add Classification", icon="ADD") row.operator("bim.enable_adding_manual_classification", text="Add Classification", icon="ADD")
def draw_add_bsdd_ui(self, context): def draw_add_bsdd_ui(self, context):
assert self.layout
row = self.layout.row() row = self.layout.row()
row.operator("bim.add_classification_from_bsdd", icon="ADD") row.operator("bim.add_classification_from_bsdd", icon="ADD")
def draw_add_file_ui(self, context): def draw_add_file_ui(self, context):
assert self.layout
if ClassificationsData.data["has_classification_file"]: if ClassificationsData.data["has_classification_file"]:
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props, "available_classifications", text="") row.prop(self.props, "available_classifications", text="")
@@ -97,13 +100,15 @@ class BIM_PT_classifications(Panel):
row.label(text="No Active Classification Library") row.label(text="No Active Classification Library")
row.operator("bim.load_classification_library", text="", icon="IMPORT") row.operator("bim.load_classification_library", text="", icon="IMPORT")
def draw_editable_ui(self): def draw_editable_ui(self) -> None:
assert self.layout
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.operator("bim.edit_classification", text="Save changes", icon="CHECKMARK") row.operator("bim.edit_classification", text="Save changes", icon="CHECKMARK")
row.operator("bim.disable_editing_classification", text="", icon="CANCEL") row.operator("bim.disable_editing_classification", text="", icon="CANCEL")
bonsai.bim.helper.draw_attributes(self.props.classification_attributes, self.layout) bonsai.bim.helper.draw_attributes(self.props.classification_attributes, self.layout)
def draw_ui(self, classification): def draw_ui(self, classification: dict[str, Any]) -> None:
assert self.layout
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text=classification["Name"], icon="ASSET_MANAGER") row.label(text=classification["Name"], icon="ASSET_MANAGER")
if not self.props.active_classification_id: if not self.props.active_classification_id:
@@ -203,6 +203,7 @@ class AssignClass(bpy.types.Operator, tool.Ifc.Operator):
predefined_type: str predefined_type: str
userdefined_type: str userdefined_type: str
context_id: int context_id: int
props_to_pset: bool
should_add_representation: bool should_add_representation: bool
ifc_representation_class: str ifc_representation_class: str
+30 -4
View File
@@ -18,11 +18,13 @@
from __future__ import annotations from __future__ import annotations
import re import re
import json import json
import numpy as np
import numpy.typing as npt
import ifcopenshell import ifcopenshell
import ifcopenshell.util.attribute import ifcopenshell.util.attribute
import ifcopenshell.util.schema import ifcopenshell.util.schema
from pathlib import Path from pathlib import Path
from typing import Any, NoReturn, Union, Optional, TYPE_CHECKING from typing import Any, NoReturn, Union, Optional, TYPE_CHECKING, TypedDict
from . import ifcopenshell_wrapper from . import ifcopenshell_wrapper
from .file import file from .file import file
from .entity_instance import entity_instance from .entity_instance import entity_instance
@@ -36,6 +38,30 @@ except ImportError as e:
print(f"No SQL support: {e}") print(f"No SQL support: {e}")
class GeometryCache(TypedDict):
shapes: dict[int, GeometryCacheShape]
geometry: dict[str, GeometryCacheGeometry]
class GeometryCacheShape(TypedDict):
co: list[float]
"""Object location."""
matrix: npt.NDArray[np.float64]
geometry: Union[str, None]
"""Element's geometry id (same value as in ``Representation.id``).
Is set to ``None` when no geometry is available for the element.
"""
class GeometryCacheGeometry(TypedDict):
verts: npt.NDArray[np.float64]
edges: npt.NDArray[np.int32]
faces: npt.NDArray[np.int32]
material_ids: npt.NDArray[np.int32]
materials: list[int]
class sqlite(file): class sqlite(file):
mvd_str: str mvd_str: str
"""As in `header.file_description.description`.""" """As in `header.file_description.description`."""
@@ -235,15 +261,15 @@ class sqlite(file):
return True return True
return False return False
def get_geometry(self, ids: list[int]) -> dict[str, dict]: def get_geometry(self, ids: list[int]) -> GeometryCache:
import numpy as np import numpy as np
ids_csv = ",".join(map(str, ids)) ids_csv = ",".join(map(str, ids))
query = f"SELECT ifc_id, x, y, z, matrix, geometry, verts, edges, faces, material_ids, materials FROM shape LEFT JOIN geometry ON shape.geometry = geometry.id WHERE `ifc_id` IN ({ids_csv})" query = f"SELECT ifc_id, x, y, z, matrix, geometry, verts, edges, faces, material_ids, materials FROM shape LEFT JOIN geometry ON shape.geometry = geometry.id WHERE `ifc_id` IN ({ids_csv})"
self.cursor.execute(query) self.cursor.execute(query)
rows = self.cursor.fetchall() rows = self.cursor.fetchall()
shapes = {} shapes: dict[int, GeometryCacheShape] = {}
geometry = {} geometry: dict[str, GeometryCacheGeometry] = {}
for row in rows: for row in rows:
if row["geometry"] and row["geometry"] not in geometry: if row["geometry"] and row["geometry"] not in geometry:
# Same data types as in ifcopenshell.util.shape. # Same data types as in ifcopenshell.util.shape.
+2 -2
View File
@@ -140,7 +140,7 @@ class Patcher(ifcpatch.BasePatcher):
self.should_skip_geometry_data = should_skip_geometry_data self.should_skip_geometry_data = should_skip_geometry_data
geometry_rows: dict[str, tuple[str, bytes, bytes, bytes, bytes, str]] geometry_rows: dict[str, tuple[str, bytes, bytes, bytes, bytes, str]]
shape_rows: dict[int, tuple[int, list[float], list[float], list[float], bytes, str]] shape_rows: dict[int, tuple[int, float, float, float, bytes, Union[str, None]]]
def get_output(self) -> Union[str, None]: def get_output(self) -> Union[str, None]:
"""Return resulting database filepath for sqlite and ``None`` for mysql.""" """Return resulting database filepath for sqlite and ``None`` for mysql."""
@@ -576,7 +576,7 @@ class Patcher(ifcpatch.BasePatcher):
if element.id() not in self.shape_rows and (placement := getattr(element, "ObjectPlacement", None)): if element.id() not in self.shape_rows and (placement := getattr(element, "ObjectPlacement", None)):
m = ifcopenshell.util.placement.get_local_placement(placement) m = ifcopenshell.util.placement.get_local_placement(placement)
x, y, z = m[:, 3][0:3].tolist() x, y, z = m[:, 3][0:3].tolist()
self.shape_rows[element.id()] = [element.id(), x, y, z, m.tobytes(), None] self.shape_rows[element.id()] = (element.id(), x, y, z, m.tobytes(), None)
if self.sql_type == "sqlite": if self.sql_type == "sqlite":
if rows: if rows: