diff --git a/geometry.scad b/geometry.scad index b95a4e9..6a69e11 100644 --- a/geometry.scad +++ b/geometry.scad @@ -573,7 +573,7 @@ function hyp_opp_to_adj(hyp,opp) = // adj = hyp_ang_to_adj(8,60); // Returns: 4 function hyp_ang_to_adj(hyp,ang) = assert(is_finite(hyp) && hyp>=0, "Triangle side length should be a positive number." ) - assert(is_finite(ang) && ang>0 && ang<90, "The angle should be an acute angle." ) + assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." ) hyp*cos(ang); @@ -590,7 +590,7 @@ function hyp_ang_to_adj(hyp,ang) = // adj = opp_ang_to_adj(8,30); // Returns: 4 function opp_ang_to_adj(opp,ang) = assert(is_finite(opp) && opp>=0, "Triangle side length should be a positive number." ) - assert(is_finite(ang) && ang>0 && ang<90, "The angle should be an acute angle." ) + assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." ) opp/tan(ang); @@ -622,7 +622,7 @@ function hyp_adj_to_opp(hyp,adj) = // opp = hyp_ang_to_opp(8,30); // Returns: 4 function hyp_ang_to_opp(hyp,ang) = assert(is_finite(hyp)&&hyp>=0, "Triangle side length should be a positive number." ) - assert(is_finite(ang) && ang>0 && ang<90, "The angle should be an acute angle." ) + assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." ) hyp*sin(ang); @@ -638,7 +638,7 @@ function hyp_ang_to_opp(hyp,ang) = // opp = adj_ang_to_opp(8,45); // Returns: 8 function adj_ang_to_opp(adj,ang) = assert(is_finite(adj)&&adj>=0, "Triangle side length should be a positive number." ) - assert(is_finite(ang) && ang>0 && ang<90, "The angle should be an acute angle." ) + assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." ) adj*tan(ang); @@ -670,7 +670,7 @@ function adj_opp_to_hyp(adj,opp) = // hyp = adj_ang_to_hyp(4,60); // Returns: 8 function adj_ang_to_hyp(adj,ang) = assert(is_finite(adj) && adj>=0, "Triangle side length should be a positive number." ) - assert(is_finite(ang) && ang>0 && ang<90, "The angle should be an acute angle." ) + assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." ) adj/cos(ang); @@ -686,7 +686,7 @@ function adj_ang_to_hyp(adj,ang) = // hyp = opp_ang_to_hyp(4,30); // Returns: 8 function opp_ang_to_hyp(opp,ang) = assert(is_finite(opp) && opp>=0, "Triangle side length should be a positive number." ) - assert(is_finite(ang) && ang>0 && ang<90, "The angle should be an acute angle." ) + assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." ) opp/sin(ang); diff --git a/shapes2d.scad b/shapes2d.scad index 5733870..23a6430 100644 --- a/shapes2d.scad +++ b/shapes2d.scad @@ -1200,26 +1200,56 @@ module octagon(r, d, or, od, ir, id, side, rounding=0, realign=false, align_tip, // h = The Y axis height of the trapezoid. // w1 = The X axis width of the front end of the trapezoid. // w2 = The X axis width of the back end of the trapezoid. +// angle = If given in place of `h`, `w1`, or `w2`, then the missing value is calculated such that the right side has that angle away from the Y axis. +// shift = Scalar value to shift the back of the trapezoid along the X axis by. Default: 0 // 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` // Examples(2D): // trapezoid(h=30, w1=40, w2=20); // trapezoid(h=25, w1=20, w2=35); // trapezoid(h=20, w1=40, w2=0); +// trapezoid(h=20, w1=20, angle=30); +// trapezoid(h=20, w1=20, angle=-30); +// trapezoid(h=20, w2=10, angle=30); +// trapezoid(h=20, w2=30, angle=-30); +// trapezoid(w1=30, w2=10, angle=30); // Example(2D): Called as Function // stroke(closed=true, trapezoid(h=30, w1=40, w2=20)); -function trapezoid(h, w1, w2, anchor=CENTER, spin=0) = +function trapezoid(h, w1, w2, angle, shift=0, anchor=CENTER, spin=0) = + assert(is_undef(h) || is_finite(h)) + assert(is_undef(w1) || is_finite(w1)) + assert(is_undef(w2) || is_finite(w2)) + assert(is_undef(angle) || is_finite(angle)) + assert(num_defined([h, w1, w2, angle]) == 3, "Must give exactly 3 of the arguments h, w1, w2, and angle.") + assert(is_finite(shift)) let( - path = [[w1/2,-h/2], [-w1/2,-h/2], [-w2/2,h/2], [w2/2,h/2]] - ) reorient(anchor,spin, two_d=true, size=[w1,h], size2=w2, p=path); + h = !is_undef(h)? h : opp_ang_to_adj(abs(w2-w1)/2, abs(angle)), + w1 = !is_undef(w1)? w1 : w2 + 2*(adj_ang_to_opp(h, angle) + shift), + w2 = !is_undef(w2)? w2 : w1 - 2*(adj_ang_to_opp(h, angle) + shift), + path = [[w1/2,-h/2], [-w1/2,-h/2], [-w2/2+shift,h/2], [w2/2+shift,h/2]] + ) + assert(w1>=0 && w2>=0 && h>0, "Degenerate trapezoid geometry.") + reorient(anchor,spin, two_d=true, size=[w1,h], size2=w2, p=path); -module trapezoid(h, w1, w2, anchor=CENTER, spin=0) { - path = [[w1/2,-h/2], [-w1/2,-h/2], [-w2/2,h/2], [w2/2,h/2]]; - attachable(anchor,spin, two_d=true, size=[w1,h], size2=w2) { - polygon(path); - children(); +module trapezoid(h, w1, w2, angle, shift=0, anchor=CENTER, spin=0) { + assert(is_undef(h) || is_finite(h)); + assert(is_undef(w1) || is_finite(w1)); + assert(is_undef(w2) || is_finite(w2)); + assert(is_undef(angle) || is_finite(angle)); + assert(num_defined([h, w1, w2, angle]) == 3, "Must give exactly 3 of the arguments h, w1, w2, and angle."); + assert(is_finite(shift)); + union() { + h = !is_undef(h)? h : opp_ang_to_adj(abs(w2-w1)/2, abs(angle)); + w1 = !is_undef(w1)? w1 : w2 + 2*(adj_ang_to_opp(h, angle) + shift); + w2 = !is_undef(w2)? w2 : w1 - 2*(adj_ang_to_opp(h, angle) + shift); + assert(w1>=0 && w2>=0 && h>0, "Degenerate trapezoid geometry."); + path = [[w1/2,-h/2], [-w1/2,-h/2], [-w2/2+shift,h/2], [w2/2+shift,h/2]]; + attachable(anchor,spin, two_d=true, size=[w1,h], size2=w2) { + polygon(path); + children(); + } } } diff --git a/version.scad b/version.scad index 736efd1..dec55e9 100644 --- a/version.scad +++ b/version.scad @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,444]; +BOSL_VERSION = [2,0,445]; // Section: BOSL Library Version Functions