$fn = 200;

module torus(r1=1, r2=2, angle=360, $fn=$fn){
    rotate_extrude(convexity=10, $fn=$fn)
    translate([r2, 0, 0])
    circle(r=r1, $fn=$fn);
}

module rounded_cube(size, r=0, $fn=$fn){
    translate([r, r, r]) minkowski(){
        cube([size[0]-r*2, size[1]-r*2, size[2]-r*2]);
        sphere(r, $fn=$fn);
    }
}

module rounded_cube_2d(size, r=0, $fn=$fn){
    translate([r, r, 0]) minkowski(){
        cube([size[0]-r*2, size[1]-r*2, size[2]/2]);
        cylinder(d=r*2, h=size[2]/2, $fn=$fn);
    }
}


wall_d = 1.5;
befestigung_d = 2*wall_d;
sphere_d = 3;
sphere_spiel = 0.2;
sphere_ueberstand = 0.5;
spehre_number = 40;
screw_hole_d = 2.6;


torus_r = (sphere_d / 2) / sin(360 / spehre_number);
torus_inner_r = (sphere_d + sphere_spiel) / 2;
gesamt_h = sphere_d + wall_d - sphere_ueberstand;
gesamt_r = torus_r + torus_inner_r + wall_d;
gesamt_inner_r = torus_r - torus_inner_r - wall_d;

// Asserts
assert(torus_inner_r < torus_r);
assert(torus_inner_r^2 - (torus_inner_r - sphere_ueberstand)^2 < (sphere_d / 2)^2, "Kugeln fallen raus! Überstand oder Spiel reduzieren!");

// Screw holes
    module screw_hole() {
        rotate(a = [0, 90, 0]) 
            cylinder(d=screw_hole_d, h=befestigung_d);
    }

difference() {
    difference() {
        union () {
            //Cylinder
            difference () {
                cylinder(r=gesamt_r, h=gesamt_h);
                cylinder(r=gesamt_inner_r, h=gesamt_h);
            }
            
            
            //Befestigung
            translate([-befestigung_d, -(gesamt_r + gesamt_h + wall_d),0]) {
                rounded_cube_2d ([befestigung_d, (gesamt_r + gesamt_h + wall_d) * 2, gesamt_h], r=0.25);
            }
        }
        translate([0,0,torus_inner_r + wall_d]) {
            torus(r1=torus_inner_r, r2=torus_r);
        }
    }
    
   
    // Only one half halfes
    translate([0,-gesamt_r,0])
        cube([gesamt_r, gesamt_r*2, gesamt_h]);

    // Screw holes
    translate([-befestigung_d,-(gesamt_r + gesamt_h / 2 + wall_d / 2),gesamt_h / 2]) screw_hole();
    translate([-befestigung_d,(gesamt_r + gesamt_h / 2 + wall_d / 2),gesamt_h / 2]) screw_hole();
    translate([-befestigung_d,0,gesamt_h / 2]) screw_hole();
    
}