mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
VNF interface update skin.scad and shapes2d.scad
This commit is contained in:
parent
7dfb99c5bb
commit
d576526b60
4 changed files with 128 additions and 88 deletions
|
@ -29,6 +29,8 @@ $parent_geom = undef;
|
||||||
$tags_shown = [];
|
$tags_shown = [];
|
||||||
$tags_hidden = [];
|
$tags_hidden = [];
|
||||||
|
|
||||||
|
_ANCHOR_TYPES = ["intersect","hull"];
|
||||||
|
|
||||||
|
|
||||||
// Section: Anchors, Spin, and Orientation
|
// Section: Anchors, Spin, and Orientation
|
||||||
// This library adds the concept of anchoring, spin and orientation to the `cube()`, `cylinder()`
|
// This library adds the concept of anchoring, spin and orientation to the `cube()`, `cylinder()`
|
||||||
|
@ -1885,7 +1887,7 @@ module show_anchors(s=10, std=true, custom=true) {
|
||||||
anchor_arrow(s, color="cyan");
|
anchor_arrow(s, color="cyan");
|
||||||
}
|
}
|
||||||
color("black")
|
color("black")
|
||||||
// tags("anchor-arrow")
|
tags("anchor-arrow")
|
||||||
{
|
{
|
||||||
xrot(two_d? 0 : 90) {
|
xrot(two_d? 0 : 90) {
|
||||||
back(s/3) {
|
back(s/3) {
|
||||||
|
|
|
@ -244,15 +244,20 @@ module circle(r, d, anchor=CENTER, spin=0) {
|
||||||
// ellipse(d=50, anchor=FRONT, spin=45);
|
// ellipse(d=50, anchor=FRONT, spin=45);
|
||||||
// Example(NORENDER): Called as Function
|
// Example(NORENDER): Called as Function
|
||||||
// path = ellipse(d=50, anchor=FRONT, spin=45);
|
// path = ellipse(d=50, anchor=FRONT, spin=45);
|
||||||
module ellipse(r, d, realign=false, circum=false, anchor=CENTER, spin=0) {
|
module ellipse(r, d, realign=false, circum=false, uniform=false, anchor=CENTER, spin=0)
|
||||||
r = get_radius(r=r, d=d, dflt=1);
|
{
|
||||||
dummy = assert((is_finite(r) || is_vector(r,2)) && all_positive(r), "Invalid radius or diameter for ellipse");
|
r = force_list(get_radius(r=r, d=d, dflt=1),2);
|
||||||
|
dummy = assert(is_vector(r,2) && all_positive(r), "Invalid radius or diameter for ellipse");
|
||||||
sides = segs(max(r));
|
sides = segs(max(r));
|
||||||
sc = circum? (1 / cos(180/sides)) : 1;
|
sc = circum? (1 / cos(180/sides)) : 1;
|
||||||
rx = default(r[0],r) * sc;
|
rx = r.x * sc;
|
||||||
ry = default(r[1],r) * sc;
|
ry = r.y * sc;
|
||||||
attachable(anchor,spin, two_d=true, r=[rx,ry]) {
|
attachable(anchor,spin, two_d=true, r=[rx,ry]) {
|
||||||
if (rx < ry) {
|
if (uniform) {
|
||||||
|
assert(!circum, "Circum option not allowed when \"uniform\" is true");
|
||||||
|
polygon(ellipse(r,realign=realign, circum=circum, uniform=true));
|
||||||
|
}
|
||||||
|
else if (rx < ry) {
|
||||||
xscale(rx/ry) {
|
xscale(rx/ry) {
|
||||||
zrot(realign? 180/sides : 0) {
|
zrot(realign? 180/sides : 0) {
|
||||||
circle(r=ry, $fn=sides);
|
circle(r=ry, $fn=sides);
|
||||||
|
@ -270,14 +275,42 @@ module ellipse(r, d, realign=false, circum=false, anchor=CENTER, spin=0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function ellipse(r, d, realign=false, circum=false, anchor=CENTER, spin=0) =
|
// Iterative refinement to produce an inscribed polygon
|
||||||
|
// in an ellipse whose side lengths are all equal
|
||||||
|
function _ellipse_refine(a,b,N, _theta=[]) =
|
||||||
|
len(_theta)==0? _ellipse_refine(a,b,N,lerpn(0,360,N,endpoint=false))
|
||||||
|
:
|
||||||
|
let(
|
||||||
|
pts = [for(t=_theta) [a*cos(t),b*sin(t)]],
|
||||||
|
lenlist= path_segment_lengths(pts,closed=true),
|
||||||
|
meanlen = mean(lenlist),
|
||||||
|
error = lenlist/meanlen
|
||||||
|
)
|
||||||
|
all_equal(error,EPSILON) ? pts
|
||||||
|
:
|
||||||
|
let(
|
||||||
|
dtheta = [each deltas(_theta),
|
||||||
|
360-last(_theta)],
|
||||||
|
newdtheta = [for(i=idx(dtheta)) dtheta[i]/error[i]],
|
||||||
|
adjusted = [0,each cumsum(list_head(newdtheta / sum(newdtheta) * 360))]
|
||||||
|
)
|
||||||
|
_ellipse_refine(a,b,N,adjusted);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function ellipse(r, d, realign=false, circum=false, uniform=false, anchor=CENTER, spin=0) =
|
||||||
|
let(
|
||||||
|
r = force_list(get_radius(r=r, d=d, dflt=1),2),
|
||||||
|
sides = segs(max(r))
|
||||||
|
)
|
||||||
|
uniform ? assert(!circum, "Circum option not allowed when \"uniform\" is true")
|
||||||
|
reorient(anchor,spin,two_d=true,r=[r.x,r.y],p=_ellipse_refine(r.x,r.y,sides))
|
||||||
|
:
|
||||||
let(
|
let(
|
||||||
r = get_radius(r=r, d=d, dflt=1),
|
|
||||||
sides = segs(max(r)),
|
|
||||||
offset = realign? 180/sides : 0,
|
offset = realign? 180/sides : 0,
|
||||||
sc = circum? (1 / cos(180/sides)) : 1,
|
sc = circum? (1 / cos(180/sides)) : 1,
|
||||||
rx = default(r[0],r) * sc,
|
rx = r.x * sc,
|
||||||
ry = default(r[1],r) * sc,
|
ry = r.y * sc,
|
||||||
pts = [for (i=[0:1:sides-1]) let(a=360-offset-i*360/sides) [rx*cos(a), ry*sin(a)]]
|
pts = [for (i=[0:1:sides-1]) let(a=360-offset-i*360/sides) [rx*cos(a), ry*sin(a)]]
|
||||||
) reorient(anchor,spin, two_d=true, r=[rx,ry], p=pts);
|
) reorient(anchor,spin, two_d=true, r=[rx,ry], p=pts);
|
||||||
|
|
||||||
|
@ -780,6 +813,7 @@ module trapezoid(h, w1, w2, angle, shift=0, chamfer=0, rounding=0, anchor=CENTER
|
||||||
// align_pit = If given as a 2D vector, rotates the whole shape so that the first inner corner is pointed towards that direction. This occurs before spin.
|
// align_pit = If given as a 2D vector, rotates the whole shape so that the first inner corner is pointed towards that direction. This occurs before spin.
|
||||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
|
// 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`
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
||||||
|
// atype = Choose "hull" or "intersect" anchor methods. Default: "hull"
|
||||||
// Extra Anchors:
|
// Extra Anchors:
|
||||||
// "tip0" ... "tip4" = Each tip has an anchor, pointing outwards.
|
// "tip0" ... "tip4" = Each tip has an anchor, pointing outwards.
|
||||||
// "pit0" ... "pit4" = The inside corner between each tip has an anchor, pointing outwards.
|
// "pit0" ... "pit4" = The inside corner between each tip has an anchor, pointing outwards.
|
||||||
|
@ -801,7 +835,8 @@ module trapezoid(h, w1, w2, angle, shift=0, chamfer=0, rounding=0, anchor=CENTER
|
||||||
// stroke([[0,0],[0,7]], endcap2="arrow2");
|
// stroke([[0,0],[0,7]], endcap2="arrow2");
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
// stroke(closed=true, star(n=5, r=50, ir=25));
|
// stroke(closed=true, star(n=5, r=50, ir=25));
|
||||||
function star(n, r, ir, d, or, od, id, step, realign=false, align_tip, align_pit, anchor=CENTER, spin=0, _mat, _anchs) =
|
function star(n, r, ir, d, or, od, id, step, realign=false, align_tip, align_pit, anchor=CENTER, spin=0, atype="hull", _mat, _anchs) =
|
||||||
|
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"")
|
||||||
assert(is_undef(align_tip) || is_vector(align_tip))
|
assert(is_undef(align_tip) || is_vector(align_tip))
|
||||||
assert(is_undef(align_pit) || is_vector(align_pit))
|
assert(is_undef(align_pit) || is_vector(align_pit))
|
||||||
assert(is_undef(align_tip) || is_undef(align_pit), "Can only specify one of align_tip and align_pit")
|
assert(is_undef(align_tip) || is_undef(align_pit), "Can only specify one of align_tip and align_pit")
|
||||||
|
@ -843,10 +878,11 @@ function star(n, r, ir, d, or, od, id, step, realign=false, align_tip, align_pit
|
||||||
named_anchor(str("midpt",i), pos, unit(pos,BACK), 0),
|
named_anchor(str("midpt",i), pos, unit(pos,BACK), 0),
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
) reorient(anchor,spin, two_d=true, path=path, p=path, anchors=anchors);
|
) reorient(anchor,spin, two_d=true, path=path, p=path, extent=atype=="hull", anchors=anchors);
|
||||||
|
|
||||||
|
|
||||||
module star(n, r, ir, d, or, od, id, step, realign=false, align_tip, align_pit, anchor=CENTER, spin=0) {
|
module star(n, r, ir, d, or, od, id, step, realign=false, align_tip, align_pit, anchor=CENTER, spin=0, atype="hull") {
|
||||||
|
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"");
|
||||||
assert(is_undef(align_tip) || is_vector(align_tip));
|
assert(is_undef(align_tip) || is_vector(align_tip));
|
||||||
assert(is_undef(align_pit) || is_vector(align_pit));
|
assert(is_undef(align_pit) || is_vector(align_pit));
|
||||||
assert(is_undef(align_tip) || is_undef(align_pit), "Can only specify one of align_tip and align_pit");
|
assert(is_undef(align_tip) || is_undef(align_pit), "Can only specify one of align_tip and align_pit");
|
||||||
|
@ -874,7 +910,7 @@ module star(n, r, ir, d, or, od, id, step, realign=false, align_tip, align_pit,
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
path = star(n=n, r=r, ir=ir, realign=realign, _mat=mat, _anchs=anchors);
|
path = star(n=n, r=r, ir=ir, realign=realign, _mat=mat, _anchs=anchors);
|
||||||
attachable(anchor,spin, two_d=true, path=path, anchors=anchors) {
|
attachable(anchor,spin, two_d=true, path=path, extent=atype=="hull", anchors=anchors) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
@ -948,7 +984,7 @@ module jittered_poly(path, dist=1/512) {
|
||||||
// Function&Module: teardrop2d()
|
// Function&Module: teardrop2d()
|
||||||
//
|
//
|
||||||
// Description:
|
// Description:
|
||||||
// Makes a 2D teardrop shape. Useful for extruding into 3D printable holes.
|
// Makes a 2D teardrop shape. Useful for extruding into 3D printable holes. Uses "intersect" style anchoring.
|
||||||
//
|
//
|
||||||
// Usage: As Module
|
// Usage: As Module
|
||||||
// teardrop2d(r/d=, [ang], [cap_h]);
|
// teardrop2d(r/d=, [ang], [cap_h]);
|
||||||
|
@ -979,7 +1015,7 @@ module jittered_poly(path, dist=1/512) {
|
||||||
module teardrop2d(r, ang=45, cap_h, d, anchor=CENTER, spin=0)
|
module teardrop2d(r, ang=45, cap_h, d, anchor=CENTER, spin=0)
|
||||||
{
|
{
|
||||||
path = teardrop2d(r=r, d=d, ang=ang, cap_h=cap_h);
|
path = teardrop2d(r=r, d=d, ang=ang, cap_h=cap_h);
|
||||||
attachable(anchor,spin, two_d=true, path=path) {
|
attachable(anchor,spin, two_d=true, path=path, extent=false) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
@ -1008,7 +1044,7 @@ function teardrop2d(r, ang=45, cap_h, d, anchor=CENTER, spin=0) =
|
||||||
),
|
),
|
||||||
maxx_idx = max_index(column(path,0)),
|
maxx_idx = max_index(column(path,0)),
|
||||||
path2 = list_rotate(path,maxx_idx)
|
path2 = list_rotate(path,maxx_idx)
|
||||||
) reorient(anchor,spin, two_d=true, path=path2, p=path2);
|
) reorient(anchor,spin, two_d=true, path=path2, p=path2, extent=false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1023,7 +1059,7 @@ function teardrop2d(r, ang=45, cap_h, d, anchor=CENTER, spin=0) =
|
||||||
// See Also: circle(), ellipse()
|
// See Also: circle(), ellipse()
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a function, returns a 2D path forming a shape of two circles joined by curved waist.
|
// When called as a function, returns a 2D path forming a shape of two circles joined by curved waist.
|
||||||
// When called as a module, creates a 2D shape of two circles joined by curved waist.
|
// When called as a module, creates a 2D shape of two circles joined by curved waist. Uses "hull" style anchoring.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// r = The radius of the end circles.
|
// r = The radius of the end circles.
|
||||||
// spread = The distance between the centers of the end circles. Default: 10
|
// spread = The distance between the centers of the end circles. Default: 10
|
||||||
|
@ -1094,6 +1130,8 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a function, returns a 2D path for the outline of the [Superformula](https://en.wikipedia.org/wiki/Superformula) shape.
|
// When called as a function, returns a 2D path for the outline of the [Superformula](https://en.wikipedia.org/wiki/Superformula) shape.
|
||||||
// When called as a module, creates a 2D [Superformula](https://en.wikipedia.org/wiki/Superformula) shape.
|
// When called as a module, creates a 2D [Superformula](https://en.wikipedia.org/wiki/Superformula) shape.
|
||||||
|
// Note that the "hull" type anchoring (the default) is more intuitive for concave star-like shapes, but the anchor points do not
|
||||||
|
// necesarily lie on the line of the anchor vector, which can be confusing, especially for simpler, ellipse-like shapes.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// step = The angle step size for sampling the superformula shape. Smaller steps are slower but more accurate.
|
// step = The angle step size for sampling the superformula shape. Smaller steps are slower but more accurate.
|
||||||
// m1 = The m1 argument for the superformula. Default: 4.
|
// m1 = The m1 argument for the superformula. Default: 4.
|
||||||
|
@ -1108,6 +1146,7 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
||||||
// d = Diameter of the shape. Scale shape to fit in a circle of diameter d.
|
// d = Diameter of the shape. Scale shape to fit in a circle of diameter d.
|
||||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
|
// 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`
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
||||||
|
// atype = Select "hull" or "intersect" style anchoring. Default: "hull".
|
||||||
// Example(2D):
|
// Example(2D):
|
||||||
// supershape(step=0.5,m1=16,m2=16,n1=0.5,n2=0.5,n3=16,r=50);
|
// supershape(step=0.5,m1=16,m2=16,n1=0.5,n2=0.5,n3=16,r=50);
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
|
@ -1133,8 +1172,9 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
||||||
// Examples:
|
// Examples:
|
||||||
// linear_extrude(height=0.3, scale=0) supershape(step=1, m1=6, n1=0.4, n2=0, n3=6);
|
// linear_extrude(height=0.3, scale=0) supershape(step=1, m1=6, n1=0.4, n2=0, n3=6);
|
||||||
// linear_extrude(height=5, scale=0) supershape(step=1, b=3, m1=6, n1=3.8, n2=16, n3=10);
|
// linear_extrude(height=5, scale=0) supershape(step=1, b=3, m1=6, n1=3.8, n2=16, n3=10);
|
||||||
function supershape(step=0.5, m1=4, m2, n1=1, n2, n3, a=1, b, r, d,anchor=CENTER, spin=0) =
|
function supershape(step=0.5, m1=4, m2, n1=1, n2, n3, a=1, b, r, d,anchor=CENTER, spin=0, atype="hull") =
|
||||||
let(
|
let(
|
||||||
|
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\""),
|
||||||
r = get_radius(r=r, d=d, dflt=undef),
|
r = get_radius(r=r, d=d, dflt=undef),
|
||||||
m2 = is_def(m2) ? m2 : m1,
|
m2 = is_def(m2) ? m2 : m1,
|
||||||
n2 = is_def(n2) ? n2 : n1,
|
n2 = is_def(n2) ? n2 : n1,
|
||||||
|
@ -1146,11 +1186,11 @@ function supershape(step=0.5, m1=4, m2, n1=1, n2, n3, a=1, b, r, d,anchor=CENTER
|
||||||
rads = [for (theta = angs) _superformula(theta=theta,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b)],
|
rads = [for (theta = angs) _superformula(theta=theta,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b)],
|
||||||
scale = is_def(r) ? r/max(rads) : 1,
|
scale = is_def(r) ? r/max(rads) : 1,
|
||||||
path = [for (i = [steps:-1:1]) let(a=angs[i]) scale*rads[i]*[cos(a), sin(a)]]
|
path = [for (i = [steps:-1:1]) let(a=angs[i]) scale*rads[i]*[cos(a), sin(a)]]
|
||||||
) reorient(anchor,spin, two_d=true, path=path, p=path);
|
) reorient(anchor,spin, two_d=true, path=path, p=path, extent=atype=="hull");
|
||||||
|
|
||||||
module supershape(step=0.5,m1=4,m2=undef,n1,n2=undef,n3=undef,a=1,b=undef, r=undef, d=undef, anchor=CENTER, spin=0) {
|
module supershape(step=0.5,m1=4,m2=undef,n1,n2=undef,n3=undef,a=1,b=undef, r=undef, d=undef, anchor=CENTER, spin=0) {
|
||||||
path = supershape(step=step,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b,r=r,d=d);
|
path = supershape(step=step,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b,r=r,d=d);
|
||||||
attachable(anchor,spin, two_d=true, path=path) {
|
attachable(anchor,spin,extent=atype=="hull", two_d=true, path=path) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
@ -1165,7 +1205,7 @@ module supershape(step=0.5,m1=4,m2=undef,n1,n2=undef,n3=undef,a=1,b=undef, r=und
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||||
// See Also: regular_ngon(), pentagon(), hexagon(), octagon()
|
// See Also: regular_ngon(), pentagon(), hexagon(), octagon()
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a 2D Reuleaux Polygon; a constant width shape that is not circular.
|
// Creates a 2D Reuleaux Polygon; a constant width shape that is not circular. Uses "intersect" type anchoring.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// N = Number of "sides" to the Reuleaux Polygon. Must be an odd positive number. Default: 3
|
// N = Number of "sides" to the Reuleaux Polygon. Must be an odd positive number. Default: 3
|
||||||
// r = Radius of the shape. Scale shape to fit in a circle of radius r.
|
// r = Radius of the shape. Scale shape to fit in a circle of radius r.
|
||||||
|
@ -1192,7 +1232,7 @@ module reuleaux_polygon(N=3, r, d, anchor=CENTER, spin=0) {
|
||||||
cp = polar_to_xy(r, ca)
|
cp = polar_to_xy(r, ca)
|
||||||
) named_anchor(str("tip",i), cp, unit(cp,BACK), 0),
|
) named_anchor(str("tip",i), cp, unit(cp,BACK), 0),
|
||||||
];
|
];
|
||||||
attachable(anchor,spin, two_d=true, path=path, anchors=anchors) {
|
attachable(anchor,spin, two_d=true, path=path, extent=false, anchors=anchors) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
@ -1219,7 +1259,7 @@ function reuleaux_polygon(N=3, r, d, anchor=CENTER, spin=0) =
|
||||||
cp = polar_to_xy(r, ca)
|
cp = polar_to_xy(r, ca)
|
||||||
) named_anchor(str("tip",i), cp, unit(cp,BACK), 0),
|
) named_anchor(str("tip",i), cp, unit(cp,BACK), 0),
|
||||||
]
|
]
|
||||||
) reorient(anchor,spin, two_d=true, path=path, anchors=anchors, p=path);
|
) reorient(anchor,spin, two_d=true, path=path, extent=false, anchors=anchors, p=path);
|
||||||
|
|
||||||
|
|
||||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||||
|
|
115
skin.scad
115
skin.scad
|
@ -150,11 +150,11 @@
|
||||||
// method = method for connecting profiles, one of "distance", "fast_distance", "tangent", "direct" or "reindex". Default: "direct".
|
// method = method for connecting profiles, one of "distance", "fast_distance", "tangent", "direct" or "reindex". Default: "direct".
|
||||||
// z = array of height values for each profile if the profiles are 2d
|
// z = array of height values for each profile if the profiles are 2d
|
||||||
// convexity = convexity setting for use with polyhedron. (module only) Default: 10
|
// convexity = convexity setting for use with polyhedron. (module only) Default: 10
|
||||||
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
// anchor = Translate so anchor point is at the origin. Default: "origin"
|
||||||
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
|
||||||
// orient = Vector to rotate top towards after spin (module only)
|
// orient = Vector to rotate top towards after spin
|
||||||
// extent = use extent method for computing anchors. (module only) Default: false
|
// atype = Select "hull" or "intersect anchor types. Default: "hull"
|
||||||
// cp = set centerpoint for anchor computation. (module only) Default: object centroid
|
// cp = set centerpoint for anchor computation. Default: "centroid"
|
||||||
// style = vnf_vertex_array style. Default: "min_edge"
|
// style = vnf_vertex_array style. Default: "min_edge"
|
||||||
// Example:
|
// Example:
|
||||||
// skin([octagon(4), circle($fn=70,r=2)], z=[0,3], slices=10);
|
// skin([octagon(4), circle($fn=70,r=2)], z=[0,3], slices=10);
|
||||||
|
@ -383,18 +383,17 @@
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
module skin(profiles, slices, refine=1, method="direct", sampling, caps, closed=false, z, style="min_edge", convexity=10,
|
module skin(profiles, slices, refine=1, method="direct", sampling, caps, closed=false, z, style="min_edge", convexity=10,
|
||||||
anchor="origin",cp,spin=0, orient=UP, extent=false)
|
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull")
|
||||||
{
|
{
|
||||||
vnf = skin(profiles, slices, refine, method, sampling, caps, closed, z, style=style);
|
vnf = skin(profiles, slices, refine, method, sampling, caps, closed, z, style=style);
|
||||||
attachable(anchor=anchor, spin=spin, orient=orient, vnf=vnf, extent=extent, cp=is_def(cp) ? cp : centroid(vnf))
|
vnf_polyhedron(vnf,convexity=convexity,spin=spin,anchor=anchor,orient=orient,atype=atype,cp=cp)
|
||||||
{
|
|
||||||
vnf_polyhedron(vnf,convexity=convexity);
|
|
||||||
children();
|
children();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function skin(profiles, slices, refine=1, method="direct", sampling, caps, closed=false, z, style="min_edge") =
|
function skin(profiles, slices, refine=1, method="direct", sampling, caps, closed=false, z, style="min_edge",
|
||||||
|
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull") =
|
||||||
|
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"")
|
||||||
assert(is_def(slices),"The slices argument must be specified.")
|
assert(is_def(slices),"The slices argument must be specified.")
|
||||||
assert(is_list(profiles) && len(profiles)>1, "Must provide at least two profiles")
|
assert(is_list(profiles) && len(profiles)>1, "Must provide at least two profiles")
|
||||||
let(
|
let(
|
||||||
|
@ -490,13 +489,13 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
|
||||||
". Method ",method[i]," requires equal values"))
|
". Method ",method[i]," requires equal values"))
|
||||||
refine[i] * len(pair[0])
|
refine[i] * len(pair[0])
|
||||||
)
|
)
|
||||||
subdivide_and_slice(pair,slices[i], nsamples, method=sampling)]
|
subdivide_and_slice(pair,slices[i], nsamples, method=sampling)],
|
||||||
|
vnf=vnf_join(
|
||||||
|
[for(i=idx(full_list))
|
||||||
|
vnf_vertex_array(full_list[i], cap1=i==0 && fullcaps[0], cap2=i==len(full_list)-1 && fullcaps[1],
|
||||||
|
col_wrap=true, style=style)])
|
||||||
)
|
)
|
||||||
vnf_join(
|
reorient(anchor,spin,orient,vnf=vnf,p=vnf,extent=atype=="hull",cp=cp);
|
||||||
[for(i=idx(full_list))
|
|
||||||
vnf_vertex_array(full_list[i], cap1=i==0 && fullcaps[0], cap2=i==len(full_list)-1 && fullcaps[1],
|
|
||||||
col_wrap=true, style=style)]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: path_sweep()
|
// Function&Module: path_sweep()
|
||||||
|
@ -566,13 +565,12 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
|
||||||
// caps = Can be a boolean or vector of two booleans. Set to false to disable caps at the two ends. Default: true
|
// caps = Can be a boolean or vector of two booleans. Set to false to disable caps at the two ends. Default: true
|
||||||
// style = vnf_vertex_array style. Default: "min_edge"
|
// style = vnf_vertex_array style. Default: "min_edge"
|
||||||
// transforms = set to true to return transforms instead of a VNF. These transforms can be manipulated and passed to sweep(). Default: false.
|
// transforms = set to true to return transforms instead of a VNF. These transforms can be manipulated and passed to sweep(). Default: false.
|
||||||
// convexity = convexity parameter for polyhedron(). Only accepted by the module version. Default: 10
|
// convexity = convexity parameter for polyhedron(). (module only) Default: 10
|
||||||
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
// anchor = Translate so anchor point is at the origin. Default: "origin"
|
||||||
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
|
||||||
// orient = Vector to rotate top towards after spin (module only)
|
// orient = Vector to rotate top towards after spin
|
||||||
// extent = use extent method for computing anchors. (module only) Default: false
|
// atype = Select "hull" or "intersect" anchor types. Default: "hull"
|
||||||
// cp = set centerpoint for anchor computation. (module only) Default: object centroid
|
// cp = set centerpoint for anchor computation. Default: "centroid"
|
||||||
//
|
|
||||||
// Example(2D): We'll use this shape in several examples
|
// Example(2D): We'll use this shape in several examples
|
||||||
// ushape = [[-10, 0],[-10, 10],[ -7, 10],[ -7, 2],[ 7, 2],[ 7, 7],[ 10, 7],[ 10, 0]];
|
// ushape = [[-10, 0],[-10, 10],[ -7, 10],[ -7, 2],[ 7, 2],[ 7, 7],[ 10, 7],[ 10, 0]];
|
||||||
// polygon(ushape);
|
// polygon(ushape);
|
||||||
|
@ -812,20 +810,19 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
|
||||||
// }
|
// }
|
||||||
module path_sweep(shape, path, method="incremental", normal, closed=false, twist=0, twist_by_length=true,
|
module path_sweep(shape, path, method="incremental", normal, closed=false, twist=0, twist_by_length=true,
|
||||||
symmetry=1, last_normal, tangent, relaxed=false, caps, style="min_edge", convexity=10,
|
symmetry=1, last_normal, tangent, relaxed=false, caps, style="min_edge", convexity=10,
|
||||||
anchor="origin",cp,spin=0, orient=UP, extent=false)
|
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull")
|
||||||
{
|
{
|
||||||
vnf = path_sweep(shape, path, method, normal, closed, twist, twist_by_length,
|
vnf = path_sweep(shape, path, method, normal, closed, twist, twist_by_length,
|
||||||
symmetry, last_normal, tangent, relaxed, caps, style);
|
symmetry, last_normal, tangent, relaxed, caps, style);
|
||||||
attachable(anchor=anchor, spin=spin, orient=orient, vnf=vnf, extent=extent, cp=is_def(cp) ? cp : centroid(vnf))
|
vnf_polyhedron(vnf,convexity=convexity,anchor=anchor, spin=spin, orient=orient, vnf=vnf, atype=atype, cp=cp)
|
||||||
{
|
|
||||||
vnf_polyhedron(vnf,convexity=convexity);
|
|
||||||
children();
|
children();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function path_sweep(shape, path, method="incremental", normal, closed=false, twist=0, twist_by_length=true,
|
function path_sweep(shape, path, method="incremental", normal, closed=false, twist=0, twist_by_length=true,
|
||||||
symmetry=1, last_normal, tangent, relaxed=false, caps, style="min_edge", transforms=false) =
|
symmetry=1, last_normal, tangent, relaxed=false, caps, style="min_edge", transforms=false,
|
||||||
|
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull") =
|
||||||
|
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"")
|
||||||
assert(!closed || twist % (360/symmetry)==0, str("For a closed sweep, twist must be a multiple of 360/symmetry = ",360/symmetry))
|
assert(!closed || twist % (360/symmetry)==0, str("For a closed sweep, twist must be a multiple of 360/symmetry = ",360/symmetry))
|
||||||
assert(closed || symmetry==1, "symmetry must be 1 when closed is false")
|
assert(closed || symmetry==1, "symmetry must be 1 when closed is false")
|
||||||
assert(is_integer(symmetry) && symmetry>0, "symmetry must be a positive integer")
|
assert(is_integer(symmetry) && symmetry>0, "symmetry must be a positive integer")
|
||||||
|
@ -919,7 +916,9 @@ function path_sweep(shape, path, method="incremental", normal, closed=false, twi
|
||||||
apply(transform_list[L], rshape)),
|
apply(transform_list[L], rshape)),
|
||||||
dummy = ends_match ? 0 : echo("WARNING: ***** The points do not match when closing the model *****")
|
dummy = ends_match ? 0 : echo("WARNING: ***** The points do not match when closing the model *****")
|
||||||
)
|
)
|
||||||
transforms ? transform_list : sweep(is_path(shape)?clockwise_polygon(shape):shape, transform_list, closed=false, caps=fullcaps,style=style);
|
transforms ? transform_list
|
||||||
|
: sweep(is_path(shape)?clockwise_polygon(shape):shape, transform_list, closed=false, caps=fullcaps,style=style,
|
||||||
|
anchor=anchor,cp=cp,spin=spin,orient=orient,atype=atype);
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: path_sweep2d()
|
// Function&Module: path_sweep2d()
|
||||||
|
@ -946,11 +945,11 @@ function path_sweep(shape, path, method="incremental", normal, closed=false, twi
|
||||||
// style = vnf_vertex_array style. Default: "min_edge"
|
// style = vnf_vertex_array style. Default: "min_edge"
|
||||||
// ---
|
// ---
|
||||||
// convexity = convexity parameter for polyhedron (module only) Default: 10
|
// convexity = convexity parameter for polyhedron (module only) Default: 10
|
||||||
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
// anchor = Translate so anchor point is at the origin. Default: "origin"
|
||||||
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
|
||||||
// orient = Vector to rotate top towards after spin (module only)
|
// orient = Vector to rotate top towards after spin
|
||||||
// extent = use extent method for computing anchors. (module only) Default: false
|
// atype = Select "hull" or "intersect" anchor types. Default: "hull"
|
||||||
// cp = set centerpoint for anchor computation. (module only) Default: object centroid
|
// cp = set centerpoint for anchor computation. Default: "centroid"
|
||||||
// Example: Sine wave example with self-intersections at each peak. This would fail with path_sweep().
|
// Example: Sine wave example with self-intersections at each peak. This would fail with path_sweep().
|
||||||
// sinewave = [for(i=[-30:10:360*2+30]) [i/40,3*sin(i)]];
|
// sinewave = [for(i=[-30:10:360*2+30]) [i/40,3*sin(i)]];
|
||||||
// path_sweep2d(circle(r=3,$fn=15), sinewave);
|
// path_sweep2d(circle(r=3,$fn=15), sinewave);
|
||||||
|
@ -967,7 +966,8 @@ function path_sweep(shape, path, method="incremental", normal, closed=false, twi
|
||||||
// path_sweep2d(circle(r=3.25, $fn=32), select(ellipse,floor(L*.2),ceil(L*.8)),closed=false);
|
// path_sweep2d(circle(r=3.25, $fn=32), select(ellipse,floor(L*.2),ceil(L*.8)),closed=false);
|
||||||
// path_sweep2d(circle(r=3.25, $fn=32), select(ellipse,floor(L*.7),ceil(L*.3)),closed=false);
|
// path_sweep2d(circle(r=3.25, $fn=32), select(ellipse,floor(L*.7),ceil(L*.3)),closed=false);
|
||||||
|
|
||||||
function path_sweep2d(shape, path, closed=false, caps, quality=1, style="min_edge") =
|
function path_sweep2d(shape, path, closed=false, caps, quality=1, style="min_edge",
|
||||||
|
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull") =
|
||||||
let(
|
let(
|
||||||
caps = is_def(caps) ? caps
|
caps = is_def(caps) ? caps
|
||||||
: closed ? false : true,
|
: closed ? false : true,
|
||||||
|
@ -992,23 +992,21 @@ function path_sweep2d(shape, path, closed=false, caps, quality=1, style="min_edg
|
||||||
)
|
)
|
||||||
select(path3d(ofs[0],pt.y),map)
|
select(path3d(ofs[0],pt.y),map)
|
||||||
]
|
]
|
||||||
)
|
),
|
||||||
|
vnf = vnf_vertex_array([
|
||||||
|
each proflist,
|
||||||
|
if (closed) proflist[0]
|
||||||
|
],cap1=fullcaps[0],cap2=fullcaps[1],col_wrap=true,style=style)
|
||||||
)
|
)
|
||||||
vnf_vertex_array([
|
reorient(anchor,spin,orient,vnf=vnf,p=vnf,extent=atype=="hull",cp=cp);
|
||||||
each proflist,
|
|
||||||
if (closed) proflist[0]
|
|
||||||
],cap1=fullcaps[0],cap2=fullcaps[1],col_wrap=true,style=style);
|
|
||||||
|
|
||||||
|
|
||||||
module path_sweep2d(profile, path, closed=false, caps, quality=1, style="min_edge", convexity=10,
|
module path_sweep2d(profile, path, closed=false, caps, quality=1, style="min_edge", convexity=10,
|
||||||
anchor="origin", cp, spin=0, orient=UP, extent=false)
|
anchor="origin", cp="centroid", spin=0, orient=UP, atype="hull")
|
||||||
{
|
{
|
||||||
vnf = path_sweep2d(profile, path, closed, caps, quality, style);
|
vnf = path_sweep2d(profile, path, closed, caps, quality, style);
|
||||||
attachable(anchor=anchor, spin=spin, orient=orient, vnf=vnf, extent=extent, cp=is_def(cp) ? cp : centroid(vnf))
|
vnf_polyhedron(vnf,convexity=convexity,anchor=anchor, spin=spin, orient=orient, vnf=vnf, atype=atype, cp=cp)
|
||||||
{
|
|
||||||
vnf_polyhedron(vnf,convexity=convexity);
|
|
||||||
children();
|
children();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract vertex mapping from offset face list. The output of this function
|
// Extract vertex mapping from offset face list. The output of this function
|
||||||
|
@ -1071,11 +1069,11 @@ function _ofs_face_edge(face,firstlen,second=false) =
|
||||||
// style = vnf_vertex_array style. Default: "min_edge"
|
// style = vnf_vertex_array style. Default: "min_edge"
|
||||||
// ---
|
// ---
|
||||||
// convexity = convexity setting for use with polyhedron. (module only) Default: 10
|
// convexity = convexity setting for use with polyhedron. (module only) Default: 10
|
||||||
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
// anchor = Translate so anchor point is at the origin. Default: "origin"
|
||||||
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
|
||||||
// orient = Vector to rotate top towards after spin (module only)
|
// orient = Vector to rotate top towards after spin (module only)
|
||||||
// extent = use extent method for computing anchors. (module only) Default: false
|
// atype = Select "hull" or "intersect" anchor types. Default: "hull"
|
||||||
// cp = set centerpoint for anchor computation. (module only) Default: object centroid
|
// cp = set centerpoint for anchor computation. Default: "centroid"
|
||||||
// Example: This is the "sweep-drop" example from list-comprehension-demos.
|
// Example: This is the "sweep-drop" example from list-comprehension-demos.
|
||||||
// function drop(t) = 100 * 0.5 * (1 - cos(180 * t)) * sin(180 * t) + 1;
|
// function drop(t) = 100 * 0.5 * (1 - cos(180 * t)) * sin(180 * t) + 1;
|
||||||
// function path(t) = [0, 0, 80 + 80 * cos(180 * t)];
|
// function path(t) = [0, 0, 80 + 80 * cos(180 * t)];
|
||||||
|
@ -1097,7 +1095,8 @@ function _ofs_face_edge(face,firstlen,second=false) =
|
||||||
// inside = [for(i=[24:-1:2]) up(i)*rot(i)*scale(1.2*i/24+1)];
|
// inside = [for(i=[24:-1:2]) up(i)*rot(i)*scale(1.2*i/24+1)];
|
||||||
// sweep(shape, concat(outside,inside));
|
// sweep(shape, concat(outside,inside));
|
||||||
|
|
||||||
function sweep(shape, transforms, closed=false, caps, style="min_edge") =
|
function sweep(shape, transforms, closed=false, caps, style="min_edge",
|
||||||
|
anchor="origin", cp="centroid", spin=0, orient=UP, atype="hull") =
|
||||||
assert(is_consistent(transforms, ident(4)), "Input transforms must be a list of numeric 4x4 matrices in sweep")
|
assert(is_consistent(transforms, ident(4)), "Input transforms must be a list of numeric 4x4 matrices in sweep")
|
||||||
assert(is_path(shape,2) || is_region(shape), "Input shape must be a 2d path or a region.")
|
assert(is_path(shape,2) || is_region(shape), "Input shape must be a 2d path or a region.")
|
||||||
let(
|
let(
|
||||||
|
@ -1128,15 +1127,13 @@ function sweep(shape, transforms, closed=false, caps, style="min_edge") =
|
||||||
|
|
||||||
|
|
||||||
module sweep(shape, transforms, closed=false, caps, style="min_edge", convexity=10,
|
module sweep(shape, transforms, closed=false, caps, style="min_edge", convexity=10,
|
||||||
anchor="origin",cp,spin=0, orient=UP, extent=false)
|
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull")
|
||||||
{
|
{
|
||||||
vnf = sweep(shape, transforms, closed, caps, style);
|
vnf = sweep(shape, transforms, closed, caps, style);
|
||||||
attachable(anchor=anchor, spin=spin, orient=orient, vnf=vnf, extent=extent, cp=is_def(cp) ? cp : centroid(vnf))
|
vnf_polyhedron(vnf,convexity=convexity,anchor=anchor, spin=spin, orient=orient, vnf=vnf, atype=atype, cp=cp)
|
||||||
{
|
children();
|
||||||
vnf_polyhedron(vnf,convexity=convexity);
|
}
|
||||||
children();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Section: Functions for resampling and slicing profile lists
|
// Section: Functions for resampling and slicing profile lists
|
||||||
|
|
7
vnf.scad
7
vnf.scad
|
@ -787,10 +787,11 @@ function _slice_3dpolygons(polys, dir, cuts) =
|
||||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
|
||||||
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
// 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`
|
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
|
||||||
module vnf_polyhedron(vnf, convexity=2, extent=true, cp=[0,0,0], anchor="origin", spin=0, orient=UP) {
|
// atype = Select "hull" or "intersect" anchor type. Default: "hull"
|
||||||
|
module vnf_polyhedron(vnf, convexity=2, extent=true, cp="centroid", anchor="origin", spin=0, orient=UP, atype="hull") {
|
||||||
vnf = is_vnf_list(vnf)? vnf_join(vnf) : vnf;
|
vnf = is_vnf_list(vnf)? vnf_join(vnf) : vnf;
|
||||||
cp = is_def(cp) ? cp : centroid(vnf);
|
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"");
|
||||||
attachable(anchor,spin,orient, vnf=vnf, extent=extent, cp=cp) {
|
attachable(anchor,spin,orient, vnf=vnf, extent=atype=="hull", cp=cp) {
|
||||||
polyhedron(vnf[0], vnf[1], convexity=convexity);
|
polyhedron(vnf[0], vnf[1], convexity=convexity);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue