mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-28 23:39:36 +00:00
Fix face orientation bugs in vnf_vertex_array, rounded_prism,
bezier_patch_degenerate. Added reverse option to count().
This commit is contained in:
parent
d4d5794ef2
commit
dea5949df8
4 changed files with 67 additions and 70 deletions
|
@ -425,11 +425,15 @@ function repeat(val, n, i=0) =
|
|||
// n = The length of the list of numbers to create.
|
||||
// s = The starting value of the list of numbers.
|
||||
// step = The amount to increment successive numbers in the list.
|
||||
// reverse = Reverse the list. Default: false.
|
||||
// Example:
|
||||
// nl1 = count(5); // Returns: [0,1,2,3,4]
|
||||
// nl2 = count(5,3); // Returns: [3,4,5,6,7]
|
||||
// nl3 = count(4,3,2); // Returns: [3,5,7,9]
|
||||
function count(n,s=0,step=1) = [for (i=[0:1:n-1]) s+i*step];
|
||||
// nl4 = count(5,reverse=true); // Returns: [4,3,2,1,0]
|
||||
// nl5 = count(5,3,reverse=true); // Returns: [7,6,5,4,3]
|
||||
function count(n,s=0,step=1,reverse=false) = reverse? [for (i=[n-1:-1:0]) s+i*step]
|
||||
: [for (i=[0:1:n-1]) s+i*step];
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1328,7 +1328,6 @@ function bezier_patch_degenerate(patch, splinesteps=16, reverse=false, return_ed
|
|||
let(
|
||||
row_degen = [for(row=patch) all_equal(row)],
|
||||
col_degen = [for(col=transpose(patch)) all_equal(col)],
|
||||
|
||||
top_degen = row_degen[0],
|
||||
bot_degen = last(row_degen),
|
||||
left_degen = col_degen[0],
|
||||
|
@ -1362,7 +1361,7 @@ function bezier_patch_degenerate(patch, splinesteps=16, reverse=false, return_ed
|
|||
for(j=[0:splinesteps-2]) bezier_points(subindex(bpatch,j+1), lerpn(0,1,rowcount[j])),
|
||||
[last(bpatch[0])]
|
||||
],
|
||||
vnf = vnf_tri_array(pts, reverse=reverse)
|
||||
vnf = vnf_tri_array(pts, reverse=!reverse)
|
||||
) [
|
||||
vnf,
|
||||
[
|
||||
|
@ -1390,7 +1389,7 @@ function bezier_patch_degenerate(patch, splinesteps=16, reverse=false, return_ed
|
|||
[bpatch[0][0]],
|
||||
for(j=[1:splinesteps]) bezier_points(subindex(bpatch,j), lerpn(0,1,rowmax[j]+1))
|
||||
],
|
||||
vnf = vnf_tri_array(pts, reverse=reverse)
|
||||
vnf = vnf_tri_array(pts, reverse=!reverse)
|
||||
) [
|
||||
vnf,
|
||||
[
|
||||
|
|
|
@ -1779,8 +1779,8 @@ function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
|
|||
// M = path3d(turtle(["left", 180, "length",3,"move", "left", "move", 3, "right", "move", "right", "move", 4, "right", "move", 3, "right", "move", 2]));
|
||||
// rounded_prism(M, apply(right(1)*scale(.75)*up(3),M), joint_top=0.5, joint_bot=0.2, joint_sides=[.2,1,1,0.5,1.5,.5,2], splinesteps=32);
|
||||
// Example: this example shows most of the different types of patches that rounded_prism creates. Note that some of the patches are close to interfering with each other across the top of the polyhedron, which would create an invalid result.
|
||||
N = apply(rot(180)*yscale(.8),turtle(["length",3,"left", "move", 2, "right", 135, "move", sqrt(2), "left", "move", sqrt(2), "right", 135, "move", 2]));
|
||||
rounded_prism(N, height=3, joint_bot=0.5, joint_top=1.25, joint_sides=[[1,1.75],0,.5,.5,2], debug=true);
|
||||
// N = apply(rot(180)*yscale(.8),turtle(["length",3,"left", "move", 2, "right", 135, "move", sqrt(2), "left", "move", sqrt(2), "right", 135, "move", 2]));
|
||||
// rounded_prism(N, height=3, joint_bot=0.5, joint_top=1.25, joint_sides=[[1,1.75],0,.5,.5,2], debug=true);
|
||||
// Example: This object has different scales on its different axies. Here is the largest symmetric rounding that fits. Note that the rounding is slightly smaller than the object dimensions because of roundoff error.
|
||||
// rounded_prism(square([100.1,30.1]), height=8.1, joint_top=4, joint_bot=4, joint_sides=15, k_sides=0.3, splinesteps=32);
|
||||
// Example: Using asymetric rounding enables a much more rounded form:
|
||||
|
@ -1886,8 +1886,8 @@ function rounded_prism(bottom, top, joint_bot=0, joint_top=0, joint_sides=0, k_b
|
|||
let(
|
||||
// Entries in the next two lists have the form [edges, vnf] where
|
||||
// edges is a list [leftedge, rightedge, topedge, botedge]
|
||||
top_samples = [for(patch=top_patch) bezier_patch_degenerate(patch,splinesteps,reverse=true,return_edges=true) ],
|
||||
bot_samples = [for(patch=bot_patch) bezier_patch_degenerate(patch,splinesteps,reverse=false,return_edges=true) ],
|
||||
top_samples = [for(patch=top_patch) bezier_patch_degenerate(patch,splinesteps,reverse=false,return_edges=true) ],
|
||||
bot_samples = [for(patch=bot_patch) bezier_patch_degenerate(patch,splinesteps,reverse=true,return_edges=true) ],
|
||||
leftidx=0,
|
||||
rightidx=1,
|
||||
topidx=2,
|
||||
|
|
118
vnf.scad
118
vnf.scad
|
@ -287,83 +287,77 @@ function vnf_vertex_array(
|
|||
reverse=false,
|
||||
style="default",
|
||||
vnf=EMPTY_VNF
|
||||
) =
|
||||
assert((!caps)||(caps&&col_wrap))
|
||||
) =
|
||||
assert(!(any([caps,cap1,cap2]) && !col_wrap), "col_wrap must be true if caps are requested")
|
||||
assert(!(any([caps,cap1,cap2]) && row_wrap), "Cannot combine caps with row_wrap")
|
||||
assert(in_list(style,["default","alt","quincunx", "convex"]))
|
||||
assert(is_consistent(points), "Non-rectangular or invalid point array")
|
||||
let(
|
||||
pts = flatten(points),
|
||||
pcnt = len(pts),
|
||||
rows = len(points),
|
||||
cols = len(points[0]),
|
||||
cols = len(points[0])
|
||||
)
|
||||
rows<=1 || cols<=1 ? vnf :
|
||||
let(
|
||||
cap1 = first_defined([cap1,caps,false]),
|
||||
cap2 = first_defined([cap2,caps,false]),
|
||||
colcnt = cols - (col_wrap?0:1),
|
||||
rowcnt = rows - (row_wrap?0:1),
|
||||
verts = [
|
||||
each pts,
|
||||
if (style=="quincunx") (
|
||||
for (r = [0:1:rowcnt-1]) (
|
||||
for (c = [0:1:colcnt-1]) (
|
||||
let(
|
||||
i1 = ((r+0)%rows)*cols + ((c+0)%cols),
|
||||
i2 = ((r+1)%rows)*cols + ((c+0)%cols),
|
||||
i3 = ((r+1)%rows)*cols + ((c+1)%cols),
|
||||
i4 = ((r+0)%rows)*cols + ((c+1)%cols)
|
||||
) mean([pts[i1], pts[i2], pts[i3], pts[i4]])
|
||||
)
|
||||
)
|
||||
)
|
||||
if (style=="quincunx")
|
||||
for (r = [0:1:rowcnt-1], c = [0:1:colcnt-1])
|
||||
let(
|
||||
i1 = ((r+0)%rows)*cols + ((c+0)%cols),
|
||||
i2 = ((r+1)%rows)*cols + ((c+0)%cols),
|
||||
i3 = ((r+1)%rows)*cols + ((c+1)%cols),
|
||||
i4 = ((r+0)%rows)*cols + ((c+1)%cols)
|
||||
)
|
||||
mean([pts[i1], pts[i2], pts[i3], pts[i4]])
|
||||
]
|
||||
)
|
||||
rows<=1 || cols<=1 ? vnf :
|
||||
vnf_merge(cleanup=true, [
|
||||
vnf, [
|
||||
verts,
|
||||
concat(
|
||||
[
|
||||
for (r = [0:1:rowcnt-1]) (
|
||||
for (c = [0:1:colcnt-1]) each (
|
||||
let(
|
||||
i1 = ((r+0)%rows)*cols + ((c+0)%cols),
|
||||
i2 = ((r+1)%rows)*cols + ((c+0)%cols),
|
||||
i3 = ((r+1)%rows)*cols + ((c+1)%cols),
|
||||
i4 = ((r+0)%rows)*cols + ((c+1)%cols),
|
||||
faces = style=="quincunx"? (
|
||||
let(i5 = pcnt + r*colcnt + c)
|
||||
[[i1,i5,i2],[i2,i5,i3],[i3,i5,i4],[i4,i5,i1]]
|
||||
) : style=="alt"? (
|
||||
[[i1,i4,i2],[i2,i4,i3]]
|
||||
) : style=="convex"? let(
|
||||
fsets = [
|
||||
[[i1,i4,i2],[i2,i4,i3]],
|
||||
[[i1,i3,i2],[i1,i4,i3]]
|
||||
],
|
||||
cps = [for (fset=fsets) [for (f=fset) mean(select(pts,f))]],
|
||||
ns = cps + [for (fset=fsets) [for (f=fset) polygon_normal(select(pts,f))]],
|
||||
dists = [for (i=idx(fsets)) norm(cps[i][1]-cps[i][0]) - norm(ns[i][1]-ns[i][0])],
|
||||
test = reverse? dists[0]>dists[1] : dists[0]<dists[1]
|
||||
) fsets[test?0:1] : (
|
||||
[[i1,i3,i2],[i1,i4,i3]]
|
||||
),
|
||||
rfaces = reverse? [for (face=faces) reverse(face)] : faces,
|
||||
ffaces = [for (face=rfaces) if(len(deduplicate_indexed(verts,face,closed=true))>=3) face]
|
||||
) faces
|
||||
)
|
||||
)
|
||||
],
|
||||
!cap1? [] : [
|
||||
reverse?
|
||||
[for (c = [0:1:cols-1]) c] :
|
||||
[for (c = [cols-1:-1:0]) c]
|
||||
],
|
||||
!cap2? [] : [
|
||||
reverse?
|
||||
[for (c = [cols-1:-1:0]) (rows-1)*cols + c] :
|
||||
[for (c = [0:1:cols-1]) (rows-1)*cols + c]
|
||||
]
|
||||
)
|
||||
]
|
||||
verts,
|
||||
[
|
||||
for (r = [0:1:rowcnt-1], c=[0:1:colcnt-1])
|
||||
each
|
||||
let(
|
||||
i1 = ((r+0)%rows)*cols + ((c+0)%cols),
|
||||
i2 = ((r+1)%rows)*cols + ((c+0)%cols),
|
||||
i3 = ((r+1)%rows)*cols + ((c+1)%cols),
|
||||
i4 = ((r+0)%rows)*cols + ((c+1)%cols),
|
||||
faces =
|
||||
style=="quincunx"?
|
||||
let(i5 = pcnt + r*colcnt + c)
|
||||
[[i1,i5,i2],[i2,i5,i3],[i3,i5,i4],[i4,i5,i1]]
|
||||
: style=="alt"?
|
||||
[[i1,i4,i2],[i2,i4,i3]]
|
||||
: style=="convex"?
|
||||
let(
|
||||
fsets = [
|
||||
[[i1,i4,i2],[i2,i4,i3]],
|
||||
[[i1,i3,i2],[i1,i4,i3]]
|
||||
],
|
||||
cps = [for (fset=fsets) [for (f=fset) mean(select(pts,f))]],
|
||||
ns = cps + [for (fset=fsets) [for (f=fset) polygon_normal(select(pts,f))]],
|
||||
dists = [for (i=idx(fsets)) norm(cps[i][1]-cps[i][0]) - norm(ns[i][1]-ns[i][0])],
|
||||
test = reverse? dists[0]>dists[1] : dists[0]<dists[1]
|
||||
)
|
||||
fsets[test?0:1]
|
||||
: [[i1,i3,i2],[i1,i4,i3]],
|
||||
rfaces = reverse? [for (face=faces) reverse(face)] : faces,
|
||||
dfaces = [for (face=rfaces)
|
||||
let(dface = deduplicate_indexed(verts,face,closed=true))
|
||||
if(len(dface)>=3) dface
|
||||
]
|
||||
)
|
||||
dfaces,
|
||||
if (cap1) count(cols,reverse=!reverse),
|
||||
if (cap2) count(cols,(rows-1)*cols, reverse=reverse)
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
|
||||
|
@ -435,7 +429,7 @@ function vnf_tri_array(points, row_wrap=false, reverse=false, vnf=EMPTY_VNF) =
|
|||
for(j=[0:1:count]) reverse ? [j+rowstart, j+nextrow, j+nextrow+1] : [j+rowstart, j+nextrow+1, j+nextrow], // bot triangles left
|
||||
for(j=[count+1:1:select(lens,i+1)-2]) reverse ? [j+rowstart-1, j+nextrow, j+nextrow+1] : [j+rowstart-1, j+nextrow+1, j+nextrow], // bot triangles right
|
||||
] :
|
||||
delta == -2 ?
|
||||
delta == -2 ?
|
||||
[
|
||||
for(j=[0:1:count-2]) reverse ? [j+nextrow, j+nextrow+1, j+rowstart+1] : [j+nextrow, j+rowstart+1, j+nextrow+1],
|
||||
for(j=[count-1:1:lens[i]-4]) reverse ? [j+nextrow,j+nextrow+1,j+rowstart+2] : [j+nextrow,j+rowstart+2, j+nextrow+1],
|
||||
|
|
Loading…
Reference in a new issue