mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 14:41:25 +00:00
typing
This commit is contained in:
@@ -198,11 +198,16 @@ class MaterialCreator:
|
|||||||
|
|
||||||
|
|
||||||
class IfcImporter:
|
class IfcImporter:
|
||||||
|
file: ifcopenshell.file
|
||||||
|
"""Either provided by user as an attribute or will be loaded from ``input_file`` during ``execute()``."""
|
||||||
|
|
||||||
|
elements: set[ifcopenshell.entity_instance]
|
||||||
|
"""Set of IfcElements to import. Excluding ``gross_elements`` and ```native_elements``."""
|
||||||
|
|
||||||
def __init__(self, ifc_import_settings: IfcImportSettings):
|
def __init__(self, ifc_import_settings: IfcImportSettings):
|
||||||
self.ifc_import_settings = ifc_import_settings
|
self.ifc_import_settings = ifc_import_settings
|
||||||
tool.Loader.set_settings(ifc_import_settings)
|
tool.Loader.set_settings(ifc_import_settings)
|
||||||
self.diff = None
|
self.diff = None
|
||||||
self.file: ifcopenshell.file = None
|
|
||||||
self.project = None
|
self.project = None
|
||||||
self.has_existing_project = False
|
self.has_existing_project = False
|
||||||
# element guids to blender collections mapping
|
# element guids to blender collections mapping
|
||||||
@@ -300,6 +305,7 @@ class IfcImporter:
|
|||||||
bpy.context.window_manager.progress_end()
|
bpy.context.window_manager.progress_end()
|
||||||
|
|
||||||
def process_context_filter(self) -> None:
|
def process_context_filter(self) -> None:
|
||||||
|
"""Setup contexts. Necessary for importing elements representations."""
|
||||||
contexts = self.file.by_type("IfcGeometricRepresentationContext")
|
contexts = self.file.by_type("IfcGeometricRepresentationContext")
|
||||||
if len(contexts) > 100: # Probably something strange happening. Encountered from Revizto.
|
if len(contexts) > 100: # Probably something strange happening. Encountered from Revizto.
|
||||||
print("Warning! Excessive contexts were found and merged where applicable.")
|
print("Warning! Excessive contexts were found and merged where applicable.")
|
||||||
@@ -384,6 +390,7 @@ class IfcImporter:
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
def parse_native_elements(self) -> None:
|
def parse_native_elements(self) -> None:
|
||||||
|
# TODO: move to `process_element_filter` to incapsulate all `self.elements` logic.
|
||||||
if not self.ifc_import_settings.should_load_geometry:
|
if not self.ifc_import_settings.should_load_geometry:
|
||||||
return
|
return
|
||||||
if not self.file.by_type("IfcSweptDiskSolid"):
|
if not self.file.by_type("IfcSweptDiskSolid"):
|
||||||
@@ -1129,7 +1136,7 @@ class IfcImporter:
|
|||||||
bpy.ops.view3d.view_selected()
|
bpy.ops.view3d.view_selected()
|
||||||
bpy.ops.object.select_all(action="DESELECT")
|
bpy.ops.object.select_all(action="DESELECT")
|
||||||
|
|
||||||
def setup_arrays(self):
|
def setup_arrays(self, elements: Optional[set[ifcopenshell.entity_instance]] = None):
|
||||||
for pset in self.file.by_type("IfcPropertySet"):
|
for pset in self.file.by_type("IfcPropertySet"):
|
||||||
if pset.Name != "BBIM_Array":
|
if pset.Name != "BBIM_Array":
|
||||||
continue
|
continue
|
||||||
@@ -1144,9 +1151,10 @@ class IfcImporter:
|
|||||||
|
|
||||||
|
|
||||||
class IfcImportSettings:
|
class IfcImportSettings:
|
||||||
|
input_file: Union[str, None] = None
|
||||||
|
logger: Union[logging.Logger, None] = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.logger: logging.Logger = None
|
|
||||||
self.input_file = None
|
|
||||||
self.diff_file = None
|
self.diff_file = None
|
||||||
self.geometry_library = "opencascade"
|
self.geometry_library = "opencascade"
|
||||||
self.should_use_cpu_multiprocessing = True
|
self.should_use_cpu_multiprocessing = True
|
||||||
@@ -1177,7 +1185,9 @@ class IfcImportSettings:
|
|||||||
self.load_indexed_maps = False
|
self.load_indexed_maps = False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def factory(context=None, input_file=None, logger=None):
|
def factory(
|
||||||
|
context=None, input_file: Optional[str] = None, logger: Optional[logging.Logger] = None
|
||||||
|
) -> IfcImportSettings:
|
||||||
scene_diff = tool.Blender.get_diff_props()
|
scene_diff = tool.Blender.get_diff_props()
|
||||||
props = tool.Project.get_project_props()
|
props = tool.Project.get_project_props()
|
||||||
settings = IfcImportSettings()
|
settings = IfcImportSettings()
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ from bpy_extras.image_utils import load_image
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from bonsai.bim.module.project.prop import Link
|
from bonsai.bim.module.project.prop import Link
|
||||||
|
from bpy._typing import rna_enums
|
||||||
|
|
||||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
@@ -223,6 +224,7 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
drawing_name: str
|
drawing_name: str
|
||||||
|
is_manifold_cache: dict[str, bool]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
@@ -1225,7 +1227,7 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
)
|
)
|
||||||
return classes
|
return classes
|
||||||
|
|
||||||
def is_manifold(self, obj):
|
def is_manifold(self, obj) -> bool:
|
||||||
result = self.is_manifold_cache.get(obj.data.name, None)
|
result = self.is_manifold_cache.get(obj.data.name, None)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
@@ -2127,14 +2129,14 @@ class ActivateModel(bpy.types.Operator):
|
|||||||
|
|
||||||
|
|
||||||
class ActivateDrawingBase:
|
class ActivateDrawingBase:
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event) -> set["rna_enums.OperatorReturnItems"]:
|
||||||
if event.type == "LEFTMOUSE" and event.alt:
|
if event.type == "LEFTMOUSE" and event.alt:
|
||||||
self.should_view_from_camera = False
|
self.should_view_from_camera = False
|
||||||
if event.type == "LEFTMOUSE" and event.shift:
|
if event.type == "LEFTMOUSE" and event.shift:
|
||||||
self.use_quick_preview = True
|
self.use_quick_preview = True
|
||||||
return self.execute(context)
|
return self.execute(context)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context) -> set["rna_enums.OperatorReturnItems"]:
|
||||||
props = tool.Drawing.get_document_props()
|
props = tool.Drawing.get_document_props()
|
||||||
if props.is_editing_drawings == False:
|
if props.is_editing_drawings == False:
|
||||||
bpy.ops.bim.load_drawings()
|
bpy.ops.bim.load_drawings()
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import bpy
|
|||||||
import json
|
import json
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
import ifcopenshell.api.pset
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
@@ -33,8 +34,9 @@ class AddArray(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
obj = context.active_object
|
assert (obj := context.active_object)
|
||||||
element = tool.Ifc.get_entity(obj)
|
assert (element := tool.Ifc.get_entity(obj))
|
||||||
|
ifc_file = tool.Ifc.get()
|
||||||
|
|
||||||
array = {
|
array = {
|
||||||
"children": [],
|
"children": [],
|
||||||
@@ -54,14 +56,13 @@ class AddArray(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
data.append(array)
|
data.append(array)
|
||||||
pset = tool.Ifc.get().by_id(pset["id"])
|
pset = tool.Ifc.get().by_id(pset["id"])
|
||||||
else:
|
else:
|
||||||
pset = ifcopenshell.api.run("pset.add_pset", tool.Ifc.get(), product=element, name="BBIM_Array")
|
pset = ifcopenshell.api.pset.add_pset(ifc_file, product=element, name="BBIM_Array")
|
||||||
data = [array]
|
data = [array]
|
||||||
|
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.pset.edit_pset(
|
||||||
"pset.edit_pset",
|
ifc_file,
|
||||||
tool.Ifc.get(),
|
|
||||||
pset=pset,
|
pset=pset,
|
||||||
properties={"Parent": element.GlobalId, "Data": tool.Ifc.get().createIfcText(json.dumps(data))},
|
properties={"Parent": element.GlobalId, "Data": ifc_file.create_entity("IfcText", json.dumps(data))},
|
||||||
)
|
)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|||||||
@@ -18,14 +18,17 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
import ifcopenshell.api.grid
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
import bonsai.core.root
|
import bonsai.core.root
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy.props import FloatProperty, IntProperty
|
from bpy.props import FloatProperty, IntProperty
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
|
||||||
def add_object(self, context):
|
def add_object(self: "BIM_OT_add_object", context: bpy.types.Context) -> None:
|
||||||
|
ifc_file = tool.Ifc.get()
|
||||||
obj = bpy.data.objects.new("Grid", None)
|
obj = bpy.data.objects.new("Grid", None)
|
||||||
obj.name = "Grid"
|
obj.name = "Grid"
|
||||||
|
|
||||||
@@ -33,6 +36,7 @@ def add_object(self, context):
|
|||||||
tool.Ifc, tool.Collector, tool.Root, obj=obj, ifc_class="IfcGrid", should_add_representation=False
|
tool.Ifc, tool.Collector, tool.Root, obj=obj, ifc_class="IfcGrid", should_add_representation=False
|
||||||
)
|
)
|
||||||
grid = tool.Ifc.get_entity(obj)
|
grid = tool.Ifc.get_entity(obj)
|
||||||
|
assert grid
|
||||||
|
|
||||||
for i in range(0, self.total_u):
|
for i in range(0, self.total_u):
|
||||||
verts = [
|
verts = [
|
||||||
@@ -46,9 +50,7 @@ def add_object(self, context):
|
|||||||
tag = chr(ord("A") + i)
|
tag = chr(ord("A") + i)
|
||||||
obj = bpy.data.objects.new(f"IfcGridAxis/{tag}", mesh)
|
obj = bpy.data.objects.new(f"IfcGridAxis/{tag}", mesh)
|
||||||
|
|
||||||
result = ifcopenshell.api.run(
|
result = ifcopenshell.api.grid.create_grid_axis(ifc_file, axis_tag=tag, uvw_axes="UAxes", grid=grid)
|
||||||
"grid.create_grid_axis", tool.Ifc.get(), axis_tag=tag, uvw_axes="UAxes", grid=grid
|
|
||||||
)
|
|
||||||
tool.Ifc.link(result, obj)
|
tool.Ifc.link(result, obj)
|
||||||
tool.Model.create_axis_curve(obj, result)
|
tool.Model.create_axis_curve(obj, result)
|
||||||
tool.Collector.assign(obj)
|
tool.Collector.assign(obj)
|
||||||
@@ -65,9 +67,7 @@ def add_object(self, context):
|
|||||||
tag = str(i + 1).zfill(2)
|
tag = str(i + 1).zfill(2)
|
||||||
obj = bpy.data.objects.new(f"IfcGridAxis/{tag}", mesh)
|
obj = bpy.data.objects.new(f"IfcGridAxis/{tag}", mesh)
|
||||||
|
|
||||||
result = ifcopenshell.api.run(
|
result = ifcopenshell.api.grid.create_grid_axis(ifc_file, axis_tag=tag, uvw_axes="VAxes", grid=grid)
|
||||||
"grid.create_grid_axis", tool.Ifc.get(), axis_tag=tag, uvw_axes="VAxes", grid=grid
|
|
||||||
)
|
|
||||||
tool.Ifc.link(result, obj)
|
tool.Ifc.link(result, obj)
|
||||||
tool.Model.create_axis_curve(obj, result)
|
tool.Model.create_axis_curve(obj, result)
|
||||||
tool.Collector.assign(obj)
|
tool.Collector.assign(obj)
|
||||||
@@ -78,6 +78,7 @@ def add_object(self, context):
|
|||||||
class BIM_OT_add_object(Operator, tool.Ifc.Operator):
|
class BIM_OT_add_object(Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "mesh.add_grid"
|
bl_idname = "mesh.add_grid"
|
||||||
bl_label = "Grid"
|
bl_label = "Grid"
|
||||||
|
bl_description = "Add IfcGrid."
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
u_spacing: FloatProperty(name="U Spacing", default=10)
|
u_spacing: FloatProperty(name="U Spacing", default=10)
|
||||||
@@ -85,6 +86,12 @@ class BIM_OT_add_object(Operator, tool.Ifc.Operator):
|
|||||||
v_spacing: FloatProperty(name="V Spacing", default=10)
|
v_spacing: FloatProperty(name="V Spacing", default=10)
|
||||||
total_v: IntProperty(name="Number of V Grids", default=3)
|
total_v: IntProperty(name="Number of V Grids", default=3)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
u_spacing: float
|
||||||
|
total_u: int
|
||||||
|
v_spacing: float
|
||||||
|
total_v: int
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return tool.Ifc.get() and context.mode == "OBJECT"
|
return tool.Ifc.get() and context.mode == "OBJECT"
|
||||||
|
|||||||
@@ -2123,6 +2123,7 @@ class Model(bonsai.core.tool.Model):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def create_axis_curve(cls, obj: bpy.types.Object, grid_axis: ifcopenshell.entity_instance) -> None:
|
def create_axis_curve(cls, obj: bpy.types.Object, grid_axis: ifcopenshell.entity_instance) -> None:
|
||||||
m = tool.Surveyor.get_absolute_matrix(obj)
|
m = tool.Surveyor.get_absolute_matrix(obj)
|
||||||
|
assert isinstance(obj.data, bpy.types.Mesh)
|
||||||
points = [m @ np.array(v.co.to_4d()) for v in obj.data.vertices[0:2]]
|
points = [m @ np.array(v.co.to_4d()) for v in obj.data.vertices[0:2]]
|
||||||
ifcopenshell.api.grid.create_axis_curve(
|
ifcopenshell.api.grid.create_axis_curve(
|
||||||
tool.Ifc.get(), p1=points[0], p2=points[1], is_si=True, grid_axis=grid_axis
|
tool.Ifc.get(), p1=points[0], p2=points[1], is_si=True, grid_axis=grid_axis
|
||||||
|
|||||||
@@ -69,10 +69,10 @@ def create_axis_curve(
|
|||||||
|
|
||||||
grid = [i for i in file.get_inverse(grid_axis) if i.is_a("IfcGrid")][0]
|
grid = [i for i in file.get_inverse(grid_axis) if i.is_a("IfcGrid")][0]
|
||||||
grid_matrix_i = np.linalg.inv(ifcopenshell.util.placement.get_local_placement(grid.ObjectPlacement))
|
grid_matrix_i = np.linalg.inv(ifcopenshell.util.placement.get_local_placement(grid.ObjectPlacement))
|
||||||
grid_axis.AxisCurve = file.createIfcPolyline(
|
grid_axis.AxisCurve = file.create_entity(
|
||||||
(
|
"IfcPolyline"(
|
||||||
file.createIfcCartesianPoint(ifc_safe_vector_type(grid_matrix_i @ p1)),
|
file.create_entity("IfcCartesianPoint", ifc_safe_vector_type(grid_matrix_i @ p1)),
|
||||||
file.createIfcCartesianPoint(ifc_safe_vector_type(grid_matrix_i @ p2)),
|
file.create_entity("IfcCartesianPoint", ifc_safe_vector_type(grid_matrix_i @ p2)),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -50,20 +50,15 @@ def create_grid_axis(
|
|||||||
:param axis_tag: The name of the axis, that would typically be labeled
|
:param axis_tag: The name of the axis, that would typically be labeled
|
||||||
on drawings or described on site during coordination, such as A, B,
|
on drawings or described on site during coordination, such as A, B,
|
||||||
C, 1, 2, 3, etc. Defaults to "A".
|
C, 1, 2, 3, etc. Defaults to "A".
|
||||||
:type axis_tag: str, optional
|
|
||||||
:param same_sense: Determines whether the direction of the axis's line
|
:param same_sense: Determines whether the direction of the axis's line
|
||||||
is reversed. True means the direction the geometry is defined in
|
is reversed. True means the direction the geometry is defined in
|
||||||
represents the direction of the axis. False means the direction is
|
represents the direction of the axis. False means the direction is
|
||||||
reversed. Leave as True if unsure. Defaults to "True".
|
reversed. Leave as True if unsure. Defaults to "True".
|
||||||
:type same_sense: bool, optional
|
|
||||||
:param uvw_axes: Choose from "UAxes", "VAxes" or "WAxes" depending on
|
:param uvw_axes: Choose from "UAxes", "VAxes" or "WAxes" depending on
|
||||||
which set of axes the new axis you are adding should belong to.
|
which set of axes the new axis you are adding should belong to.
|
||||||
Defaults to "UAxes".
|
Defaults to "UAxes".
|
||||||
:type uvw_axes: str, optional
|
|
||||||
:param grid: The IfcGrid you are adding the axis to.
|
:param grid: The IfcGrid you are adding the axis to.
|
||||||
:type grid: ifcopenshell.entity_instance
|
|
||||||
:return: The newly created IfcGridAxis
|
:return: The newly created IfcGridAxis
|
||||||
:rtype: ifcopenshell.entity_instance
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user