Add new covering tool. Mock up and initial functions

This commit is contained in:
Massimo Fabbro
2023-09-23 18:09:59 +02:00
parent 4ed901204e
commit da8cd9daba
17 changed files with 530 additions and 41 deletions
@@ -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
@@ -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")
+11 -2
View File
@@ -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
+97 -12
View File
@@ -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.
+1
View File
@@ -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