mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Renamed orient_and_anchor() to attachable() and refactored arguments and internals.
This commit is contained in:
parent
5d1865dc77
commit
6651e1be42
25 changed files with 720 additions and 335 deletions
569
attachments.scad
569
attachments.scad
|
@ -17,13 +17,13 @@ $attach_to = undef;
|
|||
$attach_anchor = [CENTER, CENTER, UP, 0];
|
||||
$attach_norot = false;
|
||||
|
||||
$parent_size = undef;
|
||||
$parent_size2 = undef;
|
||||
$parent_shift = [0,0];
|
||||
$parent_anchors = [];
|
||||
$parent_anchor = BOTTOM;
|
||||
$parent_spin = 0;
|
||||
$parent_orient = UP;
|
||||
|
||||
$parent_size = undef;
|
||||
$parent_geom = undef;
|
||||
|
||||
$tags_shown = [];
|
||||
$tags_hidden = [];
|
||||
|
||||
|
@ -103,72 +103,226 @@ $tags_hidden = [];
|
|||
function anchorpt(name, pos=[0,0,0], orient=UP, spin=0) = [name, pos, orient, spin];
|
||||
|
||||
|
||||
// Function: attach_geom_2d()
|
||||
// Usage:
|
||||
// attach_geom_2d(geom);
|
||||
// Description:
|
||||
// Returns true if the given attachment geometry description is for a 2D shape.
|
||||
function attach_geom_2d(geom) =
|
||||
let( type = geom[0] )
|
||||
type == "rect" || type == "circle" ||
|
||||
type == "path_isect" || type == "path_extent";
|
||||
|
||||
|
||||
// Function: attach_geom_size()
|
||||
// Usage:
|
||||
// attach_geom_size(geom);
|
||||
// Description:
|
||||
// Returns the `[X,Y,Z]` bounding size for the given attachment geometry description.
|
||||
function attach_geom_size(geom) =
|
||||
let( type = geom[0] )
|
||||
type == "cuboid"? ( //size, size2, shift
|
||||
let(
|
||||
size=geom[1], size2=geom[2], shift=point2d(geom[3]),
|
||||
maxx = max(size.x,size2.x),
|
||||
maxy = max(size.y,size2.y),
|
||||
z = size.z
|
||||
) [maxx, maxy, z]
|
||||
) : type == "cyl"? ( //r1, r2, l, shift
|
||||
let(
|
||||
r1=geom[1], r2=geom[2], l=geom[3], shift=point2d(geom[4]),
|
||||
maxr = max(r1,r2)
|
||||
) [2*maxr,2*maxr,l]
|
||||
) : type == "spheroid"? ( //r
|
||||
let( r=geom[1] ) [2,2,2]*r
|
||||
) : type == "vnf_extent" || type=="vnf_isect"? ( //vnf
|
||||
let(
|
||||
mm = pointlist_bounds(geom[1][0]),
|
||||
delt = mm[1]-mm[0]
|
||||
) delt
|
||||
) : type == "rect"? ( //size, size2
|
||||
let(
|
||||
size=geom[1], size2=geom[2],
|
||||
maxx = max(size.x,size2)
|
||||
) [maxx, size.y]
|
||||
) : type == "circle"? ( //r
|
||||
let( r=geom[1] ) [2,2]*r
|
||||
) : type == "path_isect" || type == "path_extent"? ( //path
|
||||
let(
|
||||
mm = pointlist_bounds(geom[1]),
|
||||
delt = mm[1]-mm[0]
|
||||
) [delt.x, delt.y]
|
||||
) :
|
||||
assert(false, "Unknown attachment geometry type.");
|
||||
|
||||
|
||||
|
||||
// Function: find_anchor()
|
||||
// Usage:
|
||||
// find_anchor(anchor, h, size, [size2], [shift], [edges], [corners]);
|
||||
// find_anchor(anchor, geom);
|
||||
// Description:
|
||||
// Returns anchor data for the given vector or anchor name.
|
||||
// Calculates the anchor data for the given `anchor` vector or name, in the given attachment
|
||||
// geometry. Returns `[ANCHOR, POS, VEC, ANG]` where `ANCHOR` is the requested anchorname
|
||||
// or vector, `POS` is the anchor position, `VEC` is the direction vector of the anchor, and
|
||||
// `ANG` is the angle to align with around the rotation axis of th anchor direction vector.
|
||||
// Arguments:
|
||||
// anchor = Vector or named anchor string.
|
||||
// h = Height of the region.
|
||||
// size = The [X,Y] size of the bottom of the cubical region.
|
||||
// size2 = The [X,Y] size of the top of the cubical region.
|
||||
// shift = The [X,Y] amount to shift the center of the top with respect to the center of the bottom.
|
||||
// offset = If the anchor is not CENTER, this is the offset to add to the rest of the anchor points.
|
||||
// geometry = One of "cube", "cylinder", or "sphere" to denote the overall geometry of the shape. Cones are "cylinder", and prismoids are "cube" for this purpose. Default: "cube"
|
||||
// anchors = A list of extra non-standard named anchors.
|
||||
// two_d = If true, object will be treated as 2D.
|
||||
function find_anchor(anchor, h, size, size2=undef, shift=[0,0], offset=[0,0,0], anchors=[], geometry="cube", two_d=false) =
|
||||
// geom = The geometry description of the shape.
|
||||
function find_anchor(anchor, geom) =
|
||||
let(
|
||||
anchor = point3d(anchor),
|
||||
offset = anchor==CENTER? CENTER : select(geom,-2),
|
||||
anchors = select(geom,-1),
|
||||
type = geom[0]
|
||||
)
|
||||
is_string(anchor)? (
|
||||
let(found = search([anchor], anchors, num_returns_per_match=1)[0])
|
||||
assert(found!=[], str("Unknown anchor: ",anchor))
|
||||
anchors[found]
|
||||
) : (
|
||||
assert(is_vector(anchor),str("anchor=",anchor))
|
||||
) :
|
||||
assert(is_vector(anchor),str("anchor=",anchor))
|
||||
anchor==CENTER? [anchor, CENTER, UP, 0] :
|
||||
let(
|
||||
oang = (
|
||||
approx(point2d(anchor), [0,0])? 0 :
|
||||
atan2(anchor.y, anchor.x)+90
|
||||
)
|
||||
)
|
||||
type == "cuboid"? ( //size, size2, shift
|
||||
let(
|
||||
size = point2d(size),
|
||||
size2 = (size2!=undef)? point2d(size2) : size,
|
||||
shift = point2d(shift),
|
||||
oang = (
|
||||
two_d? 0 :
|
||||
anchor == UP? 0 :
|
||||
anchor == DOWN? 0 :
|
||||
(norm([anchor.x,anchor.y]) < EPSILON)? 0 :
|
||||
atan2(anchor.y, anchor.x)+90
|
||||
size=geom[1], size2=geom[2], shift=point2d(geom[3]),
|
||||
h = size.z,
|
||||
u = (anchor.z+1)/2,
|
||||
axy = point2d(anchor),
|
||||
bot = point3d(vmul(point2d(size)/2,axy),-h/2),
|
||||
top = point3d(vmul(point2d(size2)/2,axy)+shift,h/2),
|
||||
pos = lerp(bot,top,u)+offset,
|
||||
sidevec = normalize(rot(from=UP, to=top-bot, p=point3d(axy))),
|
||||
vvec = normalize([0,0,anchor.z]),
|
||||
vec = anchor==CENTER? UP :
|
||||
approx(axy,[0,0])? normalize(anchor) :
|
||||
approx(anchor.z,0)? sidevec :
|
||||
normalize((sidevec+vvec)/2)
|
||||
) [anchor, pos, vec, oang]
|
||||
) : type == "cyl"? ( //r1, r2, l, shift
|
||||
let(
|
||||
r1=geom[1], r2=geom[2], l=geom[3], shift=point2d(geom[4]),
|
||||
u = (anchor.z+1)/2,
|
||||
axy = normalize(point2d(anchor)),
|
||||
bot = point3d(r1*axy,-l/2),
|
||||
top = point3d(r2*axy+shift, l/2),
|
||||
pos = lerp(bot,top,u)+offset,
|
||||
sidevec = rot(from=UP, to=top-bot, p=point3d(axy)),
|
||||
vvec = normalize([0,0,anchor.z]),
|
||||
vec = anchor==CENTER? UP :
|
||||
approx(axy,[0,0])? normalize(anchor) :
|
||||
approx(anchor.z,0)? sidevec :
|
||||
normalize((sidevec+vvec)/2)
|
||||
) [anchor, pos, vec, oang]
|
||||
) : type == "spheroid"? ( //r
|
||||
let(
|
||||
r=geom[1]
|
||||
) [anchor, r*normalize(anchor)+offset, normalize(anchor), oang]
|
||||
) : type == "vnf_isect"? ( //vnf
|
||||
let(
|
||||
vnf=geom[1],
|
||||
eps = 1/2048,
|
||||
rpts = rot(from=anchor, to=RIGHT, p=vnf[0]),
|
||||
hits = [
|
||||
for (i = idx(vnf[1])) let(
|
||||
face = vnf[1][i],
|
||||
verts = select(rpts, face)
|
||||
) if (
|
||||
max(subindex(verts,0)) >= -eps &&
|
||||
max(subindex(verts,1)) >= -eps &&
|
||||
max(subindex(verts,2)) >= -eps &&
|
||||
min(subindex(verts,1)) <= eps &&
|
||||
min(subindex(verts,2)) <= eps
|
||||
) let(
|
||||
pt = polygon_line_intersection(
|
||||
select(vnf[0], face),
|
||||
[CENTER,anchor], eps=eps
|
||||
)
|
||||
) if (!is_undef(pt)) [norm(pt),i,pt]
|
||||
]
|
||||
)
|
||||
assert(len(hits)>0, "Anchor vector does not intersect with the shape. Attachment failed.")
|
||||
let(
|
||||
furthest = max_index(subindex(hits,0)),
|
||||
pos = hits[furthest][2],
|
||||
dist = hits[furthest][0],
|
||||
nfaces = [for (hit = hits) if(approx(hit[0],dist,eps=eps)) hit[1]],
|
||||
n = normalize(
|
||||
sum([
|
||||
for (i = nfaces) let(
|
||||
faceverts = select(vnf[0],vnf[1][i]),
|
||||
faceplane = plane_from_pointslist(faceverts),
|
||||
nrm = plane_normal(faceplane)
|
||||
) nrm
|
||||
]) / len(nfaces)
|
||||
)
|
||||
)
|
||||
geometry=="sphere"? let(
|
||||
phi = (anchor==UP||anchor==CENTER)? 0 : anchor==DOWN? 180 : 90 + (45 * anchor.z),
|
||||
theta = anchor==CENTER? 90 : atan2(anchor.y, anchor.x),
|
||||
vec = spherical_to_xyz(1, theta, phi),
|
||||
offset = anchor==CENTER? [0,0,0] : offset,
|
||||
pos = anchor==CENTER? CENTER : vmul(vec, (point3d(size)+h*UP)/2) + offset
|
||||
) [anchor, pos, vec, oang] : let (
|
||||
xyal = (
|
||||
geometry=="cylinder"? (
|
||||
let(xy = point2d(anchor))
|
||||
norm(xy)>0? xy/norm(xy) : [0,0]
|
||||
) : point2d(anchor)
|
||||
),
|
||||
botpt = point3d(vmul(size/2,xyal))+DOWN*h/2,
|
||||
toppt = point3d(vmul(size2/2,xyal)+shift)+UP*h/2,
|
||||
offset = anchor==CENTER? [0,0,0] : offset,
|
||||
pos = lerp(botpt, toppt, (anchor.z+1)/2) + offset,
|
||||
sidevec = two_d? point3d(xyal) :
|
||||
approx(norm(xyal),0)? [0,0,0] :
|
||||
rotate_points3d([point3d(xyal)], from=UP, to=toppt-botpt)[0],
|
||||
vec = (
|
||||
two_d? sidevec :
|
||||
anchor==CENTER? UP :
|
||||
norm([anchor.x,anchor.y]) < EPSILON? anchor :
|
||||
norm(size)+norm(size2) < EPSILON? anchor :
|
||||
abs(anchor.z) < EPSILON? sidevec :
|
||||
anchor.z>0? (UP+sidevec)/2 :
|
||||
(DOWN+sidevec)/2
|
||||
)
|
||||
) [anchor, pos, vec, oang]
|
||||
);
|
||||
[anchor, pos, n, oang]
|
||||
) : type == "vnf_extent"? ( //vnf
|
||||
let(
|
||||
vnf=geom[1],
|
||||
rpts = rot(from=anchor, to=RIGHT, p=vnf[0]),
|
||||
maxx = max(subindex(rpts,0)),
|
||||
idxs = [for (i = idx(rpts)) if (approx(rpts[i].x, maxx)) i],
|
||||
mm = pointlist_bounds(select(rpts,idxs)),
|
||||
avgy = (mm[0].y+mm[1].y)/2,
|
||||
avgz = (mm[0].z+mm[1].z)/2,
|
||||
pos = rot(from=RIGHT, to=anchor, p=[maxx, avgy, avgz])
|
||||
) [anchor, pos, anchor, oang]
|
||||
) : type == "rect"? ( //size, size2
|
||||
let(
|
||||
size=geom[1], size2=geom[2],
|
||||
u = (anchor.y+1)/2,
|
||||
frpt = [size.x/2*anchor.x, -size.y/2],
|
||||
bkpt = [size2/2*anchor.x, size.y/2],
|
||||
pos = lerp(frpt, bkpt, u),
|
||||
vec = normalize(rot(from=BACK, to=bkpt-frpt, p=anchor))
|
||||
) [anchor, pos, vec, 0]
|
||||
) : type == "circle"? ( //r
|
||||
let(
|
||||
r=geom[1],
|
||||
anchor = normalize(point2d(anchor))
|
||||
) [anchor, r*anchor+offset, anchor, 0]
|
||||
) : type == "path_isect"? ( //path
|
||||
let(
|
||||
path=geom[1],
|
||||
anchor = point2d(anchor),
|
||||
isects = [
|
||||
for (t=triplet_wrap(path)) let(
|
||||
seg1 = [t[0],t[1]],
|
||||
seg2 = [t[1],t[2]],
|
||||
isect = ray_segment_intersection([[0,0],anchor], seg1),
|
||||
n = is_undef(isect)? [0,1] :
|
||||
!approx(isect, t[1])? line_normal(seg1) :
|
||||
normalize((line_normal(seg1)+line_normal(seg2))/2),
|
||||
n2 = vector_angle(anchor,n)>90? -n : n
|
||||
)
|
||||
if(!is_undef(isect) && !approx(isect,t[0])) [norm(isect), isect, n2]
|
||||
],
|
||||
maxidx = max_index(subindex(isects,0)),
|
||||
isect = isects[maxidx],
|
||||
pos = isect[1],
|
||||
vec = normalize(isect[2])
|
||||
) [anchor, pos, vec, 0]
|
||||
) : type == "path_extent"? ( //path
|
||||
let(
|
||||
path=geom[1],
|
||||
anchor = point2d(anchor),
|
||||
rpath = rot(from=anchor, to=RIGHT, p=path),
|
||||
maxx = max(subindex(rpath,0)),
|
||||
idxs = [for (i = idx(rpath)) if (approx(rpath[i].x, maxx)) i],
|
||||
miny = min([for (i=idxs) rpath[i].y]),
|
||||
maxy = max([for (i=idxs) rpath[i].y]),
|
||||
avgy = (miny+maxy)/2,
|
||||
pos = rot(from=RIGHT, to=anchor, p=[maxx,avgy])
|
||||
) [anchor, pos, anchor, 0]
|
||||
) :
|
||||
assert(false, "Unknown attachment geometry type.");
|
||||
|
||||
|
||||
|
||||
|
@ -180,17 +334,33 @@ function _str_char_split(s,delim,n=0,acc=[],word="") =
|
|||
|
||||
|
||||
|
||||
// Section: Modules
|
||||
// Section: Attachability Modules
|
||||
|
||||
|
||||
// Module: orient_and_anchor()
|
||||
// Module: attachable()
|
||||
//
|
||||
// Usage:
|
||||
// attachable(anchor, spin, [orient], two_d, size, [size2], [shift], [offset], [anchors] ...
|
||||
// attachable(anchor, spin, [orient], two_d, r|d, [offset], [anchors]) ...
|
||||
// attachable(anchor, spin, [orient], two_d, path, [extent], [offset], [anchors] ...
|
||||
// attachable(anchor, spin, [orient], size, [size2], [shift], [offset], [anchors] ...
|
||||
// attachable(anchor, spin, [orient], r|d, l, [offset], [anchors]) ...
|
||||
// attachable(anchor, spin, [orient], r1|d1, r2|d2, l, [offset], [anchors]) ...
|
||||
// attachable(anchor, spin, [orient], r|d, [offset], [anchors]) ...
|
||||
// attachable(anchor, spin, [orient], vnf, [extent], [offset], [anchors]) ...
|
||||
//
|
||||
// Description:
|
||||
// Takes a vertically oriented part and anchors, spins and orients it.
|
||||
// This is useful for making a custom shape available in various
|
||||
// orientations and anchorings without extra translate()s and rotate()s.
|
||||
// Children should be vertically (Z-axis) oriented, and centered.
|
||||
// Non-vector anchor points should be named via the `anchors` arg.
|
||||
// Manages the anchoring, spin, orientation, and attachments for a 3D volume or 2D area.
|
||||
// A managed 3D volume is assumed to be vertically (Z-axis) oriented, and centered.
|
||||
// A managed 2D area is just assumed to be centered. The shape to be managed is given
|
||||
// as the first child to this module, and the second child should be given as `children()`.
|
||||
// For example, to manage a conical shape:
|
||||
// ```openscad
|
||||
// attachable(anchor, spin, orient, r1=r1, r2=r2, l=h) {
|
||||
// cyl(r1=r1, r2=r2, l=h);
|
||||
// children();
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// If this is *not* run as a child of `attach()` with the `to` argument
|
||||
// given, then the following transformations are performed in order:
|
||||
|
@ -206,67 +376,182 @@ function _str_char_split(s,delim,n=0,acc=[],word="") =
|
|||
// * Rotates this part so it's anchor direction vector exactly opposes the parent's anchor direction vector.
|
||||
// * Rotates this part so it's anchor spin matches the parent's anchor spin.
|
||||
//
|
||||
// Usage:
|
||||
// orient_and_anchor(size, [anchor], [spin], [orient], [center], [noncentered], [anchors], [chain]) ...
|
||||
//
|
||||
// Arguments:
|
||||
// size = The [X,Y,Z] size of the part.
|
||||
// size2 = The [X,Y] size of the top of the part.
|
||||
// shift = The [X,Y] offset of the top of the part, compared to the bottom of the part.
|
||||
// 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`
|
||||
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
|
||||
// center = If given, overrides `anchor`. If true, centers vertically. If false, `anchor` will be set to the value in `noncentered`.
|
||||
// noncentered = The value to set `anchor` to if `center` == `false`. Default: `BOTTOM`.
|
||||
// offset = The offset of the center of the object from the CENTER anchor.
|
||||
// geometry = One of "cube", "cylinder", or "sphere" to denote the overall geometry of the shape. Cones are "cylinder", and prismoids are "cube" for this purpose. Default: "cube"
|
||||
// anchors = A list of extra, non-standard optional anchors.
|
||||
// chain = If true, allow attachable children.
|
||||
// two_d = If true, object will be treated as 2D.
|
||||
// size = If given as a 3D vector, contains the XY size of the bottom of the cuboidal/prismoidal volume, and the Z height. If given as a 2D vector, contains the front X width of the rectangular/trapezoidal shape, and the Y length.
|
||||
// size2 = If given as a 2D vector, contains the XY size of the top of the prismoidal volume. If given as a number, contains the back width of the trapezoidal shape.
|
||||
// shift = If given as a 2D vector, shifts the top of the prismoidal or conical shape by the given amount. If given as a number, shifts the back of the trapezoidal shape right by that amount. Default: No shift.
|
||||
// r = Radius of the cylindrical/conical volume.
|
||||
// d = Diameter of the cylindrical/conical volume.
|
||||
// r1 = Radius of the bottom of the conical volume.
|
||||
// r2 = Radius of the top of the conical volume.
|
||||
// d1 = Diameter of the bottom of the conical volume.
|
||||
// d2 = Diameter of the top of the conical volume.
|
||||
// l = Length of the cylindrical/conical volume along axis.
|
||||
// vnf = The [VNF](vnf.scad) of the volume.
|
||||
// path = The path to generate a polygon from.
|
||||
// extent = If true, calculate anchors by extents, rather than intersection. Default: false.
|
||||
// offset = If given, offsets the center of the volume.
|
||||
// anchors = If given as a list of anchor points, allows named anchor points.
|
||||
// two_d = If true, the attachable shape is 2D. If false, 3D. Default: false (3D)
|
||||
//
|
||||
// Side Effects:
|
||||
// `$parent_size` is set to the parent object's cubical region size.
|
||||
// `$parent_size2` is set to the parent object's top [X,Y] size.
|
||||
// `$parent_shift` is set to the parent object's `shift` value, if any.
|
||||
// `$parent_geom` is set to the parent object's `geometry` value.
|
||||
// `$parent_orient` is set to the parent object's `orient` value.
|
||||
// `$parent_anchor` is set to the parent object's `anchor` value.
|
||||
// `$parent_anchors` is set to the parent object's list of non-standard extra anchors.
|
||||
// `$parent_2d` is set to the parent object's `two_d` value.
|
||||
// `$parent_spin` is set to the parent object's `spin` value.
|
||||
// `$parent_orient` is set to the parent object's `orient` value.
|
||||
// `$parent_geom` is set to the parent object's `geom` value.
|
||||
// `$parent_size` is set to the parent object's cubical `[X,Y,Z]` volume size.
|
||||
//
|
||||
// Example(Med):
|
||||
// #cylinder(d1=50, d2=30, h=60);
|
||||
// orient_and_anchor(size=[50,50,60], size2=[30,30], anchor=RIGHT, orient=FWD)
|
||||
// cylinder(d1=50, d2=30, h=60);
|
||||
module orient_and_anchor(
|
||||
size=undef,
|
||||
orient=UP,
|
||||
// Example(NORENDER): Cubical Shape
|
||||
// attachable(anchor, spin, orient, size=size) {
|
||||
// cube(size, center=true);
|
||||
// children();
|
||||
// }
|
||||
//
|
||||
// Example(NORENDER): Prismoidal Shape
|
||||
// attachable(
|
||||
// anchor, spin, orient,
|
||||
// size=point3d(botsize,h),
|
||||
// size2=topsize,
|
||||
// shift=shift
|
||||
// ) {
|
||||
// prismoid(botsize, topsize, h=h, shift=shift);
|
||||
// children();
|
||||
// }
|
||||
//
|
||||
// Example(NORENDER): Cylindrical Shape
|
||||
// attachable(anchor, spin, orient, r=r, l=h) {
|
||||
// cyl(r=r, l=h);
|
||||
// children();
|
||||
// }
|
||||
//
|
||||
// Example(NORENDER): Conical Shape
|
||||
// attachable(anchor, spin, orient, r1=r1, r2=r2, l=h) {
|
||||
// cyl(r1=r1, r2=r2, l=h);
|
||||
// children();
|
||||
// }
|
||||
//
|
||||
// Example(NORENDER): Spherical Shape
|
||||
// attachable(anchor, spin, orient, r=r) {
|
||||
// staggered_sphere(r=r);
|
||||
// children();
|
||||
// }
|
||||
//
|
||||
// Example(NORENDER): Arbitrary VNF Shape
|
||||
// attachable(anchor, spin, orient, vnf=vnf) {
|
||||
// vnf_polyhedron(vnf);
|
||||
// children();
|
||||
// }
|
||||
//
|
||||
// Example(NORENDER): 2D Rectangular Shape
|
||||
// attachable(anchor, spin, orient, size=size) {
|
||||
// square(size, center=true);
|
||||
// children();
|
||||
// }
|
||||
//
|
||||
// Example(NORENDER): 2D Trapezoidal Shape
|
||||
// attachable(
|
||||
// anchor, spin, orient,
|
||||
// size=[x1,y],
|
||||
// size2=x2,
|
||||
// shift=shift
|
||||
// ) {
|
||||
// trapezoid(w1=x1, w2=x2, h=y, shift=shift);
|
||||
// children();
|
||||
// }
|
||||
//
|
||||
// Example(NORENDER): 2D Circular Shape
|
||||
// attachable(anchor, spin, orient, two_d=true, r=r) {
|
||||
// circle(r=r);
|
||||
// children();
|
||||
// }
|
||||
//
|
||||
// Example(NORENDER): Arbitrary 2D Polygon Shape
|
||||
// attachable(anchor, spin, orient, path=path) {
|
||||
// polygon(path);
|
||||
// children();
|
||||
// }
|
||||
module attachable(
|
||||
anchor=CENTER,
|
||||
center=undef,
|
||||
noncentered=BOTTOM,
|
||||
spin=0,
|
||||
size2=undef,
|
||||
shift=[0,0],
|
||||
orient=UP,
|
||||
size, size2, shift,
|
||||
r,r1,r2, d,d1,d2, l,
|
||||
vnf, path,
|
||||
extent=true,
|
||||
offset=[0,0,0],
|
||||
geometry="cube",
|
||||
anchors=[],
|
||||
chain=false,
|
||||
two_d=false
|
||||
) {
|
||||
size2 = point2d(default(size2, size));
|
||||
shift = point2d(shift);
|
||||
anchr = is_undef(center)? anchor : (center? CENTER : noncentered);
|
||||
pos = find_anchor(anchr, size.z, size, size2=size2, shift=shift, offset=offset, anchors=anchors, geometry=geometry, two_d=two_d)[1];
|
||||
assert($children==2);
|
||||
assert(is_string(anchor) || is_vector(anchor));
|
||||
assert(is_num(spin));
|
||||
assert(is_vector(orient));
|
||||
assert(is_vector(offset));
|
||||
assert(is_list(anchors));
|
||||
|
||||
$parent_size = size;
|
||||
$parent_size2 = size2;
|
||||
$parent_shift = shift;
|
||||
$parent_geom = geometry;
|
||||
geom = !is_undef(size)? (
|
||||
two_d? (
|
||||
let(
|
||||
size2 = default(size2, size.x),
|
||||
shift = default(shift, 0)
|
||||
)
|
||||
assert(is_vector(size) && len(size)==2)
|
||||
assert(is_num(size2))
|
||||
assert(is_num(shift))
|
||||
["rect", point2d(size), size2, shift, offset, anchors]
|
||||
) : (
|
||||
let(
|
||||
size2 = default(size2, point2d(size)),
|
||||
shift = default(shift, [0,0])
|
||||
)
|
||||
assert(is_vector(size) && len(size)==3)
|
||||
assert(is_vector(size2) && len(size2)==2)
|
||||
assert(is_vector(shift) && len(shift)==2)
|
||||
["cuboid", size, size2, shift, offset, anchors]
|
||||
)
|
||||
) : !is_undef(vnf)? (
|
||||
assert(is_vnf(vnf))
|
||||
assert(two_d == false)
|
||||
extent? ["vnf_extent", vnf, offset, anchors] :
|
||||
["vnf_isect", vnf, offset, anchors]
|
||||
) : !is_undef(path)? (
|
||||
assert(is_path(path))
|
||||
assert(two_d == true)
|
||||
extent? ["path_extent", path, offset, anchors] :
|
||||
["path_isect", path, offset, anchors]
|
||||
) :
|
||||
let(
|
||||
r1 = get_radius(r1=r1,d1=d1,r=r,d=d,dflt=undef)
|
||||
)
|
||||
!is_undef(r1)? (
|
||||
assert(is_num(r1))
|
||||
!is_undef(l)? (
|
||||
let(
|
||||
shift = default(shift, [0,0]),
|
||||
r2 = get_radius(r1=r2,d1=d2,r=r,d=d,dflt=undef)
|
||||
)
|
||||
assert(is_num(l))
|
||||
assert(is_num(r2))
|
||||
assert(is_vector(shift) && len(shift)==2)
|
||||
["cyl", r1, r2, l, shift, offset, anchors]
|
||||
) : (
|
||||
two_d? ["circle", r1, offset, anchors] :
|
||||
["spheroid", r1, offset, anchors]
|
||||
)
|
||||
) :
|
||||
assert(false, "attachable(): Unrecognizable geometry description.");
|
||||
|
||||
pos = find_anchor(anchor, geom)[1];
|
||||
size = attach_geom_size(geom);
|
||||
|
||||
$parent_anchor = anchor;
|
||||
$parent_spin = spin;
|
||||
$parent_orient = orient;
|
||||
$parent_offset = offset;
|
||||
$parent_2d = two_d;
|
||||
$parent_anchor = anchr;
|
||||
$parent_anchors = anchors;
|
||||
$parent_geom = geom;
|
||||
$parent_size = size;
|
||||
|
||||
tags = _str_char_split($tags, " ");
|
||||
s_tags = $tags_shown;
|
||||
|
@ -274,7 +559,7 @@ module orient_and_anchor(
|
|||
shown = !s_tags || any([for (tag=tags) in_list(tag, s_tags)]);
|
||||
hidden = any([for (tag=tags) in_list(tag, h_tags)]);
|
||||
if ($attach_to != undef) {
|
||||
anch = find_anchor($attach_to, size.z, size, size2=size2, shift=shift, offset=offset, anchors=anchors, geometry=geometry, two_d=two_d);
|
||||
anch = find_anchor($attach_to, geom);
|
||||
ang = vector_angle(anch[2], two_d? BACK : DOWN);
|
||||
axis = two_d? UP : vector_axis(anch[2], DOWN);
|
||||
ang2 = (anch[2]==UP || anch[2]==DOWN)? 0 : 180-anch[3];
|
||||
|
@ -283,36 +568,39 @@ module orient_and_anchor(
|
|||
|
||||
rot(ang, v=axis2)
|
||||
rotate(ang2+spin)
|
||||
translate(-anch[1])
|
||||
{
|
||||
if ($children>1 && chain) {
|
||||
if(shown && !hidden) {
|
||||
color($color) for (i=[0:1:$children-2]) children(i);
|
||||
translate(-anch[1]) {
|
||||
if(shown && !hidden) {
|
||||
if (is_undef($color)) {
|
||||
children(0);
|
||||
} else color($color) {
|
||||
$color = undef;
|
||||
children(0);
|
||||
}
|
||||
children($children-1);
|
||||
} else {
|
||||
if(shown && !hidden) color($color) children();
|
||||
}
|
||||
children(1);
|
||||
}
|
||||
} else {
|
||||
rot(from=UP,to=orient)
|
||||
rotate(spin)
|
||||
translate(-pos)
|
||||
{
|
||||
if ($children>1 && chain) {
|
||||
if(shown && !hidden) {
|
||||
color($color) for (i=[0:1:$children-2]) children(i);
|
||||
translate(-pos) {
|
||||
if(shown && !hidden) {
|
||||
if (is_undef($color)) {
|
||||
children(0);
|
||||
} else color($color) {
|
||||
$color = undef;
|
||||
children(0);
|
||||
}
|
||||
children($children-1);
|
||||
} else {
|
||||
if(shown && !hidden) color($color) children();
|
||||
}
|
||||
children(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Section: Attachment Positioning
|
||||
|
||||
|
||||
// Module: position()
|
||||
// Usage:
|
||||
// position(from, [overlap]) ...
|
||||
|
@ -328,10 +616,10 @@ module orient_and_anchor(
|
|||
// }
|
||||
module position(from)
|
||||
{
|
||||
assert($parent_size != undef, "No object to attach to!");
|
||||
assert($parent_geom != undef, "No object to attach to!");
|
||||
anchors = (is_vector(from)||is_string(from))? [from] : from;
|
||||
for (anchr = anchors) {
|
||||
anch = find_anchor(anchr, $parent_size.z, point2d($parent_size), size2=$parent_size2, shift=$parent_shift, offset=$parent_offset, anchors=$parent_anchors, geometry=$parent_geom, two_d=$parent_2d);
|
||||
anch = find_anchor(anchr, $parent_geom);
|
||||
$attach_to = undef;
|
||||
$attach_anchor = anch;
|
||||
$attach_norot = true;
|
||||
|
@ -364,18 +652,19 @@ module position(from)
|
|||
// }
|
||||
module attach(from, to=undef, overlap=undef, norot=false)
|
||||
{
|
||||
assert($parent_size != undef, "No object to attach to!");
|
||||
assert($parent_geom != undef, "No object to attach to!");
|
||||
overlap = (overlap!=undef)? overlap : $overlap;
|
||||
anchors = (is_vector(from)||is_string(from))? [from] : from;
|
||||
for (anchr = anchors) {
|
||||
anch = find_anchor(anchr, $parent_size.z, point2d($parent_size), size2=$parent_size2, shift=$parent_shift, offset=$parent_offset, anchors=$parent_anchors, geometry=$parent_geom, two_d=$parent_2d);
|
||||
anch = find_anchor(anchr, $parent_geom);
|
||||
two_d = attach_geom_2d($parent_geom);
|
||||
$attach_to = to;
|
||||
$attach_anchor = anch;
|
||||
$attach_norot = norot;
|
||||
if (norot || (norm(anch[2]-UP)<1e-9 && anch[3]==0)) {
|
||||
translate(anch[1]) translate([0,0,-overlap]) children();
|
||||
} else {
|
||||
fromvec = $parent_2d? BACK : UP;
|
||||
fromvec = two_d? BACK : UP;
|
||||
translate(anch[1]) rot(anch[3],from=fromvec,to=anch[2]) translate([0,0,-overlap]) children();
|
||||
}
|
||||
}
|
||||
|
@ -400,7 +689,7 @@ module attach(from, to=undef, overlap=undef, norot=false)
|
|||
// edge_profile([TOP,"Z"],except=[BACK,TOP+LEFT])
|
||||
// mask2d_roundover(r=10, inset=2);
|
||||
module edge_profile(edges=EDGES_ALL, except=[], convexity=10) {
|
||||
assert($parent_size != undef, "No object to attach to!");
|
||||
assert($parent_geom != undef, "No object to attach to!");
|
||||
edges = edges(edges, except=except);
|
||||
vecs = [
|
||||
for (i = [0:3], axis=[0:2])
|
||||
|
@ -410,7 +699,7 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) {
|
|||
for (vec = vecs) {
|
||||
vcount = (vec.x?1:0) + (vec.y?1:0) + (vec.z?1:0);
|
||||
assert(vcount == 2, "Not an edge vector!");
|
||||
anch = find_anchor(vec, $parent_size.z, point2d($parent_size), size2=$parent_size2, shift=$parent_shift, offset=$parent_offset, anchors=$parent_anchors, geometry=$parent_geom, two_d=$parent_2d);
|
||||
anch = find_anchor(vec, $parent_geom);
|
||||
$attach_to = undef;
|
||||
$attach_anchor = anch;
|
||||
$attach_norot = true;
|
||||
|
@ -449,7 +738,7 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) {
|
|||
// edge_mask([TOP,"Z"],except=[BACK,TOP+LEFT])
|
||||
// rounding_mask_z(l=71,r=10);
|
||||
module edge_mask(edges=EDGES_ALL, except=[]) {
|
||||
assert($parent_size != undef, "No object to attach to!");
|
||||
assert($parent_geom != undef, "No object to attach to!");
|
||||
edges = edges(edges, except=except);
|
||||
vecs = [
|
||||
for (i = [0:3], axis=[0:2])
|
||||
|
@ -459,7 +748,7 @@ module edge_mask(edges=EDGES_ALL, except=[]) {
|
|||
for (vec = vecs) {
|
||||
vcount = (vec.x?1:0) + (vec.y?1:0) + (vec.z?1:0);
|
||||
assert(vcount == 2, "Not an edge vector!");
|
||||
anch = find_anchor(vec, $parent_size.z, point2d($parent_size), size2=$parent_size2, shift=$parent_shift, offset=$parent_offset, anchors=$parent_anchors, geometry=$parent_geom, two_d=$parent_2d);
|
||||
anch = find_anchor(vec, $parent_geom);
|
||||
$attach_to = undef;
|
||||
$attach_anchor = anch;
|
||||
$attach_norot = true;
|
||||
|
@ -495,13 +784,13 @@ module edge_mask(edges=EDGES_ALL, except=[]) {
|
|||
// translate([20,20,20]) sphere(r=20);
|
||||
// }
|
||||
module corner_mask(corners=CORNERS_ALL, except=[]) {
|
||||
assert($parent_size != undef, "No object to attach to!");
|
||||
assert($parent_geom != undef, "No object to attach to!");
|
||||
corners = corners(corners, except=except);
|
||||
vecs = [for (i = [0:7]) if (corners[i]>0) CORNER_OFFSETS[i]];
|
||||
for (vec = vecs) {
|
||||
vcount = (vec.x?1:0) + (vec.y?1:0) + (vec.z?1:0);
|
||||
assert(vcount == 3, "Not an edge vector!");
|
||||
anch = find_anchor(vec, $parent_size.z, point2d($parent_size), size2=$parent_size2, shift=$parent_shift, offset=$parent_offset, anchors=$parent_anchors, geometry=$parent_geom, two_d=$parent_2d);
|
||||
anch = find_anchor(vec, $parent_geom);
|
||||
$attach_to = undef;
|
||||
$attach_anchor = anch;
|
||||
$attach_norot = true;
|
||||
|
@ -597,7 +886,7 @@ module show(tags="")
|
|||
// Example:
|
||||
// diff("neg", "pos", keep="axle")
|
||||
// sphere(d=100, $tags="pos") {
|
||||
// attach(CENTER) xcyl(d=40, h=120, $tags="axle");
|
||||
// attach(CENTER) xcyl(d=40, l=120, $tags="axle");
|
||||
// attach(CENTER) cube([40,120,100], anchor=CENTER, $tags="neg");
|
||||
// }
|
||||
// Example: Masking
|
||||
|
@ -655,7 +944,7 @@ module diff(neg, pos=undef, keep=undef)
|
|||
// intersect("wheel", "mask", keep="axle")
|
||||
// sphere(d=100, $tags="wheel") {
|
||||
// attach(CENTER) cube([40,100,100], anchor=CENTER, $tags="mask");
|
||||
// attach(CENTER) xcyl(d=40, h=100, $tags="axle");
|
||||
// attach(CENTER) xcyl(d=40, l=100, $tags="axle");
|
||||
// }
|
||||
module intersect(a, b=undef, keep=undef)
|
||||
{
|
||||
|
@ -695,7 +984,7 @@ module intersect(a, b=undef, keep=undef)
|
|||
// hulling("body")
|
||||
// sphere(d=100, $tags="body") {
|
||||
// attach(CENTER) cube([40,90,90], anchor=CENTER, $tags="body");
|
||||
// attach(CENTER) xcyl(d=40, h=120, $tags="other");
|
||||
// attach(CENTER) xcyl(d=40, l=120, $tags="other");
|
||||
// }
|
||||
module hulling(a)
|
||||
{
|
||||
|
|
15
beziers.scad
15
beziers.scad
|
@ -468,10 +468,11 @@ module bezier_polygon(bezier, splinesteps=16, N=3) {
|
|||
// [ 25, -15], [-10, 0]
|
||||
// ];
|
||||
// linear_sweep_bezier(bez, height=20, splinesteps=32);
|
||||
module linear_sweep_bezier(bezier, height=100, splinesteps=16, N=3, center=undef, convexity=undef, twist=undef, slices=undef, scale=undef, anchor=BOTTOM, spin=0, orient=UP) {
|
||||
module linear_sweep_bezier(bezier, height=100, splinesteps=16, N=3, center, convexity, twist, slices, scale, anchor, spin=0, orient=UP) {
|
||||
maxx = max([for (pt = bezier) abs(pt[0])]);
|
||||
maxy = max([for (pt = bezier) abs(pt[1])]);
|
||||
orient_and_anchor([maxx*2,maxy*2,height], orient, anchor, spin=spin, center=center, chain=true) {
|
||||
anchor = get_anchor(anchor,center,BOT,BOT);
|
||||
attachable(anchor,spin,orient, size=[maxx*2,maxy*2,height]) {
|
||||
linear_extrude(height=height, center=true, convexity=convexity, twist=twist, slices=slices, scale=scale) {
|
||||
bezier_polygon(bezier, splinesteps=splinesteps, N=N);
|
||||
}
|
||||
|
@ -506,11 +507,13 @@ module linear_sweep_bezier(bezier, height=100, splinesteps=16, N=3, center=undef
|
|||
// rotate_sweep_bezier(path, splinesteps=32, $fn=180);
|
||||
module rotate_sweep_bezier(bezier, splinesteps=16, N=3, convexity=undef, angle=360, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
maxx = max([for (pt = bezier) abs(pt[0])]);
|
||||
maxy = max([for (pt = bezier) abs(pt[1])]);
|
||||
orient_and_anchor([maxx*2,maxx*2,0], orient, anchor, spin=spin, geometry="cylinder", chain=true) {
|
||||
oline = bezier_polyline(bezier, splinesteps=splinesteps, N=N);
|
||||
maxx = max([for (pt = oline) abs(pt[0])]);
|
||||
miny = min(subindex(oline,1));
|
||||
maxy = max(subindex(oline,1));
|
||||
attachable(anchor,spin,orient, r=maxx, l=max(abs(miny),abs(maxy))*2) {
|
||||
rotate_extrude(convexity=convexity, angle=angle) {
|
||||
bezier_polygon(bezier, splinesteps, N);
|
||||
polygon(oline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ module pco1810_neck(wall=2, anchor="support-ring", spin=0, orient=UP)
|
|||
anchorpt("support-ring", [0,0,neck_h-h/2]),
|
||||
anchorpt("tamper-ring", [0,0,h/2-tamper_base_h])
|
||||
];
|
||||
orient_and_anchor([support_d,support_d,h], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, d=support_d, l=h, anchors=anchors) {
|
||||
down(h/2) {
|
||||
rotate_extrude(convexity=10) {
|
||||
polygon(turtle(
|
||||
|
@ -159,7 +159,7 @@ module pco1810_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP)
|
|||
anchors = [
|
||||
anchorpt("inside-top", [0,0,-(h/2-wall)])
|
||||
];
|
||||
orient_and_anchor([w, w, h], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, d=w, l=h, anchors=anchors) {
|
||||
down(h/2) zrot(45) {
|
||||
difference() {
|
||||
union() {
|
||||
|
@ -236,7 +236,7 @@ module pco1881_neck(wall=2, anchor="support-ring", spin=0, orient=UP)
|
|||
anchorpt("support-ring", [0,0,neck_h-h/2]),
|
||||
anchorpt("tamper-ring", [0,0,h/2-tamper_base_h])
|
||||
];
|
||||
orient_and_anchor([support_d,support_d,h], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, d=support_d, l=h, anchors=anchors) {
|
||||
down(h/2) {
|
||||
rotate_extrude(convexity=10) {
|
||||
polygon(turtle(
|
||||
|
@ -323,7 +323,7 @@ module pco1881_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP)
|
|||
anchors = [
|
||||
anchorpt("inside-top", [0,0,-(h/2-wall)])
|
||||
];
|
||||
orient_and_anchor([w, w, h], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, d=w, l=h, anchors=anchors) {
|
||||
down(h/2) zrot(45) {
|
||||
difference() {
|
||||
union() {
|
||||
|
|
|
@ -55,7 +55,7 @@ module cubetruss_segment(size=undef, strut=undef, bracing=undef, anchor=CENTER,
|
|||
h = size;
|
||||
crossthick = strut/sqrt(2);
|
||||
voffset = 0.333;
|
||||
orient_and_anchor(size=[size, size, size], anchor=anchor, spin=spin, orient=orient, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[size,size,size]) {
|
||||
render(convexity=10)
|
||||
union() {
|
||||
difference() {
|
||||
|
@ -123,7 +123,7 @@ module cubetruss_clip(extents=1, size=undef, strut=undef, clipthick=undef, ancho
|
|||
clipheight = min(size+strut, size/3+2*strut*2.6);
|
||||
clipsize = 0.5;
|
||||
s = [extents*(size-strut)+strut+2*clipthick, strut*2, clipheight-2*strut];
|
||||
orient_and_anchor(size=s, anchor=anchor, spin=spin, orient=orient, chain=true) {
|
||||
attachable(anchor,spin,orient, size=s) {
|
||||
xflip_copy(offset=(extents*(size-strut)+strut)/2) {
|
||||
difference() {
|
||||
union() {
|
||||
|
@ -184,7 +184,7 @@ module cubetruss_foot(w=1, size=undef, strut=undef, clipthick=undef, anchor=CENT
|
|||
wall_h = strut+clipthick*1.5;
|
||||
cyld = (size-2*strut)/cos(180/8);
|
||||
s = [w*(size-strut)+strut+2*clipthick, size-2*strut, strut+clipthick];
|
||||
orient_and_anchor(size=s, anchor=anchor, spin=spin, orient=orient, offset=[0,0,(strut-clipthick)/2], chain=true) {
|
||||
attachable(anchor,spin,orient, size=s, offset=[0,0,(strut-clipthick)/2]) {
|
||||
down(clipthick) {
|
||||
// Base
|
||||
up(clipthick/2) {
|
||||
|
@ -258,7 +258,7 @@ module cubetruss_joiner(w=1, vert=true, size=undef, strut=undef, clipthick=undef
|
|||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
clipsize = 0.5;
|
||||
s = [cubetruss_dist(w,1)+2*clipthick, cubetruss_dist(2,0)-0.1, strut+clipthick];
|
||||
orient_and_anchor(size=s, anchor=anchor, spin=spin, orient=orient, offset=[0,0,-(clipthick-strut)/2], chain=true) {
|
||||
attachable(anchor,spin,orient, size=s, offset=[0,0,-(clipthick-strut)/2]) {
|
||||
down(clipthick) {
|
||||
// Base
|
||||
cube([w*(size-strut)+strut+2*clipthick, size, clipthick], anchor=BOT);
|
||||
|
@ -319,7 +319,7 @@ module cubetruss_uclip(dual=true, size=undef, strut=undef, clipthick=undef, anch
|
|||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
clipsize = 0.5;
|
||||
s = [(dual?2:1)*strut+2*clipthick+$slop, strut+2*clipthick, size/3.5];
|
||||
orient_and_anchor(size=s, anchor=anchor, spin=spin, orient=orient, chain=true) {
|
||||
attachable(anchor,spin,orient, size=s) {
|
||||
union() {
|
||||
difference() {
|
||||
cube(s, center=true);
|
||||
|
@ -373,7 +373,7 @@ module cubetruss(extents=6, clips=[], bracing=undef, size=undef, strut=undef, cl
|
|||
l = extents[1];
|
||||
h = extents[2];
|
||||
s = [cubetruss_dist(w,1), cubetruss_dist(l,1), cubetruss_dist(h,1)];
|
||||
orient_and_anchor(size=s, anchor=anchor, spin=spin, orient=orient, chain=true) {
|
||||
attachable(anchor,spin,orient, size=s) {
|
||||
union() {
|
||||
for (zrow = [0:h-1]) {
|
||||
up((zrow-(h-1)/2)*(size-strut)) {
|
||||
|
@ -437,7 +437,7 @@ module cubetruss_corner(h=1, extents=[1,1,0,0,1], bracing=undef, size=undef, str
|
|||
exts = is_vector(extents)? list_fit(extents,5,fill=0) : [extents, extents, 0, 0, extents];
|
||||
s = [cubetruss_dist(1+exts[0]+exts[2],1), cubetruss_dist(1+exts[1]+exts[3],1), cubetruss_dist(h+exts[4],1)];
|
||||
offset = [cubetruss_dist(exts[0]-exts[2],0), cubetruss_dist(exts[1]-exts[3],0), cubetruss_dist(exts[4],0)]/2;
|
||||
orient_and_anchor(size=s, anchor=anchor, spin=spin, orient=orient, offset=offset, chain=true) {
|
||||
attachable(anchor,spin,orient, size=s, offset=offset) {
|
||||
union() {
|
||||
for (zcol = [0:h-1]) {
|
||||
up((size-strut+0.01)*zcol) {
|
||||
|
|
20
debug.scad
20
debug.scad
|
@ -168,13 +168,17 @@ function standard_anchors() = [
|
|||
// anchor_arrow(s=20);
|
||||
module anchor_arrow(s=10, color=[0.333,0.333,1], flag=true, $tags="anchor-arrow") {
|
||||
$fn=12;
|
||||
recolor("gray") spheroid(d=s/6)
|
||||
attach(CENTER,BOT) recolor(color) cyl(h=s*2/3, d=s/15, anchor=BOT)
|
||||
attach(TOP) cyl(h=s/3, d1=s/5, d2=0, anchor=BOT) {
|
||||
if(flag) {
|
||||
attach(BOTTOM) recolor([1,0.5,0.5]) cuboid([s/50, s/6, s/4], anchor=FRONT+TOP);
|
||||
recolor("gray") spheroid(d=s/6) {
|
||||
attach(CENTER,BOT) recolor(color) cyl(h=s*2/3, d=s/15) {
|
||||
attach(TOP,BOT) cyl(h=s/3, d1=s/5, d2=0) {
|
||||
if(flag) {
|
||||
position(BOT)
|
||||
recolor([1,0.5,0.5])
|
||||
cuboid([s/100, s/6, s/4], anchor=FRONT+BOT);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,7 +214,7 @@ module show_anchors(s=10, std=true, custom=true) {
|
|||
}
|
||||
}
|
||||
if (custom) {
|
||||
for (anchor=$parent_anchors) {
|
||||
for (anchor=select($parent_geom,-1)) {
|
||||
attach(anchor[0]) {
|
||||
anchor_arrow(s, color="cyan");
|
||||
recolor("black")
|
||||
|
@ -287,7 +291,7 @@ module ruler(length=100, width=undef, thickness=1, depth=3, labels=false, pipsca
|
|||
width = default(width, scales[0]);
|
||||
widths = width * widthfactor * [for(logsize = [0:-1:-depth+1]) pow(pipscale,-logsize)];
|
||||
offsets = concat([0],cumsum(widths));
|
||||
orient_and_anchor([length,width,thickness], anchor=anchor, spin=spin, orient=orient, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[length,width,thickness], offset=offset) {
|
||||
translate([-length/2, -width/2, 0])
|
||||
for(i=[0:1:len(scales)-1]){
|
||||
count = ceil(length/scales[i]);
|
||||
|
|
|
@ -4,8 +4,8 @@ $fn=32;
|
|||
|
||||
cuboid([60,40,40], rounding=5, edges=edges("Z"), anchor=BOTTOM) {
|
||||
attach(TOP, BOTTOM) rounded_prismoid([60,40],[20,20], h=50, r1=5, r2=10) {
|
||||
attach(TOP) cylinder(d=20, h=30) {
|
||||
attach(TOP) cylinder(d1=50, d2=30, h=12);
|
||||
attach(TOP) cylinder(d=20, h=30, center=false) {
|
||||
attach(TOP) cylinder(d1=50, d2=30, h=12, center=false);
|
||||
}
|
||||
attach([FRONT, BACK, LEFT, RIGHT]) cylinder(d1=14, d2=5, h=20) {
|
||||
attach(TOP, LEFT, overlap=5) prismoid([30,20], [20,20], h=10, shift=[-7,0]);
|
||||
|
|
70
examples/lsystems.scad
Normal file
70
examples/lsystems.scad
Normal file
|
@ -0,0 +1,70 @@
|
|||
include <BOSL2/std.scad>
|
||||
|
||||
function _lsystem_recurse(s, rules, lev) =
|
||||
lev<=0? s : _lsystem_recurse([
|
||||
for (
|
||||
i = 0,
|
||||
slen = len(s),
|
||||
sout = "";
|
||||
|
||||
i <= slen;
|
||||
|
||||
ch = s[i],
|
||||
found = search([ch], rules)[0],
|
||||
sout = str(sout, i==slen? "" : found==[]? ch : rules[found][1]),
|
||||
i = i + 1
|
||||
) if (i==slen) sout
|
||||
][0], rules, lev-1);
|
||||
|
||||
|
||||
function _lsystem_to_turtle(s, step=1, angle=90, startang=0) =
|
||||
concat(
|
||||
startang? ["left", startang] : [],
|
||||
["angle", angle, "length", step],
|
||||
[
|
||||
for (
|
||||
i = 0,
|
||||
slen = len(s);
|
||||
|
||||
i <= slen;
|
||||
|
||||
ch = s[i],
|
||||
cmd = (ch=="A" || ch=="B" || ch=="F")? ["move"] :
|
||||
(ch=="+")? ["left"] :
|
||||
(ch=="-")? ["right"] :
|
||||
[],
|
||||
i=i+1
|
||||
) if(i>0 && cmd!=[]) each cmd
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
function lsystem_turtle(basis, rules, levels=5, step=1, angle=90, startang=0) =
|
||||
turtle(_lsystem_to_turtle(_lsystem_recurse(basis, rules, levels), step=step, angle=angle, startang=startang));
|
||||
|
||||
|
||||
function dragon_curve (levels=9, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "FX", [["X", "X+YF+"], ["Y", "-FX-Y"]]);
|
||||
function terdragon_curve (levels=7, step=1) = lsystem_turtle(levels=levels, step=step, angle=120, "F", [["F", "F+F-F"]]);
|
||||
function twindragon_curve (levels=11, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "FX+FX+", [["X", "X+YF"], ["Y","FX-Y"]]);
|
||||
function moore_curve (levels=4, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "LFL+F+LFL", [["L", "-RF+LFL+FR-"], ["R", "+LF-RFR-FL+"]]);
|
||||
function hilbert_curve (levels=4, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "X", [["X","-YF+XFX+FY-"], ["Y","+XF-YFY-FX+"]]);
|
||||
function gosper_curve (levels=4, step=1) = lsystem_turtle(levels=levels, step=step, angle=60, "A", [["A", "A-B--B+A++AA+B-"], ["B", "+A-BB--B-A++A+B"]]);
|
||||
function quadratic_gosper (levels=2, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "-YF", [["X", "XFX-YF-YF+FX+FX-YF-YFFX+YF+FXFXYF-FX+YF+FXFX+YF-FXYF-YF-FX+FX+YFYF-"], ["Y", "+FXFX-YF-YF+FX+FXYF+FX-YFYF-FX-YF+FXYFYF-FX-YFFX+FX+YF-YF-FX+FX+YFY"]]);
|
||||
function peano_curve (levels=4, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "X", [["X","XFYFX+F+YFXFY-F-XFYFX"], ["Y","YFXFY-F-XFYFX+F+YFXFY"]]);
|
||||
function koch_snowflake (levels=4, step=1) = lsystem_turtle(levels=levels, step=step, angle=60, "F++F++F", [["F","F-F++F-F"]]);
|
||||
function sierpinski_arrowhead(levels=6, step=1) = lsystem_turtle(levels=levels, step=step, angle=60, "A", [["A", "B-A-B"], ["B","A+B+A"]]);
|
||||
function sierpinski_triangle (levels=4, step=1) = lsystem_turtle(levels=levels, step=step, angle=120, "A-B-B", [["A","A-B+A+B-A"], ["B","BB"]]);
|
||||
function square_sierpinski (levels=5, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "F+XF+F+XF", [["X","XF-F+F-XF+F+XF-F+F-X"]]);
|
||||
function cesaro_curve (levels=4, step=1) = lsystem_turtle(levels=levels, step=step, angle=85, "F", [["F","F+F--F+F"]]);
|
||||
function paul_bourke1 (levels=3, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "F+F+F+F+", [["F","F+F-F-FF+F+F-F"]]);
|
||||
function paul_bourke_triangle(levels=6, step=1) = lsystem_turtle(levels=levels, step=step, angle=120, "F+F+F", [["F","F-F+F"]]);
|
||||
function paul_bourke_crystal (levels=4, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "F+F+F+F", [["F","FF+F++F+F"]]);
|
||||
function space_filling_tree (levels=4, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "X", [["X","FX++F-FX++F-FX++F-FX++F-"],["F", "FF"]], startang=45);
|
||||
function krishna_anklets (levels=6, step=1) = lsystem_turtle(levels=levels, step=step, angle=45, "-X--X", [["X","XFX--XFX"]]);
|
||||
|
||||
|
||||
points = hilbert_curve(levels=5, step=100/pow(2,5));
|
||||
stroke(points, width=1);
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
|
@ -30,7 +30,9 @@
|
|||
module folding_hinge_mask(l, thick, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
hingegap = default(hingegap, layerheight)+2*$slop;
|
||||
orient_and_anchor(size=[l, hingegap, 2*thick], size2=[l,hingegap+2*thick*tan(foldangle/2)], anchor=anchor, spin=spin, orient=orient, chain=true) {
|
||||
size = [l, hingegap, 2*thick];
|
||||
size2 = [l, hingegap+2*thick*tan(foldangle/2)];
|
||||
attachable(anchor,spin,orient, size=size, size2=size2) {
|
||||
up(layerheight*2) prismoid([l,hingegap], [l, hingegap+2*thick/tan(foldangle/2)], h=thick, anchor=BOT);
|
||||
children();
|
||||
}
|
||||
|
@ -58,7 +60,8 @@ module snap_lock(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hi
|
|||
{
|
||||
hingegap = default(hingegap, layerheight)+2*$slop;
|
||||
snap_x = (snapdiam/2) / tan(foldangle/2) + (thick-2*layerheight)/tan(foldangle/2) + hingegap/2;
|
||||
orient_and_anchor(size=[snaplen, snapdiam, 2*thick], anchor=anchor, spin=spin, orient=orient, chain=true) {
|
||||
size = [snaplen, snapdiam, 2*thick];
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
back(snap_x) {
|
||||
cube([snaplen, snapdiam, snapdiam/2+thick], anchor=BOT) {
|
||||
attach(TOP) xcyl(l=snaplen, d=snapdiam, $fn=16);
|
||||
|
@ -91,7 +94,8 @@ module snap_socket(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90,
|
|||
{
|
||||
hingegap = default(hingegap, layerheight)+2*$slop;
|
||||
snap_x = (snapdiam/2) / tan(foldangle/2) + (thick-2*layerheight)/tan(foldangle/2) + hingegap/2;
|
||||
orient_and_anchor(size=[snaplen, snapdiam, 2*thick], anchor=anchor, spin=spin, orient=orient, chain=true) {
|
||||
size = [snaplen, snapdiam, 2*thick];
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
fwd(snap_x) {
|
||||
zrot_copies([0,180], r=snaplen+$slop) {
|
||||
diff("divot")
|
||||
|
|
|
@ -371,7 +371,7 @@ module gear(
|
|||
c = outer_radius(pitch, teeth, clearance, interior);
|
||||
r = root_radius(pitch, teeth, clearance, interior);
|
||||
twist = atan2(thickness*tan(helical),p);
|
||||
orient_and_anchor([p, p, thickness], orient, anchor, spin=spin, geometry="cylinder", chain=true) {
|
||||
attachable(anchor,spin,orient, r=p, l=thickness) {
|
||||
difference() {
|
||||
linear_extrude(height=thickness, center=true, convexity=10, twist=twist) {
|
||||
gear2d(
|
||||
|
@ -545,7 +545,7 @@ module bevel_gear(
|
|||
]
|
||||
]
|
||||
);
|
||||
orient_and_anchor([p1, p1, thickness], orient, anchor, spin=spin, size2=[p2,p2], geometry="cylinder", chain=true) {
|
||||
attachable(anchor,spin,orient, r1=p1, r2=p2, l=thickness) {
|
||||
union() {
|
||||
difference() {
|
||||
down(thickness/2) {
|
||||
|
@ -630,7 +630,7 @@ module rack(
|
|||
anchorpt("dedendum-top", [0,-d,thickness/2], UP),
|
||||
anchorpt("dedendum-bottom", [0,-d,-thickness/2], DOWN),
|
||||
];
|
||||
orient_and_anchor([l, 2*abs(a-height), thickness], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[l, 2*abs(a-height), thickness], anchors=anchors) {
|
||||
left((teeth-1)*pitch/2) {
|
||||
linear_extrude(height = thickness, center = true, convexity = 10) {
|
||||
for (i = [0:1:teeth-1] ) {
|
||||
|
|
62
joiners.scad
62
joiners.scad
|
@ -39,7 +39,7 @@ module half_joiner_clear(h=20, w=10, a=30, clearance=0, overlap=0.01, anchor=CEN
|
|||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
|
||||
orient_and_anchor([w, guide_width, h], orient, anchor, spin=spin) {
|
||||
attachable(anchor,spin,orient, size=[w, guide_width, h]) {
|
||||
union() {
|
||||
yspread(overlap, n=overlap>0? 2 : 1) {
|
||||
difference() {
|
||||
|
@ -55,6 +55,7 @@ module half_joiner_clear(h=20, w=10, a=30, clearance=0, overlap=0.01, anchor=CEN
|
|||
}
|
||||
if (overlap>0) cube([w+clearance, overlap+0.001, h], center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,14 +86,8 @@ module half_joiner(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=
|
|||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
|
||||
if ($children > 0) {
|
||||
difference() {
|
||||
children();
|
||||
half_joiner_clear(h=h, w=w, a=a, clearance=0.1, overlap=0.01, anchor=anchor, spin=spin, orient=orient);
|
||||
}
|
||||
}
|
||||
render(convexity=12)
|
||||
orient_and_anchor([w, 2*l, h], orient, anchor, spin=spin) {
|
||||
attachable(anchor,spin,orient, size=[w, 2*l, h]) {
|
||||
difference() {
|
||||
union() {
|
||||
// Make base.
|
||||
|
@ -101,7 +96,7 @@ module half_joiner(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=
|
|||
fwd(l/2) cube(size=[w, l, h], center=true);
|
||||
|
||||
// Clear diamond for tab
|
||||
grid3d(xa=[-(w*2/3), (w*2/3)]) {
|
||||
xspread(2*w*2/3) {
|
||||
half_joiner_clear(h=h+0.01, w=w, clearance=$slop*2, a=a);
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +133,7 @@ module half_joiner(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=
|
|||
yrot(90) cylinder(r=screwsize*1.1/2, h=w+1, center=true, $fn=12);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
//half_joiner(screwsize=3);
|
||||
|
@ -168,15 +164,8 @@ module half_joiner2(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor
|
|||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
|
||||
if ($children > 0) {
|
||||
difference() {
|
||||
children();
|
||||
half_joiner_clear(h=h, w=w, a=a, clearance=0.1, overlap=0.01, orient=orient, spin=spin, anchor=anchor);
|
||||
}
|
||||
}
|
||||
|
||||
render(convexity=12)
|
||||
orient_and_anchor([w, 2*l, h], orient, anchor, spin=spin) {
|
||||
attachable(anchor,spin,orient, size=[w, 2*l, h]) {
|
||||
difference() {
|
||||
union () {
|
||||
fwd(l/2) cube(size=[w, l, h], center=true);
|
||||
|
@ -191,6 +180,7 @@ module half_joiner2(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor
|
|||
xcyl(r=screwsize*1.1/2, l=w+1, $fn=12);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,11 +212,12 @@ module joiner_clear(h=40, w=10, a=30, clearance=0, overlap=0.01, anchor=CENTER,
|
|||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
|
||||
orient_and_anchor([w, guide_width, h], orient, anchor, spin=spin) {
|
||||
attachable(anchor,spin,orient, size=[w, guide_width, h]) {
|
||||
union() {
|
||||
up(h/4) half_joiner_clear(h=h/2.0-0.01, w=w, a=a, overlap=overlap, clearance=clearance);
|
||||
down(h/4) half_joiner_clear(h=h/2.0-0.01, w=w, a=a, overlap=overlap, clearance=-0.01);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,17 +244,12 @@ module joiner_clear(h=40, w=10, a=30, clearance=0, overlap=0.01, anchor=CENTER,
|
|||
// joiner(w=10, l=10, h=40, spin=-90) cuboid([10, 10*2, 40], anchor=RIGHT);
|
||||
module joiner(h=40, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
if ($children > 0) {
|
||||
difference() {
|
||||
children();
|
||||
joiner_clear(h=h, w=w, a=a, clearance=0.1, orient=orient, spin=spin, anchor=anchor);
|
||||
}
|
||||
}
|
||||
orient_and_anchor([w, 2*l, h], orient, anchor, spin=spin) {
|
||||
attachable(anchor,spin,orient, size=[w, 2*l, h]) {
|
||||
union() {
|
||||
up(h/4) half_joiner(h=h/2, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
down(h/4) half_joiner2(h=h/2, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,10 +284,11 @@ module joiner_pair_clear(spacing=100, h=40, w=10, a=30, n=2, clearance=0, overla
|
|||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
|
||||
orient_and_anchor([spacing+w, guide_width, h], orient, anchor, spin=spin) {
|
||||
attachable(anchor,spin,orient, size=[spacing+w, guide_width, h]) {
|
||||
xspread(spacing, n=n) {
|
||||
joiner_clear(h=h, w=w, a=a, clearance=clearance, overlap=overlap);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,13 +321,7 @@ module joiner_pair_clear(spacing=100, h=40, w=10, a=30, n=2, clearance=0, overla
|
|||
// joiner_pair(spacing=50, l=10, n=3, alternate="alt", spin=-90);
|
||||
module joiner_pair(spacing=100, h=40, w=10, l=10, a=30, n=2, alternate=true, screwsize=undef, guides=true, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
if ($children > 0) {
|
||||
difference() {
|
||||
children();
|
||||
joiner_pair_clear(spacing=spacing, h=h, w=w, a=a, clearance=0.1, orient=orient, spin=spin, anchor=anchor);
|
||||
}
|
||||
}
|
||||
orient_and_anchor([spacing+w, 2*l, h], orient, anchor, spin=spin) {
|
||||
attachable(anchor,spin,orient, size=[spacing+w, 2*l, h]) {
|
||||
left((n-1)*spacing/2) {
|
||||
for (i=[0:1:n-1]) {
|
||||
right(i*spacing) {
|
||||
|
@ -350,6 +331,7 @@ module joiner_pair(spacing=100, h=40, w=10, l=10, a=30, n=2, alternate=true, scr
|
|||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,12 +364,13 @@ module joiner_quad_clear(xspacing=undef, yspacing=undef, spacing1=undef, spacing
|
|||
{
|
||||
spacing1 = first_defined([spacing1, xspacing, 100]);
|
||||
spacing2 = first_defined([spacing2, yspacing, 50]);
|
||||
orient_and_anchor([w+spacing1, spacing2, h], orient, anchor, spin=spin) {
|
||||
attachable(anchor,spin,orient, size=[w+spacing1, spacing2, h]) {
|
||||
zrot_copies(n=2) {
|
||||
back(spacing2/2) {
|
||||
joiner_pair_clear(spacing=spacing1, n=n, h=h, w=w, a=a, clearance=clearance, overlap=overlap);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,18 +405,13 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
|
|||
{
|
||||
spacing1 = first_defined([spacing1, xspacing, 100]);
|
||||
spacing2 = first_defined([spacing2, yspacing, 50]);
|
||||
if ($children > 0) {
|
||||
difference() {
|
||||
children();
|
||||
joiner_quad_clear(spacing1=spacing1, spacing2=spacing2, h=h, w=w, a=a, clearance=0.1, orient=orient, spin=spin, anchor=anchor);
|
||||
}
|
||||
}
|
||||
orient_and_anchor([w+spacing1, spacing2, h], orient, anchor, spin=spin) {
|
||||
attachable(anchor,spin,orient, size=[w+spacing1, spacing2, h]) {
|
||||
zrot_copies(n=2) {
|
||||
back(spacing2/2) {
|
||||
joiner_pair(spacing=spacing1, n=n, h=h, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,7 +549,7 @@ module dovetail(gender, length, l, width, w, height, h, angle, slope, taper, bac
|
|||
|
||||
adjustment = gender == "male" ? -0.01 : 0.01; // Adjustment for default overlap in attach()
|
||||
|
||||
orient_and_anchor([width+2*offset, length, height],anchor=anchor,orient=orient,spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[width+2*offset, length, height]) {
|
||||
down(height/2+adjustment) {
|
||||
skin(
|
||||
[
|
||||
|
|
|
@ -107,7 +107,7 @@ module knurled_cylinder(
|
|||
]
|
||||
]
|
||||
);
|
||||
orient_and_anchor([2*r1,2*r1,l], size2=[2*r2,2*r2], anchor=anchor, spin=spin, orient=orient, geometry="cylinder", chain=true) {
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
intersection() {
|
||||
polyhedron(points=vertices, faces=faces, convexity=2*layers);
|
||||
cyl(
|
||||
|
@ -157,7 +157,7 @@ module knurled_cylinder_mask(
|
|||
) {
|
||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=10);
|
||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=10);
|
||||
orient_and_anchor([2*r1,2*r1,l], size2=[2*r2,2*r2], anchor=anchor, spin=spin, orient=orient, geometry="cylinder", chain=true) {
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
difference() {
|
||||
cylinder(r1=r1+overage, r2=r2+overage, h=l, center=true);
|
||||
knurled_cylinder(r1=r1, r2=r2, l=l+0.01);
|
||||
|
|
|
@ -92,7 +92,7 @@ module linear_bearing_housing(d=15, l=24, tab=7, gap=5, wall=3, tabwall=5, screw
|
|||
anchorpt("screw", [0,2-ogap/2,tabh-tab/2/2],FWD),
|
||||
anchorpt("nut", [0,ogap/2-2,tabh-tab/2/2],FWD)
|
||||
];
|
||||
orient_and_anchor([l, od, h], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[l, od, h], anchors=anchors) {
|
||||
down(tab/2/2)
|
||||
difference() {
|
||||
union() {
|
||||
|
|
49
masks.scad
49
masks.scad
|
@ -40,7 +40,7 @@ module angle_pie_mask(
|
|||
l = first_defined([l, h, 1]);
|
||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=10);
|
||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=10);
|
||||
orient_and_anchor([2*r1, 2*r1, l], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
pie_slice(ang=ang, l=l+0.1, r1=r1, r2=r2, anchor=CENTER);
|
||||
children();
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ module cylinder_mask(
|
|||
cylinder_mask(l=l, r1=sc*r1, r2=sc*r2, chamfer1=cham1, chamfer2=cham2, chamfang1=ang1, chamfang2=ang2, rounding1=fil1, rounding2=fil2, orient=orient, from_end=from_end);
|
||||
}
|
||||
} else {
|
||||
orient_and_anchor([2*r1, 2*r1, l], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, r=r1, l=l) {
|
||||
difference() {
|
||||
union() {
|
||||
chlen1 = cham1 / (from_end? 1 : tan(ang1));
|
||||
|
@ -142,7 +142,7 @@ module cylinder_mask(
|
|||
}
|
||||
cyl(r1=sc*r1, r2=sc*r2, l=l, chamfer1=cham1, chamfer2=cham2, chamfang1=ang1, chamfang2=ang2, from_end=from_end, rounding1=fil1, rounding2=fil2);
|
||||
}
|
||||
children();
|
||||
nil();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ module cylinder_mask(
|
|||
// #chamfer_mask(l=50, chamfer=10, orient=RIGHT);
|
||||
// }
|
||||
module chamfer_mask(l=1, chamfer=1, anchor=CENTER, spin=0, orient=UP) {
|
||||
orient_and_anchor([chamfer*2, chamfer*2, l], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[chamfer*2, chamfer*2, l]) {
|
||||
cylinder(r=chamfer, h=l+0.1, center=true, $fn=4);
|
||||
children();
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ module chamfer(chamfer=1, size=[1,1,1], edges=EDGES_ALL, except_edges=[])
|
|||
module chamfer_cylinder_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
orient_and_anchor([2*r,2*r,chamfer*2], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, r=r, l=chamfer*2) {
|
||||
cylinder_mask(l=chamfer*3, r=r, chamfer2=chamfer, chamfang2=ang, from_end=from_end, ends_only=true, anchor=TOP);
|
||||
children();
|
||||
}
|
||||
|
@ -348,7 +348,7 @@ module chamfer_hole_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false,
|
|||
h = chamfer * (from_end? 1 : tan(90-ang));
|
||||
r2 = r + chamfer * (from_end? tan(ang) : 1);
|
||||
$fn = segs(r);
|
||||
orient_and_anchor([2*r, 2*r, h*2], orient, anchor, spin=spin, size2=[2*r2, 2*r2], chain=true) {
|
||||
attachable(anchor,spin,orient, r1=r, r2=r2, l=h*2) {
|
||||
union() {
|
||||
cylinder(r=r2, h=overage, center=false);
|
||||
down(h) cylinder(r1=r, r2=r2, h=h, center=false);
|
||||
|
@ -410,7 +410,7 @@ module rounding_mask(l=undef, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
|
|||
r1 = get_radius(r1=r1, r=r, dflt=1);
|
||||
r2 = get_radius(r1=r2, r=r, dflt=1);
|
||||
sides = quantup(segs(max(r1,r2)),4);
|
||||
orient_and_anchor([2*r1, 2*r1, l], orient, anchor, spin=spin, size2=[2*r2,2*r2], chain=true) {
|
||||
attachable(anchor,spin,orient, size=[2*r1,2*r1,l], size2=[2*r2,2*r2]) {
|
||||
if (r1<r2) {
|
||||
zflip() {
|
||||
linear_extrude(height=l, convexity=4, center=true, scale=r1/r2) {
|
||||
|
@ -596,23 +596,28 @@ module rounding(r=1, size=[1,1,1], edges=EDGES_ALL, except_edges=[])
|
|||
// }
|
||||
module rounding_angled_edge_mask(h=1.0, r=undef, r1=undef, r2=undef, ang=90, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
function _mask_shape(r) = [
|
||||
for (i = [0:1:n]) let (a=90+ang+i*sweep/n) [r*cos(a)+x, r*sin(a)+r],
|
||||
for (i = [0:1:n]) let (a=90+i*sweep/n) [r*cos(a)+x, r*sin(a)-r],
|
||||
[min(-1, r*cos(270-ang)+x-1), r*sin(270-ang)-r],
|
||||
[min(-1, r*cos(90+ang)+x-1), r*sin(90+ang)+r],
|
||||
];
|
||||
|
||||
sweep = 180-ang;
|
||||
n = ceil(segs(max(r1,r2))*sweep/360);
|
||||
x = r1*sin(90-(ang/2))/sin(ang/2);
|
||||
r1 = get_radius(r1=r1, r=r, dflt=1);
|
||||
r2 = get_radius(r1=r2, r=r, dflt=1);
|
||||
orient_and_anchor([2*x,2*r1,h], orient, anchor, spin=spin, size2=[2*x*r2/r1,2*r2], chain=true) {
|
||||
linear_extrude(height=h, convexity=4, center=true, scale=r2/r1) {
|
||||
polygon(
|
||||
points=concat(
|
||||
[for (i = [0:1:n]) let (a=90+ang+i*sweep/n) [r1*cos(a)+x, r1*sin(a)+r1]],
|
||||
[for (i = [0:1:n]) let (a=90+i*sweep/n) [r1*cos(a)+x, r1*sin(a)-r1]],
|
||||
[
|
||||
[min(-1, r1*cos(270-ang)+x-1), r1*sin(270-ang)-r1],
|
||||
[min(-1, r1*cos(90+ang)+x-1), r1*sin(90+ang)+r1],
|
||||
]
|
||||
)
|
||||
);
|
||||
attachable(anchor,spin,orient, size=[2*x,2*r1,h], size2=[2*x*r2/r1,2*r2]) {
|
||||
if(r1<r2) {
|
||||
zflip()
|
||||
linear_extrude(height=h, convexity=4, center=true, scale=r1/r2) {
|
||||
polygon(_mask_shape(r2));
|
||||
}
|
||||
} else {
|
||||
linear_extrude(height=h, convexity=4, center=true, scale=r2/r1) {
|
||||
polygon(_mask_shape(r1));
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
|
@ -647,7 +652,7 @@ module rounding_angled_corner_mask(r=1.0, ang=90, anchor=CENTER, spin=0, orient=
|
|||
dx = r / tan(ang/2);
|
||||
dx2 = dx / cos(ang/2) + 1;
|
||||
fn = quantup(segs(r), 4);
|
||||
orient_and_anchor([2*dx2, 2*dx2, r*2], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, d=dx2, l=2*r) {
|
||||
difference() {
|
||||
down(r) cylinder(r=dx2, h=r+1, center=false);
|
||||
yflip_copy() {
|
||||
|
@ -691,7 +696,7 @@ module rounding_angled_corner_mask(r=1.0, ang=90, anchor=CENTER, spin=0, orient=
|
|||
// }
|
||||
module rounding_corner_mask(r=1.0, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
orient_and_anchor([2*r, 2*r, 2*r], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[2,2,2]*r) {
|
||||
difference() {
|
||||
cube(size=r*2, center=true);
|
||||
grid3d(n=[2,2,2], spacing=r*2-0.05) {
|
||||
|
@ -764,7 +769,7 @@ module rounding_cylinder_mask(r=1.0, rounding=0.25)
|
|||
module rounding_hole_mask(r=undef, d=undef, rounding=0.25, overage=0.1, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
orient_and_anchor([2*(r+rounding), 2*(r+rounding), rounding*2], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, r=r+rounding, l=2*rounding) {
|
||||
rotate_extrude(convexity=4) {
|
||||
difference() {
|
||||
right(r-overage) fwd(rounding) square(rounding+overage, center=false);
|
||||
|
|
|
@ -400,7 +400,7 @@ module screw(
|
|||
anchorpt("countersunk", [0,0,(headlen+screwlen)/2-0.01]),
|
||||
anchorpt("base", [0,0,-headlen/2+screwlen/2])
|
||||
];
|
||||
orient_and_anchor([screwsize, screwsize, headlen+screwlen], orient, anchor, spin=spin, anchors=anchors, geometry="cylinder", chain=true) {
|
||||
attachable(anchor,spin,orient, d=screwsize, l=headlen+screwlen, anchors=anchors) {
|
||||
down(headlen/2-screwlen/2) {
|
||||
down(screwlen/2) {
|
||||
if (pitch == undef) {
|
||||
|
@ -525,7 +525,7 @@ module metric_bolt(
|
|||
];
|
||||
|
||||
//color("silver")
|
||||
orient_and_anchor([size, size, headlen+l], orient, anchor, spin=spin, geometry="cylinder", anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, d=size, l=headlen+l, anchors=anchors) {
|
||||
up(base) {
|
||||
difference() {
|
||||
union() {
|
||||
|
@ -655,8 +655,8 @@ module metric_nut(
|
|||
pitch=undef,
|
||||
details=false,
|
||||
flange=0,
|
||||
center=undef,
|
||||
anchor=CENTER,
|
||||
center,
|
||||
anchor,
|
||||
spin=0,
|
||||
orient=UP
|
||||
) {
|
||||
|
@ -668,7 +668,8 @@ module metric_nut(
|
|||
bevtop = (dcirc - D)/2;
|
||||
|
||||
//color("silver")
|
||||
orient_and_anchor([dcirc+flange, dcirc+flange, H], orient, anchor, spin=spin, center=center, geometry="cylinder", chain=true) {
|
||||
anchor = get_anchor(anchor,center,BOT,CENTER);
|
||||
attachable(anchor,spin,orient, d=dcirc+flange, l=H) {
|
||||
difference() {
|
||||
union() {
|
||||
difference() {
|
||||
|
|
|
@ -133,7 +133,7 @@ module nema11_stepper(h=24, shaft=5, shaft_len=20, anchor=TOP, spin=0, orient=UP
|
|||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
orient_and_anchor([motor_width, motor_width, h], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
union() {
|
||||
difference() {
|
||||
|
@ -198,7 +198,7 @@ module nema14_stepper(h=24, shaft=5, shaft_len=24, anchor=TOP, spin=0, orient=UP
|
|||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
orient_and_anchor([motor_width, motor_width, h], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
union() {
|
||||
difference() {
|
||||
|
@ -263,7 +263,7 @@ module nema17_stepper(h=34, shaft=5, shaft_len=20, anchor=TOP, spin=0, orient=UP
|
|||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
orient_and_anchor([motor_width, motor_width, h], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
union() {
|
||||
difference() {
|
||||
|
@ -348,7 +348,7 @@ module nema23_stepper(h=50, shaft=6.35, shaft_len=25, anchor=TOP, spin=0, orient
|
|||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
orient_and_anchor([motor_width, motor_width, h], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
difference() {
|
||||
union() {
|
||||
|
@ -415,7 +415,7 @@ module nema34_stepper(h=75, shaft=12.7, shaft_len=32, anchor=TOP, spin=0, orient
|
|||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
orient_and_anchor([motor_width, motor_width, h], orient, anchor, spin=spin, anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
difference() {
|
||||
union() {
|
||||
|
@ -481,7 +481,8 @@ module nema_mount_holes(size=17, depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
|||
];
|
||||
screwfn = quantup(max(8,segs(screw_size/2)),4);
|
||||
plinthfn = quantup(max(8,segs(plinth_diam/2)),4);
|
||||
orient_and_anchor([screw_spacing+screw_size, screw_spacing+screw_size+l, depth], orient, anchor, spin=spin, chain=true) {
|
||||
s = [screw_spacing+screw_size, screw_spacing+screw_size+l, depth];
|
||||
attachable(anchor,spin,orient, size=s, anchors=anchors) {
|
||||
union() {
|
||||
xspread(screw_spacing) {
|
||||
yspread(screw_spacing) {
|
||||
|
|
|
@ -651,9 +651,10 @@ module extrude_from_to(pt1, pt2, convexity=undef, twist=undef, scale=undef, slic
|
|||
// Example:
|
||||
// poly = [[-10,0], [-3,-5], [3,-5], [10,0], [0,-30]];
|
||||
// spiral_sweep(poly, h=200, r=50, twist=1080, $fn=36);
|
||||
module spiral_sweep(polyline, h, r, twist=360, center=undef, anchor=BOTTOM, spin=0, orient=UP) {
|
||||
module spiral_sweep(polyline, h, r, twist=360, center, anchor, spin=0, orient=UP) {
|
||||
pline_count = len(polyline);
|
||||
steps = ceil(segs(r)*(twist/360));
|
||||
anchor = get_anchor(anchor,center,BOT,BOT);
|
||||
|
||||
poly_points = [
|
||||
for (
|
||||
|
@ -693,7 +694,7 @@ module spiral_sweep(polyline, h, r, twist=360, center=undef, anchor=BOTTOM, spin
|
|||
);
|
||||
|
||||
tri_faces = triangulate_faces(poly_points, poly_faces);
|
||||
orient_and_anchor([r,r,h], orient, anchor, spin=spin, center=center, geometry="cylinder", chain=true) {
|
||||
attachable(anchor,spin,orient, r=r, l=h) {
|
||||
polyhedron(points=poly_points, faces=tri_faces, convexity=10);
|
||||
children();
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ module phillips_drive(size="#2", shaft=6, l=20, $fn=36, anchor=BOTTOM, spin=0, o
|
|||
p0 = [0,0];
|
||||
p1 = [e/2, adj_ang_to_opp(e/2, 90-alpha/2)];
|
||||
p2 = p1 + [(shaft-e)/2, adj_ang_to_hyp((shaft-e)/2, 90-gamma/2)];
|
||||
orient_and_anchor([shaft,shaft,l], anchor=anchor, spin=spin, orient=orient, geometry="cylinder", chain=true) {
|
||||
attachable(anchor,spin,orient, d=shaft, l=l) {
|
||||
down(l/2) {
|
||||
difference() {
|
||||
union() {
|
||||
|
|
|
@ -43,24 +43,36 @@
|
|||
// path = square([40,30], chamfer=5, anchor=FRONT, spin=30);
|
||||
// stroke(path, closed=true);
|
||||
// place_copies(path) color("blue") circle(d=2,$fn=8);
|
||||
module square(size=1, rounding=0, chamfer=0, center, anchor=FRONT+LEFT, spin=0) {
|
||||
module square(size=1, rounding=0, chamfer=0, center, anchor, spin=0) {
|
||||
size = is_num(size)? [size,size] : point2d(size);
|
||||
pts = square(size=size, rounding=rounding, center=false, chamfer=chamfer);
|
||||
orient_and_anchor(point3d(size), UP, anchor, spin=spin, center=center, noncentered=FRONT+LEFT, two_d=true, chain=true) {
|
||||
anchor = get_anchor(anchor, center, FRONT+LEFT, FRONT+LEFT);
|
||||
pts = square(size=size, rounding=rounding, chamfer=chamfer, center=false);
|
||||
attachable(anchor,spin, two_d=true, size=size) {
|
||||
translate(-size/2) polygon(pts);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function square(size=1, rounding=0, chamfer=0, center, anchor=FRONT+LEFT, spin=0) =
|
||||
function square(size=1, rounding=0, chamfer=0, center, anchor, spin=0) =
|
||||
assert(is_num(size) || is_vector(size))
|
||||
assert(is_num(chamfer) || len(chamfer)==4)
|
||||
assert(is_num(rounding) || len(rounding)==4)
|
||||
let(
|
||||
size = is_num(size)? [size,size] : point2d(size),
|
||||
anchor = get_anchor(anchor, center, FRONT+LEFT, FRONT+LEFT)
|
||||
)
|
||||
(rounding==0 && chamfer==0)? let(
|
||||
path = [
|
||||
[ size.x/2, -size.y/2],
|
||||
[-size.x/2, -size.y/2],
|
||||
[-size.x/2, size.y/2],
|
||||
[ size.x/2, size.y/2]
|
||||
]
|
||||
) rot(spin, p=move(-vmul(anchor,size/2), p=path)) :
|
||||
let(
|
||||
chamfer = is_list(chamfer)? chamfer : [for (i=[0:3]) chamfer],
|
||||
rounding = is_list(rounding)? rounding : [for (i=[0:3]) rounding],
|
||||
anchor = center==true? CENTER : center==false? FRONT+LEFT : anchor,
|
||||
size = is_num(size)? [size,size] : point2d(size),
|
||||
quadorder = [3,2,1,0],
|
||||
quadpos = [[1,1],[-1,1],[-1,-1],[1,-1]],
|
||||
insets = [for (i=[0:3]) chamfer[i]>0? chamfer[i] : rounding[i]>0? rounding[i] : 0],
|
||||
|
@ -116,7 +128,7 @@ module circle(r, d, realign=false, circum=false, anchor=CENTER, spin=0) {
|
|||
sides = segs(r);
|
||||
rr = circum? r/cos(180/sides) : r;
|
||||
pts = circle(r=rr, realign=realign, $fn=sides);
|
||||
orient_and_anchor([2*rr,2*rr,0], UP, anchor, spin=spin, geometry="cylinder", two_d=true, chain=true) {
|
||||
attachable(anchor,spin, two_d=true, r=rr) {
|
||||
polygon(pts);
|
||||
children();
|
||||
}
|
||||
|
@ -162,10 +174,11 @@ function circle(r, d, realign=false, circum=false, anchor=CENTER, spin=0) =
|
|||
// cube([20,40,50], anchor=BOTTOM+FRONT, spin=30, orient=FWD);
|
||||
// Example: Standard Connectors.
|
||||
// cube(40, center=true) show_anchors();
|
||||
module cube(size=1, center, anchor=ALLNEG, spin=0, orient=UP)
|
||||
module cube(size=1, center, anchor, spin=0, orient=UP)
|
||||
{
|
||||
size = scalar_vec3(size);
|
||||
orient_and_anchor(size, orient, anchor, center, spin=spin, noncentered=ALLNEG, chain=true) {
|
||||
anchor = get_anchor(anchor, center, ALLNEG, ALLNEG);
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
linear_extrude(height=size.z, convexity=2, center=true) {
|
||||
square([size.x, size.y], center=true);
|
||||
}
|
||||
|
@ -214,8 +227,9 @@ module cube(size=1, center, anchor=ALLNEG, spin=0, orient=UP)
|
|||
// cylinder(h=30, d=25) show_anchors();
|
||||
// cylinder(h=30, d1=25, d2=10) show_anchors();
|
||||
// }
|
||||
module cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor=BOTTOM, spin=0, orient=UP)
|
||||
module cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP)
|
||||
{
|
||||
anchor = get_anchor(anchor, center, BOTTOM, BOTTOM);
|
||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
|
||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
|
||||
l = first_defined([h, l, 1]);
|
||||
|
@ -223,7 +237,7 @@ module cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor=BOTTOM, spin=0, orien
|
|||
sides = segs(max(r1,r2));
|
||||
size = [r1*2, r1*2, l];
|
||||
path = [[0,hh],[r2,hh],[r1,-hh],[0,-hh]];
|
||||
orient_and_anchor(size, orient, anchor, center, spin=spin, size2=[r2*2,r2*2], noncentered=BOTTOM, geometry="cylinder", chain=true) {
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
rotate_extrude(convexity=2, $fn=sides) {
|
||||
polygon(path);
|
||||
}
|
||||
|
@ -262,7 +276,7 @@ module sphere(r, d, anchor=CENTER, spin=0, orient=UP)
|
|||
r = get_radius(r=r, d=d, dflt=1);
|
||||
sides = segs(r);
|
||||
size = [r*2, r*2, r*2];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, geometry="sphere", chain=true) {
|
||||
attachable(anchor,spin,orient, r=r) {
|
||||
rotate_extrude(convexity=2) {
|
||||
difference() {
|
||||
circle(r=r, $fn=sides);
|
||||
|
|
71
shapes.scad
71
shapes.scad
|
@ -97,7 +97,7 @@ module cuboid(
|
|||
if (any(edges[2])) assert(rounding <= size.x/2 && rounding<=size.y/2, "rounding radius must be smaller than half the cube width or length.");
|
||||
}
|
||||
majrots = [[0,90,0], [90,0,0], [0,0,0]];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
if (chamfer != undef) {
|
||||
if (edges == EDGES_ALL && trimcorners) {
|
||||
if (chamfer<0) {
|
||||
|
@ -349,7 +349,7 @@ module prismoid(
|
|||
shiftby = point3d(point2d(shift));
|
||||
s1 = [max(size1.x, eps), max(size1.y, eps)];
|
||||
s2 = [max(size2.x, eps), max(size2.y, eps)];
|
||||
orient_and_anchor([s1.x,s1.y,h], orient, anchor, spin=spin, size2=s2, shift=shift, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[s1.x,s1.y,h], size2=s2, shift=shift) {
|
||||
polyhedron(
|
||||
points=[
|
||||
[+s2.x/2, +s2.y/2, +h/2] + shiftby,
|
||||
|
@ -419,16 +419,16 @@ module rounded_prismoid(
|
|||
rr1 = min(maxrad1, (r1!=undef)? r1 : r);
|
||||
rr2 = min(maxrad2, (r2!=undef)? r2 : r);
|
||||
shiftby = point3d(shift);
|
||||
orient_and_anchor([size1.x, size1.y, h], orient, anchor, spin=spin, size2=size2, shift=shift, noncentered=UP, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[size1.x, size1.y, h], size2=size2, shift=shift) {
|
||||
down(h/2) {
|
||||
hull() {
|
||||
linear_extrude(height=eps, center=false, convexity=2) {
|
||||
square([max(eps, size1[0]-2*rr1), max(eps, size1[1]-2*rr1)], rounding=rr1, center=true);
|
||||
square(size1, rounding=rr1, center=true);
|
||||
}
|
||||
up(h-0.01) {
|
||||
translate(shiftby) {
|
||||
linear_extrude(height=eps, center=false, convexity=2) {
|
||||
square([max(eps, size2[0]-2*rr2), max(eps, size2[1]-2*rr2)], rounding=rr2, center=true);
|
||||
square(size2, rounding=rr2, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -460,10 +460,11 @@ module rounded_prismoid(
|
|||
// right_triangle([60, 40, 10]);
|
||||
// Example: Standard Connectors
|
||||
// right_triangle([60, 40, 15]) show_anchors();
|
||||
module right_triangle(size=[1, 1, 1], anchor=ALLNEG, spin=0, orient=UP, center=undef)
|
||||
module right_triangle(size=[1, 1, 1], center, anchor, spin=0, orient=UP)
|
||||
{
|
||||
size = scalar_vec3(size);
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, center=center, noncentered=ALLNEG, chain=true) {
|
||||
anchor = get_anchor(anchor, center, ALLNEG, ALLNEG);
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
linear_extrude(height=size.z, convexity=2, center=true) {
|
||||
polygon([[-size.x/2,-size.y/2], [-size.x/2,size.y/2], [size.x/2,-size.y/2]]);
|
||||
}
|
||||
|
@ -581,17 +582,16 @@ module cyl(
|
|||
chamfang=undef, chamfang1=undef, chamfang2=undef,
|
||||
rounding=undef, rounding1=undef, rounding2=undef,
|
||||
circum=false, realign=false, from_end=false,
|
||||
anchor=CENTER, spin=0, orient=UP, center=undef
|
||||
center, anchor, spin=0, orient=UP
|
||||
) {
|
||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
|
||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
|
||||
l = first_defined([l, h, 1]);
|
||||
size1 = [r1*2,r1*2,l];
|
||||
size2 = [r2*2,r2*2,l];
|
||||
sides = segs(max(r1,r2));
|
||||
sc = circum? 1/cos(180/sides) : 1;
|
||||
phi = atan2(l, r2-r1);
|
||||
orient_and_anchor(size1, orient, anchor, spin=spin, center=center, size2=size2, geometry="cylinder", chain=true) {
|
||||
anchor = get_anchor(anchor,center,BOT,CENTER);
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
zrot(realign? 180/sides : 0) {
|
||||
if (!any_defined([chamfer, chamfer1, chamfer2, rounding, rounding1, rounding2])) {
|
||||
cylinder(h=l, r1=r1*sc, r2=r2*sc, center=true, $fn=sides);
|
||||
|
@ -850,8 +850,8 @@ module tube(
|
|||
od=undef, od1=undef, od2=undef,
|
||||
ir=undef, id=undef, ir1=undef,
|
||||
ir2=undef, id1=undef, id2=undef,
|
||||
anchor=BOTTOM, spin=0, orient=UP,
|
||||
center=undef, realign=false
|
||||
anchor, spin=0, orient=UP,
|
||||
center, realign=false
|
||||
) {
|
||||
r1 = first_defined([or1, od1/2, r1, d1/2, or, od/2, r, d/2, ir1+wall, id1/2+wall, ir+wall, id/2+wall]);
|
||||
r2 = first_defined([or2, od2/2, r2, d2/2, or, od/2, r, d/2, ir2+wall, id2/2+wall, ir+wall, id/2+wall]);
|
||||
|
@ -860,9 +860,8 @@ module tube(
|
|||
assert(ir1 <= r1, "Inner radius is larger than outer radius.");
|
||||
assert(ir2 <= r2, "Inner radius is larger than outer radius.");
|
||||
sides = segs(max(r1,r2));
|
||||
size = [r1*2,r1*2,h];
|
||||
size2 = [r2*2,r2*2,h];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, center=center, size2=size2, geometry="cylinder", chain=true) {
|
||||
anchor = get_anchor(anchor, center, BOT, BOT);
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2) {
|
||||
zrot(realign? 180/sides : 0) {
|
||||
difference() {
|
||||
cyl(h=h, r1=r1, r2=r2, $fn=sides) children();
|
||||
|
@ -908,15 +907,14 @@ module torus(
|
|||
r2=undef, d2=undef,
|
||||
or=undef, od=undef,
|
||||
ir=undef, id=undef,
|
||||
anchor=CENTER, center=undef,
|
||||
spin=0, orient=UP
|
||||
center, anchor, spin=0, orient=UP
|
||||
) {
|
||||
orr = get_radius(r=or, d=od, dflt=1.0);
|
||||
irr = get_radius(r=ir, d=id, dflt=0.5);
|
||||
majrad = get_radius(r=r, d=d, dflt=(orr+irr)/2);
|
||||
minrad = get_radius(r=r2, d=d2, dflt=(orr-irr)/2);
|
||||
size = [(majrad+minrad)*2, (majrad+minrad)*2, minrad*2];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, center=center, geometry="cylinder", chain=true) {
|
||||
anchor = get_anchor(anchor, center, BOT, CENTER);
|
||||
attachable(anchor,spin,orient, r=(majrad+minrad), l=minrad*2) {
|
||||
rotate_extrude(convexity=4) {
|
||||
right(majrad) circle(minrad);
|
||||
}
|
||||
|
@ -953,8 +951,7 @@ module spheroid(r=undef, d=undef, circum=false, anchor=CENTER, spin=0, orient=UP
|
|||
hsides = segs(r);
|
||||
vsides = ceil(hsides/2);
|
||||
rr = circum? (r / cos(90/vsides) / cos(180/hsides)) : r;
|
||||
size = [2*rr, 2*rr, 2*rr];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, geometry="sphere", chain=true) {
|
||||
attachable(anchor,spin,orient, r=rr) {
|
||||
sphere(r=rr);
|
||||
children();
|
||||
}
|
||||
|
@ -1020,8 +1017,7 @@ module staggered_sphere(r=undef, d=undef, circum=false, anchor=CENTER, spin=0, o
|
|||
) each [[v1,v4,v3], [v1,v2,v4]]
|
||||
]
|
||||
);
|
||||
size = [2*rr, 2*rr, 2*rr];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, geometry="sphere", chain=true) {
|
||||
attachable(anchor,spin,orient, r=rr) {
|
||||
zrot((floor(sides/4)%2==1)? 180/sides : 0) polyhedron(points=pts, faces=faces);
|
||||
children();
|
||||
}
|
||||
|
@ -1061,10 +1057,11 @@ module teardrop(r=undef, d=undef, l=undef, h=undef, ang=45, cap_h=undef, anchor=
|
|||
r = get_radius(r=r, d=d, dflt=1);
|
||||
l = first_defined([l, h, 1]);
|
||||
size = [r*2,l,r*2];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, chain=true) {
|
||||
rot(from=UP,to=FWD)
|
||||
linear_extrude(height=l, center=true, slices=2) {
|
||||
teardrop2d(r=r, ang=ang, cap_h=cap_h);
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
rot(from=UP,to=FWD) {
|
||||
linear_extrude(height=l, center=true, slices=2) {
|
||||
teardrop2d(r=r, ang=ang, cap_h=cap_h);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
|
@ -1101,11 +1098,10 @@ module onion(cap_h=undef, r=undef, d=undef, maxang=45, h=undef, anchor=CENTER, s
|
|||
r = get_radius(r=r, d=d, dflt=1);
|
||||
h = first_defined([cap_h, h]);
|
||||
maxd = 3*r/tan(maxang);
|
||||
size = [r*2,r*2,r*2];
|
||||
anchors = [
|
||||
["cap", [0,0,h], UP, 0]
|
||||
];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, geometry="sphere", anchors=anchors, chain=true) {
|
||||
attachable(anchor,spin,orient, r=r, anchors=anchors) {
|
||||
rotate_extrude(convexity=2) {
|
||||
difference() {
|
||||
teardrop2d(r=r, ang=maxang, cap_h=h);
|
||||
|
@ -1137,7 +1133,7 @@ module nil() union(){}
|
|||
// Arguments:
|
||||
// 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`
|
||||
module noop(spin=0, orient=UP) orient_and_anchor([0.01,0.01,0.01], orient, CENTER, spin=spin, chain=true) {nil(); children();}
|
||||
module noop(spin=0, orient=UP) attachable(CENTER,spin,orient, d=0.01) {nil(); children();}
|
||||
|
||||
|
||||
// Module: pie_slice()
|
||||
|
@ -1171,15 +1167,15 @@ module pie_slice(
|
|||
ang=30, l=undef,
|
||||
r=10, r1=undef, r2=undef,
|
||||
d=undef, d1=undef, d2=undef,
|
||||
anchor=BOTTOM, spin=0, orient=UP,
|
||||
center=undef, h=undef
|
||||
h=undef, center,
|
||||
anchor, spin=0, orient=UP
|
||||
) {
|
||||
l = first_defined([l, h, 1]);
|
||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=10);
|
||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=10);
|
||||
maxd = max(r1,r2)+0.1;
|
||||
size = [2*r1, 2*r1, l];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, center=center, geometry="cylinder", chain=true) {
|
||||
anchor = get_anchor(anchor, center, BOT, BOT);
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
difference() {
|
||||
cylinder(r1=r1, r2=r2, h=l, center=true);
|
||||
if (ang<180) rotate(ang) back(maxd/2) cube([2*maxd, maxd, l+0.1], center=true);
|
||||
|
@ -1232,7 +1228,7 @@ module interior_fillet(l=1.0, r=1.0, ang=90, overlap=0.01, anchor=FRONT+LEFT, sp
|
|||
dy = r/tan(ang/2);
|
||||
steps = ceil(segs(r)*ang/360);
|
||||
step = ang/steps;
|
||||
orient_and_anchor([r,r,l], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[r,r,l]) {
|
||||
linear_extrude(height=l, convexity=4, center=true) {
|
||||
path = concat(
|
||||
[[0,0]],
|
||||
|
@ -1330,8 +1326,7 @@ module arced_slot(
|
|||
sr2 = get_radius(r1=sr2, r=sr, d1=sd2, d=sd, dflt=2);
|
||||
fn_minor = first_defined([$fn2, $fn]);
|
||||
da = ea - sa;
|
||||
size = [r+sr1, r+sr1, h];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, geometry="cylinder", chain=true) {
|
||||
attachable(anchor,spin,orient, r1=r+sr1, r2=r+sr2) {
|
||||
translate(cp) {
|
||||
zrot(sa) {
|
||||
difference() {
|
||||
|
|
|
@ -628,8 +628,9 @@ function regular_ngon(n=6, r, d, or, od, ir, id, side, rounding=0, realign=false
|
|||
module regular_ngon(n=6, r, d, or, od, ir, id, side, rounding=0, realign=false, anchor=CENTER, spin=0) {
|
||||
sc = 1/cos(180/n);
|
||||
r = get_radius(r1=ir*sc, r2=or, r=r, d1=id*sc, d2=od, d=d, dflt=side/2/sin(180/n));
|
||||
orient_and_anchor([2*r,2*r,0], UP, anchor, spin=spin, geometry="cylinder", two_d=true, chain=true) {
|
||||
polygon(regular_ngon(n=n, r=r, rounding=rounding, realign=realign));
|
||||
path = regular_ngon(n=n, r=r, rounding=rounding, realign=realign);
|
||||
attachable(anchor,spin, two_d=true, path=path) {
|
||||
polygon(path);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
@ -788,8 +789,9 @@ function trapezoid(h, w1, w2, anchor=CENTER, spin=0) =
|
|||
|
||||
|
||||
module trapezoid(h, w1, w2, anchor=CENTER, spin=0) {
|
||||
orient_and_anchor([w1,h,0], size2=[w2,h], UP, anchor, spin=spin, two_d=true, chain=true) {
|
||||
polygon(trapezoid(h=h, w1=w1, w2=w2));
|
||||
path = trapezoid(h=h, w1=w1, w2=w2);
|
||||
attachable(anchor,spin, two_d=true, size=[w1,h], size2=w2) {
|
||||
polygon(path);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
@ -819,8 +821,11 @@ module trapezoid(h, w1, w2, anchor=CENTER, spin=0) {
|
|||
// teardrop2d(r=30, ang=30, cap_h=20);
|
||||
module teardrop2d(r, d, ang=45, cap_h, anchor=CENTER, spin=0)
|
||||
{
|
||||
path = teardrop2d(r=r, d=d, ang=ang, cap_h=cap_h, anchor=anchor, spin=spin);
|
||||
polygon(path);
|
||||
path = teardrop2d(r=r, d=d, ang=ang, cap_h=cap_h);
|
||||
attachable(anchor,spin, two_d=true, path=path) {
|
||||
polygon(path);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -892,8 +897,13 @@ function glued_circles(r, d, spread=10, tangent=30, anchor=CENTER, spin=0) =
|
|||
) rot(spin, p=move(-vmul(anchor,s), p=path));
|
||||
|
||||
|
||||
module glued_circles(r, d, spread=10, tangent=30, anchor=CENTER, spin=0)
|
||||
polygon(glued_circles(r=r, d=d, spread=spread, tangent=tangent, anchor=anchor, spin=spin));
|
||||
module glued_circles(r, d, spread=10, tangent=30, anchor=CENTER, spin=0) {
|
||||
path = glued_circles(r=r, d=d, spread=spread, tangent=tangent);
|
||||
attachable(anchor,spin, two_d=true, path=path, extent=true) {
|
||||
polygon(path);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Function&Module: star()
|
||||
|
@ -940,8 +950,13 @@ function star(n, r, d, or, od, ir, id, step, realign=false, anchor=CENTER, spin=
|
|||
) rot(spin, p=move(-r*normalize(anchor), p=path));
|
||||
|
||||
|
||||
module star(n, r, d, or, od, ir, id, step, realign=false, anchor=CENTER, spin=0)
|
||||
polygon(star(n=n, r=r, d=d, od=od, or=or, ir=ir, id=id, step=step, realign=realign, anchor=anchor, spin=spin));
|
||||
module star(n, r, d, or, od, ir, id, step, realign=false, anchor=CENTER, spin=0) {
|
||||
path = star(n=n, r=r, d=d, od=od, or=or, ir=ir, id=id, step=step, realign=realign);
|
||||
attachable(anchor,spin, two_d=true, path=path, extent=true) {
|
||||
polygon(path);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
||||
|
@ -1006,8 +1021,13 @@ function supershape(step=0.5,m1=4,m2=undef,n1=1,n2=undef,n3=undef,a=1,b=undef,r=
|
|||
path = [for (i = [0:steps-1]) let(a=angs[i]) scale*rads[i]*[cos(a), sin(a)]]
|
||||
) rot(spin, p=move(-scale*max(rads)*normalize(anchor), p=path));
|
||||
|
||||
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)
|
||||
polygon(supershape(step=step,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b, r=r,d=d, anchor=anchor, spin=spin));
|
||||
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);
|
||||
attachable(anchor,spin, two_d=true, path=path, extent=true) {
|
||||
polygon(path);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Section: 2D Masking Shapes
|
||||
|
|
|
@ -35,7 +35,7 @@ module slider(l=30, w=10, h=10, base=10, wall=5, ang=30, anchor=BOTTOM, spin=0,
|
|||
full_width = w + 2*wall;
|
||||
full_height = h + base;
|
||||
|
||||
orient_and_anchor([full_width, l, h+2*base], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[full_width, l, h+2*base]) {
|
||||
zrot(90)
|
||||
down(base+h/2) {
|
||||
// Base
|
||||
|
@ -102,7 +102,7 @@ module rail(l=30, w=10, h=10, chamfer=1.0, ang=30, anchor=BOTTOM, spin=0, orient
|
|||
y1 = l/2;
|
||||
y2 = y1 - attack_len * cos(attack_ang);
|
||||
|
||||
orient_and_anchor([w, l, h], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[w, l, h]) {
|
||||
polyhedron(
|
||||
convexity=4,
|
||||
points=[
|
||||
|
|
|
@ -63,7 +63,7 @@ module thread_helix(base_d, pitch, thread_depth=undef, thread_angle=15, twist=72
|
|||
pline = scale_points(profile, [1,1,1]*pitch);
|
||||
dir = left_handed? -1 : 1;
|
||||
idir = internal? -1 : 1;
|
||||
orient_and_anchor([2*r, 2*r, h], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, r=r, l=h) {
|
||||
difference() {
|
||||
spiral_sweep(pline, h=h, r=base_d/2, twist=twist*dir, $fn=segs(base_d/2), anchor=CENTER);
|
||||
down(h/2) right(r) right(internal? thread_depth : 0) zrot(higbee*dir*idir) fwd(dir*pitch/2) cube([3*thread_depth/cos(higbee), pitch, pitch], center=true);
|
||||
|
@ -137,10 +137,7 @@ module trapezoidal_threaded_rod(
|
|||
starts=1,
|
||||
profile=undef,
|
||||
internal=false,
|
||||
anchor=CENTER,
|
||||
spin=0,
|
||||
orient=UP,
|
||||
center=undef
|
||||
center, anchor, spin=0, orient=UP
|
||||
) {
|
||||
function _thread_pt(thread, threads, start, starts, astep, asteps, part, parts) =
|
||||
astep + asteps * (thread + threads * (part + parts * start));
|
||||
|
@ -277,7 +274,8 @@ module trapezoidal_threaded_rod(
|
|||
) otri
|
||||
]
|
||||
);
|
||||
orient_and_anchor([d,d,l], orient, anchor, spin=spin, center=center, chain=true) {
|
||||
anchor = get_anchor(anchor, center, BOT, CENTER);
|
||||
attachable(anchor,spin,orient, d=d, l=l) {
|
||||
difference() {
|
||||
polyhedron(points=poly_points, faces=poly_faces, convexity=threads*starts*2);
|
||||
zspread(l+4*pitch*starts) cube([d+1, d+1, 4*pitch*starts], center=true);
|
||||
|
@ -332,7 +330,7 @@ module trapezoidal_threaded_nut(
|
|||
orient=UP
|
||||
) {
|
||||
depth = min((thread_depth==undef? pitch/2 : thread_depth), pitch/2/tan(thread_angle));
|
||||
orient_and_anchor([od/cos(30),od,h], orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=[od/cos(30),od,h]) {
|
||||
difference() {
|
||||
cylinder(d=od/cos(30), h=h, center=true, $fn=6);
|
||||
trapezoidal_threaded_rod(
|
||||
|
|
|
@ -184,9 +184,10 @@ module torx_drive2d(size) {
|
|||
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
|
||||
// Examples:
|
||||
// torx_drive(size=30, l=10, $fa=1, $fs=1);
|
||||
module torx_drive(size, l=5, center=undef, anchor=BOTTOM, spin=0, orient=UP) {
|
||||
module torx_drive(size, l=5, center, anchor, spin=0, orient=UP) {
|
||||
anchor = get_anchor(anchor, center, BOT, BOT);
|
||||
od = torx_outer_diam(size);
|
||||
orient_and_anchor([od, od, l], orient, anchor, spin=spin, center=center, chain=true) {
|
||||
attachable(anchor,spin,orient, d=od, l=l) {
|
||||
linear_extrude(height=l, convexity=4, center=true) {
|
||||
torx_drive2d(size);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BOSL_VERSION = [2,0,136];
|
||||
BOSL_VERSION = [2,0,137];
|
||||
|
||||
|
||||
// Section: BOSL Library Version Functions
|
||||
|
|
15
walls.scad
15
walls.scad
|
@ -38,7 +38,7 @@ module narrowing_strut(w=10, l=100, wall=5, ang=30, anchor=BOTTOM, spin=0, orien
|
|||
{
|
||||
h = wall + w/2/tan(ang);
|
||||
size = [w, l, h];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
xrot(90)
|
||||
fwd(h/2) {
|
||||
linear_extrude(height=l, center=true, slices=2) {
|
||||
|
@ -115,7 +115,7 @@ module thinning_wall(h=50, l=100, thick=5, ang=30, braces=false, strut=5, wall=2
|
|||
brace_len = norm(corner1-corner2);
|
||||
|
||||
size = [l1, thick, h];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, size2=[l2,thick], chain=true) {
|
||||
attachable(anchor,spin,orient, size=size, size2=[l2,thick]) {
|
||||
union() {
|
||||
polyhedron(
|
||||
points=[
|
||||
|
@ -262,12 +262,13 @@ module thinning_wall(h=50, l=100, thick=5, ang=30, braces=false, strut=5, wall=2
|
|||
// thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, center=false);
|
||||
// Example: Diagonal Brace Only
|
||||
// thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, diagonly=true, center=false);
|
||||
module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly=false, center=undef, anchor=CENTER, spin=0, orient=UP)
|
||||
module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly=false, center, anchor, spin=0, orient=UP)
|
||||
{
|
||||
dang = atan(h/l);
|
||||
dlen = h/sin(dang);
|
||||
size = [thick, l, h];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, center=center, noncentered=BOTTOM+FRONT, chain=true) {
|
||||
anchor = get_anchor(anchor, center, BOT+FRONT, CENTER);
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
difference() {
|
||||
union() {
|
||||
if (!diagonly) {
|
||||
|
@ -344,7 +345,7 @@ module sparse_strut(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, anc
|
|||
len = zstep / cos(ang);
|
||||
|
||||
size = [thick, l, h];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
yrot(90)
|
||||
linear_extrude(height=thick, convexity=4*yreps, center=true) {
|
||||
difference() {
|
||||
|
@ -415,7 +416,7 @@ module sparse_strut3d(h=50, l=100, w=50, thick=3, maxang=40, strut=3, max_bridge
|
|||
supp_step = cross_len/2/supp_reps;
|
||||
|
||||
size = [w, l, h];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
intersection() {
|
||||
union() {
|
||||
ybridge = (l - (yreps+1) * strut) / yreps;
|
||||
|
@ -495,7 +496,7 @@ module corrugated_wall(h=50, l=100, thick=5, strut=5, wall=2, anchor=CENTER, spi
|
|||
step = period/steps;
|
||||
il = l - 2*strut + 2*step;
|
||||
size = [thick, l, h];
|
||||
orient_and_anchor(size, orient, anchor, spin=spin, chain=true) {
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
union() {
|
||||
linear_extrude(height=h-2*strut+0.1, slices=2, convexity=ceil(2*il/period), center=true) {
|
||||
polygon(
|
||||
|
|
Loading…
Reference in a new issue