diff --git a/edges.scad b/edges.scad index 088b5f7..9a3340e 100644 --- a/edges.scad +++ b/edges.scad @@ -41,7 +41,7 @@ function _edges_text(edges) = is_string(edges) ? [str("\"",edges,"\"")] : edges==EDGES_NONE ? ["EDGES_NONE"] : edges==EDGES_ALL ? ["EDGES_ALL"] : - is_edge_array(edges) ? [""] : + _is_edge_array(edges) ? [""] : is_vector(edges,3) ? _edges_vec_txt(edges) : is_list(edges) ? let( lst = [for (x=edges) each _edges_text(x)], @@ -109,20 +109,20 @@ EDGE_OFFSETS = [ // Section: Edge Helpers -// Function: is_edge_array() +/// Internal Function: _is_edge_array() // Topics: Edges, Type Checking // Usage: -// bool = is_edge_array(x); +// bool = _is_edge_array(x); // Description: // Returns true if the given value has the form of an edge array. // Arguments: // x = The item to check the type of. // See Also: edges(), EDGES_NONE, EDGES_ALL -function is_edge_array(x) = is_list(x) && is_vector(x[0]) && len(x)==3 && len(x[0])==4; +function _is_edge_array(x) = is_list(x) && is_vector(x[0]) && len(x)==3 && len(x[0])==4; function _edge_set(v) = - is_edge_array(v)? v : [ + _is_edge_array(v)? v : [ for (ax=[0:2]) [ for (b=[-1,1], a=[-1,1]) let( v2=[[0,a,b],[a,0,b],[a,b,0]][ax] @@ -153,15 +153,15 @@ function _edge_set(v) = ]; -// Function: normalize_edges() -// Topics: Edges +/// Internal Function: _normalize_edges() +/// Topics: Edges // Usage: -// edges = normalize_edges(v); +// edges = _normalize_edges(v); // Description: // Normalizes all values in an edge array to be `1`, if it was originally greater than `0`, // or `0`, if it was originally less than or equal to `0`. -// See Also: is_edge_array(), edges(), EDGES_NONE, EDGES_ALL -function normalize_edges(v) = [for (ax=v) [for (edge=ax) edge>0? 1 : 0]]; +// See Also: edges(), EDGES_NONE, EDGES_ALL +function _normalize_edges(v) = [for (ax=v) [for (edge=ax) edge>0? 1 : 0]]; // Function: edges() @@ -259,7 +259,7 @@ function normalize_edges(v) = [for (ax=v) [for (edge=ax) edge>0? 1 : 0]]; // v = The edge set to include. // except = The edge set to specifically exclude, even if they are in `v`. // -// See Also: is_edge_array(), normalize_edges(), EDGES_NONE, EDGES_ALL +// See Also: EDGES_NONE, EDGES_ALL // // Example(3D): Just the front-top edge // edg = edges(FRONT+TOP); @@ -283,11 +283,11 @@ function normalize_edges(v) = [for (ax=v) [for (edge=ax) edge>0? 1 : 0]]; // edg = edges("ALL", except=edges("Z", except=BACK)); // show_edges(edges=edg); function edges(v, except=[]) = - (is_string(v) || is_vector(v) || is_edge_array(v))? edges([v], except=except) : - (is_string(except) || is_vector(except) || is_edge_array(except))? edges(v, except=[except]) : - except==[]? normalize_edges(sum([for (x=v) _edge_set(x)])) : - normalize_edges( - normalize_edges(sum([for (x=v) _edge_set(x)])) - + (is_string(v) || is_vector(v) || _is_edge_array(v))? edges([v], except=except) : + (is_string(except) || is_vector(except) || _is_edge_array(except))? edges(v, except=[except]) : + except==[]? _normalize_edges(sum([for (x=v) _edge_set(x)])) : + _normalize_edges( + _normalize_edges(sum([for (x=v) _edge_set(x)])) - sum([for (x=except) _edge_set(x)]) ); @@ -303,7 +303,7 @@ function edges(v, except=[]) = // size = The scalar size of the cube. // text = The text to show on the front of the cube. // txtsize = The size of the text. -// See Also: is_edge_array(), edges(), EDGES_NONE, EDGES_ALL +// See Also: edges(), EDGES_NONE, EDGES_ALL // Example: // show_edges(size=30, edges=["X","Y"]); module show_edges(edges="ALL", size=20, text, txtsize=3) { @@ -365,29 +365,29 @@ CORNER_OFFSETS = [ // Section: Corner Helpers -// Function: is_corner_array() -// Topics: Corners, Type Checking +/// Internal Function: _is_corner_array() +/// Topics: Corners, Type Checking // Usage: -// bool = is_corner_array(x) +// bool = _is_corner_array(x) // Description: // Returns true if the given value has the form of a corner array. // See Also: CORNERS_NONE, CORNERS_ALL, corners() -function is_corner_array(x) = is_vector(x) && len(x)==8 && all([for (xx=x) xx==1||xx==0]); +function _is_corner_array(x) = is_vector(x) && len(x)==8 && all([for (xx=x) xx==1||xx==0]); -// Function: normalize_corners() -// Topics: Corners +/// Internal Function: _normalize_corners() +/// Topics: Corners // Usage: -// corns = normalize_corners(v); +// corns = _normalize_corners(v); // Description: // Normalizes all values in a corner array to be `1`, if it was originally greater than `0`, // or `0`, if it was originally less than or equal to `0`. -// See Also: CORNERS_NONE, CORNERS_ALL, is_corner_array(), corners() -function normalize_corners(v) = [for (x=v) x>0? 1 : 0]; +// See Also: CORNERS_NONE, CORNERS_ALL, corners() +function _normalize_corners(v) = [for (x=v) x>0? 1 : 0]; function _corner_set(v) = - is_corner_array(v)? v : [ + _is_corner_array(v)? v : [ for (i=[0:7]) let( v2 = CORNER_OFFSETS[i] ) ( @@ -480,7 +480,7 @@ function _corner_set(v) = // show_corners(corners="ALL"); // show_corners(corners="NONE"); // } -// See Also: CORNERS_NONE, CORNERS_ALL, is_corner_array(), normalize_corners() +// See Also: CORNERS_NONE, CORNERS_ALL // Example(3D): Just the front-top-right corner // crn = corners(FRONT+TOP+RIGHT); // show_corners(corners=crn); @@ -497,37 +497,37 @@ function _corner_set(v) = // crn = corners([BOTTOM,FRONT], except=BOTTOM+FRONT); // show_corners(corners=crn); function corners(v, except=[]) = - (is_string(v) || is_vector(v) || is_corner_array(v))? corners([v], except=except) : - (is_string(except) || is_vector(except) || is_corner_array(except))? corners(v, except=[except]) : - except==[]? normalize_corners(sum([for (x=v) _corner_set(x)])) : + (is_string(v) || is_vector(v) || _is_corner_array(v))? corners([v], except=except) : + (is_string(except) || is_vector(except) || _is_corner_array(except))? corners(v, except=[except]) : + except==[]? _normalize_corners(sum([for (x=v) _corner_set(x)])) : let( - a = normalize_corners(sum([for (x=v) _corner_set(x)])), - b = normalize_corners(sum([for (x=except) _corner_set(x)])) - ) normalize_corners(a - b); + a = _normalize_corners(sum([for (x=v) _corner_set(x)])), + b = _normalize_corners(sum([for (x=except) _corner_set(x)])) + ) _normalize_corners(a - b); -// Function: corner_edges() -// Topics: Corners +/// Internal Function: _corner_edges() +/// Topics: Corners // Description: // Returns [XCOUNT,YCOUNT,ZCOUNT] where each is the count of edges aligned with that // axis that are in the edge set and touch the given corner. // Arguments: // edges = Standard edges array. // v = Vector pointing to the corner to count edge intersections at. -// See Also: CORNERS_NONE, CORNERS_ALL, is_corner_array(), corners(), corner_edge_count() -function corner_edges(edges, v) = +// See Also: CORNERS_NONE, CORNERS_ALL, corners() +function _corner_edges(edges, v) = let(u = (v+[1,1,1])/2) [edges[0][u.y+u.z*2], edges[1][u.x+u.z*2], edges[2][u.x+u.y*2]]; -// Function: corner_edge_count() -// Topics: Corners +/// InternalFunction: _corner_edge_count() +/// Topics: Corners // Description: // Counts how many given edges intersect at a specific corner. // Arguments: // edges = Standard edges array. // v = Vector pointing to the corner to count edge intersections at. -// See Also: CORNERS_NONE, CORNERS_ALL, is_corner_array(), corners(), corner_edges() -function corner_edge_count(edges, v) = +// See Also: CORNERS_NONE, CORNERS_ALL, corners() +function _corner_edge_count(edges, v) = let(u = (v+[1,1,1])/2) edges[0][u.y+u.z*2] + edges[1][u.x+u.z*2] + edges[2][u.x+u.y*2]; @@ -535,7 +535,7 @@ function _corners_text(corners) = is_string(corners) ? [str("\"",corners,"\"")] : corners==CORNERS_NONE ? ["CORNERS_NONE"] : corners==CORNERS_ALL ? ["CORNERS_ALL"] : - is_corner_array(corners) ? [""] : + _is_corner_array(corners) ? [""] : is_vector(corners,3) ? _edges_vec_txt(corners) : is_list(corners) ? let( lst = [for (x=corners) each _corners_text(x)], @@ -563,7 +563,7 @@ function _corners_text(corners) = // size = The scalar size of the cube. // text = If given, overrides the text to be shown on the front of the cube. // txtsize = The size of the text. -// See Also: CORNERS_NONE, CORNERS_ALL, is_corner_array(), corners() +// See Also: CORNERS_NONE, CORNERS_ALL, corners() // Example: // show_corners(corners=FWD+RIGHT, size=30); module show_corners(corners="ALL", size=20, text, txtsize=3) { diff --git a/mutators.scad b/mutators.scad index cdc4121..0f51e73 100644 --- a/mutators.scad +++ b/mutators.scad @@ -598,6 +598,188 @@ module cylindrical_extrude(or, ir, od, id, size=1000, convexity=10, spin=0, orie } +// Module: extrude_from_to() +// Description: +// Extrudes a 2D shape between the 3d points pt1 and pt2. Takes as children a set of 2D shapes to extrude. +// Arguments: +// pt1 = starting point of extrusion. +// pt2 = ending point of extrusion. +// convexity = max number of times a line could intersect a wall of the 2D shape being extruded. +// twist = number of degrees to twist the 2D shape over the entire extrusion length. +// scale = scale multiplier for end of extrusion compared the start. +// slices = Number of slices along the extrusion to break the extrusion into. Useful for refining `twist` extrusions. +// Example(FlatSpin,VPD=200,VPT=[0,0,15]): +// extrude_from_to([0,0,0], [10,20,30], convexity=4, twist=360, scale=3.0, slices=40) { +// xcopies(3) circle(3, $fn=32); +// } +module extrude_from_to(pt1, pt2, convexity, twist, scale, slices) { + assert(is_vector(pt1)); + assert(is_vector(pt2)); + pt1 = point3d(pt1); + pt2 = point3d(pt2); + rtp = xyz_to_spherical(pt2-pt1); + translate(pt1) { + rotate([0, rtp[2], rtp[1]]) { + if (rtp[0] > 0) { + linear_extrude(height=rtp[0], convexity=convexity, center=false, slices=slices, twist=twist, scale=scale) { + children(); + } + } + } + } +} + + + +// Module: spiral_sweep() +// Description: +// Takes a closed 2D polygon path, centered on the XY plane, and sweeps/extrudes it along a 3D spiral path +// of a given radius, height and twist. The origin in the profile traces out the helix of the specified radius. +// If twist is positive the path will be right-handed; if twist is negative the path will be left-handed. +// . +// Higbee specifies tapering applied to the ends of the extrusion and is given as the linear distance +// over which to taper. +// Arguments: +// poly = Array of points of a polygon path, to be extruded. +// h = height of the spiral to extrude along. +// r = Radius of the spiral to extrude along. Default: 50 +// twist = number of degrees of rotation to spiral up along height. +// --- +// d = Diameter of the spiral to extrude along. +// higbee = Length to taper thread ends over. +// higbee1 = Taper length at start +// higbee2 = Taper length at end +// internal = direction to taper the threads with higbee. If true threads taper outward; if false they taper inward. Default: false +// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER` +// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0` +// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP` +// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=BOTTOM`. +// Example: +// poly = [[-10,0], [-3,-5], [3,-5], [10,0], [0,-30]]; +// spiral_sweep(poly, h=200, r=50, twist=1080, $fn=36); +module spiral_sweep(poly, h, r, twist=360, higbee, center, r1, r2, d, d1, d2, higbee1, higbee2, internal=false, anchor, spin=0, orient=UP) { + higsample = 10; // Oversample factor for higbee tapering + dummy1=assert(is_num(twist) && twist != 0); + bounds = pointlist_bounds(poly); + yctr = (bounds[0].y+bounds[1].y)/2; + xmin = bounds[0].x; + xmax = bounds[1].x; + poly = path3d(clockwise_polygon(poly)); + anchor = get_anchor(anchor,center,BOT,BOT); + r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=50); + r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=50); + sides = segs(max(r1,r2)); + dir = sign(twist); + ang_step = 360/sides*dir; + anglist = [for(ang = [0:ang_step:twist-EPSILON]) ang, + twist]; + higbee1 = first_defined([higbee1, higbee, 0]); + higbee2 = first_defined([higbee2, higbee, 0]); + higang1 = 360 * higbee1 / (2 * r1 * PI); + higang2 = 360 * higbee2 / (2 * r2 * PI); + dummy2=assert(higbee1>=0 && higbee2>=0) + assert(higang1 < dir*twist/2,"Higbee1 is more than half the threads") + assert(higang2 < dir*twist/2,"Higbee2 is more than half the threads"); + function polygon_r(N,theta) = + let( alpha = 360/N ) + cos(alpha/2)/(cos(posmod(theta,alpha)-alpha/2)); + higofs = pow(0.05,2); // Smallest hig scale is the square root of this value + function taperfunc(x) = sqrt((1-higofs)*x+higofs); + interp_ang = [ + for(i=idx(anglist,e=-2)) + each lerpn(anglist[i],anglist[i+1], + (higang1>0 && higang1>dir*anglist[i+1] + || (higang2>0 && higang2>dir*(twist-anglist[i]))) ? ceil((anglist[i+1]-anglist[i])/ang_step*higsample) + : 1, + endpoint=false), + last(anglist) + ]; + skewmat = affine3d_skew_xz(xa=atan2(r2-r1,h)); + points = [ + for (a = interp_ang) let ( + hsc = dir*a0?true:false, + style=higbee1>0 || higbee2>0 ? "quincunx" : "alt" + ); + + attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) { + vnf_polyhedron(vnf, convexity=ceil(2*dir*twist/360)); + children(); + } +} + + + +// Module: path_extrude() +// Description: +// Extrudes 2D children along a 3D path. This may be slow. +// Arguments: +// path = array of points for the bezier path to extrude along. +// convexity = maximum number of walls a ran can pass through. +// clipsize = increase if artifacts are left. Default: 1000 +// Example(FlatSpin,VPD=600,VPT=[75,16,20]): +// path = [ [0, 0, 0], [33, 33, 33], [66, 33, 40], [100, 0, 0], [150,0,0] ]; +// path_extrude(path) circle(r=10, $fn=6); +module path_extrude(path, convexity=10, clipsize=100) { + function polyquats(path, q=q_ident(), v=[0,0,1], i=0) = let( + v2 = path[i+1] - path[i], + ang = vector_angle(v,v2), + axis = ang>0.001? unit(cross(v,v2)) : [0,0,1], + newq = q_mul(quat(axis, ang), q), + dist = norm(v2) + ) i < (len(path)-2)? + concat([[dist, newq, ang]], polyquats(path, newq, v2, i+1)) : + [[dist, newq, ang]]; + + epsilon = 0.0001; // Make segments ever so slightly too long so they overlap. + ptcount = len(path); + pquats = polyquats(path); + for (i = [0:1:ptcount-2]) { + pt1 = path[i]; + pt2 = path[i+1]; + dist = pquats[i][0]; + q = pquats[i][1]; + difference() { + translate(pt1) { + q_rot(q) { + down(clipsize/2/2) { + if ((dist+clipsize/2) > 0) { + linear_extrude(height=dist+clipsize/2, convexity=convexity) { + children(); + } + } + } + } + } + translate(pt1) { + hq = (i > 0)? q_slerp(q, pquats[i-1][1], 0.5) : q; + q_rot(hq) down(clipsize/2+epsilon) cube(clipsize, center=true); + } + translate(pt2) { + hq = (i < ptcount-2)? q_slerp(q, pquats[i+1][1], 0.5) : q; + q_rot(hq) up(clipsize/2+epsilon) cube(clipsize, center=true); + } + } + } +} + + + + ////////////////////////////////////////////////////////////////////// // Section: Offset Mutators diff --git a/paths.scad b/paths.scad index 551769b..f3fa9a0 100644 --- a/paths.scad +++ b/paths.scad @@ -1215,190 +1215,4 @@ function resample_path(path, N, spacing, closed=false) = ]; - -// Section: 3D Modules - - -// Module: extrude_from_to() -// Description: -// Extrudes a 2D shape between the 3d points pt1 and pt2. Takes as children a set of 2D shapes to extrude. -// Arguments: -// pt1 = starting point of extrusion. -// pt2 = ending point of extrusion. -// convexity = max number of times a line could intersect a wall of the 2D shape being extruded. -// twist = number of degrees to twist the 2D shape over the entire extrusion length. -// scale = scale multiplier for end of extrusion compared the start. -// slices = Number of slices along the extrusion to break the extrusion into. Useful for refining `twist` extrusions. -// Example(FlatSpin,VPD=200,VPT=[0,0,15]): -// extrude_from_to([0,0,0], [10,20,30], convexity=4, twist=360, scale=3.0, slices=40) { -// xcopies(3) circle(3, $fn=32); -// } -module extrude_from_to(pt1, pt2, convexity, twist, scale, slices) { - assert(is_vector(pt1)); - assert(is_vector(pt2)); - pt1 = point3d(pt1); - pt2 = point3d(pt2); - rtp = xyz_to_spherical(pt2-pt1); - translate(pt1) { - rotate([0, rtp[2], rtp[1]]) { - if (rtp[0] > 0) { - linear_extrude(height=rtp[0], convexity=convexity, center=false, slices=slices, twist=twist, scale=scale) { - children(); - } - } - } - } -} - - - -// Module: spiral_sweep() -// Description: -// Takes a closed 2D polygon path, centered on the XY plane, and sweeps/extrudes it along a 3D spiral path -// of a given radius, height and twist. The origin in the profile traces out the helix of the specified radius. -// If twist is positive the path will be right-handed; if twist is negative the path will be left-handed. -// . -// Higbee specifies tapering applied to the ends of the extrusion and is given as the linear distance -// over which to taper. -// Arguments: -// poly = Array of points of a polygon path, to be extruded. -// h = height of the spiral to extrude along. -// r = Radius of the spiral to extrude along. Default: 50 -// twist = number of degrees of rotation to spiral up along height. -// --- -// d = Diameter of the spiral to extrude along. -// higbee = Length to taper thread ends over. -// higbee1 = Taper length at start -// higbee2 = Taper length at end -// internal = direction to taper the threads with higbee. If true threads taper outward; if false they taper inward. Default: false -// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER` -// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0` -// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP` -// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=BOTTOM`. -// Example: -// poly = [[-10,0], [-3,-5], [3,-5], [10,0], [0,-30]]; -// spiral_sweep(poly, h=200, r=50, twist=1080, $fn=36); -module spiral_sweep(poly, h, r, twist=360, higbee, center, r1, r2, d, d1, d2, higbee1, higbee2, internal=false, anchor, spin=0, orient=UP) { - higsample = 10; // Oversample factor for higbee tapering - dummy1=assert(is_num(twist) && twist != 0); - bounds = pointlist_bounds(poly); - yctr = (bounds[0].y+bounds[1].y)/2; - xmin = bounds[0].x; - xmax = bounds[1].x; - poly = path3d(clockwise_polygon(poly)); - anchor = get_anchor(anchor,center,BOT,BOT); - r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=50); - r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=50); - sides = segs(max(r1,r2)); - dir = sign(twist); - ang_step = 360/sides*dir; - anglist = [for(ang = [0:ang_step:twist-EPSILON]) ang, - twist]; - higbee1 = first_defined([higbee1, higbee, 0]); - higbee2 = first_defined([higbee2, higbee, 0]); - higang1 = 360 * higbee1 / (2 * r1 * PI); - higang2 = 360 * higbee2 / (2 * r2 * PI); - dummy2=assert(higbee1>=0 && higbee2>=0) - assert(higang1 < dir*twist/2,"Higbee1 is more than half the threads") - assert(higang2 < dir*twist/2,"Higbee2 is more than half the threads"); - function polygon_r(N,theta) = - let( alpha = 360/N ) - cos(alpha/2)/(cos(posmod(theta,alpha)-alpha/2)); - higofs = pow(0.05,2); // Smallest hig scale is the square root of this value - function taperfunc(x) = sqrt((1-higofs)*x+higofs); - interp_ang = [ - for(i=idx(anglist,e=-2)) - each lerpn(anglist[i],anglist[i+1], - (higang1>0 && higang1>dir*anglist[i+1] - || (higang2>0 && higang2>dir*(twist-anglist[i]))) ? ceil((anglist[i+1]-anglist[i])/ang_step*higsample) - : 1, - endpoint=false), - last(anglist) - ]; - skewmat = affine3d_skew_xz(xa=atan2(r2-r1,h)); - points = [ - for (a = interp_ang) let ( - hsc = dir*a0?true:false, - style=higbee1>0 || higbee2>0 ? "quincunx" : "alt" - ); - - attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) { - vnf_polyhedron(vnf, convexity=ceil(2*dir*twist/360)); - children(); - } -} - - - -// Module: path_extrude() -// Description: -// Extrudes 2D children along a 3D path. This may be slow. -// Arguments: -// path = array of points for the bezier path to extrude along. -// convexity = maximum number of walls a ran can pass through. -// clipsize = increase if artifacts are left. Default: 1000 -// Example(FlatSpin,VPD=600,VPT=[75,16,20]): -// path = [ [0, 0, 0], [33, 33, 33], [66, 33, 40], [100, 0, 0], [150,0,0] ]; -// path_extrude(path) circle(r=10, $fn=6); -module path_extrude(path, convexity=10, clipsize=100) { - function polyquats(path, q=q_ident(), v=[0,0,1], i=0) = let( - v2 = path[i+1] - path[i], - ang = vector_angle(v,v2), - axis = ang>0.001? unit(cross(v,v2)) : [0,0,1], - newq = q_mul(quat(axis, ang), q), - dist = norm(v2) - ) i < (len(path)-2)? - concat([[dist, newq, ang]], polyquats(path, newq, v2, i+1)) : - [[dist, newq, ang]]; - - epsilon = 0.0001; // Make segments ever so slightly too long so they overlap. - ptcount = len(path); - pquats = polyquats(path); - for (i = [0:1:ptcount-2]) { - pt1 = path[i]; - pt2 = path[i+1]; - dist = pquats[i][0]; - q = pquats[i][1]; - difference() { - translate(pt1) { - q_rot(q) { - down(clipsize/2/2) { - if ((dist+clipsize/2) > 0) { - linear_extrude(height=dist+clipsize/2, convexity=convexity) { - children(); - } - } - } - } - } - translate(pt1) { - hq = (i > 0)? q_slerp(q, pquats[i-1][1], 0.5) : q; - q_rot(hq) down(clipsize/2+epsilon) cube(clipsize, center=true); - } - translate(pt2) { - hq = (i < ptcount-2)? q_slerp(q, pquats[i+1][1], 0.5) : q; - q_rot(hq) up(clipsize/2+epsilon) cube(clipsize, center=true); - } - } - } -} - - - - // vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap diff --git a/tests/test_edges.scad b/tests/test_edges.scad index e420499..fcd531f 100644 --- a/tests/test_edges.scad +++ b/tests/test_edges.scad @@ -1,19 +1,19 @@ include <../std.scad> -module test_is_edge_array() { - assert(is_edge_array([[0,0,0,0],[0,0,0,0],[0,0,0,0]])); - assert(is_edge_array([[1,1,1,1],[1,1,1,1],[1,1,1,1]])); - assert(!is_edge_array([[1,1,1],[1,1,1],[1,1,1]])); - assert(!is_edge_array([[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1]])); - assert(!is_edge_array([[1,1,1,1],[1,1,1,1]])); - assert(!is_edge_array([1,1,1,1])); - assert(!is_edge_array("foo")); - assert(!is_edge_array(42)); - assert(!is_edge_array(true)); - assert(is_edge_array(edges(["X","Y"]))); +module test__is_edge_array() { + assert(_is_edge_array([[0,0,0,0],[0,0,0,0],[0,0,0,0]])); + assert(_is_edge_array([[1,1,1,1],[1,1,1,1],[1,1,1,1]])); + assert(!_is_edge_array([[1,1,1],[1,1,1],[1,1,1]])); + assert(!_is_edge_array([[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1]])); + assert(!_is_edge_array([[1,1,1,1],[1,1,1,1]])); + assert(!_is_edge_array([1,1,1,1])); + assert(!_is_edge_array("foo")); + assert(!_is_edge_array(42)); + assert(!_is_edge_array(true)); + assert(_is_edge_array(edges(["X","Y"]))); } -test_is_edge_array(); +test__is_edge_array(); module test__edge_set() { @@ -62,14 +62,14 @@ module test__edge_set() { test__edge_set(); -module test_normalize_edges() { - assert(normalize_edges([[-2,-2,-2,-2],[-2,-2,-2,-2],[-2,-2,-2,-2]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]); - assert(normalize_edges([[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]); - assert(normalize_edges([[0,0,0,0],[0,0,0,0],[0,0,0,0]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]); - assert(normalize_edges([[1,1,1,1],[1,1,1,1],[1,1,1,1]]) == [[1,1,1,1],[1,1,1,1],[1,1,1,1]]); - assert(normalize_edges([[2,2,2,2],[2,2,2,2],[2,2,2,2]]) == [[1,1,1,1],[1,1,1,1],[1,1,1,1]]); +module test__normalize_edges() { + assert(_normalize_edges([[-2,-2,-2,-2],[-2,-2,-2,-2],[-2,-2,-2,-2]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]); + assert(_normalize_edges([[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]); + assert(_normalize_edges([[0,0,0,0],[0,0,0,0],[0,0,0,0]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]); + assert(_normalize_edges([[1,1,1,1],[1,1,1,1],[1,1,1,1]]) == [[1,1,1,1],[1,1,1,1],[1,1,1,1]]); + assert(_normalize_edges([[2,2,2,2],[2,2,2,2],[2,2,2,2]]) == [[1,1,1,1],[1,1,1,1],[1,1,1,1]]); } -test_normalize_edges(); +test__normalize_edges(); module test_edges() { @@ -90,24 +90,24 @@ module test_edges() { test_edges(); -module test_corner_edge_count() { +module test__corner_edge_count() { edges = edges([TOP,FRONT+RIGHT]); - assert(corner_edge_count(edges,TOP+FRONT+RIGHT) == 3); - assert(corner_edge_count(edges,TOP+FRONT+LEFT) == 2); - assert(corner_edge_count(edges,BOTTOM+FRONT+RIGHT) == 1); - assert(corner_edge_count(edges,BOTTOM+FRONT+LEFT) == 0); + assert(_corner_edge_count(edges,TOP+FRONT+RIGHT) == 3); + assert(_corner_edge_count(edges,TOP+FRONT+LEFT) == 2); + assert(_corner_edge_count(edges,BOTTOM+FRONT+RIGHT) == 1); + assert(_corner_edge_count(edges,BOTTOM+FRONT+LEFT) == 0); } -test_corner_edge_count(); +test__corner_edge_count(); -module test_corner_edges() { +module test__corner_edges() { edges = edges([TOP,FRONT+RIGHT]); - assert_equal(corner_edges(edges,TOP+FRONT+RIGHT), [1,1,1]); - assert_equal(corner_edges(edges,TOP+FRONT+LEFT), [1,1,0]); - assert_equal(corner_edges(edges,BOTTOM+FRONT+RIGHT), [0,0,1]); - assert_equal(corner_edges(edges,BOTTOM+FRONT+LEFT), [0,0,0]); + assert_equal(_corner_edges(edges,TOP+FRONT+RIGHT), [1,1,1]); + assert_equal(_corner_edges(edges,TOP+FRONT+LEFT), [1,1,0]); + assert_equal(_corner_edges(edges,BOTTOM+FRONT+RIGHT), [0,0,1]); + assert_equal(_corner_edges(edges,BOTTOM+FRONT+LEFT), [0,0,0]); } -test_corner_edges(); +test__corner_edges(); module test_corners() { @@ -174,36 +174,36 @@ module test_corners() { test_corners(); -module test_is_corner_array() { +module test__is_corner_array() { edges = edges([TOP,FRONT+RIGHT]); corners = corners([TOP,FRONT+RIGHT]); - assert(!is_corner_array(undef)); - assert(!is_corner_array(true)); - assert(!is_corner_array(false)); - assert(!is_corner_array(INF)); - assert(!is_corner_array(-INF)); - assert(!is_corner_array(NAN)); - assert(!is_corner_array(-4)); - assert(!is_corner_array(0)); - assert(!is_corner_array(4)); - assert(!is_corner_array("foo")); - assert(!is_corner_array([])); - assert(!is_corner_array([4,5,6])); - assert(!is_corner_array([2:3:9])); - assert(!is_corner_array(edges)); - assert(is_corner_array(corners)); + assert(!_is_corner_array(undef)); + assert(!_is_corner_array(true)); + assert(!_is_corner_array(false)); + assert(!_is_corner_array(INF)); + assert(!_is_corner_array(-INF)); + assert(!_is_corner_array(NAN)); + assert(!_is_corner_array(-4)); + assert(!_is_corner_array(0)); + assert(!_is_corner_array(4)); + assert(!_is_corner_array("foo")); + assert(!_is_corner_array([])); + assert(!_is_corner_array([4,5,6])); + assert(!_is_corner_array([2:3:9])); + assert(!_is_corner_array(edges)); + assert(_is_corner_array(corners)); } -test_is_corner_array(); +test__is_corner_array(); -module test_normalize_corners() { - assert_equal(normalize_corners([-2,-2,-2,-2,-2,-2,-2,-2]), [0,0,0,0,0,0,0,0]); - assert_equal(normalize_corners([-1,-1,-1,-1,-1,-1,-1,-1]), [0,0,0,0,0,0,0,0]); - assert_equal(normalize_corners([0,0,0,0,0,0,0,0]), [0,0,0,0,0,0,0,0]); - assert_equal(normalize_corners([1,1,1,1,1,1,1,1]), [1,1,1,1,1,1,1,1]); - assert_equal(normalize_corners([2,2,2,2,2,2,2,2]), [1,1,1,1,1,1,1,1]); +module test__normalize_corners() { + assert_equal(_normalize_corners([-2,-2,-2,-2,-2,-2,-2,-2]), [0,0,0,0,0,0,0,0]); + assert_equal(_normalize_corners([-1,-1,-1,-1,-1,-1,-1,-1]), [0,0,0,0,0,0,0,0]); + assert_equal(_normalize_corners([0,0,0,0,0,0,0,0]), [0,0,0,0,0,0,0,0]); + assert_equal(_normalize_corners([1,1,1,1,1,1,1,1]), [1,1,1,1,1,1,1,1]); + assert_equal(_normalize_corners([2,2,2,2,2,2,2,2]), [1,1,1,1,1,1,1,1]); } -test_normalize_corners(); +test__normalize_corners();