diff --git a/attachments.scad b/attachments.scad index 23519e8..7858789 100644 --- a/attachments.scad +++ b/attachments.scad @@ -8,7 +8,7 @@ // Default values for attachment code. $tags = ""; -$overlap = 0.01; +$overlap = 0; $color = undef; $attach_to = undef; diff --git a/debug.scad b/debug.scad index fccc6c9..4bb8479 100644 --- a/debug.scad +++ b/debug.scad @@ -149,12 +149,14 @@ module debug_vertices(vertices, size=1, disabled=false) { if (!disabled) { echo(vertices=vertices); color("blue") { - for (i = [0:1:len(vertices)-1]) { - v = vertices[i]; + dups = search_radius(vertices, vertices, 1e-9); + for (ind = dups){ + numstr = str_join([for(i=ind) str(i)],","); + v = vertices[ind[0]]; translate(v) { up(size/8) zrot($vpr[2]) xrot(90) { linear_extrude(height=size/10, center=true, convexity=10) { - text(text=str(i), size=size, halign="center"); + text(text=numstr, size=size, halign="center"); } } sphere(size/10); @@ -239,19 +241,18 @@ module debug_faces(vertices, faces, size=1, disabled=false) { -// Module: debug_polyhedron() +// Module: debug_vnf() // Usage: -// debug_polyhedron(points, faces, , , ); +// debug_vnf(vnfs, , , ); // Description: -// A drop-in module to replace `polyhedron()` and help debug vertices and faces. +// A drop-in module to replace `vnf_polyhedron()` and help debug vertices and faces. // Draws all the vertices at their 3D position, numbered in blue by their -// position in the vertex array. Each face will have their face number drawn +// position in the vertex array. Each face will have its face number drawn // in red, aligned with the center of face. All given faces are drawn with // transparency. All children of this module are drawn with transparency. // Works best with Thrown-Together preview mode, to see reversed faces. // Arguments: -// points = Array of point vertices. -// faces = Array of faces by vertex numbers. +// vnf = vnf to display // --- // convexity = The max number of walls a ray can pass through the given polygon paths. // txtsize = The size of the text used to label the faces and vertices. @@ -259,15 +260,14 @@ module debug_faces(vertices, faces, size=1, disabled=false) { // Example(EdgesMed): // verts = [for (z=[-10,10], a=[0:120:359.9]) [10*cos(a),10*sin(a),z]]; // faces = [[0,1,2], [5,4,3], [0,3,4], [0,4,1], [1,4,5], [1,5,2], [2,5,3], [2,3,0]]; -// debug_polyhedron(points=verts, faces=faces, txtsize=1); -module debug_polyhedron(points, faces, convexity=6, txtsize=1, disabled=false) { - debug_faces(vertices=points, faces=faces, size=txtsize, disabled=disabled) { - polyhedron(points=points, faces=faces, convexity=convexity); +// debug_vnf([verts,faces], txtsize=2); +module debug_vnf(vnf, convexity=6, txtsize=1, disabled=false) { + debug_faces(vertices=vnf[0], faces=vnf[1], size=txtsize, disabled=disabled) { + vnf_polyhedron(vnf, convexity=convexity); } } - // Function: standard_anchors() // Usage: // anchs = standard_anchors(); diff --git a/joiners.scad b/joiners.scad index 4a6856b..306d33a 100644 --- a/joiners.scad +++ b/joiners.scad @@ -419,7 +419,7 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde // Module: dovetail() // // Usage: -// dovetail(gender, w|width, h|height, slide, [slope|angle], [taper|back_width], [chamfer], [r|radius], [round], [$slop]) +// dovetail(gender, w|width, h|height, slide, [slope|angle], [taper|back_width], [chamfer], [r|radius], [round], [extra], [$slop]) // // Description: // Produces a possibly tapered dovetail joint shape to attach to or subtract from two parts you wish to join together. @@ -429,7 +429,9 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde // parallel to the Y axis and projecting upwards, so in its default orientation it will slide together with a translation // in the positive Y direction. The gender determines whether the shape is meant to be added to your model or // differenced, and it also changes the anchor and orientation. The default anchor for dovetails is BOTTOM; -// the default orientation depends on the gender, with male dovetails oriented UP and female ones DOWN. +// the default orientation depends on the gender, with male dovetails oriented UP and female ones DOWN. The dovetails by default +// have extra extension of 0.01 for unions and differences. You should ensure that attachment is done with overlap=0 to ensure that +// the sizing and positioning is correct. // // Arguments: // gender = A string, "male" or "female", to specify the gender of the dovetail. @@ -473,14 +475,14 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde // diff("remove") // cuboid([50,30,10]) { // attach(BACK) dovetail("male", slide=10, width=15, height=8, radius=1, $fn=32); -// attach(FRONT, overlap=-0.1) dovetail("female", slide=10, width=15, height=8, radius=1, $tags="remove", $fn=32); +// attach(FRONT) dovetail("female", slide=10, width=15, height=8, radius=1, $tags="remove", $fn=32); // } // Example: Or you can make a fully rounded joint // $fn=32; // diff("remove") // cuboid([50,30,10]){ // attach(BACK) dovetail("male", slide=10, width=15, height=8, radius=1.5, round=true); -// attach(FRONT,overlap=-0.1) dovetail("female", slide=10, width=15, height=8, radius=1.5, round=true, $tags="remove"); +// attach(FRONT) dovetail("female", slide=10, width=15, height=8, radius=1.5, round=true, $tags="remove"); // } // Example: With a long joint like this, a taper makes the joint easy to assemble. It will go together easily and wedge tightly if you get the tolerances right. Specifying the taper with `back_width` may be easier than using a taper angle. // cuboid([50,30,10]) @@ -548,8 +550,9 @@ module dovetail(gender, width, height, slide, h, w, angle, slope, taper, back_wi is_def(back_width) ? (back_width-width) / 2 : 0; bigend_points = move([offset,slide+2*extra,0], p=smallend_points); - adjustment = $overlap * (gender == "male" ? -1 : 1); // Adjustment for default overlap in attach() - + //adjustment = $overlap * (gender == "male" ? -1 : 1); // Adjustment for default overlap in attach() + adjustment = 0; // Default overlap is assumed to be zero + attachable(anchor,spin,orient, size=[width+2*offset, slide, height]) { down(height/2+adjustment) { skin( @@ -601,7 +604,8 @@ module _pin_slot(l, r, t, d, nub, depth, stretch) { module _pin_shaft(r, lStraight, nub, nubscale, stretch, d, pointed) { - extra = 0.02; + extra = 0.02; // This sets the extra extension below the socket bottom + // so that difference() works without issues rPoint = r / sqrt(2); down(extra) cylinder(r = r, h = lStraight + extra); up(lStraight) { @@ -726,6 +730,8 @@ module snap_pin(size,r,radius,d,diameter, l,length, nub_depth, snap, thickness, // if you add a lubricant. If `pointed` is true the socket is pointed to receive a pointed pin, otherwise it has a rounded and and // will be shorter. If `fins` is set to true then two fins are included inside the socket to act as supports (which may help when printing tip up, // especially when `pointed=false`). The default orientation is DOWN with anchor BOTTOM so that you can difference() the socket away from an object. +// The socket extends 0.02 extra below its bottom anchor point so that differences will work correctly. (You must have $overlap smaller than 0.02 in +// attach or the socket will be beneath the surface of the parent object.) // . // The "large" or "standard" size pin has a length of 10.8 and diameter of 7. The "medium" pin has a length of 8 and diameter of 4.6. The "small" pin // has a length of 6 and diameter of 3.2. The "tiny" pin has a length of 4 and a diameter of 2.5. @@ -802,13 +808,14 @@ module snap_pin_socket(size, r, radius, l,length, d,diameter,nub_depth, snap, fi // make the socket with a larger depth than the clip (try 0.4 mm) to allow ease of insertion of the clip. The clearance // value does not apply to the depth. The splinesteps parameter increases the sampling of the clip curves. // . -// By default clips appear with orient=UP and sockets with orient=DOWN. +// By default clips appear with orient=UP and sockets with orient=DOWN. The clips and sockets extend 0.02 units below +// their base so that unions and differences will work without trouble, but be sure that the attach overlap is smaller +// than 0.02. // . // The first figure shows the dimensions of the rabbit clip. The second figure shows the clip in red overlayed on // its socket in yellow. The left clip has a nonzero clearance, so its socket is bigger than the clip all around. // The right hand locking clip has no clearance, but it has a lock clearance, which provides some space behind -// the lock to allow the clip to fit. (Note that depending on your printer, this can be set to zero.) -// +// the lock to allow the clip to fit. (Note that depending on your printer, this can be set to zero.) // Figure(2DMed): // snap=1.5; // comp=0.75; @@ -939,7 +946,8 @@ module rabbit_clip(type, length, width, snap, thickness, depth, compression=0.1 } else { anchor = default(anchor,BOTTOM); is_pin = in_list(type,["pin","male"]); - default_overlap = 0.01 * (is_pin?1:-1); // Shift by this much to undo default overlap + //default_overlap = 0.01 * (is_pin?1:-1); // Shift by this much to undo default overlap + default_overlap = 0; extra = 0.02; // Amount of extension below nominal based position for the socket, must exceed default overlap of 0.01 clearance = is_pin ? 0 : clearance; compression = is_pin ? compression : 0; @@ -989,8 +997,6 @@ module rabbit_clip(type, length, width, snap, thickness, depth, compression=0.1 bez = path_to_bezier(path,relsize=smoothing,tangents=tangent); rounded = bezier_path(bez,splinesteps=splinesteps); bounds = pointlist_bounds(rounded); - //kk = search([bounds[1].y], subindex(rounded,1)); - //echo(rounded[kk[0]]); extrapt = is_pin ? [] : [rounded[0] - [0,extra]]; finalpath = is_pin ? rounded : let(withclearance=offset(rounded, r=-clearance)) @@ -1005,6 +1011,7 @@ module rabbit_clip(type, length, width, snap, thickness, depth, compression=0.1 xflip_copy() right(clearance) polygon([sidepath[1]+[-thickness/10,lock_clearance], + sidepath[2]-[thickness*.75,0], sidepath[2], [sidepath[2].x,sidepath[1].y+lock_clearance]]); if (is_pin) diff --git a/vectors.scad b/vectors.scad index b110fd7..a98594a 100644 --- a/vectors.scad +++ b/vectors.scad @@ -355,4 +355,32 @@ function vp_nearest(points, tree, p, k) = subindex(_vp_nearest(points, tree, p, k),0); +// Function: search_radius() +// Usage: +// index_list = search_radius(points, queries, r, ); +// Description: +// Given a list of points and a compatible list of queries, for each query +// search the points list for all points whose distance from the query +// is less than or equal to r. The return value index_list[i] lists the indices +// in points of all matches to query q[i]. This list can be in arbitrary order. +// . +// This function is advantageous to use especially when both `points` and `queries` +// are large sets. The method contructs a vantage point tree and then uses it +// to check all the queries. If you use queries=points and set r to epsilon then +// you can find all of the approximate duplicates in a large list of vectors. +// Example: Finding duplicates in a list of vectors. With exact equality the order of the output is consistent, but with small variations [2,4] could occur in one position and [4,2] in the other one. +// v = array_group(rands(0,10,5*3,seed=9),3); +// points = [v[0],v[1],v[2],v[3],v[2],v[3],v[3],v[4]]; +// echo(search_radius(points,points,1e-9)); // Prints [[0],[1],[2,4],[3,5,6],[2,4],[3,5,6],[3,5,6],[7]] +// +function search_radius(points, queries, r, leafsize=25) = + assert(is_matrix(points),"Invalid points list") + assert(is_matrix(queries),"Invalid query list") + assert(len(points[0])==len(queries[0]), "Query vectors don't match length of points") + let( + vptree = vp_tree(points, leafsize) + ) + [for(q=queries) vp_search(points, vptree, q, r)]; + + // vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap