From 9735e48126175e115c1f7aea25df5118257d3072 Mon Sep 17 00:00:00 2001 From: Luke Hubmayer-Werner Date: Fri, 3 Jan 2025 18:20:30 +1030 Subject: [PATCH] PETG Classical guitar neck 1alpha --- CFTubes.scad | 111 ++++++++++++++++++++++++++++++++++---------- CFTubes/common.scad | 70 ++++++++++++++++++++++++++++ common.scad | 10 ++++ 3 files changed, 166 insertions(+), 25 deletions(-) diff --git a/CFTubes.scad b/CFTubes.scad index 51d17a8..92531cf 100644 --- a/CFTubes.scad +++ b/CFTubes.scad @@ -343,35 +343,61 @@ module bridge(string_spacing=18, string_margin=4.5, num_strings=3, target_neck_t module Nylon6String() { fsl_mm = fret_scale_length(0); - echo(str("Making a Nylon 6 String with scale length ", fsl_mm, "mm = ", fsl_mm/25.4, "in")) - assert(fsl_mm == Classical_Short_Scale_mm); // Make sure the function correctly uses our changed global + + string_diameters_thous = [28, 32, 40, 30, 36, 42]; + string_diameters_mm = string_diameters_thous * 0.0254; num_frets = 20; num_strings = 6; // 56mm wide neck string_spacing = 10; // 50mm E to e string_margin = 3; // +6 + neck_width = string_spacing*(num_strings-1) + string_margin*2; scallop_depth = 2.5; target_neck_thickness = 22; fret_width=2.4; + echo(str("Making a Nylon 6 String with scale length ", fsl_mm, "mm = ", fsl_mm/25.4, "in and neck width ", neck_width, "mm")); + assert(fsl_mm == Classical_Short_Scale_mm); // Make sure the function correctly uses our changed global + + function CF_Span_Coords(full_length = 700, ply = 3) = [for (i=[0:ply-1]) [0, lerp(0, full_length-CF_Tube_Len, i/(ply-1)), CF_Square_Width*i]]; + module CF_Span(full_length = 700, ply = 3, hole = true) { + for (v = CF_Span_Coords(full_length, ply)) + translate(v) CFSquare(hole=hole); + } + + reinforcing_tube_positions = flatten([ + [ + for (i=[-1,1]) each [ + // Headside reinforcement + [i*21, -40+280, -4], + [i*17, -40+280, -12], + // Bridgeside reinforcement + [i*16, -40, -7], + ] + ], + [ + // Bridgeside reinforcement + [0, -40, -4], + [0, -40, -15], + ]]); + echo(reinforcing_tube_positions); + // Through span construction + span_coords = CF_Span_Coords(); + reinforcing_square_positions = [ + for (i=[-1,1]) each [ for (v = span_coords) [i*10, -40, -16] + v ] + ]; + echo(reinforcing_square_positions); + // neck(num_frets=num_frets, num_strings=num_strings, string_margin=string_margin, string_spacing=string_spacing); - module CF_Span(full_length = 700, ply = 3, hole = true) { - for (i=[0:ply-1]) - translate([0, lerp(0, full_length-CF_Tube_Len, i/(ply-1)), CF_Square_Width*i]) CFSquare(hole=hole); - } - // for (m=[0,11]) mirror([m, 0, 0]) color([0.4, 0.5, 0.5]) translate([9, -40, -16]) CF_Span(); - // CFTube(); // %neck(num_frets=num_frets, num_strings=num_strings, string_margin=string_margin, string_spacing=string_spacing, scallop_depth=scallop_depth, target_neck_thickness=target_neck_thickness); - module NeckFragment(from_fret, to_fret, to_origin=true, include_from_fret=false) { + module NeckFragment(from_fret, to_fret, to_origin=true, include_from_fret=false, test_tolerances_piece=false) { x0 = fret_scale_length(to_fret) - fret_width/2; x1 = fret_scale_length(from_fret) + ((include_from_fret)?1:(-1)) * fret_width/2; xn = fsl_mm + fret_width; - translate([0,to_origin ? -x0 : 0,0]) render() difference() { - neck(num_frets=num_frets, num_strings=num_strings, string_margin=string_margin, string_spacing=string_spacing, scallop_depth=scallop_depth, target_neck_thickness=target_neck_thickness); - translate([-100, 0, -100]) cube([200, x0, 200]); - translate([-100, x1, -100]) cube([200, xn-x1, 200]); + + module TestTolerancesPiece() { for (m=[0,11]) mirror([m, 0, 0]) color([0.4, 0.5, 0.5]) translate([9, 0, -16+(CF_Square_Width*2)]) CFSquareCutout(x0, x1, taper_length=2); translate([ 12,0,-14]) CFSquareCutout(x0, x1, taper_length=2); translate([ 12-CF_Square_Width,0,-14]) CFSquareCutout(x0, x1-8, taper_length=2, taper_x2=false); @@ -379,22 +405,57 @@ module Nylon6String() { translate([-12+CF_Square_Width,0,-14]) CFSquareCutout(x0+8, x1, taper_length=2, taper_x1=false); translate([20,0,-6]) CFTubeCutout(x0, x1, taper_length=2); } - } - difference(){ - NeckFragment(2, 3); - translate([-20,0,-1]) rotate([-90,180,180]) linear_extrude(3, center=true) text("PETG", size=3.5, halign="center", valign="center"); - translate([-20,0,-6]) rotate([-90,180,180]) linear_extrude(3, center=true) text("1α", size=3.5, halign="center", valign="center"); + + translate([0,to_origin ? -x0 : 0,0]) render() difference() { + neck(num_frets=num_frets, num_strings=num_strings, string_margin=string_margin, string_spacing=string_spacing, scallop_depth=scallop_depth, target_neck_thickness=target_neck_thickness); + translate([-100, 0, -100]) cube([200, x0, 200]); + translate([-100, x1, -100]) cube([200, xn-x1, 200]); + for (v = reinforcing_tube_positions) CFTubeCutout2(v, x0, x1); + for (v = reinforcing_square_positions) CFSquareCutout2(v, x0, x1); + if (test_tolerances_piece) TestTolerancesPiece(); + } } - // translate([0,0,30]) difference() { - // neck(num_frets=num_frets, num_strings=num_strings, string_margin=string_margin, string_spacing=string_spacing, scallop_depth=scallop_depth, target_neck_thickness=target_neck_thickness); - // for (m=[0,11]) mirror([m, 0, 0]) color([0.4, 0.5, 0.5]) translate([9, -40, -16]) CF_Span(hole=false); - // } + // Test tolerances piece + module TestTolerancesPiece() { + difference(){ + NeckFragment(2, 3, test_tolerances_piece=true); + translate([-20,0,-1]) rotate([-90,180,180]) linear_extrude(3, center=true) text("PETG", size=3.5, halign="center", valign="center"); + translate([-20,0,-6]) rotate([-90,180,180]) linear_extrude(3, center=true) text("1α", size=3.5, halign="center", valign="center"); + } + } + // TestTolerancesPiece(); - // for (m=[0,11]) mirror([m, 0, 0]) translate([29,10,-32]) rotate([0,-90,0]) NylonTuner(); + module RealPiece(from_fret, to_fret, include_from_fret=false) { + midpoint = (fret_scale_length(from_fret) - fret_scale_length(to_fret) + (include_from_fret ? fret_width : 0))/2; + render() difference(){ + NeckFragment(from_fret, to_fret, include_from_fret=include_from_fret); + color("red") for (ra = [[0,0,0], [0,0,180]]) rotate_around(ra, [0,midpoint,0]) + translate([0,0,-9]) rotate([-90,180,180]) linear_extrude(3, center=true) text("PETG1α", size=2.5, halign="center", valign="center"); + } + } + RealPiece(0, 8, include_from_fret=true); + %translate([100, 0, 0]) RealPiece(8, 21); + + %translate([-100,0,0]) union() { + c_cf = [0.4, 0.5, 0.5]; + %neck(num_frets=num_frets, num_strings=num_strings, string_margin=string_margin, string_spacing=string_spacing, scallop_depth=scallop_depth, target_neck_thickness=target_neck_thickness); + // CF square stacks + for (v = reinforcing_tube_positions) color(c_cf) translate(v) CFTube(); + for (v = reinforcing_square_positions) color(c_cf) translate(v) CFSquare(); + // Approximate tuner placement + for (m=[0,1]) mirror([m, 0, 0]) translate([29,10,-32]) rotate([0,-90,0]) NylonTuner(); + + // Render strings above for spacing reference + string_excess = 80; + for (i = [0:num_strings-1]) { + translate([(num_strings-i-1)*string_spacing - neck_width/2 + string_margin,0,5]) rotate([-90,0,0]) translate([0,0,-string_excess/2]) cylinder(h=fsl_mm+string_excess, d=string_diameters_mm[i], $fn=cyl_ld_fn); + } + } // Debug markers to aid part slicing eyeballing - for (i = [150:250:1000]) { - %translate([50,i,0]) union() {text(str(i, "mm")); cube([50, 1, 1], center=true);} + // %for (i = [150:250:1000]) { + %for (i = [0:250:1000]) { + translate([50,i,0]) union() {text(str(i, "mm")); cube([50, 1, 1], center=true);} } } diff --git a/CFTubes/common.scad b/CFTubes/common.scad index 12c7350..00da332 100644 --- a/CFTubes/common.scad +++ b/CFTubes/common.scad @@ -73,3 +73,73 @@ module CFSquareCutout(x1, x2, tolerance = CF_Square_Width_tolerance, taper_x1 = } } } + +module CFTubeCutout2(v, block_y0, block_y1, tolerance = CF_Tube_OD_tolerance, VLH = false, taper_length = 2, taper_mul = 1.1) { + // Alternate approach: supply start vector v, and the bounding y values of the piece, taper on entry points only. + tolerance = tolerance + (VLH ? 0.3 : 0); + tube_y0 = v[1]; + tube_y1 = tube_y0 + CF_Tube_Len; + OD = CF_Tube_OD + tolerance; + taper_OD = (CF_Tube_OD*taper_mul) + tolerance; + + fn = 360; + // Full cylinder, unconditional + translate(v) + rotate([-90,0,0]) cylinder(h=CF_Tube_Len, d=OD, $fn=fn); + // Check for tapered holes + if ((block_y0 >= tube_y0) && (block_y0 < tube_y1)) // Tube protrudes through start of block + hull() { + translate([v[0], block_y0, v[2]]) + rotate([-90,0,0]) cylinder(h=hull_epsilon, d=taper_OD, $fn=fn); + translate([v[0], block_y0+taper_length, v[2]]) + rotate([-90,0,0]) cylinder(h=hull_epsilon, d=OD, $fn=fn); + } + if ((block_y1 <= tube_y1) && (block_y1 > tube_y0)) // Tube protrudes through end of block + hull() { + translate([v[0], block_y1-hull_epsilon, v[2]]) + rotate([-90,0,0]) cylinder(h=hull_epsilon, d=taper_OD, $fn=fn); + translate([v[0], block_y1-hull_epsilon-taper_length, v[2]]) + rotate([-90,0,0]) cylinder(h=hull_epsilon, d=OD, $fn=fn); + } +} + +module CFSquareCutout2(v, block_y0, block_y1, tolerance = CF_Square_Width_tolerance, taper_length = 2, taper_mul = 1.1) { + w = CF_Square_Width + tolerance; + taper_w = (CF_Square_Width * taper_mul) + tolerance; + tube_y0 = v[1]; + tube_y1 = tube_y0 + CF_Tube_Len; + + // Full square rod, unconditional + translate([v[0]-w/2, v[1], v[2]-w/2]) cube([w, CF_Tube_Len, w]); + // Check for tapered holes + if ((block_y0 >= tube_y0) && (block_y0 < tube_y1)) // Tube protrudes through start of block + hull() { + translate([v[0], block_y0, v[2]]) + cube([taper_w, hull_epsilon*2, taper_w], center=true); + translate([v[0], block_y0+taper_length, v[2]]) + cube([w, hull_epsilon*2, w], center=true); + } + if ((block_y1 <= tube_y1) && (block_y1 > tube_y0)) // Tube protrudes through end of block + hull() { + translate([v[0], block_y1-hull_epsilon, v[2]]) + cube([taper_w, hull_epsilon*2, taper_w], center=true); + translate([v[0], block_y1-hull_epsilon-taper_length, v[2]]) + cube([w, hull_epsilon*2, w], center=true); + } + // if (taper_x1) { + // hull() { + // translate([0, x1, 0]) + // cube([w*taper_mul, hull_epsilon, w*taper_mul], center=true); + // translate([0, x1+(taper_length*taper_direction), 0]) + // cube([w, hull_epsilon, w], center=true); + // } + // } + // if (taper_x2){ + // hull() { + // translate([0, x2, 0]) + // cube([w*taper_mul, hull_epsilon, w*taper_mul], center=true); + // translate([0, x2-(taper_length*taper_direction), 0]) + // cube([w, hull_epsilon, w], center=true); + // } + // } +} diff --git a/common.scad b/common.scad index 2327264..8cbd444 100644 --- a/common.scad +++ b/common.scad @@ -1,6 +1,7 @@ Fender_Scale_mm = 648; // Actually 25.5inch = 647.7mm Classical_Normal_Scale_mm = 650; // about 25.59inch Classical_Short_Scale_mm = 635; // = 25inch +Gibson_Scale_mm = 630; // 24.75inch = 628.65mm Guitar_Scale_Length_mm = Fender_Scale_mm; ln2 = ln(2); @@ -10,6 +11,8 @@ function mm_to_fret_number(mm) = -log2(mm/Guitar_Scale_Length_mm)*12; function lerp(start, end, amount) = start + (end-start)*amount; function clamp(minimum, value, maximum) = min(max(minimum, value), maximum); +function flatten(l) = [ for (a = l) for (b = a) b]; + function tri_circumcenter(pts) = let( v0 = pts[1] - pts[0], @@ -42,6 +45,13 @@ module round_cube(size, r) { } } +module rotate_around(angles, pt) { + translate(pt) + rotate(angles) + translate(-pt) + children(); +} + // We can't use Droid Sans Japanese because the rendering library is really dumb and will pick the wrong Droid Sans. CJK fonts must be singular files. JP_Serif_Font = "New Tegomin"; JP_Sans_Font = "Yuji Boku";