2024-04-01 14:55:15 +10:30
include < common.scad >
include < AluTCommon.scad >
semitone_strings = [ "0" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "X" , "XI" ] ;
octave_strings = [ "" , "˙" , "¨" , "¯" ] ;
octave_scales = [ 1.1 , 1 , 0.9 , 0.8 ] ;
2024-04-01 20:19:34 +10:30
z_resolution = $ preview ? 0.5 : 0.1 ;
2024-04-01 23:31:40 +10:30
profile_arc_steps_backside = $ preview ? 8 : 180 ;
profile_arc_steps_topside = $ preview ? 8 : 20 ;
2024-04-01 14:55:15 +10:30
// $fn = $preview ? 32 : 512;
// mink_fn = $preview ? 12 : 128;
// mink_fn_2d = $preview ? 32 : 256;
2024-04-01 20:19:34 +10:30
// $fn = 32;
// mink_fn = 12;
// mink_fn_2d = 32;
2024-04-01 14:55:15 +10:30
fret_width = 2.4 ; //2.8; // Jumbo = 0.11", 0.055" tall
2024-04-01 20:19:34 +10:30
zero_fret_width = fret_width * 1.5 ;
zero_fret_extra_height = 1.2 ;
fret_angle = 60 ; //Fret angle of 45° is normal, anything over 60 will not work correctly
2024-04-01 14:55:15 +10:30
tube_radius = Cap_Spine + T_circumcenter [ 0 ] ;
2024-04-01 20:19:34 +10:30
standard_profile_center_x = T_circumcenter [ 0 ] ;
2024-04-01 23:31:40 +10:30
x_min = standard_profile_center_x - tube_radius ;
standard_y_width = 26.4517 ;
2024-04-01 14:55:15 +10:30
2024-04-01 20:19:34 +10:30
module tube ( from_fret , to_fret , scale_offset = 0 , fingerboard_min_thick = 2.5 , fingerboard_max_thick = 5 ) {
2024-04-01 14:55:15 +10:30
function fsl ( fret_number ) = fret_scale_length ( fret_number + scale_offset ) ;
2024-04-01 23:31:40 +10:30
z0 = fsl ( 0 ) ;
function get_desired_width_scale ( z ) = 2.0 - ( z / z0 ) ;
function get_desired_profile_radius ( ws ) =
let (
x = fingerboard_max_thick ,
y = standard_y_width * 0.5 * ws ,
cc = tri_circumcenter ( [ [ x , - y ] , [ x , y ] , [ x_min , 0 ] ] )
)
cc [ 0 ] - x_min ;
2024-04-01 20:19:34 +10:30
z_min = fsl ( to_fret ) - fret_width / 2 ;
z_max = fsl ( from_fret ) + zero_fret_width / 2 ;
2024-04-01 14:55:15 +10:30
z_offset = z_min ;
Cap_Length = z_max - z_min ;
echo ( str ( "Cap length from fret " , from_fret , " to " , to_fret , " is " , Cap_Length , "mm" ) ) ;
2024-04-01 20:19:34 +10:30
module solid_tube ( cap_taper = 1.5 ) {
function get_x_max ( z ) =
let (
fret_num = mm_to_fret_number ( z ) - scale_offset ,
nearest_fret = round ( fret_num ) ,
nearest_fret_height = fingerboard_max_thick + ( ( nearest_fret = = 0 ) ? zero_fret_extra_height : 0 ) ,
nearest_fret_mm = fsl ( nearest_fret )
)
z ;
2024-04-01 23:31:40 +10:30
module outline_xy ( width_scale = 1.0 , x_max = fingerboard_max_thick , rounding_radius = 1.5 , backside = true , topside = true ) {
profile_radius = get_desired_profile_radius ( width_scale ) ;
profile_radius_scale = profile_radius / tube_radius ;
2024-04-01 20:19:34 +10:30
profile_center_x = ( profile_radius_scale - 1.0 ) * tube_radius + standard_profile_center_x ;
2024-04-01 23:31:40 +10:30
// Backside should join up relatively straight across the whole mesh
a_backside_start = acos ( ( - 2 - profile_center_x ) / profile_radius ) ;
a_backside_end = 360 - a_backside_start ;
a_backside_step = ( a_backside_end - a_backside_start ) / profile_arc_steps_backside ;
// Frontside should have very detailed topology
a_topside_start = acos ( ( x_max - profile_center_x ) / profile_radius ) ;
a_topside_end = 360 - a_topside_start ;
a_topside_step = ( a_backside_start - a_topside_start ) / profile_arc_steps_topside ;
2024-04-01 20:19:34 +10:30
function pt ( a ) = [ profile_center_x + profile_radius * cos ( a ) , profile_radius * sin ( a ) ] ;
2024-04-01 23:31:40 +10:30
backside_points = backside ? [ for ( i = [ 0 : profile_arc_steps_backside ] ) pt ( a_backside_start + i * a_backside_step ) ] : [ ] ;
topside_points_1 = topside ? [ for ( i = [ 0 : profile_arc_steps_topside ] ) pt ( a_topside_start + i * a_topside_step ) ] : [ ] ;
topside_points_2 = topside ? [ for ( i = [ 0 : profile_arc_steps_topside ] ) pt ( a_backside_end + i * a_topside_step ) ] : [ ] ;
polygon ( points = concat ( topside_points_1 , backside_points , topside_points_2 ) ) ;
top_width = pt ( a_topside_start ) [ 1 ] * 2 ;
echo ( str ( "WScale=" , width_scale , " PScale=" , profile_radius_scale , " r=" , profile_radius , " has top width of " , top_width , " divides to " , top_width / width_scale , " (goal is 26.4517)" ) ) ;
2024-04-01 14:55:15 +10:30
}
module fret_bumps ( w = 100 ) {
2024-04-01 20:19:34 +10:30
translate ( [ fingerboard_max_thick - fret_width / 2 , w / 2 , - z_offset + fsl ( from_fret ) ] )
rotate ( [ 90 , 0 , 0 ] ) cylinder ( h = w , r = zero_fret_width / 2 , $fn = 32 ) ;
translate ( [ fingerboard_max_thick - fret_width / 2 , w / 2 , - z_offset ] )
for ( fret = [ from_fret + 1 : to_fret ] )
translate ( [ 0 , 0 , fsl ( fret ) ] )
rotate ( [ 90 , 0 , 0 ] ) cylinder ( h = w , r = fret_width / 2 , $fn = 32 ) ;
2024-04-01 14:55:15 +10:30
}
module scallops ( w = 100 ) {
2024-04-01 20:19:34 +10:30
// for (fret = [from_fret:to_fret+1])
for ( fret = [ from_fret : to_fret ] )
2024-04-01 14:55:15 +10:30
let (
f_prev = fsl ( fret - 1 ) - z_offset ,
f_next = fsl ( fret ) - z_offset ,
o = fret_width / 2 * sin ( fret_angle ) ,
x0 = f_prev - o ,
x1 = f_next + o ,
y0 = fingerboard_min_thick ,
y1 = fingerboard_max_thick - ( fret_width / 2 * cos ( fret_angle ) ) ,
pts = [ [ x0 , y1 ] , [ x1 , y1 ] , [ ( x0 + x1 ) / 2 , y0 ] ] ,
cc = tri_circumcenter ( pts ) ,
r = norm ( [ x0 , y1 ] - cc )
) {
translate ( [ 0 , - w / 2 , 0 ] )
rotate ( [ - 90 , - 90 , 0 ] )
translate ( cc ) cylinder ( h = w , r = r ) ;
}
}
module basic_fretboard ( ) {
intersection ( ) {
hull ( ) {
2024-04-01 23:31:40 +10:30
translate ( [ 0 , 0 , Cap_Length ] ) linear_extrude ( 0.001 ) outline_xy ( get_desired_width_scale ( z_max ) , topside = true ) ;
translate ( [ 0 , 0 , 0 ] ) linear_extrude ( 0.001 ) outline_xy ( get_desired_width_scale ( z_min ) , topside = true ) ;
2024-04-01 14:55:15 +10:30
}
union ( ) {
color ( "black" ) fret_bumps ( ) ;
color ( "white" , alpha = 0.01 ) translate ( [ - 50 , - 50 , 0 ] ) cube ( [ 50 + fingerboard_max_thick - ( fret_width / 2 * cos ( fret_angle ) ) , 100 , Cap_Length ] ) ;
}
}
}
// Make a solid tube and then subtract the notches
difference ( ) {
basic_fretboard ( ) ;
difference ( ) {
color ( "red" ) scallops ( ) ;
color ( "blue" ) fret_bumps ( ) ;
}
}
// color("red") scallops();
}
2024-04-01 23:31:40 +10:30
module fret_number_markers ( engrave_depth = 1 ) {
color ( "purple" )
// for (fret = [from_fret:to_fret])
for ( fret = [ from_fret + 1 : to_fret ] ) {
zn = fsl ( fret ) ;
pr = get_desired_profile_radius ( get_desired_width_scale ( zn ) ) ;
octave = floor ( fret / 12 ) ;
semitone = fret % 12 ;
octave_scale = octave_scales [ octave ] ;
// translate([-3,-16,zn-z_offset]) rotate([90,25,16]) linear_extrude(100) {
// translate([-3,-16,zn-z_offset]) rotate([90,25,-16+16*(zn/z0)]) linear_extrude(100) {
p_x0 = pr + x_min ;
translate ( [ p_x0 , 0 , zn - z_offset ] ) rotate ( [ 90 , 25 , - asin ( ( p_x0 + 2 ) / pr ) ] ) translate ( [ 0 , 0 , pr - engrave_depth ] ) linear_extrude ( engrave_depth + 1 ) {
text ( semitone_strings [ semitone ] , size = 4 * octave_scale , halign = "center" , valign = "center" , font = "Noto Sans" ) ;
text ( octave_strings [ octave ] , size = 6 * octave_scale , halign = "center" , valign = "center" , font = "Noto Sans" ) ;
}
translate ( [ p_x0 , 0 , zn - z_offset ] ) rotate ( [ 90 , - 25 , 180 + asin ( ( p_x0 + 2 ) / pr ) ] ) translate ( [ 0 , 0 , pr - engrave_depth ] ) linear_extrude ( engrave_depth + 1 ) {
text ( semitone_strings [ semitone ] , size = 4 * octave_scale , halign = "center" , valign = "center" , font = "Noto Sans" ) ;
text ( octave_strings [ octave ] , size = 6 * octave_scale , halign = "center" , valign = "center" , font = "Noto Sans" ) ;
}
}
}
2024-04-01 14:55:15 +10:30
difference ( ) {
solid_tube ( 1.5 ) ;
linear_extrude ( Cap_Length ) T_hole ( ) ;
2024-04-01 23:31:40 +10:30
fret_number_markers ( ) ;
2024-04-01 14:55:15 +10:30
tapered_T_hole ( z0 = 0 , z1 = 3 ) ;
tapered_T_hole ( z0 = Cap_Length - 3 , z1 = Cap_Length + 0.0001 , o0 = 0 , o1 = 1 ) ;
// Version number
translate ( [ - 10 , 10 , Cap_Length - 0.5 ] ) linear_extrude ( 1 ) text ( "06" , size = 5 , halign = "center" , valign = "center" , font = "Noto Sans" ) ;
}
}
tube ( from_fret = 0 , to_fret = 36 , scale_offset = - 5 ) ;
//translate([50, 0]) tube(from_fret = -4, to_fret = -3);
//translate([100, 0]) tube(from_fret = -2, to_fret = 0);
//translate([150, 0]) tube(from_fret = 1, to_fret = 3);
//translate([200, 0]) tube(from_fret = 4, to_fret = 7);
//translate([250, 0]) tube(from_fret = 8, to_fret = 12);
//translate([300, 0]) tube(from_fret = 13, to_fret = 19);
//translate([350, 0]) tube(from_fret = 20, to_fret = 30);