use ; use ; head_size = 26; segments = 99; thickness = 3; spacing = 0.65; module joint_Y(leng, width, height, ring_offset, thickness) { half_h = height / 2; half_thickness = thickness / 2; inner_leng = leng - thickness * 2; inner_width = width - thickness * 2; // U linear_extrude(height, center = true) difference() { hollow_out(thickness) offset(delta = thickness, chamfer = true) square([inner_leng, inner_width], center = true); translate([-half_thickness - inner_leng / 2, 0, 0]) square([thickness, inner_width], center = true); } // ring r = half_h; offset_x = ring_offset - r / 4; translate([half_h + inner_leng / 2 + half_thickness, 0, 0]) rotate([90, 0, 0]) linear_extrude(thickness, center = true) difference() { hull() { translate([offset_x, 0]) circle(r); translate([-r / 2, 0, 0]) square([r, height], center = true); } translate([offset_x, 0]) circle(r - thickness); } } module moving_fish(head_size, segments, thickness, spacing) { joint_leng = thickness * 2; joint_height = thickness * 2 + spacing * 2; joint_thickness = joint_leng / 3; joint_width = joint_thickness + (spacing + joint_thickness) * 2; ring_offset = joint_thickness / 2; module tri_bone(tri_side_leng) { double_spacing = spacing * 2; tri_r = tri_side_leng * 0.5773502; tri_r_m1 = tri_r - 1; half_tri_r_m1 = tri_r_m1 / 2; slot_leng = joint_thickness + double_spacing; translate([0, 0, half_tri_r_m1 + 1]) { translate([slot_leng, 0, joint_height / 2 - half_tri_r_m1 - 1]) rotate([90, 0, 0]) joint_Y( joint_leng, joint_width, joint_height, joint_thickness/ 2 , joint_thickness ); offset_x = (-tri_r - 1 + joint_width) / 2; rotate([0, -90, 0]) { // triangle linear_extrude(thickness, center = true) difference() { offset(r = 1) circle(tri_r_m1, $fn = 3); // slot translate([offset_x, 0, 0]) square( [ slot_leng, joint_height + double_spacing ], center = true ); } // stick translate([offset_x, 0, 0]) rotate([90, 0, 0]) rotate([0, 90, 0]) linear_extrude(slot_leng, center = true) circle(joint_height / 2 - joint_thickness - spacing); } } } module head(tri_leng) { tri_leng_d2 = tri_leng / 2; tri_leng_d4 = tri_leng / 4; tri_leng_d5 = tri_leng / 5; module eye() { translate([tri_leng_d4, tri_leng_d5, tri_leng_d5]) sphere(tri_leng / 10); } tri_r_m1 = tri_leng * 0.5773502 - 1; mr = tri_leng_d4 * 0.8660254; translate([0, 0, tri_r_m1 / 2 + 1]) rotate([0, -90, 0]) { difference() { hull() { linear_extrude(thickness, center = true) offset(r = 1) circle(tri_r_m1, $fn = 3); translate([tri_leng / 14 * 3, 0, tri_leng_d2]) sphere(mr); translate([-tri_leng_d4, 0, tri_leng_d2]) sphere(mr); } linear_extrude(tri_leng * 1.5, center = true) translate([-tri_leng / 2 - tri_r_m1 / 2 - 1, 0, 0]) square([tri_leng, tri_leng], center = true); translate([0, 0, tri_leng / 1.25]) rotate([90, 0, 0]) scale([0.75, 1, 1]) linear_extrude(tri_leng, center = true) circle(tri_leng / 1.5, $fn = 3); } // eyes eye(); mirror([0, 1, 0]) eye(); } } point_distance = joint_leng + ring_offset + spacing * 3; arm_distance = head_size; init_angle = 540; num_of_points = segments + 2; points_angles = archimedean_spiral( arm_distance = arm_distance, init_angle = init_angle, point_distance = point_distance, num_of_points = num_of_points ); side_leng_step = 0.45 * head_size / segments; // head rotate(init_angle) translate(-points_angles[0][0]) rotate(90) { tri_bone(head_size); head(head_size); } // body leng_pts = len(points_angles); for(i = [1: leng_pts - 2]) { translate(points_angles[i][0]) rotate(points_angles[i][1] + 90) tri_bone(head_size - side_leng_step * i); } tail_r = head_size / 3; // tail translate(points_angles[leng_pts - 1][0]) linear_extrude(joint_height) rotate(90 + points_angles[leng_pts - 2][1]) translate([tail_r / 2, 0, 0]) { difference() { circle(tail_r); translate([tail_r * 0.75, 0, 0]) circle(tail_r); } hollow_out(thickness / 2.4) circle(3 * thickness / 2.4); } } moving_fish(head_size, segments, thickness, spacing, $fn = 24);