2017-08-30 00:00:16 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// Masking shapes.
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/*
|
|
|
|
BSD 2-Clause License
|
|
|
|
|
|
|
|
Copyright (c) 2017, Revar Desmera
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright notice, this
|
|
|
|
list of conditions and the following disclaimer.
|
|
|
|
|
|
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer in the documentation
|
|
|
|
and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
include <transforms.scad>
|
2018-11-26 09:53:02 +00:00
|
|
|
include <shapes.scad>
|
2017-08-30 01:57:37 +00:00
|
|
|
include <math.scad>
|
2017-08-30 00:00:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
module angle_half_pie_mask(
|
|
|
|
ang=45, h=1,
|
|
|
|
r=undef, r1=undef, r2=undef,
|
|
|
|
d=1.0, d1=undef, d2=undef,
|
|
|
|
) {
|
|
|
|
r = (r != undef)? r : (d/2);
|
|
|
|
r1 = (r1 != undef)? r1 : ((d1 != undef)? (d1/2) : r);
|
|
|
|
r2 = (r2 != undef)? r2 : ((d2 != undef)? (d2/2) : r);
|
|
|
|
rm = max(r1,r2);
|
|
|
|
difference() {
|
|
|
|
cylinder(h=h, r1=r1, r2=r2, center=true);
|
|
|
|
translate([0, -rm/2, 0])
|
|
|
|
cube(size=[rm*2+1, rm, h+1], center=true);
|
|
|
|
zrot(ang) {
|
|
|
|
translate([0, rm/2, 0]) {
|
|
|
|
cube(size=[rm*2.1, rm, h+1], center=true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Creates a pie wedge shape that can be used to mask other shapes.
|
|
|
|
// You must specify either r or d, or their r1/r2, d1/d2 variants.
|
|
|
|
// ang = angle of wedge in degrees.
|
|
|
|
// h = height of wedge.
|
|
|
|
// r = Radius of circle wedge is created from. (optional)
|
|
|
|
// r1 = Bottom radius of cone that wedge is created from. (optional)
|
|
|
|
// r2 = Upper radius of cone that wedge is created from. (optional)
|
|
|
|
// d = Diameter of circle wedge is created from. (optional)
|
|
|
|
// d1 = Bottom diameter of cone that wedge is created from. (optional)
|
|
|
|
// d2 = Upper diameter of cone that wedge is created from. (optional)
|
|
|
|
// Example:
|
|
|
|
// angle_pie_mask(ang=30, d=100, h=20);
|
|
|
|
module angle_pie_mask(
|
|
|
|
ang=45, h=1,
|
|
|
|
r=undef, r1=undef, r2=undef,
|
|
|
|
d=1.0, d1=undef, d2=undef,
|
|
|
|
) {
|
|
|
|
a1 = min(ang, 180.0);
|
|
|
|
a2 = max(0.0, ang-180.0);
|
|
|
|
r = (r != undef)? r : (d/2);
|
|
|
|
r1 = (r1 != undef)? r1 : ((d1 != undef)? (d1/2) : r);
|
|
|
|
r2 = (r2 != undef)? r2 : ((d2 != undef)? (d2/2) : r);
|
|
|
|
union() {
|
|
|
|
angle_half_pie_mask(h=h, r1=r1, r2=r2, ang=a1);
|
|
|
|
if (a2 > 0.0) {
|
|
|
|
zrot(180) angle_half_pie_mask(h=h, r1=r1, r2=r2, ang=a2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Creates a shape that can be used to chamfer a 90 degree edge along the Z axis.
|
|
|
|
// Difference it from the object to be chamfered. The center of the mask
|
|
|
|
// object should align exactly with the edge to be chamfered.
|
|
|
|
// l = Height of mask
|
|
|
|
// chamfer = size of chamfer
|
|
|
|
// Example:
|
|
|
|
// chamfer_mask_z(l=10.0, chamfer=2.0);
|
|
|
|
module chamfer_mask_z(l=1.0, chamfer=1.0) {
|
|
|
|
zrot(45) cube(size=[chamfer*sqrt(2.0), chamfer*sqrt(2.0), l], center=true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Creates a shape that can be used to chamfer a 90 degree edge along the Y axis.
|
|
|
|
// Difference it from the object to be chamfered. The center of the mask
|
|
|
|
// object should align exactly with the edge to be chamfered.
|
|
|
|
// l = Height of mask
|
|
|
|
// chamfer = size of chamfer
|
|
|
|
// Example:
|
|
|
|
// chamfer_mask_y(l=10.0, chamfer=2.0);
|
2018-10-07 05:23:01 +00:00
|
|
|
module chamfer_mask_y(l=1.0, chamfer=1.0) {
|
|
|
|
xrot(90) chamfer_mask_z(l=l, chamfer=chamfer);
|
|
|
|
}
|
2017-08-30 00:00:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Creates a shape that can be used to chamfer a 90 degree edge along the X axis.
|
|
|
|
// Difference it from the object to be chamfered. The center of the mask
|
|
|
|
// object should align exactly with the edge to be chamfered.
|
|
|
|
// l = Height of mask
|
|
|
|
// chamfer = size of chamfer
|
|
|
|
// Example:
|
|
|
|
// chamfer_mask_x(l=10.0, chamfer=2.0);
|
2018-10-07 05:23:01 +00:00
|
|
|
module chamfer_mask_x(l=1.0, chamfer=1.0) {
|
|
|
|
yrot(90) chamfer_mask_z(l=l, chamfer=chamfer);
|
|
|
|
}
|
2017-08-30 00:00:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Chamfers the edges of a cuboid region containing the given children.
|
2019-02-16 08:55:35 +00:00
|
|
|
// chamfer = Inset of the chamfer from the edge. (Default: 1)
|
2017-08-30 00:00:16 +00:00
|
|
|
// size = The size of the rectangular cuboid we want to chamfer.
|
2019-02-16 08:55:35 +00:00
|
|
|
// edges = Which edges do we want to chamfer. Recommend to use EDGE constants from constants.scad.
|
2017-08-30 00:00:16 +00:00
|
|
|
// [
|
|
|
|
// [Y+Z+, Y-Z+, Y-Z-, Y+Z-],
|
|
|
|
// [X+Z+, X-Z+, X-Z-, X+Z-],
|
|
|
|
// [X+Y+, X-Y+, X-Y-, X+Y-]
|
|
|
|
// ]
|
|
|
|
// Example:
|
2019-02-16 08:55:35 +00:00
|
|
|
// include <BOSL/constants.scad>
|
|
|
|
// chamfer(chamfer=2, size=[10,40,30], edges=EDGE_BOT_BK + EDGE_TOP_RT + EDGE_TOP_LF) {
|
2018-11-26 09:53:02 +00:00
|
|
|
// cube(size=[10,40,30], center=true);
|
2017-08-30 00:00:16 +00:00
|
|
|
// }
|
|
|
|
module chamfer(chamfer=1, size=[1,1,1], edges=[[0,0,0,0], [1,1,0,0], [0,0,0,0]])
|
|
|
|
{
|
|
|
|
eps = 0.1;
|
|
|
|
x = size[0];
|
|
|
|
y = size[1];
|
|
|
|
z = size[2];
|
|
|
|
lx = x + eps;
|
|
|
|
ly = y + eps;
|
|
|
|
lz = z + eps;
|
|
|
|
difference() {
|
|
|
|
union() {
|
|
|
|
children();
|
|
|
|
}
|
|
|
|
union() {
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[0][0] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
up(z/2) back(y/2) chamfer_mask_x(l=lx, chamfer=chamfer);
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[0][1] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
up(z/2) fwd(y/2) chamfer_mask_x(l=lx, chamfer=chamfer);
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[0][2] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
down(z/2) back(y/2) chamfer_mask_x(l=lx, chamfer=chamfer);
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[0][3] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
down(z/2) fwd(y/2) chamfer_mask_x(l=lx, chamfer=chamfer);
|
|
|
|
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[1][0] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
up(z/2) right(x/2) chamfer_mask_y(l=ly, chamfer=chamfer);
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[1][1] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
up(z/2) left(x/2) chamfer_mask_y(l=ly, chamfer=chamfer);
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[1][2] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
down(z/2) right(x/2) chamfer_mask_y(l=ly, chamfer=chamfer);
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[1][3] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
down(z/2) left(x/2) chamfer_mask_y(l=ly, chamfer=chamfer);
|
|
|
|
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[2][0] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
back(y/2) right(x/2) chamfer_mask_z(l=lz, chamfer=chamfer);
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[2][1] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
back(y/2) left(x/2) chamfer_mask_z(l=lz, chamfer=chamfer);
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[2][2] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
fwd(y/2) right(x/2) chamfer_mask_z(l=lz, chamfer=chamfer);
|
2019-02-16 08:55:35 +00:00
|
|
|
if (edges[2][3] > 0)
|
2017-08-30 00:00:16 +00:00
|
|
|
fwd(y/2) left(x/2) chamfer_mask_z(l=lz, chamfer=chamfer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-12-22 10:37:39 +00:00
|
|
|
// Create a mask that can be used to bevel/chamfer the edge of a circular hole.
|
|
|
|
// Difference it from the hole to be chamferred. The center of the mask object
|
|
|
|
// should align exactly with the center of the end of the hole to be chamferred.
|
|
|
|
// r = radius of hole to chamfer.
|
|
|
|
// d = Diameter of hole to chamfer. Use instead of r.
|
|
|
|
// chamfer = size of the edge chamferred. (Default: 0.25)
|
|
|
|
// Example:
|
|
|
|
// $fa=2; $fs=2;
|
|
|
|
// difference() {
|
|
|
|
// cube([150,150,100], center=true);
|
|
|
|
// cylinder(r=50, h=100.1, center=true);
|
|
|
|
// up(50) chamfer_hole_mask(r=50, chamfer=10);
|
|
|
|
// }
|
|
|
|
module chamfer_hole_mask(r=1.0, d=undef, chamfer=0.25)
|
|
|
|
{
|
|
|
|
r = d==undef? r : d/2;
|
|
|
|
down(chamfer) cylinder(r1=r, r2=r+chamfer, h=chamfer+0.01, center=false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create a mask that can be used to bevel/chamfer the end of a cylinder.
|
|
|
|
// Difference it from the cylinder to be chamferred. The center of the mask object
|
|
|
|
// should align exactly with the center of the end of the cylinder to be chamferred.
|
|
|
|
// r = radius of hole to chamfer.
|
|
|
|
// d = Diameter of hole to chamfer. Use instead of r.
|
|
|
|
// chamfer = size of the edge chamferred. (Default: 0.25)
|
|
|
|
// Example:
|
|
|
|
// $fa=2; $fs=2;
|
|
|
|
// difference() {
|
|
|
|
// cylinder(r=50, h=100, center=true);
|
|
|
|
// up(50) chamfer_cylinder_mask(r=50, chamfer=10);
|
|
|
|
// }
|
|
|
|
module chamfer_cylinder_mask(r=1.0, d=undef, chamfer=0.25)
|
|
|
|
{
|
|
|
|
r = d==undef? r : d/2;
|
|
|
|
difference() {
|
|
|
|
cube([2*r+1, 2*r+1, 2*chamfer], center=true);
|
|
|
|
down(chamfer+0.01) cylinder(r1=r, r2=r-chamfer, h=chamfer, center=false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-08-30 00:00:16 +00:00
|
|
|
// Creates a shape that can be used to fillet a vertical 90 degree edge.
|
|
|
|
// Difference it from the object to be filletted. The center of the mask
|
|
|
|
// object should align exactly with the edge to be filletted.
|
|
|
|
// h = height of vertical mask.
|
|
|
|
// r = radius of the fillet.
|
|
|
|
// center = If true, vertically center mask.
|
|
|
|
// Example:
|
|
|
|
// difference() {
|
|
|
|
// cube(size=100, center=false);
|
2018-11-26 09:53:02 +00:00
|
|
|
// up(50) fillet_mask(h=100.1, r=25.0);
|
2017-08-30 00:00:16 +00:00
|
|
|
// }
|
|
|
|
module fillet_mask(h=1.0, r=1.0, center=true)
|
|
|
|
{
|
|
|
|
n = ceil(segs(r)/4)*4;
|
|
|
|
linear_extrude(height=h, convexity=4, center=center) {
|
|
|
|
polygon(
|
|
|
|
points=concat(
|
|
|
|
[for (a = [ 0:360/n: 90]) [r*cos(a)-r, r*sin(a)-r]],
|
|
|
|
[for (a = [270:360/n:360]) [r*cos(a)-r, r*sin(a)+r]],
|
|
|
|
[for (a = [180:360/n:270]) [r*cos(a)+r, r*sin(a)+r]],
|
|
|
|
[for (a = [ 90:360/n:180]) [r*cos(a)+r, r*sin(a)-r]]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2017-08-30 01:57:37 +00:00
|
|
|
module fillet_mask_z(l=1.0, r=1.0) fillet_mask(h=l, r=r, center=true);
|
|
|
|
module fillet_mask_y(l=1.0, r=1.0) xrot(90) fillet_mask(h=l, r=r, center=true);
|
|
|
|
module fillet_mask_x(l=1.0, r=1.0) yrot(90) fillet_mask(h=l, r=r, center=true);
|
2017-08-30 00:00:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Creates a vertical mask that can be used to fillet the edge where two
|
|
|
|
// face meet, at any arbitrary angle. Difference it from the object to
|
|
|
|
// be filletted. The center of the mask should align exactly with the
|
|
|
|
// edge to be filletted.
|
|
|
|
// h = height of vertical mask.
|
|
|
|
// r = radius of the fillet.
|
|
|
|
// ang = angle that the planes meet at.
|
|
|
|
// center = If true, vertically center mask.
|
|
|
|
// Example:
|
2018-11-26 09:53:02 +00:00
|
|
|
// difference() {
|
|
|
|
// angle_pie_mask(ang=70, h=50, d=100);
|
|
|
|
// fillet_angled_edge_mask(h=51, r=20.0, ang=70, $fn=32);
|
|
|
|
// }
|
2017-08-30 01:57:37 +00:00
|
|
|
module fillet_angled_edge_mask(h=1.0, r=1.0, ang=90, center=true)
|
2017-08-30 00:00:16 +00:00
|
|
|
{
|
|
|
|
sweep = 180-ang;
|
|
|
|
n = ceil(segs(r)*sweep/360);
|
|
|
|
x = r*sin(90-(ang/2))/sin(ang/2);
|
|
|
|
linear_extrude(height=h, convexity=4, center=center) {
|
|
|
|
polygon(
|
|
|
|
points=concat(
|
|
|
|
[for (i = [0:n]) let (a=90+ang+i*sweep/n) [r*cos(a)+x, r*sin(a)+r]],
|
|
|
|
[for (i = [0: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],
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Creates a shape that can be used to fillet the corner of an angle.
|
|
|
|
// Difference it from the object to be filletted. The center of the mask
|
|
|
|
// object should align exactly with the point of the corner to be filletted.
|
|
|
|
// fillet = radius of the fillet.
|
|
|
|
// ang = angle between planes that you need to fillet the corner of.
|
|
|
|
// Example:
|
2018-11-26 09:53:02 +00:00
|
|
|
// ang=60;
|
|
|
|
// difference() {
|
|
|
|
// angle_pie_mask(ang=ang, h=50, r=200);
|
|
|
|
// up(50/2) {
|
|
|
|
// fillet_angled_corner_mask(fillet=20, ang=ang);
|
|
|
|
// zrot_copies([0, ang]) right(200/2) fillet_mask_x(l=200, r=20);
|
|
|
|
// }
|
|
|
|
// fillet_angled_edge_mask(h=51, r=20, ang=ang);
|
|
|
|
// }
|
2017-08-30 01:57:37 +00:00
|
|
|
module fillet_angled_corner_mask(fillet=1.0, ang=90)
|
2017-08-30 00:00:16 +00:00
|
|
|
{
|
2018-11-26 09:53:02 +00:00
|
|
|
dx = fillet / tan(ang/2);
|
|
|
|
fn = quantup(segs(fillet), 4);
|
2017-08-30 00:00:16 +00:00
|
|
|
difference() {
|
2018-11-26 09:53:02 +00:00
|
|
|
down(fillet) cylinder(r=dx/cos(ang/2)+1, h=fillet+1, center=false);
|
|
|
|
yflip_copy() {
|
|
|
|
translate([dx, fillet, -fillet]) {
|
|
|
|
hull() {
|
|
|
|
sphere(r=fillet, $fn=fn);
|
|
|
|
down(fillet*3) sphere(r=fillet, $fn=fn);
|
|
|
|
zrot_copies([0,ang]) {
|
|
|
|
right(fillet*3) sphere(r=fillet, $fn=fn);
|
2017-08-30 00:00:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Creates a shape that you can use to round 90 degree corners on a fillet.
|
|
|
|
// Difference it from the object to be filletted. The center of the mask
|
|
|
|
// object should align exactly with the corner to be filletted.
|
|
|
|
// r = radius of corner fillet.
|
|
|
|
// Example:
|
|
|
|
// $fa=1; $fs=1;
|
|
|
|
// difference() {
|
|
|
|
// cube(size=[6,10,16], center=true);
|
|
|
|
// translate([0, 5, 8]) yrot(90) fillet_mask(h=7, r=3);
|
|
|
|
// translate([3, 0, 8]) xrot(90) fillet_mask(h=11, r=3);
|
|
|
|
// translate([3, 5, 0]) fillet_mask(h=17, r=3);
|
2017-08-30 01:57:37 +00:00
|
|
|
// translate([3, 5, 8]) fillet_corner_mask(r=3);
|
2017-08-30 00:00:16 +00:00
|
|
|
// }
|
2017-08-30 01:57:37 +00:00
|
|
|
module fillet_corner_mask(r=1.0)
|
2017-08-30 00:00:16 +00:00
|
|
|
{
|
|
|
|
difference() {
|
|
|
|
cube(size=r*2, center=true);
|
|
|
|
grid_of(count=[2,2,2], spacing=r*2-0.05) {
|
|
|
|
sphere(r=r, center=true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-08-30 01:57:37 +00:00
|
|
|
//!fillet_corner_mask(r=10.0);
|
2017-08-30 00:00:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Create a mask that can be used to round the end of a cylinder.
|
|
|
|
// Difference it from the cylinder to be filletted. The center of the
|
|
|
|
// mask object should align exactly with the center of the end of the
|
|
|
|
// cylinder to be filletted.
|
|
|
|
// r = radius of cylinder to fillet. (Default: 1.0)
|
|
|
|
// fillet = radius of the edge filleting. (Default: 0.25)
|
|
|
|
// xtilt = angle of tilt of end of cylinder in the X direction. (Default: 0)
|
|
|
|
// ytilt = angle of tilt of end of cylinder in the Y direction. (Default: 0)
|
|
|
|
// Example:
|
|
|
|
// $fa=2; $fs=2;
|
|
|
|
// difference() {
|
|
|
|
// cylinder(r=50, h=100, center=true);
|
2018-11-26 09:53:02 +00:00
|
|
|
// up(50) !fillet_cylinder_mask(r=50, fillet=10, xtilt=30);
|
2017-08-30 00:00:16 +00:00
|
|
|
// }
|
|
|
|
module fillet_cylinder_mask(r=1.0, fillet=0.25, xtilt=0, ytilt=0)
|
|
|
|
{
|
|
|
|
dhx = 2*r*sin(xtilt);
|
|
|
|
dhy = 2*r*sin(ytilt);
|
|
|
|
dh = hypot(dhy, dhx);
|
|
|
|
down(dh/2) {
|
2018-11-26 09:53:02 +00:00
|
|
|
skew_xz(za=xtilt) {
|
|
|
|
skew_yz(za=ytilt) {
|
2017-08-30 00:00:16 +00:00
|
|
|
down(fillet) {
|
|
|
|
difference() {
|
|
|
|
up((dh+2*fillet)/2) {
|
|
|
|
cube(size=[r*2+10, r*2+10, dh+2*fillet], center=true);
|
|
|
|
}
|
|
|
|
torus(or=r, ir=r-2*fillet);
|
|
|
|
cylinder(r=r-fillet, h=2*fillet, center=true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create a mask that can be used to round the edge of a circular hole.
|
|
|
|
// Difference it from the hole to be filletted. The center of the
|
|
|
|
// mask object should align exactly with the center of the end of the
|
|
|
|
// hole to be filletted.
|
|
|
|
// r = radius of hole to fillet. (Default: 1.0)
|
|
|
|
// fillet = radius of the edge filleting. (Default: 0.25)
|
|
|
|
// xtilt = angle of tilt of end of cylinder in the X direction. (Default: 0)
|
|
|
|
// ytilt = angle of tilt of end of cylinder in the Y direction. (Default: 0)
|
|
|
|
// Example:
|
|
|
|
// $fa=2; $fs=2;
|
|
|
|
// difference() {
|
|
|
|
// cube([150,150,100], center=true);
|
|
|
|
// cylinder(r=50, h=100.1, center=true);
|
|
|
|
// up(50) fillet_hole_mask(r=50, fillet=10, xtilt=0, ytilt=0);
|
|
|
|
// }
|
|
|
|
module fillet_hole_mask(r=1.0, fillet=0.25, xtilt=0, ytilt=0)
|
|
|
|
{
|
2018-12-22 10:37:39 +00:00
|
|
|
skew_xz(za=xtilt) {
|
|
|
|
skew_yz(za=ytilt) {
|
2017-08-30 00:00:16 +00:00
|
|
|
difference() {
|
|
|
|
cylinder(r=r+fillet, h=2*fillet, center=true);
|
|
|
|
down(fillet) torus(ir=r, or=r+2*fillet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|