mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
Refactor create_space operator and better UI for covering tool
This commit is contained in:
@@ -42,13 +42,14 @@ class CoveringTool(WorkSpaceTool):
|
||||
bl_description = "Create and edit coverings"
|
||||
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.covering")
|
||||
bl_widget = None
|
||||
ifc_element_type = "IfcCoveringType"
|
||||
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")
|
||||
CoveringToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
|
||||
|
||||
def add_layout_hotkey(layout, text, hotkey, description):
|
||||
args = ["covering", layout, text, hotkey, description]
|
||||
@@ -71,7 +72,6 @@ class CoveringToolUI:
|
||||
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"):
|
||||
@@ -97,6 +97,7 @@ class CoveringToolUI:
|
||||
if AuthoringData.data["predefined_type"] == "FLOORING":
|
||||
if element and bpy.context.selected_objects and element.is_a("IfcWall"):
|
||||
op = row.operator("bim.add_instance_flooring_coverings_from_walls")
|
||||
# PLEASE KEEP COMMENTS AS A REMINDER
|
||||
# elif element and bpy.context.selected_objects and element.is_a("IfcSpace"):
|
||||
# op. = row.operator("bim.add_istance_flooring_from_spaces"):
|
||||
else:
|
||||
@@ -183,8 +184,11 @@ class Hotkey(bpy.types.Operator, Operator):
|
||||
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()
|
||||
if AuthoringData.data["predefined_type"] == "FLOORING":
|
||||
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()
|
||||
else:
|
||||
bpy.ops.bim.add_constr_type_instance()
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ 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 Covering From Walls"
|
||||
bl_label = "Add Flooring 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"
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ def update_type_class(self, context):
|
||||
def update_relating_type_id(self, context):
|
||||
AuthoringData.data["relating_type_id"] = AuthoringData.relating_type_id()
|
||||
AuthoringData.data["type_thumbnail"] = AuthoringData.type_thumbnail()
|
||||
AuthoringData.data["predefined_type"] = AuthoringData.predefined_type()
|
||||
|
||||
|
||||
def update_type_page(self, context):
|
||||
|
||||
@@ -50,13 +50,7 @@ class GenerateSpace(bpy.types.Operator, tool.Ifc.Operator):
|
||||
def msg(self, context):
|
||||
self.layout.label(text="NO ACTIVE STOREY")
|
||||
|
||||
props = context.scene.BIMModelProperties
|
||||
relating_type_id = props.relating_type_id
|
||||
relating_type = None
|
||||
if relating_type_id:
|
||||
relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||
if not relating_type.is_a("IfcSpaceType"):
|
||||
relating_type = None
|
||||
# props = context.scene.BIMModelProperties
|
||||
|
||||
collection = context.view_layer.active_layer_collection.collection
|
||||
collection_obj = collection.BIMCollectionProperties.obj
|
||||
@@ -68,158 +62,7 @@ class GenerateSpace(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR")
|
||||
return
|
||||
|
||||
# core.generate_space(tool.Ifc, tool.Spatial)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
active_obj = bpy.context.active_object
|
||||
element = None
|
||||
if bpy.context.selected_objects and active_obj:
|
||||
element = tool.Ifc.get_entity(active_obj)
|
||||
mat = active_obj.matrix_world
|
||||
local_bbox_center = 0.125 * sum((Vector(b) for b in active_obj.bound_box), Vector())
|
||||
global_bbox_center = mat @ local_bbox_center
|
||||
x = global_bbox_center.x
|
||||
y = global_bbox_center.y
|
||||
z = (mat @ Vector(active_obj.bound_box[0])).z
|
||||
|
||||
h = active_obj.dimensions.z
|
||||
else:
|
||||
x, y = context.scene.cursor.location.xy
|
||||
z = collection_obj.matrix_world.translation.z
|
||||
mat = Matrix()
|
||||
mat.translation = (x, y, z)
|
||||
h = 3
|
||||
|
||||
calculation_rl = context.scene.BIMModelProperties.rl3
|
||||
self.cut_point = collection_obj.matrix_world.translation.copy() + Vector((0, 0, calculation_rl))
|
||||
self.cut_normal = Vector((0, 0, 1))
|
||||
boundary_lines = []
|
||||
|
||||
gross_settings = ifcopenshell.geom.settings()
|
||||
gross_settings.set(gross_settings.DISABLE_OPENING_SUBTRACTIONS, True)
|
||||
|
||||
for obj in bpy.context.visible_objects:
|
||||
visible_element = tool.Ifc.get_entity(obj)
|
||||
|
||||
if (
|
||||
not visible_element
|
||||
or obj.type != "MESH"
|
||||
or not self.is_bounding_class(visible_element)
|
||||
or not tool.Drawing.is_intersecting_plane(obj, self.cut_point, self.cut_normal)
|
||||
):
|
||||
continue
|
||||
|
||||
old_mesh = None
|
||||
if visible_element.HasOpenings:
|
||||
new_mesh = self.create_mesh(ifcopenshell.geom.create_shape(gross_settings, visible_element))
|
||||
old_mesh = obj.data
|
||||
obj.data = new_mesh
|
||||
|
||||
local_cut_point = obj.matrix_world.inverted() @ self.cut_point
|
||||
local_cut_normal = obj.matrix_world.inverted().to_quaternion() @ self.cut_normal
|
||||
verts, edges = tool.Drawing.bisect_mesh_with_plane(obj, local_cut_point, local_cut_normal)
|
||||
|
||||
if old_mesh:
|
||||
obj.data = old_mesh
|
||||
bpy.data.meshes.remove(new_mesh)
|
||||
|
||||
for edge in edges or []:
|
||||
boundary_lines.append(
|
||||
shapely.LineString(
|
||||
[Vector((round(x, 3) for x in verts[edge[0]])), Vector((round(x, 3) for x in verts[edge[1]]))]
|
||||
)
|
||||
)
|
||||
|
||||
unioned_boundaries = shapely.union_all(shapely.GeometryCollection(boundary_lines))
|
||||
closed_polygons = shapely.polygonize(unioned_boundaries.geoms)
|
||||
|
||||
space_polygon = None
|
||||
for polygon in closed_polygons.geoms:
|
||||
if shapely.contains_xy(polygon, x, y):
|
||||
space_polygon = shapely.force_3d(polygon)
|
||||
|
||||
if not space_polygon:
|
||||
return
|
||||
|
||||
bm = bmesh.new()
|
||||
bm.verts.index_update()
|
||||
bm.edges.index_update()
|
||||
|
||||
mat_invert = mat.inverted()
|
||||
new_verts = [bm.verts.new(mat_invert @ Vector([v[0], v[1], z])) for v in space_polygon.exterior.coords[0:-1]]
|
||||
[bm.edges.new((new_verts[i], new_verts[i + 1])) for i in range(len(new_verts) - 1)]
|
||||
bm.edges.new((new_verts[len(new_verts) - 1], new_verts[0]))
|
||||
|
||||
for interior in space_polygon.interiors:
|
||||
new_verts = [bm.verts.new(mat_invert @ Vector([v[0], v[1], z])) for v in interior.coords[0:-1]]
|
||||
[bm.edges.new((new_verts[i], new_verts[i + 1])) for i in range(len(new_verts) - 1)]
|
||||
bm.edges.new((new_verts[len(new_verts) - 1], new_verts[0]))
|
||||
|
||||
bm.verts.index_update()
|
||||
bm.edges.index_update()
|
||||
|
||||
bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=1e-5)
|
||||
bmesh.ops.triangle_fill(bm, 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)
|
||||
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)
|
||||
|
||||
mesh = bpy.data.meshes.new(name="Space")
|
||||
bm.to_mesh(mesh)
|
||||
bm.free()
|
||||
|
||||
if element and element.is_a("IfcSpace"):
|
||||
mesh.name = active_obj.data.name
|
||||
mesh.BIMMeshProperties.ifc_definition_id = active_obj.data.BIMMeshProperties.ifc_definition_id
|
||||
tool.Geometry.change_object_data(active_obj, mesh, is_global=True)
|
||||
tool.Ifc.edit(active_obj)
|
||||
else:
|
||||
if relating_type:
|
||||
name = tool.Model.generate_occurrence_name(relating_type, "IfcSpace")
|
||||
else:
|
||||
name = "Space"
|
||||
obj = bpy.data.objects.new("Space", mesh)
|
||||
obj.matrix_world = mat
|
||||
collection.objects.link(obj)
|
||||
bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcSpace")
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if relating_type:
|
||||
blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=element, type=relating_type)
|
||||
|
||||
def is_bounding_class(self, element):
|
||||
for ifc_class in ["IfcWall", "IfcColumn", "IfcMember", "IfcVirtualElement", "IfcPlate"]:
|
||||
if element.is_a(ifc_class):
|
||||
return True
|
||||
return False
|
||||
|
||||
def create_mesh(self, shape):
|
||||
geometry = shape.geometry
|
||||
mesh = bpy.data.meshes.new("tmp")
|
||||
verts = geometry.verts
|
||||
if geometry.faces:
|
||||
num_vertices = len(verts) // 3
|
||||
total_faces = len(geometry.faces)
|
||||
loop_start = range(0, total_faces, 3)
|
||||
num_loops = total_faces // 3
|
||||
loop_total = [3] * num_loops
|
||||
num_vertex_indices = len(geometry.faces)
|
||||
|
||||
mesh.vertices.add(num_vertices)
|
||||
mesh.vertices.foreach_set("co", verts)
|
||||
mesh.loops.add(num_vertex_indices)
|
||||
mesh.loops.foreach_set("vertex_index", geometry.faces)
|
||||
mesh.polygons.add(num_loops)
|
||||
mesh.polygons.foreach_set("loop_start", loop_start)
|
||||
mesh.polygons.foreach_set("loop_total", loop_total)
|
||||
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
||||
mesh.update()
|
||||
return mesh
|
||||
core.generate_space(tool.Ifc, tool.Spatial, tool.Model)
|
||||
|
||||
|
||||
class GenerateSpacesFromWalls(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
# 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 blenderbim.core
|
||||
|
||||
import blenderbim.core.type
|
||||
|
||||
def reference_structure(ifc, spatial, structure=None, element=None):
|
||||
if spatial.can_reference(structure, element):
|
||||
@@ -128,8 +127,51 @@ def select_decomposed_elements(spatial):
|
||||
spatial.select_products(spatial.get_decomposed_elements(container))
|
||||
|
||||
#HERE STARTS SPATIAL TOOL
|
||||
def generate_space(ifc, spatial):
|
||||
pass
|
||||
def generate_space(ifc, spatial, model):
|
||||
active_obj = spatial.get_active_obj()
|
||||
selected_objects = spatial.get_selected_objects()
|
||||
element = None
|
||||
relating_type_id = spatial.get_relating_type_id()
|
||||
|
||||
relating_type = None
|
||||
if relating_type_id:
|
||||
relating_type = ifc.get().by_id(int(relating_type_id))
|
||||
if not relating_type.is_a("IfcSpaceType"):
|
||||
relating_type = None
|
||||
|
||||
if selected_objects and active_obj:
|
||||
x, y, z, h, mat = spatial.get_x_y_z_h_mat_from_active_obj(active_obj) ##mat
|
||||
element = ifc.get_entity(active_obj)
|
||||
|
||||
else:
|
||||
x, y, z, h, mat = spatial.get_x_y_z_h_mat_from_cursor() ##mat
|
||||
|
||||
space_polygon = spatial.get_space_polygon_from_context_visible_objects(x, y)
|
||||
|
||||
if not space_polygon:
|
||||
return
|
||||
|
||||
bm = spatial.get_bmesh_from_polygon(space_polygon, h=h) ##mat
|
||||
|
||||
mesh = spatial.get_named_mesh_from_bmesh(name = "Space", bmesh = bm)
|
||||
|
||||
if element and element.is_a("IfcSpace"):
|
||||
spatial.edit_active_space_obj_from_mesh(mesh)
|
||||
else:
|
||||
if relating_type:
|
||||
name = model.generate_occurrence_name(relating_type, "IfcSpace")
|
||||
else:
|
||||
name = "Space"
|
||||
|
||||
obj = spatial.get_named_obj_from_mesh(name, mesh) ##mat
|
||||
spatial.set_obj_origin_to_cursor_position(obj)
|
||||
spatial.link_obj_to_active_collection(obj)
|
||||
spatial.assign_ifcspace_class_to_obj(obj)
|
||||
|
||||
element = ifc.get_entity(obj)
|
||||
|
||||
if relating_type:
|
||||
blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=element, type=relating_type)
|
||||
|
||||
|
||||
def generate_spaces_from_walls(ifc, spatial, collector):
|
||||
|
||||
@@ -809,6 +809,13 @@ class Spatial:
|
||||
def set_relative_object_matrix(cls, target_obj, relative_to_obj, matrix): pass
|
||||
def show_scene_objects(cls): pass
|
||||
#HERE STARTS SPATIAL TOOL
|
||||
def is_bounding_class(cls, visible_element): pass
|
||||
def get_space_polygon_from_context_visible_objects(cls, x, y): pass
|
||||
def get_boundary_lines_from_context_visible_objects(cls, visible_objects): pass
|
||||
def get_gross_mesh_from_element(cls, visible_element): pass
|
||||
def create_mesh_from_shape(cls, shape): pass
|
||||
def get_x_y_z_h_mat_from_active_obj(cls, active_obj): pass
|
||||
def get_x_y_z_h_mat_from_cursor(cls): pass
|
||||
def get_union_shape_from_selected_objects(cls): pass
|
||||
def get_boundary_elements(cls, selected_objects): pass
|
||||
def get_polygons(cls, boundary_elements): pass
|
||||
@@ -819,9 +826,16 @@ class Spatial:
|
||||
def get_buffered_poly_from_linear_ring(cls, linear_ring): pass
|
||||
def get_bmesh_from_polygon(cls, poly, h): pass
|
||||
def get_named_obj_from_bmesh(cls, name, bmesh): pass
|
||||
def get_named_obj_from_mesh(cls, name, mesh): pass
|
||||
def get_named_mesh_from_bmesh(cls, name, bmesh): pass
|
||||
def edit_active_space_obj_from_mesh(cls, mesh): pass
|
||||
def set_obj_origin_to_bboxcenter(cls, obj): pass
|
||||
def set_obj_origin_to_cursor_position(cls, obj): pass
|
||||
def get_selected_objects(cls): pass
|
||||
def get_active_obj(cls): pass
|
||||
def get_active_obj_z(cls): pass
|
||||
def get_active_obj_height(cls): pass
|
||||
def get_relating_type_id(cls): 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
|
||||
|
||||
@@ -270,6 +270,123 @@ class Spatial(blenderbim.core.tool.Spatial):
|
||||
|
||||
#HERE STARTS SPATIAL TOOL
|
||||
|
||||
@classmethod
|
||||
def is_bounding_class(cls, visible_element):
|
||||
for ifc_class in ["IfcWall", "IfcColumn", "IfcMember", "IfcVirtualElement", "IfcPlate"]:
|
||||
if visible_element.is_a(ifc_class):
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_space_polygon_from_context_visible_objects(cls, x, y):
|
||||
boundary_lines = cls.get_boundary_lines_from_context_visible_objects()
|
||||
unioned_boundaries = shapely.union_all(shapely.GeometryCollection(boundary_lines))
|
||||
closed_polygons = shapely.polygonize(unioned_boundaries.geoms)
|
||||
space_polygon = None
|
||||
for polygon in closed_polygons.geoms:
|
||||
if shapely.contains_xy(polygon, x, y):
|
||||
space_polygon = shapely.force_3d(polygon)
|
||||
return space_polygon
|
||||
|
||||
@classmethod
|
||||
def get_boundary_lines_from_context_visible_objects(cls):
|
||||
calculation_rl = bpy.context.scene.BIMModelProperties.rl3
|
||||
collection = bpy.context.view_layer.active_layer_collection.collection
|
||||
collection_obj = collection.BIMCollectionProperties.obj
|
||||
cut_point = collection_obj.matrix_world.translation.copy() + Vector((0, 0, calculation_rl))
|
||||
cut_normal = Vector((0, 0, 1))
|
||||
boundary_lines = []
|
||||
|
||||
for obj in bpy.context.visible_objects:
|
||||
|
||||
|
||||
visible_element = tool.Ifc.get_entity(obj)
|
||||
|
||||
if (
|
||||
not visible_element
|
||||
or obj.type != "MESH"
|
||||
or not cls.is_bounding_class(visible_element)
|
||||
or not tool.Drawing.is_intersecting_plane(obj, cut_point, cut_normal)
|
||||
):
|
||||
continue
|
||||
|
||||
old_mesh = None
|
||||
if visible_element.HasOpenings:
|
||||
new_mesh = cls.get_gross_mesh_from_element(visible_element)
|
||||
old_mesh = obj.data
|
||||
obj.data = new_mesh
|
||||
|
||||
local_cut_point = obj.matrix_world.inverted() @ cut_point
|
||||
local_cut_normal = obj.matrix_world.inverted().to_quaternion() @ cut_normal
|
||||
verts, edges = tool.Drawing.bisect_mesh_with_plane(obj, local_cut_point, local_cut_normal)
|
||||
|
||||
if old_mesh:
|
||||
obj.data = old_mesh
|
||||
bpy.data.meshes.remove(new_mesh)
|
||||
|
||||
for edge in edges or []:
|
||||
boundary_lines.append(
|
||||
shapely.LineString(
|
||||
[Vector((round(x, 3) for x in verts[edge[0]])), Vector((round(x, 3) for x in verts[edge[1]]))]
|
||||
)
|
||||
)
|
||||
|
||||
return boundary_lines
|
||||
|
||||
@classmethod
|
||||
def get_gross_mesh_from_element(cls, visible_element):
|
||||
gross_settings = ifcopenshell.geom.settings()
|
||||
gross_settings.set(gross_settings.DISABLE_OPENING_SUBTRACTIONS, True)
|
||||
new_mesh = cls.create_mesh_from_shape(ifcopenshell.geom.create_shape(gross_settings, visible_element))
|
||||
return new_mesh
|
||||
|
||||
@classmethod
|
||||
def create_mesh_from_shape(cls, shape):
|
||||
geometry = shape.geometry
|
||||
mesh = bpy.data.meshes.new("tmp")
|
||||
verts = geometry.verts
|
||||
if geometry.faces:
|
||||
num_vertices = len(verts) // 3
|
||||
total_faces = len(geometry.faces)
|
||||
loop_start = range(0, total_faces, 3)
|
||||
num_loops = total_faces // 3
|
||||
loop_total = [3] * num_loops
|
||||
num_vertex_indices = len(geometry.faces)
|
||||
|
||||
mesh.vertices.add(num_vertices)
|
||||
mesh.vertices.foreach_set("co", verts)
|
||||
mesh.loops.add(num_vertex_indices)
|
||||
mesh.loops.foreach_set("vertex_index", geometry.faces)
|
||||
mesh.polygons.add(num_loops)
|
||||
mesh.polygons.foreach_set("loop_start", loop_start)
|
||||
mesh.polygons.foreach_set("loop_total", loop_total)
|
||||
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
||||
mesh.update()
|
||||
return mesh
|
||||
|
||||
@classmethod
|
||||
def get_x_y_z_h_mat_from_active_obj(cls, active_obj):
|
||||
element = tool.Ifc.get_entity(active_obj)
|
||||
mat = active_obj.matrix_world
|
||||
local_bbox_center = 0.125 * sum((Vector(b) for b in active_obj.bound_box), Vector())
|
||||
global_bbox_center = mat @ local_bbox_center
|
||||
x = global_bbox_center.x
|
||||
y = global_bbox_center.y
|
||||
z = (mat @ Vector(active_obj.bound_box[0])).z
|
||||
|
||||
h = active_obj.dimensions.z
|
||||
return x, y, z, h, mat
|
||||
|
||||
@classmethod
|
||||
def get_x_y_z_h_mat_from_cursor(cls):
|
||||
collection = bpy.context.view_layer.active_layer_collection.collection
|
||||
collection_obj = collection.BIMCollectionProperties.obj
|
||||
x, y = bpy.context.scene.cursor.location.xy
|
||||
z = collection_obj.matrix_world.translation.z
|
||||
mat = Matrix()
|
||||
h = 3
|
||||
return x, y, z, h, mat
|
||||
|
||||
@classmethod
|
||||
def get_union_shape_from_selected_objects(cls):
|
||||
selected_objects = bpy.context.selected_objects
|
||||
@@ -369,7 +486,11 @@ class Spatial(blenderbim.core.tool.Spatial):
|
||||
|
||||
@classmethod
|
||||
def get_bmesh_from_polygon(cls, poly, h):
|
||||
mat = bpy.context.active_object.matrix_world
|
||||
if bpy.context.selected_objects and bpy.context.active_object:
|
||||
mat = bpy.context.active_object.matrix_world
|
||||
else:
|
||||
mat = Matrix()
|
||||
|
||||
bm = bmesh.new()
|
||||
bm.verts.index_update()
|
||||
bm.edges.index_update()
|
||||
@@ -398,13 +519,32 @@ class Spatial(blenderbim.core.tool.Spatial):
|
||||
|
||||
@classmethod
|
||||
def get_named_obj_from_bmesh(cls, name, bmesh):
|
||||
mesh = cls.get_named_mesh_from_bmesh(name, bmesh)
|
||||
obj = cls.get_named_obj_from_mesh(name, mesh)
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def get_named_obj_from_mesh(cls, name, mesh):
|
||||
obj = bpy.data.objects.new(name, mesh)
|
||||
if bpy.context.active_object:
|
||||
mat = bpy.context.active_object.matrix_world
|
||||
obj.matrix_world = mat
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def get_named_mesh_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
|
||||
return mesh
|
||||
|
||||
@classmethod
|
||||
def edit_active_space_obj_from_mesh(cls, mesh):
|
||||
active_obj = bpy.context.active_object
|
||||
mesh.name = active_obj.data.name
|
||||
mesh.BIMMeshProperties.ifc_definition_id = active_obj.data.BIMMeshProperties.ifc_definition_id
|
||||
tool.Geometry.change_object_data(active_obj, mesh, is_global=True)
|
||||
tool.Ifc.edit(active_obj)
|
||||
|
||||
@classmethod
|
||||
def set_obj_origin_to_bboxcenter(cls, obj):
|
||||
@@ -422,6 +562,34 @@ class Spatial(blenderbim.core.tool.Spatial):
|
||||
vert.co = inverted @ aux_vector
|
||||
obj.location = newLoc
|
||||
|
||||
@classmethod
|
||||
def set_obj_origin_to_cursor_position(cls, obj):
|
||||
mat = obj.matrix_world
|
||||
inverted = mat.inverted()
|
||||
|
||||
|
||||
collection = bpy.context.view_layer.active_layer_collection.collection
|
||||
collection_obj = collection.BIMCollectionProperties.obj
|
||||
x, y = bpy.context.scene.cursor.location.xy
|
||||
z = collection_obj.matrix_world.translation.z
|
||||
|
||||
oldLoc = obj.location
|
||||
newLoc = Vector((x,y,z))
|
||||
diff = newLoc - oldLoc
|
||||
for vert in obj.data.vertices:
|
||||
aux_vector = mat @ vert.co
|
||||
aux_vector = aux_vector - diff
|
||||
vert.co = inverted @ aux_vector
|
||||
obj.location = newLoc
|
||||
|
||||
@classmethod
|
||||
def get_selected_objects(cls):
|
||||
return bpy.context.selected_objects
|
||||
|
||||
@classmethod
|
||||
def get_active_obj(cls):
|
||||
return bpy.context.active_object
|
||||
|
||||
@classmethod
|
||||
def get_active_obj_z(cls):
|
||||
x, y, z = bpy.context.active_object.matrix_world.translation.xyz
|
||||
@@ -432,6 +600,12 @@ class Spatial(blenderbim.core.tool.Spatial):
|
||||
height = bpy.context.active_object.dimensions.z
|
||||
return height
|
||||
|
||||
@classmethod
|
||||
def get_relating_type_id(cls):
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
relating_type_id = props.relating_type_id
|
||||
return relating_type_id
|
||||
|
||||
@classmethod
|
||||
def traslate_obj_to_z_location(cls, obj, z):
|
||||
if z != 0:
|
||||
|
||||
Reference in New Issue
Block a user