2019-07-12 05:57:43 +00:00
//////////////////////////////////////////////////////////////////////
// LibFile: knurling.scad
// Shapes and masks for knurling cylinders.
2021-01-05 09:20:01 +00:00
// Includes:
2019-07-12 05:57:43 +00:00
// include <BOSL2/std.scad>
2021-01-05 09:54:15 +00:00
// include <BOSL2/knurling.scad>
2021-12-13 23:48:30 +00:00
// FileGroup: Parts
// FileSummary: Masks and shapes to create knurling.
2019-07-12 05:57:43 +00:00
//////////////////////////////////////////////////////////////////////
// Section: Knurling
// Module: knurled_cylinder()
// Usage:
2022-04-09 00:17:41 +00:00
// knurled_cylinder(l|h|height, r|d=, [count=], [profile=], [helix=]);
// knurled_cylinder(l|h|height, r1=|d1=, r2=|d2=, [count=], [profile=], [helix=]);
2019-07-12 05:57:43 +00:00
// Description:
2022-04-09 00:17:41 +00:00
// Creates a knurled cylinder. The knurling is made from small bumps (pyramids) arranged on the surface.
// The
2019-07-12 05:57:43 +00:00
// Arguments:
2022-04-09 00:17:41 +00:00
// l / h / height = The length/height of the cylinder
// r = The radius of the cylinder to knurl.
2019-07-12 05:57:43 +00:00
// r1 = The radius of the bottom of the conical cylinder to knurl.
// r2 = The radius of the top of the conical cylinder to knurl.
// d = The diameter of the cylinder to knurl.
// d1 = The diameter of the bottom of the conical cylinder to knurl.
// d2 = The diameter of the top of the conical cylinder to knurl.
2022-04-09 00:17:41 +00:00
// count = The number of bumps filling one revolution of the cylinder. Default: 30
// profile = The lower angle between the pyramid-shaped bumps. Smaller angles make the bumps sharper and can lead to bad models if count is small. Default 120
// helix = The helical angle of the bumps, in degrees. Close to zero produces vertical ribbing. Close to 90 degrees produces very thin bumps and is not recommended. Default: 30
2019-07-12 19:59:18 +00:00
// chamfer = The size of the chamfers on the ends of the cylinder. Default: none.
// chamfer1 = The size of the chamfer on the bottom end of the cylinder. Default: none.
// chamfer2 = The size of the chamfer on the top end of the cylinder. Default: none.
// chamfang = The angle in degrees of the chamfers on the ends of the cylinder.
// chamfang1 = The angle in degrees of the chamfer on the bottom end of the cylinder.
// chamfang2 = The angle in degrees of the chamfer on the top end of the cylinder.
// from_end = If true, chamfer is measured from the end of the cylinder, instead of inset from the edge. Default: `false`.
// rounding = The radius of the rounding on the ends of the cylinder. Default: none.
// rounding1 = The radius of the rounding on the bottom end of the cylinder.
// rounding2 = The radius of the rounding on the top end of the cylinder.
2021-11-20 03:33:16 +00:00
// 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. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
2019-08-09 03:27:55 +00:00
// Examples(Med):
2019-07-12 19:59:18 +00:00
// knurled_cylinder(l=30, r=20, count=30, profile=120, helix=45);
// knurled_cylinder(l=30, r=20, count=30, profile=120, helix=30);
// knurled_cylinder(l=30, r=20, count=30, profile=90, helix=30);
// knurled_cylinder(l=30, r=20, count=20, profile=120, helix=30);
2022-04-09 00:17:41 +00:00
// knurled_cylinder(l=30, r=20, count=20, profile=120, helix=0.01);
// knurled_cylinder(l=30, r=20, count=20, profile=140, helix=60);
2022-04-09 03:04:10 +00:00
// knurled_cylinder(l=30, r1=20, r2=12, count=40, profile=90, helix=55);
2019-07-12 05:57:43 +00:00
module knurled_cylinder (
2022-04-09 00:17:41 +00:00
l ,
2020-05-30 02:04:34 +00:00
r = undef , r1 = undef , r2 = undef ,
d = undef , d1 = undef , d2 = undef ,
count = 30 , profile = 120 , helix = 30 ,
chamfer = undef , chamfer1 = undef , chamfer2 = undef ,
chamfang = undef , chamfang1 = undef , chamfang2 = undef ,
from_end = false ,
rounding = undef , rounding1 = undef , rounding2 = undef ,
2022-04-09 00:17:41 +00:00
anchor = CENTER , spin = 0 , orient = UP ,
height , h
2019-07-12 05:57:43 +00:00
) {
2022-04-09 00:17:41 +00:00
assert ( is_finite ( helix ) && helix > 0 && helix < 90 , "Must give helix angle between 0 and 90" ) ;
assert ( is_finite ( profile ) && profile > 0 && profile < 180 , "Must give profile between 0 and 180" ) ;
l = one_defined ( [ l , h , height ] , "l,h,height" ) ;
2020-05-30 02:04:34 +00:00
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 ) ;
inset = r1 * sin ( 180 / count ) / tan ( profile / 2 ) ;
twist = 360 * l * tan ( helix ) / ( r1 * 2 * PI ) ;
c1 = circle ( r = r1 , $fn = count ) ;
c2 = rot ( - 180 / count , p = circle ( r = r1 - inset , $fn = count ) ) ;
path = [ for ( i = idx ( c1 ) ) each [ c1 [ i ] , c2 [ i ] ] ] ;
knob_w = 2 * PI * r1 / count ;
knob_h = knob_w / tan ( helix ) ;
layers = ceil ( l / knob_h ) ;
plen = len ( path ) ;
vertices = concat (
[
for ( layer = [ 0 : 1 : layers ] , pt = path )
2022-04-09 03:04:10 +00:00
let ( scale_factor = lerp ( 1 , r2 / r1 , layer / layers ) )
scale ( [ scale_factor , scale_factor , 1 ] ,
( layer % 2 ) ? [ pt . x , pt . y , layer * knob_h - layers * knob_h / 2 ] :
rot ( 180 / count , p = [ pt . x , pt . y , layer * knob_h - layers * knob_h / 2 ] )
)
2020-05-30 02:04:34 +00:00
] , [
[ 0 , 0 , - layers * knob_h / 2 ] ,
[ 0 , 0 , layers * knob_h / 2 ]
]
) ;
faces = concat (
[
for ( layer = [ 0 : 1 : layers - 1 ] , i = idx ( path ) ) let (
loff = ( layer % 2 ) ? 2 : 0 ,
i1 = layer * plen + ( ( i + 1 ) % plen ) ,
i2 = layer * plen + ( ( i + 2 ) % plen ) ,
i3 = ( layer + 1 ) * plen + posmod ( i + 1 + loff , plen ) ,
i4 = ( layer + 1 ) * plen + posmod ( i + 2 + loff , plen ) ,
i5 = ( layer + 1 ) * plen + posmod ( i - 0 + loff , plen ) ,
i6 = ( layer + 1 ) * plen + posmod ( i - 1 + loff , plen )
) each [
[ i1 , i2 , ( ( i % 2 ) ? i5 : i3 ) ] ,
[ i3 , i5 , ( ( i % 2 ) ? i2 : i1 ) ]
]
] , [
for ( i = [ 0 : 1 : count - 1 ] ) let (
i1 = posmod ( i * 2 + 1 , plen ) ,
i2 = posmod ( i * 2 + 2 , plen ) ,
i3 = posmod ( i * 2 + 3 , plen ) ,
loff = layers * plen
) each [
[ i1 , i3 , i2 ] ,
[ i1 + loff , i2 + loff , i3 + loff ] ,
[ i3 , i1 , len ( vertices ) - 2 ] ,
[ i1 + loff , i3 + loff , len ( vertices ) - 1 ]
]
]
) ;
attachable ( anchor , spin , orient , r1 = r1 , r2 = r2 , l = l ) {
intersection ( ) {
polyhedron ( points = vertices , faces = faces , convexity = 2 * layers ) ;
cyl (
r1 = r1 , r2 = r2 , l = l ,
chamfer = chamfer , chamfer1 = chamfer1 , chamfer2 = chamfer2 ,
chamfang = chamfang , chamfang1 = chamfang1 , chamfang2 = chamfang2 ,
from_end = from_end ,
rounding = rounding , rounding1 = rounding1 , rounding2 = rounding2 ,
$fn = count * 2
) ;
}
children ( ) ;
}
2019-07-12 05:57:43 +00:00
}
// Module: knurled_cylinder_mask()
// Usage:
2022-04-09 00:17:41 +00:00
// knurled_cylinder_mask(l|h|height, r|d=, [overage], [count], [profile], [helix]) [ATTACHMENTS];
// knurled_cylinder_mask(l|h|height, r=1|d1=, r2=|d2=, [overage=], [count=], [profile=], [helix=],...) [ATTACHMENTS];
2019-07-12 05:57:43 +00:00
// Description:
// Creates a mask to difference from a cylinder to give it a knurled surface.
// Arguments:
2022-04-09 00:17:41 +00:00
// l = The length of the axis of the mask.
// r = The radius of the cylinder to knurl.
2019-07-12 05:57:43 +00:00
// overage = Extra backing to the mask. Default: 5
2022-04-09 00:17:41 +00:00
// ---
2019-07-12 05:57:43 +00:00
// r1 = The radius of the bottom of the conical cylinder to knurl.
// r2 = The radius of the top of the conical cylinder to knurl.
// d = The diameter of the cylinder to knurl.
// d1 = The diameter of the bottom of the conical cylinder to knurl.
// d2 = The diameter of the top of the conical cylinder to knurl.
2022-04-09 00:17:41 +00:00
// count = The number of bumps filling one revolution of the cylinder. Default: 30
// profile = The lower angle between the pyramid-shaped bumps. Smaller angles make the bumps sharper and can lead to bad models if count is small. Default 120
// helix = The helical angle of the bumps, in degrees. Close to zero produces vertical ribbing. Close to 90 degrees produces very thin bumps and is not recommended. Default: 30
2021-11-20 03:33:16 +00:00
// 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. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
2019-07-12 05:57:43 +00:00
// Examples:
// knurled_cylinder_mask(l=30, r=20, overage=5, profile=120, helix=30);
// knurled_cylinder_mask(l=30, r=20, overage=10, profile=120, helix=30);
module knurled_cylinder_mask (
2022-04-09 00:17:41 +00:00
l , r , overage = 5 ,
r1 = undef , r2 = undef ,
2020-05-30 02:04:34 +00:00
d = undef , d1 = undef , d2 = undef ,
count = 30 , profile = 120 , helix = 30 ,
2022-04-09 00:17:41 +00:00
anchor = CENTER , spin = 0 , orient = UP , height , h
2019-07-12 05:57:43 +00:00
) {
2022-04-09 00:17:41 +00:00
l = one_defined ( [ l , h , height ] , "l,h,height" ) ;
2020-05-30 02:04:34 +00:00
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 ) ;
attachable ( anchor , spin , orient , r1 = r1 , r2 = r2 , l = l ) {
difference ( ) {
cylinder ( r1 = r1 + overage , r2 = r2 + overage , h = l , center = true ) ;
2022-04-09 00:17:41 +00:00
knurled_cylinder ( r1 = r1 , r2 = r2 , l = l + 0.01 , profile = profile , helix = helix , count = count ) ;
2020-05-30 02:04:34 +00:00
}
children ( ) ;
}
2019-07-12 05:57:43 +00:00
}
2020-05-30 02:04:34 +00:00
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap