allow full cuboid rounding in rounded_prism; improve error checking

This commit is contained in:
Adrian Mariano 2024-02-04 12:23:11 -05:00
parent 478a5e8f16
commit 8f80872ba5

View file

@ -2026,6 +2026,11 @@ function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
// joint_top[1] is negative the shape will flare upward. At least one value must be non-negative. The same rules apply for joint_bot.
// The joint_sides parameter must be entirely nonnegative.
// .
// If the roundings at two adjacent side edges exceed the width of the face then the polyhedron will have self-intersecting faces, so it will be invalid.
// Similarly, if the roundings on the top or bottom edges cross the top face and intersect with each other, the resulting polyhedron is invalid:
// the top face after the roundings are applied must be a valid, non-degenerate polyhedron. There are two exceptions: it is permissible to
// construct a top that is a single point or two points. This means you can completely round a cube by setting the joint to half of
// the cube's width.
// If you set `debug` to true the module version will display the polyhedron even when it is invalid and it will show the bezier patches at the corners.
// This can help troubleshoot problems with your parameters. With the function form setting debug to true causes it to return [patches,vnf] where
// patches is a list of the bezier control points for the corner patches.
@ -2210,23 +2215,44 @@ function rounded_prism(bottom, top, joint_bot=0, joint_top=0, joint_sides=0, k_b
bot_patch = _rp_compute_patches(bottom, top, joint_bot, joint_sides_vec, k_bot, k_sides_vec, concave),
vertbad = [for(i=[0:N-1])
if (norm(top[i]-top_patch[i][4][2]) + norm(bottom[i]-bot_patch[i][4][2]) > norm(bottom[i]-top[i])) i],
if (norm(top[i]-top_patch[i][4][2]) + norm(bottom[i]-bot_patch[i][4][2]) > EPSILON + norm(bottom[i]-top[i])) i],
// Check that the patch fits on the polygon edge
topbad = [for(i=[0:N-1])
if (norm(top_patch[i][2][4]-top_patch[i][2][2]) + norm(select(top_patch,i+1)[2][0]-select(top_patch,i+1)[2][2])
> norm(top_patch[i][2][2] - select(top_patch,i+1)[2][2])) [i,(i+1)%N]],
> EPSILON + norm(top_patch[i][2][2] - select(top_patch,i+1)[2][2])) [i,(i+1)%N]],
botbad = [for(i=[0:N-1])
if (norm(bot_patch[i][2][4]-bot_patch[i][2][2]) + norm(select(bot_patch,i+1)[2][0]-select(bot_patch,i+1)[2][2])
> norm(bot_patch[i][2][2] - select(bot_patch,i+1)[2][2])) [i,(i+1)%N]],
topinbad = [for(i=[0:N-1])
> EPSILON + norm(bot_patch[i][2][2] - select(bot_patch,i+1)[2][2])) [i,(i+1)%N]],
// If top/bot is L-shaped, check that arms of L from adjacent patches don't cross
topLbad = [for(i=[0:N-1])
if (norm(top_patch[i][0][2]-top_patch[i][0][4]) + norm(select(top_patch,i+1)[0][0]-select(top_patch,i+1)[0][2])
> norm(top_patch[i][0][2]-select(top_patch,i+1)[0][2])) [i,(i+1)%N]],
botinbad = [for(i=[0:N-1])
> EPSILON + norm(top_patch[i][0][2]-select(top_patch,i+1)[0][2])) [i,(i+1)%N]],
botLbad = [for(i=[0:N-1])
if (norm(bot_patch[i][0][2]-bot_patch[i][0][4]) + norm(select(bot_patch,i+1)[0][0]-select(bot_patch,i+1)[0][2])
> norm(bot_patch[i][0][2]-select(bot_patch,i+1)[0][2])) [i,(i+1)%N]]
> EPSILON + norm(bot_patch[i][0][2]-select(bot_patch,i+1)[0][2])) [i,(i+1)%N]],
// Check that the inner edges of the patch don't cross
topinbad = [for(i=[0:N-1])
let(
line1 = project_plane(top,[top_patch[i][2][0],top_patch[i][0][0]]),
line2 = project_plane(top,[select(top_patch,i+1)[2][4],select(top_patch,i+1)[0][4]])
)
if (!approx(line1[0],line1[1]) && !approx(line2[0],line2[1]) &&
line_intersection(line1,line2, SEGMENT,SEGMENT))
[i,(i+1)%N]],
botinbad = [for(i=[0:N-1])
let(
line1 = project_plane(bottom,[bot_patch[i][2][0],bot_patch[i][0][0]]),
line2 = project_plane(bottom,[select(bot_patch,i+1)[2][4],select(bot_patch,i+1)[0][4]])
)
if (!approx(line1[0],line1[1]) && !approx(line2[0],line2[1]) &&
line_intersection(line1,line2, SEGMENT,SEGMENT))
[i,(i+1)%N]]
)
assert(debug || vertbad==[], str("Top and bottom joint lengths are too large; they interfere with each other at vertices: ",vertbad))
assert(debug || topbad==[], str("Joint lengths too large at top edges: ",topbad))
assert(debug || botbad==[], str("Joint lengths too large at bottom edges: ",botbad))
assert(debug || topbad==[], str("Joint lengths too large at top or side edges: ",topbad))
assert(debug || botbad==[], str("Joint lengths too large at bottom or side edges: ",botbad))
assert(debug || topLbad==[], str("Joint length too large on the top face or side at edges: ", topLbad))
assert(debug || botLbad==[], str("Joint length too large on the bottom face or side at edges: ", botLbad))
assert(debug || topinbad==[], str("Joint length too large on the top face at edges: ", topinbad))
assert(debug || botinbad==[], str("Joint length too large on the bottom face at edges: ", botinbad))
let(
@ -2256,8 +2282,12 @@ function rounded_prism(bottom, top, joint_bot=0, joint_top=0, joint_sides=0, k_b
top_patch[i][4][4]
]
],
top_simple = is_path_simple(project_plane(faces[0],faces[0]),closed=true),
bot_simple = is_path_simple(project_plane(faces[1],faces[1]),closed=true),
top_collinear = is_collinear(faces[0]),
bot_collinear = is_collinear(faces[1]),
top_degen_ok = top_collinear && len(deduplicate(faces[0]))<=2,
bot_degen_ok = bot_collinear && len(deduplicate(faces[1]))<=2,
top_simple = top_degen_ok || (!top_collinear && is_path_simple(project_plane(faces[0],faces[0]),closed=true)),
bot_simple = bot_degen_ok || (!bot_collinear && is_path_simple(project_plane(faces[1],faces[1]),closed=true)),
// verify vertical edges
verify_vert =
[for(i=[0:N-1],j=[0:4])