Merge pull request #1042 from adrianVmariano/master

tapezoid angle fix (angle->ang)
This commit is contained in:
Revar Desmera 2023-02-03 15:08:24 -08:00 committed by GitHub
commit 9e752547d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 37 deletions

View File

@ -28,20 +28,38 @@
// parent. This means that `$` variables like `$idx` are not available in assignments, so if you use them you will get a warning about an unknown variable.
// Two workarounds exist, neither of which are needed in newer versions of OpenSCAD. The workarounds solve the problem because
// **modules** execute after their parent, so the `$` variables **are** available in modules. You can put your assignments
// in a `let()` module, or you can wrap your child in a `union()`. Both methods appear below in the examples.
// Example(2D): This example shows how we can use `$idx` to produce **different** geometry at each index.
// in a `let()` module, or you can wrap your child in a `union()`. Both methods appear below.
// ```
// xcopies(n=10, spacing=10)
// text(str($idx));
// Example(2D): Here the children are sometimes squares and sometimes circles as determined by the conditional `if` module. This use of `if` is OK because no variables are assigned.
// ```
// Figure(2D): This example shows how we can use `$idx` to produce **different** geometry at each index.
// xcopies(n=10, spacing=10)
// text(str($idx));
// Continues:
// Figure(2D): Here the children are sometimes squares and sometimes circles as determined by the conditional `if` module. This use of `if` is OK because no variables are assigned.
// xcopies(n=4, spacing=10)
// if($idx%2==0) circle(r=3,$fn=16);
// else rect(6);
// Example(2D): Suppose we would like to color odd and even index copies differently. In this example we compute the color for a given child from `$idx` using the ternary operator. The `let()` module is a module that sets variables and makes them available to its children. Note that multiple assignments in `let()` are separated by commas, not semicolons.
// Continues:
// ```
// xcopies(n=4, spacing=10)
// if($idx%2==0) circle(r=3,$fn=16);
// else rect(6);
// ```
// Figure(2D): Suppose we would like to color odd and even index copies differently. In this example we compute the color for a given child from `$idx` using the ternary operator. The `let()` module is a module that sets variables and makes them available to its children. Note that multiple assignments in `let()` are separated by commas, not semicolons.
// xcopies(n=6, spacing=10){
// let(c = $idx % 2 == 0 ? "red" : "green")
// color(c) rect(6);
// }
// Example(2D): This example shows how you can change the position of children adaptively. If you want to avoid repeating your code for each case, this requires storing a transformation matrix in a variable and then applying it using `multmatrix()`. We wrap our code in `union()` to ensure that it works in OpenSCAD 2021.01.
// Continues:
// ```
// xcopies(n=6, spacing=10){
// let(c = $idx % 2 == 0 ? "red" : "green")
// color(c) rect(6);
// }
// ```
// Figure(2D): This example shows how you can change the position of children adaptively. If you want to avoid repeating your code for each case, this requires storing a transformation matrix in a variable and then applying it using `multmatrix()`. We wrap our code in `union()` to ensure that it works in OpenSCAD 2021.01.
// xcopies(n=5,spacing=10)
// union()
// {
@ -49,6 +67,16 @@
// spin = zrot(180*$idx/4);
// multmatrix(shiftback*spin) stroke([[-4,0],[4,0]],endcap2="arrow2",width=1/2);
// }
// Continues:
// ```
// xcopies(n=5,spacing=10)
// union()
// {
// shiftback = $idx%2==0 ? back(5) : IDENT;
// spin = zrot(180*$idx/4);
// multmatrix(shiftback*spin) stroke([[-4,0],[4,0]],endcap2="arrow2",width=1/2);
// }
// ```
//////////////////////////////////////////////////////////////////////

View File

@ -845,24 +845,26 @@ module right_triangle(size=[1,1], center, anchor, spin=0) {
// Function&Module: trapezoid()
// Usage: As Module
// trapezoid(h, w1, w2, [shift=], [rounding=], [chamfer=], ...) [ATTACHMENTS];
// trapezoid(h, w1, angle=, ...) [ATTACHMENTS];
// trapezoid(h, w2, angle=, ...) [ATTACHMENTS];
// trapezoid(w1, w2, angle=, ...) [ATTACHMENTS];
// trapezoid(h, w1, w2, [shift=], [rounding=], [chamfer=], [flip=], ...) [ATTACHMENTS];
// trapezoid(h, w1, ang=, [rounding=], [chamfer=], [flip=], ...) [ATTACHMENTS];
// trapezoid(h, w2=, ang=, [rounding=], [chamfer=], [flip=], ...) [ATTACHMENTS];
// trapezoid(w1=, w2=, ang=, [rounding=], [chamfer=], [flip=], ...) [ATTACHMENTS];
// Usage: As Function
// path = trapezoid(...);
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
// See Also: rect(), square()
// Description:
// When called as a function, returns a 2D path for a trapezoid with parallel front and back sides.
// When called as a module, creates a 2D trapezoid with parallel front and back sides.
// When called as a function, returns a 2D path for a trapezoid with parallel front and back (top and bottom) sides.
// When called as a module, creates a 2D trapezoid. You can specify the trapezoid by giving its height and the lengths
// of its two bases. Alternatively, you can omit one of those parameters and specify the lower angle(s).
// The shift parameter, which cannot be combined with ang, shifts the back (top) of the trapezoid to the right.
// Arguments:
// 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
// ang = Specify the bottom angle(s) of the trapezoid. Can give a scalar for an isosceles trapezoid or a list of two angles, the left angle and right angle. You must omit one of `h`, `w1`, or `w2` to allow the freedom to control the angles.
// shift = Scalar value to shift the back of the trapezoid along the X axis by. Cannot be combined with ang. Default: 0
// rounding = The rounding radius for the corners. If given as a list of four numbers, gives individual radii for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no rounding)
// chamfer = The Length of the chamfer faces at the corners. If given as a list of four numbers, gives individual chamfers for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no chamfer)
// flip = If true, negative roundings and chamfers will point forward and back instead of left and right. Default: `false`.
@ -872,11 +874,11 @@ module right_triangle(size=[1,1], center, anchor, spin=0) {
// 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=30, 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);
// trapezoid(h=20, w1=30, ang=60);
// trapezoid(h=20, w1=20, ang=120);
// trapezoid(h=20, w2=10, ang=60);
// trapezoid(h=20, w1=50, ang=[40,60]);
// trapezoid(w1=30, w2=10, ang=[30,90]);
// Example(2D): Chamfered Trapezoid
// trapezoid(h=30, w1=60, w2=40, chamfer=5);
// Example(2D): Negative Chamfered Trapezoid
@ -893,20 +895,30 @@ module right_triangle(size=[1,1], center, anchor, spin=0) {
// trapezoid(h=30, w1=60, w2=40, rounding=[5,0,-10,0],chamfer=[0,8,0,-15],$fa=1,$fs=1);
// Example(2D): Called as Function
// stroke(closed=true, trapezoid(h=30, w1=40, w2=20));
function trapezoid(h, w1, w2, angle, shift=0, chamfer=0, rounding=0, flip=false, anchor=CENTER, spin=0) =
function trapezoid(h, w1, w2, ang, shift, chamfer=0, rounding=0, flip=false, anchor=CENTER, spin=0, angle) =
assert(is_undef(angle), "The angle parameter has been replaced by ang, which specifies trapezoid interior angle")
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))
assert(is_undef(ang) || is_finite(ang) || is_vector(ang,2))
assert(num_defined([h, w1, w2, ang]) == 3, "Must give exactly 3 of the arguments h, w1, w2, and angle.")
assert(is_undef(shift) || is_finite(shift))
assert(num_defined([shift,ang])<2, "Cannot specify shift and ang together")
assert(is_finite(chamfer) || is_vector(chamfer,4))
assert(is_finite(rounding) || is_vector(rounding,4))
let(
ang = force_list(ang,2),
angOK = ang==[undef,undef] || (all_positive(ang) && ang[0]<180 && ang[1]<180)
)
assert(angOK, "trapezoid angles must be strictly between 0 and 180")
let(
simple = chamfer==0 && rounding==0,
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),
h = is_def(h)? h : (w1-w2) * sin(ang[0]) * sin(ang[1]) / sin(ang[0]+ang[1]),
x1 = is_undef(ang[0]) || ang[0]==90 ? 0 : h/tan(ang[0]),
x2 = is_undef(ang[1]) || ang[1]==90 ? 0 : h/tan(ang[1]),
w1 = is_def(w1)? w1 : w2 + x1 + x2,
w2 = is_def(w2)? w2 : w1 - x1 - x2,
shift = first_defined([shift,(x1-x2)/2]),
chamfs = is_num(chamfer)? [for (i=[0:3]) chamfer] :
assert(len(chamfer)==4) chamfer,
rounds = is_num(rounding)? [for (i=[0:3]) rounding] :
@ -966,19 +978,23 @@ function trapezoid(h, w1, w2, angle, shift=0, chamfer=0, rounding=0, flip=false,
),
],
path = reverse(cpath)
) simple
) true //simple // force regular anchoring
? reorient(anchor,spin, two_d=true, size=[w1,h], size2=w2, shift=shift, p=path)
: reorient(anchor,spin, two_d=true, path=path, p=path);
module trapezoid(h, w1, w2, angle, shift=0, chamfer=0, rounding=0, flip=false, anchor=CENTER, spin=0) {
path = trapezoid(h=h, w1=w1, w2=w2, angle=angle, shift=shift, chamfer=chamfer, rounding=rounding, flip=flip);
module trapezoid(h, w1, w2, ang, shift, chamfer=0, rounding=0, flip=false, anchor=CENTER, spin=0, angle) {
path = trapezoid(h=h, w1=w1, w2=w2, ang=ang, shift=shift, chamfer=chamfer, rounding=rounding, flip=flip, angle=angle);
union() {
simple = chamfer==0 && rounding==0;
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);
simple = true; //chamfer==0 && rounding==0; // force "normal" anchoring for now
ang = force_list(ang,2);
h = is_def(h)? h : (w1-w2) * sin(ang[0]) * sin(ang[1]) / sin(ang[0]+ang[1]);
x1 = is_undef(ang[0]) || ang[0]==90 ? 0 : h/tan(ang[0]);
x2 = is_undef(ang[1]) || ang[1]==90 ? 0 : h/tan(ang[1]);
w1 = is_def(w1)? w1 : w2 + x1 + x2;
w2 = is_def(w2)? w2 : w1 - x1 - x2;
shift = first_defined([shift,(x1-x2)/2]);
if (simple) {
attachable(anchor,spin, two_d=true, size=[w1,h], size2=w2, shift=shift) {
polygon(path);
@ -1275,8 +1291,7 @@ function teardrop2d(r, ang=45, cap_h, d, circum=false, realign=false, anchor=CEN
if (p) [i,p]
],
i = last(isect)[0],
p = last(isect)[1],
ff=echo(isect)
p = last(isect)[1]
)
[
cap[0],

View File

@ -1064,8 +1064,8 @@ module rotate_sweep(
// turns = number of revolutions to spiral up along the height.
// ---
// d = Diameter of the spiral to extrude along.
// d1|r1 = Bottom inside diameter or radius of spiral to extrude along.
// d2|r2 = Top inside diameter or radius of spiral to extrude along.
// d1/r1 = Bottom inside diameter or radius of spiral to extrude along.
// d2/r2 = Top inside diameter or radius of spiral to extrude along.
// taper = Length of tapers for thread ends. Positive to add taper to threads, negative to taper within specified length. Default: 0
// taper1 = Length of taper for bottom thread end
// taper2 = Length of taper for top thread end

View File

@ -131,7 +131,7 @@ function vnf_vertex_array(
) =
assert(!(any([caps,cap1,cap2]) && !col_wrap), "col_wrap must be true if caps are requested")
assert(!(any([caps,cap1,cap2]) && row_wrap), "Cannot combine caps with row_wrap")
assert(in_list(style,["default","alt","quincunx", "convex","concave", "min_edge"]))
assert(in_list(style,["default","alt","quincunx", "convex","concave", "min_edge","min_area"]))
assert(is_matrix(points[0], n=3),"Point array has the wrong shape or points are not 3d")
assert(is_consistent(points), "Non-rectangular or invalid point array")
let(
@ -174,6 +174,15 @@ function vnf_vertex_array(
[[i1,i5,i2],[i2,i5,i3],[i3,i5,i4],[i4,i5,i1]]
: style=="alt"?
[[i1,i4,i2],[i2,i4,i3]]
: style=="min_area"?
let(
area42 = norm(cross(pts[i2]-pts[i1], pts[14]-pts[i1]))+norm(cross(pts[i4]-pts[i3], pts[i2]-pts[i3])),
area13 = norm(cross(pts[i1]-pts[i4], pts[i3]-pts[i4]))+norm(cross(pts[i3]-pts[i2], pts[i1]-pts[i2])),
minarea_edge = area42 < area13 + EPSILON
? [[i1,i4,i2],[i2,i4,i3]]
: [[i1,i3,i2],[i1,i4,i3]]
)
minarea_edge
: style=="min_edge"?
let(
d42=norm(pts[i4]-pts[i2]),