first commit of dogears

This commit is contained in:
tessaK9 2026-04-02 12:19:44 +02:00
commit 615277344f
10 changed files with 711 additions and 0 deletions

View file

@ -0,0 +1,43 @@
// extrusion takes a list of polygons (list of points in 3d space) and connects these into one big polyeder
module extrusion(points){
//points[0] must have its points ordered clockwise
n = len(points);
k = len(points[0]);
points_new = [for(L = points) for(p = L) p];
faces = concat([[for(i = [0 : k-1]) i], [for(i = [1 : k]) (n*k)-i]],
concat([for (i = [0 : n-2]) for (j = [0 : k-2]) [(i*k)+j+1, (i*k)+j, ((i+1)*k)+j, ((i+1)*k)+j+1]], [for (i = [0 : n-2]) [i*k,(i+1)*k-1,((i+2)*k)-1,(i+1)*k]]));
polyhedron(points = points_new, faces = faces, convexity = 10);
}
//ctrl is a list containing 4 control points of the bezier curve. shape is polygon in the 2d plane which is being extruded. mod is a function [0,1] -> |R scaling the shape, mod_x in the x-direction (of the shape), mod_y in the y-direction. if partial is true, then the polyeder is rendered in slices with length given by merlon and gap size given by gap, section defines the number of sections the bezier curve is broken into
module bezier_extrude(ctrl, shape, mod = function (t) 1, mod_x = function(t) 1, mod_y = function (t) 1, partial = false, merlon = 1, gap = 1, sections = 128){
B_0 = ctrl[0];
B_1 = 3*(-ctrl[0] + ctrl[1]);
B_2 = 3*(ctrl[0] - 2*ctrl[1] + ctrl[2]);
B_3 = -ctrl[0] + 3*(ctrl[1] - ctrl[2]) + ctrl[3];
function bezier(t) = B_0 + t*B_1 + (t^2)*B_2 + (t^3)*B_3;
Bn_0 = [B_1.y,-B_1.x];
Bn_1 = [2*B_2.y,(-2)*B_2.x];
Bn_2 = [3*B_3.y,(-3)*B_3.x];
function normal(t) = Bn_0 + t*Bn_1 + (t^2)*Bn_2;
slices = [for (i = [0 : sections])
let (t = i/sections, p = bezier(t), normal = normal(t), n = normal/norm(normal))
[for (v = shape) [p.x+(mod(t) * mod_x(t) * n.x * v.x),p.y+(mod(t) * mod_x(t) * n.y * v.x), mod(t) * mod_y(t) * v.y]]];
if(partial){
for(i = [0 : merlon+gap : sections-merlon]){
extrusion([slices[i],slices[i+merlon]]);
}
}
else{
extrusion(slices);
}
}
//some thing to play around with
shape = [[0,0.5],[0.8,0],[0.5,-1],[-0.5,-1],[-0.8,0]];
ctrl = [[0,0],[0,20],[20,20],[20,0]];
wave1 = function (x) 0.75+0.25*cos(8*360*x);
wave2 = function (x) 0.75+0.25*sin(8*360*x);
bezier_extrude(ctrl = ctrl, shape = shape, mod_x = wave1, mod_y = wave2, partial = true, merlon = 3, gap = 1, sections = 128);

80
scad/base/dogear.scad Normal file
View file

@ -0,0 +1,80 @@
use <hinge.scad>;
//a1, a2, a3, a4 are the four angles of the pairs of hinges on the ear from bottom to tip
module dogearAllOptions(a1, a2, a3, a4){
translate([25,0,0]){
union(){
linear_extrude(height = 6, center = false, convexity = 10){
polygon(points = [[-33,0],[-25,0],[-25,7]]);
}
hinge(a1, len_before = 25, len_after = 5.5);
translate([12.5,0,0]) hinge(a2, len_after = 5.5);
translate([25,0,0]) hinge(a3, len_after = 5.5);
translate([0,37,0]) hinge(a1, len_before = 8, len_after = 5.5);
translate([12.5,37,0]) hinge(a2, len_after = 5.5);
translate([25,37,0]) hinge(a3, len_after = 8);
translate([34,0,0]){
cube([7,18.5,6]);
translate([3.5,18.5,0]) cylinder(h = 6, r = 3.5, center = false, $fn=32);
}
translate([40,40.5,0]) cylinder(h = 6, r = 3.5, center = false, $fn=32);
translate([53,0,0]) cube([24,7,6], center = false);
translate([40,11,0]){
rotate(-45,[0,0,1]){
hinge(a4, len_before = 7, len_after = 7);
translate([14.1,3.5,0]){
cylinder(h = 6, r = 3.5, center = false, $fn=32);
}
translate([0,17.3,0]) hinge(a4, len_before = 21, len_after = 24.6);
translate([31.4,20.8,0]) cylinder(h = 6, r = 3.5, center = false, $fn=32);
}
}
}
}
}
module dogear(flopness){
a1 = 30;
a2 = 30;
a3 = 30;
a4 = 45;
if(flopness == "vvvflop"){
a1 = 45;
a2 = 45;
a3 = 45;
dogearAllOptions(a1, a2, a3, a4);
}
else{
if(flopness == "vvflop"){
a1 = 40;
a2 = 40;
a3 = 40;
dogearAllOptions(a1, a2, a3, a4);
}
else{
if(flopness == "vflop"){
a1 = 35;
a2 = 35;
a3 = 35;
dogearAllOptions(a1, a2, a3, a4);
}
else{
if(flopness == "lflop"){
a1 = 15;
a2 = 15;
a3 = 15;
a4 = 30;
dogearAllOptions(a1, a2, a3, a4);
}
else{
dogearAllOptions(a1, a2, a3, a4);
}
}
}
}
}

46
scad/base/headband.scad Normal file
View file

@ -0,0 +1,46 @@
use <bezier_extrusion.scad>;
module headband(thickness, height){
rake_length = 3;
shape_band = [[thickness/2,height/2-0.4],
[thickness/2,-height/2+0.4],
[thickness/2-0.4,-height/2],
[-thickness/2+0.4,-height/2],
[-thickness/2,-height/2+0.4],
[-thickness/2,height/2-0.4],
[-thickness/2+0.4,height/2],
[thickness/2-0.4,height/2]];
shape_rake = [[0,-height/2],
[0,height/2],
[rake_length,height/2-2],
[rake_length,-height/2+2]];
shape_halfband = [[thickness/2,height/2-0.4],
[thickness/2,-height/2+0.4],
[thickness/2-0.4,-height/2],
[0,-height/2],
[0,height/2],
[thickness/2-0.4,height/2]];
ctrl_band = [[21,0],[77,56],[56,126],[0,126]];
ctrl_end = [[21,0],[20,-1],[18,-4],[17,-8]];
ctrl_rake = [[-52,86],[-40,139.5],[40,139.5],[52,86]];
union(){
bezier_extrude(ctrl = ctrl_band, shape = shape_band, sections = 64);
mirror([1,0,0]) bezier_extrude(ctrl = ctrl_band, shape = shape_band, sections = 64);
bezier_extrude(ctrl = ctrl_end, shape = shape_band, sections = 16);
translate([17,-8]){
rotate_extrude(convexity = 10, $fn = 16) polygon(shape_halfband);
}
mirror([1,0,0]) bezier_extrude(ctrl = ctrl_end, shape = shape_band, sections = 16);
translate([-17,-8]){
rotate_extrude(convexity = 10, $fn = 16) polygon(shape_halfband);
}
bezier_extrude(ctrl = ctrl_rake, shape = shape_rake, partial = true, merlon = 2, gap = 3, sections = (2+3)*42+1);
}
}
headband(thickness = 2.7, height = 5.5);

54
scad/base/hinge.scad Normal file
View file

@ -0,0 +1,54 @@
//deg is the amount in degrees the hinge should be able to pivot, len_before the length of the section before the hinge, len_after the length of the section after the hinge
module hinge(deg, len_before = 0, len_after = 0){
cut_points = [[6,0,5.5],
[6,7,5.5],
[4.5,0,7],
[4.5,7,7],
[6,0,7],
[6,7,7]];
cut_faces = [[0,2,4],
[1,5,3],
[0,1,3,2],
[0,4,5,1],
[2,3,5,4]];
union(){
difference(){
cube([6,7,6], center = false);
polyhedron(points = cut_points, faces = cut_faces, convexity = 10);
translate([3,3.5,3.5]){
rotate(90, [1,0,0]) cylinder(h = 6, r = 2, center = true, $fn = 16);
}
if(deg <= 45){
translate([3,2,4.75]){
rotate(-deg,[0,1,0]){
translate([0,0,-4]){
cube([4,3,4], center = false);
}
}
}
}
else{
translate([1.75,2,3.5]){
rotate(-deg,[0,1,0]){
translate([0,0,-6]){
cube([6,3,6], center = false);
}
}
}
}
translate([4,2,1.5]) cube([4,3,4], center = false);
}
cube([6.5,7,1.5], center = false);
translate([3,3.5,3.5]){
rotate(90, [1,0,0]) cylinder(h = 4.5, r = 1.25, center = true, $fn = 16);
}
translate([3,2.5,2.25]) cube([4,2,2.5], center = false);
translate([-len_before,0,0]) cube([len_before,7,6], center = false);
translate([7,0,0]) cube([len_after,7,6], center = false);
}
}

26
scad/dogears.scad Normal file
View file

@ -0,0 +1,26 @@
use <base/headband.scad>;
use <base/dogear.scad>;
thickness = 2.7;
//options for ears include low flopness ("lflop"), regular flopness ("flop"), high flopness ("vflop"), very high flopness ("vvflop"), very very high flopness ("vvvflop")
module dogears(rightear = "flop", leftear = "flop"){
union() {
translate([54,96,-3]){
rotate(75, [0,0,1]){
dogear(flopness = leftear);
}
}
mirror([1,0,0]){
translate([54,96,-3]){
rotate(75, [0,0,1]){
dogear(flopness = rightear);
}
}
}
//height needs to be 6 since the dogears are 6 high
headband(thickness = thickness, height = 6);
}
}
dogears();

10
scad/test/hingetest.scad Normal file
View file

@ -0,0 +1,10 @@
use <../base/hinge.scad>;
union(){
translate([7,0,0]) cube([5,47,6]);
hinge(15,0,0);
translate([0,10,0]) hinge(30);
translate([0,20,0]) hinge(45);
translate([0,30,0]) hinge(60);
translate([0,40,0]) hinge(90);
}