mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
add attachable to bottlecaps & mutators
This commit is contained in:
parent
25aef90fc7
commit
1bee8c96f9
3 changed files with 418 additions and 352 deletions
401
bottlecaps.scad
401
bottlecaps.scad
|
@ -443,15 +443,17 @@ module generic_bottle_neck(
|
||||||
diamMagMult = neck_d / 26.19;
|
diamMagMult = neck_d / 26.19;
|
||||||
heightMagMult = height / 17.00;
|
heightMagMult = height / 17.00;
|
||||||
|
|
||||||
|
assert(all_nonnegative([support_d]),"support_d must be a nonnegative number");
|
||||||
sup_r = 0.30 * (heightMagMult > 1 ? heightMagMult : 1);
|
sup_r = 0.30 * (heightMagMult > 1 ? heightMagMult : 1);
|
||||||
support_r = floor(((supp_d == neck_d) ? sup_r : min(sup_r, (supp_d - neck_d) / 2)) * 5000) / 10000;
|
support_r = floor(((supp_d == neck_d) ? sup_r : min(sup_r, (supp_d - neck_d) / 2)) * 5000) / 10000;
|
||||||
support_rad = (wall == undef || !round_supp) ? support_r :
|
support_rad = (wall == undef || !round_supp) ? support_r :
|
||||||
min(support_r, floor((supp_d - (inner_d + 2 * wall)) * 5000) / 10000);
|
min(support_r, floor((supp_d - (inner_d + 2 * wall)) * 5000) / 10000);
|
||||||
//Too small of a radius will cause errors with the arc, this limits granularity to .0001mm
|
//Too small of a radius will cause errors with the arc, this limits granularity to .0001mm
|
||||||
support_width = 1 * (heightMagMult > 1 ? heightMagMult : 1) * sign(support_d);
|
support_width = max(heightMagMult,1) * sign(support_d);
|
||||||
roundover = 0.58 * diamMagMult;
|
roundover = 0.58 * diamMagMult;
|
||||||
lip_roundover_r = (roundover > (neck_d - inner_d) / 2) ? 0 : roundover;
|
lip_roundover_r = (roundover > (neck_d - inner_d) / 2) ? 0 : roundover;
|
||||||
h = height + support_width;
|
h = height + support_width;
|
||||||
|
echo(h=h);
|
||||||
threadbase_d = neck_d - 0.8 * diamMagMult;
|
threadbase_d = neck_d - 0.8 * diamMagMult;
|
||||||
|
|
||||||
$fn = segs(33 / 2);
|
$fn = segs(33 / 2);
|
||||||
|
@ -459,7 +461,7 @@ module generic_bottle_neck(
|
||||||
anchors = [
|
anchors = [
|
||||||
named_anchor("support-ring", [0, 0, 0 - h / 2])
|
named_anchor("support-ring", [0, 0, 0 - h / 2])
|
||||||
];
|
];
|
||||||
attachable(anchor, spin, orient, d1 = neck_d, d2 = 0, l = h, anchors = anchors) {
|
attachable(anchor, spin, orient, d = neck_d, l = h, anchors = anchors) {
|
||||||
down(h / 2) {
|
down(h / 2) {
|
||||||
rotate_extrude(convexity = 10) {
|
rotate_extrude(convexity = 10) {
|
||||||
polygon(turtle(
|
polygon(turtle(
|
||||||
|
@ -555,7 +557,7 @@ module generic_bottle_cap(
|
||||||
wall = 2,
|
wall = 2,
|
||||||
texture = "none",
|
texture = "none",
|
||||||
height = 11.2,
|
height = 11.2,
|
||||||
thread_od = 28.58,
|
thread_depth = 2.34,
|
||||||
tolerance = .2,
|
tolerance = .2,
|
||||||
neck_od = 25.5,
|
neck_od = 25.5,
|
||||||
flank_angle = 15,
|
flank_angle = 15,
|
||||||
|
@ -565,11 +567,10 @@ module generic_bottle_cap(
|
||||||
orient = UP
|
orient = UP
|
||||||
) {
|
) {
|
||||||
$fn = segs(33 / 2);
|
$fn = segs(33 / 2);
|
||||||
threadOuterDTol = thread_od + 2 * tolerance;
|
threadOuterDTol = neck_od + 2*(thread_depth - 0.8) + 2 * tolerance; // WTF; Engineered for consistency with old code, but
|
||||||
w = threadOuterDTol + 2 * wall;
|
w = threadOuterDTol + 2 * wall; // no clue why this was chosen
|
||||||
h = height + wall;
|
h = height + wall;
|
||||||
neckOuterDTol = neck_od + 2 * tolerance;
|
neckOuterDTol = neck_od + 2 * tolerance;
|
||||||
threadDepth = (thread_od - neck_od) / 2 + .8;
|
|
||||||
|
|
||||||
diamMagMult = (w > 32.58) ? w / 32.58 : 1;
|
diamMagMult = (w > 32.58) ? w / 32.58 : 1;
|
||||||
heightMagMult = (height > 11.2) ? height / 11.2 : 1;
|
heightMagMult = (height > 11.2) ? height / 11.2 : 1;
|
||||||
|
@ -596,8 +597,8 @@ module generic_bottle_cap(
|
||||||
}
|
}
|
||||||
difference(){
|
difference(){
|
||||||
up(wall + pitch / 2) {
|
up(wall + pitch / 2) {
|
||||||
thread_helix(d = neckOuterDTol, pitch = pitch, thread_depth = threadDepth, flank_angle = flank_angle,
|
thread_helix(d = neckOuterDTol, pitch = pitch, thread_depth = thread_depth, flank_angle = flank_angle,
|
||||||
turns = ((height - pitch) / pitch), lead_in = -threadDepth, internal = true, anchor = BOTTOM);
|
turns = ((height - pitch) / pitch), lead_in = -thread_depth, internal = true, anchor = BOTTOM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,7 +627,7 @@ function generic_bottle_cap(
|
||||||
// texture = The surface texture of the cap. Valid values are "none", "knurled", or "ribbed". Default: "none"
|
// texture = The surface texture of the cap. Valid values are "none", "knurled", or "ribbed". Default: "none"
|
||||||
// cap_wall = Wall thickness of the cap in mm.
|
// cap_wall = Wall thickness of the cap in mm.
|
||||||
// cap_h = Interior height of the cap in mm.
|
// cap_h = Interior height of the cap in mm.
|
||||||
// cap_thread_od = Outer diameter of cap threads in mm.
|
// cap_thread_depth = Cap thread depth. Default: 2.34
|
||||||
// tolerance = Extra space to add to the outer diameter of threads and neck in mm. Applied to radius.
|
// tolerance = Extra space to add to the outer diameter of threads and neck in mm. Applied to radius.
|
||||||
// cap_neck_od = Inner diameter of the cap threads.
|
// cap_neck_od = Inner diameter of the cap threads.
|
||||||
// cap_neck_id = Inner diameter of the hole through the cap.
|
// cap_neck_id = Inner diameter of the hole through the cap.
|
||||||
|
@ -640,6 +641,9 @@ function generic_bottle_cap(
|
||||||
// neck_support_od = Outer diameter of neck support ring. Leave undefined to set equal to OD of cap. Set to 0 for no ring. Default: undef
|
// neck_support_od = Outer diameter of neck support ring. Leave undefined to set equal to OD of cap. Set to 0 for no ring. Default: undef
|
||||||
// d = Distance between bottom of neck and top of cap
|
// d = Distance between bottom of neck and top of cap
|
||||||
// taper_lead_in = Length to leave straight before tapering on tube between neck and cap if exists.
|
// taper_lead_in = Length to leave straight before tapering on tube between neck and cap if exists.
|
||||||
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
||||||
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
||||||
|
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
||||||
// Examples:
|
// Examples:
|
||||||
// bottle_adapter_neck_to_cap();
|
// bottle_adapter_neck_to_cap();
|
||||||
module bottle_adapter_neck_to_cap(
|
module bottle_adapter_neck_to_cap(
|
||||||
|
@ -647,7 +651,7 @@ module bottle_adapter_neck_to_cap(
|
||||||
texture = "none",
|
texture = "none",
|
||||||
cap_wall = 2,
|
cap_wall = 2,
|
||||||
cap_h = 11.2,
|
cap_h = 11.2,
|
||||||
cap_thread_od = 28.58,
|
cap_thread_depth = 2.34,
|
||||||
tolerance = .2,
|
tolerance = .2,
|
||||||
cap_neck_od = 25.5,
|
cap_neck_od = 25.5,
|
||||||
cap_neck_id,
|
cap_neck_id,
|
||||||
|
@ -660,69 +664,79 @@ module bottle_adapter_neck_to_cap(
|
||||||
neck_thread_pitch = 3.2,
|
neck_thread_pitch = 3.2,
|
||||||
neck_support_od,
|
neck_support_od,
|
||||||
d = 0,
|
d = 0,
|
||||||
taper_lead_in = 0
|
taper_lead_in = 0, anchor, spin,orient
|
||||||
) {
|
) {
|
||||||
neck_support_od = (neck_support_od == undef || (d == 0 && neck_support_od < cap_thread_od + 2 * tolerance)) ? cap_thread_od + 2 * (cap_wall + tolerance) : neck_support_od;
|
cap_od = cap_neck_od + 2*(cap_thread_depth - 0.8) + 2 * tolerance;
|
||||||
cap_neck_id = (cap_neck_id == undef) ? neck_id : cap_neck_id;
|
neck_support_od = (neck_support_od == undef || (d == 0 && neck_support_od < cap_od)) ? cap_od+2*cap_wall
|
||||||
wall = (wall == undef) ? neck_support_od + neck_d + cap_thread_od + neck_id : wall;
|
: neck_support_od;
|
||||||
|
cap_neck_id = default(cap_neck_id,neck_id);
|
||||||
|
wall = default(wall, neck_support_od + neck_d + cap_od + neck_id - 2*tolerance);
|
||||||
|
echo(wall=wall);
|
||||||
|
|
||||||
$fn = segs(33 / 2);
|
$fn = segs(33 / 2);
|
||||||
wallt1 = min(wall, (max(neck_support_od, neck_d) - neck_id) / 2);
|
wallt1 = min(wall, (max(neck_support_od, neck_d) - neck_id) / 2);
|
||||||
wallt2 = min(wall, (cap_thread_od + 2 * (cap_wall + tolerance) - cap_neck_id) / 2);
|
wallt2 = min(wall, (cap_od + 2 * cap_wall - cap_neck_id) / 2);
|
||||||
|
|
||||||
difference(){
|
top_h = neck_h + max(1,neck_h/17)*sign(neck_support_od);
|
||||||
union(){
|
echo(top_h=top_h);
|
||||||
up(d / 2) {
|
bot_h = cap_h + cap_wall;
|
||||||
generic_bottle_neck(neck_d = neck_d,
|
attachable(anchor=anchor,orient=orient,spin=spin, r=max([neck_id/2+wallt1, cap_neck_id/2+wallt2, neck_support_od/2]), h=top_h+bot_h+d) {
|
||||||
id = neck_id,
|
zmove((bot_h-top_h)/2)
|
||||||
thread_od = neck_thread_od,
|
difference(){
|
||||||
height = neck_h,
|
union(){
|
||||||
support_d = neck_support_od,
|
up(d / 2) {
|
||||||
pitch = neck_thread_pitch,
|
generic_bottle_neck(neck_d = neck_d,
|
||||||
round_supp = ((wallt1 < (neck_support_od - neck_id) / 2) && (d > 0 || neck_support_od > (cap_thread_od + 2 * (cap_wall + tolerance)))),
|
id = neck_id,
|
||||||
wall = (d > 0) ? wallt1 : min(wallt1, ((cap_thread_od + 2 * (cap_wall + tolerance) - neck_id) / 2))
|
thread_od = neck_thread_od,
|
||||||
);
|
height = neck_h,
|
||||||
}
|
support_d = neck_support_od,
|
||||||
if (d != 0) {
|
pitch = neck_thread_pitch,
|
||||||
rotate_extrude(){
|
round_supp = ((wallt1 < (neck_support_od - neck_id) / 2) && (d > 0 || neck_support_od > (cap_thread_od + 2 * (cap_wall + tolerance)))),
|
||||||
polygon(points = [
|
wall = (d > 0) ? wallt1 : min(wallt1, ((cap_od + 2 * (cap_wall) - neck_id) / 2))
|
||||||
[0, d / 2],
|
);
|
||||||
[neck_id / 2 + wallt1, d / 2],
|
}
|
||||||
[neck_id / 2 + wallt1, d / 2 - taper_lead_in],
|
if (d != 0) {
|
||||||
[cap_neck_id / 2 + wallt2, taper_lead_in - d / 2],
|
rotate_extrude(){
|
||||||
[cap_neck_id / 2 + wallt2, -d / 2],
|
polygon(points = [
|
||||||
[0, -d / 2]
|
[0, d / 2],
|
||||||
]);
|
[neck_id / 2 + wallt1, d / 2],
|
||||||
|
[neck_id / 2 + wallt1, d / 2 - taper_lead_in],
|
||||||
|
[cap_neck_id / 2 + wallt2, taper_lead_in - d / 2],
|
||||||
|
[cap_neck_id / 2 + wallt2, -d / 2],
|
||||||
|
[0, -d / 2]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
down(d / 2){
|
||||||
|
generic_bottle_cap(wall = cap_wall,
|
||||||
|
texture = texture,
|
||||||
|
height = cap_h,
|
||||||
|
thread_depth = cap_thread_depth,
|
||||||
|
tolerance = tolerance,
|
||||||
|
neck_od = cap_neck_od,
|
||||||
|
flank_angle = cap_thread_taper,
|
||||||
|
orient = DOWN,
|
||||||
|
pitch = cap_thread_pitch
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
down(d / 2){
|
rotate_extrude() {
|
||||||
generic_bottle_cap(wall = cap_wall,
|
polygon(points = [
|
||||||
texture = texture,
|
[0, d / 2 + 0.1],
|
||||||
height = cap_h,
|
[neck_id / 2, d / 2],
|
||||||
thread_od = cap_thread_od,
|
[neck_id / 2, d / 2 - taper_lead_in],
|
||||||
tolerance = tolerance,
|
[cap_neck_id / 2, taper_lead_in - d / 2],
|
||||||
neck_od = cap_neck_od,
|
[cap_neck_id / 2, -d / 2 - cap_wall],
|
||||||
flank_angle = cap_thread_taper,
|
[0, -d / 2 - cap_wall - 0.1]
|
||||||
orient = DOWN,
|
]);
|
||||||
pitch = cap_thread_pitch
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rotate_extrude() {
|
children();
|
||||||
polygon(points = [
|
|
||||||
[0, d / 2 + 0.1],
|
|
||||||
[neck_id / 2, d / 2],
|
|
||||||
[neck_id / 2, d / 2 - taper_lead_in],
|
|
||||||
[cap_neck_id / 2, taper_lead_in - d / 2],
|
|
||||||
[cap_neck_id / 2, -d / 2 - cap_wall],
|
|
||||||
[0, -d / 2 - cap_wall - 0.1]
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function bottle_adapter_neck_to_cap(
|
function bottle_adapter_neck_to_cap(
|
||||||
wall, texture, cap_wall, cap_h, cap_thread_od,
|
wall, texture, cap_wall, cap_h, cap_thread_depth1,
|
||||||
tolerance, cap_neck_od, cap_neck_id, cap_thread_taper,
|
tolerance, cap_neck_od, cap_neck_id, cap_thread_taper,
|
||||||
cap_thread_pitch, neck_d, neck_id, neck_thread_od,
|
cap_thread_pitch, neck_d, neck_id, neck_thread_od,
|
||||||
neck_h, neck_thread_pitch, neck_support_od, d, taper_lead_in
|
neck_h, neck_thread_pitch, neck_support_od, d, taper_lead_in
|
||||||
|
@ -734,107 +748,115 @@ function bottle_adapter_neck_to_cap(
|
||||||
// Topics: Bottles, Threading
|
// Topics: Bottles, Threading
|
||||||
// See Also: bottle_adapter_neck_to_cap(), bottle_adapter_neck_to_neck()
|
// See Also: bottle_adapter_neck_to_cap(), bottle_adapter_neck_to_neck()
|
||||||
// Usage:
|
// Usage:
|
||||||
// bottle_adapter_cap_to_cap(wall, [texture]);
|
// bottle_adapter_cap_to_cap(wall, [texture]) [ATTACHMENTS];
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a threaded cap to cap adapter.
|
// Creates a threaded cap to cap adapter.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// wall = Wall thickness in mm.
|
// wall = Wall thickness in mm.
|
||||||
// texture = The surface texture of the cap. Valid values are "none", "knurled", or "ribbed". Default: "none"
|
// texture = The surface texture of the cap. Valid values are "none", "knurled", or "ribbed". Default: "none"
|
||||||
// cap_h1 = Interior height of top cap.
|
// cap_h1 = Interior height of top cap.
|
||||||
// cap_thread_od1 = Outer diameter of threads on top cap.
|
// cap_thread_depth1 = Thread depth on top cap. Default: 2.34
|
||||||
// tolerance = Extra space to add to the outer diameter of threads and neck in mm. Applied to radius.
|
// tolerance = Extra space to add to the outer diameter of threads and neck in mm. Applied to radius.
|
||||||
// cap_neck_od1 = Inner diameter of threads on top cap.
|
// cap_neck_od1 = Inner diameter of threads on top cap.
|
||||||
// cap_thread_pitch1 = Thread pitch of top cap in mm.
|
// cap_thread_pitch1 = Thread pitch of top cap in mm.
|
||||||
// cap_h2 = Interior height of bottom cap. Leave undefined to duplicate cap_h1.
|
// cap_h2 = Interior height of bottom cap. Leave undefined to duplicate cap_h1.
|
||||||
// cap_thread_od2 = Outer diameter of threads on bottom cap. Leave undefined to duplicate capThread1.
|
// cap_thread_depth2 = Thread depth on bottom cap. Default: same as cap_thread_depth1
|
||||||
// cap_neck_od2 = Inner diameter of threads on top cap. Leave undefined to duplicate cap_neck_od1.
|
// cap_neck_od2 = Inner diameter of threads on top cap. Leave undefined to duplicate cap_neck_od1.
|
||||||
// cap_thread_pitch2 = Thread pitch of bottom cap in mm. Leave undefinced to duplicate cap_thread_pitch1.
|
// cap_thread_pitch2 = Thread pitch of bottom cap in mm. Leave undefinced to duplicate cap_thread_pitch1.
|
||||||
// d = Distance between caps.
|
// d = Distance between caps.
|
||||||
// neck_id1 = Inner diameter of cutout in top cap.
|
// neck_id1 = Inner diameter of cutout in top cap.
|
||||||
// neck_id2 = Inner diameter of cutout in bottom cap.
|
// neck_id2 = Inner diameter of cutout in bottom cap.
|
||||||
// taper_lead_in = Length to leave straight before tapering on tube between caps if exists.
|
// taper_lead_in = Length to leave straight before tapering on tube between caps if exists.
|
||||||
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
||||||
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
||||||
|
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
||||||
// Examples:
|
// Examples:
|
||||||
// bottle_adapter_cap_to_cap();
|
// bottle_adapter_cap_to_cap();
|
||||||
module bottle_adapter_cap_to_cap(
|
module bottle_adapter_cap_to_cap(
|
||||||
wall = 2,
|
wall = 2,
|
||||||
texture = "none",
|
texture = "none",
|
||||||
cap_h1 = 11.2,
|
cap_h1 = 11.2,
|
||||||
cap_thread_od1 = 28.58,
|
cap_thread_depth1 = 2.34,
|
||||||
tolerance = .2,
|
tolerance = .2,
|
||||||
cap_neck_od1 = 25.5,
|
cap_neck_od1 = 25.5,
|
||||||
cap_thread_pitch1 = 4,
|
cap_thread_pitch1 = 4,
|
||||||
cap_h2,
|
cap_h2,
|
||||||
cap_thread_od2,
|
cap_thread_depth2,
|
||||||
cap_neck_od2,
|
cap_neck_od2,
|
||||||
cap_thread_pitch2,
|
cap_thread_pitch2,
|
||||||
d = 0,
|
d = 0,
|
||||||
neck_id1, neck_id2,
|
neck_id,
|
||||||
taper_lead_in = 0
|
taper_lead_in = 0, anchor, spin,orient
|
||||||
) {
|
) {
|
||||||
cap_h2 = (cap_h2 == undef) ? cap_h1 : cap_h2;
|
cap_h2 = default(cap_h2,cap_h1);
|
||||||
cap_thread_od2 = (cap_thread_od2 == undef) ? cap_thread_od1 : cap_thread_od2;
|
cap_thread_depth2 = default(cap_thread_depth2,cap_thread_depth1);
|
||||||
cap_neck_od2 = (cap_neck_od2 == undef) ? cap_neck_od1 : cap_neck_od2;
|
cap_neck_od2 = default(cap_neck_od2,cap_neck_od1);
|
||||||
cap_thread_pitch2 = (cap_thread_pitch2 == undef) ? cap_thread_pitch1 : cap_thread_pitch2;
|
cap_thread_pitch2 = default(cap_thread_pitch2,cap_thread_pitch1);
|
||||||
neck_id2 = (neck_id2 == undef && neck_id1 != undef) ? neck_id1 : neck_id2;
|
|
||||||
taper_lead_in = (d >= taper_lead_in * 2) ? taper_lead_in : d / 2;
|
taper_lead_in = (d >= taper_lead_in * 2) ? taper_lead_in : d / 2;
|
||||||
|
|
||||||
|
neck_id = min(cap_neck_od1 - cap_thread_depth1, cap_neck_od2-cap_thread_depth2);
|
||||||
|
|
||||||
|
top_h = cap_h1+wall;
|
||||||
|
bot_h = cap_h2+wall;
|
||||||
|
|
||||||
|
|
||||||
|
cap_od1 = cap_neck_od1 + 2*(cap_thread_depth1 - 0.8) + 2 * tolerance; // WTF; Engineered for consistency with old code, but
|
||||||
|
cap_od2 = cap_neck_od2 + 2*(cap_thread_depth2 - 0.8) + 2 * tolerance; // WTF; Engineered for consistency with old code, but
|
||||||
|
|
||||||
$fn = segs(33 / 2);
|
$fn = segs(33 / 2);
|
||||||
|
attachable(anchor=anchor,spin=spin,orient=orient, h=top_h+bot_h+d, d=max(cap_od1,cap_od2)+2*wall){
|
||||||
difference(){
|
zmove((bot_h-top_h)/2)
|
||||||
union(){
|
difference(){
|
||||||
up(d / 2){
|
union(){
|
||||||
generic_bottle_cap(
|
up(d / 2){
|
||||||
orient = UP,
|
generic_bottle_cap(
|
||||||
wall = wall,
|
orient = UP,
|
||||||
texture = texture,
|
wall = wall,
|
||||||
height = cap_h1,
|
texture = texture,
|
||||||
thread_od = cap_thread_od1,
|
height = cap_h1,
|
||||||
tolerance = tolerance,
|
thread_depth = cap_thread_depth1,
|
||||||
neck_od = cap_neck_od1,
|
tolerance = tolerance,
|
||||||
pitch = cap_thread_pitch1
|
neck_od = cap_neck_od1,
|
||||||
);
|
pitch = cap_thread_pitch1
|
||||||
}
|
);
|
||||||
if (d != 0) {
|
}
|
||||||
rotate_extrude() {
|
if (d != 0) {
|
||||||
polygon(points = [
|
rotate_extrude() {
|
||||||
[0, d / 2],
|
polygon(points = [
|
||||||
[cap_thread_od1 / 2 + (wall + tolerance), d / 2],
|
[0, d / 2],
|
||||||
[cap_thread_od1 / 2 + (wall + tolerance), d / 2 - taper_lead_in],
|
[cap_od1 / 2 + wall, d / 2],
|
||||||
[cap_thread_od2 / 2 + (wall + tolerance), taper_lead_in - d / 2],
|
[cap_od1 / 2 + wall, d / 2 - taper_lead_in],
|
||||||
[cap_thread_od2 / 2 + (wall + tolerance), -d / 2],
|
[cap_od2 / 2 + wall, taper_lead_in - d / 2],
|
||||||
[0, -d / 2]
|
[cap_od2 / 2 + wall, -d / 2],
|
||||||
]);
|
[0, -d / 2]
|
||||||
}
|
]);
|
||||||
}
|
}
|
||||||
down(d / 2){
|
}
|
||||||
generic_bottle_cap(
|
down(d / 2){
|
||||||
orient = DOWN,
|
generic_bottle_cap(
|
||||||
wall = wall,
|
orient = DOWN,
|
||||||
texture = texture,
|
wall = wall,
|
||||||
height = cap_h2,
|
texture = texture,
|
||||||
thread_od = cap_thread_od2,
|
height = cap_h2,
|
||||||
tolerance = tolerance,
|
thread_depth = cap_thread_depth2,
|
||||||
neck_od = cap_neck_od2,
|
tolerance = tolerance,
|
||||||
pitch = cap_thread_pitch2
|
neck_od = cap_neck_od2,
|
||||||
);
|
pitch = cap_thread_pitch2
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
if (neck_id1 != undef || neck_id2 != undef) {
|
}
|
||||||
neck_id1 = (neck_id1 == undef) ? neck_id2 : neck_id1;
|
rotate_extrude() {
|
||||||
neck_id2 = (neck_id2 == undef) ? neck_id1 : neck_id2;
|
polygon(points = [
|
||||||
|
[0, wall + d / 2 + 0.1],
|
||||||
rotate_extrude() {
|
[neck_id / 2, wall + d / 2],
|
||||||
polygon(points = [
|
[neck_id / 2, wall + d / 2 - taper_lead_in],
|
||||||
[0, wall + d / 2 + 0.1],
|
[neck_id / 2, taper_lead_in - d / 2 - wall],
|
||||||
[neck_id1 / 2, wall + d / 2],
|
[neck_id / 2, -d / 2 - wall],
|
||||||
[neck_id1 / 2, wall + d / 2 - taper_lead_in],
|
[0, -d / 2 - wall - 0.1]
|
||||||
[neck_id2 / 2, taper_lead_in - d / 2 - wall],
|
]);
|
||||||
[neck_id2 / 2, -d / 2 - wall],
|
}
|
||||||
[0, -d / 2 - wall - 0.1]
|
}
|
||||||
]);
|
children();
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,7 +872,7 @@ function bottle_adapter_cap_to_cap(
|
||||||
// Topics: Bottles, Threading
|
// Topics: Bottles, Threading
|
||||||
// See Also: bottle_adapter_neck_to_cap(), bottle_adapter_cap_to_cap()
|
// See Also: bottle_adapter_neck_to_cap(), bottle_adapter_cap_to_cap()
|
||||||
// Usage:
|
// Usage:
|
||||||
// bottle_adapter_neck_to_neck(...);
|
// bottle_adapter_neck_to_neck(...) [ATTACHMENTS];
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a threaded neck to neck adapter.
|
// Creates a threaded neck to neck adapter.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
@ -869,7 +891,10 @@ function bottle_adapter_cap_to_cap(
|
||||||
// support_od2 = Outer diameter of the support ring on bottom neck. Set to 0 for no ring. Leave undefined to duplicate support_od1
|
// support_od2 = Outer diameter of the support ring on bottom neck. Set to 0 for no ring. Leave undefined to duplicate support_od1
|
||||||
// pitch2 = Thread pitch of bottom neck. Leave undefined to duplicate thread_pitch1
|
// pitch2 = Thread pitch of bottom neck. Leave undefined to duplicate thread_pitch1
|
||||||
// taper_lead_in = Length to leave straight before tapering on tube between necks if exists.
|
// taper_lead_in = Length to leave straight before tapering on tube between necks if exists.
|
||||||
// wall = Thickness of tube wall between necks. Leave undefined to match outer diameters with the neckODs/supportODs.
|
// wall = Thickness of tube wall between necks. Leave undefined to match outer diameters with the neckODs/supportODs.
|
||||||
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
||||||
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
||||||
|
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
||||||
// Examples:
|
// Examples:
|
||||||
// bottle_adapter_neck_to_neck();
|
// bottle_adapter_neck_to_neck();
|
||||||
module bottle_adapter_neck_to_neck(
|
module bottle_adapter_neck_to_neck(
|
||||||
|
@ -882,10 +907,9 @@ module bottle_adapter_neck_to_neck(
|
||||||
thread_pitch1 = 3.2,
|
thread_pitch1 = 3.2,
|
||||||
neck_od2, neck_id2,
|
neck_od2, neck_id2,
|
||||||
thread_od2, height2,
|
thread_od2, height2,
|
||||||
support_od2, pitch2,
|
support_od2, pitch2,
|
||||||
taper_lead_in = 0, wall
|
taper_lead_in = 0, wall, anchor, spin, orient
|
||||||
) {
|
) {
|
||||||
no_children($children);
|
|
||||||
neck_od2 = (neck_od2 == undef) ? neck_od1 : neck_od2;
|
neck_od2 = (neck_od2 == undef) ? neck_od1 : neck_od2;
|
||||||
neck_id2 = (neck_id2 == undef) ? neck_id1 : neck_id2;
|
neck_id2 = (neck_id2 == undef) ? neck_id1 : neck_id2;
|
||||||
thread_od2 = (thread_od2 == undef) ? thread_od1 : thread_od2;
|
thread_od2 = (thread_od2 == undef) ? thread_od1 : thread_od2;
|
||||||
|
@ -903,60 +927,67 @@ module bottle_adapter_neck_to_neck(
|
||||||
|
|
||||||
taper_lead_in = (d >= taper_lead_in * 2) ? taper_lead_in : d / 2;
|
taper_lead_in = (d >= taper_lead_in * 2) ? taper_lead_in : d / 2;
|
||||||
|
|
||||||
difference(){
|
top_h = height1 + max(1,height1/17)*sign(support_od1);
|
||||||
union(){
|
bot_h = height2 + max(1,height2/17)*sign(support_od2);
|
||||||
up(d / 2){
|
|
||||||
generic_bottle_neck(orient = UP,
|
attachable(anchor=anchor,orient=orient,spin=spin, h=top_h+bot_h+d, d=max(neck_od1,neck_od2)){
|
||||||
neck_d = neck_od1,
|
zmove((bot_h-top_h)/2)
|
||||||
id = neck_id1,
|
difference(){
|
||||||
thread_od = thread_od1,
|
union(){
|
||||||
height = height1,
|
up(d / 2){
|
||||||
support_d = supprtOD1,
|
generic_bottle_neck(orient = UP,
|
||||||
pitch = thread_pitch1,
|
neck_d = neck_od1,
|
||||||
round_supp = ((wallt1 < (supprtOD1 - neck_id1) / 2) || (support_od1 > max(neck_od2, support_od2) && d == 0)),
|
id = neck_id1,
|
||||||
wall = (d > 0) ? wallt1 : min(wallt1, ((max(neck_od2, support_od2)) - neck_id1) / 2)
|
thread_od = thread_od1,
|
||||||
);
|
height = height1,
|
||||||
}
|
support_d = supprtOD1,
|
||||||
if (d != 0) {
|
pitch = thread_pitch1,
|
||||||
rotate_extrude() {
|
round_supp = ((wallt1 < (supprtOD1 - neck_id1) / 2) || (support_od1 > max(neck_od2, support_od2) && d == 0)),
|
||||||
polygon(points = [
|
wall = (d > 0) ? wallt1 : min(wallt1, ((max(neck_od2, support_od2)) - neck_id1) / 2)
|
||||||
[0, d / 2],
|
);
|
||||||
[neck_id1 / 2 + wallt1, d / 2],
|
}
|
||||||
[neck_id1 / 2 + wallt1, d / 2 - taper_lead_in],
|
if (d != 0) {
|
||||||
[neck_id2 / 2 + wallt2, taper_lead_in - d / 2],
|
rotate_extrude() {
|
||||||
[neck_id2 / 2 + wallt2, -d / 2],
|
polygon(points = [
|
||||||
[0, -d / 2]
|
[0, d / 2],
|
||||||
]);
|
[neck_id1 / 2 + wallt1, d / 2],
|
||||||
}
|
[neck_id1 / 2 + wallt1, d / 2 - taper_lead_in],
|
||||||
}
|
[neck_id2 / 2 + wallt2, taper_lead_in - d / 2],
|
||||||
down(d / 2){
|
[neck_id2 / 2 + wallt2, -d / 2],
|
||||||
generic_bottle_neck(orient = DOWN,
|
[0, -d / 2]
|
||||||
neck_d = neck_od2,
|
]);
|
||||||
id = neck_id2,
|
}
|
||||||
thread_od = thread_od2,
|
}
|
||||||
height = height2,
|
down(d / 2){
|
||||||
support_d = supprtOD2,
|
generic_bottle_neck(orient = DOWN,
|
||||||
pitch = pitch2,
|
neck_d = neck_od2,
|
||||||
round_supp = ((wallt2 < (supprtOD2 - neck_id2) / 2) || (support_od2 > max(neck_od1, support_od1) && d == 0)),
|
id = neck_id2,
|
||||||
wall = (d > 0) ? wallt2 : min(wallt2, ((max(neck_od1, support_od1)) - neck_id2) / 2)
|
thread_od = thread_od2,
|
||||||
);
|
height = height2,
|
||||||
}
|
support_d = supprtOD2,
|
||||||
}
|
pitch = pitch2,
|
||||||
if (neck_id1 != undef || neck_id2 != undef) {
|
round_supp = ((wallt2 < (supprtOD2 - neck_id2) / 2) || (support_od2 > max(neck_od1, support_od1) && d == 0)),
|
||||||
neck_id1 = (neck_id1 == undef) ? neck_id2 : neck_id1;
|
wall = (d > 0) ? wallt2 : min(wallt2, ((max(neck_od1, support_od1)) - neck_id2) / 2)
|
||||||
neck_id2 = (neck_id2 == undef) ? neck_id1 : neck_id2;
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (neck_id1 != undef || neck_id2 != undef) {
|
||||||
|
neck_id1 = (neck_id1 == undef) ? neck_id2 : neck_id1;
|
||||||
|
neck_id2 = (neck_id2 == undef) ? neck_id1 : neck_id2;
|
||||||
|
|
||||||
rotate_extrude() {
|
rotate_extrude() {
|
||||||
polygon(points = [
|
polygon(points = [
|
||||||
[0, d / 2],
|
[0, d / 2],
|
||||||
[neck_id1 / 2, d / 2],
|
[neck_id1 / 2, d / 2],
|
||||||
[neck_id1 / 2, d / 2 - taper_lead_in],
|
[neck_id1 / 2, d / 2 - taper_lead_in],
|
||||||
[neck_id2 / 2, taper_lead_in - d / 2],
|
[neck_id2 / 2, taper_lead_in - d / 2],
|
||||||
[neck_id2 / 2, -d / 2],
|
[neck_id2 / 2, -d / 2],
|
||||||
[0, -d / 2]
|
[0, -d / 2]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
310
mutators.scad
310
mutators.scad
|
@ -85,15 +85,19 @@ module bounding_box(excess=0, planar=false) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(planar) {
|
req_children($children);
|
||||||
offset(excess-1/2) _oversize_bbox() children();
|
attachable(){
|
||||||
} else {
|
if(planar) {
|
||||||
render(convexity=2)
|
offset(excess-1/2) _oversize_bbox() children();
|
||||||
if (excess>.1) {
|
} else {
|
||||||
_oversize_bbox() children();
|
render(convexity=2)
|
||||||
} else {
|
if (excess>.1) {
|
||||||
_shrink_cube() _oversize_bbox() children();
|
_oversize_bbox() children();
|
||||||
}
|
} else {
|
||||||
|
_shrink_cube() _oversize_bbox() children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
union();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,10 +141,12 @@ module bounding_box(excess=0, planar=false) {
|
||||||
// }
|
// }
|
||||||
module chain_hull()
|
module chain_hull()
|
||||||
{
|
{
|
||||||
union() {
|
req_children($children);
|
||||||
|
attachable(){
|
||||||
if ($children == 1) {
|
if ($children == 1) {
|
||||||
children();
|
children();
|
||||||
} else if ($children > 1) {
|
}
|
||||||
|
else {
|
||||||
for (i =[1:1:$children-1]) {
|
for (i =[1:1:$children-1]) {
|
||||||
$idx = i;
|
$idx = i;
|
||||||
hull() {
|
hull() {
|
||||||
|
@ -149,6 +155,7 @@ module chain_hull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
union();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,6 +210,7 @@ module chain_hull()
|
||||||
// move_copies([[-3.5,1.5],[0.0,3.0],[3.5,1.5]])
|
// move_copies([[-3.5,1.5],[0.0,3.0],[3.5,1.5]])
|
||||||
// circle(r=1.5);
|
// circle(r=1.5);
|
||||||
module path_extrude2d(path, caps=false, closed=false, s, convexity=10) {
|
module path_extrude2d(path, caps=false, closed=false, s, convexity=10) {
|
||||||
|
req_children($children);
|
||||||
extra_ang = 0.1; // Extra angle for overlap of joints
|
extra_ang = 0.1; // Extra angle for overlap of joints
|
||||||
check =
|
check =
|
||||||
assert(caps==false || closed==false, "Cannot have caps on a closed extrusion")
|
assert(caps==false || closed==false, "Cannot have caps on a closed extrusion")
|
||||||
|
@ -213,58 +221,63 @@ module path_extrude2d(path, caps=false, closed=false, s, convexity=10) {
|
||||||
norm(b[1]-b[0]);
|
norm(b[1]-b[0]);
|
||||||
check2 = assert(is_finite(s));
|
check2 = assert(is_finite(s));
|
||||||
L = len(path);
|
L = len(path);
|
||||||
for (i = [0:1:L-(closed?1:2)]) {
|
attachable(){
|
||||||
seg = select(path, i, i+1);
|
union(){
|
||||||
segv = seg[1] - seg[0];
|
for (i = [0:1:L-(closed?1:2)]) {
|
||||||
seglen = norm(segv);
|
seg = select(path, i, i+1);
|
||||||
translate((seg[0]+seg[1])/2) {
|
segv = seg[1] - seg[0];
|
||||||
rot(from=BACK, to=segv) {
|
seglen = norm(segv);
|
||||||
difference() {
|
translate((seg[0]+seg[1])/2) {
|
||||||
xrot(90) {
|
rot(from=BACK, to=segv) {
|
||||||
linear_extrude(height=seglen, center=true, convexity=convexity) {
|
difference() {
|
||||||
children();
|
xrot(90) {
|
||||||
|
linear_extrude(height=seglen, center=true, convexity=convexity) {
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (closed || i>0) {
|
||||||
|
pt = select(path, i-1);
|
||||||
|
pang = v_theta(rot(from=-segv, to=RIGHT, p=pt - seg[0]));
|
||||||
|
fwd(seglen/2+0.01) zrot(pang/2) cube(s, anchor=BACK);
|
||||||
|
}
|
||||||
|
if (closed || i<L-2) {
|
||||||
|
pt = select(path, i+2);
|
||||||
|
pang = v_theta(rot(from=segv, to=RIGHT, p=pt - seg[1]));
|
||||||
|
back(seglen/2+0.01) zrot(pang/2) cube(s, anchor=FWD);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (closed || i>0) {
|
|
||||||
pt = select(path, i-1);
|
|
||||||
pang = v_theta(rot(from=-segv, to=RIGHT, p=pt - seg[0]));
|
|
||||||
fwd(seglen/2+0.01) zrot(pang/2) cube(s, anchor=BACK);
|
|
||||||
}
|
|
||||||
if (closed || i<L-2) {
|
|
||||||
pt = select(path, i+2);
|
|
||||||
pang = v_theta(rot(from=segv, to=RIGHT, p=pt - seg[1]));
|
|
||||||
back(seglen/2+0.01) zrot(pang/2) cube(s, anchor=FWD);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
for (t=triplet(path,wrap=closed)) {
|
||||||
for (t=triplet(path,wrap=closed)) {
|
ang = -(180-vector_angle(t)) * sign(_point_left_of_line2d(t[2],[t[0],t[1]]));
|
||||||
ang = -(180-vector_angle(t)) * sign(_point_left_of_line2d(t[2],[t[0],t[1]]));
|
delt = point3d(t[2] - t[1]);
|
||||||
delt = point3d(t[2] - t[1]);
|
if (ang!=0)
|
||||||
if (ang!=0)
|
translate(t[1]) {
|
||||||
translate(t[1]) {
|
frame_map(y=delt, z=UP)
|
||||||
frame_map(y=delt, z=UP)
|
rotate(-sign(ang)*extra_ang/2)
|
||||||
rotate(-sign(ang)*extra_ang/2)
|
rotate_extrude(angle=ang+sign(ang)*extra_ang)
|
||||||
rotate_extrude(angle=ang+sign(ang)*extra_ang)
|
if (ang<0)
|
||||||
if (ang<0)
|
right_half(planar=true) children();
|
||||||
right_half(planar=true) children();
|
else
|
||||||
else
|
left_half(planar=true) children();
|
||||||
left_half(planar=true) children();
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
}
|
if (caps) {
|
||||||
if (caps) {
|
bseg = select(path,0,1);
|
||||||
bseg = select(path,0,1);
|
move(bseg[0])
|
||||||
move(bseg[0])
|
rot(from=BACK, to=bseg[0]-bseg[1])
|
||||||
rot(from=BACK, to=bseg[0]-bseg[1])
|
rotate_extrude(angle=180)
|
||||||
rotate_extrude(angle=180)
|
right_half(planar=true) children();
|
||||||
right_half(planar=true) children();
|
eseg = select(path,-2,-1);
|
||||||
eseg = select(path,-2,-1);
|
move(eseg[1])
|
||||||
move(eseg[1])
|
rot(from=BACK, to=eseg[1]-eseg[0])
|
||||||
rot(from=BACK, to=eseg[1]-eseg[0])
|
rotate_extrude(angle=180)
|
||||||
rotate_extrude(angle=180)
|
right_half(planar=true) children();
|
||||||
right_half(planar=true) children();
|
}
|
||||||
|
}
|
||||||
|
union();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,6 +311,7 @@ module path_extrude2d(path, caps=false, closed=false, s, convexity=10) {
|
||||||
// cylindrical_extrude(or=40, ir=35, orient=BACK)
|
// cylindrical_extrude(or=40, ir=35, orient=BACK)
|
||||||
// text(text="Hello World!", size=10, halign="center", valign="center");
|
// text(text="Hello World!", size=10, halign="center", valign="center");
|
||||||
module cylindrical_extrude(ir, or, od, id, size=1000, convexity=10, spin=0, orient=UP) {
|
module cylindrical_extrude(ir, or, od, id, size=1000, convexity=10, spin=0, orient=UP) {
|
||||||
|
req_children($children);
|
||||||
check1 = assert(is_num(size) || is_vector(size,2));
|
check1 = assert(is_num(size) || is_vector(size,2));
|
||||||
size = is_num(size)? [size,size] : size;
|
size = is_num(size)? [size,size] : size;
|
||||||
ir = get_radius(r=ir,d=id);
|
ir = get_radius(r=ir,d=id);
|
||||||
|
@ -310,23 +324,26 @@ module cylindrical_extrude(ir, or, od, id, size=1000, convexity=10, spin=0, orie
|
||||||
sides = segs(or);
|
sides = segs(or);
|
||||||
step = circumf / sides;
|
step = circumf / sides;
|
||||||
steps = ceil(width / step);
|
steps = ceil(width / step);
|
||||||
rot(from=UP, to=orient) rot(spin) {
|
attachable() {
|
||||||
for (i=[0:1:steps-2]) {
|
rot(from=UP, to=orient) rot(spin) {
|
||||||
x = (i+0.5-steps/2) * step;
|
for (i=[0:1:steps-2]) {
|
||||||
zrot(360 * x / circumf) {
|
x = (i+0.5-steps/2) * step;
|
||||||
fwd(or*cos(180/sides)) {
|
zrot(360 * x / circumf) {
|
||||||
xrot(-90) {
|
fwd(or*cos(180/sides)) {
|
||||||
linear_extrude(height=or-ir, scale=[ir/or,1], center=false, convexity=convexity) {
|
xrot(-90) {
|
||||||
yflip()
|
linear_extrude(height=or-ir, scale=[ir/or,1], center=false, convexity=convexity) {
|
||||||
intersection() {
|
yflip()
|
||||||
left(x) children();
|
intersection() {
|
||||||
rect([quantup(step,pow(2,-15)),size.y]);
|
left(x) children();
|
||||||
}
|
rect([quantup(step,pow(2,-15)),size.y]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
union();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,6 +370,7 @@ module cylindrical_extrude(ir, or, od, id, size=1000, convexity=10, spin=0, orie
|
||||||
// xcopies(3) circle(3, $fn=32);
|
// xcopies(3) circle(3, $fn=32);
|
||||||
// }
|
// }
|
||||||
module extrude_from_to(pt1, pt2, convexity, twist, scale, slices) {
|
module extrude_from_to(pt1, pt2, convexity, twist, scale, slices) {
|
||||||
|
req_children($children);
|
||||||
check =
|
check =
|
||||||
assert(is_vector(pt1),"First point must be a vector")
|
assert(is_vector(pt1),"First point must be a vector")
|
||||||
assert(is_vector(pt2),"Second point must be a vector");
|
assert(is_vector(pt2),"Second point must be a vector");
|
||||||
|
@ -391,6 +409,7 @@ module extrude_from_to(pt1, pt2, convexity, twist, scale, slices) {
|
||||||
// path = [ [0, 0, 0], [33, 33, 33], [66, 33, 40], [100, 0, 0], [150,0,0] ];
|
// path = [ [0, 0, 0], [33, 33, 33], [66, 33, 40], [100, 0, 0], [150,0,0] ];
|
||||||
// path_extrude(path) circle(r=10, $fn=6);
|
// path_extrude(path) circle(r=10, $fn=6);
|
||||||
module path_extrude(path, convexity=10, clipsize=100) {
|
module path_extrude(path, convexity=10, clipsize=100) {
|
||||||
|
req_children($children);
|
||||||
rotmats = cumprod([
|
rotmats = cumprod([
|
||||||
for (i = idx(path,e=-2)) let(
|
for (i = idx(path,e=-2)) let(
|
||||||
vec1 = i==0? UP : unit(path[i]-path[i-1], UP),
|
vec1 = i==0? UP : unit(path[i]-path[i-1], UP),
|
||||||
|
@ -401,32 +420,35 @@ module path_extrude(path, convexity=10, clipsize=100) {
|
||||||
interp = rot_resample(rotmats,n=2,method="count");
|
interp = rot_resample(rotmats,n=2,method="count");
|
||||||
epsilon = 0.0001; // Make segments ever so slightly too long so they overlap.
|
epsilon = 0.0001; // Make segments ever so slightly too long so they overlap.
|
||||||
ptcount = len(path);
|
ptcount = len(path);
|
||||||
for (i = [0:1:ptcount-2]) {
|
attachable(){
|
||||||
pt1 = path[i];
|
for (i = [0:1:ptcount-2]) {
|
||||||
pt2 = path[i+1];
|
pt1 = path[i];
|
||||||
dist = norm(pt2-pt1);
|
pt2 = path[i+1];
|
||||||
T = rotmats[i];
|
dist = norm(pt2-pt1);
|
||||||
difference() {
|
T = rotmats[i];
|
||||||
translate(pt1) {
|
difference() {
|
||||||
multmatrix(T) {
|
translate(pt1) {
|
||||||
down(clipsize/2/2) {
|
multmatrix(T) {
|
||||||
if ((dist+clipsize/2) > 0) {
|
down(clipsize/2/2) {
|
||||||
linear_extrude(height=dist+clipsize/2, convexity=convexity) {
|
if ((dist+clipsize/2) > 0) {
|
||||||
children();
|
linear_extrude(height=dist+clipsize/2, convexity=convexity) {
|
||||||
}
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
translate(pt1) {
|
}
|
||||||
hq = (i > 0)? interp[2*i-1] : T;
|
translate(pt1) {
|
||||||
multmatrix(hq) down(clipsize/2+epsilon) cube(clipsize, center=true);
|
hq = (i > 0)? interp[2*i-1] : T;
|
||||||
}
|
multmatrix(hq) down(clipsize/2+epsilon) cube(clipsize, center=true);
|
||||||
translate(pt2) {
|
}
|
||||||
hq = (i < ptcount-2)? interp[2*i+1] : T;
|
translate(pt2) {
|
||||||
multmatrix(hq) up(clipsize/2+epsilon) cube(clipsize, center=true);
|
hq = (i < ptcount-2)? interp[2*i+1] : T;
|
||||||
}
|
multmatrix(hq) up(clipsize/2+epsilon) cube(clipsize, center=true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
union();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,17 +481,21 @@ module path_extrude(path, convexity=10, clipsize=100) {
|
||||||
// sphere(r=10);
|
// sphere(r=10);
|
||||||
// }
|
// }
|
||||||
module minkowski_difference(planar=false) {
|
module minkowski_difference(planar=false) {
|
||||||
difference() {
|
req_children($children);
|
||||||
bounding_box(excess=0, planar=planar) children(0);
|
attachable(){
|
||||||
render(convexity=20) {
|
difference() {
|
||||||
minkowski() {
|
bounding_box(excess=0, planar=planar) children(0);
|
||||||
difference() {
|
render(convexity=20) {
|
||||||
bounding_box(excess=1, planar=planar) children(0);
|
minkowski() {
|
||||||
children(0);
|
difference() {
|
||||||
}
|
bounding_box(excess=1, planar=planar) children(0);
|
||||||
for (i=[1:1:$children-1]) children(i);
|
children(0);
|
||||||
}
|
}
|
||||||
}
|
for (i=[1:1:$children-1]) children(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
union();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,29 +517,33 @@ module minkowski_difference(planar=false) {
|
||||||
// size = Maximum size of object to be contracted, given as a scalar. Default: 100
|
// size = Maximum size of object to be contracted, given as a scalar. Default: 100
|
||||||
// convexity = Max number of times a line could intersect the walls of the object. Default: 10
|
// convexity = Max number of times a line could intersect the walls of the object. Default: 10
|
||||||
module offset3d(r, size=100, convexity=10) {
|
module offset3d(r, size=100, convexity=10) {
|
||||||
|
req_children($children);
|
||||||
n = quant(max(8,segs(abs(r))),4);
|
n = quant(max(8,segs(abs(r))),4);
|
||||||
if (r==0) {
|
attachable(){
|
||||||
children();
|
if (r==0) {
|
||||||
} else if (r>0) {
|
children();
|
||||||
render(convexity=convexity)
|
} else if (r>0) {
|
||||||
minkowski() {
|
render(convexity=convexity)
|
||||||
children();
|
minkowski() {
|
||||||
sphere(r, $fn=n);
|
children();
|
||||||
}
|
sphere(r, $fn=n);
|
||||||
} else {
|
}
|
||||||
size2 = size * [1,1,1];
|
} else {
|
||||||
size1 = size2 * 1.02;
|
size2 = size * [1,1,1];
|
||||||
render(convexity=convexity)
|
size1 = size2 * 1.02;
|
||||||
difference() {
|
render(convexity=convexity)
|
||||||
cube(size2, center=true);
|
difference() {
|
||||||
minkowski() {
|
cube(size2, center=true);
|
||||||
difference() {
|
minkowski() {
|
||||||
cube(size1, center=true);
|
difference() {
|
||||||
children();
|
cube(size1, center=true);
|
||||||
}
|
children();
|
||||||
sphere(-r, $fn=n);
|
}
|
||||||
}
|
sphere(-r, $fn=n);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
union();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,12 +570,16 @@ module offset3d(r, size=100, convexity=10) {
|
||||||
// ir = Radius to round only inside (concave) corners to. Use instead of `r`.
|
// ir = Radius to round only inside (concave) corners to. Use instead of `r`.
|
||||||
module round3d(r, or, ir, size=100)
|
module round3d(r, or, ir, size=100)
|
||||||
{
|
{
|
||||||
|
req_children($children);
|
||||||
or = get_radius(r1=or, r=r, dflt=0);
|
or = get_radius(r1=or, r=r, dflt=0);
|
||||||
ir = get_radius(r1=ir, r=r, dflt=0);
|
ir = get_radius(r1=ir, r=r, dflt=0);
|
||||||
offset3d(or, size=size)
|
attachable(){
|
||||||
offset3d(-ir-or, size=size)
|
offset3d(or, size=size)
|
||||||
offset3d(ir, size=size)
|
offset3d(-ir-or, size=size)
|
||||||
children();
|
offset3d(ir, size=size)
|
||||||
|
children();
|
||||||
|
union();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -329,37 +329,38 @@ module regular_polyhedron(
|
||||||
faces = entry[3];
|
faces = entry[3];
|
||||||
face_normals = entry[4];
|
face_normals = entry[4];
|
||||||
in_radius = entry[5];
|
in_radius = entry[5];
|
||||||
if (draw){
|
translate(translation){
|
||||||
if (rounding==0)
|
if (draw){
|
||||||
polyhedron(move(translation, p=scaled_points), faces = face_triangles);
|
if (rounding==0)
|
||||||
else {
|
polyhedron(scaled_points, faces = face_triangles);
|
||||||
fn = segs(rounding);
|
else {
|
||||||
rounding = rounding/cos(180/fn);
|
fn = segs(rounding);
|
||||||
adjusted_scale = 1 - rounding / in_radius;
|
rounding = rounding/cos(180/fn);
|
||||||
minkowski(){
|
adjusted_scale = 1 - rounding / in_radius;
|
||||||
sphere(r=rounding, $fn=fn);
|
minkowski(){
|
||||||
polyhedron(move(translation,p=adjusted_scale*scaled_points), faces = face_triangles);
|
sphere(r=rounding, $fn=fn);
|
||||||
|
polyhedron(adjusted_scale*scaled_points, faces = face_triangles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if ($children>0) {
|
||||||
translate(translation)
|
maxrange = repeat ? len(faces)-1 : $children-1;
|
||||||
if ($children>0) {
|
for(i=[0:1:maxrange]) {
|
||||||
maxrange = repeat ? len(faces)-1 : $children-1;
|
// Would like to orient so an edge (longest edge?) is parallel to x axis
|
||||||
for(i=[0:1:maxrange]) {
|
facepts = select(scaled_points, faces[i]);
|
||||||
// Would like to orient so an edge (longest edge?) is parallel to x axis
|
$center = -mean(facepts);
|
||||||
facepts = select(scaled_points, faces[i]);
|
cfacepts = move($center, p=facepts);
|
||||||
$center = -mean(facepts);
|
$face = rotate_children
|
||||||
cfacepts = move($center, p=facepts);
|
? path2d(frame_map(z=face_normals[i], x=facepts[0]-facepts[1], reverse=true, p=cfacepts))
|
||||||
$face = rotate_children
|
: cfacepts;
|
||||||
? path2d(frame_map(z=face_normals[i], x=facepts[0]-facepts[1], reverse=true, p=cfacepts))
|
$faceindex = i;
|
||||||
: cfacepts;
|
translate(-$center)
|
||||||
$faceindex = i;
|
if (rotate_children) {
|
||||||
translate(-$center)
|
frame_map(z=face_normals[i], x=facepts[0]-facepts[1])
|
||||||
if (rotate_children) {
|
children(i % $children);
|
||||||
frame_map(z=face_normals[i], x=facepts[0]-facepts[1])
|
} else {
|
||||||
children(i % $children);
|
children(i % $children);
|
||||||
} else {
|
}
|
||||||
children(i % $children);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue