_UNDEF definition didn't work; moving to constants.scad fixed this.

Fixed vnf.scad so that "convex" is efficient and handles degenerate
case in vnf_vertex_array
Fixed skin to correctly handle multi-section "distance" skins.
This commit is contained in:
Adrian Mariano 2021-04-14 16:32:47 -04:00
parent f2914f0efb
commit 75b974906d
4 changed files with 70 additions and 24 deletions

View file

@ -6,6 +6,7 @@
//////////////////////////////////////////////////////////////////////
// Section: Type handling helpers.
@ -322,7 +323,8 @@ function first_defined(v,recursive=false,_i=0) =
// Examples:
// length = one_defined([length,L,l], ["length","L","l"]);
// length = one_defined([length,L,l], "length,L,l", dflt=1);
function one_defined(vals, names, dflt=_UNDEF) =
function one_defined(vals, names, dflt=_UNDEF) =
let(
checkargs = is_list(names)? assert(len(vals) == len(names)) :
is_string(names)? let(
@ -533,10 +535,6 @@ function get_radius(r1, r2, r, d1, d2, d, dflt) =
// echo(f(undef, arg1="given1", undef));
// // ["given1", undef, undef]
// a value that the user should never enter randomly;
// result of `dd if=/dev/random bs=32 count=1 |base64` :
_UNDEF="LRG+HX7dy89RyHvDlAKvb9Y04OTuaikpx205CTh8BSI";
/* Note: however tempting it might be, it is *not* possible to accept
* named argument as a list [named1, named2, ...] (without default
* values), because the values [named1, named2...] themselves might be

View file

@ -5,6 +5,9 @@
// include <BOSL2/std.scad>
//////////////////////////////////////////////////////////////////////
// a value that the user should never enter randomly;
// result of `dd if=/dev/random bs=32 count=1 |base64` :
_UNDEF="LRG+HX7dy89RyHvDlAKvb9Y04OTuaikpx205CTh8BSI";
// Section: General Constants

View file

@ -5,7 +5,6 @@
// - https://github.com/openscad/list-comprehension-demos/blob/master/skin.scad
// Includes:
// include <BOSL2/std.scad>
// include <BOSL2/skin.scad>
//////////////////////////////////////////////////////////////////////
@ -465,7 +464,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
: reindex_polygon(resampled[i-1],resampled[i])],
sliced = slice_profiles(fixedprof, slices, closed)
)
!closed ? sliced : concat(sliced,[sliced[0]])
[!closed ? sliced : concat(sliced,[sliced[0]])]
: // There are duplicators, so use approach where each pair is treated separately
[for(i=[0:profcount-1])
let(
@ -482,9 +481,59 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
". Method ",method[i]," requires equal values"))
refine[i] * len(pair[0])
)
each subdivide_and_slice(pair,slices[i], nsamples, method=sampling)]
subdivide_and_slice(pair,slices[i], nsamples, method=sampling)]
)
vnf_vertex_array(full_list, cap1=fullcaps[0], cap2=fullcaps[1], col_wrap=true, style=style);
vnf_merge(cleanup=false,
[for(i=idx(full_list))
vnf_vertex_array(full_list[i], cap1=i==0 && fullcaps[0], cap2=i==len(full_list)-1 && fullcaps[1],
col_wrap=true, style=style)]);
function _skin_core(profiles, caps) =
let(
vertices = flatten(profiles),
plen = len(profiles[0]),
faces = [
for(pidx=idx(profiles,e=-2))
let(
prof1 = profiles[pidx],
prof2 = profiles[pidx+1],
voff = pidx*plen,
faces = [
for(
first = true,
finishing = false,
finished = false,
i=0, j=0, side=false;
!finished;
side =
let(
p1a = prof1[i%plen],
p1b = prof1[(i+1)%plen],
p2a = prof2[j%plen],
p2b = prof2[(j+1)%plen],
dist1 = norm(p1a-p2b),
dist2 = norm(p1b-p2a)
) (i==j) ? dist1>dist2 : i<j,
p1 = voff + (i%plen),
p2 = voff + (j%plen) + plen,
p3 = voff + (side? (i+1)%plen : (j+1)%plen + plen),
face = [p1, p3, p2],
i = i + (side? 1 : 0),
j = j + (side? 0 : 1),
first = false,
finished = finishing,
finishing = i>=plen && j>=plen
) if (!first) face
]
) each faces,
if (caps[0]) count(plen,reverse=true),
if (caps[1]) count(plen,plen*(len(profiles)-1))
]
) [vertices, faces];
@ -1419,7 +1468,7 @@ function path_sweep2d(shape, path, closed=false, caps, quality=1, style="min_edg
vnf_vertex_array([
each proflist,
if (closed) proflist[0]
],cap1=fullcaps[0],cap1=fullcaps[1],col_wrap=true,style=style);
],cap1=fullcaps[0],cap2=fullcaps[1],col_wrap=true,style=style);
module path_sweep2d(profile, path, closed=false, caps, quality=1, style="min_edge", convexity=10,

View file

@ -298,7 +298,7 @@ function vnf_vertex_array(
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","min_edge"]))
assert(is_consistent(points), "Non-rectangular or invalid point array")
assert(is_consistent(points), "Non-rectangular or invalid point array")
let(
pts = flatten(points),
pcnt = len(pts),
@ -346,22 +346,18 @@ function vnf_vertex_array(
let(
d42=norm(pts[i4]-pts[i2]),
d13=norm(pts[i1]-pts[i3]),
shortface = d42<=d13 ? [[i1,i4,i2],[i2,i4,i3]]
shortedge = d42<=d13 ? [[i1,i4,i2],[i2,i4,i3]]
: [[i1,i3,i2],[i1,i4,i3]]
)
shortface
: style=="convex"? // This style bombs on degenerate faces
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]
shortedge
: style=="convex"?
let( // Find normal for 3 of the points. Is the other point above or below?
n = (reverse?-1:1)*cross(pts[i2]-pts[i1],pts[i3]-pts[i1]),
convexfaces = n==0 ? [[i1,i4,i3]]
: n*pts[i4] > n*pts[i1] ? [[i1,i4,i2],[i2,i4,i3]]
: [[i1,i3,i2],[i1,i4,i3]]
)
fsets[test?0:1]
convexfaces
: [[i1,i3,i2],[i1,i4,i3]],
// remove degenerate faces
culled_faces= [for(face=faces)