unit() now asserts error for zero-length vector unless dflt= arg is given.

This commit is contained in:
Garth Minette 2020-07-10 00:03:55 -07:00
parent a0d8c0a5c3
commit dde616dad5
5 changed files with 53 additions and 45 deletions

View file

@ -420,12 +420,12 @@ function find_anchor(anchor, geom) =
bot = point3d(vmul(point2d(size)/2,axy),-h/2),
top = point3d(vmul(point2d(size2)/2,axy)+shift,h/2),
pos = point3d(cp) + lerp(bot,top,u) + offset,
sidevec = unit(rot(from=UP, to=top-bot, p=point3d(axy))),
sidevec = unit(rot(from=UP, to=top-bot, p=point3d(axy)),UP),
vvec = anchor==CENTER? UP : unit([0,0,anchor.z]),
vec = anchor==CENTER? UP :
approx(axy,[0,0])? unit(anchor) :
approx(axy,[0,0])? unit(anchor,UP) :
approx(anchor.z,0)? sidevec :
unit((sidevec+vvec)/2)
unit((sidevec+vvec)/2,UP)
) [anchor, pos, vec, oang]
) : type == "cyl"? ( //r1, r2, l, shift
let(
@ -433,24 +433,24 @@ function find_anchor(anchor, geom) =
r1 = is_num(rr1)? [rr1,rr1] : rr1,
r2 = is_num(rr2)? [rr2,rr2] : rr2,
u = (anchor.z+1)/2,
axy = unit(point2d(anchor)),
axy = unit(point2d(anchor),[0,0]),
bot = point3d(vmul(r1,axy), -l/2),
top = point3d(vmul(r2,axy)+shift, l/2),
pos = point3d(cp) + lerp(bot,top,u) + offset,
sidevec = rot(from=UP, to=top-bot, p=point3d(axy)),
vvec = anchor==CENTER? UP : unit([0,0,anchor.z]),
vvec = anchor==CENTER? UP : unit([0,0,anchor.z],UP),
vec = anchor==CENTER? UP :
approx(axy,[0,0])? unit(anchor) :
approx(axy,[0,0])? unit(anchor,UP) :
approx(anchor.z,0)? sidevec :
unit((sidevec+vvec)/2)
unit((sidevec+vvec)/2,UP)
) [anchor, pos, vec, oang]
) : type == "spheroid"? ( //r
let(
rr = geom[1],
r = is_num(rr)? [rr,rr,rr] : rr,
anchor = unit(point3d(anchor)),
anchor = unit(point3d(anchor),CENTER),
pos = point3d(cp) + vmul(r,anchor) + offset,
vec = unit(vmul(r,anchor))
vec = unit(vmul(r,anchor),UP)
) [anchor, pos, vec, oang]
) : type == "vnf_isect"? ( //vnf
let(
@ -490,7 +490,8 @@ function find_anchor(anchor, geom) =
faceplane = plane_from_points(faceverts),
nrm = plane_normal(faceplane)
) nrm
]) / len(nfaces)
]) / len(nfaces),
UP
)
)
[anchor, pos, n, oang]
@ -513,15 +514,15 @@ function find_anchor(anchor, geom) =
frpt = [size.x/2*anchor.x, -size.y/2],
bkpt = [size2/2*anchor.x, size.y/2],
pos = point2d(cp) + lerp(frpt, bkpt, u) + offset,
vec = unit(rot(from=BACK, to=bkpt-frpt, p=anchor))
vec = unit(rot(from=BACK, to=bkpt-frpt, p=anchor),[0,1])
) [anchor, pos, vec, 0]
) : type == "circle"? ( //r
let(
rr = geom[1],
r = is_num(rr)? [rr,rr] : rr,
pos = point2d(cp) + vmul(r,anchor) + offset,
anchor = unit(point2d(anchor)),
vec = unit(vmul([r.y,r.x],anchor))
anchor = unit(point2d(anchor),[0,0]),
vec = unit(vmul([r.y,r.x],anchor),[0,1])
) [anchor, pos, vec, 0]
) : type == "path_isect"? ( //path
let(
@ -534,7 +535,7 @@ function find_anchor(anchor, geom) =
isect = ray_segment_intersection([[0,0],anchor], seg1),
n = is_undef(isect)? [0,1] :
!approx(isect, t[1])? line_normal(seg1) :
unit((line_normal(seg1)+line_normal(seg2))/2),
unit((line_normal(seg1)+line_normal(seg2))/2,[0,1]),
n2 = vector_angle(anchor,n)>90? -n : n
)
if(!is_undef(isect) && !approx(isect,t[0])) [norm(isect), isect, n2]
@ -542,7 +543,7 @@ function find_anchor(anchor, geom) =
maxidx = max_index(subindex(isects,0)),
isect = isects[maxidx],
pos = point2d(cp) + isect[1],
vec = unit(isect[2])
vec = unit(isect[2],[0,1])
) [anchor, pos, vec, 0]
) : type == "path_extent"? ( //path
let(

View file

@ -237,8 +237,8 @@ module stroke(
} else {
quatsums = Q_Cumulative([
for (i = idx(path2,end=-2)) let(
vec1 = i==0? UP : unit(path2[i]-path2[i-1]),
vec2 = unit(path2[i+1]-path2[i]),
vec1 = i==0? UP : unit(path2[i]-path2[i-1], UP),
vec2 = unit(path2[i+1]-path2[i], UP),
axis = vector_axis(vec1,vec2),
ang = vector_angle(vec1,vec2)
) Quat(axis,ang)
@ -961,8 +961,8 @@ function regular_ngon(n=6, r, d, or, od, ir, id, side, rounding=0, realign=false
tipp = polar_to_xy(r-inset+rounding,a1),
pos = (p1+p2)/2
) each [
anchorpt(str("tip",i), tipp, unit(tipp), 0),
anchorpt(str("side",i), pos, unit(pos), 0),
anchorpt(str("tip",i), tipp, unit(tipp,BACK), 0),
anchorpt(str("side",i), pos, unit(pos,BACK), 0),
]
]
) reorient(anchor,spin, two_d=true, path=path, extent=false, p=path, anchors=anchors);
@ -983,8 +983,8 @@ module regular_ngon(n=6, r, d, or, od, ir, id, side, rounding=0, realign=false,
tipp = polar_to_xy(r-inset+rounding,a1),
pos = (p1+p2)/2
) each [
anchorpt(str("tip",i), tipp, unit(tipp), 0),
anchorpt(str("side",i), pos, unit(pos), 0),
anchorpt(str("tip",i), tipp, unit(tipp,BACK), 0),
anchorpt(str("side",i), pos, unit(pos,BACK), 0),
]
];
attachable(anchor,spin, two_d=true, path=path, extent=false, anchors=anchors) {
@ -1332,9 +1332,9 @@ function star(n, r, d, or, od, ir, id, step, realign=false, anchor=CENTER, spin=
p3 = polar_to_xy(r,a3),
pos = (p1+p3)/2
) each [
anchorpt(str("tip",i), p1, unit(p1), 0),
anchorpt(str("corner",i), p2, unit(p2), 0),
anchorpt(str("midpt",i), pos, unit(pos), 0),
anchorpt(str("tip",i), p1, unit(p1,BACK), 0),
anchorpt(str("corner",i), p2, unit(p2,BACK), 0),
anchorpt(str("midpt",i), pos, unit(pos,BACK), 0),
]
]
) reorient(anchor,spin, two_d=true, path=path, p=path, anchors=anchors);
@ -1355,9 +1355,9 @@ module star(n, r, d, or, od, ir, id, step, realign=false, anchor=CENTER, spin=0)
p3 = polar_to_xy(r,a3),
pos = (p1+p3)/2
) each [
anchorpt(str("tip",i), p1, unit(p1), 0),
anchorpt(str("corner",i), p2, unit(p2), 0),
anchorpt(str("midpt",i), pos, unit(pos), 0),
anchorpt(str("tip",i), p1, unit(p1,BACK), 0),
anchorpt(str("corner",i), p2, unit(p2,BACK), 0),
anchorpt(str("midpt",i), pos, unit(pos,BACK), 0),
]
];
attachable(anchor,spin, two_d=true, path=path, anchors=anchors) {

View file

@ -87,7 +87,7 @@ module test_line_normal() {
assert(line_normal([[0,0],[-10,0]]) == [0,-1]);
assert(line_normal([[0,0],[0,-10]]) == [1,0]);
assert(approx(line_normal([[0,0],[10,10]]), [-sqrt(2)/2,sqrt(2)/2]));
pts = [for (i=list_range(1000)) rands(-100,100,2,seed_value=4312)];
pts = [for (p=pair(rands(-100,100,1000,seed_value=4312))) p];
for (p = pair_wrap(pts)) {
p1 = p.x;
p2 = p.y;
@ -351,18 +351,18 @@ module test_tri_functions() {
opp = p.y;
hyp = norm([opp,adj]);
ang = atan2(opp,adj);
assert(approx(hyp_opp_to_adj(hyp,opp),adj));
assert(approx(hyp_ang_to_adj(hyp,ang),adj));
assert(approx(opp_ang_to_adj(opp,ang),adj));
assert(approx(hyp_adj_to_opp(hyp,adj),opp));
assert(approx(hyp_ang_to_opp(hyp,ang),opp));
assert(approx(adj_ang_to_opp(adj,ang),opp));
assert(approx(adj_opp_to_hyp(adj,opp),hyp));
assert(approx(adj_ang_to_hyp(adj,ang),hyp));
assert(approx(opp_ang_to_hyp(opp,ang),hyp));
assert(approx(hyp_adj_to_ang(hyp,adj),ang));
assert(approx(hyp_opp_to_ang(hyp,opp),ang));
assert(approx(adj_opp_to_ang(adj,opp),ang));
assert_approx(hyp_opp_to_adj(hyp,opp), adj);
assert_approx(hyp_ang_to_adj(hyp,ang), adj);
assert_approx(opp_ang_to_adj(opp,ang), adj);
assert_approx(hyp_adj_to_opp(hyp,adj), opp);
assert_approx(hyp_ang_to_opp(hyp,ang), opp);
assert_approx(adj_ang_to_opp(adj,ang), opp);
assert_approx(adj_opp_to_hyp(adj,opp), hyp);
assert_approx(adj_ang_to_hyp(adj,ang), hyp);
assert_approx(opp_ang_to_hyp(opp,ang), hyp);
assert_approx(hyp_adj_to_ang(hyp,adj), ang);
assert_approx(hyp_opp_to_ang(hyp,opp), ang);
assert_approx(adj_opp_to_ang(adj,opp), ang);
}
}
test_tri_functions();

View file

@ -105,18 +105,25 @@ function vceil(v) = [for (x=v) ceil(x)];
// Function: unit()
// Usage:
// unit(v, [dflt]);
// Description:
// Returns unit length normalized version of vector v.
// If passed a zero-length vector, returns the unchanged vector.
// Returns unit length normalized version of vector v. If passed a zero-length vector,
// asserts an error unless `dflt` is given, in which case the value of `dflt` is returned.
// Arguments:
// v = The vector to normalize.
// dflt = If given, and input is a zero-length vector, this value is returned. Default: `undef` (assert error on zero-length vector)
// Examples:
// unit([10,0,0]); // Returns: [1,0,0]
// unit([0,10,0]); // Returns: [0,1,0]
// unit([0,0,10]); // Returns: [0,0,1]
// unit([0,-10,0]); // Returns: [0,-1,0]
// unit([0,0,0]); // Returns: [0,0,0]
function unit(v) = assert(is_vector(v),str(v)) norm(v)<=EPSILON? v : v/norm(v);
// unit([0,0,0],[1,2,3]); // Returns: [1,2,3]
// unit([0,0,0]); // Asserts an error.
function unit(v, dflt) =
assert(is_vector(v), str("Expected a vector. Got: ",v))
norm(v)<EPSILON? (is_undef(dflt)? assert(norm(v)>=EPSILON) : dflt) :
v/norm(v);
// Function: vector_angle()

View file

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////////////
BOSL_VERSION = [2,0,389];
BOSL_VERSION = [2,0,390];
// Section: BOSL Library Version Functions