use <threads-scad/threads.scad>

/*
Schraube MetricCountersunkBolt()
Schraubenloch CountersunkClearanceHole()
Gewindebolzen RodStart() RodEnd()
Mutter MetricNut()
*/

$fn = 300;

module MetricNutShape(diameter, thickness = 0, tolerance = 0.4) {
  thickness = (thickness == 0) ? NutThickness(diameter) : thickness;
  cylinder(h = thickness, r = HexAcrossCorners(diameter) / 2 - 0.5 * tolerance,
           $fn = 6);
}

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);
  }
}

module kugellager_mit_nuts(sphere_number = 330, h = 10 + 0.5) {
  wall_d = 1.5;
  sphere_d = 3;
  sphere_spiel = 0.2;
  sphere_ueberstand = 0.5;
  screws_d = 3;
  screws_inner_number = 2;
  screws_outer_number = 3;
  gesamt_h = h - sphere_ueberstand;
  angle = 90;

  torus_r = (sphere_d / 2) / sin(360 / sphere_number);
  torus_inner_r = (sphere_d + sphere_spiel) / 2;
  gesamt_r = torus_r + torus_inner_r + wall_d;
  gesamt_inner_r = torus_r - torus_inner_r - wall_d;
  befestigung_d = screws_d + 4 * wall_d;

  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!");

  difference() {
    rotate_extrude(convexity = 10, angle = angle, $fn = $fn) {
      difference() {
        square([ gesamt_r, gesamt_h ]);
        square([ gesamt_inner_r, gesamt_h ]);
        translate([
          torus_r, gesamt_h - torus_inner_r + sphere_ueberstand + sphere_spiel,
          0
        ]) circle(r = torus_inner_r, $fn = $fn);
      }
      translate([ gesamt_inner_r - befestigung_d, 0, 0 ])
          square([ 2 * (befestigung_d + torus_inner_r + wall_d), wall_d ]);
    }
    for (r = [
           gesamt_r + befestigung_d / 2, gesamt_inner_r - befestigung_d / 2
         ]) {
      screws_number = (r == gesamt_r + befestigung_d / 2) ? screws_outer_number
                                                          : screws_inner_number;
      for (i = [1:screws_number]) {
        phi = angle / screws_number * (i - 1 / 2);
        translate([ r * cos(phi), r * sin(phi), wall_d / 2 ])
            MetricNutShape(diameter = screws_d);
        translate([ r * cos(phi), r * sin(phi), 0 ])
            cylinder(h = wall_d, r = (screws_d + 0.4) / 2);
      }
    }
  }
}

module kugellager(sphere_number = 330, h = 10 + 0.5, nut_d = 10, wall_d = 1.5) {
  sphere_d = 3;
  sphere_spiel = 0.2;
  sphere_ueberstand = 0.5;
  screws_d = 3;
  screws_inner_number = 2;
  screws_outer_number = 3;
  gesamt_h = h - sphere_ueberstand;
  angle = 360;

  torus_r = (sphere_d / 2) / sin(360 / sphere_number);
  torus_inner_r = (sphere_d + sphere_spiel) / 2;
  gesamt_r = torus_r + torus_inner_r + wall_d;
  gesamt_inner_r = torus_r - torus_inner_r - wall_d;
  befestigung_d = screws_d + 4 * wall_d;

  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!");

  rotate_extrude(convexity = 10, angle = angle, $fn = $fn) {
    difference() {
      square([ gesamt_r, gesamt_h ]);
      square([ gesamt_inner_r, gesamt_h ]);
      translate([
        torus_r, gesamt_h - torus_inner_r + sphere_ueberstand + sphere_spiel, 0
      ]) circle(r = torus_inner_r, $fn = $fn);
    }
  }
  difference() {
    union() {
      cylinder(r = gesamt_r, h = wall_d);
      cylinder(d = 2.5 * nut_d, h = 2 * wall_d);
    }
    MetricNutShape(diameter = nut_d, thickness = wall_d);
    translate([ 0, 0, wall_d ]) cylinder(d = nut_d + 2, h = wall_d);
  }
}