Initial commit
This commit is contained in:
commit
dfdd8c480b
|
@ -0,0 +1,3 @@
|
|||
[submodule "scad-utils"]
|
||||
path = scad-utils
|
||||
url = https://github.com/OskarLinde/scad-utils.git
|
|
@ -0,0 +1,26 @@
|
|||
from subprocess import Popen
|
||||
|
||||
fret_pairs = [
|
||||
# Old lengths that are unfortunately too long (Up Box caps out at 205mm tall!)
|
||||
(-4, 0), # Bass
|
||||
( 1, 7), # Start of guitar
|
||||
( 8, 19), # Rougly similar length to above
|
||||
# New shorter segmentation ~120mm tall max
|
||||
(-4, -3), # 91.7217mm
|
||||
(-2, 0), # 119.166mm
|
||||
( 1, 3), # 100.206mm
|
||||
( 4, 7), # 109.258mm
|
||||
( 8, 12), # 105.444mm
|
||||
(13, 19), # 104.732mm
|
||||
(20, 30), # 98.839mm
|
||||
# Alternates for testing
|
||||
(0,0), # Just to see what it looks like, would redesign for 0-fret anyway
|
||||
(20,20), # Short debug print
|
||||
]
|
||||
|
||||
print("Compiling .stl files for fret pairs: ", fret_pairs)
|
||||
processes = [Popen(["openscad", "-o", f"fret_tube_{i}_{j}.stl", "-D", f"I={i}", "-D", f"J={j}", "fret_tube_I_J.scad"]) for (i,j) in fret_pairs]
|
||||
for p in processes:
|
||||
p.wait()
|
||||
|
||||
print("Finished compiling!")
|
|
@ -0,0 +1,5 @@
|
|||
use <../2Banger_fret_tube.scad>
|
||||
// I = 0; // Override with -D 'I=... J=...'
|
||||
// J = 24; // Override with -D
|
||||
echo(str("Called with I=", I, " J=", J))
|
||||
tube(from_fret = I, to_fret = J);
|
|
@ -0,0 +1,33 @@
|
|||
include <AluTCommon.scad>
|
||||
|
||||
$fn = $preview ? 32 : 512;
|
||||
mink_fn = $preview ? 12 : 128;
|
||||
mink_fn_2d = $preview ? 32 : 256;
|
||||
|
||||
|
||||
function tang_points(a0 = -160, a1 = -90, r = 13) =
|
||||
concat(
|
||||
[[r*cos(a1), r*sin(a0)]],
|
||||
[for (a = [a0:a1]) [r*cos(a), r*sin(a)]]
|
||||
);
|
||||
|
||||
module tang_block(a0 = -160, a1 = -90, r = 13)
|
||||
translate(T_circumcenter)
|
||||
polygon(tang_points(a0=a0, a1=a1, r=r));
|
||||
|
||||
module tang_outline(offset = -0.1, base_width = 1) {
|
||||
difference() {
|
||||
offset((base_width+offset)/2) tang_block();
|
||||
offset(-(base_width+offset)/2) tang_block();
|
||||
}
|
||||
}
|
||||
|
||||
module tapered_tang_groove(depth, taper = 1, offset = 0.1, base_width = 1) {
|
||||
difference() {
|
||||
hull() {
|
||||
linear_extrude(depth) offset((base_width+offset)/2) tang_block();
|
||||
translate([0,0,depth]) linear_extrude(taper) offset(-(base_width)/2) tang_block();
|
||||
}
|
||||
linear_extrude(depth + taper) offset(-(base_width+offset)/2) tang_block();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
include <2BangerCommon.scad>
|
||||
|
||||
module cap(length = 10) {
|
||||
module solid_cap(cap_taper = 1) {
|
||||
hull() {
|
||||
minkowski($fn = mink_fn) {
|
||||
sphere(cap_taper, $fn = mink_fn);
|
||||
translate([0,0,cap_taper]) linear_extrude(0.01) offset(-1) cap_outline();
|
||||
}
|
||||
linear_extrude(0.01) offset(-1) cap_outline();
|
||||
translate([0,0,cap_taper]) linear_extrude(length-cap_taper) cap_outline();
|
||||
}
|
||||
}
|
||||
|
||||
difference() {
|
||||
solid_cap();
|
||||
translate([0,0,Cap_Thick]) linear_extrude(length) T_hole();
|
||||
tapered_T_hole(z0 = length-1, z1 = length, o0 = 0, o1 = 1);
|
||||
translate([-10,10,length-0.5]) linear_extrude(1) text("04²", size=5, halign="center", valign="center", font="Noto Sans");
|
||||
}
|
||||
}
|
||||
|
||||
cap();
|
|
@ -0,0 +1,101 @@
|
|||
include <common.scad>
|
||||
include <2BangerCommon.scad>
|
||||
|
||||
fret_width = 2.4; //2.8; // Jumbo = 0.11", 0.055" tall
|
||||
|
||||
module tube(from_fret, to_fret, tang_depth = 3) {
|
||||
z_min = (fret_scale_length(to_fret) + fret_scale_length(to_fret+1))/2;
|
||||
z_max = (fret_scale_length(from_fret) + fret_scale_length(from_fret-1))/2;
|
||||
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"));
|
||||
|
||||
module solid_tube(cap_taper = 1.5, fingerboard_min_thick = 2.5, fingerboard_max_thick = 5, fret_angle = 60) { // Fret angle of 45° is normal, anything over 60 will not work correctly
|
||||
module fret_bumps(w=50) {
|
||||
translate([0,0,-z_offset]) for (fret = [from_fret:to_fret])
|
||||
translate([fingerboard_max_thick - fret_width/2, w/2, fret_scale_length(fret)])
|
||||
rotate([90,0,0]) cylinder(h = w, r = fret_width/2);
|
||||
}
|
||||
|
||||
module scallops(w=50) {
|
||||
for (fret = [from_fret:to_fret+1])
|
||||
let(
|
||||
f_prev = fret_scale_length(fret-1) - z_offset,
|
||||
f_next = fret_scale_length(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() {
|
||||
minkowski($fn = mink_fn) {
|
||||
sphere(cap_taper, $fn = mink_fn);
|
||||
translate([0,0,cap_taper]) linear_extrude(0.01) offset(-cap_taper)
|
||||
cap_outline(fingerboard_min_thick = fingerboard_min_thick, fingerboard_max_thick = fingerboard_max_thick);
|
||||
}
|
||||
minkowski($fn = mink_fn) {
|
||||
sphere(cap_taper, $fn = mink_fn);
|
||||
translate([0,0,Cap_Length-cap_taper]) linear_extrude(0.01) offset(-cap_taper)
|
||||
cap_outline(fingerboard_min_thick = fingerboard_min_thick, fingerboard_max_thick = fingerboard_max_thick);
|
||||
}
|
||||
linear_extrude(Cap_Length) offset(-1) cap_outline();
|
||||
translate([0,0,cap_taper]) linear_extrude(Cap_Length-cap_taper*2)
|
||||
cap_outline(fingerboard_min_thick = fingerboard_min_thick, fingerboard_max_thick = fingerboard_max_thick);
|
||||
}
|
||||
union() {
|
||||
fret_bumps();
|
||||
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() {
|
||||
union() {
|
||||
basic_fretboard();
|
||||
translate([0,0,Cap_Length]) linear_extrude(tang_depth) tang_outline(-0.1);
|
||||
}
|
||||
difference() {
|
||||
scallops();
|
||||
fret_bumps();
|
||||
}
|
||||
tapered_tang_groove(depth = tang_depth + 0.5, taper = 0);
|
||||
tapered_tang_groove(depth = 0.5, taper = 0, offset = 0.5);
|
||||
}
|
||||
// color("red") scallops();
|
||||
}
|
||||
|
||||
difference() {
|
||||
solid_tube(1.5);
|
||||
linear_extrude(Cap_Length) T_hole();
|
||||
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("05²", size=5, halign="center", valign="center", font="Noto Sans");
|
||||
// Fret number markers
|
||||
for (fret = [from_fret:to_fret])
|
||||
translate([-3,-16,fret_scale_length(fret)-z_offset]) rotate([90,25,16]) linear_extrude(100) text(str(fret), size=4, halign="center", valign="center", font="Noto Sans");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tube(from_fret = 0, to_fret = 0);
|
||||
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);
|
|
@ -0,0 +1,74 @@
|
|||
include <common.scad>
|
||||
use <skin.scad>
|
||||
|
||||
L_minor = 1/2 * 25.4;
|
||||
L_major = 3/4 * 25.4;
|
||||
L_thick = 1.8; //9/128 * 25.4; //1/16 * 25.4;
|
||||
T_flat_top = L_minor * 2; // 1"
|
||||
T_spine = L_major; // 3/4"
|
||||
T_tolerance = 0.285;
|
||||
// Cap_Length = 150;
|
||||
Cap_Thick = 3;
|
||||
Cap_Spine = T_spine + Cap_Thick;
|
||||
|
||||
|
||||
points = [[-T_spine, 0], [0, -L_minor], [0, L_minor]];
|
||||
|
||||
function tri_circumcenter(pts) =
|
||||
let(
|
||||
v0 = pts[1] - pts[0],
|
||||
v1 = pts[2] - pts[1],
|
||||
d0 = (pts[1] + pts[0])/2 * v0,
|
||||
d1 = (pts[2] + pts[1])/2 * v1,
|
||||
det = -cross(v0, v1)
|
||||
)
|
||||
[cross([d1, d0], [v1.y, v0.y]), cross([d0, d1], [v0.x, v1.x])] / det;
|
||||
|
||||
T_circumcenter = tri_circumcenter(points);
|
||||
tube_radius = Cap_Spine + T_circumcenter[0];
|
||||
|
||||
module cap_outline(radius = 1.5, fingerboard_min_thick = 2.5, fingerboard_max_thick = 5) {
|
||||
minkowski($fn = mink_fn_2d) {
|
||||
circle(r = radius);
|
||||
difference() {
|
||||
translate(T_circumcenter) circle(r = tube_radius - radius);
|
||||
translate([fingerboard_max_thick - radius, -50]) square([100,100]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function T_hole_points(r = 4, a_step = 5, offset = 0) =
|
||||
let(
|
||||
x0 = T_tolerance + offset,
|
||||
x1 = x0 - L_thick - (T_tolerance*2) - (offset*2),
|
||||
x2 = -T_spine - T_tolerance - offset,
|
||||
y_out = L_minor + T_tolerance + offset,
|
||||
y_in = L_thick + T_tolerance + offset,
|
||||
top_points = [
|
||||
[x1, -y_out],
|
||||
[x0, -y_out],
|
||||
[x0, y_out],
|
||||
[x1, y_out]
|
||||
],
|
||||
bottom_points = [
|
||||
[x2, y_in],
|
||||
[x2, -y_in],
|
||||
],
|
||||
joint_corner_left = [x1, -y_in],
|
||||
joint_corner_right = [x1, y_in],
|
||||
join_points_left = [for (a = [0:a_step:90]) joint_corner_left + [-r * (1-sin(a)), -r * (1-cos(a))]],
|
||||
join_points_right = [for (a = [0:a_step:90]) joint_corner_right + [-r * (1-cos(a)), r * (1-sin(a))]]
|
||||
)
|
||||
concat(top_points, join_points_right, bottom_points, join_points_left);
|
||||
|
||||
module T_hole(r = 4, a_step = 5, offset = 0)
|
||||
polygon(T_hole_points(r=r, a_step=a_step, offset=offset));
|
||||
|
||||
module tapered_T_hole(z0 = 0, z1 = 4, o0 = 1, o1 = 0) {
|
||||
// z1 must > z0 for faces to work
|
||||
pts0 = [for (pt = T_hole_points(offset = o0)) concat(pt, z0)];
|
||||
pts1 = [for (pt = T_hole_points(offset = o1)) concat(pt, z1)];
|
||||
skin([pts0, pts1]);
|
||||
}
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
Tuner_Spacing_4 = 64;
|
||||
Post_Hole_Dia = 14.75; // 14 + tolerance
|
||||
Post_Hole_Depth = 14;
|
||||
Post_Top_Dia = 9;
|
||||
Post_Top_Height = 17;
|
||||
Tuner_Body_Dia = 17; // 16.5 + tolerance
|
||||
Tuner_Body_R = Tuner_Body_Dia/2; // 16.5 + tolerance
|
||||
Tuner_Body_Width = 21;
|
||||
Tuner_Body_Thickness = 10; // 9.5 + tolerance
|
||||
Tuner_Body_Rect_Len = Tuner_Body_Width-Tuner_Body_R;
|
||||
Tuner_Tab_Angle = 60;
|
||||
Tuner_Tab_Hole_Dia = 2.5;
|
||||
Tuner_Tab_Thickness = 2;
|
||||
Tuner_Tab_Total = 27.5;
|
||||
Tuner_Tab_Hole_Inset = 2;
|
||||
Tuner_Tab_Hole_Outset = (Tuner_Tab_Total-Tuner_Body_Rect_Len)-Tuner_Tab_Hole_Inset;
|
||||
Engrave_String = "01γ";
|
||||
// Font = "Ani";
|
||||
Font = "GFS Didot";
|
||||
// Font = "GFS Neohellenic";
|
||||
// Font = "Liberation Mono";
|
||||
// Font = "Noto Sans";
|
||||
|
||||
module cyl(d=10, z0=-100, z1=100, $fn=64)
|
||||
translate([0,0,z0])
|
||||
cylinder(h=z1-z0, r=d/2, $fn=$fn);
|
||||
module c(d=10, z=0, $fn=64) // 3d circle
|
||||
translate([0,0,z])
|
||||
cylinder(h=0.00001, r=d/2, $fn=$fn);
|
||||
|
||||
module tuner_tab_hole(shrink=0) {
|
||||
translate([0, -Tuner_Tab_Hole_Outset+Tuner_Tab_Hole_Dia/2])
|
||||
circle((Tuner_Tab_Hole_Dia-shrink)/2, $fn=32);
|
||||
}
|
||||
|
||||
module tuner_outline(shrink=0) {
|
||||
union() {
|
||||
hull() {
|
||||
translate([0, -Tuner_Tab_Hole_Outset])
|
||||
circle((Tuner_Tab_Hole_Dia+Tuner_Tab_Hole_Inset-shrink)/2, $fn=32);
|
||||
circle(Tuner_Body_R-shrink/2, $fn=64);
|
||||
}
|
||||
translate([-Tuner_Body_R+shrink/2, 0])
|
||||
square([Tuner_Body_Dia-shrink, Tuner_Body_Rect_Len-shrink/2]);
|
||||
}
|
||||
}
|
||||
|
||||
// color("blue") tuner_outline(-1.5);
|
||||
// translate([0,0,0.001])
|
||||
// color("red") tuner_outline(0);
|
||||
|
||||
module tuner_body() {
|
||||
linear_extrude(Tuner_Body_Thickness) union() {
|
||||
translate([-Tuner_Body_R, 0])
|
||||
square([Tuner_Body_Dia, Tuner_Body_Rect_Len]);
|
||||
circle(Tuner_Body_R, $fn=32);
|
||||
}
|
||||
translate([0, 0, Tuner_Body_Thickness-Tuner_Tab_Thickness])
|
||||
linear_extrude(Tuner_Tab_Thickness) difference() {
|
||||
hull() {
|
||||
translate([0, -Tuner_Tab_Hole_Outset])
|
||||
circle((Tuner_Tab_Hole_Dia+Tuner_Tab_Hole_Inset)/2, $fn=32);
|
||||
circle(Tuner_Body_R, $fn=64);
|
||||
}
|
||||
tuner_tab_hole();
|
||||
}
|
||||
// handle
|
||||
color(c = "red")
|
||||
translate([0, Tuner_Body_Rect_Len-Tuner_Body_Thickness/2, Tuner_Body_Thickness/2])
|
||||
rotate([0,-90,0])
|
||||
cylinder(h = 40, r = Tuner_Body_Thickness/2);
|
||||
}
|
||||
|
||||
module tuner_post() {
|
||||
cylinder(h = Post_Hole_Depth, r = Post_Hole_Dia/2, $fn=64);
|
||||
color("cyan")
|
||||
translate([0, 0, Post_Hole_Depth])
|
||||
difference() {
|
||||
cylinder(h = Post_Top_Height, r = Post_Top_Dia/2);
|
||||
translate([-1,-5, Post_Top_Height-6]) cube([2,10,7]);
|
||||
}
|
||||
}
|
||||
|
||||
module tuner() {
|
||||
tuner_body();
|
||||
translate([0, 0, Tuner_Body_Thickness])
|
||||
tuner_post();
|
||||
}
|
||||
|
||||
module tuner_arrange()
|
||||
for (a = [90:30:180])
|
||||
rotate([0,0,a])
|
||||
translate([-31, 31, 0])
|
||||
children();
|
||||
|
||||
module handle_cutouts() {
|
||||
tuner_arrange()
|
||||
translate([0, Tuner_Body_Rect_Len-Tuner_Body_Thickness/2, Tuner_Body_Thickness/2])
|
||||
rotate([-90, 0, 90]) linear_extrude(40) hull() {
|
||||
circle(Tuner_Body_Thickness/2, $fn=32);
|
||||
translate([-Tuner_Body_Thickness/2, 0]) square([Tuner_Body_Thickness, 20]);
|
||||
}
|
||||
}
|
||||
|
||||
module retainer_outline()
|
||||
// polygon([[-50, -10], [-45, -35], [-20, -55], [20, -55], [45, -35], [50, -10]]);
|
||||
polygon(concat([for (i = [-52:1:45]) [60*sin(i), -60*cos(i)]], [[40,-5], [-40, -5], [-47, -18]]));
|
||||
|
||||
|
||||
module part() {
|
||||
module layer_bolt_holes_outer(dia=3.05, z0=-100, z1=100)
|
||||
for (a = [-120:30:-60])
|
||||
rotate([0,0,a])
|
||||
translate([55,0,z0])
|
||||
cylinder(h=z1-z0, r=dia/2, $fn=64);
|
||||
module layer_bolt_holes_inner(dia=3.05, z0=-100, z1=100)
|
||||
for (x = [-20,0,20])
|
||||
translate([x,-10,z0])
|
||||
cylinder(h=z1-z0, r=dia/2, $fn=64);
|
||||
|
||||
module bottom_engraving()
|
||||
// translate([0,-26,1]) rotate([0,180,0]) linear_extrude(30)
|
||||
translate([0,-28,1]) rotate([15,180,0]) linear_extrude(30)
|
||||
text(text = Engrave_String, size = 5, halign="center", valign="center", font=Font);
|
||||
|
||||
// Top half
|
||||
difference() {
|
||||
color("blue")
|
||||
translate([0, 0, Tuner_Body_Thickness])
|
||||
linear_extrude(Post_Hole_Depth-0.001)
|
||||
retainer_outline();
|
||||
tuner_arrange() tuner();
|
||||
// tuner screw holes
|
||||
tuner_arrange()
|
||||
linear_extrude(Tuner_Body_Thickness+Post_Hole_Depth-1)
|
||||
tuner_tab_hole(shrink=0.5);
|
||||
// layer bolt holes
|
||||
layer_bolt_holes_outer();
|
||||
layer_bolt_holes_outer(dia=7.05, z0=Tuner_Body_Thickness+Post_Hole_Depth-4); // 5.4 OD for bolt head, 7 for M3 washer
|
||||
layer_bolt_holes_inner();
|
||||
layer_bolt_holes_inner(dia=7.05, z0=Tuner_Body_Thickness+Post_Hole_Depth-4);
|
||||
// engraving
|
||||
translate([0,-20,Tuner_Body_Thickness+Post_Hole_Depth-1])
|
||||
linear_extrude(5) text(text = Engrave_String, size = 12, halign="center", valign="center", font=Font);
|
||||
}
|
||||
// Bottom half
|
||||
color("grey")
|
||||
difference() {
|
||||
linear_extrude(Tuner_Body_Thickness) difference() {
|
||||
retainer_outline();
|
||||
// tuner body holes
|
||||
translate([0, 0, -20])
|
||||
tuner_arrange()
|
||||
tuner_outline(-1.5);
|
||||
}
|
||||
// layer bolt holes
|
||||
layer_bolt_holes_outer();
|
||||
layer_bolt_holes_outer(dia=5.1, z1=5+1.5); // Heat insert is 5mm tall, we will use 20mm bolt for these holes
|
||||
layer_bolt_holes_inner();
|
||||
// tuning handle finger bit
|
||||
handle_cutouts();
|
||||
// engraving
|
||||
bottom_engraving();
|
||||
}
|
||||
// Mounting
|
||||
color("aqua")
|
||||
difference() {
|
||||
translate([0,0,-12]) linear_extrude(12) difference() {
|
||||
retainer_outline();
|
||||
tuner_arrange() tuner_outline(-1.5);
|
||||
}
|
||||
// reinforcing layer bolt holes
|
||||
layer_bolt_holes_inner();
|
||||
layer_bolt_holes_inner(dia=7.05, z1=(Tuner_Body_Thickness+Post_Hole_Depth-4)-29+5); // Heat insert is 5mm tall, we will use 30mm bolt for these holes
|
||||
// mounting holes
|
||||
for (x = [-30, -10, 10, 30])
|
||||
translate([x,0,-5])
|
||||
rotate([90,0,0]) {
|
||||
cylinder(h=100, r=2.5, $fn=32);
|
||||
// translate([0,0,10]) cylinder(h=20, r=3.8, $fn=32); // Bolt head
|
||||
// translate([0,0,11]) cylinder(h=20, r=4.7, $fn=32); // Washer
|
||||
translate([0,0,11]) cylinder(h=20, r=2.55, $fn=32); // Heat Insert
|
||||
}
|
||||
// mounting hollow
|
||||
cyl_offset = [0,-36,-13];
|
||||
translate(cyl_offset) rotate([0,90,0]) cyl(d=28, $fn=128);
|
||||
translate([-100,-100+cyl_offset[1],-50]) cube([200,100,100]);
|
||||
for (i = [-1,1]) hull() {
|
||||
translate([0,-18,-15]) rotate([0,90,0]) c(d=32, z=50*i, $fn=128);
|
||||
translate(cyl_offset) rotate([0,90,0]) c(d=28, z=14*i, $fn=128);
|
||||
translate(cyl_offset) rotate([0,90,0]) c(d=28, z=50*i, $fn=128);
|
||||
}
|
||||
bottom_engraving();
|
||||
}
|
||||
}
|
||||
part();
|
||||
|
||||
// tuner_arrange() tuner();
|
||||
// handle_cutouts();
|
|
@ -0,0 +1,181 @@
|
|||
// Fender standard is 25.5"
|
||||
Guitar_Scale_Length_In = 25.5;
|
||||
// Convert to mm (1" = 25.4mm)
|
||||
//Guitar_Scale_Length_mm = Guitar_Scale_Length_In * 25.4;
|
||||
// This conversion ends up with 647.7mm, but 648mm has nice round number 865mm on the -5 fret too! Regular P-bass is 864mm
|
||||
Guitar_Scale_Length_mm = 648;
|
||||
// Extending the Strat by 5 frets gives a P-Bass
|
||||
Bass_Fret = -5;
|
||||
|
||||
PBass_Nut_Width_In = 1.625; // (43mm)
|
||||
JBass_Nut_Width_In = 1.5; // (38mm)
|
||||
Strat_Nut_Width_In = 1.65; // (42mm)
|
||||
|
||||
function fret_scale_length(n) = Guitar_Scale_Length_mm * 2^(-n/12);
|
||||
function lerp(start, end, amount) = start + (end-start)*amount;
|
||||
|
||||
echo(str("Guitar scale length is ", fret_scale_length(0), "mm"));
|
||||
echo(str("Bass scale length is ", fret_scale_length(Bass_Fret), "mm"));
|
||||
|
||||
// Our modules need to fit in our 25x20cm build area
|
||||
// This can be obtained by [-5,0), [0,7), [7,19), [19,bridge] modules.
|
||||
|
||||
module radiused_chord(w, r, points=12) {
|
||||
// w <= abs(r)*2
|
||||
// Negative r possible for mirroring across y-axis
|
||||
angle = asin(0.5*w/r);
|
||||
angles = [
|
||||
for (i = [0:points-1])
|
||||
let (f = -0.5 + i/(points-1))
|
||||
f * 2 * angle
|
||||
];
|
||||
x0 = r*cos(angle);
|
||||
coords = [
|
||||
for (th = angles)
|
||||
let (
|
||||
x = r*cos(th) - x0,
|
||||
y = r*sin(th)
|
||||
)
|
||||
[x,y]
|
||||
];
|
||||
polygon(coords);
|
||||
}
|
||||
|
||||
module c_text(s, size)
|
||||
text(s, size=size, halign="center", valign="center", font="Noto Sans");
|
||||
|
||||
epsilon = 0.0001;
|
||||
module to3d()
|
||||
{linear_extrude(epsilon) children();}
|
||||
|
||||
nut_width = 38;
|
||||
bridge_width = nut_width + 40;
|
||||
|
||||
fretboard_radius = 5.5*25.4;
|
||||
neck_radius = 20;
|
||||
color("red")
|
||||
rotate([0,90]) hull(){
|
||||
translate([0,0,fret_scale_length(Bass_Fret)/4])
|
||||
to3d() radiused_chord(lerp(bridge_width, nut_width, 1/4), -fretboard_radius);
|
||||
translate([0,0,fret_scale_length(Bass_Fret)])
|
||||
to3d() radiused_chord(nut_width, -fretboard_radius);
|
||||
}
|
||||
// color("blue")
|
||||
// rotate([0,90]) hull(){
|
||||
// translate([0,-bridge_width/2,0])
|
||||
// cube([20, bridge_width, 1]);
|
||||
// translate([0,0,fret_scale_length(Bass_Fret)])
|
||||
// to3d() scale([0.25,1]) radiused_chord(nut_width, neck_radius);
|
||||
// }
|
||||
|
||||
module frets_and_markers(min_fret=-5, max_fret=36, width=bridge_width) {
|
||||
// Fret wire placeholder model
|
||||
for (x = [for (i = [min_fret:max_fret]) fret_scale_length(i)])
|
||||
translate([x, -width/2, 0])
|
||||
cube([1, width, 12]);
|
||||
|
||||
// Fret dots
|
||||
for (octave = [0:3])
|
||||
for (fret = [3, 5, 7, 9]) {
|
||||
i = fret + (octave*12);
|
||||
if (i > min_fret && i <= max_fret)
|
||||
translate([(fret_scale_length(i)+fret_scale_length(i-1))/2,0,0])
|
||||
//cylinder(h=10, r=4);
|
||||
linear_extrude(10) c_text(str(fret), size=8);
|
||||
}
|
||||
// Octave markers
|
||||
for (i = [0, 12, 24, 36]) if (i > min_fret && i <= max_fret) hull(){
|
||||
translate([(fret_scale_length(i)+fret_scale_length(i-1))/2,20,0]) cylinder(h=10, r=3);
|
||||
translate([(fret_scale_length(i)+fret_scale_length(i-1))/2,-20,0]) cylinder(h=10, r=1);
|
||||
}
|
||||
// Bass extension
|
||||
if (min_fret < -1)
|
||||
for (i = [min_fret+1:-1])
|
||||
translate([(fret_scale_length(i)+fret_scale_length(i-1))/2,0,0])
|
||||
linear_extrude(10) c_text(str(i), size=12);
|
||||
}
|
||||
|
||||
Module_Length = 220; // Printer can do up to 250mm, the bass fret run is 217mm. Don't forget overlapping joins!
|
||||
Module_Overhang = 20;
|
||||
Module_Bridge_Offset = -15; //80 240
|
||||
|
||||
module Connector() {
|
||||
translate([0,0,-15])
|
||||
linear_extrude(10)
|
||||
polygon([[0,5],[0,-5],[Module_Overhang,-15],[Module_Overhang,15]]);
|
||||
}
|
||||
|
||||
module Body(thickness=20, width=90) {
|
||||
color("blue", 0.5)
|
||||
translate([Module_Bridge_Offset, -width/2, -thickness])
|
||||
cube([Module_Length, width, thickness]);
|
||||
frets_and_markers(20, 24);
|
||||
translate([Module_Bridge_Offset+Module_Length, 0, 0]) Connector();
|
||||
|
||||
// Bridge
|
||||
translate([-20, -bridge_width/2, 3])
|
||||
cube([20, bridge_width, 10]);
|
||||
}
|
||||
|
||||
module Neck1(thickness=18, width=70) {
|
||||
color([0,0.5,1], 0.5)
|
||||
translate([Module_Bridge_Offset+Module_Length, -width/2, -thickness])
|
||||
cube([Module_Length, width, thickness]);
|
||||
frets_and_markers(8, 20);
|
||||
translate([Module_Bridge_Offset+Module_Length*2, 0, 0]) Connector();
|
||||
}
|
||||
|
||||
module Neck2(thickness=17, width=60) {
|
||||
color([0.5,0,1], 0.5)
|
||||
translate([Module_Bridge_Offset+Module_Length*2, -width/2, -thickness])
|
||||
cube([Module_Length, width, thickness]);
|
||||
frets_and_markers(1, 7);
|
||||
translate([Module_Bridge_Offset+Module_Length*3, 0, 0]) Connector();
|
||||
}
|
||||
|
||||
module Neck_Bass(thickness=16, width=40) {
|
||||
color([1,0,0.5], 0.5)
|
||||
translate([Module_Bridge_Offset+Module_Length*3, -width/2, -thickness])
|
||||
cube([Module_Length+Module_Overhang, width, thickness]);
|
||||
frets_and_markers(-5, 0);
|
||||
}
|
||||
|
||||
|
||||
// Structural Aluminium
|
||||
density_6063 = 2.7; // 6063 alloy is around 2.7g/cm3
|
||||
echo(str("Weight of one 12mm x 3mm x 1m bar is ", density_6063*1.2*0.3*100, "g"));
|
||||
echo(str("Weight of three 12mm x 3mm x 1m bar is ", density_6063*3.6*0.3*100, "g"));
|
||||
echo(str("Weight of one 12x3 and two 10x3 x 1m bars is ", density_6063*3.2*0.3*100, "g"));
|
||||
echo(str("Weight of one 12mm x 12mm x 1.5mm x 1m channel is roughly ", density_6063*1.2*0.15*100*3, "g"));
|
||||
echo(str("Weight of one 16mm x 16mm x 1.5mm x 1m channel is roughly ", density_6063*1.6*0.15*100*3, "g"));
|
||||
|
||||
module Parallel_Bars(spacing=18, x0=-80) {
|
||||
// for (y = [-1.5-spacing, -1.5, -1.5+spacing])
|
||||
// translate([x0, y, -12]) cube([1000,3,12]); // 12mm x 3mm bar, 1m length
|
||||
translate([x0, -1.5, -12]) cube([1000,3,12]); // 12mm x 3mm bar, 1m length
|
||||
for (y = [-1.5-spacing, -1.5+spacing])
|
||||
translate([x0, y, -10]) cube([1000,3,10]); // 12mm x 3mm bar, 1m length
|
||||
}
|
||||
module Alu_Channel(x0=-80) {
|
||||
thickness = 1.5;
|
||||
y0 = -thickness/2;
|
||||
//12x12x1.5 channel
|
||||
translate([x0, -6, -thickness]) cube([1000, 12, thickness]);
|
||||
for (y = [y0-6, y0+6])
|
||||
translate([x0, y, -12]) cube([1000, thickness, 12]);
|
||||
}
|
||||
|
||||
// frets_and_markers(-5, 29);
|
||||
Body(); Neck1(); Neck2();
|
||||
Neck_Bass();
|
||||
Parallel_Bars();
|
||||
|
||||
translate([0,150,0]) Body();
|
||||
translate([0,250,0]) Neck1();
|
||||
translate([0,150,0]) Neck2();
|
||||
translate([0,250,0]) Neck_Bass();
|
||||
|
||||
translate([0,-150,0]) {
|
||||
Body(); Neck1(); Neck2();
|
||||
Alu_Channel();
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
Pickup_Length = 58; // Tolerance
|
||||
Pickup_Width = 28.5; // Tolerance
|
||||
Pickup_Height = 20;
|
||||
Pickup_Offset = -37.5;
|
||||
Magnet_Height = 3;
|
||||
Corner_Radius = 1.5; // Half-guessed
|
||||
Hole_Spacing = 65;
|
||||
Cavity_Width = 64; // Tolerance
|
||||
|
||||
Tang_Height = 1.5;
|
||||
Tang_Groove_Height = Tang_Height + 0.25;
|
||||
|
||||
body_h = 20;
|
||||
|
||||
Engrave_String = "P01β²";
|
||||
Font = "GFS Didot";
|
||||
// Font_JP = "New Tegomin";
|
||||
Font_JP = "Yuji Boku";
|
||||
|
||||
|
||||
module cyl(d=10, z0=-100, z1=100, $fn=128)
|
||||
translate([0,0,z0])
|
||||
cylinder(h=z1-z0, r=d/2, $fn=$fn);
|
||||
module circ(r=10) circle(r=r, $fn=128);
|
||||
|
||||
|
||||
pl1 = Pickup_Length/2 - Corner_Radius;
|
||||
pw1 = Pickup_Width/2 - Corner_Radius;
|
||||
module half_pickup() {
|
||||
difference() {
|
||||
union() {
|
||||
// translate([-Pickup_Length/2, -Pickup_Width/2, 0]) cube([Pickup_Length, Pickup_Width, Pickup_Height]);
|
||||
color([0.3, 0.3, 0.3]) hull()
|
||||
for (x = [-pl1, pl1])
|
||||
for (y = [-pw1, pw1])
|
||||
translate([x, y, 0])
|
||||
cyl(d=Corner_Radius*2, z0=Magnet_Height, z1=Pickup_Height);
|
||||
for (x = [-29, 29])
|
||||
color([0.3, 0.3, 0.3])
|
||||
translate([x, 0, 0])
|
||||
cyl(d=12, z0=6, z1=16);
|
||||
color([0.5, 0.5, 0.6])
|
||||
translate([-20, -5, 0])
|
||||
cube([40, 10, Magnet_Height]);
|
||||
for (x = [-14.25:9.5:14.25])
|
||||
color([0.7, 0.75, 0.8])
|
||||
translate([x, 0, 0])
|
||||
cyl(d=4, z0=Pickup_Height, z1=Pickup_Height+2);
|
||||
}
|
||||
for (x = [-Hole_Spacing/2, Hole_Spacing/2])
|
||||
translate([x, 0, 0])
|
||||
cyl(d=3);
|
||||
}
|
||||
}
|
||||
|
||||
module for_each_pickup() {
|
||||
for (off = [[0, 0], [Pickup_Offset, Pickup_Width]]) translate(off) children();
|
||||
}
|
||||
|
||||
module split_pickup() {
|
||||
for_each_pickup() half_pickup();
|
||||
}
|
||||
|
||||
module pickup_outline(grow=0.5) {
|
||||
union() {
|
||||
hull() {
|
||||
for (x = [-pl1-grow, pl1+grow])
|
||||
for (y = [-pw1-grow, pw1+grow])
|
||||
translate([x, y])
|
||||
circ(r=Corner_Radius);
|
||||
}
|
||||
for (x = [-29, 29])
|
||||
translate([x, 0])
|
||||
circ(r=6+grow);
|
||||
}
|
||||
}
|
||||
|
||||
module body_outline(shrink=0, body_r=8) {
|
||||
union() {
|
||||
hull() {
|
||||
// Base Plate
|
||||
for (x = [-60+body_r, 20-body_r])
|
||||
for (y = [-18+body_r, Cavity_Width-18-body_r])
|
||||
translate([x,y])
|
||||
circ(body_r - shrink);
|
||||
for (off = [[0, 0], [Pickup_Offset, Pickup_Width]]) translate(off)
|
||||
for (x = [-29, 29]) translate([x, 0])
|
||||
circ((12+5)/2 - shrink);
|
||||
// Jack Plate
|
||||
translate([-67, 20]) circ(6 - shrink);
|
||||
// Pad pickup corners
|
||||
dist = Pickup_Length/2 + 5 - body_r;
|
||||
translate([dist, -18+body_r]) circ(body_r - shrink);
|
||||
translate([Pickup_Offset - dist, Cavity_Width-18-body_r]) circ(body_r - shrink);
|
||||
}
|
||||
hull() {
|
||||
translate([-67, 20]) circ(6 - shrink);
|
||||
translate([-67, -9]) circ(6 - shrink);
|
||||
translate([-60+body_r, -18+body_r]) circ(body_r - shrink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module tang(margin=0.1) { // Negative margin as subtraction for the slot
|
||||
difference() {
|
||||
body_outline(shrink=1+margin);
|
||||
body_outline(shrink=2-margin);
|
||||
translate([45, 0]) square(40+margin, center=true);
|
||||
translate([-83, 32]) square(40+margin, center=true);
|
||||
};
|
||||
translate([-60,11.5]) square([27-margin, 1-margin]);
|
||||
translate([-6,17]) square([27-margin, 1-margin]);
|
||||
}
|
||||
|
||||
// color("blue") translate([-60, -18, -1]) cube([80, Cavity_Width, 1]);
|
||||
module lower() {
|
||||
difference() {
|
||||
union() {
|
||||
taper = 5;
|
||||
translate([0,0,taper]) minkowski($fn = $preview ? 8 : 64) {
|
||||
sphere(r = taper, $fn = $preview ? 8 : 64);
|
||||
linear_extrude(0.0001) body_outline(shrink=taper);
|
||||
}
|
||||
// hull() {
|
||||
// linear_extrude(taper) body_outline(shrink=3);
|
||||
translate([0,0,taper]) linear_extrude(body_h-taper) body_outline();
|
||||
// }
|
||||
// tang
|
||||
color("blue")
|
||||
translate([0,0,body_h])
|
||||
linear_extrude(Tang_Height)
|
||||
tang();
|
||||
}
|
||||
// Subtractions
|
||||
// Jack cavity
|
||||
hull() {
|
||||
translate([-69, -10, 2.5]) cube([15, 20, 20]);
|
||||
translate([-69, -10, 10]) cube([35, 20, 20]);
|
||||
}
|
||||
// Jack hole
|
||||
translate([0,0,14]) rotate([0,-90,0]) cyl(d=11,z0=60);
|
||||
// Wire channels
|
||||
translate([0,0,5]) linear_extrude(body_h) union() {
|
||||
translate([-35, 7]) square([25,6], center=true);
|
||||
translate([-66, 13]) square([6,20], center=true);
|
||||
}
|
||||
// M4 holes to mount to body
|
||||
for (off = [[Pickup_Offset-5, 0], [5, Pickup_Width]]) translate(off) {
|
||||
cyl(d=4);
|
||||
cyl(d=9.5, z0=5);
|
||||
}
|
||||
for_each_pickup() {
|
||||
// Pickup adjustment brass insert holes
|
||||
for (x = [-Hole_Spacing/2, Hole_Spacing/2])
|
||||
translate([x, 0, 0]) {
|
||||
cyl(5.1);
|
||||
hull(){
|
||||
cyl(5.25, z0=7, z1=10);
|
||||
cyl(6, z0=9, z1=20);
|
||||
}
|
||||
}
|
||||
// Pickup outlines
|
||||
translate([0,0,10]) linear_extrude(100) pickup_outline();
|
||||
}
|
||||
translate([4, 38, body_h-2]) linear_extrude(5)
|
||||
text(text = Engrave_String, size = 6, halign="center", valign="center", font=Font);
|
||||
translate([14, 28, body_h-2]) linear_extrude(5)
|
||||
text(text = "下", size = 8, halign="center", valign="center", font=Font_JP);
|
||||
}
|
||||
}
|
||||
|
||||
module upper(wall_height=3.5, roof_height=2.5) {
|
||||
module elec_cavity() {
|
||||
hull() {
|
||||
for (off = [[-27, -11], [-52, -11], [-66, -8], [-66, 7], [-27, 7]])
|
||||
translate(off) circ(r=2.5);
|
||||
}
|
||||
}
|
||||
module walls() {
|
||||
difference() {
|
||||
body_outline();
|
||||
for_each_pickup() pickup_outline();
|
||||
elec_cavity();
|
||||
}
|
||||
}
|
||||
|
||||
module roof() {
|
||||
difference() {
|
||||
body_outline();
|
||||
for_each_pickup() pickup_outline();
|
||||
}
|
||||
}
|
||||
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(Tang_Groove_Height) difference() {
|
||||
walls();
|
||||
tang(-0.1);
|
||||
}
|
||||
h = wall_height - Tang_Groove_Height;
|
||||
translate([0, 0, Tang_Groove_Height])
|
||||
linear_extrude(h)
|
||||
walls();
|
||||
intersection() {
|
||||
translate([0,0,wall_height]) linear_extrude(roof_height) roof();
|
||||
translate([0,0,wall_height])
|
||||
minkowski($fn = $preview ? 8 : 64) {
|
||||
sphere(roof_height, $fn = $preview ? 8 : 64);
|
||||
linear_extrude(0.001) body_outline(shrink=roof_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
linear_extrude(100) for_each_pickup() pickup_outline();
|
||||
// Engravings
|
||||
translate([0, 0, wall_height+0.5]) linear_extrude(100) {
|
||||
translate([-2,22])
|
||||
text(text = "LHW", size = 4, font=Font);
|
||||
translate([-6,17])
|
||||
text(text = "2023-03-29", size = 4, font=Font);
|
||||
translate([-50,0])
|
||||
text(text = Engrave_String, size = 6, halign="center", valign="center", font=Font);
|
||||
translate([-50,-8])
|
||||
text(text = "上", size = 8, halign="center", valign="center", font=Font_JP);
|
||||
}
|
||||
// Jack hole
|
||||
translate([0,0,14-body_h]) rotate([0,-90,0]) cyl(d=11+2,z0=60);
|
||||
}
|
||||
}
|
||||
|
||||
// lower();
|
||||
upper();
|
||||
// translate([0,0,10]) split_pickup();
|
|
@ -0,0 +1,69 @@
|
|||
;===========================;
|
||||
; List of supported G-codes ;
|
||||
;===========================;
|
||||
; G0: linear Move
|
||||
; G4: Dwell
|
||||
; G28: Move to Origin (Home)
|
||||
; G90: Set to Absolute Positioning
|
||||
; G91: Set to Relative Positioning
|
||||
; G92: Set Position, only support A axis reset.
|
||||
; M0: Stop or Unconditional stop
|
||||
; M1: Sleep or Conditional stop
|
||||
; M2: Program End
|
||||
; M25: Pause SD print
|
||||
; M42: Switch I/O pin
|
||||
; M73: Set build percentage
|
||||
; M80: ATX Power On
|
||||
; M81: ATX Power Off
|
||||
; M82: Set extruder to absolute mode
|
||||
; M83: Set extruder to relative mode
|
||||
; M92: Set axis_steps_per_unit
|
||||
; M104: Set Extruder Temperature
|
||||
; M109: Set Extruder Temperature and Wait, Example M109 S215
|
||||
; M140: Set Bed Temperature (Fast)
|
||||
; M141: Set Chamber Temperature (Fast)
|
||||
; M190: Wait for bed temperature to reach target temp
|
||||
; M191: Wait for chamber temperature to reach target temp
|
||||
; M204: Set default acceleration
|
||||
; M206: Offset axes
|
||||
|
||||
;==========================;
|
||||
; List of relevant G-codes ;
|
||||
;==========================;
|
||||
; M92: Set axis_steps_per_unit
|
||||
; e.g. M92 X87.489 Y87.489 Z87.489 E420:420
|
||||
; M204: Set default acceleration
|
||||
; M206: Offset axes
|
||||
;
|
||||
; G90: Set to Absolute Positioning (default)
|
||||
; G91: Set to Relative Positioning
|
||||
; G92: Set Position, "only support A axis reset." - in other machines, this can set new absolute origin
|
||||
; M82: Set extruder to absolute mode (default)
|
||||
; M83: Set extruder to relative mode
|
||||
;
|
||||
; M190: Wait for bed temperature to reach target temp
|
||||
; M109: Set Extruder Temperature and Wait, Example M109 S215
|
||||
;
|
||||
; G0: linear Move - this is rapid linear move on other systems, G1 is normal speed linear move for them
|
||||
; e.g. G0 X000 Y000 Z000 E000 F000
|
||||
; F is feed rate, E is extruder
|
||||
; Traditionally, S is used for "power", which may be laser power or spindle speed. N/A here.
|
||||
; G4: Dwell (ms)
|
||||
; e.g. G4 P1000
|
||||
; G28: Move to Origin (Home)
|
||||
; e.g. G28
|
||||
; e.g. G28 X Y
|
||||
;
|
||||
; M0: Stop or Unconditional stop
|
||||
; M1: Sleep or Conditional stop
|
||||
; M2: Program End
|
||||
; M73: Set build percentage
|
||||
; e.g. M73 P100
|
||||
;
|
||||
; M80: ATX Power On
|
||||
; M81: ATX Power Off
|
||||
;
|
||||
;
|
||||
; M140: Set Bed Temperature (Fast) - does not wait!
|
||||
; e.g. M140 S65 R40 (set to 65°C, wait until 40°C)
|
||||
; M104: Set Extruder Temperature
|
|
@ -0,0 +1,3 @@
|
|||
Guitar_Scale_Length_mm = 648;
|
||||
function fret_scale_length(n) = Guitar_Scale_Length_mm * 2^(-n/12);
|
||||
function lerp(start, end, amount) = start + (end-start)*amount;
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 27c7ede3b7298f0a629553033e2a78e13e627bef
|
|
@ -0,0 +1,75 @@
|
|||
use <scad-utils/transformations.scad>
|
||||
use <scad-utils/lists.scad>
|
||||
|
||||
// Skin a set of profiles with a polyhedral mesh
|
||||
module skin(profiles, loop=false /* unimplemented */) {
|
||||
P = max_len(profiles);
|
||||
N = len(profiles);
|
||||
|
||||
profiles = [
|
||||
for (p = profiles)
|
||||
for (pp = augment_profile(to_3d(p),P))
|
||||
pp
|
||||
];
|
||||
|
||||
function quad(i,P,o) = [[o+i, o+i+P, o+i%P+P+1], [o+i, o+i%P+P+1, o+i%P+1]];
|
||||
|
||||
function profile_triangles(tindex) = [
|
||||
for (index = [0:P-1])
|
||||
let (qs = quad(index+1, P, P*(tindex-1)-1))
|
||||
for (q = qs) q
|
||||
];
|
||||
|
||||
triangles = [
|
||||
for(index = [1:N-1])
|
||||
for(t = profile_triangles(index))
|
||||
t
|
||||
];
|
||||
|
||||
start_cap = [range([0:P-1])];
|
||||
end_cap = [range([P*N-1 : -1 : P*(N-1)])];
|
||||
|
||||
polyhedron(convexity=2, points=profiles, faces=concat(start_cap, triangles, end_cap));
|
||||
}
|
||||
|
||||
// Augments the profile with steiner points making the total number of vertices n
|
||||
function augment_profile(profile, n) =
|
||||
subdivide(profile,insert_extra_vertices_0([profile_lengths(profile),dup(0,len(profile))],n-len(profile))[1]);
|
||||
|
||||
function subdivide(profile,subdivisions) = let (N=len(profile)) [
|
||||
for (i = [0:N-1])
|
||||
let(n = len(subdivisions)>0 ? subdivisions[i] : subdivisions)
|
||||
for (p = interpolate(profile[i],profile[(i+1)%N],n+1))
|
||||
p
|
||||
];
|
||||
|
||||
function interpolate(a,b,subdivisions) = [
|
||||
for (index = [0:subdivisions-1])
|
||||
let(t = index/subdivisions)
|
||||
a*(1-t)+b*t
|
||||
];
|
||||
|
||||
function distribute_extra_vertex(lengths_count,ma_=-1) = ma_<0 ? distribute_extra_vertex(lengths_count, max_element(lengths_count[0])) :
|
||||
concat([set(lengths_count[0],ma_,lengths_count[0][ma_] * (lengths_count[1][ma_]+1) / (lengths_count[1][ma_]+2))], [increment(lengths_count[1],max_element(lengths_count[0]),1)]);
|
||||
|
||||
function insert_extra_vertices_0(lengths_count,n_extra) = n_extra <= 0 ? lengths_count :
|
||||
insert_extra_vertices_0(distribute_extra_vertex(lengths_count),n_extra-1);
|
||||
|
||||
// Find the index of the maximum element of arr
|
||||
function max_element(arr,ma_,ma_i_=-1,i_=0) = i_ >= len(arr) ? ma_i_ :
|
||||
i_ == 0 || arr[i_] > ma_ ? max_element(arr,arr[i_],i_,i_+1) : max_element(arr,ma_,ma_i_,i_+1);
|
||||
|
||||
function max_len(arr) = max([for (i=arr) len(i)]);
|
||||
|
||||
function increment(arr,i,x=1) = set(arr,i,arr[i]+x);
|
||||
|
||||
function profile_lengths(profile) = [
|
||||
for (i = [0:len(profile)-1])
|
||||
profile_segment_length(profile,i)
|
||||
];
|
||||
|
||||
function profile_segment_length(profile,i) = norm(profile[(i+1)%len(profile)] - profile[i]);
|
||||
|
||||
// Generates an array with n copies of value (default 0)
|
||||
function dup(value=0,n) = [for (i = [1:n]) value];
|
||||
|
Loading…
Reference in New Issue