mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
d2e851ae42
35 changed files with 287 additions and 127 deletions
|
@ -277,9 +277,9 @@ function affine_frame_map(x,y,z, reverse=false) =
|
|||
assert(yvalid,"Input y must be a length 3 vector")
|
||||
assert(zvalid,"Input z must be a length 3 vector")
|
||||
let(
|
||||
x = is_undef(x)? undef : unit(x),
|
||||
y = is_undef(y)? undef : unit(y),
|
||||
z = is_undef(z)? undef : unit(z),
|
||||
x = is_undef(x)? undef : unit(x,RIGHT),
|
||||
y = is_undef(y)? undef : unit(y,BACK),
|
||||
z = is_undef(z)? undef : unit(z,UP),
|
||||
map = is_undef(x)? [cross(y,z), y, z] :
|
||||
is_undef(y)? [x, cross(z,x), z] :
|
||||
is_undef(z)? [x, y, cross(x,y)] :
|
||||
|
|
14
arrays.scad
14
arrays.scad
|
@ -104,21 +104,13 @@ function slice(list,start,end) =
|
|||
// in_list("bar", ["foo", "bar", "baz"]); // Returns true.
|
||||
// in_list("bee", ["foo", "bar", "baz"]); // Returns false.
|
||||
// in_list("bar", [[2,"foo"], [4,"bar"], [3,"baz"]], idx=1); // Returns true.
|
||||
// in_list("bee", ["foo", "bar", ["bee",0]]); // Returns true.
|
||||
// in_list("bar", [[2,"foo"], [4,["bar"]], [3,"baz"]]); // Returns false.
|
||||
// Note:
|
||||
// When `val==NAN` the answer will be false for any list.
|
||||
// `val` cannot be a boolean.
|
||||
// When the some element in `list` is a list containing `val` at it first element, the return is also true.
|
||||
|
||||
function in_list(val,list,idx=undef) =
|
||||
let( s = search([val], list, num_returns_per_match=1, index_col_num=idx)[0] )
|
||||
s==[] || s[0]==[] ? false
|
||||
s==[] ? false
|
||||
: is_undef(idx) ? val==list[s]
|
||||
: val==list[s][idx];
|
||||
|
||||
//***
|
||||
// 1. for sake of consistence, the arguments were changed to val and list
|
||||
// 2. in_list(0,[ 1, [0,1],2])) was returning true
|
||||
|
||||
|
||||
|
||||
// Function: min_index()
|
||||
|
|
|
@ -421,7 +421,7 @@ function find_anchor(anchor, geom) =
|
|||
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)),UP),
|
||||
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,UP) :
|
||||
approx(anchor.z,0)? sidevec :
|
||||
|
|
17
debug.scad
17
debug.scad
|
@ -191,16 +191,17 @@ module debug_faces(vertices, faces, size=1, disabled=false) {
|
|||
if (face[0] < 0 || face[1] < 0 || face[2] < 0 || face[0] >= vlen || face[1] >= vlen || face[2] >= vlen) {
|
||||
echo("BAD FACE: ", vlen=vlen, face=face);
|
||||
} else {
|
||||
v0 = vertices[face[0]];
|
||||
v1 = vertices[face[1]];
|
||||
v2 = vertices[face[2]];
|
||||
c = mean(select(vertices,face));
|
||||
verts = select(vertices,face);
|
||||
c = mean(verts);
|
||||
v0 = verts[0];
|
||||
v1 = verts[1];
|
||||
v2 = verts[2];
|
||||
dv0 = unit(v1 - v0);
|
||||
dv1 = unit(v2 - v0);
|
||||
nrm0 = unit(cross(dv0, dv1));
|
||||
nrm1 = [0, 0, 1];
|
||||
axis = unit(cross(nrm0, nrm1));
|
||||
ang = vector_angle(nrm0, nrm1);
|
||||
nrm0 = cross(dv0, dv1);
|
||||
nrm1 = UP;
|
||||
axis = vector_axis(nrm0, nrm1);
|
||||
ang = vector_angle(nrm0, nrm1);
|
||||
theta = atan2(nrm0[1], nrm0[0]);
|
||||
translate(c) {
|
||||
rotate(a=180-ang, v=axis) {
|
||||
|
|
185
geometry.scad
185
geometry.scad
|
@ -133,8 +133,9 @@ function distance_from_line(line, pt) =
|
|||
// color("green") stroke([p1,p1+10*n], endcap2="arrow2");
|
||||
// color("blue") move_copies([p1,p2]) circle(d=2, $fn=12);
|
||||
function line_normal(p1,p2) =
|
||||
is_undef(p2)? line_normal(p1[0],p1[1]) :
|
||||
unit([p1.y-p2.y,p2.x-p1.x]);
|
||||
is_undef(p2)?
|
||||
assert(is_path(p1,2)) line_normal(p1[0],p1[1]) :
|
||||
assert(is_vector(p1,2)&&is_vector(p2,2)) unit([p1.y-p2.y,p2.x-p1.x]);
|
||||
|
||||
|
||||
// 2D Line intersection from two segments.
|
||||
|
@ -252,34 +253,192 @@ function segment_intersection(s1,s2,eps=EPSILON) =
|
|||
// Usage:
|
||||
// line_closest_point(line,pt);
|
||||
// Description:
|
||||
// Returns the point on the given `line` that is closest to the given point `pt`.
|
||||
// Returns the point on the given 2D or 3D `line` that is closest to the given point `pt`.
|
||||
// The `line` and `pt` args should either both be 2D or both 3D.
|
||||
// Arguments:
|
||||
// line = A list of two points that are on the unbounded line.
|
||||
// pt = The point to find the closest point on the line to.
|
||||
// Example(2D):
|
||||
// line = [[-30,0],[30,30]];
|
||||
// pt = [-32,-10];
|
||||
// p2 = line_closest_point(line,pt);
|
||||
// stroke(line, endcaps="arrow2");
|
||||
// color("blue") translate(pt) circle(r=1,$fn=12);
|
||||
// color("red") translate(p2) circle(r=1,$fn=12);
|
||||
// Example(2D):
|
||||
// line = [[-30,0],[30,30]];
|
||||
// pt = [-5,0];
|
||||
// p2 = line_closest_point(line,pt);
|
||||
// stroke(line, endcaps="arrow2");
|
||||
// color("blue") translate(pt) circle(r=1,$fn=12);
|
||||
// color("red") translate(p2) circle(r=1,$fn=12);
|
||||
// Example(2D):
|
||||
// line = [[-30,0],[30,30]];
|
||||
// pt = [40,25];
|
||||
// p2 = line_closest_point(line,pt);
|
||||
// stroke(line, endcaps="arrow2");
|
||||
// color("blue") translate(pt) circle(r=1,$fn=12);
|
||||
// color("red") translate(p2) circle(r=1,$fn=12);
|
||||
// Example(FlatSpin):
|
||||
// line = [[-30,-15,0],[30,15,30]];
|
||||
// pt = [5,5,5];
|
||||
// p2 = line_closest_point(line,pt);
|
||||
// stroke(line, endcaps="arrow2");
|
||||
// color("blue") translate(pt) sphere(r=1,$fn=12);
|
||||
// color("red") translate(p2) sphere(r=1,$fn=12);
|
||||
// Example(FlatSpin):
|
||||
// line = [[-30,-15,0],[30,15,30]];
|
||||
// pt = [-35,-15,0];
|
||||
// p2 = line_closest_point(line,pt);
|
||||
// stroke(line, endcaps="arrow2");
|
||||
// color("blue") translate(pt) sphere(r=1,$fn=12);
|
||||
// color("red") translate(p2) sphere(r=1,$fn=12);
|
||||
// Example(FlatSpin):
|
||||
// line = [[-30,-15,0],[30,15,30]];
|
||||
// pt = [40,15,25];
|
||||
// p2 = line_closest_point(line,pt);
|
||||
// stroke(line, endcaps="arrow2");
|
||||
// color("blue") translate(pt) sphere(r=1,$fn=12);
|
||||
// color("red") translate(p2) sphere(r=1,$fn=12);
|
||||
function line_closest_point(line,pt) =
|
||||
assert(is_path(line)&&len(line)==2)
|
||||
assert(same_shape(pt,line[0]))
|
||||
assert(!approx(line[0],line[1]))
|
||||
let(
|
||||
n = line_normal(line),
|
||||
isect = _general_line_intersection(line,[pt,pt+n])
|
||||
) isect[0];
|
||||
seglen = norm(line[1]-line[0]),
|
||||
segvec = (line[1]-line[0])/seglen,
|
||||
projection = (pt-line[0]) * segvec
|
||||
)
|
||||
line[0] + projection*segvec;
|
||||
|
||||
|
||||
// Function: ray_closest_point()
|
||||
// Usage:
|
||||
// ray_closest_point(seg,pt);
|
||||
// Description:
|
||||
// Returns the point on the given 2D or 3D ray `ray` that is closest to the given point `pt`.
|
||||
// The `ray` and `pt` args should either both be 2D or both 3D.
|
||||
// Arguments:
|
||||
// ray = The ray, given as a list `[START,POINT]` of the start-point START, and a point POINT on the ray.
|
||||
// pt = The point to find the closest point on the ray to.
|
||||
// Example(2D):
|
||||
// ray = [[-30,0],[30,30]];
|
||||
// pt = [-32,-10];
|
||||
// p2 = ray_closest_point(ray,pt);
|
||||
// stroke(ray, endcap2="arrow2");
|
||||
// color("blue") translate(pt) circle(r=1,$fn=12);
|
||||
// color("red") translate(p2) circle(r=1,$fn=12);
|
||||
// Example(2D):
|
||||
// ray = [[-30,0],[30,30]];
|
||||
// pt = [-5,0];
|
||||
// p2 = ray_closest_point(ray,pt);
|
||||
// stroke(ray, endcap2="arrow2");
|
||||
// color("blue") translate(pt) circle(r=1,$fn=12);
|
||||
// color("red") translate(p2) circle(r=1,$fn=12);
|
||||
// Example(2D):
|
||||
// ray = [[-30,0],[30,30]];
|
||||
// pt = [40,25];
|
||||
// p2 = ray_closest_point(ray,pt);
|
||||
// stroke(ray, endcap2="arrow2");
|
||||
// color("blue") translate(pt) circle(r=1,$fn=12);
|
||||
// color("red") translate(p2) circle(r=1,$fn=12);
|
||||
// Example(FlatSpin):
|
||||
// ray = [[-30,-15,0],[30,15,30]];
|
||||
// pt = [5,5,5];
|
||||
// p2 = ray_closest_point(ray,pt);
|
||||
// stroke(ray, endcap2="arrow2");
|
||||
// color("blue") translate(pt) sphere(r=1,$fn=12);
|
||||
// color("red") translate(p2) sphere(r=1,$fn=12);
|
||||
// Example(FlatSpin):
|
||||
// ray = [[-30,-15,0],[30,15,30]];
|
||||
// pt = [-35,-15,0];
|
||||
// p2 = ray_closest_point(ray,pt);
|
||||
// stroke(ray, endcap2="arrow2");
|
||||
// color("blue") translate(pt) sphere(r=1,$fn=12);
|
||||
// color("red") translate(p2) sphere(r=1,$fn=12);
|
||||
// Example(FlatSpin):
|
||||
// ray = [[-30,-15,0],[30,15,30]];
|
||||
// pt = [40,15,25];
|
||||
// p2 = ray_closest_point(ray,pt);
|
||||
// stroke(ray, endcap2="arrow2");
|
||||
// color("blue") translate(pt) sphere(r=1,$fn=12);
|
||||
// color("red") translate(p2) sphere(r=1,$fn=12);
|
||||
function ray_closest_point(ray,pt) =
|
||||
assert(is_path(ray)&&len(ray)==2)
|
||||
assert(same_shape(pt,ray[0]))
|
||||
assert(!approx(ray[0],ray[1]))
|
||||
let(
|
||||
seglen = norm(ray[1]-ray[0]),
|
||||
segvec = (ray[1]-ray[0])/seglen,
|
||||
projection = (pt-ray[0]) * segvec
|
||||
)
|
||||
projection<=0 ? ray[0] :
|
||||
ray[0] + projection*segvec;
|
||||
|
||||
|
||||
// Function: segment_closest_point()
|
||||
// Usage:
|
||||
// segment_closest_point(seg,pt);
|
||||
// Description:
|
||||
// Returns the point on the given line segment `seg` that is closest to the given point `pt`.
|
||||
// Returns the point on the given 2D or 3D line segment `seg` that is closest to the given point `pt`.
|
||||
// The `seg` and `pt` args should either both be 2D or both 3D.
|
||||
// Arguments:
|
||||
// seg = A list of two points that are the endpoints of the bounded line segment.
|
||||
// pt = The point to find the closest point on the segment to.
|
||||
// Example(2D):
|
||||
// seg = [[-30,0],[30,30]];
|
||||
// pt = [-32,-10];
|
||||
// p2 = segment_closest_point(seg,pt);
|
||||
// stroke(seg);
|
||||
// color("blue") translate(pt) circle(r=1,$fn=12);
|
||||
// color("red") translate(p2) circle(r=1,$fn=12);
|
||||
// Example(2D):
|
||||
// seg = [[-30,0],[30,30]];
|
||||
// pt = [-5,0];
|
||||
// p2 = segment_closest_point(seg,pt);
|
||||
// stroke(seg);
|
||||
// color("blue") translate(pt) circle(r=1,$fn=12);
|
||||
// color("red") translate(p2) circle(r=1,$fn=12);
|
||||
// Example(2D):
|
||||
// seg = [[-30,0],[30,30]];
|
||||
// pt = [40,25];
|
||||
// p2 = segment_closest_point(seg,pt);
|
||||
// stroke(seg);
|
||||
// color("blue") translate(pt) circle(r=1,$fn=12);
|
||||
// color("red") translate(p2) circle(r=1,$fn=12);
|
||||
// Example(FlatSpin):
|
||||
// seg = [[-30,-15,0],[30,15,30]];
|
||||
// pt = [5,5,5];
|
||||
// p2 = segment_closest_point(seg,pt);
|
||||
// stroke(seg);
|
||||
// color("blue") translate(pt) sphere(r=1,$fn=12);
|
||||
// color("red") translate(p2) sphere(r=1,$fn=12);
|
||||
// Example(FlatSpin):
|
||||
// seg = [[-30,-15,0],[30,15,30]];
|
||||
// pt = [-35,-15,0];
|
||||
// p2 = segment_closest_point(seg,pt);
|
||||
// stroke(seg);
|
||||
// color("blue") translate(pt) sphere(r=1,$fn=12);
|
||||
// color("red") translate(p2) sphere(r=1,$fn=12);
|
||||
// Example(FlatSpin):
|
||||
// seg = [[-30,-15,0],[30,15,30]];
|
||||
// pt = [40,15,25];
|
||||
// p2 = segment_closest_point(seg,pt);
|
||||
// stroke(seg);
|
||||
// color("blue") translate(pt) sphere(r=1,$fn=12);
|
||||
// color("red") translate(p2) sphere(r=1,$fn=12);
|
||||
function segment_closest_point(seg,pt) =
|
||||
assert(is_path(seg)&&len(seg)==2)
|
||||
assert(same_shape(pt,seg[0]))
|
||||
approx(seg[0],seg[1])? seg[0] :
|
||||
let(
|
||||
n = line_normal(seg),
|
||||
isect = _general_line_intersection(seg,[pt,pt+n])
|
||||
seglen = norm(seg[1]-seg[0]),
|
||||
segvec = (seg[1]-seg[0])/seglen,
|
||||
projection = (pt-seg[0]) * segvec
|
||||
)
|
||||
norm(n)==0? seg[0] :
|
||||
isect[1]<=0? seg[0] :
|
||||
isect[1]>=1? seg[1] :
|
||||
isect[0];
|
||||
projection<=0 ? seg[0] :
|
||||
projection>=seglen ? seg[1] :
|
||||
seg[0] + projection*segvec;
|
||||
|
||||
|
||||
// Section: 2D Triangles
|
||||
|
|
|
@ -159,6 +159,7 @@ include <structs.scad>
|
|||
// fwd(60) // Note how the different points are cut back by different amounts
|
||||
// stroke(round_corners(zig,radius=1.5,closed=false),width=1);
|
||||
// Example(FlatSpin): Rounding some random 3D paths
|
||||
// $fn=36;
|
||||
// list1= [
|
||||
// [2.887360, 4.03497, 6.372090],
|
||||
// [5.682210, 9.37103, 0.783548],
|
||||
|
@ -926,10 +927,10 @@ function os_profile(points, extra,check_valid, quality, offset_maxstep, offset)
|
|||
//
|
||||
// Example: Chamfered elliptical prism. If you stretch a chamfered cylinder the chamfer will be uneven.
|
||||
// convex_offset_extrude(bottom = os_chamfer(height=-2), top=os_chamfer(height=1), height=7)
|
||||
// xscale(4)circle(r=6);
|
||||
// xscale(4)circle(r=6,$fn=64);
|
||||
// Example: Elliptical prism with circular roundovers.
|
||||
// convex_offset_extrude(bottom=os_circle(r=-2), top=os_circle(r=1), height=7,steps=10)
|
||||
// xscale(4)circle(r=6);
|
||||
// xscale(4)circle(r=6,$fn=64);
|
||||
// Example: If you give a non-convex input you get a convex hull output
|
||||
// right(50) linear_extrude(height=7) star(5,r=22,ir=13);
|
||||
// convex_offset_extrude(bottom = os_chamfer(height=-2), top=os_chamfer(height=1), height=7)
|
||||
|
@ -1122,6 +1123,7 @@ function _remove_undefined_vals(list) =
|
|||
// fwd(7)
|
||||
// offset_stroke(arc, width=2, start=os_pointed(loc=2,dist=2),end=os_pointed(loc=.5,dist=-1));
|
||||
// Example(2D): The os_round() end treatment adds roundovers to the end corners by specifying the `cut` parameter. In the first example, the cut parameter is the same at each corner. The bezier smoothness parameter `k` is given to allow a larger cut. In the second example, each corner is given a different roundover, including zero for no rounding at all. The red shows the same strokes without the roundover.
|
||||
// $fn=36;
|
||||
// arc = arc(points=[[1,1],[3,4],[6,3]],N=50);
|
||||
// path = [[0,0],[6,2],[9,7],[8,10]];
|
||||
// offset_stroke(path, width=2, rounded=false,start=os_round(angle=-20, cut=0.4,k=.9), end=os_round(angle=-35, cut=0.4,k=.9));
|
||||
|
@ -1133,9 +1135,9 @@ function _remove_undefined_vals(list) =
|
|||
// Example(2D): Negative cut values produce a flaring end. Note how the absolute angle aligns the ends of the first example withi the axes. In the second example positive and negative cut values are combined. Note also that very different cuts are needed at the start end to produce a similar looking flare.
|
||||
// arc = arc(points=[[1,1],[3,4],[6,3]],N=50);
|
||||
// path = [[0,0],[6,2],[9,7],[8,10]];
|
||||
// offset_stroke(path, width=2, rounded=false,start=os_round(cut=-1, abs_angle=90), end=os_round(cut=-0.5, abs_angle=0));
|
||||
// offset_stroke(path, width=2, rounded=false,start=os_round(cut=-1, abs_angle=90), end=os_round(cut=-0.5, abs_angle=0),$fn=36);
|
||||
// right(10)
|
||||
// offset_stroke(arc, width=2, rounded=false, start=os_round(cut=[-.75,-.2], angle=-45), end=os_round(cut=[-.2,.2], angle=20));
|
||||
// offset_stroke(arc, width=2, rounded=false, start=os_round(cut=[-.75,-.2], angle=-45), end=os_round(cut=[-.2,.2], angle=20),$fn=36);
|
||||
// Example(2D): Setting the width to a vector allows generation of a set of parallel strokes
|
||||
// path = [[0,0],[4,4],[8,4],[2,9],[10,10]];
|
||||
// for(i=[0:.25:2])
|
||||
|
@ -1146,9 +1148,9 @@ function _remove_undefined_vals(list) =
|
|||
// offset_stroke(path, rounded=true,width = [i,i+.08]);
|
||||
// Example(2D): In this example a spurious triangle appears. This results from overly enthusiastic validity checking. Turning validity checking off fixes it in this case.
|
||||
// path = [[0,0],[4,4],[8,4],[2,9],[10,10]];
|
||||
// offset_stroke(path, check_valid=true,rounded=false,width = [1.4, 1.45]);
|
||||
// offset_stroke(path, check_valid=true,rounded=false,width = [1.4, 1.5]);
|
||||
// right(2)
|
||||
// offset_stroke(path, check_valid=false,rounded=false,width = [1.4, 1.45]);
|
||||
// offset_stroke(path, check_valid=false,rounded=false,width = [1.4, 1.5]);
|
||||
// Example(2D): But in this case, disabling the validity check produces an invalid result.
|
||||
// path = [[0,0],[4,4],[8,4],[2,9],[10,10]];
|
||||
// offset_stroke(path, check_valid=true,rounded=false,width = [1.9, 2]);
|
||||
|
@ -1786,7 +1788,7 @@ function _circle_mask(r) =
|
|||
// less than 180 degrees, and the path shouldn't have closely spaced points at concave points of high curvature because
|
||||
// this will cause self-intersection in the mask polyhedron, resulting in CGAL failures.
|
||||
// Arguments:
|
||||
// r|radius = center radius of the cylindrical shell to cut a hole in
|
||||
// r / radius = center radius of the cylindrical shell to cut a hole in
|
||||
// thickness = thickness of cylindrical shell (may need to be slighly oversized)
|
||||
// path = 2d path that defines the hole to cut
|
||||
// Example: The mask as long pointed ends because this was the most efficient way to close off those ends.
|
||||
|
|
|
@ -97,7 +97,7 @@ def image_compare(file1, file2):
|
|||
sq = (value * (i % 256) ** 2 for i, value in enumerate(diff))
|
||||
sum_squares = sum(sq)
|
||||
rms = math.sqrt(sum_squares / float(img1.size[0] * img1.size[1]))
|
||||
return rms<10
|
||||
return rms<2
|
||||
|
||||
|
||||
def image_resize(infile, outfile, newsize=(320,240)):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/hull.scad>
|
||||
include <../std.scad>
|
||||
include <../hull.scad>
|
||||
|
||||
|
||||
testpoints_on_sphere = [ for(p =
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include<BOSL2/std.scad>
|
||||
include<BOSL2/polyhedra.scad>
|
||||
include<../std.scad>
|
||||
include<../polyhedra.scad>
|
||||
|
||||
|
||||
$fn=96;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
module test_ident() {
|
||||
|
|
|
@ -33,9 +33,13 @@ module test_in_list() {
|
|||
assert(in_list("bar", ["foo", "bar", "baz"]));
|
||||
assert(!in_list("bee", ["foo", "bar", "baz"]));
|
||||
assert(in_list("bar", [[2,"foo"], [4,"bar"], [3,"baz"]], idx=1));
|
||||
|
||||
assert(!in_list(undef, [3,4,5]));
|
||||
assert(in_list(undef,[3,4,undef,5]));
|
||||
assert(!in_list(3,[]));
|
||||
assert(!in_list(3,[4,5,[3]]));
|
||||
|
||||
assert(!in_list("bee", ["foo", "bar", ["bee"]]));
|
||||
assert(in_list(NAN, [NAN])==false);
|
||||
|
||||
}
|
||||
test_in_list();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
module test_point2d() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/cubetruss.scad>
|
||||
include <../std.scad>
|
||||
include <../cubetruss.scad>
|
||||
|
||||
|
||||
module test_cubetruss_dist() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
module test_standard_anchors() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
module test_is_edge_array() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
// Can't test echo output as yet. Include these for coverage calculations.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
module test_point_on_segment2d() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/linear_bearings.scad>
|
||||
include <../std.scad>
|
||||
include <../linear_bearings.scad>
|
||||
|
||||
|
||||
module test_get_lmXuu_bearing_diam() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
// Simple Calculations
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
module test_HSL() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
module test_square() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/strings.scad>
|
||||
include <../std.scad>
|
||||
include <../strings.scad>
|
||||
|
||||
|
||||
function rec_cmp(a,b,eps=1e-9) =
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/queues.scad>
|
||||
include <../std.scad>
|
||||
include <../queues.scad>
|
||||
|
||||
|
||||
module test_queue_init() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/hull.scad>
|
||||
include <../std.scad>
|
||||
include <../hull.scad>
|
||||
|
||||
|
||||
module test_prismoid() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
module test_turtle() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/skin.scad>
|
||||
include <../std.scad>
|
||||
include <../skin.scad>
|
||||
|
||||
|
||||
module test_skin() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/stacks.scad>
|
||||
include <../std.scad>
|
||||
include <../stacks.scad>
|
||||
|
||||
|
||||
module test_stack_init() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/strings.scad>
|
||||
include <../std.scad>
|
||||
include <../strings.scad>
|
||||
|
||||
|
||||
module test_upcase() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/structs.scad>
|
||||
include <../std.scad>
|
||||
include <../structs.scad>
|
||||
|
||||
|
||||
module test_struct_set() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
module test_translate() {
|
||||
|
|
|
@ -9,10 +9,11 @@ module test_is_vector() {
|
|||
assert(is_vector(1) == false);
|
||||
assert(is_vector("foo") == false);
|
||||
assert(is_vector(true) == false);
|
||||
assert(is_vector([0,0],nonzero=true) == false);
|
||||
assert(is_vector([0,1e-12,0],nonzero=true) == false);
|
||||
assert(is_vector([0,1e-6,0],nonzero=true) == true);
|
||||
assert(is_vector([0,1e-6,0],nonzero=true,eps=1e-4) == false);
|
||||
|
||||
assert(is_vector([0,0,0],zero=true) == true);
|
||||
assert(is_vector([0,0,0],zero=false) == false);
|
||||
assert(is_vector([0,1,0],zero=true) == false);
|
||||
assert(is_vector([0,0,1],zero=false) == true);
|
||||
}
|
||||
test_is_vector();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <../std.scad>
|
||||
|
||||
|
||||
module test_bosl_version() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/vnf.scad>
|
||||
include <../std.scad>
|
||||
include <../vnf.scad>
|
||||
|
||||
|
||||
module test_is_vnf() {
|
||||
|
|
81
vectors.scad
81
vectors.scad
|
@ -19,31 +19,30 @@
|
|||
// Arguments:
|
||||
// v = The value to test to see if it is a vector.
|
||||
// length = If given, make sure the vector is `length` items long.
|
||||
// zero = If false, require that the length of the vector is not approximately zero. If true, require the length of the vector to be approx zero-length. Default: `undef` (don't check vector length.)
|
||||
// eps = The minimum vector length that is considered non-zero. Default: `EPSILON` (`1e-9`)
|
||||
// Example:
|
||||
// is_vector(4); // Returns false
|
||||
// is_vector([4,true,false]); // Returns false
|
||||
// is_vector([3,4,INF,5]); // Returns false
|
||||
// is_vector([3,4,5,6]); // Returns true
|
||||
// is_vector([3,4,undef,5]); // Returns false
|
||||
// is_vector([3,4,5],3); // Returns true
|
||||
// is_vector([3,4,5],4); // Returns true
|
||||
// is_vector([]); // Returns false
|
||||
// is_vector([0,4,0],3,nonzero=true); // Returns true
|
||||
// is_vector([0,0,0],nonzero=true); // Returns false
|
||||
// is_vector([0,0,1e-12],nonzero=true); // Returns false
|
||||
// is_vector([],nonzero=true); // Returns false
|
||||
function is_vector(v,length, nonzero=false, eps=EPSILON) =
|
||||
is_list(v) && is_num(0*(v*v))
|
||||
&& (is_undef(length)|| len(v)==length)
|
||||
&& ( ! nonzero || ([]!=[for(vi=v) if(abs(vi)>=eps) 1]) );
|
||||
|
||||
//***
|
||||
// including non_zero option
|
||||
// extended examples
|
||||
// is_vector(4); // Returns false
|
||||
// is_vector([4,true,false]); // Returns false
|
||||
// is_vector([3,4,INF,5]); // Returns false
|
||||
// is_vector([3,4,5,6]); // Returns true
|
||||
// is_vector([3,4,undef,5]); // Returns false
|
||||
// is_vector([3,4,5],3); // Returns true
|
||||
// is_vector([3,4,5],4); // Returns true
|
||||
// is_vector([]); // Returns false
|
||||
// is_vector([0,0,0],zero=true); // Returns true
|
||||
// is_vector([0,0,0],zero=false); // Returns false
|
||||
// is_vector([0,1,0],zero=true); // Returns false
|
||||
// is_vector([0,0,1],zero=false); // Returns true
|
||||
function is_vector(v,length,zero,eps=EPSILON) =
|
||||
is_list(v) && is_num(0*(v*v))
|
||||
&& (is_undef(length) || len(v)==length)
|
||||
&& (is_undef(zero) || ((norm(v) >= eps) == !zero));
|
||||
|
||||
//***
|
||||
// add_scalar() is an array operation: moved to array.scad
|
||||
|
||||
|
||||
// Function: vang()
|
||||
// Usage:
|
||||
// theta = vang([X,Y]);
|
||||
|
@ -204,26 +203,28 @@ function vector_axis(v1,v2=undef,v3=undef) =
|
|||
is_vector(v3)
|
||||
? assert(is_consistent([v3,v2,v1]), "Bad arguments.")
|
||||
vector_axis(v1-v2, v3-v2)
|
||||
: assert( is_undef(v3), "Bad arguments.")
|
||||
is_undef(v2)
|
||||
? assert( is_list(v1), "Bad arguments.")
|
||||
len(v1) == 2
|
||||
? vector_axis(v1[0],v1[1])
|
||||
: vector_axis(v1[0],v1[1],v1[2])
|
||||
: assert( is_vector(v1,nonzero=true) && is_vector(v2,nonzero=true) && is_consistent([v1,v2])
|
||||
, "Bad arguments.")
|
||||
let(
|
||||
eps = 1e-6,
|
||||
w1 = point3d(v1/norm(v1)),
|
||||
w2 = point3d(v2/norm(v2)),
|
||||
w3 = (norm(w1-w2) > eps && norm(w1+w2) > eps) ? w2
|
||||
: (norm(vabs(w2)-UP) > eps)? UP
|
||||
: RIGHT
|
||||
) unit(cross(w1,w3));
|
||||
:
|
||||
assert( is_undef(v3), "Bad arguments.")
|
||||
is_undef(v2)
|
||||
? assert( is_list(v1), "Bad arguments.")
|
||||
len(v1) == 2
|
||||
? vector_axis(v1[0],v1[1])
|
||||
: vector_axis(v1[0],v1[1],v1[2])
|
||||
:
|
||||
assert(
|
||||
is_vector(v1,zero=false) &&
|
||||
is_vector(v2,zero=false) &&
|
||||
is_consistent([v1,v2]),
|
||||
"Bad arguments."
|
||||
)
|
||||
let(
|
||||
eps = 1e-6,
|
||||
w1 = point3d(v1/norm(v1)),
|
||||
w2 = point3d(v2/norm(v2)),
|
||||
w3 = (norm(w1-w2) > eps && norm(w1+w2) > eps) ? w2
|
||||
: (norm(vabs(w2)-UP) > eps) ? UP
|
||||
: RIGHT
|
||||
) unit(cross(w1,w3));
|
||||
|
||||
|
||||
//***
|
||||
// completing input data check and refactoring
|
||||
// Note: vector_angle and vector_axis have the same kind of inputs and two code strategy alternatives
|
||||
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BOSL_VERSION = [2,0,391];
|
||||
BOSL_VERSION = [2,0,397];
|
||||
|
||||
|
||||
// Section: BOSL Library Version Functions
|
||||
|
|
Loading…
Reference in a new issue