mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 14:31:39 +00:00
MEP bends - support for circular profiles
Demo - https://imgur.com/a/XQBOvGz
This commit is contained in:
@@ -940,19 +940,16 @@ class MEPAddBend(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
if not types_check():
|
if not types_check():
|
||||||
self.report(
|
self.report(
|
||||||
{"ERROR"},
|
{"ERROR"},
|
||||||
"Segments types do not match " "or one of the segments doesn't have type which is required for a bend.",
|
"Segments types do not match or one of the segments doesn't have type which is required for a bend.",
|
||||||
)
|
)
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
# TODO: support circular profiles
|
|
||||||
profile = tool.Model.get_flow_segment_profile(start_element)
|
profile = tool.Model.get_flow_segment_profile(start_element)
|
||||||
if not profile.is_a("IfcRectangleProfileDef"):
|
if not profile.is_a("IfcRectangleProfileDef") and not profile.is_a("IfcCircleProfileDef"):
|
||||||
self.report(
|
self.report(
|
||||||
{
|
{"ERROR"},
|
||||||
"ERROR",
|
"For now Only IfcRectangleProfileDef/IfcCircleProfileDef profiles supported for a bend, "
|
||||||
"For now Only IfcRectangleProfileDef profiles supported for a bend, "
|
f"the segments are {profile.is_a()}",
|
||||||
f"the segments are {profile.is_a()}",
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
|||||||
@@ -1321,6 +1321,7 @@ class ShapeBuilder:
|
|||||||
# TODO: test with 0 radius
|
# TODO: test with 0 radius
|
||||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
profile = get_profile(segment)
|
profile = get_profile(segment)
|
||||||
|
is_circular_profile = profile.is_a("IfcCircleProfileDef")
|
||||||
profile_dim = get_dim(profile, start_length)
|
profile_dim = get_dim(profile, start_length)
|
||||||
|
|
||||||
rounded_offset = round_vector_to_precision(profile_offset, si_conversion)
|
rounded_offset = round_vector_to_precision(profile_offset, si_conversion)
|
||||||
@@ -1334,19 +1335,23 @@ class ShapeBuilder:
|
|||||||
# bend circle center
|
# bend circle center
|
||||||
O = V(0, 0, 0)
|
O = V(0, 0, 0)
|
||||||
O[lateral_axis] = (radius + profile_dim[lateral_axis]) * lateral_sign
|
O[lateral_axis] = (radius + profile_dim[lateral_axis]) * lateral_sign
|
||||||
|
|
||||||
theta = angle
|
theta = angle
|
||||||
|
|
||||||
def get_circle_extrusion():
|
def get_bend_representation_item():
|
||||||
# get as much segment_length segments as possible
|
if is_circular_profile:
|
||||||
segment_length = pi / 20
|
theta_segments = [0, theta / 2, theta]
|
||||||
num_segments = ceil(theta / segment_length)
|
else:
|
||||||
theta_segments = [i * segment_length for i in range(num_segments)]
|
# get as much segment_length segments as possible
|
||||||
if not is_x(theta_segments[-1], theta):
|
segment_length = pi / 20
|
||||||
theta_segments.append(theta)
|
num_segments = ceil(theta / segment_length)
|
||||||
|
theta_segments = [i * segment_length for i in range(num_segments)]
|
||||||
|
if not is_x(theta_segments[-1], theta):
|
||||||
|
theta_segments.append(theta)
|
||||||
|
|
||||||
inner_points, outer_points = [], []
|
inner_points, outer_points = [], []
|
||||||
r = radius
|
r = radius
|
||||||
|
if is_circular_profile:
|
||||||
|
r += profile_dim[lateral_axis]
|
||||||
|
|
||||||
for cur_theta in theta_segments:
|
for cur_theta in theta_segments:
|
||||||
cur_theta -= pi / 2
|
cur_theta -= pi / 2
|
||||||
@@ -1356,24 +1361,33 @@ class ShapeBuilder:
|
|||||||
inner[lateral_axis] = lateral_sign * sin(cur_theta) * r
|
inner[lateral_axis] = lateral_sign * sin(cur_theta) * r
|
||||||
inner_points.append(inner)
|
inner_points.append(inner)
|
||||||
|
|
||||||
outer = V(0, 0, 0)
|
if not is_circular_profile:
|
||||||
outer.z = z_sign * cos(cur_theta) * (r + 2 * profile_dim[lateral_axis])
|
outer = V(0, 0, 0)
|
||||||
outer[lateral_axis] = lateral_sign * sin(cur_theta) * (r + 2 * profile_dim[lateral_axis])
|
outer.z = z_sign * cos(cur_theta) * (r + 2 * profile_dim[lateral_axis])
|
||||||
outer_points.append(outer)
|
outer[lateral_axis] = lateral_sign * sin(cur_theta) * (r + 2 * profile_dim[lateral_axis])
|
||||||
|
outer_points.append(outer)
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
points = inner_points + outer_points[::-1]
|
points = inner_points + outer_points[::-1]
|
||||||
points = [p + O for p in points]
|
points = [p + O for p in points]
|
||||||
offset = V(0, 0, 0)
|
offset = V(0, 0, 0)
|
||||||
offset[non_lateral_axis] = -profile_dim[non_lateral_axis]
|
|
||||||
extrusion_vector = V(0, 0, 0)
|
|
||||||
extrusion_vector[non_lateral_axis] = 1
|
|
||||||
extrusion = self.extrude_face_set(
|
|
||||||
points, magnitude=profile_dim[non_lateral_axis] * 2, offset=offset, extrusion_vector=extrusion_vector
|
|
||||||
)
|
|
||||||
return extrusion
|
|
||||||
|
|
||||||
rep_items.append(get_circle_extrusion())
|
if is_circular_profile:
|
||||||
|
bend_path = self.polyline(points, closed=False, arc_points=[1])
|
||||||
|
bend = self.create_swept_disk_solid(bend_path, profile_dim[lateral_axis])
|
||||||
|
else:
|
||||||
|
offset[non_lateral_axis] = -profile_dim[non_lateral_axis]
|
||||||
|
extrusion_vector = V(0, 0, 0)
|
||||||
|
extrusion_vector[non_lateral_axis] = 1
|
||||||
|
bend = self.extrude_face_set(
|
||||||
|
points,
|
||||||
|
magnitude=profile_dim[non_lateral_axis] * 2,
|
||||||
|
offset=offset,
|
||||||
|
extrusion_vector=extrusion_vector,
|
||||||
|
)
|
||||||
|
return bend
|
||||||
|
|
||||||
|
rep_items.append(get_bend_representation_item())
|
||||||
body = ifcopenshell.util.representation.get_context(self.file, "Model", "Body", "MODEL_VIEW")
|
body = ifcopenshell.util.representation.get_context(self.file, "Model", "Body", "MODEL_VIEW")
|
||||||
rep = self.get_representation(body, rep_items)
|
rep = self.get_representation(body, rep_items)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user