mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Fix #3903. Bug where stairs started off with an empty mesh and had a representation added, resulting in an invalid empty point cloud.
Now stairs have should_add_representation=False when creating the IfcStairFlight, and the representation is updated explicitly, similar to how parametric doors and windows etc have their representations updated.
This commit is contained in:
@@ -17,21 +17,17 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import json
|
||||
import bmesh
|
||||
import ifcopenshell
|
||||
import blenderbim
|
||||
import blenderbim.tool as tool
|
||||
from mathutils import Vector
|
||||
from bmesh.types import BMVert
|
||||
from bpy.types import Operator
|
||||
from bpy.props import FloatProperty, IntProperty
|
||||
from bpy_extras.object_utils import AddObjectHelper, object_data_add
|
||||
|
||||
import bmesh
|
||||
from bmesh.types import BMVert
|
||||
|
||||
import ifcopenshell
|
||||
from ifcopenshell.util.shape_builder import V, ShapeBuilder
|
||||
import blenderbim
|
||||
import blenderbim.tool as tool
|
||||
|
||||
from mathutils import Vector
|
||||
from pprint import pprint
|
||||
import json
|
||||
|
||||
|
||||
def add_dumb_stair_object(self, context):
|
||||
@@ -106,8 +102,7 @@ def generate_stair_2d_profile(
|
||||
if stair_type == "WOOD/STEEL":
|
||||
builder = ShapeBuilder(None)
|
||||
tread_shape = builder.get_rectangle_coords(
|
||||
size=V(tread_run, 0, tread_depth),
|
||||
position=V(0, 0, -(tread_depth-tread_rise))
|
||||
size=V(tread_run, 0, tread_depth), position=V(0, 0, -(tread_depth - tread_rise))
|
||||
)
|
||||
tread_offset = V(tread_run, 0, tread_rise)
|
||||
|
||||
@@ -116,12 +111,14 @@ def generate_stair_2d_profile(
|
||||
vertices.extend(cur_trade_shape)
|
||||
|
||||
cur_vertex = i * 4
|
||||
edges.extend([
|
||||
(cur_vertex, cur_vertex+1),
|
||||
(cur_vertex+1, cur_vertex+2),
|
||||
(cur_vertex+2, cur_vertex+3),
|
||||
(cur_vertex+3, cur_vertex),
|
||||
])
|
||||
edges.extend(
|
||||
[
|
||||
(cur_vertex, cur_vertex + 1),
|
||||
(cur_vertex + 1, cur_vertex + 2),
|
||||
(cur_vertex + 2, cur_vertex + 3),
|
||||
(cur_vertex + 3, cur_vertex),
|
||||
]
|
||||
)
|
||||
faces.append(list(range(cur_vertex, cur_vertex + 1)))
|
||||
|
||||
return (vertices, edges, faces)
|
||||
@@ -129,36 +126,26 @@ def generate_stair_2d_profile(
|
||||
elif stair_type == "GENERIC":
|
||||
vertices.append(Vector([0, 0, 0]))
|
||||
|
||||
tread_verts = [
|
||||
Vector([0, 0, tread_rise]),
|
||||
Vector([tread_run, 0, tread_rise])
|
||||
]
|
||||
tread_verts = [Vector([0, 0, tread_rise]), Vector([tread_run, 0, tread_rise])]
|
||||
tread_offset = Vector([tread_run, 0, tread_rise])
|
||||
|
||||
for i in range(number_of_risers):
|
||||
current_tread_verts = [v + tread_offset * i for v in tread_verts]
|
||||
last_vert_i = len(vertices) - 1
|
||||
edges.extend([
|
||||
(last_vert_i, last_vert_i + 1),
|
||||
(last_vert_i + 1, last_vert_i + 2)
|
||||
])
|
||||
edges.extend([(last_vert_i, last_vert_i + 1), (last_vert_i + 1, last_vert_i + 2)])
|
||||
vertices.extend(current_tread_verts)
|
||||
|
||||
last_vert_i = len(vertices)
|
||||
vertices.append(vertices[-1] * V(1,0,0))
|
||||
edges.extend([
|
||||
(last_vert_i - 1, last_vert_i),
|
||||
(last_vert_i, 0)
|
||||
])
|
||||
vertices.append(vertices[-1] * V(1, 0, 0))
|
||||
edges.extend([(last_vert_i - 1, last_vert_i), (last_vert_i, 0)])
|
||||
|
||||
return (vertices, edges, faces)
|
||||
|
||||
elif stair_type == "CONCRETE":
|
||||
for i in range(number_of_risers):
|
||||
vertices.extend([
|
||||
Vector((tread_run*i, 0, tread_rise*i)),
|
||||
Vector((tread_run*i, 0, tread_rise*(i+1)))
|
||||
])
|
||||
vertices.extend(
|
||||
[Vector((tread_run * i, 0, tread_rise * i)), Vector((tread_run * i, 0, tread_rise * (i + 1)))]
|
||||
)
|
||||
cur_vertex = i * 2
|
||||
if i != 0:
|
||||
edges.append((cur_vertex - 1, cur_vertex))
|
||||
@@ -179,11 +166,11 @@ def generate_stair_2d_profile(
|
||||
|
||||
# top nib
|
||||
if has_top_nib:
|
||||
vertices.append( vertices[number_of_risers * 2] + Vector((0, 0, -top_slab_depth)) )
|
||||
vertices.append( vertices[number_of_risers * 2] + Vector(((-top_slab_depth - b) / k, 0, -top_slab_depth)) )
|
||||
vertices.append(vertices[number_of_risers * 2] + Vector((0, 0, -top_slab_depth)))
|
||||
vertices.append(vertices[number_of_risers * 2] + Vector(((-top_slab_depth - b) / k, 0, -top_slab_depth)))
|
||||
last_vertex_i = len(vertices) - 1
|
||||
edges.append( (number_of_risers * 2, last_vertex_i - 1) )
|
||||
edges.append( (last_vertex_i - 1, last_vertex_i) )
|
||||
edges.append((number_of_risers * 2, last_vertex_i - 1))
|
||||
edges.append((last_vertex_i - 1, last_vertex_i))
|
||||
else:
|
||||
vertices.append(vertices[number_of_risers * 2] + depth_vector)
|
||||
last_vertex_i = len(vertices) - 1
|
||||
@@ -200,17 +187,17 @@ def generate_stair_2d_profile(
|
||||
vertices.append(vertices[0] + Vector(((-base_slab_depth - b) / k, 0, -base_slab_depth)))
|
||||
vertices.append(vertices[0] + Vector((0, 0, -base_slab_depth)))
|
||||
last_vertex_i = len(vertices) - 1
|
||||
edges.append( (0, last_vertex_i) )
|
||||
edges.append( (last_vertex_i - 1, last_vertex_i) )
|
||||
edges.append((0, last_vertex_i))
|
||||
edges.append((last_vertex_i - 1, last_vertex_i))
|
||||
bottom_nib_end = len(vertices) - 2
|
||||
|
||||
edges.append( (bottom_nib_end, top_nib_end) )
|
||||
edges.append((bottom_nib_end, top_nib_end))
|
||||
faces = [list(range(len(vertices)))]
|
||||
|
||||
return (vertices, edges, faces)
|
||||
|
||||
|
||||
def update_stair_modifier(context):
|
||||
def regenerate_stair_mesh(context):
|
||||
obj = context.active_object
|
||||
props_kwargs = obj.BIMStairProperties.get_props_kwargs()
|
||||
vertices, edges, faces = generate_stair_2d_profile(**props_kwargs)
|
||||
@@ -221,7 +208,7 @@ def update_stair_modifier(context):
|
||||
bm.edges.index_update()
|
||||
|
||||
new_verts = [bm.verts.new(v) for v in vertices]
|
||||
new_edges = [bm.edges.new( (new_verts[e[0]], new_verts[e[1]]) ) for e in edges]
|
||||
new_edges = [bm.edges.new((new_verts[e[0]], new_verts[e[1]])) for e in edges]
|
||||
bm.verts.index_update()
|
||||
bm.edges.index_update()
|
||||
|
||||
@@ -242,6 +229,26 @@ def update_stair_modifier(context):
|
||||
obj.data.update()
|
||||
|
||||
|
||||
def update_stair_representation(obj):
|
||||
body = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
|
||||
representation = ifcopenshell.api.run(
|
||||
"geometry.add_representation",
|
||||
tool.Ifc.get(),
|
||||
context=body,
|
||||
blender_object=obj,
|
||||
geometry=obj.data,
|
||||
coordinate_offset=tool.Geometry.get_cartesian_point_coordinate_offset(obj),
|
||||
total_items=tool.Geometry.get_total_representation_items(obj),
|
||||
should_force_faceted_brep=tool.Geometry.should_force_faceted_brep(),
|
||||
should_force_triangulation=tool.Geometry.should_force_triangulation(),
|
||||
should_generate_uvs=tool.Geometry.should_generate_uvs(obj),
|
||||
ifc_representation_class=None,
|
||||
profile_set_usage=None,
|
||||
)
|
||||
tool.Model.replace_object_ifc_representation(body, obj, representation)
|
||||
tool.Ifc.finish_edit(obj)
|
||||
|
||||
|
||||
def update_ifc_stair_props(obj):
|
||||
"""should be called after new geometry settled
|
||||
since it's going to update ifc representation
|
||||
@@ -327,7 +334,7 @@ class BIM_OT_add_clever_stair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
obj.location = spawn_location
|
||||
collection = context.view_layer.active_layer_collection.collection
|
||||
collection.objects.link(obj)
|
||||
|
||||
|
||||
body_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW")
|
||||
element = blenderbim.core.root.assign_class(
|
||||
tool.Ifc,
|
||||
@@ -335,7 +342,7 @@ class BIM_OT_add_clever_stair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
tool.Root,
|
||||
obj=obj,
|
||||
ifc_class="IfcStairFlight",
|
||||
should_add_representation=True,
|
||||
should_add_representation=False,
|
||||
context=body_context,
|
||||
)
|
||||
if tool.Ifc.get_schema() != "IFC2X3":
|
||||
@@ -372,8 +379,9 @@ class AddStair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
pset=pset,
|
||||
properties={"Data": json.dumps(stair_data)},
|
||||
)
|
||||
update_stair_modifier(context)
|
||||
regenerate_stair_mesh(context)
|
||||
update_ifc_stair_props(obj)
|
||||
update_stair_representation(obj)
|
||||
|
||||
|
||||
class CancelEditingStair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
@@ -388,7 +396,7 @@ class CancelEditingStair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
props = obj.BIMStairProperties
|
||||
# restore previous settings since editing was canceled
|
||||
props.set_props_kwargs_from_ifc_data(data)
|
||||
update_stair_modifier(context)
|
||||
regenerate_stair_mesh(context)
|
||||
|
||||
props.is_editing = False
|
||||
|
||||
@@ -407,7 +415,8 @@ class FinishEditingStair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
data = props.get_props_kwargs(convert_to_project_units=True)
|
||||
props.is_editing = False
|
||||
update_stair_modifier(context)
|
||||
regenerate_stair_mesh(context)
|
||||
update_stair_representation(obj)
|
||||
|
||||
pset = tool.Pset.get_element_pset(element, "BBIM_Stair")
|
||||
data = json.dumps(data)
|
||||
|
||||
@@ -30,7 +30,7 @@ from blenderbim.bim.module.model.data import (
|
||||
RoofData,
|
||||
)
|
||||
from blenderbim.bim.module.model.prop import get_ifc_class
|
||||
from blenderbim.bim.module.model.stair import update_stair_modifier
|
||||
from blenderbim.bim.module.model.stair import regenerate_stair_mesh
|
||||
from blenderbim.bim.module.model.window import update_window_modifier_bmesh
|
||||
from blenderbim.bim.module.model.door import update_door_modifier_bmesh
|
||||
from blenderbim.bim.module.model.railing import update_railing_modifier_bmesh
|
||||
@@ -267,7 +267,7 @@ class BIM_PT_stair(bpy.types.Panel):
|
||||
row = self.layout.row(align=True)
|
||||
for prop_name in props.get_props_kwargs():
|
||||
self.layout.prop(props, prop_name)
|
||||
update_stair_modifier(context)
|
||||
regenerate_stair_mesh(context)
|
||||
else:
|
||||
row.operator("bim.enable_editing_stair", icon="GREASEPENCIL", text="")
|
||||
row.operator("bim.remove_stair", icon="X", text="")
|
||||
|
||||
@@ -410,7 +410,7 @@ class AddType(bpy.types.Operator, tool.Ifc.Operator):
|
||||
obj=obj,
|
||||
predefined_type=predefined_type,
|
||||
ifc_class="IfcStairFlightType",
|
||||
should_add_representation=True,
|
||||
should_add_representation=False,
|
||||
context=body,
|
||||
)
|
||||
tool.Blender.select_and_activate_single_object(context, obj)
|
||||
|
||||
Reference in New Issue
Block a user