diff --git a/bezier_circle_approximation.scad b/bezier_circle_approximation.scad new file mode 100644 index 0000000..3d1a1bc --- /dev/null +++ b/bezier_circle_approximation.scad @@ -0,0 +1,32 @@ +include ; + +a=90; + +module circle_(r) { + c = 0.55191; + cp=[ + [ 0, 1, 0], // 0 + [ c, 1, 0], // 1 + [ 1, c, 0], // 2 + [ 1, 0, 0], // 3 + [ 1, 0, 0], // 4 + [ 1, -c, 0], // 5 + [ c, -1, 0], // 6 + [ 0, -1, 0], // 7 + [ 0, -1, 0], // 8 + [-c, -1, 0], // 9 + [-1, -c, 0], // a + [-1, 0, 0], // b + [-1, 0, 0], // c + [-1, c, 0], // d + [-c, 1, 0], // e + [ 0, 1, 0] // f + ]; + for (i=[0:3]) { + control_points=[cp[i*4], cp[i*4+1], cp[i*4+2], cp[i*4+3]]; + curve_vertices=bezier_curve_vertices(control_points*r, $fn); + render_curve(curve_vertices, width=2, height=2, chamfer=1, debug=false); + } +} + +circle_(50); diff --git a/bunnyear_headband.scad b/bunnyear_headband.scad index 956a67b..c7cada7 100644 --- a/bunnyear_headband.scad +++ b/bunnyear_headband.scad @@ -1,7 +1,16 @@ use include -module bunnyear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND, ear_scale=0.5, ear_bend_factor=0.2, ear_stretch_factor=8, ear_angle=30) { +EAR_VERSION = 3; +EAR_SKEW = 1; +EAR_SCALE = 0.5; +EAR_BEND_FACTOR = 1.0; +EAR_STRETCH_FACTOR = 8; +EAR_ANGLE = 30; +WITH_RAKE = true; +DETAILS = true; + +module bunnyear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND, ear_scale=EAR_SCALE, ear_bend_factor=EAR_BEND_FACTOR, ear_stretch_factor=EAR_STRETCH_FACTOR, ear_angle=EAR_ANGLE, ear_version=EAR_VERSION, ear_skew=EAR_SKEW) { catear_headband( debug=debug, size=size, @@ -14,7 +23,9 @@ module bunnyear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKN ear_scale=ear_scale, ear_bend_factor=ear_bend_factor, ear_stretch_factor=ear_stretch_factor, - ear_angle=ear_angle); + ear_angle=ear_angle, + ear_version=ear_version, + ear_skew=ear_skew); } -bunnyear_headband(); +rotate(-90) bunnyear_headband(); diff --git a/c3cat-bottle-clip/c3cat-bottle-clip.scad b/c3cat-bottle-clip/c3cat-bottle-clip.scad index 19a51e7..4c5a6e2 100644 --- a/c3cat-bottle-clip/c3cat-bottle-clip.scad +++ b/c3cat-bottle-clip/c3cat-bottle-clip.scad @@ -61,7 +61,7 @@ USE_TINY_EARS = true; */ scale([0.2, 0.2, 0.2]) { difference() { - scale([5, 5, 5]) rotate(45, [0, 0, 1]) bottle_clip(name=NAME); + scale([5, 5, 5]) rotate(45, [0, 0, 1]) bottle_clip(name=NAME, logo=LOGO_FILE); translate([ 15*5, 0*5, 18*5]) rotate(80, [0, 1, 0]) catear(); translate([-15*5, 0*5, 18*5]) rotate(-80, [0, 1, 0]) catear(); } @@ -93,6 +93,7 @@ module name(name, font, rl, ht, ru) { module logo(logo, rl, ht, ru, width) { echo("logo: ", logo); if(logo == "") { + echo("CATEAR LOGO"); ear_size=ht; echo("ht: ", ht); echo("ru: ", ru); @@ -114,32 +115,29 @@ module logo(logo, rl, ht, ru, width) { with_rake=false ); } else { + echo("LOGO: ", logo); // The logo has been split in 3 parts. // well was... TODO -/* - rotate([0,0,-48]) translate([0,0,ht*3/4-0.1]) + rotate([0,0,-45]) translate([0,0,ht*3/4-0.1]) rotate([90,0,0]) - scale([0.9,0.9,1]) + scale([0.8,0.8,1]) scale([ht/100,ht/100,1]) - translate([-25,-29,0.5]) + translate([-32,-33,0.5]) linear_extrude(height=max(ru,rl)*2) - import("logo_1.dxf"); -*/ + import("test.svg"); translate([0,0,ht*3/4-0.1]) rotate([90,0,0]) scale([0.8,0.8,1]) scale([ht/100,ht/100,1]) - translate([-18,-22,0.5]) + translate([-32,-33,0.5]) linear_extrude(height=max(ru,rl)*2) import(logo); -/* - rotate([0,0,44]) translate([0,0,ht*3/4-0.1]) + rotate([0,0,45]) translate([0,0,ht*3/4-0.1]) rotate([90,0,0]) - scale([0.7,0.7,1]) + scale([0.8,0.8,1]) scale([ht/100,ht/100,1]) - translate([-25,-26,0.5]) + translate([-32,-33,0.5]) linear_extrude(height=max(ru,rl)*2) - import("logo_3.dxf"); -*/ + import("test.svg"); } } @@ -153,7 +151,7 @@ module bottle_clip(ru=13, rl=17.5, ht=26, width=2.5, name="c3cat", font="write/o difference() { union() { name(name=name, font=font, rl=rl, ht=ht, ru=ru); - logo(logo=logo, rl=rl, ht=ht, ru=ru, width=width); + logo(logo=logo, rl=rl, ht=ht, ru=ru, width=2*width); } cylinder(r1=rl+width/2, r2=ru+width/2, h=ht); } diff --git a/c3cat-bottle-clip/sterntastatur.svg b/c3cat-bottle-clip/sterntastatur.svg new file mode 100644 index 0000000..520ed37 --- /dev/null +++ b/c3cat-bottle-clip/sterntastatur.svg @@ -0,0 +1,910 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/c3cat-bottle-clip/test.svg b/c3cat-bottle-clip/test.svg new file mode 100644 index 0000000..c983ded --- /dev/null +++ b/c3cat-bottle-clip/test.svg @@ -0,0 +1,46 @@ + + + + + + + + + + diff --git a/catear_headband.scad b/catear_headband.scad index 142ade5..c3bd260 100644 --- a/catear_headband.scad +++ b/catear_headband.scad @@ -1,9 +1,75 @@ include ; +include ; use ; use ; -module catear(height, thickness, fractal=0, side_len=30, bend_factor=0.5, stretch_factor=1.2, debug=false, chamfer=CHAMFER, chamfer_shape=CHAMFER_SHAPE, details=true) { +EAR_VERSION = 3; +EAR_SKEW = 0.6; +EAR_SCALE = 1.4; +EAR_BEND_FACTOR = 0.04; +EAR_STRETCH_FACTOR = 1.2; +EAR_ANGLE = 42; +WITH_RAKE = true; +DETAILS = true; + +catear_v3_control_points = function (S, sf, bf, mn, a) let (s=S/2, R=rotation_matrix(a)) [ + [ s , 0, 0], + [ S*bf, S*sf*mn, 0] * R, + [-S*bf, S*sf*mn, 0] * R, + [-s , 0, 0], +]; + +/** + * unsupported parameters: chamfer, chamfer_shape, details, end_caps + */ +module catear_v3(height, thickness, fractal=0, side_len=30, bend_factor=0.15, stretch_factor=1.2, debug=false, chamfer=CHAMFER, chamfer_shape=CHAMFER_SHAPE, details=true, end_caps=true, skew=2.0, $fn=$fn) { + control_points = catear_v3_control_points( + S=side_len, + sf=stretch_factor, + bf=bend_factor, + mn=1.16, + a=skew*10 + ); + curve_vertices = bezier_curve_vertices(control_points, $fn); + if (debug) { + translate([0, 0, 2*height]) rotate(90) bezier_curve_debug(control_points); + echo("curve_vertices: ", curve_vertices); + } + rotate(90) render_curve( + curve_vertices, + width=thickness, + height=height, + chamfer=chamfer, + debug=debug + ); +} + +/** + * unsupported parameters: debug, chamfer, chamfer_shape, details, end_caps + */ +module catear_v2(height, thickness, fractal=0, side_len=30, bend_factor=0.15, stretch_factor=1.2, debug=false, chamfer=CHAMFER, chamfer_shape=CHAMFER_SHAPE, details=true, end_caps=true, skew=2.0) { + r=side_len/2; + T=side_len+thickness; + S=side_len-thickness; + x_stretch = function (x) pow(x, abs(skew)); + y_stretch = function (y) pow(y, 2.0); + E=1.6*stretch_factor; + a=y_stretch(r)+thickness/2; + b=y_stretch(r)-thickness/2; + e=(E*a-thickness)/b; + echo("E",E,"e",e, "a", a, "b", b, "c", thickness); + outer_remap = function (p) [scalc(x_stretch, p.x, T/2, -T/2)*sign(skew), scalc(y_stretch, p.y, 0, T/2)*E, p.z]; + inner_remap = function (p) [scalc(x_stretch, p.x, S/2, -S/2)*sign(skew), scalc(y_stretch, p.y, 0, T/2)*e, p.z]; + or = function (p) [p.x, 2*p.y, p.z]; + + arc(0.5, r, thickness, height, outer_remap=outer_remap, inner_remap=inner_remap); +} + +/** + * unsupported parameters: skew + */ +module catear_v1(height, thickness, fractal=0, side_len=30, bend_factor=0.15, stretch_factor=1.2, debug=false, chamfer=CHAMFER, chamfer_shape=CHAMFER_SHAPE, details=true, end_caps=true, skew=2.0) { $A=[0, side_len/2]; $B=[0,-side_len/2]; $C=[-(side_len/2/sin(120))*1.5*stretch_factor, 0]; @@ -42,15 +108,17 @@ module catear(height, thickness, fractal=0, side_len=30, bend_factor=0.5, stretc thickness=thickness, height=height ); - translate($A) color("#aaaaaa") - chamfer(size=chamfer, child_h=height, child_bot=-height/2, shape=chamfer_shape) - cylinder(h=height, d=thickness, center=true); - translate($B) color("#bbbbbb") - chamfer(size=chamfer, child_h=height, child_bot=-height/2, shape=chamfer_shape) - cylinder(h=height, d=thickness, center=true); - translate($C) color("#cccccc") - chamfer(size=chamfer, child_h=height, child_bot=-height/2, shape=chamfer_shape) - cylinder(h=height, d=thickness, center=true); + if (end_caps) { + translate($A) color("#aaaaaa") + chamfer(size=chamfer, child_h=height, child_bot=-height/2, shape=chamfer_shape) + cylinder(h=height, d=thickness, center=true); + translate($B) color("#bbbbbb") + chamfer(size=chamfer, child_h=height, child_bot=-height/2, shape=chamfer_shape) + cylinder(h=height, d=thickness, center=true); + translate($C) color("#cccccc") + chamfer(size=chamfer, child_h=height, child_bot=-height/2, shape=chamfer_shape) + cylinder(h=height, d=thickness, center=true); + } if (debug) { echo("A", $A, "a", $a, "alpha", $alpha); @@ -74,38 +142,102 @@ module catear(height, thickness, fractal=0, side_len=30, bend_factor=0.5, stretc } } -module catear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND, ear_scale=1.5, ear_bend_factor=0.15, ear_stretch_factor=1.2, ear_angle=42, chamfer=CHAMFER, chamfer_shape=CHAMFER_SHAPE, with_rake=true, details=true) { +module catear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND, ear_scale=EAR_SCALE, ear_bend_factor=EAR_BEND_FACTOR, ear_stretch_factor=EAR_STRETCH_FACTOR, ear_angle=EAR_ANGLE, chamfer=CHAMFER, chamfer_shape=CHAMFER_SHAPE, with_rake=WITH_RAKE, details=DETAILS, ear_skew=EAR_SKEW, ear_version=EAR_VERSION) { $a=size/2*ear_scale; $delta=2*(acos($a/(size*2))-90); ear_offset=size*sin(90-$delta/2); union() { - rotate( ear_angle, [0, 0, 1]) { - translate([-ear_offset, 0, 0]) catear( - debug=debug, - height=height, - thickness=thickness, - side_len=size/2*ear_scale, - bend_factor=ear_bend_factor, - stretch_factor=ear_stretch_factor, - chamfer=chamfer, - chamfer_shape=chamfer_shape, - details=details - ); + if (ear_version == 3 ) { + rotate( ear_angle, [0, 0, 1]) { + translate([-ear_offset, 0, 0]) catear_v3( + debug=debug, + height=height, + thickness=thickness, + side_len=size/2*ear_scale, + bend_factor=ear_bend_factor, + stretch_factor=ear_stretch_factor, + chamfer=chamfer, + chamfer_shape=chamfer_shape, + details=details, + skew=ear_skew + ); + } + rotate(-ear_angle, [0, 0, 1]) { + translate([-ear_offset, 0, 0]) catear_v3( + debug=false, + height=height, + thickness=thickness, + side_len=size/2*ear_scale, + bend_factor=ear_bend_factor, + stretch_factor=ear_stretch_factor, + chamfer=chamfer, + chamfer_shape=chamfer_shape, + details=details, + skew=-ear_skew + ); + } } - rotate(-ear_angle, [0, 0, 1]) { - translate([-ear_offset, 0, 0]) catear( - debug=false, - height=height, - thickness=thickness, - side_len=size/2*ear_scale, - bend_factor=ear_bend_factor, - stretch_factor=ear_stretch_factor, - chamfer=chamfer, - chamfer_shape=chamfer_shape, - details=details - ); + if (ear_version == 2 ) { + rotate( ear_angle, [0, 0, 1]) { + translate([-ear_offset, 0, 0]) catear_v2( + debug=debug, + height=height, + thickness=thickness, + side_len=size/2*ear_scale, + bend_factor=ear_bend_factor, + stretch_factor=ear_stretch_factor, + chamfer=chamfer, + chamfer_shape=chamfer_shape, + details=details, + skew=ear_skew + ); + } + rotate(-ear_angle, [0, 0, 1]) { + translate([-ear_offset, 0, 0]) catear_v2( + debug=false, + height=height, + thickness=thickness, + side_len=size/2*ear_scale, + bend_factor=ear_bend_factor, + stretch_factor=ear_stretch_factor, + chamfer=chamfer, + chamfer_shape=chamfer_shape, + details=details, + skew=-ear_skew + ); + } + } + if (ear_version == 1 ) { + rotate( ear_angle, [0, 0, 1]) { + translate([-ear_offset, 0, 0]) catear_v1( + debug=debug, + height=height, + thickness=thickness, + side_len=size/2*ear_scale, + bend_factor=ear_bend_factor, + stretch_factor=ear_stretch_factor, + chamfer=chamfer, + chamfer_shape=chamfer_shape, + details=details, + skew=ear_skew + ); + } + rotate(-ear_angle, [0, 0, 1]) { + translate([-ear_offset, 0, 0]) catear_v1( + debug=false, + height=height, + thickness=thickness, + side_len=size/2*ear_scale, + bend_factor=ear_bend_factor, + stretch_factor=ear_stretch_factor, + chamfer=chamfer, + chamfer_shape=chamfer_shape, + details=details, + skew=-ear_skew + ); + } } headband( size=size, @@ -121,4 +253,4 @@ module catear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNES }; } -catear_headband(); +rotate(-90) catear_headband(); diff --git a/foxear_headband.scad b/foxear_headband.scad index 7fb26af..0ec041a 100644 --- a/foxear_headband.scad +++ b/foxear_headband.scad @@ -1,7 +1,16 @@ use include -module foxear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND, ear_scale=1.2, ear_bend_factor=0.05, ear_stretch_factor=1.2, ear_angle=30) { +EAR_VERSION = 3; +EAR_SKEW = 1; +EAR_SCALE = 1.2; +EAR_BEND_FACTOR = 0.00; +EAR_STRETCH_FACTOR = 1.2; +EAR_ANGLE = 30; +WITH_RAKE = true; +DETAILS = true; + +module foxear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND, ear_scale=EAR_SCALE, ear_bend_factor=EAR_BEND_FACTOR, ear_stretch_factor=EAR_STRETCH_FACTOR, ear_angle=EAR_ANGLE, ear_version=EAR_VERSION, ear_skew=EAR_SKEW) { catear_headband( debug=debug, size=size, @@ -14,7 +23,9 @@ module foxear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNES ear_scale=ear_scale, ear_bend_factor=ear_bend_factor, ear_stretch_factor=ear_stretch_factor, - ear_angle=ear_angle); + ear_angle=ear_angle, + ear_version=ear_version, + ear_skew=ear_skew); } -foxear_headband(); +rotate(-90) foxear_headband(); diff --git a/generate_bottle_tag.sh b/generate_bottle_tag.sh index 8ea378d..877f7e8 100755 --- a/generate_bottle_tag.sh +++ b/generate_bottle_tag.sh @@ -11,6 +11,10 @@ FN=90 NAME="\"$1\"" +if [[ $# -ge 2 ]];then + LOGO_FILE="\"$2\"" +fi + # usage: render NAME PART render() { case "$2" in diff --git a/globals.scad b/globals.scad index 2f53cd2..1d74fc4 100644 --- a/globals.scad +++ b/globals.scad @@ -12,8 +12,8 @@ RAKE_WIDTH=1; RAKE_STRETCH=1; RAKE_CHAMFER=0.5; CHAMFER=1; -CHAMFER_SHAPE="curve"; +CHAMFER_SHAPE="cone"; INSERTICLE_X = 4.6; INSERTICLE_Y = 7.4; -INSERTICLE_Z = 5.4; \ No newline at end of file +INSERTICLE_Z = 5.4; diff --git a/headband.scad b/headband.scad index 9a0bab7..53465e7 100644 --- a/headband.scad +++ b/headband.scad @@ -1,13 +1,7 @@ include +include use -module partial_ring(part, radius, thickness, height) { - rotate(180-180*part, [0, 0, 1]) - rotate_extrude(angle=360*part) - translate([radius, 0]) - square([thickness, height], center=true); -} - module headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND, rake_depth=RAKE_DEPTH, rake_width=RAKE_WIDTH, rake_stretch=RAKE_STRETCH, rake_chamfer=RAKE_CHAMFER, chamfer=CHAMFER, chamfer_shape=CHAMFER_SHAPE, with_rake=true, details=true) { union() { chamfer(size=(details)?chamfer:0, child_h=height, child_bot=-height/2, shape=chamfer_shape) union() { diff --git a/mouseear_headband.scad b/mouseear_headband.scad index af1ca43..262f32e 100644 --- a/mouseear_headband.scad +++ b/mouseear_headband.scad @@ -1,7 +1,16 @@ use include -module mouseear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND, ear_scale=1, ear_bend_factor=0.65, ear_stretch_factor=1, ear_angle=40) { +EAR_VERSION = 3; +EAR_SKEW = 0; +EAR_SCALE = 1; +EAR_BEND_FACTOR = 0.5; +EAR_STRETCH_FACTOR = 1; +EAR_ANGLE = 40; +WITH_RAKE = true; +DETAILS = true; + +module mouseear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND, ear_scale=EAR_SCALE, ear_bend_factor=EAR_BEND_FACTOR, ear_stretch_factor=EAR_STRETCH_FACTOR, ear_angle=EAR_ANGLE) { catear_headband( debug=debug, size=size, @@ -17,4 +26,4 @@ module mouseear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKN ear_angle=ear_angle); } -mouseear_headband(); +rotate(-90) mouseear_headband(); diff --git a/pressfit_bunnyears.scad b/pressfit_bunnyears.scad new file mode 100644 index 0000000..9c64e2b --- /dev/null +++ b/pressfit_bunnyears.scad @@ -0,0 +1,46 @@ +include ; + +use ; +use ; +use ; + +$fn=90; +EAR_SCALE = 0.5; +EAR_BEND_FACTOR = 0.2; +EAR_STRETCH_FACTOR = 8; +STEP_SIZE = .25; + + +module loop(i) { + j=pow(0.99, i); + //chamfer_ = floor(abs(2*i/(SIZE/2*EAR_SCALE-1)-1)); + translate([-j*20, 0, 0]) + difference() { + rotate(90, [0, 1, 0]) + /*chamfer(size=1, child_h=1, child_bot=-0.5, shape=CHAMFER_SHAPE)*/ { + //echo("i", i, "j", j, "chamfer_", chamfer_); + union() catear( + debug=DEBUG, + height=INSERTICLE_Z*1.2, + thickness=THICKNESS, + side_len=SIZE/2*EAR_SCALE-i, + bend_factor=EAR_BEND_FACTOR, + stretch_factor=EAR_STRETCH_FACTOR, + chamfer=0, //chamfer_, + chamfer_shape=CHAMFER_SHAPE, + details=false, + end_caps=true + ); + } + cube([100, 100, THICKNESS], center=true); + } +} + +//difference() { + translate([20*pow(0.99, SIZE/2*EAR_SCALE-1-THICKNESS), 0, -THICKNESS/2]) + union() for (i=[0:STEP_SIZE:0/*SIZE/2*EAR_SCALE-1*/]) { + loop(i); + } +// translate([0, 0, -THICKNESS]) cube([100, 100, THICKNESS], center=true); +// scale([1, 1, 2]) inserticle(); +//} diff --git a/pressfit_catears.scad b/pressfit_catears.scad index 7697690..58f255b 100644 --- a/pressfit_catears.scad +++ b/pressfit_catears.scad @@ -1,5 +1,7 @@ include ; +include ; +use ; use ; use ; use ; @@ -7,26 +9,62 @@ use ; EAR_SCALE = 1.5; EAR_BEND_FACTOR = 0.15; EAR_STRETCH_FACTOR = 1.2; +STEP_SIZE = 100; -difference() { -translate([20*pow(0.99, SIZE/2*EAR_SCALE-1-THICKNESS), 0, -THICKNESS/2]) -union() for (i=[0:SIZE/2*EAR_SCALE-1]) { - j=pow(0.99, i); - chamfer_ = floor(abs(2*i/(SIZE/2*EAR_SCALE-1)-1)); - translate([-j*20, 0, 0]) - rotate(90, [0, 1, 0]) - /*chamfer(size=1, child_h=1, child_bot=-0.5, shape=CHAMFER_SHAPE)*/ - catear( - debug=DEBUG, - height=INSERTICLE_Z*1.2, - thickness=THICKNESS, - side_len=SIZE/2*EAR_SCALE-i, - bend_factor=EAR_BEND_FACTOR, - stretch_factor=EAR_STRETCH_FACTOR, - chamfer=chamfer_, - chamfer_shape=CHAMFER_SHAPE - ); +translate([50, 0, 0]) difference() { + translate([20*pow(0.99, SIZE/2*EAR_SCALE-1-THICKNESS), 0, -THICKNESS/2]) + union() for (i=[0:STEP_SIZE:SIZE/2*EAR_SCALE-1]) { + j=pow(0.99, i); + chamfer_ = floor(abs(2*i/(SIZE/2*EAR_SCALE-1)-1)); + translate([-j*20, 0, 0]) + rotate(90, [0, 1, 0]) + /*chamfer(size=1, child_h=1, child_bot=-0.5, shape=CHAMFER_SHAPE)*/ + catear_v1( + debug=DEBUG, + height=INSERTICLE_Z*1.2, + thickness=THICKNESS, + side_len=SIZE/2*EAR_SCALE-i, + bend_factor=EAR_BEND_FACTOR, + stretch_factor=EAR_STRETCH_FACTOR, + chamfer=0, //chamfer_, + chamfer_shape=CHAMFER_SHAPE, + end_caps=false + ); + } + translate([0, 0, -THICKNESS]) cube([100, 100, THICKNESS], center=true); + scale([1, 1, 2]) inserticle(); } -translate([0, 0, -THICKNESS]) cube([100, 100, THICKNESS], center=true); -scale([1, 1, 2]) inserticle(); -} \ No newline at end of file + +side_len=SIZE/2*EAR_SCALE; +r=side_len/2; +E=1.6*EAR_STRETCH_FACTOR; +e=E*(r+THICKNESS/4)/(r-THICKNESS/4); +T=side_len+THICKNESS; +S=side_len-THICKNESS; +xremap = function (x) pow(x, EAR_STRETCH_FACTOR); +yremap = function (y) pow(y, 1); +//f = function (p) [j((p.x+T/2)/T)*T-T/2, pow(p.y, 2)/r*E, p.z]; +//g = function (p) [j((p.x+S/2)/S)*S-S/2, pow(p.y, 2)/r*E*(T+THICKNESS)/S, p.z]; +f = function (p) [scalc(xremap, p.x, -T/2, T/2), scalc(yremap, p.y, 0, T/2)*E, p.z]; +g = function (p) [scalc(xremap, p.x, -S/2, S/2), scalc(yremap, p.y, 0, S/2)*e, p.z]; + +rotate([0, 90, 0]) color("yellow") arc(0.5, r, THICKNESS, HEIGHT, outer_remap=f, inner_remap=g); + +color("red") catear_v2( + height=HEIGHT, + thickness=THICKNESS, + side_len=SIZE/2*EAR_SCALE, + stretch_factor=EAR_STRETCH_FACTOR +); + +// a = b + c +// x * a = y * b + c +// y * b = x * a - c +// y =(x * a - c)/ b + +// 100 = 95 + 5 +// x * 100 = y * 95 + 5 +// 5 * 100 = y * 95 + 5 +// 500 = y * 95 + 5 +// 495 = y * 95 +// y = 495 / 95 diff --git a/pressfit_headband.scad b/pressfit_headband.scad index 93cc684..7d592a7 100644 --- a/pressfit_headband.scad +++ b/pressfit_headband.scad @@ -2,32 +2,69 @@ include use +RENDER_PLA = true; +RENDER_PETG = true; + module inserticle() { - cube([INSERTICLE_X, INSERTICLE_Y, INSERTICLE_Z], center=true); + cube([INSERTICLE_X, INSERTICLE_Y, INSERTICLE_Z], center=true); } -module pressfit_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND) { - union() { - color("pink") { $a=48; - rotate( $a, [0, 0, 1]) { - translate([-size-4, 0,]) rotate(90, [0, 1, 0]) inserticle(); - translate([-size-3, 0,]) rotate(90, [0, 1, 0]) inserticle(); - } - rotate(-$a, [0, 0, 1]) { - translate([-size-4, 0,]) rotate(90, [0, 1, 0]) inserticle(); - translate([-size-3, 0,]) rotate(90, [0, 1, 0]) inserticle(); - } +module anchored_inserticle() { + translate([-1, 0, 0]) rotate(90, [0, 1, 0]) inserticle(); + rotate(90, [0, 1, 0]) { + cube([INSERTICLE_X-2*CHAMFER, INSERTICLE_Y, INSERTICLE_Z], center=true); + translate([0, 0, INSERTICLE_Z/2+0.5]) + cube([INSERTICLE_X/2, INSERTICLE_Y+2, 1], center=true); + } +} + +module pla_parts(size, a) { + color("pink") { + for (i=[-1, 1]) { + union() { + rotate(i*a, [0, 0, 1]) { + translate([-size-3, 0, 0]) anchored_inserticle(); + translate([-size-4, 0,]) rotate(90, [0, 1, 0]) inserticle(); + translate([-size-3, 0,]) rotate(90, [0, 1, 0]) { + cube([INSERTICLE_X-2*CHAMFER, INSERTICLE_Y, INSERTICLE_Z], center=true); + translate([0, 0, INSERTICLE_Z/2+0.5]) + cube([INSERTICLE_X/2, INSERTICLE_Y+2, 1], center=true); + } } - headband( - size=size, - height=height, - thickness=thickness, - part=part, - stretch_len=stretch_len, - tip_len=tip_len, - tip_bend=tip_bend - ); - }; + } + } + } +} + +module petg_parts(size, height, thickness, part, stretch_len, tip_len, tip_bend) { + headband( + size=size, + height=height, + thickness=thickness, + part=part, + stretch_len=stretch_len, + tip_len=tip_len, + tip_bend=tip_bend + ); +} + +module pressfit_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNESS, part=PART, stretch_len=STRETCH_LEN, tip_len=TIP_LEN, tip_bend=TIP_BEND, a=48) { + if (RENDER_PLA && RENDER_PETG) { + union() { + petg_parts(size, height, thickness, part, stretch_len, tip_len, tip_bend); + pla_parts(size, a); + } + } else { + if (RENDER_PETG) { + difference() { + petg_parts(size, height, thickness, part, stretch_len, tip_len, tip_bend); + pla_parts(size, a); + } + } + if (RENDER_PLA) { + pla_parts(size, a); + } + } } pressfit_headband(); diff --git a/primitives.scad b/primitives.scad new file mode 100644 index 0000000..d24e117 --- /dev/null +++ b/primitives.scad @@ -0,0 +1,188 @@ +include + +id = function (x) x; + +lerp = function (v, old_min, old_max, new_min, new_max) (v-old_min)/(old_max-old_min)*(new_max-new_min)+new_min; + +scalc = function (f, v, min, max) lerp(f(lerp(v, min, max, 0, 1)), 0, 1, min, max); + +normalize = function (vector) vector / norm(vector); + +mat_T = function (mat) [ + for (x_y=[0:len(mat[0])-1]) [ + for (y_x=[0:len(mat)-1]) mat[y_x][x_y] + ] +]; + +rotation_matrix = function(a) [ + [cos(a), -sin(a), 0], + [sin(a), cos(a), 0], + [ 0, 0, 1] +]; + +bezier_matrix = [[1, -3, 3, -1], + [0, 3, -6, 3], + [0, 0, 3, -3], + [0, 0, 0, 1]]; + +spline = function (control_points, spline_matrix, t) mat_T(control_points) * spline_matrix * [1, t, t*t, t*t*t]; + +bezier_spline = function (control_points, t) spline(control_points, bezier_matrix, t); + +bezier_curve_vertices = function (control_points, $fn=$fn) [ + for (t=[0:1/($fn-1):1]) bezier_spline(control_points, t) +]; + +module bezier_curve_debug(control_points, $fn=$fn) { + #color("red") for (c = control_points) translate(c) sphere(d=4, $fn=32); + color("yellow") for (v = bezier_curve_vertices(control_points, $fn)) translate(v) sphere(d=.5, $fn=16); + color("green") translate(bezier_spline(control_points, 0.5)) sphere(d=1, $fn=24); +} + +// c^2=a^2+b^2 // a == b +// c^2=2a^2 // /2 +// c^2/2=a^2 // sqrt +// sqrt(c^2/2)=a +//chamfer_offset = function (c) sqrt((c*c)/2); +chamfer_offset = function (c) c/2; + +rendered_curve_segment_vertices = function (p, v, n, width, height, chamfer) + let (d=normalize(n-p)) let (up=[0, 0, 1]) let (right=normalize(cross(d, up))) [ + //p, v, n, width, height, chamfer_offset(chamfer), d, up, right, + v+up*(height/2)+right*(-width/2+chamfer_offset(chamfer)), + v+up*(height/2)+right*(width/2-chamfer_offset(chamfer)), + v+up*(height/2-chamfer_offset(chamfer))+right*(width/2), + v+up*(-height/2+chamfer_offset(chamfer))+right*(width/2), + v+up*(-height/2)+right*(width/2-chamfer_offset(chamfer)), + v+up*(-height/2)+right*(-width/2+chamfer_offset(chamfer)), + v+up*(-height/2+chamfer_offset(chamfer))+right*(-width/2), + v+up*(height/2-chamfer_offset(chamfer))+right*(-width/2) +]; + +module render_curve(curve_vertices, width, height, chamfer, debug=false) { + /* + * vertex generation order: + * - we generate vertices segment by segment + * - one segement for every curve vertex provided + * - each segment has eight vertices that form the outer ring + * - the corners are chamfered so the vertices are pairs at the corners + * - we start with the top segment and move clockwise + * - top-down axis is determined globally by z-axis unless direction at start vertex is z + * - if direction at start vertes is z, top-down is y-adis instead + * - the left vertex of the top edge is 0, the other is 1 + * - left-right axis is determined by normal between travel direction and up-down axis + * - the last vertex is part of the same corner as 0 but part of the left edge + * - segment edge n has vertices `n` and `(n+1)%8` + * - segment joining edge n has vertices local index `n` of both segments + * - global `i` index of local index `n` for segment `m` is `i=8*m+n` + * - so we have `count=length(curve_vertices)` segments and `count*8` vertices + * - we are not generating a thorus so the faces for our polyhedron are: + * - two eight sided end cap faces + * - `(count-1)*8` four sided mantle faces + * - direction at vertex is the vector from the previonus to the next vertex + * - for the first an last vertex the only neighbor is mirrored around the vertex + * - the start end cap is face `0` + * - the face mantle face n has vertices `[n, +(n+1)%8, n+8, n+8+(n+1)%8]` + * - the stop end cap is face `count*8` + */ + + start = let(v=curve_vertices[0], n=curve_vertices[1]) let(p=v+(v-n)) + rendered_curve_segment_vertices(p, v, n, width, height, chamfer); + echo("len(curve_vertices): ", len(curve_vertices)); + middle = [ for (i=[1:len(curve_vertices)-2]) let( + p = curve_vertices[i-1], + v = curve_vertices[i], + n = curve_vertices[i+1] + ) each rendered_curve_segment_vertices(p, v, n, width, height, chamfer) + ]; + echo("len(middle): ", len(middle)); + stop = let(i=len(curve_vertices)) + let(v=curve_vertices[i-1], p=curve_vertices[i-2]) let(n=v+(v-p)) + rendered_curve_segment_vertices(p, v, n, width, height, chamfer); + + if (debug) { + echo(start); + color("#ff00ff") for (v = start) translate(v+[0, 0, height]) sphere(d=.25, $fn=16); + echo(middle); + color("white") for (v = middle) translate(v+[0, 0, height]) sphere(d=.25, $fn=16); + echo(stop); + color("cyan") for (v = stop) translate(v+[0, 0, height]) sphere(d=.25, $fn=16); + } + + render_vertices = concat(start, middle, stop); + echo("len(render_vertices)", len(render_vertices)); + echo(render_vertices); + + start_cap = [ for (i=[0:1:7]) i]; + echo(start_cap); + mantle = let (M=len(curve_vertices)-1) [ for (m=[0:M-1],n=[0:7]) let (i=m*8+n) + [i, i+8, n==7 ? i+1 : i+8+1, n==7 ? i-7 : i+1] + ]; + echo(mantle); + end_cap = let (m=len(curve_vertices)-1) [ for (i=[m*8+7:-1:m*8]) i ]; + echo(end_cap); + + faces = concat([start_cap], mantle, [end_cap]); + + translate([0, 0, debug ? height : 0]) polyhedron(points=render_vertices, faces=faces); +} + +arc_vertex = function (a, r, t, translate=[0,0,0], remap=id) remap([ + translate.x+cos(a*t)*r, + translate.y+sin(a*t)*r, + translate.z +]); + +arc_vertices = function (a, r, t, x=0, y=0, z=0, remap=id, arc_vertex=arc_vertex) [ + for (i=[0:1/(t-1):1]) arc_vertex(a, r, i, translate=[x,y,z], remap=remap) +]; + +module arc(part, radius, thickness, height, $fn=$fn, outer_remap=id, inner_remap=id, arc_vertices=arc_vertices) { + a = 360 * part; + r = radius+thickness/2; + w = thickness; + h = height; + t = $fn; + + vertices_lower_outer = arc_vertices(a, r , t, z=-h/2, remap=outer_remap); + vertices_lower_inner = arc_vertices(a, r-w, t, z=-h/2, remap=inner_remap); + vertices_upper_outer = arc_vertices(a, r , t, z= h/2, remap=outer_remap); + vertices_upper_inner = arc_vertices(a, r-w, t, z= h/2, remap=inner_remap); + vertices = concat( + vertices_lower_outer, + vertices_lower_inner, + vertices_upper_outer, + vertices_upper_inner + ); + + faces_end1 = [ 0, t, 3*t, 2*t]; + faces_end2 = [ 2*t-1, t-1, 3*t-1, 4*t-1]; + faces_lower = concat( + [ for (i=[t-1:-1:0]) i ], + [ for (i=[t:1:2*t-1]) i ] + ); + faces_upper = concat( + [ for (i=[2*t:1:3*t-1]) i ], + [ for (i=[4*t-1:-1:3*t]) i ] + ); + faces_outer = [ for (i=[0:1:t-2]) [i, 2*t+i, 2*t+i+1, i+1] ]; + faces_inner = [ for (i=[0:1:t-2]) [t+i, t+i+1, 3*t+i+1, 3*t+i] ]; + + faces = concat( + [faces_end1], + [faces_end2], + [faces_lower], + [faces_upper], + faces_outer, + faces_inner + ); + + rotate(a/2) polyhedron(vertices, faces); +} + +module partial_ring(part, radius, thickness, height) { + rotate(180-180*part, [0, 0, 1]) + rotate_extrude(angle=360*part) + translate([radius, 0]) + square([thickness, height], center=true); +}