From dea5949df8e183a7310a7c7164bbca2e87372ba4 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Mon, 12 Apr 2021 20:15:01 -0400 Subject: [PATCH] Fix face orientation bugs in vnf_vertex_array, rounded_prism, bezier_patch_degenerate. Added reverse option to count(). --- arrays.scad | 6 ++- beziers.scad | 5 +-- rounding.scad | 8 ++-- vnf.scad | 118 ++++++++++++++++++++++++-------------------------- 4 files changed, 67 insertions(+), 70 deletions(-) diff --git a/arrays.scad b/arrays.scad index ac97444..cb37111 100644 --- a/arrays.scad +++ b/arrays.scad @@ -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]; diff --git a/beziers.scad b/beziers.scad index 7cda75b..90b9790 100644 --- a/beziers.scad +++ b/beziers.scad @@ -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, [ diff --git a/rounding.scad b/rounding.scad index d2493c6..0b980b3 100644 --- a/rounding.scad +++ b/rounding.scad @@ -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, diff --git a/vnf.scad b/vnf.scad index 55095c8..abdcd8f 100644 --- a/vnf.scad +++ b/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]=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]=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],