mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 06:21:40 +00:00
Add new covering tool. Mock up and initial functions
This commit is contained in:
@@ -78,6 +78,7 @@ modules = {
|
|||||||
"augin": None,
|
"augin": None,
|
||||||
"debug": None,
|
"debug": None,
|
||||||
"ifcgit": None,
|
"ifcgit": None,
|
||||||
|
"covering": None,
|
||||||
# Uncomment this line to enable loading of the demo module. Happy hacking!
|
# Uncomment this line to enable loading of the demo module. Happy hacking!
|
||||||
# The name "demo" must correlate to a folder name in `bim/module/`.
|
# The name "demo" must correlate to a folder name in `bim/module/`.
|
||||||
# "demo": None,
|
# "demo": None,
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
|
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of BlenderBIM Add-on.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
from . import prop, workspace
|
||||||
|
|
||||||
|
classes = (
|
||||||
|
prop.BIMCoveringProperties,
|
||||||
|
workspace.Hotkey,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def register():
|
||||||
|
if not bpy.app.background:
|
||||||
|
bpy.utils.register_tool(workspace.CoveringTool, after={"bim.structural_tool"}, separator=False, group=False)
|
||||||
|
bpy.types.Scene.BIMCoveringProperties = bpy.props.PointerProperty(type=prop.BIMCoveringProperties)
|
||||||
|
# bpy.types.Object.BIMObjectSpatialProperties = bpy.props.PointerProperty(type=prop.BIMObjectSpatialProperties)
|
||||||
|
# bpy.types.Scene.BIMSpatialManagerProperties = bpy.props.PointerProperty(type=prop.BIMSpatialManagerProperties)
|
||||||
|
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
if not bpy.app.background:
|
||||||
|
bpy.utils.unregister_tool(workspace.CoveringTool)
|
||||||
|
del bpy.types.Scene.BIMCoveringProperties
|
||||||
|
# del bpy.types.Object.BIMObjectSpatialProperties
|
||||||
|
# del bpy.types.Scene.BIMSpatialManagerProperties
|
||||||
Binary file not shown.
@@ -0,0 +1,40 @@
|
|||||||
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
|
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of BlenderBIM Add-on.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
from blenderbim.bim.prop import StrProperty, Attribute
|
||||||
|
#from blenderbim.bim.module.spatial.data import SpatialData
|
||||||
|
from bpy.types import PropertyGroup
|
||||||
|
from bpy.props import (
|
||||||
|
PointerProperty,
|
||||||
|
StringProperty,
|
||||||
|
EnumProperty,
|
||||||
|
BoolProperty,
|
||||||
|
IntProperty,
|
||||||
|
FloatProperty,
|
||||||
|
FloatVectorProperty,
|
||||||
|
CollectionProperty,
|
||||||
|
)
|
||||||
|
import blenderbim.tool as tool
|
||||||
|
import blenderbim.core.geometry
|
||||||
|
import ifcopenshell
|
||||||
|
|
||||||
|
|
||||||
|
class BIMCoveringProperties(PropertyGroup):
|
||||||
|
pass
|
||||||
|
# depth: bpy.props.FloatProperty(name="Depth", default=0.1, subtype="DISTANCE", description="Flooring depth")
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
|
# Copyright (C) 2023 @Andrej730
|
||||||
|
#
|
||||||
|
# This file is part of BlenderBIM Add-on.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
import bpy
|
||||||
|
import blenderbim.tool as tool
|
||||||
|
from blenderbim.bim.helper import prop_with_search
|
||||||
|
from blenderbim.bim.module.model.data import AuthoringData
|
||||||
|
from bpy.types import WorkSpaceTool
|
||||||
|
from blenderbim.bim.ifc import IfcStore
|
||||||
|
import blenderbim.bim.handler
|
||||||
|
|
||||||
|
|
||||||
|
# declaring it here to avoid circular import problems
|
||||||
|
class Operator:
|
||||||
|
def execute(self, context):
|
||||||
|
IfcStore.execute_ifc_operator(self, context)
|
||||||
|
blenderbim.bim.handler.refresh_ui_data()
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
class CoveringTool(WorkSpaceTool):
|
||||||
|
bl_space_type = "VIEW_3D"
|
||||||
|
bl_context_mode = "OBJECT"
|
||||||
|
bl_idname = "bim.covering_tool"
|
||||||
|
bl_label = "Covering Tool"
|
||||||
|
bl_description = "Create and edit coverings"
|
||||||
|
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.covering")
|
||||||
|
bl_widget = None
|
||||||
|
bl_keymap = tool.Blender.get_default_selection_keypmap() + (
|
||||||
|
("bim.covering_hotkey", {"type": "A", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_A")]}),
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_settings(cls, context, layout, ws_tool):
|
||||||
|
CoveringToolUI.draw(context, layout, ifc_element_type="IfcCoveringType")
|
||||||
|
|
||||||
|
def add_layout_hotkey(layout, text, hotkey, description):
|
||||||
|
args = ["covering", layout, text, hotkey, description]
|
||||||
|
tool.Blender.add_layout_hotkey_operator(*args)
|
||||||
|
|
||||||
|
class CoveringToolUI:
|
||||||
|
@classmethod
|
||||||
|
def draw(cls, context, layout, ifc_element_type = None):
|
||||||
|
cls.layout = layout
|
||||||
|
cls.props = context.scene.BIMModelProperties
|
||||||
|
cls.covering_props = context.scene.BIMCoveringProperties
|
||||||
|
|
||||||
|
row = cls.layout.row(align=True)
|
||||||
|
if not tool.Ifc.get():
|
||||||
|
row.label(text="No IFC Project", icon="ERROR")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not AuthoringData.is_loaded:
|
||||||
|
AuthoringData.load(ifc_element_type)
|
||||||
|
elif AuthoringData.data["ifc_element_type"] != ifc_element_type:
|
||||||
|
AuthoringData.load(ifc_element_type)
|
||||||
|
|
||||||
|
|
||||||
|
if context.region.type == "TOOL_HEADER":
|
||||||
|
cls.draw_header_interface()
|
||||||
|
elif context.region.type in ("UI", "WINDOW"):
|
||||||
|
cls.draw_basic_bim_tool_interface()
|
||||||
|
|
||||||
|
cls.draw_default_interface()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_header_interface(cls):
|
||||||
|
cls.draw_type_selection_interface()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_default_interface(cls):
|
||||||
|
if AuthoringData.data["ifc_classes"]:
|
||||||
|
row = cls.layout.row(align=True)
|
||||||
|
row.label(text="", icon="EVENT_SHIFT")
|
||||||
|
row.label(text="", icon="EVENT_A")
|
||||||
|
active_obj = bpy.context.active_object
|
||||||
|
element = tool.Ifc.get_entity(active_obj)
|
||||||
|
if element and bpy.context.selected_objects and element.is_a("IfcWall"):
|
||||||
|
op = row.operator("bim.add_instance_flooring_coverings_from_walls")
|
||||||
|
else:
|
||||||
|
op = row.operator("bim.add_constr_type_instance", text="Add")
|
||||||
|
op.from_invoke = True
|
||||||
|
if cls.props.relating_type_id.isnumeric():
|
||||||
|
op.relating_type_id = int(cls.props.relating_type_id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_type_selection_interface(cls):
|
||||||
|
# shared by both sidebar and header
|
||||||
|
row = cls.layout.row(align=True)
|
||||||
|
if AuthoringData.data["ifc_classes"]:
|
||||||
|
row = cls.layout.row(align=True)
|
||||||
|
row.label(text="", icon="FILE_3D")
|
||||||
|
prop_with_search(row, cls.props, "relating_type_id", text="")
|
||||||
|
row.operator("bim.launch_type_manager", icon="LIGHTPROBE_GRID", text="")
|
||||||
|
else:
|
||||||
|
row.label(text=f"No {AuthoringData.data['ifc_element_type']} Found", icon="ERROR")
|
||||||
|
row = cls.layout.row()
|
||||||
|
row.operator("bim.launch_type_manager", icon="LIGHTPROBE_GRID", text="Launch Type Manager")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_basic_bim_tool_interface(cls):
|
||||||
|
cls.draw_type_selection_interface()
|
||||||
|
|
||||||
|
if AuthoringData.data["ifc_classes"]:
|
||||||
|
if cls.props.ifc_class:
|
||||||
|
box = cls.layout.box()
|
||||||
|
if AuthoringData.data["type_thumbnail"]:
|
||||||
|
box.template_icon(icon_value=AuthoringData.data["type_thumbnail"], scale=5)
|
||||||
|
else:
|
||||||
|
op = box.operator("bim.load_type_thumbnails", text="Load Thumbnails", icon="FILE_REFRESH")
|
||||||
|
op.ifc_class = cls.props.ifc_class
|
||||||
|
|
||||||
|
|
||||||
|
class Hotkey(bpy.types.Operator, Operator):
|
||||||
|
bl_idname = "bim.covering_hotkey"
|
||||||
|
bl_label = "Hotkey"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
hotkey: bpy.props.StringProperty()
|
||||||
|
description: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return tool.Ifc.get()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def description(cls, context, operator):
|
||||||
|
return operator.description or ""
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
# self.props = context.scene.BIMCoveringProperties
|
||||||
|
getattr(self, f"hotkey_{self.hotkey}")()
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
# https://blender.stackexchange.com/questions/276035/how-do-i-make-operators-remember-their-property-values-when-called-from-a-hotkey
|
||||||
|
# self.props = context.scene.BIMSpatialProperties
|
||||||
|
return self.execute(context)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def hotkey_S_A(self):
|
||||||
|
active_obj = bpy.context.active_object
|
||||||
|
element = tool.Ifc.get_entity(active_obj)
|
||||||
|
if element and bpy.context.selected_objects and element.is_a("IfcWall"):
|
||||||
|
bpy.ops.bim.add_instance_flooring_coverings_from_walls()
|
||||||
|
else:
|
||||||
|
bpy.ops.bim.add_constr_type_instance()
|
||||||
|
|
||||||
@@ -28,6 +28,7 @@ from . import (
|
|||||||
roof,
|
roof,
|
||||||
slab,
|
slab,
|
||||||
space,
|
space,
|
||||||
|
covering,
|
||||||
stair,
|
stair,
|
||||||
window,
|
window,
|
||||||
opening,
|
opening,
|
||||||
@@ -106,7 +107,7 @@ classes = (
|
|||||||
slab.SetArcIndex,
|
slab.SetArcIndex,
|
||||||
space.GenerateSpace,
|
space.GenerateSpace,
|
||||||
space.GenerateSpacesFromWalls,
|
space.GenerateSpacesFromWalls,
|
||||||
space.GenerateFlooringCoveringsFromWalls,
|
covering.AddInstanceFlooringCoveringsFromWalls,
|
||||||
space.ToggleSpaceVisibility,
|
space.ToggleSpaceVisibility,
|
||||||
mep.FitFlowSegments,
|
mep.FitFlowSegments,
|
||||||
mep.RegenerateDistributionElement,
|
mep.RegenerateDistributionElement,
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
|
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of BlenderBIM Add-on.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import ifcopenshell
|
||||||
|
import blenderbim.tool as tool
|
||||||
|
import blenderbim.core.covering as core
|
||||||
|
|
||||||
|
|
||||||
|
class AddInstanceFlooringCoveringsFromWalls(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
bl_idname = "bim.add_instance_flooring_coverings_from_walls"
|
||||||
|
bl_label = "Add Typed Covering From Walls"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
bl_description = "Add instance flooring coverings from selected walls. The active object must be a wall and layered vertically"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
active_obj = bpy.context.active_object
|
||||||
|
element = tool.Ifc.get_entity(active_obj)
|
||||||
|
if element:
|
||||||
|
if element.is_a("IfcWall") and tool.Model.get_usage_type(element) == "LAYER2":
|
||||||
|
return context.selected_objects
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
# This only works based on a 2D plan only considering the standard
|
||||||
|
# walls (i.e. prismatic) in the active object storey.
|
||||||
|
# In order to run, the active object must be a wall and
|
||||||
|
# there must be selected walls
|
||||||
|
|
||||||
|
active_obj = bpy.context.active_object
|
||||||
|
if not active_obj:
|
||||||
|
self.report({"ERROR"}, "No active object. Please select a wall")
|
||||||
|
return
|
||||||
|
|
||||||
|
element = tool.Ifc.get_entity(active_obj)
|
||||||
|
if element and not element.is_a("IfcWall"):
|
||||||
|
return self.report({"ERROR"}, "The active object is not a wall. Please select a wall.")
|
||||||
|
|
||||||
|
container = ifcopenshell.util.element.get_container(element)
|
||||||
|
if not container:
|
||||||
|
self.report({"ERROR"}, "The wall is not contained.")
|
||||||
|
|
||||||
|
if not bpy.context.selected_objects:
|
||||||
|
self.report({"ERROR"}, "No selected objects found. Please select walls.")
|
||||||
|
return
|
||||||
|
|
||||||
|
core.add_instance_flooring_coverings_from_walls(tool.Ifc, tool.Spatial, tool.Collector, tool.Geometry)
|
||||||
|
|
||||||
@@ -235,26 +235,6 @@ class GenerateSpacesFromWalls(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
# there must be selected walls
|
# there must be selected walls
|
||||||
core.generate_spaces_from_walls(tool.Ifc, tool.Spatial, tool.Collector)
|
core.generate_spaces_from_walls(tool.Ifc, tool.Spatial, tool.Collector)
|
||||||
|
|
||||||
class GenerateFlooringCoveringsFromWalls(bpy.types.Operator, tool.Ifc.Operator):
|
|
||||||
bl_idname = "bim.generate_flooring_coverings_from_walls"
|
|
||||||
bl_label = "Generate Flooring Coverings From Walls"
|
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
|
||||||
bl_description = "Generate flooring coverings from selected walls. The active object must be a wall"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
active_obj = bpy.context.active_object
|
|
||||||
element = tool.Ifc.get_entity(active_obj)
|
|
||||||
if element:
|
|
||||||
return context.selected_objects and element.is_a("IfcWall")
|
|
||||||
|
|
||||||
def _execute(self, context):
|
|
||||||
# This only works based on a 2D plan only considering the standard
|
|
||||||
# walls (i.e. prismatic) in the active object storey.
|
|
||||||
# In order to run, the active object must be a wall and
|
|
||||||
# there must be selected walls
|
|
||||||
core.generate_flooring_coverings_from_walls(tool.Ifc, tool.Spatial, tool.Collector)
|
|
||||||
|
|
||||||
class ToggleSpaceVisibility(bpy.types.Operator, tool.Ifc.Operator):
|
class ToggleSpaceVisibility(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.toggle_space_visibility"
|
bl_idname = "bim.toggle_space_visibility"
|
||||||
bl_label = "Toggle Space Visibility"
|
bl_label = "Toggle Space Visibility"
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
|
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of BlenderBIM Add-on.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
def add_instance_flooring_coverings_from_walls(ifc, spatial, collector, geometry):
|
||||||
|
z = spatial.get_active_obj_z()
|
||||||
|
union = spatial.get_union_shape_from_selected_objects()
|
||||||
|
for i, linear_ring in enumerate(union.interiors):
|
||||||
|
poly = spatial.get_buffered_poly_from_linear_ring(linear_ring)
|
||||||
|
bm = spatial.get_bmesh_from_polygon(poly, h=0)
|
||||||
|
|
||||||
|
name = "Covering" + str(i)
|
||||||
|
obj = spatial.get_named_obj_from_bmesh(name, bmesh = bm)
|
||||||
|
|
||||||
|
spatial.set_obj_origin_to_bboxcenter(obj)
|
||||||
|
spatial.traslate_obj_to_z_location(obj, z)
|
||||||
|
spatial.link_obj_to_active_collection(obj)
|
||||||
|
|
||||||
|
points = spatial.get_2d_vertices_from_obj(obj)
|
||||||
|
|
||||||
|
spatial.assign_type_to_obj(obj)
|
||||||
|
spatial.assign_container_to_obj(obj)
|
||||||
|
|
||||||
|
spatial.assign_swept_area_outer_curve_from_2d_vertices(obj, vertices = points)
|
||||||
|
body = spatial.get_body_representation(obj)
|
||||||
|
spatial.regen_obj_representation(ifc, geometry, obj, body)
|
||||||
|
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
import blenderbim.core
|
import blenderbim.core
|
||||||
import bpy
|
import bpy
|
||||||
import ifcopenshell
|
|
||||||
|
|
||||||
|
|
||||||
def reference_structure(ifc, spatial, structure=None, element=None):
|
def reference_structure(ifc, spatial, structure=None, element=None):
|
||||||
@@ -126,7 +125,6 @@ def select_decomposed_elements(spatial):
|
|||||||
#HERE STARTS SPATIAL TOOL
|
#HERE STARTS SPATIAL TOOL
|
||||||
|
|
||||||
def generate_spaces_from_walls(ifc, spatial, collector):
|
def generate_spaces_from_walls(ifc, spatial, collector):
|
||||||
#props = bpy.context.scene.BIMModelProperties
|
|
||||||
container, active_obj = spatial.get_container_and_active_obj()
|
container, active_obj = spatial.get_container_and_active_obj()
|
||||||
|
|
||||||
if not active_obj:
|
if not active_obj:
|
||||||
@@ -176,9 +174,6 @@ def generate_spaces_from_walls(ifc, spatial, collector):
|
|||||||
ifc, collector, spatial, structure_obj=container_obj, element_obj=obj
|
ifc, collector, spatial, structure_obj=container_obj, element_obj=obj
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_flooring_coverings_from_walls(ifc, spatial, collector):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def toggle_space_visibility(ifc, spatial):
|
def toggle_space_visibility(ifc, spatial):
|
||||||
model = ifc.get()
|
model = ifc.get()
|
||||||
spaces = model.by_type("IfcSpace")
|
spaces = model.by_type("IfcSpace")
|
||||||
|
|||||||
@@ -811,7 +811,7 @@ class Spatial:
|
|||||||
def set_relative_object_matrix(cls, target_obj, relative_to_obj, matrix): pass
|
def set_relative_object_matrix(cls, target_obj, relative_to_obj, matrix): pass
|
||||||
def show_scene_objects(cls): pass
|
def show_scene_objects(cls): pass
|
||||||
#HERE STARTS SPATIAL TOOL
|
#HERE STARTS SPATIAL TOOL
|
||||||
def get_container_and_active_obj(cls): pass
|
# def get_container_and_active_obj(cls): pass
|
||||||
def get_union_shape_from_selected_objects(cls, selected_objects): pass
|
def get_union_shape_from_selected_objects(cls, selected_objects): pass
|
||||||
def get_boundary_elements(cls, selected_objects): pass
|
def get_boundary_elements(cls, selected_objects): pass
|
||||||
def get_polygons(cls, boundary_elements): pass
|
def get_polygons(cls, boundary_elements): pass
|
||||||
@@ -820,8 +820,17 @@ class Spatial:
|
|||||||
def get_purged_inner_holes_poly(cls, union_geom, min_area): pass
|
def get_purged_inner_holes_poly(cls, union_geom, min_area): pass
|
||||||
def get_poly_valid_interior_list(cls, poly, min_area, interiors_list): pass
|
def get_poly_valid_interior_list(cls, poly, min_area, interiors_list): pass
|
||||||
def get_buffered_poly_from_linear_ring(cls, linear_ring): pass
|
def get_buffered_poly_from_linear_ring(cls, linear_ring): pass
|
||||||
def get_bmesh_from_polygon(cls, poly, mat, h): pass
|
def get_bmesh_from_polygon(cls, poly, h): pass
|
||||||
|
def get_named_obj_from_bmesh(cls, name, bmesh): pass
|
||||||
def set_obj_origin_to_bboxcenter(cls, obj): pass
|
def set_obj_origin_to_bboxcenter(cls, obj): pass
|
||||||
|
def get_active_obj_z(cls, obj): pass
|
||||||
|
def traslate_obj_to_z_location(cls, obj): pass
|
||||||
|
def link_obj_to_active_collection(cls, obj): pass
|
||||||
|
def get_2d_vertices_from_obj(cls, obj): pass
|
||||||
|
def assign_swept_area_outer_curve_from_2d_vertices(cls, obj, vertices): pass
|
||||||
|
def get_body_representation(cls, obj): pass
|
||||||
|
def assign_type_to_obj(cls, obj): pass
|
||||||
|
def regen_obj_representation(cls, ifc, geometry, obj, body): pass
|
||||||
def toggle_spaces_visibility_wired_and_textured(cls, spaces): pass
|
def toggle_spaces_visibility_wired_and_textured(cls, spaces): pass
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
|
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of BlenderBIM Add-on.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import bmesh
|
||||||
|
import shapely
|
||||||
|
import ifcopenshell
|
||||||
|
import blenderbim.core.tool
|
||||||
|
import blenderbim.core.root
|
||||||
|
import blenderbim.core.spatial
|
||||||
|
import blenderbim.core.geometry
|
||||||
|
import blenderbim.tool as tool
|
||||||
|
import json
|
||||||
|
from math import pi
|
||||||
|
from mathutils import Vector, Matrix
|
||||||
|
from shapely import Polygon, MultiPolygon
|
||||||
|
|
||||||
|
class Covering(blenderbim.core.tool.Covering):
|
||||||
|
@classmethod
|
||||||
|
# def toggle_spaces_visibility_wired_and_textured(cls, spaces):
|
||||||
|
# first_obj = tool.Ifc.get_object(spaces[0])
|
||||||
|
# if bpy.data.objects[first_obj.name].display_type == "TEXTURED":
|
||||||
|
# for space in spaces:
|
||||||
|
# obj = tool.Ifc.get_object(space)
|
||||||
|
# bpy.data.objects[obj.name].show_wire = True
|
||||||
|
# bpy.data.objects[obj.name].display_type = "WIRE"
|
||||||
|
# return
|
||||||
|
#
|
||||||
|
# elif bpy.data.objects[first_obj.name].display_type == "WIRE":
|
||||||
|
# for space in spaces:
|
||||||
|
# obj = tool.Ifc.get_object(space)
|
||||||
|
# bpy.data.objects[obj.name].show_wire = False
|
||||||
|
# bpy.data.objects[obj.name].display_type = "TEXTURED"
|
||||||
|
# return
|
||||||
@@ -23,6 +23,7 @@ import ifcopenshell
|
|||||||
import blenderbim.core.tool
|
import blenderbim.core.tool
|
||||||
import blenderbim.core.root
|
import blenderbim.core.root
|
||||||
import blenderbim.core.spatial
|
import blenderbim.core.spatial
|
||||||
|
import blenderbim.core.geometry
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
import json
|
import json
|
||||||
from math import pi
|
from math import pi
|
||||||
@@ -270,14 +271,8 @@ class Spatial(blenderbim.core.tool.Spatial):
|
|||||||
#HERE STARTS SPATIAL TOOL
|
#HERE STARTS SPATIAL TOOL
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_container_and_active_obj(cls):
|
def get_union_shape_from_selected_objects(cls):
|
||||||
active_obj = bpy.context.active_object
|
selected_objects = bpy.context.selected_objects
|
||||||
element = tool.Ifc.get_entity(active_obj)
|
|
||||||
container = ifcopenshell.util.element.get_container(element)
|
|
||||||
return container, active_obj
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_union_shape_from_selected_objects(cls, selected_objects):
|
|
||||||
boundary_elements = cls.get_boundary_elements(selected_objects)
|
boundary_elements = cls.get_boundary_elements(selected_objects)
|
||||||
polys = cls.get_polygons(boundary_elements)
|
polys = cls.get_polygons(boundary_elements)
|
||||||
converted_tolerance = cls.get_converted_tolerance(tolerance=0.03)
|
converted_tolerance = cls.get_converted_tolerance(tolerance=0.03)
|
||||||
@@ -373,7 +368,8 @@ class Spatial(blenderbim.core.tool.Spatial):
|
|||||||
return poly
|
return poly
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_bmesh_from_polygon(cls, poly, mat, h):
|
def get_bmesh_from_polygon(cls, poly, h):
|
||||||
|
mat = bpy.context.active_object.matrix_world
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
bm.verts.index_update()
|
bm.verts.index_update()
|
||||||
bm.edges.index_update()
|
bm.edges.index_update()
|
||||||
@@ -391,14 +387,25 @@ class Spatial(blenderbim.core.tool.Spatial):
|
|||||||
bmesh.ops.triangle_fill(bm, edges=bm.edges)
|
bmesh.ops.triangle_fill(bm, edges=bm.edges)
|
||||||
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 5, verts=bm.verts, edges=bm.edges)
|
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 5, verts=bm.verts, edges=bm.edges)
|
||||||
|
|
||||||
extrusion = bmesh.ops.extrude_face_region(bm, geom=bm.faces)
|
if h!=0:
|
||||||
extruded_verts = [g for g in extrusion["geom"] if isinstance(g, bmesh.types.BMVert)]
|
extrusion = bmesh.ops.extrude_face_region(bm, geom=bm.faces)
|
||||||
bmesh.ops.translate(bm, vec=[0.0, 0.0, h], verts=extruded_verts)
|
extruded_verts = [g for g in extrusion["geom"] if isinstance(g, bmesh.types.BMVert)]
|
||||||
|
bmesh.ops.translate(bm, vec=[0.0, 0.0, h], verts=extruded_verts)
|
||||||
|
|
||||||
bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
|
bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
|
||||||
|
|
||||||
return bm
|
return bm
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_named_obj_from_bmesh(cls, name, bmesh):
|
||||||
|
mesh = bpy.data.meshes.new(name=name)
|
||||||
|
bmesh.to_mesh(mesh)
|
||||||
|
bmesh.free()
|
||||||
|
obj = bpy.data.objects.new(name, mesh)
|
||||||
|
mat = bpy.context.active_object.matrix_world
|
||||||
|
obj.matrix_world = mat
|
||||||
|
return obj
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_obj_origin_to_bboxcenter(cls, obj):
|
def set_obj_origin_to_bboxcenter(cls, obj):
|
||||||
mat = obj.matrix_world
|
mat = obj.matrix_world
|
||||||
@@ -415,6 +422,84 @@ class Spatial(blenderbim.core.tool.Spatial):
|
|||||||
vert.co = inverted @ aux_vector
|
vert.co = inverted @ aux_vector
|
||||||
obj.location = newLoc
|
obj.location = newLoc
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_active_obj_z(cls):
|
||||||
|
x, y, z = bpy.context.active_object.matrix_world.translation.xyz
|
||||||
|
return z
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def traslate_obj_to_z_location(cls, obj, z):
|
||||||
|
if z != 0:
|
||||||
|
obj.location = obj.location + Vector((0, 0, z))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def link_obj_to_active_collection(cls, obj):
|
||||||
|
bpy.context.view_layer.active_layer_collection.collection.objects.link(obj)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_2d_vertices_from_obj(cls, obj):
|
||||||
|
points = []
|
||||||
|
vectors = [v.co for v in obj.data.vertices.values()]
|
||||||
|
for vector in vectors:
|
||||||
|
point = (vector[0], vector[1])
|
||||||
|
points.append(point)
|
||||||
|
|
||||||
|
points.append((vectors[0][0], vectors[0][1]))
|
||||||
|
return points
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def assign_swept_area_outer_curve_from_2d_vertices(cls, obj, vertices):
|
||||||
|
body = cls.get_body_representation(obj)
|
||||||
|
model = tool.Ifc.get()
|
||||||
|
extrusion = tool.Model.get_extrusion(body)
|
||||||
|
area = extrusion.SweptArea
|
||||||
|
old_area = area.OuterCurve
|
||||||
|
|
||||||
|
builder = ifcopenshell.util.shape_builder.ShapeBuilder(model)
|
||||||
|
outer_curve = builder.polyline(vertices, closed = True)
|
||||||
|
|
||||||
|
area.OuterCurve = outer_curve
|
||||||
|
ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), old_area)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_body_representation(cls, obj):
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
model = tool.Ifc.get()
|
||||||
|
body = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||||
|
return body
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def assign_type_to_obj(cls, obj):
|
||||||
|
relating_type_id = bpy.context.scene.BIMModelProperties.relating_type_id
|
||||||
|
relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||||
|
ifc_class = relating_type.is_a()
|
||||||
|
instance_class = ifcopenshell.util.type.get_applicable_entities(ifc_class, tool.Ifc.get().schema)[0]
|
||||||
|
bpy.ops.bim.assign_class(obj=obj.name, ifc_class=instance_class)
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=element, type=relating_type)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def assign_container_to_obj(cls, obj):
|
||||||
|
active_obj = bpy.context.active_object
|
||||||
|
element = tool.Ifc.get_entity(active_obj)
|
||||||
|
container = ifcopenshell.util.element.get_container(element)
|
||||||
|
container_obj = tool.Ifc.get_object(container)
|
||||||
|
blenderbim.core.spatial.assign_container(
|
||||||
|
tool.Ifc, tool.Collector, tool.Spatial, structure_obj=container_obj, element_obj=obj
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def regen_obj_representation(cls, ifc, geometry, obj, body):
|
||||||
|
blenderbim.core.geometry.switch_representation(
|
||||||
|
ifc,
|
||||||
|
geometry,
|
||||||
|
obj=obj,
|
||||||
|
representation=body,
|
||||||
|
should_reload=True,
|
||||||
|
is_global=True,
|
||||||
|
should_sync_changes_first=False,
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def toggle_spaces_visibility_wired_and_textured(cls, spaces):
|
def toggle_spaces_visibility_wired_and_textured(cls, spaces):
|
||||||
first_obj = tool.Ifc.get_object(spaces[0])
|
first_obj = tool.Ifc.get_object(spaces[0])
|
||||||
|
|||||||
Binary file not shown.
@@ -7,6 +7,7 @@ markers =
|
|||||||
classification
|
classification
|
||||||
context
|
context
|
||||||
cost
|
cost
|
||||||
|
covering
|
||||||
debug
|
debug
|
||||||
demo
|
demo
|
||||||
document
|
document
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
@covering
|
||||||
|
Feature: Covering
|
||||||
|
Covers covering tool.
|
||||||
|
|
||||||
|
Scenario: Execute generate flooring coverings from walls
|
||||||
|
Given an empty IFC project
|
||||||
|
And I load the demo construction library
|
||||||
|
And I set "scene.BIMModelProperties.ifc_class" to "IfcWallType"
|
||||||
|
And the variable "element_type" is "[e for e in {ifc}.by_type('IfcWallType') if e.Name == 'WAL100'][0].id()"
|
||||||
|
And I set "scene.BIMModelProperties.relating_type_id" to "{element_type}"
|
||||||
|
And I press "bim.add_constr_type_instance"
|
||||||
|
And the object "IfcWall/Wall" is selected
|
||||||
|
When I press "bim.add_instance_flooring_coverings_from_walls"
|
||||||
|
Then nothing happens
|
||||||
|
|
||||||
Reference in New Issue
Block a user