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:
Dion Moult
2023-10-20 12:28:18 +11:00
parent afd3ac1881
commit eff68dda38
3 changed files with 62 additions and 53 deletions
@@ -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)