diff --git a/bezier_circle_approximation.scad b/bezier_circle_approximation.scad new file mode 100644 index 0000000..fd404d2 --- /dev/null +++ b/bezier_circle_approximation.scad @@ -0,0 +1,15 @@ +a=90; + +module bezier_curve(p0, p1, p2, p3) { + // TODO +} + +module /*TODO*/ { + c = /*TODO*/; + bezier_curve( + [0, 1], + [c, 1], + [1, c], + [1, 0] + ); +} diff --git a/catear_headband.scad b/catear_headband.scad index a54398d..2606ce1 100644 --- a/catear_headband.scad +++ b/catear_headband.scad @@ -1,9 +1,58 @@ 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, end_caps=true) { +/** + * 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) { + S = side_len; + s = S/2; + sf = stretch_factor; + bf = bend_factor; + mn = 1.16; // magic number + f=skew*S*0.2; + + a = skew*10; + R = [[cos(a), -sin(a), 0], + [sin(a), cos(a), 0], + [ 0, 0, 1]]; + + A = [ s , 0, 0]; + B = [ S*bf, S*sf*mn, 0] * R; + C = [-S*bf, S*sf*mn, 0] * R; + D = [-s , 0, 0]; + + if (debug) translate([0, 0, height]) rotate(90) bezier_curve_debug([A, B, C, D]); +} + +/** + * 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]; @@ -76,7 +125,7 @@ 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=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, ear_skew=2.0) { $a=size/2*ear_scale; $delta=2*(acos($a/(size*2))-90); @@ -84,7 +133,7 @@ module catear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNES union() { rotate( ear_angle, [0, 0, 1]) { - translate([-ear_offset, 0, 0]) catear( + translate([-ear_offset, 0, 0]) catear_v3( debug=debug, height=height, thickness=thickness, @@ -93,11 +142,40 @@ module catear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNES stretch_factor=ear_stretch_factor, chamfer=chamfer, chamfer_shape=chamfer_shape, - details=details + details=details, + skew=ear_skew + ); + } + rotate( ear_angle, [0, 0, 1]) { + translate([-ear_offset, 0, -2*height]) 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, -height]) 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( + translate([-ear_offset, 0, 0]) catear_v3( debug=false, height=height, thickness=thickness, @@ -106,7 +184,36 @@ module catear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNES stretch_factor=ear_stretch_factor, chamfer=chamfer, chamfer_shape=chamfer_shape, - details=details + details=details, + skew=-ear_skew + ); + } + rotate(-ear_angle, [0, 0, 1]) { + translate([-ear_offset, 0, -2*height]) 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 + ); + } + rotate(-ear_angle, [0, 0, 1]) { + translate([-ear_offset, 0, -height]) 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( @@ -123,4 +230,4 @@ module catear_headband(debug=DEBUG, size=SIZE, height=HEIGHT, thickness=THICKNES }; } -catear_headband(); +rotate(-90) catear_headband(ear_bend_factor=0.15, ear_skew=2, debug=true); diff --git a/headband.scad b/headband.scad index 9a0bab7..768ea3a 100644 --- a/headband.scad +++ b/headband.scad @@ -1,16 +1,10 @@ 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() { + /*chamfer(size=(details)?chamfer:0, child_h=height, child_bot=-height/2, shape=chamfer_shape)*/ union() { color("purple") partial_ring(part, radius=size, thickness=thickness, height=height); rotate( 90-180*part, [0, 0, 1]) diff --git a/pressfit_bunnyears.scad b/pressfit_bunnyears.scad index 7a34637..9c64e2b 100644 --- a/pressfit_bunnyears.scad +++ b/pressfit_bunnyears.scad @@ -8,30 +8,38 @@ $fn=90; EAR_SCALE = 0.5; EAR_BEND_FACTOR = 0.2; EAR_STRETCH_FACTOR = 8; -STEP_SIZE = .5; +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: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)*/ { - echo("i", i, "j", j, "chamfer_", chamfer_); - 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=false - ); - } + 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 69b0e1d..05e2a41 100644 --- a/pressfit_catears.scad +++ b/pressfit_catears.scad @@ -1,5 +1,7 @@ include ; +include ; +use ; use ; use ; use ; @@ -7,9 +9,9 @@ use ; EAR_SCALE = 1.5; EAR_BEND_FACTOR = 0.15; EAR_STRETCH_FACTOR = 1.2; -STEP_SIZE = 1; +STEP_SIZE = 100; -difference() { +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); @@ -17,7 +19,7 @@ difference() { translate([-j*20, 0, 0]) rotate(90, [0, 1, 0]) /*chamfer(size=1, child_h=1, child_bot=-0.5, shape=CHAMFER_SHAPE)*/ - catear( + catear_v1( debug=DEBUG, height=INSERTICLE_Z*1.2, thickness=THICKNESS, @@ -32,3 +34,25 @@ difference() { translate([0, 0, -THICKNESS]) cube([100, 100, THICKNESS], center=true); scale([1, 1, 2]) inserticle(); } + +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, THICKNESS, side_len=SIZE/2*EAR_SCALE, stretch_factor=EAR_STRETCH_FACTOR); + +// a = b + c +// x * a = y * b + c +// y / x = a /(b + c) +// y = x * a /(b + c) diff --git a/primitives.scad b/primitives.scad new file mode 100644 index 0000000..b73deca --- /dev/null +++ b/primitives.scad @@ -0,0 +1,113 @@ +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] + ] +]; + +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); +} + + + +rendered_curve_segment_vertices = function (p, v, n, width, height, chamfer) []; + +module render_curve(curve_vertices, width, height, chamfer) { + start = let(v=curve_vertices[0], n=curve_vertices[1]) let(p=v-n) + rendered_curve_segment_vertices(p, v, n, width, height, chamfer); + middle = [ for (i=[1:len(curve_vertices)-2]) let( + p = curve_vertives[i-1], + v = curve_vertices[i], + n = curve_vertives[i+1] + ) rendered_curve_segment_vertices(p, v, n, width, height, chamfer) + ]; + end = let(i=len(curve_vertices)) let(v=curve_vertices[i], p=curve_vertices[i-1]) let(n=v-p) + rendered_curve_segment_vertices(p, v, n, width, height, chamfer); + + // TODO +} + +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); +}