From 598ae04ba54c786c91e9c1ea641c11268b08187c Mon Sep 17 00:00:00 2001 From: Garth Minette Date: Sun, 19 Jul 2020 05:39:49 -0700 Subject: [PATCH 1/5] Tighten image comparison requirements. --- scripts/docs_gen.py | 2 +- version.scad | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/version.scad b/version.scad index eda7210..b15931a 100644 --- a/version.scad +++ b/version.scad @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,391]; +BOSL_VERSION = [2,0,392]; // Section: BOSL Library Version Functions From 14e013cd13529bfcffec47a7354acdaae4bcc6f0 Mon Sep 17 00:00:00 2001 From: Garth Minette Date: Sun, 19 Jul 2020 05:49:05 -0700 Subject: [PATCH 2/5] Bugfix for unit() changes in attachment --- attachments.scad | 2 +- version.scad | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/version.scad b/version.scad index b15931a..073f188 100644 --- a/version.scad +++ b/version.scad @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,392]; +BOSL_VERSION = [2,0,393]; // Section: BOSL Library Version Functions From 87c8adef659be38ec93fc835d2d319806433ecec Mon Sep 17 00:00:00 2001 From: Garth Minette Date: Sun, 19 Jul 2020 06:24:16 -0700 Subject: [PATCH 3/5] Bad use of unit() in debug_polyhedron() --- debug.scad | 17 +++++++++-------- version.scad | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) 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/version.scad b/version.scad index 073f188..b26cd44 100644 --- a/version.scad +++ b/version.scad @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,393]; +BOSL_VERSION = [2,0,394]; // Section: BOSL Library Version Functions From 375f1f2e3bf30ae0f68c011217ec42a33979afed Mon Sep 17 00:00:00 2001 From: Garth Minette Date: Sun, 19 Jul 2020 23:05:54 -0700 Subject: [PATCH 4/5] Bugfix for new unit() in affine_frame_map() --- affine.scad | 6 +++--- version.scad | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) 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/version.scad b/version.scad index b26cd44..5ce4534 100644 --- a/version.scad +++ b/version.scad @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,394]; +BOSL_VERSION = [2,0,395]; // Section: BOSL Library Version Functions From ae1a6d8d6137d2143b1dbc7f2eca7da6f4adbbbe Mon Sep 17 00:00:00 2001 From: Garth Minette Date: Sun, 19 Jul 2020 23:07:49 -0700 Subject: [PATCH 5/5] Rewrote line_closest_point() and segment_closest_point() to support 3D. Added ray_closest_point(). --- geometry.scad | 185 ++++++++++++++++++++++++++++++++++++++++++++++---- version.scad | 2 +- 2 files changed, 173 insertions(+), 14 deletions(-) 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/version.scad b/version.scad index 5ce4534..4ba73cf 100644 --- a/version.scad +++ b/version.scad @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,395]; +BOSL_VERSION = [2,0,396]; // Section: BOSL Library Version Functions