diff --git a/affine.scad b/affine.scad index 4a1a7ff..b39529f 100644 --- a/affine.scad +++ b/affine.scad @@ -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)] : diff --git a/arrays.scad b/arrays.scad index e29edef..5d72e37 100644 --- a/arrays.scad +++ b/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() diff --git a/attachments.scad b/attachments.scad index 1c4b19a..1e7a9fb 100644 --- a/attachments.scad +++ b/attachments.scad @@ -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 : diff --git a/debug.scad b/debug.scad index 3ff5704..ada55e8 100644 --- a/debug.scad +++ b/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) { diff --git a/geometry.scad b/geometry.scad index b5f4c29..62dd436 100644 --- a/geometry.scad +++ b/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 diff --git a/rounding.scad b/rounding.scad index 6f2a065..8d6e2c6 100644 --- a/rounding.scad +++ b/rounding.scad @@ -159,6 +159,7 @@ include // 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. diff --git a/scripts/docs_gen.py b/scripts/docs_gen.py index d2f819c..b1131d3 100755 --- a/scripts/docs_gen.py +++ b/scripts/docs_gen.py @@ -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)): diff --git a/tests/hull.scad b/tests/hull.scad index 98bdb3f..50366d2 100644 --- a/tests/hull.scad +++ b/tests/hull.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../hull.scad> testpoints_on_sphere = [ for(p = diff --git a/tests/polyhedra.scad b/tests/polyhedra.scad index 5f2bedb..3a77fbc 100644 --- a/tests/polyhedra.scad +++ b/tests/polyhedra.scad @@ -1,5 +1,5 @@ -include -include +include<../std.scad> +include<../polyhedra.scad> $fn=96; diff --git a/tests/test_affine.scad b/tests/test_affine.scad index a37153c..a759b56 100644 --- a/tests/test_affine.scad +++ b/tests/test_affine.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> module test_ident() { diff --git a/tests/test_arrays.scad b/tests/test_arrays.scad index 479f4bb..d432b81 100644 --- a/tests/test_arrays.scad +++ b/tests/test_arrays.scad @@ -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(); diff --git a/tests/test_coords.scad b/tests/test_coords.scad index 702a351..4b89c12 100644 --- a/tests/test_coords.scad +++ b/tests/test_coords.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> module test_point2d() { diff --git a/tests/test_cubetruss.scad b/tests/test_cubetruss.scad index 9b71f0e..3c6965d 100644 --- a/tests/test_cubetruss.scad +++ b/tests/test_cubetruss.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../cubetruss.scad> module test_cubetruss_dist() { diff --git a/tests/test_debug.scad b/tests/test_debug.scad index 8c30564..b6351c5 100644 --- a/tests/test_debug.scad +++ b/tests/test_debug.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> module test_standard_anchors() { diff --git a/tests/test_edges.scad b/tests/test_edges.scad index 047c1f9..0b755d6 100644 --- a/tests/test_edges.scad +++ b/tests/test_edges.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> module test_is_edge_array() { diff --git a/tests/test_errors.scad b/tests/test_errors.scad index ba82755..fffe9eb 100644 --- a/tests/test_errors.scad +++ b/tests/test_errors.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> // Can't test echo output as yet. Include these for coverage calculations. diff --git a/tests/test_geometry.scad b/tests/test_geometry.scad index dca4069..92b9f16 100644 --- a/tests/test_geometry.scad +++ b/tests/test_geometry.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> module test_point_on_segment2d() { diff --git a/tests/test_linear_bearings.scad b/tests/test_linear_bearings.scad index 19bc2f5..fb57ba5 100644 --- a/tests/test_linear_bearings.scad +++ b/tests/test_linear_bearings.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../linear_bearings.scad> module test_get_lmXuu_bearing_diam() { diff --git a/tests/test_math.scad b/tests/test_math.scad index 8b34da7..3233e6f 100644 --- a/tests/test_math.scad +++ b/tests/test_math.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> // Simple Calculations diff --git a/tests/test_mutators.scad b/tests/test_mutators.scad index 5854b52..7361434 100644 --- a/tests/test_mutators.scad +++ b/tests/test_mutators.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> module test_HSL() { diff --git a/tests/test_primitives.scad b/tests/test_primitives.scad index 8780b5b..e903617 100644 --- a/tests/test_primitives.scad +++ b/tests/test_primitives.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> module test_square() { diff --git a/tests/test_quaternions.scad b/tests/test_quaternions.scad index 7a66d25..b1e5130 100644 --- a/tests/test_quaternions.scad +++ b/tests/test_quaternions.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../strings.scad> function rec_cmp(a,b,eps=1e-9) = diff --git a/tests/test_queues.scad b/tests/test_queues.scad index cf45eef..4ce3c8c 100644 --- a/tests/test_queues.scad +++ b/tests/test_queues.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../queues.scad> module test_queue_init() { diff --git a/tests/test_shapes.scad b/tests/test_shapes.scad index 0b66d60..ec1d58b 100644 --- a/tests/test_shapes.scad +++ b/tests/test_shapes.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../hull.scad> module test_prismoid() { diff --git a/tests/test_shapes2d.scad b/tests/test_shapes2d.scad index dc8e874..1ee5ffa 100644 --- a/tests/test_shapes2d.scad +++ b/tests/test_shapes2d.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> module test_turtle() { diff --git a/tests/test_skin.scad b/tests/test_skin.scad index 347ccd2..c4a231d 100644 --- a/tests/test_skin.scad +++ b/tests/test_skin.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../skin.scad> module test_skin() { diff --git a/tests/test_stacks.scad b/tests/test_stacks.scad index 3f3f0d2..7241203 100644 --- a/tests/test_stacks.scad +++ b/tests/test_stacks.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../stacks.scad> module test_stack_init() { diff --git a/tests/test_strings.scad b/tests/test_strings.scad index 673e8f0..a1d05d6 100644 --- a/tests/test_strings.scad +++ b/tests/test_strings.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../strings.scad> module test_upcase() { diff --git a/tests/test_structs.scad b/tests/test_structs.scad index 55db3b4..a4a4d92 100644 --- a/tests/test_structs.scad +++ b/tests/test_structs.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../structs.scad> module test_struct_set() { diff --git a/tests/test_transforms.scad b/tests/test_transforms.scad index 722b65e..a44e47c 100644 --- a/tests/test_transforms.scad +++ b/tests/test_transforms.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> module test_translate() { diff --git a/tests/test_vectors.scad b/tests/test_vectors.scad index be3e542..743112f 100644 --- a/tests/test_vectors.scad +++ b/tests/test_vectors.scad @@ -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(); diff --git a/tests/test_version.scad b/tests/test_version.scad index f877b5c..e82f13f 100644 --- a/tests/test_version.scad +++ b/tests/test_version.scad @@ -1,4 +1,4 @@ -include +include <../std.scad> module test_bosl_version() { diff --git a/tests/test_vnf.scad b/tests/test_vnf.scad index 65d5350..753803c 100644 --- a/tests/test_vnf.scad +++ b/tests/test_vnf.scad @@ -1,5 +1,5 @@ -include -include +include <../std.scad> +include <../vnf.scad> module test_is_vnf() { diff --git a/vectors.scad b/vectors.scad index 82535e0..828a120 100644 --- a/vectors.scad +++ b/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 diff --git a/version.scad b/version.scad index eda7210..406f9e4 100644 --- a/version.scad +++ b/version.scad @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,391]; +BOSL_VERSION = [2,0,397]; // Section: BOSL Library Version Functions