mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
@@ -83,6 +83,7 @@ def update_railing_modifier_ifc_data(context):
|
||||
pset_data = tool.Model.get_modeling_bbim_pset_data(bpy.context.active_object, "BBIM_Railing")
|
||||
path_data = pset_data["data_dict"]["path_data"]
|
||||
railing_path = [Vector(v) for v in path_data["verts"]]
|
||||
looped_path = path_data["edges"][-1][-1] == path_data["edges"][0][0]
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
|
||||
representation_data = {
|
||||
@@ -95,6 +96,7 @@ def update_railing_modifier_ifc_data(context):
|
||||
"clear_width": props.clear_width / si_conversion,
|
||||
"terminal_type": props.terminal_type,
|
||||
"height": props.height / si_conversion,
|
||||
"looped_path": looped_path,
|
||||
}
|
||||
model_representation = ifcopenshell.api.run(
|
||||
"geometry.add_railing_representation", ifc_file, **representation_data
|
||||
@@ -213,10 +215,14 @@ def get_path_data(obj):
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
|
||||
bm = tool.Blender.get_bmesh_for_mesh(obj.data)
|
||||
end_points = [v for v in bm.verts if len(v.link_edges) == 1]
|
||||
if not end_points:
|
||||
return None
|
||||
|
||||
if not bm.verts or not bm.edges:
|
||||
return
|
||||
|
||||
end_points = [v for v in bm.verts if len(v.link_edges) == 1]
|
||||
looped = not end_points
|
||||
|
||||
# TODO: check with previous data
|
||||
# if we have some previous data then we try to match
|
||||
# start or end of the path with the previous path
|
||||
previous_data = False
|
||||
@@ -231,11 +237,13 @@ def get_path_data(obj):
|
||||
start_point = potential_start[0]
|
||||
else:
|
||||
start_point = next(v for v in end_points if v != potential_start[0])
|
||||
else:
|
||||
elif not looped:
|
||||
start_point = min(end_points, key=lambda v: v.index)
|
||||
elif looped:
|
||||
start_point = bm.verts[:][0]
|
||||
|
||||
# walking through the path
|
||||
# to make sure all verts and in consequent order
|
||||
# to make sure all verts are in consequent order
|
||||
edge = start_point.link_edges[0]
|
||||
v = edge.other_vert(start_point)
|
||||
points = [start_point.co, v.co]
|
||||
@@ -246,10 +254,14 @@ def get_path_data(obj):
|
||||
|
||||
while len(link_edges := v.link_edges) != 1:
|
||||
prev_v = v
|
||||
link_edges = v.link_edges
|
||||
|
||||
edge = other_edge(link_edges, edge)
|
||||
v = edge.other_vert(prev_v)
|
||||
|
||||
if looped and v == start_point:
|
||||
segments.append((i - 1, 0))
|
||||
break
|
||||
|
||||
# skip path verts if they just go vertical to avoid errors
|
||||
if (v.co.xy - prev_v.co.xy).length <= 0.0001:
|
||||
continue
|
||||
@@ -318,6 +330,8 @@ class AddRailing(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
railing_data = props.get_general_kwargs(convert_to_project_units=True)
|
||||
path_data = get_path_data(obj)
|
||||
|
||||
# NOTE: will occur only on meshes without edges or verts
|
||||
if not path_data:
|
||||
path_data = {
|
||||
"edges": [[0, 1], [1, 2]],
|
||||
|
||||
@@ -54,6 +54,7 @@ class Usecase:
|
||||
"clear_width": self.convert_si_to_unit(mm(40)),
|
||||
"terminal_type": "180",
|
||||
"height": self.convert_si_to_unit(mm(1000)),
|
||||
"looped_path": False,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -80,6 +81,7 @@ class Usecase:
|
||||
cap_type = self.settings["terminal_type"]
|
||||
ifc_context = self.settings["context"]
|
||||
railing_coords = self.settings["railing_path"]
|
||||
looped_path = self.settings["looped_path"]
|
||||
railing_coords = [p - z_down * railing_radius for p in railing_coords]
|
||||
|
||||
# constant
|
||||
@@ -157,7 +159,10 @@ class Usecase:
|
||||
prev_dir = cur_dir
|
||||
i = i + 1
|
||||
|
||||
output_points.append(base_points[-1])
|
||||
if looped_path:
|
||||
output_points[0] = output_points[-1]
|
||||
else:
|
||||
output_points.append(base_points[-1])
|
||||
return output_points
|
||||
|
||||
def create_supports_items(railing_coords, manual_supports=False):
|
||||
@@ -215,37 +220,45 @@ class Usecase:
|
||||
ortho_dir = -ortho_dir
|
||||
|
||||
arc_middle_point_cos = sin(radians(45))
|
||||
|
||||
if cap_type in ('180', 'TO_END_POST'):
|
||||
|
||||
if cap_type in ("180", "TO_END_POST"):
|
||||
arc_point = start_point + cap_dir * terminal_radius + terminal_radius * z_down
|
||||
arc_points.append(arc_point)
|
||||
cap_coords = [arc_point, start_point + terminal_radius * 2 * z_down]
|
||||
|
||||
if cap_type == 'TO_END_POST':
|
||||
if cap_type == "TO_END_POST":
|
||||
end_point = railing_coords_for_cap[-2].copy()
|
||||
end_point.z -= terminal_radius * 2
|
||||
cap_coords.append(end_point)
|
||||
|
||||
elif cap_type == 'TO_WALL':
|
||||
arc_point = start_point + cap_dir * clear_width * arc_middle_point_cos + ortho_dir * clear_width * (1-arc_middle_point_cos)
|
||||
|
||||
elif cap_type == "TO_WALL":
|
||||
arc_point = (
|
||||
start_point
|
||||
+ cap_dir * clear_width * arc_middle_point_cos
|
||||
+ ortho_dir * clear_width * (1 - arc_middle_point_cos)
|
||||
)
|
||||
arc_points.append(arc_point)
|
||||
cap_coords = [arc_point, start_point + ortho_dir * clear_width + cap_dir * clear_width]
|
||||
|
||||
elif cap_type == 'TO_FLOOR':
|
||||
arc_point = start_point + cap_dir * terminal_radius * arc_middle_point_cos + z_down * terminal_radius * (1-arc_middle_point_cos)
|
||||
elif cap_type == "TO_FLOOR":
|
||||
arc_point = (
|
||||
start_point
|
||||
+ cap_dir * terminal_radius * arc_middle_point_cos
|
||||
+ z_down * terminal_radius * (1 - arc_middle_point_cos)
|
||||
)
|
||||
arc_points.append(arc_point)
|
||||
arc_end = start_point + cap_dir * terminal_radius + terminal_radius * z_down
|
||||
cap_coords = [
|
||||
arc_point,
|
||||
arc_point,
|
||||
arc_end,
|
||||
arc_end+z_down*(height-terminal_radius),
|
||||
arc_end + z_down * (height - terminal_radius),
|
||||
]
|
||||
|
||||
elif cap_type == 'TO_END_POST_AND_FLOOR':
|
||||
elif cap_type == "TO_END_POST_AND_FLOOR":
|
||||
first_arc_end = start_point + cap_dir * terminal_radius + terminal_radius * z_down
|
||||
first_arc_coords = get_fillet_points(
|
||||
start_point, start_point + cap_dir * terminal_radius,
|
||||
first_arc_end, terminal_radius)
|
||||
start_point, start_point + cap_dir * terminal_radius, first_arc_end, terminal_radius
|
||||
)
|
||||
arc_points.append(first_arc_coords[1])
|
||||
|
||||
end_point = railing_coords_for_cap[-2].copy()
|
||||
@@ -255,17 +268,22 @@ class Usecase:
|
||||
)
|
||||
arc_points.append(second_arc_coords[1])
|
||||
cap_coords = [start_point] + first_arc_coords + second_arc_coords + [end_point]
|
||||
|
||||
|
||||
railing_coords = railing_coords_for_cap + cap_coords
|
||||
|
||||
if start:
|
||||
railing_coords = railing_coords[::-1]
|
||||
return railing_coords, arc_points
|
||||
|
||||
# need to add first two points to the path
|
||||
# to create the turning arcs and supports on the last segment of the loop
|
||||
if looped_path:
|
||||
railing_coords += railing_coords[:2]
|
||||
|
||||
items_3d.extend(create_supports_items(railing_coords, manual_supports=use_manual_supports))
|
||||
railing_coords = add_arcs_on_turnings_points(railing_coords)
|
||||
|
||||
if cap_type != 'NONE':
|
||||
if not looped_path and cap_type != "NONE":
|
||||
railing_coords, arc_points = add_cap(railing_coords, arc_points, start=True)
|
||||
railing_coords, arc_points = add_cap(railing_coords, arc_points, start=False)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user