[Case]: Move holes higher so it's hopefully not necessary to use file

$fn = 32;

thickness = 2.5;

// raspberry pi
case_width = 85;
case_height = 56;
case_radius = 3;
case_hole_d = 2.75;
case_hole_d2 = 6.2;
raspi_thickness = 1.3;
case_depth = 22;
case_margin = 10;

box();
//bottom_part_print();
//right_part_print();
//front_part_print();
//left_part_print();
//rear_part_print();
//top_part_print();
//cam_holder();

module cam_holder() {
	depth = 3;
	width = 14.15;
	height = 14.15;
	hole_d = 7.45;
	hole_r = hole_d / 2;

	lens_width = 7.9;
	lens_height = 7.9;
	lens_depth = 5.25;

	difference() {
		cube([width, height, lens_depth]);
		translate([width / 2 - lens_width / 2, height / 2 - lens_height / 2, 0])
			cube([lens_width, lens_height, lens_depth]);
	}
}

module box() {
	rear_part();
	front_part();
	right_part();
	left_part();
	bottom_part();
	top_part();
}

module top_part_print() {
	translate([0, 0, -case_depth - thickness])
		top_part();
}

module rear_part_print() {
	translate([0, 0, case_width + thickness])
		rotate([0, 90, 0])
			difference() {
				rear_part();
				left_part();
				right_part();
			}
}

module left_part_print() {
	translate([0, 0, thickness])
		rotate([90, 0, 0])
			difference() {
				left_part();
				bottom_part();
				top_part();
			}
}

module right_part_print() {
	translate([0, 0, case_height + thickness])
		rotate([-90, 0, 0])
		difference() {
			right_part();
			bottom_part();
			top_part();
		}
}

module front_part_print() {
	translate([0, 0, thickness])
	rotate([0, -90, 0])
		difference() {
			front_part();
			right_part();
			translate([0, -case_height - thickness,0])
				right_part();
		}
}

module bottom_part_print() {
	bottom_part();
}

module rear_part() {
	height = 5;
	translate([case_width, -2 * thickness, -thickness])
		rotate([90, 0, 90]) {
			difference() {
				round_cube([case_height + 4 * thickness, case_depth + 4 * thickness, thickness], case_radius);
				translate([0, case_depth - height / 4 - height, 0]) {
					translate([thickness + case_height + thickness, 2 * thickness, 0])
						cube([thickness, height / 4 + 2, thickness]);
					translate([thickness, 2 * thickness, 0])
						cube([thickness, height / 4, thickness + 10]);
				}
				translate([2 * thickness + ((case_height - 52) / 2), 2 * thickness + 2.2, -2])
					cube([52.5, 16, thickness + 4]);
                translate([2 * thickness + ((case_height - 52) / 2) + 52.5 - 33, 2 * thickness + 2.2 + 16, 0])
                    cube([33 ,4, thickness]);
			}
		}
}

module front_part() {
	translate([-thickness, -2 * thickness, -thickness])
		rotate([90, 0, 90]) {
			difference() {
				round_cube([case_height + 4 * thickness, case_depth + 4 * thickness, thickness], case_radius);
				translate([2 * thickness + case_height / 2 - 10, 2 * thickness- 0.7, 0])
					cube([20, 2.9, 3.5]);
				translate([2 * thickness + 1.15, 2 * thickness + 8, 0])
					cube([20, 2.2, 3.5]);
			}
		}
}

module top_part() {
	width = 20;
	offset = 10;

	switcher_width = 45;
	switcher_height = 42;
	switcher_board_thickness = 1.6;
	switcher_margin_bottom = 2.2;
	parts_depth = 9;

	translate ([0, 0, case_depth + thickness]) {
		difference() {
			round_cube([case_width, case_height, thickness], case_radius);
			translate([11, switcher_height + 2 * thickness, 0]) {
                union() {
                    translate([0, 2.8, 0])
                        cube([23.7, 2.8, thickness]);
                    cube([switcher_width + 2 * thickness, 4, thickness]);
                }
            }
		}

		translate([offset, - thickness, 0])
			round_cube([width, thickness * 2, thickness], case_radius);
		translate([case_width - width - offset, - thickness, 0])
			round_cube([width, thickness * 2, thickness], case_radius);
		translate([offset, - thickness + case_height, 0])
			round_cube([width, thickness * 2, thickness], case_radius);
		translate([case_width - width - offset, - thickness + case_height, 0])
			round_cube([width, thickness * 2, thickness], case_radius);

		translate([11, 0, thickness]) {
			difference() {
				cube([2 * thickness + switcher_width, 2 * thickness + switcher_height, switcher_margin_bottom + switcher_board_thickness]);
				translate([thickness, thickness, 0])
					cube([switcher_width, switcher_height, switcher_margin_bottom + switcher_board_thickness]);
			}

			translate([thickness, thickness, 0]) {
				linear_extrude(thickness) {
					polygon([[0, 0], [0, 5], [5, 0]]);
					polygon([[0, switcher_height], [0, switcher_height - 5], [5, switcher_height]]);
					polygon([[switcher_width, 0], [switcher_width, 5], [switcher_width - 5, 0]]);
					polygon([[switcher_width, switcher_height], [switcher_width - 5, switcher_height], [switcher_width, switcher_height - 5]]);
				}
			}
		}
	}
}

module left_part() {
	width = 10;
	height = 5;
	offset = 5;
	radius = 2.5;

	translate([0, 0, -thickness])
		rotate([90, 0, 0]) {
			difference() {
				union() {
					round_cube([case_width, case_depth + thickness * 4, thickness], case_radius);
					translate([-width / 2, offset, 0])
						difference() {
							round_cube([width, height, thickness], radius);
							translate([width / 2 - thickness, 0, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([case_width -width / 2, offset, 0])
						difference() {
							round_cube([width, height, thickness], radius);
							translate([width / 2, 0, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([-width / 2, case_depth + thickness * 2 - offset, 0])
						difference()  {
							round_cube([width, height, thickness], radius);
							translate([width / 2 - thickness, height - height / 4, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([case_width -width / 2, case_depth + thickness * 2 - offset, 0])
						difference()  {
							round_cube([width, height, thickness], radius);
							translate([width / 2, height - height / 4, 0])
								cube([thickness, height / 4, thickness]);
						}
				}
				translate([case_width -width / 2, offset, 0]) {
					translate([0, height / 2.5, 0])
						cube([width, height / 5, thickness]);
					rotate([0, 0, 90])
						translate([1 - height / 2 - offset + 3 * (height / 5), -height / 5, 0])
							cube([-1 + height / 2 + offset, height / 5, thickness]);
				}
				translate([6, 2 * thickness + 2.2 + raspi_thickness, 0])
					cube([case_width - 25 - 6, 7, thickness]);
                translate([6 - 0.3, 2 * thickness + 2.2 + raspi_thickness - 0.3, 0])
					cube([8, 3, thickness]);
				translate([-width / 2, offset, 0]) {
					translate([0, height / 2.5, 0])
						cube([width, height / 5, thickness]);
					rotate([0, 0, 90])
						translate([1 - height / 2 - offset + 3 * (height / 5), -width, 0])
							cube([-1 + height / 2 + offset - height / 5, height / 5, thickness]);
				}
			}
		}
}

module right_part() {
	width = 10;
	height = 5;
	offset = 5;
	radius = 2.5;

	translate([0, case_height + thickness, -thickness])
		rotate([90, 0, 0]) {
			difference() {
				union() {
					round_cube([case_width, case_depth + thickness * 4, thickness], case_radius);
					translate([-width / 2, offset, 0])
						difference() {
							round_cube([width, height, thickness], radius);
							translate([width / 2 - thickness, 0, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([case_width -width / 2, offset, 0])
						difference() {
							round_cube([width, height, thickness], radius);
							translate([width / 2, 0, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([-width / 2, case_depth + thickness * 2 - offset, 0])
						difference()  {
							round_cube([width, height, thickness], radius);
							translate([width / 2 - thickness, height - height / 4, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([case_width -width / 2, case_depth + thickness * 2 - offset, 0])
						difference()  {
							round_cube([width, height, thickness], radius);
							translate([width / 2, height - height / 4, 0])
								cube([thickness, height / 4, thickness]);
						}
				}
				translate([-width / 2, offset, 0]) {
					translate([0, height / 2.5, 0])
						cube([width, height / 5, thickness]);
					rotate([0, 0, 90])
						translate([1 - height / 2 - offset + 3 * (height / 5), -width, 0])
							cube([-1 + height / 2 + offset - height / 5, height / 5, thickness]);
				}
				translate([case_width -width / 2, offset, 0]) {
					translate([0, height / 2.5, 0])
						cube([width, height / 5, thickness]);
					rotate([0, 0, 90])
						translate([1 - height / 2 - offset + 3 * (height / 5), -height / 5, 0])
							cube([-1 + height / 2 + offset, height / 5, thickness]);
				}
			}
		}
}

module bottom_part() {
	round_cube([case_width, case_height, thickness], case_radius);

	width = 20;
	offset = 10;
	translate([offset, - thickness, 0])
		round_cube([width, thickness * 2, thickness], case_radius);
	translate([case_width - width - offset, - thickness, 0])
		round_cube([width, thickness * 2, thickness], case_radius);
	translate([offset, - thickness + case_height, 0])
		round_cube([width, thickness * 2, thickness], case_radius);
	translate([case_width - width - offset, - thickness + case_height, 0])
		round_cube([width, thickness * 2, thickness], case_radius);

	translate([3.5, 3.5, 0])
		cylinder(thickness + 2.2, d = case_hole_d2);
	translate([3.5, case_height - 3.5, 0])
		cylinder(thickness + 2.2, d = case_hole_d2);
	translate([3.5 + 58, 3.5, 0])
		cylinder(thickness + 2.2, d = case_hole_d2);
	translate([3.5 + 58, case_height - 3.5, 0])
		cylinder(thickness + 2.2, d = case_hole_d2);

	translate([3.5, 3.5, 0])
		cylinder(thickness + 2.2 + raspi_thickness, d = case_hole_d);
	translate([3.5, case_height - 3.5, 0])
		cylinder(thickness + 2.2 + raspi_thickness, d = case_hole_d);
	translate([3.5 + 58, 3.5, 0])
		cylinder(thickness + 2.2 + raspi_thickness, d = case_hole_d);
	translate([3.5 + 58, case_height - 3.5, 0])
		cylinder(thickness + 2.2 + raspi_thickness, d = case_hole_d);
}

module round_cube(dimensions, radius) {
	// todo: doesn't work for smaller parts where d < x || d < y
	diameter = 2 * radius;
	if (dimensions[0] < diameter || dimensions[1] < diameter) {
		echo("[warning]: Round cubes with dimension lower than diameter doesn't works properly.");
	}

	hull() {
		translate([radius, radius, 0])
			cylinder(dimensions[2], radius, radius);
	   translate([dimensions[0] - radius, radius, 0])
			cylinder(dimensions[2], radius, radius);
		translate([radius, dimensions[1] - radius, 0])
			cylinder(dimensions[2], radius, radius);
		translate([dimensions[0] - radius, dimensions[1] - radius, 0])
			cylinder(dimensions[2], radius, radius);
		}
}

$fn = 32;

thickness = 2.5;

// raspberry pi
case_width = 85;
case_height = 56;
case_radius = 3;
case_hole_d = 2.75;
case_hole_d2 = 6.2;
raspi_thickness = 1.3;
case_depth = 22;
case_margin = 10;

box();
//bottom_part_print();
//right_part_print();
//front_part_print();
//left_part_print();
//rear_part_print();
//top_part_print();
//cam_holder();

module cam_holder() {
	depth = 3;
	width = 14.15;
	height = 14.15;
	hole_d = 7.45;
	hole_r = hole_d / 2;

	lens_width = 7.9;
	lens_height = 7.9;
	lens_depth = 5.25;

	difference() {
		cube([width, height, lens_depth]);
		translate([width / 2 - lens_width / 2, height / 2 - lens_height / 2, 0])
			cube([lens_width, lens_height, lens_depth]);
	}
}

module box() {
	rear_part();
	front_part();
	right_part();
	left_part();
	bottom_part();
	top_part();
}

module top_part_print() {
	translate([0, 0, -case_depth - thickness])
		top_part();
}

module rear_part_print() {
	translate([0, 0, case_width + thickness])
		rotate([0, 90, 0])
			difference() {
				rear_part();
				left_part();
				right_part();
			}
}

module left_part_print() {
	translate([0, 0, thickness])
		rotate([90, 0, 0])
			difference() {
				left_part();
				bottom_part();
				top_part();
			}
}

module right_part_print() {
	translate([0, 0, case_height + thickness])
		rotate([-90, 0, 0])
		difference() {
			right_part();
			bottom_part();
			top_part();
		}
}

module front_part_print() {
	translate([0, 0, thickness])
	rotate([0, -90, 0])
		difference() {
			front_part();
			right_part();
			translate([0, -case_height - thickness,0])
				right_part();
		}
}

module bottom_part_print() {
	bottom_part();
}

module rear_part() {
	height = 5;
	translate([case_width, -2 * thickness, -thickness])
		rotate([90, 0, 90]) {
			difference() {
				round_cube([case_height + 4 * thickness, case_depth + 4 * thickness, thickness], case_radius);
				translate([0, case_depth - height / 4 - height, 0]) {
					translate([thickness + case_height + thickness, 2 * thickness, 0])
						cube([thickness, height / 4 + 2, thickness]);
					translate([thickness, 2 * thickness, 0])
						cube([thickness, height / 4, thickness + 10]);
				}
				translate([2 * thickness + ((case_height - 52) / 2), 2 * thickness + 2.2, -2])
					cube([52, 16, thickness + 4]);
			}
		}
}

module front_part() {
	translate([-thickness, -2 * thickness, -thickness])
		rotate([90, 0, 90]) {
			difference() {
				round_cube([case_height + 4 * thickness, case_depth + 4 * thickness, thickness], case_radius);
				translate([2 * thickness + case_height / 2 - 10, 2 * thickness, 0])
					cube([20, 2.2, 3.5]);
				translate([2 * thickness + 1.15, 2 * thickness + 8, 0])
					cube([20, 2.2, 3.5]);
			}
		}
}

module top_part() {
	width = 20;
	offset = 10;

	switcher_width = 45;
	switcher_height = 42;
	switcher_board_thickness = 1.6;
	switcher_margin_bottom = 2.2;
	parts_depth = 9;

	translate ([0, 0, case_depth + thickness]) {
		difference() {
			round_cube([case_width, case_height, thickness], case_radius);
			translate([11, switcher_height + 2 * thickness, 0])
				cube([switcher_width + 2 * thickness, 4, thickness]);
		}

		translate([offset, - thickness, 0])
			round_cube([width, thickness * 2, thickness], case_radius);
		translate([case_width - width - offset, - thickness, 0])
			round_cube([width, thickness * 2, thickness], case_radius);
		translate([offset, - thickness + case_height, 0])
			round_cube([width, thickness * 2, thickness], case_radius);
		translate([case_width - width - offset, - thickness + case_height, 0])
			round_cube([width, thickness * 2, thickness], case_radius);

		translate([11, 0, thickness]) {
			difference() {
				cube([2 * thickness + switcher_width, 2 * thickness + switcher_height, switcher_margin_bottom + switcher_board_thickness]);
				translate([thickness, thickness, 0])
					cube([switcher_width, switcher_height, switcher_margin_bottom + switcher_board_thickness]);
			}

			translate([thickness, thickness, 0]) {
				linear_extrude(thickness) {
					polygon([[0, 0], [0, 5], [5, 0]]);
					polygon([[0, switcher_height], [0, switcher_height - 5], [5, switcher_height]]);
					polygon([[switcher_width, 0], [switcher_width, 5], [switcher_width - 5, 0]]);
					polygon([[switcher_width, switcher_height], [switcher_width - 5, switcher_height], [switcher_width, switcher_height - 5]]);
				}
			}
		}
	}
}

module left_part() {
	width = 10;
	height = 5;
	offset = 5;
	radius = 2.5;

	translate([0, 0, -thickness])
		rotate([90, 0, 0]) {
			difference() {
				union() {
					round_cube([case_width, case_depth + thickness * 4, thickness], case_radius);
					translate([-width / 2, offset, 0])
						difference() {
							round_cube([width, height, thickness], radius);
							translate([width / 2 - thickness, 0, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([case_width -width / 2, offset, 0])
						difference() {
							round_cube([width, height, thickness], radius);
							translate([width / 2, 0, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([-width / 2, case_depth + thickness * 2 - offset, 0])
						difference()  {
							round_cube([width, height, thickness], radius);
							translate([width / 2 - thickness, height - height / 4, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([case_width -width / 2, case_depth + thickness * 2 - offset, 0])
						difference()  {
							round_cube([width, height, thickness], radius);
							translate([width / 2, height - height / 4, 0])
								cube([thickness, height / 4, thickness]);
						}
				}
				translate([case_width -width / 2, offset, 0]) {
					translate([0, height / 2.5, 0])
						cube([width, height / 5, thickness]);
					rotate([0, 0, 90])
						translate([1 - height / 2 - offset + 3 * (height / 5), -height / 5, 0])
							cube([-1 + height / 2 + offset, height / 5, thickness]);
				}
				translate([6, 2 * thickness + 2.2 + raspi_thickness, 0])
					cube([case_width - 25 - 6, 7, thickness]);
				translate([-width / 2, offset, 0]) {
					translate([0, height / 2.5, 0])
						cube([width, height / 5, thickness]);
					rotate([0, 0, 90])
						translate([1 - height / 2 - offset + 3 * (height / 5), -width, 0])
							cube([-1 + height / 2 + offset - height / 5, height / 5, thickness]);
				}
			}
		}
}

module right_part() {
	width = 10;
	height = 5;
	offset = 5;
	radius = 2.5;

	translate([0, case_height + thickness, -thickness])
		rotate([90, 0, 0]) {
			difference() {
				union() {
					round_cube([case_width, case_depth + thickness * 4, thickness], case_radius);
					translate([-width / 2, offset, 0])
						difference() {
							round_cube([width, height, thickness], radius);
							translate([width / 2 - thickness, 0, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([case_width -width / 2, offset, 0])
						difference() {
							round_cube([width, height, thickness], radius);
							translate([width / 2, 0, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([-width / 2, case_depth + thickness * 2 - offset, 0])
						difference()  {
							round_cube([width, height, thickness], radius);
							translate([width / 2 - thickness, height - height / 4, 0])
								cube([thickness, height / 4, thickness]);
						}
					translate([case_width -width / 2, case_depth + thickness * 2 - offset, 0])
						difference()  {
							round_cube([width, height, thickness], radius);
							translate([width / 2, height - height / 4, 0])
								cube([thickness, height / 4, thickness]);
						}
				}
				translate([-width / 2, offset, 0]) {
					translate([0, height / 2.5, 0])
						cube([width, height / 5, thickness]);
					rotate([0, 0, 90])
						translate([1 - height / 2 - offset + 3 * (height / 5), -width, 0])
							cube([-1 + height / 2 + offset - height / 5, height / 5, thickness]);
				}
				translate([case_width -width / 2, offset, 0]) {
					translate([0, height / 2.5, 0])
						cube([width, height / 5, thickness]);
					rotate([0, 0, 90])
						translate([1 - height / 2 - offset + 3 * (height / 5), -height / 5, 0])
							cube([-1 + height / 2 + offset, height / 5, thickness]);
				}
			}
		}
}

module bottom_part() {
	round_cube([case_width, case_height, thickness], case_radius);

	width = 20;
	offset = 10;
	translate([offset, - thickness, 0])
		round_cube([width, thickness * 2, thickness], case_radius);
	translate([case_width - width - offset, - thickness, 0])
		round_cube([width, thickness * 2, thickness], case_radius);
	translate([offset, - thickness + case_height, 0])
		round_cube([width, thickness * 2, thickness], case_radius);
	translate([case_width - width - offset, - thickness + case_height, 0])
		round_cube([width, thickness * 2, thickness], case_radius);

	translate([3.5, 3.5, 0])
		cylinder(thickness + 2.2, d = case_hole_d2);
	translate([3.5, case_height - 3.5, 0])
		cylinder(thickness + 2.2, d = case_hole_d2);
	translate([3.5 + 58, 3.5, 0])
		cylinder(thickness + 2.2, d = case_hole_d2);
	translate([3.5 + 58, case_height - 3.5, 0])
		cylinder(thickness + 2.2, d = case_hole_d2);

	translate([3.5, 3.5, 0])
		cylinder(thickness + 2.2 + raspi_thickness, d = case_hole_d);
	translate([3.5, case_height - 3.5, 0])
		cylinder(thickness + 2.2 + raspi_thickness, d = case_hole_d);
	translate([3.5 + 58, 3.5, 0])
		cylinder(thickness + 2.2 + raspi_thickness, d = case_hole_d);
	translate([3.5 + 58, case_height - 3.5, 0])
		cylinder(thickness + 2.2 + raspi_thickness, d = case_hole_d);
}

module round_cube(dimensions, radius) {
	// todo: doesn't work for smaller parts where d < x || d < y
	diameter = 2 * radius;
	if (dimensions[0] < diameter || dimensions[1] < diameter) {
		echo("[warning]: Round cubes with dimension lower than diameter doesn't works properly.");
	}

	hull() {
		translate([radius, radius, 0])
			cylinder(dimensions[2], radius, radius);
	   translate([dimensions[0] - radius, radius, 0])
			cylinder(dimensions[2], radius, radius);
		translate([radius, dimensions[1] - radius, 0])
			cylinder(dimensions[2], radius, radius);
		translate([dimensions[0] - radius, dimensions[1] - radius, 0])
			cylinder(dimensions[2], radius, radius);
		}
}


fixed screw mounts locations

fixed screw mounts locations


base mount for rod

base mount for rod

eps = 0.01;
rod_d = 5;
mount_h = 40;

module rod_mount()
{
  base_h = 4;
  base_d = 35;
  // base
  difference()
  {
    cylinder(d=base_d, h=base_h);
    n=5;
    for(i=[0:n-1])
      rotate([0, 0, 1]*(i/n*360))
        translate([base_d/2-5, 0, -eps])
          cylinder(d=3.5, h=base_h+2*eps, $fn=30);
  }
  // main block
  translate([0, 0, base_h])
    difference()
    {
      cylinder(d=rod_d+1.5, h=mount_h, $fn=30);
      cylinder(d=rod_d, h=mount_h+eps, $fn=100);
    }
}

rod_mount();


knob draft ready

knob draft ready


Add minkowski sum to get rounded corners

use <compass.scad>
use <arduino_footprint.scad>
use <battery_footprint.scad>

module support_arm()
{
	thickness = 5;

	difference()
	{
		union()
		{
			arm();
			minkowski()
			{
				cylinder(r=5, h=thickness/3.0);
				translate([20,0,0]) cube(size=[50,150,thickness/3.0], center=true);
			}
		}
		translate([20,-45,0]) nano_connector_footprint(2*thickness);
		translate([20,5,0]) 9V_battery();
		translate([0,5,0]) cube(size=[3,12,2*thickness], center=true);
		translate([40,5,0]) cube(size=[3,12,2*thickness], center=true);
		translate([0,-45,0]) cube(size=[3,12,2*thickness], center=true);
		translate([40,-45,0]) cube(size=[3,12,2*thickness], center=true);
	}
}
projection() support_arm();

use <compass.scad>
use <arduino_footprint.scad>
use <battery_footprint.scad>

thickness = 5;

difference()
{
	union()
	{
		arm();
		translate([20,0,0]) cube(size=[50,150,thickness], center=true);
	}
	translate([20,-45,0]) nano_connector_footprint(2*thickness);
	translate([20,5,0]) 9V_battery();
	translate([0,5,0]) cube(size=[3,12,2*thickness], center=true);
	translate([40,5,0]) cube(size=[3,12,2*thickness], center=true);
	translate([0,-45,0]) cube(size=[3,12,2*thickness], center=true);
	translate([40,-45,0]) cube(size=[3,12,2*thickness], center=true);
}


Fix strap/retainer. Add version imprint to base

use <pin-hinge.scad>;
model_version="UR2 v1.0";
width=40;
half_w=width/2;
length=66;
half_l=length/2;
height=17.5;
lid_height=8;
wall=1;
radius_xy=wall*4;
radius_z=wall*2;
inset=0.75;
strap_height=13;

// debug: check all objects sit on the bed platform
//projection(cut=true) {
translate([width/3,0,-1]) %cube([width*4, length+20, 2], center=true);
union() {
    offset_x=5;
    enclosure_base([-1*(width/2+offset_x),0,height/2+wall/2]);
    enclosure_lid([width/2+offset_x,0,lid_height/2+wall/2]);
    enclosure_straps([width+offset_x*2+20,0,0.75]);
}
//}

// the base
module enclosure_base(offsets) {
    translate(offsets) {
        difference() {
            union() {
                hinged_box(width, length, height, 1);
                // lanyard attach point
                translate([0,-0.5*length-6, -0.5*(height+wall)+2.5]) {
                    difference() {
                        cylinder(r=9, h=5, center=true);
                        union() {
                            cylinder(r=5, h=5, center=true);
                            translate([0, 8.5, 0]) cube([18, 5, 5], center=true);
                        }
                    }
                }
                // lip
                union() {
                    lip_w=wall*1.5;
                    lip_h=6;
                    translate([half_w-lip_w/2,-half_l+20,wall+height/2-1]) cube([lip_w, 10, lip_h], center=true);
                    translate([-half_w+lip_w/2,-half_l+20,wall+height/2-1]) cube([lip_w, 10, lip_h], [0,2,0], center=true);
                    translate([half_w-lip_w/2,-half_l+56,wall+height/2-1]) cube([lip_w, 10, lip_h], center=true);
                    translate([-half_w+lip_w/2,-half_l+56,wall+height/2-1]) cube([lip_w, 10, lip_h], center=true);
                }
            }
            union() {
                // version stamp
                translate([0,0,-height/2+wall-0/0.25]) {
                    #linear_extrude(height=1, center=true)
                        text(model_version, size=4, valign="center", halign="center");
                }

                // aperture for the usb port
                translate([-width/2-wall, -length/2+39.5, height/2-1]) {
                   rotate(90) charge_port(10, 7, wall*2);
                }
                *translate([width/2+wall-1, -length/2+32, height/2-5]) {
                   #cube(5);
                }
                // aperture for the battery port
                translate([width/2+wall-1, -length/2+32, height/2-1]) {
                   rotate(90) #charge_port(10, 7, wall*2);
                }
                // latch push
                translate([0, length/2+width/4-1.25, width/4-2]) rotate([90,0,0]) #cylinder(r=7, h=inset*2, center=true);
            }
        }
    }
}

// the lid
module enclosure_lid(offsets) {
    translate(offsets) rotate([0,180,0]) {
        difference() {
            union() {
                hinged_box(width, length, lid_height, -1);
            }
            #translate([0,12,lid_height/2]) rotate(180) button(10,36,wall*2);
        }

    }
}

module enclosure_straps(offsets) {
    // the strap
    length=60;
    translate(offsets) {
        union() {
            translate([0,0,0]) cube([8, length, 1.5], center=true);
            #translate([0,-length/2+20,0.75]) cube([width-3, 1.5, 1.5], center=true);
            translate([0,-length/2+22,0]) cube([width, 8, 1.5], center=true);
            translate([0,length/2-4,0]) cube([width, 8, 1.5], center=true);
            translate([0,length/2-0.75,1]) cube([width, 1.5, 3], center=true);
        }
    }
}

module retainer(dims, center=false) {
    xdim=dims[0];
    ydim=dims[1];
    zdim=dims[2];
    half_z=zdim/2;
    translate([0, 0, center? half_z/2 : 0]) {
        cube([xdim, ydim, half_z], center=center);
        translate([0,0,half_z]) {
            if (center) {
                cube([xdim-zdim*2, ydim, half_z], center=center);
            }
            else {
                translate([zdim, 0, half_z]) cube([xdim-zdim*2, ydim, half_z], center=center);
            }
        }
    }

}

module outer_ridges(radius, length, bounds) {
    translate([-1*(bounds[0]/2+radius/2), 0]) {
        rotate([180,0,0]) ridge(radius, length, 1);
    }
    translate([bounds[0]/2+radius/2, 0]) {
        rotate([180,0,0]) ridge(radius, length, -1);
    }
}
module ridge(radius, length, orient=1) {
    rotate([0,0,orient<0?0:180])
    translate([-radius/2, 0, radius/2]) difference() {
        rotate([90,0,0]) cylinder(r=radius, h=length, center=true, $fn=12);
        union() {
            translate([0,0,radius/2]) cube([radius*2, length, radius], center=true);
            translate([-radius/2,0,0]) cube([radius, length, radius*2], center=true);
        }
    }
}

module hinged_oval_box(width, length, height, orient) {
    // WIP/not in use
    hull() {
        translate([0, -length/2+5, 2]) {
            resize(newsize=[width, width/2, height]) sphere(d=width, center=true);
        }
        translate([0, +length/2-5, 2]) {
            resize(newsize=[width*1.25, width/2, height]) sphere(d=width, center=true);
        }
    }
}
module hinged_box(width, length, height, orient) {
    hinge_radius=4;
    hinge_y_offset=length/2+radius_xy+hinge_radius/2;
    difference() {
        union() {
            difference() {
                shell(width, length, height, orient);
                translate([0, -1*hinge_y_offset, orient*(height/2)]) {
                  rotate(a=[0,90,0]) translate([0,0,0.25]) {
                        // add clearance for opposite hinge barrels
                      #cylinder(r=hinge_radius,
                                h=width*.66+orient*-hinge_radius*2,
                                center=true);
                  }
                }

            }
            translate([0, -1*hinge_y_offset, orient*(height/2)]) {
              rotate(a=[90,180,0]) translate([0,0,0.25]) {
                  _pin_hinge(width*.66, hinge_radius, orient>0?0:1);
              }
            }
            // the latch
            translate([0,length/2+8.5,orient*(height/2-3)]) {
                translate([0,-1.5,0]) cube([20, wall, 6], center=true);
            }
            if (orient > 0) {
                translate([0,length/2+7.25,height/2+4.5]) {
                    translate([0,-1,-4.5]) cube([10, wall*1.5, 10], center=true);
                    rotate([90, 90, 0]) ridge(1, 10, 1);
                }
            }
        }
        union() {
            if (orient < 0) {
                // lid latch receiver
                translate([0,length/2+7.25,height/2-3]) {
                    difference() {
                        translate([0,0,-1.5]) #cube([10, wall*1.5, 2], center=true);
                        *translate([0,-1,-4.5]) cube([10, wall*1.5, 10], center=true);
                    }
                }
            }
        }
    }
}

module _pin_hinge(h, radius, is_top=0, clearance=0) {
    fingers=5;
    pin_radius=1.5;
    gap=0.25;
    total_gap=(fingers-1)*gap;
    unit_h=(h-total_gap)/fingers;
    rotate([-90,0,0]) rotate([0,90,0]) translate([0,-radius,-1*(h/2)+unit_h/2]) {
        for(i=[0:fingers-1]) {
            if (i%2>0 && is_top) {
                translate([-0.5,0, gap*i+i*unit_h]) {
                    pin_hinge_unit(unit_h, radius, pin_radius, i, gap);
                    translate([radius,radius*2,0]) cube([radius*1.5, radius, unit_h], center=true);
                }
            }
            if (i%2==0 && !is_top) {
                translate([0.5,0, gap*i+i*unit_h]) {
                    pin_hinge_unit(unit_h, radius, pin_radius, i);
                    translate([-1*(radius),radius*2,0]) cube([radius*1.5, radius, unit_h], center=true);
                }
            }
        }
    }
}

module shell(width, length, height, orient=1) {
    difference() {
        union() {
            //cube([2,length, 2], center=true);
            hull() {
                linear_extrude(height=height+wall, center=true) {
                    offset(radius_xy) square([width-radius_xy*2+wall*2, length], center=true);
                }
                translate([0,length/2-wall,0]) {
                    difference() {
                        resize([width, width/2, height]) cylinder(d=width, height=height, center=true);
                        translate([0,-width/4,0]) cube([width, width/2, height], center=true);
                    }
                }
            }
        }
        translate([0,0,orient*wall]) {
            translate([0,length/2-inset, orient*wall]) {
                difference() {
                    resize([width-wall, width/2-wall*4, height+2*wall], auto=true) cylinder(d=width, height=height, center=true);
                    translate([0,-width/4+wall*2,0]) cube([width-wall, width/2-wall*4, height], center=true);
                }
            }
            cube([width, length, height], center=true);
        }
    }
    translate([0,length/2+wall,0]) {
        #cube([width*0.66, wall*2, height], center=true);
    }
}

module radiused_cube(dims, radii, center=true) {
    // radiused box sized to *outer* dimensions
    // flatten the radii to 1/2 height
    rad_x=radii[0];
    rad_y=radii[1];
    rad_z=radii[2];
    w=dims[0]; l=dims[1]; h=dims[2];

    translate([-w/2,-l/2,-h/2]) hull() {
        for(z=[0:1]) {
            translate([rad_x,rad_y,z==0?rad_z:h-rad_z]) {
                resize(newsize=[rad_x, rad_y, rad_z]) sphere(rad_x, center=true);
            }
            translate([w-rad_x,rad_y,z==0?rad_z:h-rad_z]) {
                resize(newsize=[rad_x, rad_y, rad_z]) sphere(rad_x, center=true);
            }
            translate([rad_x,l-rad_y,z==0?rad_z:h-rad_z]) {
                resize(newsize=[rad_x, rad_y, rad_z]) sphere(rad_x, center=true);
            }
            translate([w-rad_x,l-rad_y,z==0?rad_z:h-rad_z]) {
                resize(newsize=[rad_x, rad_y, rad_z]) sphere(rad_x, center=true);
            }
        }
    }
}

module button(radius, length, depth) {
    gap=1;
    difference() {
        linear_extrude(height=depth, twist=0, center=true) {
            difference() {
                offset(r=radius_xy+gap) {
                    circle(radius, center = true);
                    translate([0, 10, 0]) square([radius, radius*2.5], center = true);
                }
                offset(r=radius_xy) {
                    circle(radius, center = true);
                    translate([0, 10, 0]) square([radius, radius*2.5], center = true);
                }
            }
        }
        translate([0,  radius*2.5, 0]) cube([radius*2, radius_xy+gap, depth], center=true);
    }
}

module charge_port(width, height, wall) {
    radius=height/2;
    translate([0, -wall/2, 0]) rotate([90, 0, 0]) hull() {
        linear_extrude(height=wall, center=true) {
            offset(r=2) square([width-4, height-2], center=true);
        }
    }
}

use <pin-hinge.scad>;
width=40;
length=66;
height=17.5;
lid_height=8;
wall=1;
radius_xy=wall*4;
radius_z=wall*2;
inset=0.75;
strap_height=13;

// debug: check all objects sit on the bed platform
//projection(cut=true) {
translate([width/3,0,-1]) %cube([width*4, length+20, 2], center=true);
union() {
    offset_x=5;
    enclosure_base([-1*(width/2+offset_x),0,height/2+wall/2]);
    enclosure_lid([width/2+offset_x,0,lid_height/2+wall/2]);
    enclosure_straps([width+offset_x*2+20,0,0]);
}
//}

// the base
module enclosure_base(offsets) {
    translate(offsets) {
        difference() {
            union() {
                hinged_box(width, length, height, 1);

                // lanyard attach point
                translate([0,-0.5*length-6, -0.5*(height+wall)+2.5]) {
                    difference() {
                        cylinder(r=9, h=5, center=true);
                        union() {
                            cylinder(r=5, h=5, center=true);
                            translate([0, 8.5, 0]) cube([18, 5, 5], center=true);
                        }
                    }
                }
                // lip
                union() {
                    translate([width/2-wall+0.25,-length/2+12,wall+height/2]) cube([wall, 16, 8], center=true);
                    #translate([-width/2+0.25,-length/2+18,wall+height/2]) cube([wall, 16, 8], [0,2,0], center=true);
                    translate([width/2-wall+0.25,-length/2+52,wall+height/2]) cube([wall, 10, 8], center=true);
                    translate([-width/2+0.25,-length/2+50,wall+height/2]) #cube([wall, 10, 8], center=true);
                }
            }
            union() {
                // aperture for the usb port
                translate([-width/2-wall, -length/2+37, height/2-1]) {
                   rotate(90) charge_port(10, 5, wall*2);
                }
                *translate([width/2+wall-1, -length/2+32, height/2-5]) {
                   #cube(5);
                }
                translate([width/2+wall-1, -length/2+32, height/2-1]) {
                   rotate(90) #charge_port(10, 5, wall*2);
                }
                // latch push
                translate([0, length/2+width/4-1.25, width/4-2]) rotate([90,0,0]) #cylinder(r=7, h=inset*2, center=true);
            }
        }
    }
}

// the lid
module enclosure_lid(offsets) {
    translate(offsets) rotate([0,180,0]) {
        difference() {
            union() {
                hinged_box(width, length, lid_height, -1);
            }
            #translate([0,12,lid_height/2]) rotate(180) button(10,36,wall*2);
        }

    }
}

module enclosure_straps(offsets) {
    // the strap
    length=60;
    translate(offsets) {
        union() {
            translate([0,0,0]) cube([8, length, 1.5], center=true);
            #translate([0,-length/2+20,0.75]) cube([width-3, 1.5, 1.5], center=true);
            translate([0,-length/2+22,0]) cube([width, 8, 1.5], center=true);
            translate([0,length/2-4,0]) cube([width, 8, 1.5], center=true);
            translate([0,length/2-0.75,1]) cube([width, 1.5, 3], center=true);
        }
    }
}

module retainer(dims, center=false) {
    xdim=dims[0];
    ydim=dims[1];
    zdim=dims[2];
    half_z=zdim/2;
    translate([0, 0, center? half_z/2 : 0]) {
        cube([xdim, ydim, half_z], center=center);
        translate([0,0,half_z]) {
            if (center) {
                cube([xdim-zdim*2, ydim, half_z], center=center);
            }
            else {
                translate([zdim, 0, half_z]) cube([xdim-zdim*2, ydim, half_z], center=center);
            }
        }
    }

}

module outer_ridges(radius, length, bounds) {
    translate([-1*(bounds[0]/2+radius/2), 0]) {
        rotate([180,0,0]) ridge(radius, length, 1);
    }
    translate([bounds[0]/2+radius/2, 0]) {
        rotate([180,0,0]) ridge(radius, length, -1);
    }
}
module ridge(radius, length, orient=1) {
    rotate([0,0,orient<0?0:180])
    translate([-radius/2, 0, radius/2]) difference() {
        rotate([90,0,0]) cylinder(r=radius, h=length, center=true, $fn=12);
        union() {
            translate([0,0,radius/2]) cube([radius*2, length, radius], center=true);
            translate([-radius/2,0,0]) cube([radius, length, radius*2], center=true);
        }
    }
}

module hinged_oval_box(width, length, height, orient) {
    // WIP/not in use
    hull() {
        translate([0, -length/2+5, 2]) {
            resize(newsize=[width, width/2, height]) sphere(d=width, center=true);
        }
        translate([0, +length/2-5, 2]) {
            resize(newsize=[width*1.25, width/2, height]) sphere(d=width, center=true);
        }
    }
}
module hinged_box(width, length, height, orient) {
    hinge_radius=4;
    hinge_y_offset=length/2+radius_xy+hinge_radius/2;
    difference() {
        union() {
            difference() {
                shell(width, length, height, orient);
                translate([0, -1*hinge_y_offset, orient*(height/2)]) {
                  rotate(a=[0,90,0]) translate([0,0,0.25]) {
                        // add clearance for opposite hinge barrels
                      #cylinder(r=hinge_radius,
                                h=width*.66+orient*-hinge_radius*2,
                                center=true);
                  }
                }

            }
            translate([0, -1*hinge_y_offset, orient*(height/2)]) {
              rotate(a=[90,180,0]) translate([0,0,0.25]) {
                  _pin_hinge(width*.66, hinge_radius, orient>0?0:1);
              }
            }
            // the latch
            translate([0,length/2+8.5,orient*(height/2-3)]) {
                translate([0,-1.5,0]) cube([20, wall, 6], center=true);
            }
            if (orient > 0) {
                translate([0,length/2+7.25,height/2+4.5]) {
                    translate([0,-1,-4.5]) cube([10, wall*1.5, 10], center=true);
                    rotate([90, 90, 0]) ridge(1, 10, 1);
                }
            }
        }
        union() {
            if (orient < 0) {
                // lid latch receiver
                translate([0,length/2+7.25,height/2-3]) {
                    difference() {
                        translate([0,0,-1.5]) #cube([10, wall*1.5, 2], center=true);
                        *translate([0,-1,-4.5]) cube([10, wall*1.5, 10], center=true);
                    }
                }
            }
        }
    }
}

module _pin_hinge(h, radius, is_top=0, clearance=0) {
    fingers=5;
    pin_radius=1.5;
    gap=0.25;
    total_gap=(fingers-1)*gap;
    unit_h=(h-total_gap)/fingers;
    rotate([-90,0,0]) rotate([0,90,0]) translate([0,-radius,-1*(h/2)+unit_h/2]) {
        for(i=[0:fingers-1]) {
            if (i%2>0 && is_top) {
                translate([-0.5,0, gap*i+i*unit_h]) {
                    pin_hinge_unit(unit_h, radius, pin_radius, i, gap);
                    translate([radius,radius*2,0]) cube([radius*1.5, radius, unit_h], center=true);
                }
            }
            if (i%2==0 && !is_top) {
                translate([0.5,0, gap*i+i*unit_h]) {
                    pin_hinge_unit(unit_h, radius, pin_radius, i);
                    translate([-1*(radius),radius*2,0]) cube([radius*1.5, radius, unit_h], center=true);
                }
            }
        }
    }
}

module shell(width, length, height, orient=1) {
    difference() {
        union() {
            //cube([2,length, 2], center=true);
            hull() {
                linear_extrude(height=height+wall, center=true) {
                    offset(radius_xy) square([width-radius_xy*2+wall*2, length], center=true);
                }
                translate([0,length/2-wall,0]) {
                    difference() {
                        resize([width, width/2, height]) cylinder(d=width, height=height, center=true);
                        translate([0,-width/4,0]) cube([width, width/2, height], center=true);
                    }
                }
            }
        }
        translate([0,0,orient*wall]) {
            translate([0,length/2-inset, orient*wall]) {
                difference() {
                    resize([width-wall, width/2-wall*4, height+2*wall], auto=true) cylinder(d=width, height=height, center=true);
                    translate([0,-width/4+wall*2,0]) cube([width-wall, width/2-wall*4, height], center=true);
                }
            }
            cube([width, length, height], center=true);
        }
    }
    translate([0,length/2+wall,0]) {
        #cube([width*0.66, wall*2, height], center=true);
    }
}

module radiused_cube(dims, radii, center=true) {
    // radiused box sized to *outer* dimensions
    // flatten the radii to 1/2 height
    rad_x=radii[0];
    rad_y=radii[1];
    rad_z=radii[2];
    w=dims[0]; l=dims[1]; h=dims[2];

    translate([-w/2,-l/2,-h/2]) hull() {
        for(z=[0:1]) {
            translate([rad_x,rad_y,z==0?rad_z:h-rad_z]) {
                resize(newsize=[rad_x, rad_y, rad_z]) sphere(rad_x, center=true);
            }
            translate([w-rad_x,rad_y,z==0?rad_z:h-rad_z]) {
                resize(newsize=[rad_x, rad_y, rad_z]) sphere(rad_x, center=true);
            }
            translate([rad_x,l-rad_y,z==0?rad_z:h-rad_z]) {
                resize(newsize=[rad_x, rad_y, rad_z]) sphere(rad_x, center=true);
            }
            translate([w-rad_x,l-rad_y,z==0?rad_z:h-rad_z]) {
                resize(newsize=[rad_x, rad_y, rad_z]) sphere(rad_x, center=true);
            }
        }
    }
}

module button(radius, length, depth) {
    gap=1;
    difference() {
        linear_extrude(height=depth, twist=0, center=true) {
            difference() {
                offset(r=radius_xy+gap) {
                    circle(radius, center = true);
                    translate([0, 10, 0]) square([radius, radius*2.5], center = true);
                }
                offset(r=radius_xy) {
                    circle(radius, center = true);
                    translate([0, 10, 0]) square([radius, radius*2.5], center = true);
                }
            }
        }
        translate([0,  radius*2.5, 0]) cube([radius*2, radius_xy+gap, depth], center=true);
    }
}

module charge_port(width, height, wall) {
    radius=height/2;
    translate([0, -wall/2, 0]) rotate([90, 0, 0]) hull() {
        linear_extrude(height=wall, center=true) {
            offset(r=2) square([width-4, height-2], center=true);
        }
    }
}


shoulder spacers compelete

shoulder spacers compelete

use <StepMotor_28BYJ-48.scad>;
use <Hub_28BYJ-48.scad>;
include <Bearing_6807-2RS.scad>;

// global rendering parameters
$fn = 24;

// library examples
// translate([100, 100, 10]) { StepMotor28BYJ(); }
// stepperHub(10, 7, 6, 3.1, 1.5, 2.75);
//translate([0, 0, 8]) bearing6807_2RS();
// bearingInnerStep(bearing6807_2RS_d - iFitAdjust, 2, 2);
//shoulderBase(2, 55, 9.1, 3.1);

// interference fit adjustment for 3D printer
iFitAdjust = .4;

// shoulder base parameters
shoulderBaseHeight = 3;
shoulderBaseDiameter = 55;
shaftBossDiameter = 10;
mountScrewDiameter = 3.1;
bearingStep = 2; // size in mm of bearing interface step
// joint parameters
hubHeight = 10;
hubRadius = 7;
shaftHeight = 6;
shaftRadius = 3.1;
setScrewRadius = 1.5;
setScrewHeight = 2.75;
spokeWidth = 3;
spokes = 6;
screwTabs = 4;
screwTabHeight = 4;
armLength = 100;
// misc
baseDeckExtension = 60;
boundingBox = 8;
boundingBoxHalf = boundingBox / 2;
// 8 is distance from shaft center to screw center on x axis
// 35 is screw center to screw center on y axis
shaftCenterToMountHoldCenterXAxis = 8;
mountHoleCenterToMountHoleCenter = 35;
leadScrewDiameter = 8;
// forearm
forearmLength = 75;

/* Pieces in this model
** Shoulder:
*** Base plate
*** Top plate
*** Lower arm
*** Upper arm
** Forearm:
*** ?
** Hand:
*** ?
*/

// shoulder base
color([.7, .7, 1])
    shoulderBase(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// shoulder lower stepper
rotate([0, 180, 0])
    translate([-8, 0, 10])
        StepMotor28BYJ();
// lower shoulder bearing
translate([0, 0, shoulderBaseHeight + bearingStep])
    %bearing6807_2RS();
// shoulder top
color([.6, .6, .9])
    translate([0, 0, 2 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep)])
    rotate([180, 0, 0])
        shoulderBase(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// upper shoulder bearing
translate([0, 0, shoulderBaseHeight + (3 * bearing6807_2RS_B) + (7 * bearingStep)])
    %bearing6807_2RS();
// shoulder upper stepper
rotate([0, 0, 180])
    translate([-8, 0, 10 + 2 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep)])
        StepMotor28BYJ();
// shoulder spacers
color([.7, .6, .2])
shoulderSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
// end shoulder

// lower arm including the shoulder - arm joint
//render()
color([1, .7, .7])
    translate([0, 0, shoulderBaseHeight + bearing6807_2RS_B])
        armLower(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength);
// upper arm
//render()
color([.9, .7, .7])
    translate([0, 0, shoulderBaseHeight + ( 2*bearing6807_2RS_B) + (12 * bearingStep) - (.5 * bearingStep)])
        rotate([180, 0, 0])
            armLower(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength);
// elbow joint pieces
// lower bearing
translate([-armLength, 0, shoulderBaseHeight + bearing6807_2RS_B + bearingStep])
    %bearing6807_2RS();
// arm upper stepper
translate([-armLength + 8, 0, shoulderBaseHeight + ( 3*bearing6807_2RS_B) + (16 * bearingStep) - (.5 * bearingStep)])
    rotate([0, 0, 180])
        StepMotor28BYJ();
// arm lower stepper
rotate([0, 180, 0])
    translate([armLength - 8, 0, bearingStep * 2])
        StepMotor28BYJ();
// arm spacers
color([.6, .6, .3])
    armSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
// end arm

// forearm pieces
// lower
color([.1, .7, .1])
translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (4 *bearingStep)])
//translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (14 *bearingStep)])
    forearmLower(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight + (bearing6807_2RS_B / 2) + (bearingStep/2), hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox);
// upper
color([.2, .8, .2])
translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (4 *bearingStep)])
    rotate([180, 0, 0])
        forearmLower(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight + (bearing6807_2RS_B / 2) + (bearingStep/2), hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox);
// forearm upper bearing
translate([-armLength, 0, shoulderBaseHeight + (2 * bearing6807_2RS_B) + (7 * bearingStep)])
    %bearing6807_2RS();
// forearm spacers

/*
deprecated
render()
    translate([-armLength, 0, shoulderBaseHeight + bearing6807_2RS_B + (2* bearingStep)])
        armJointSpacer(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, shaftBossDiameter, mountScrewDiameter);
*/

//bearingInnerStep(bearing6807_2RS_d - iFitAdjust, 2, 2);
module bearingInnerStep(bearingID, stepHeight, stepWidth) {
    difference() {
        union() {
            // this fits inside of the bearing
            cylinder(h = stepHeight * 2, d = bearingID);
            // this rests on the bearing inner lip
            cylinder(h = stepHeight, d = bearingID + stepWidth);
        }
        // remove center
        cylinder(h = stepHeight * 2, d = bearingID - (stepWidth * 2));
    }
}

//translate([0, 0, 12]) bearingOuterStep(bearing6807_2RS_D + iFitAdjust, 2, 2);
module bearingOuterStep(bearingOD, stepHeight, stepWidth) {
    //render(convexivity = 3)
    difference() {
        cylinder(h = stepHeight * 2, d = bearingOD + stepWidth);
        cylinder(h = stepHeight * 2, d = bearingOD - stepWidth);
        cylinder(h = stepHeight, d = bearingOD);
    }
}

module shoulderSpacers(bearingOD, screwSpacerHeight) {
    union() {
        // screw holes for joining to arm
        rotate([0, 0, -30])
        radial_array_partial(vec = [0, 0, 1], n = 6, 2)
            translate([bearingOD / 2 + (setScrewRadius * 8), 0, shoulderBaseHeight * 1.0])
        difference() {
            union () {
                cylinder(h = screwSpacerHeight, r = setScrewRadius * 2);

                }
            cylinder(h = screwTabHeight, r = setScrewRadius);
        }
    }
}

module armSpacers(bearingOD, screwSpacerHeight) {
    union() {
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = 4)
            translate([bearingOD / 2 + (setScrewRadius * 2), 0, shoulderBaseHeight + bearing6807_2RS_B + 2 * bearingStep])
        difference() {
            union () {
                cylinder(h = bearing6807_2RS_B * 2 + 4 * bearingStep, r = setScrewRadius * 2);

                }
            cylinder(h = bearing6807_2RS_B * 2 + 4 * bearingStep, r = setScrewRadius);
        }
    }
}

// armJointSpacer(bearing6807_2RS_D - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, shaftBossDiameter, mountScrewDiameter);
module armJointSpacer(bearingID, bearingOD, bearingStep, shaftBossDiameter, mountScrewDiameter) {
    union() {
        difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
            cylinder(h = bearingStep * 2, d = bearingID);
        }
        translate([0, 0, bearingStep * 2])
                bearingInnerStep(bearingID, bearingStep, bearingStep);
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * bearingStep) - screwTabHeight])
                    difference() {
                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }
                        cylinder(h = screwTabHeight, r = setScrewRadius);
                    }
    }
}

//shoulderBase(2, 55, 9.1, 3.1);
// WARNING: has some hard-coded non-parametric values in here!
module shoulderBase(bearingID, bearingOD, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter) {
    mountHoleDepth = shoulderBaseHeight;

    //render(convexivity = 3)
    difference() {
        union () {
            cylinder(h = shoulderBaseHeight, d = shoulderBaseDiameter);
            translate([0, 0, shoulderBaseHeight])
                bearingInnerStep(bearing6807_2RS_d - iFitAdjust, bearingStep, bearingStep);
            // 40 is the length of deck extension from the baseplate in x
            translate([0, -shoulderBaseDiameter / 2, 0])
                cube([baseDeckExtension, shoulderBaseDiameter, shoulderBaseHeight], center = false);
        }
        // motor shaft hole
        cylinder(h = shoulderBaseHeight + (bearingStep * 2), d = shaftBossDiameter);
        // mounting holes

        translate([shaftCenterToMountHoldCenterXAxis, mountHoleCenterToMountHoleCenter/2, 0])
            cylinder(h = mountHoleDepth, d = mountScrewDiameter);
        translate([shaftCenterToMountHoldCenterXAxis, -mountHoleCenterToMountHoleCenter/2, 0])
            cylinder(h = mountHoleDepth, d = mountScrewDiameter);
        // lead screw hole
        translate([baseDeckExtension - (leadScrewDiameter * 1.5), 0, 0])
            cylinder(h = shoulderBaseHeight, d = leadScrewDiameter + (leadScrewDiameter / 2));
        // upper to lower spacer screw holes
        rotate([0, 0, -30])
            radial_array_partial(vec = [0, 0, 1], n = 6, 2)
                translate([bearingOD / 2 + (setScrewRadius * 6), 0, shoulderBaseHeight * 0])
                    cylinder(h = screwTabHeight, r = setScrewRadius);

    }
    // NOTE: need to add LM8UU mounts
}

module armLower(bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength) {
    armWidth = bearingOD / 2;
    //render(convexivity = 3)
    difference() {
    union() {
        armInnerJoint(bearingOD, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight);
        translate([-armLength, 0, 0])
            armOuterJointBase(bearingOD, bearingStep, setScrewRadius, screwTabs, screwTabHeight);
        difference() {
            translate([-armLength, -armWidth / 2, 0])
                cube([armLength, armWidth, bearingStep * 2], center=false);
            cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-armLength, 0, 0])
                cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-armLength + (bearingOD / 2) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                cube([armLength - bearingOD - (boundingBox + boundingBoxHalf), armWidth - boundingBox, bearingStep * 2], center = false);
        }
        difference() {
            intersection() {

                translate([-armLength + (bearingOD / 2) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                    cube([armLength - bearingOD - boundingBox, armWidth - boundingBox, bearingStep * 2], center = false);
                for (i = [ bearingOD / 2 - boundingBoxHalf: armWidth : armLength]) {
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, 45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, -45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                }
            }

        }
   }
           // screw holes for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])
                       cylinder(h = screwTabHeight, r = setScrewRadius);
   }
}

module armOuterJointBase(bearingOD, bearingStep, setScrewRadius, screwTabs, screwTabHeight) {
    mountHoleDepth = bearingStep * 2;

    union() {
        difference() {
            union() {
                translate([0, 0, -(bearingStep * 2)])
                    cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
                translate([0, 0, bearingStep * 2])
                    rotate([0, 180, 0])
                        bearingOuterStep(bearingOD, bearingStep, bearingStep);
            }
            // motor shaft hole
            translate([0, 0, -(bearingStep * 2)])
                cylinder(h = shoulderBaseHeight + (bearingStep * 2), d = shaftBossDiameter);
            // mounting holes
            translate([0, 0, -(bearingStep * 2)]) {
                translate([shaftCenterToMountHoldCenterXAxis, mountHoleCenterToMountHoleCenter/2, 0])
                cylinder(h = mountHoleDepth, d = mountScrewDiameter);
                translate([shaftCenterToMountHoldCenterXAxis, -mountHoleCenterToMountHoleCenter/2, 0])
                cylinder(h = mountHoleDepth, d = mountScrewDiameter);
            }
        }

    }
}

//armInnerJoint(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight);
module armInnerJoint(bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight) {
    //translate([0, 0, hubHeight - (2 * stepHeight)])
    difference() {
        union() {
         difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + (setScrewRadius * 6));
            cylinder(h = bearingStep * 2, d = bearingOD);
//            translate([0, -bearingOD, 0])
//                cube([bearingOD, bearingOD * 2, bearingStep * 2]);
        }
        bearingOuterStep(bearingOD, stepHeight, stepWidth);
        // hub
        translate([0, 0, -(hubHeight - (2 * stepHeight))])
            stepperHub(hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight);
        // spokes
        radial_array(vec=[0, 0, 1], n = spokes)
                translate([hubRadius - (stepWidth / 2), -(spokeWidth / 2), stepHeight])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, stepHeight], center = false);
        // screw tabs for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])

                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }

                    }
        // screw holes for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])
                       cylinder(h = screwTabHeight, r = setScrewRadius);
    }
}

module forearmLower(bearingID, bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox) {
    armWidth = bearingOD / 2;

    rotate([180, 0, 0]) union() {
        boundingBoxHalf = boundingBox / 2;
        difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
            cylinder(h = bearingStep * 2, d = bearingID - (2 * bearingStep));
        }
        translate([0, 0, bearingStep * 2])
            bearingInnerStep(bearingID, bearingStep, bearingStep);
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * bearingStep) - screwTabHeight])
                    difference() {
                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }
                        cylinder(h = screwTabHeight, r = setScrewRadius);
                    }
        // hub
        translate([0, 0, hubHeight]) rotate([180, 0, 0])
            stepperHub(hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight);
        // spokes
        radial_array(vec=[0, 0, 1], n = spokes)
                translate([hubRadius - (stepWidth / 2), -(spokeWidth / 2), 0])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, 2 *stepHeight], center = false);
        // forearm extension
             difference() {
            translate([-forearmLength, -armWidth / 2, 0])
                cube([forearmLength, armWidth, bearingStep * 2], center=false);
            cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-forearmLength, 0, 0])
                cylinder(h = bearingStep * 2, d = bearingOD / 2);
                 // 4 on next line comes from dividing the bearingOD on the above line
            translate([-forearmLength + (bearingOD / 4) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                cube([forearmLength - (bearingOD/2) - (boundingBox + boundingBoxHalf), armWidth - boundingBox, bearingStep * 2], center = false);
        }

            intersection() {

                translate([-forearmLength + boundingBox * 2, -(armWidth / 2) + boundingBoxHalf, 0])
                    cube([forearmLength - (bearingOD / 2) - boundingBox, armWidth - boundingBox, bearingStep * 2], center = false);
                for (i = [ bearingOD / 2 - boundingBoxHalf: armWidth : forearmLength]) {
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, 45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, -45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                }
            }

    }
}

module copy_mirror(vec=[0,1,0]) {
    children();
    mirror(vec)
        children();
}

module radial_array(vec = [0,0,1], n = 4) {
    for ( i = [0 : n - 1] )
    {
        rotate( i * 360 / n, vec)
            children();
    }
}

module radial_array_partial(vec = [0,0,1], n = 4, j = 2) {
    for ( i = [0 : n - 1] )
    {
        if (i < j)
            rotate( i * 360 / n, vec)
                children();
    }
}

use <StepMotor_28BYJ-48.scad>;
use <Hub_28BYJ-48.scad>;
include <Bearing_6807-2RS.scad>;

// global rendering parameters
$fn = 24;

// library examples
// translate([100, 100, 10]) { StepMotor28BYJ(); }
// stepperHub(10, 7, 6, 3.1, 1.5, 2.75);
//translate([0, 0, 8]) bearing6807_2RS();
// bearingInnerStep(bearing6807_2RS_d - iFitAdjust, 2, 2);
//shoulderBase(2, 55, 9.1, 3.1);

// interference fit adjustment for 3D printer
iFitAdjust = .4;

// shoulder base parameters
shoulderBaseHeight = 3;
shoulderBaseDiameter = 55;
shaftBossDiameter = 10;
mountScrewDiameter = 3.1;
bearingStep = 2; // size in mm of bearing interface step
// joint parameters
hubHeight = 10;
hubRadius = 7;
shaftHeight = 6;
shaftRadius = 3.1;
setScrewRadius = 1.5;
setScrewHeight = 2.75;
spokeWidth = 3;
spokes = 6;
screwTabs = 4;
screwTabHeight = 4;
armLength = 100;
// misc
baseDeckExtension = 60;
boundingBox = 8;
boundingBoxHalf = boundingBox / 2;
// 8 is distance from shaft center to screw center on x axis
// 35 is screw center to screw center on y axis
shaftCenterToMountHoldCenterXAxis = 8;
mountHoleCenterToMountHoleCenter = 35;
leadScrewDiameter = 8;
// forearm
forearmLength = 75;

/* Pieces in this model
** Shoulder:
*** Base plate
*** Top plate
*** Lower arm
*** Upper arm
** Forearm:
*** ?
** Hand:
*** ?
*/

// shoulder base
//color([.7, .7, 1])
    %shoulderBase(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// shoulder lower stepper
rotate([0, 180, 0])
    translate([-8, 0, 10])
        StepMotor28BYJ();
// lower shoulder bearing
translate([0, 0, shoulderBaseHeight + bearingStep])
    %bearing6807_2RS();
// shoulder top
//color([.6, .6, .9])
    translate([0, 0, 2 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep)])
    rotate([180, 0, 0])
        %shoulderBase(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter);
// upper shoulder bearing
translate([0, 0, shoulderBaseHeight + (3 * bearing6807_2RS_B) + (7 * bearingStep)])
    %bearing6807_2RS();
// shoulder upper stepper
rotate([0, 0, 180])
    translate([-8, 0, 10 + 2 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep)])
        StepMotor28BYJ();
// shoulder spacers
shoulderSpacers(bearing6807_2RS_D + iFitAdjust, 0 * shoulderBaseHeight + (4 * bearing6807_2RS_B) + (8 * bearingStep));
// end shoulder

// lower arm including the shoulder - arm joint
//render()
color([1, .7, .7])
    translate([0, 0, shoulderBaseHeight + bearing6807_2RS_B])
        armLower(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength);
// upper arm
//render()
color([.9, .7, .7])
    translate([0, 0, shoulderBaseHeight + ( 2*bearing6807_2RS_B) + (12 * bearingStep) - (.5 * bearingStep)])
        rotate([180, 0, 0])
            armLower(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength);
// elbow joint pieces
// lower bearing
translate([-armLength, 0, shoulderBaseHeight + bearing6807_2RS_B + bearingStep])
    %bearing6807_2RS();
// arm upper stepper
translate([-armLength + 8, 0, shoulderBaseHeight + ( 3*bearing6807_2RS_B) + (16 * bearingStep) - (.5 * bearingStep)])
    rotate([0, 0, 180])
        StepMotor28BYJ();
// arm lower stepper
rotate([0, 180, 0])
    translate([armLength - 8, 0, bearingStep * 2])
        StepMotor28BYJ();
// forearm pieces
// lower
color([.1, .7, .1])
translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (4 *bearingStep)])
//translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (14 *bearingStep)])
    forearmLower(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight + (bearing6807_2RS_B / 2) + (bearingStep/2), hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox);
// upper
color([.2, .8, .2])
translate([-armLength, 0, shoulderBaseHeight + (bearing6807_2RS_B * 2) + (4 *bearingStep)])
    rotate([180, 0, 0])
        forearmLower(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight + (bearing6807_2RS_B / 2) + (bearingStep/2), hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox);
// forearm upper bearing
translate([-armLength, 0, shoulderBaseHeight + (2 * bearing6807_2RS_B) + (7 * bearingStep)])
    %bearing6807_2RS();
// forearm spacers

/*
deprecated
render()
    translate([-armLength, 0, shoulderBaseHeight + bearing6807_2RS_B + (2* bearingStep)])
        armJointSpacer(bearing6807_2RS_d - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, shaftBossDiameter, mountScrewDiameter);
*/

//bearingInnerStep(bearing6807_2RS_d - iFitAdjust, 2, 2);
module bearingInnerStep(bearingID, stepHeight, stepWidth) {
    difference() {
        union() {
            // this fits inside of the bearing
            cylinder(h = stepHeight * 2, d = bearingID);
            // this rests on the bearing inner lip
            cylinder(h = stepHeight, d = bearingID + stepWidth);
        }
        // remove center
        cylinder(h = stepHeight * 2, d = bearingID - (stepWidth * 2));
    }
}

//translate([0, 0, 12]) bearingOuterStep(bearing6807_2RS_D + iFitAdjust, 2, 2);
module bearingOuterStep(bearingOD, stepHeight, stepWidth) {
    //render(convexivity = 3)
    difference() {
        cylinder(h = stepHeight * 2, d = bearingOD + stepWidth);
        cylinder(h = stepHeight * 2, d = bearingOD - stepWidth);
        cylinder(h = stepHeight, d = bearingOD);
    }
}

module shoulderSpacers(bearingOD, screwSpacerHeight) {
    render() union() {
        // screw holes for joining to arm
        rotate([0, 0, -30])
        radial_array_partial(vec = [0, 0, 1], n = 6, 2)
            translate([bearingOD / 2 + (setScrewRadius * 6), 0, shoulderBaseHeight * 1.0])
        difference() {
            union () {
                cylinder(h = screwSpacerHeight, r = setScrewRadius * 2);

                }
            cylinder(h = screwTabHeight, r = setScrewRadius);
        }
    }
}

// armJointSpacer(bearing6807_2RS_D - iFitAdjust, bearing6807_2RS_D + iFitAdjust, bearingStep, shaftBossDiameter, mountScrewDiameter);
module armJointSpacer(bearingID, bearingOD, bearingStep, shaftBossDiameter, mountScrewDiameter) {
    union() {
        difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
            cylinder(h = bearingStep * 2, d = bearingID);
        }
        translate([0, 0, bearingStep * 2])
                bearingInnerStep(bearingID, bearingStep, bearingStep);
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * bearingStep) - screwTabHeight])
                    difference() {
                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }
                        cylinder(h = screwTabHeight, r = setScrewRadius);
                    }
    }
}

//shoulderBase(2, 55, 9.1, 3.1);
// WARNING: has some hard-coded non-parametric values in here!
module shoulderBase(bearingID, bearingOD, shoulderBaseHeight, shoulderBaseDiameter, shaftBossDiameter, mountScrewDiameter) {
    mountHoleDepth = shoulderBaseHeight;

    //render(convexivity = 3)
    difference() {
        union () {
            cylinder(h = shoulderBaseHeight, d = shoulderBaseDiameter);
            translate([0, 0, shoulderBaseHeight])
                bearingInnerStep(bearing6807_2RS_d - iFitAdjust, bearingStep, bearingStep);
            // 40 is the length of deck extension from the baseplate in x
            translate([0, -shoulderBaseDiameter / 2, 0])
                cube([baseDeckExtension, shoulderBaseDiameter, shoulderBaseHeight], center = false);
        }
        // motor shaft hole
        cylinder(h = shoulderBaseHeight + (bearingStep * 2), d = shaftBossDiameter);
        // mounting holes

        translate([shaftCenterToMountHoldCenterXAxis, mountHoleCenterToMountHoleCenter/2, 0])
            cylinder(h = mountHoleDepth, d = mountScrewDiameter);
        translate([shaftCenterToMountHoldCenterXAxis, -mountHoleCenterToMountHoleCenter/2, 0])
            cylinder(h = mountHoleDepth, d = mountScrewDiameter);
        // lead screw hole
        translate([baseDeckExtension - (leadScrewDiameter * 1.5), 0, 0])
            cylinder(h = shoulderBaseHeight, d = leadScrewDiameter + (leadScrewDiameter / 2));
        // upper to lower spacer screw holes
        rotate([0, 0, -30])
            radial_array_partial(vec = [0, 0, 1], n = 6, 2)
                translate([bearingOD / 2 + (setScrewRadius * 6), 0, shoulderBaseHeight * 0])
                    cylinder(h = screwTabHeight, r = setScrewRadius);

    }
    // NOTE: need to add LM8UU mounts
}

module armLower(bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight, armLength) {
    armWidth = bearingOD / 2;
    //render(convexivity = 3)
    difference() {
    union() {
        armInnerJoint(bearingOD, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight);
        translate([-armLength, 0, 0])
            armOuterJointBase(bearingOD, bearingStep, setScrewRadius, screwTabs, screwTabHeight);
        difference() {
            translate([-armLength, -armWidth / 2, 0])
                cube([armLength, armWidth, bearingStep * 2], center=false);
            cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-armLength, 0, 0])
                cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-armLength + (bearingOD / 2) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                cube([armLength - bearingOD - (boundingBox + boundingBoxHalf), armWidth - boundingBox, bearingStep * 2], center = false);
        }
        difference() {
            intersection() {

                translate([-armLength + (bearingOD / 2) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                    cube([armLength - bearingOD - boundingBox, armWidth - boundingBox, bearingStep * 2], center = false);
                for (i = [ bearingOD / 2 - boundingBoxHalf: armWidth : armLength]) {
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, 45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, -45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                }
            }

        }
   }
           // screw holes for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])
                       cylinder(h = screwTabHeight, r = setScrewRadius);
   }
}

module armOuterJointBase(bearingOD, bearingStep, setScrewRadius, screwTabs, screwTabHeight) {
    mountHoleDepth = bearingStep * 2;

    union() {
        difference() {
            union() {
                translate([0, 0, -(bearingStep * 2)])
                    cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
                translate([0, 0, bearingStep * 2])
                    rotate([0, 180, 0])
                        bearingOuterStep(bearingOD, bearingStep, bearingStep);
            }
            // motor shaft hole
            translate([0, 0, -(bearingStep * 2)])
                cylinder(h = shoulderBaseHeight + (bearingStep * 2), d = shaftBossDiameter);
            // mounting holes
            translate([0, 0, -(bearingStep * 2)]) {
                translate([shaftCenterToMountHoldCenterXAxis, mountHoleCenterToMountHoleCenter/2, 0])
                cylinder(h = mountHoleDepth, d = mountScrewDiameter);
                translate([shaftCenterToMountHoldCenterXAxis, -mountHoleCenterToMountHoleCenter/2, 0])
                cylinder(h = mountHoleDepth, d = mountScrewDiameter);
            }
        }

    }
}

//armInnerJoint(bearing6807_2RS_D + iFitAdjust, bearingStep, bearingStep, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight);
module armInnerJoint(bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, screwTabs, screwTabHeight) {
    //translate([0, 0, hubHeight - (2 * stepHeight)])
    difference() {
        union() {
         difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + (setScrewRadius * 6));
            cylinder(h = bearingStep * 2, d = bearingOD);
//            translate([0, -bearingOD, 0])
//                cube([bearingOD, bearingOD * 2, bearingStep * 2]);
        }
        bearingOuterStep(bearingOD, stepHeight, stepWidth);
        // hub
        translate([0, 0, -(hubHeight - (2 * stepHeight))])
            stepperHub(hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight);
        // spokes
        radial_array(vec=[0, 0, 1], n = spokes)
                translate([hubRadius - (stepWidth / 2), -(spokeWidth / 2), stepHeight])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, stepHeight], center = false);
        // screw tabs for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])

                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }

                    }
        // screw holes for joining to upper
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * stepHeight) - screwTabHeight])
                       cylinder(h = screwTabHeight, r = setScrewRadius);
    }
}

module forearmLower(bearingID, bearingOD, stepHeight, stepWidth, hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight, spokeWidth, spokes, forearmLength, boundingBox) {
    armWidth = bearingOD / 2;

    rotate([180, 0, 0]) union() {
        boundingBoxHalf = boundingBox / 2;
        difference() {
            cylinder(h = bearingStep * 2, d = bearingOD + bearingStep);
            cylinder(h = bearingStep * 2, d = bearingID - (2 * bearingStep));
        }
        translate([0, 0, bearingStep * 2])
            bearingInnerStep(bearingID, bearingStep, bearingStep);
        // screw holes for joining to arm
        radial_array(vec = [0, 0, 1], n = screwTabs)
                translate([bearingOD / 2 + (setScrewRadius * 2), 0, (2 * bearingStep) - screwTabHeight])
                    difference() {
                        union () {
                            cylinder(h = screwTabHeight, r = setScrewRadius * 2);
                            translate([-2 * setScrewRadius, - 2 * setScrewRadius, 0])
                                cube([setScrewRadius * 2, 4 * setScrewRadius, screwTabHeight], center = false);
                        }
                        cylinder(h = screwTabHeight, r = setScrewRadius);
                    }
        // hub
        translate([0, 0, hubHeight]) rotate([180, 0, 0])
            stepperHub(hubHeight, hubRadius, shaftHeight, shaftRadius, setScrewRadius, setScrewHeight);
        // spokes
        radial_array(vec=[0, 0, 1], n = spokes)
                translate([hubRadius - (stepWidth / 2), -(spokeWidth / 2), 0])
                    cube([(bearingOD / 2) - hubRadius, spokeWidth, 2 *stepHeight], center = false);
        // forearm extension
             difference() {
            translate([-forearmLength, -armWidth / 2, 0])
                cube([forearmLength, armWidth, bearingStep * 2], center=false);
            cylinder(h = bearingStep * 2, d = bearingOD);
            translate([-forearmLength, 0, 0])
                cylinder(h = bearingStep * 2, d = bearingOD / 2);
                 // 4 on next line comes from dividing the bearingOD on the above line
            translate([-forearmLength + (bearingOD / 4) + (boundingBox / 2), -(armWidth / 2) + boundingBoxHalf, 0])
                cube([forearmLength - (bearingOD/2) - (boundingBox + boundingBoxHalf), armWidth - boundingBox, bearingStep * 2], center = false);
        }

            intersection() {

                translate([-forearmLength + boundingBox * 2, -(armWidth / 2) + boundingBoxHalf, 0])
                    cube([forearmLength - (bearingOD / 2) - boundingBox, armWidth - boundingBox, bearingStep * 2], center = false);
                for (i = [ bearingOD / 2 - boundingBoxHalf: armWidth : forearmLength]) {
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, 45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                    translate([ -i, 0, bearingStep])
                        rotate([0, 0, -45])
                            cube([spokeWidth, armWidth + boundingBoxHalf, bearingStep * 2], center = true);
                }
            }

    }
}

module copy_mirror(vec=[0,1,0]) {
    children();
    mirror(vec)
        children();
}

module radial_array(vec = [0,0,1], n = 4) {
    for ( i = [0 : n - 1] )
    {
        rotate( i * 360 / n, vec)
            children();
    }
}

module radial_array_partial(vec = [0,0,1], n = 4, j = 2) {
    for ( i = [0 : n - 1] )
    {
        if (i < j)
            rotate( i * 360 / n, vec)
                children();
    }
}


shapes: add hull_pairwise

shapes: add hull_pairwise

use <misc.scad>

// translate children
module lineup(arr=undef)
{
    /*echo(arr);*/
    /*echo($children);*/
    if($children>0)
    {
        for (i = [0 : $children-1])
            translate(arr[i]) children(i);
    }
}

module stack(dist=10, distances=undef)
{
    if(dist == undef && distances != undef)
    {
        for (i = [0:len(separations)-1])
        {
            offset = v_sum(separations,i);
            /*echo("i",i,"offset",offset);*/
            translate ([0,0,offset])
            {
                child(i);
            }
        }
    }
    else if(dist != undef && distances == undef)
    {
      for (i = [0 : $children-1])
          translate([ dist*i, 0, 0 ]) children(i);
    }
}

module orient(zaxes, roll=0)
{
    zaxes = len(zaxes.x) == undef && zaxes.x != undef? [zaxes] : zaxes;
    for(zaxis=zaxes)
    {
        rotate(_orient_angles(zaxis))
        /*rotate(roll*z)*/
            children();
    }
}

module size_align(size=[10,10,10], align=[0,0,0], orient=[0,0,1])
{
    bounds = _rotate_matrix(_orient_angles(orient)) * [size.x,size.y,size.z,1];
    t=hadamard(align, [abs(bounds.x/2),abs(bounds.y/2),abs(bounds.z/2)]);
    translate(t)
    {
        orient(orient)
        {
            children();
        }
    }
}

module hull_pairwise()
{
    for (i= [1:1:$children-1])
    {
        hull()
        {
            children(i-1);
            children(i);
        }
    }
}

module cubea(size=[10,10,10], align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            cube(size+extrasize, center=true);
        }
    }
}

module rcubea(size=[10,10,10], facets=32, rounding_radius=1, align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            rcube(size=size+extrasize, facets=facets, rounding_radius=rounding_radius);
        }
    }
}

module rcube(size=[20,20,20], rounding_radius=1)
{
    hull()
    for(x=[-(size[0]/2-rounding_radius),(size[0]/2-rounding_radius)])
    for(y=[-(size[1]/2-rounding_radius),(size[1]/2-rounding_radius)])
    for(z=[-(size[2]/2-rounding_radius),(size[2]/2-rounding_radius)])
    translate([x,y,z])
    sphere(r=rounding_radius);
}

module cylindera(
        h=10,
        r=undef,
        r1=undef,
        r2=undef,
        d=undef,
        d1=undef,
        d2=undef,
        align=[0,0,0],
        orient=[0,0,1],
        extra_h=0,
        extra_r=undef,
        extra_d=undef,
        extra_align=[0,0,1],
        round_radius=undef,
        debug=false
        )
{
    pi=3.1415926536;

    useDia = r == undef && (r1 == undef && r2 == undef);

    r1_ = useDia?((d1==undef?undef:d1)/2):r1;
    r2_ = useDia?((d2==undef?undef:d2)/2):r2;
    r_= useDia?d/2:(r==undef?0:r);
    r1r2max = max(r1,r2) == undef ? max(d1,d2)/2 : max(r1,r2);
    r__ = r_==undef? r1r2max : r_;
    extra_r_ = useDia?((extra_d==undef?0:extra_d)/2):((extra_r==undef)?0:extra_r);

    sizexy=r__*2;
    extra_sizexy=extra_r_*2;

    // some orient hax here to properly support extra_align
    orient(-orient)
    size_align([extra_sizexy,extra_sizexy,extra_h], align=extra_align, orient=orient)
    orient(orient)
    {
        if(debug)
        {
            echo(useDia, h, r_, r1_, r2_, extra_r_, align);
        }

        // some orient hax here to properly support extra_align
        orient(-orient)
        size_align([sizexy,sizexy,h], align=align, orient=orient)
        {
            if(round_radius==undef)
            {
                cylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, center=true);
            }
            else
            {
                rcylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, round_radius=round_radius);
            }
        }
    }
}

/*translate([10,0,0])*/
/*rotate_extrude()*/
        /*translate([10-2,2,0])*/
/*$fa = 5.6;*/
/*$fs = 0.3;*/
/*circle(r = 100);*/
/*torus(10, 2, align=[0,0,0], orient=[0,0,1]);*/

module torus(radius, radial_width, align=[0,0,0], orient=[0,0,1])
{
    size_align(size=[radius*2+radial_width*2, radius*2+radial_width*2, radial_width*2], align=align, orient=orient)
    rotate_extrude()
    translate([radius, 0, 0])
    circle(radial_width);
}

module rcylinder(d=10, r1=undef, r2=undef, h=10, round_radius=2)
{
    r_= (r1!=undef && r2!=undef) ? [r1,r2] : [d/2,d/2];
    /*translate([0,0,-h/2])*/
    hull()
    {
        /*a = r_[0]-r_[1];*/
        /*b = h;*/
        /*c = pythag_hyp(a,b);*/
        /*echo(c);*/
        /*d = c;//pythag_leg(a,c);*/
        /*echo(d);*/
        /*translate([0,r1-round_radius,0])*/
        /*cube([d,d,d]);*/
        /*angle2 = -atan2(-h, r1-r2);*/
        /*echo(angle2);*/
        /*x2 = r2-r1 < 0 ? (round_radius*2*cos(angle2)) : (round_radius*2*sin(angle2));*/
        /*echo(x2)*/
        /*translate([0, 0, h/2-round_radius])*/
        /*torus(radius=r_[1]-round_radius, radial_width=round_radius, align=[0,0,0]);*/

        for(z=[-1,1])
        translate([0, 0, z*(-h/2)])
        {
            /*rd = abs(r1-r2);*/
            /*angle1 = atan2(h, abs(r2-r1));*/
            /*x1 = round_radius*2*cos(angle1);*/
            /*echo(angle1, x1);*/
            r__=z!=-1?r_[0]:r_[1];
            torus(radius=r__-round_radius/2, radial_width=round_radius/2, align=[0,0,z]);

            /*translate([0, 0, -round_radius])*/
            /*cubea([r__*2,r__*2,5], align=[0,0,-z]);*/
        }
    }
}

module pie_slice_shape(r, start_angle, end_angle) {
    R = r * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    if(end_angle > start_angle)
    {
        intersection() {
            circle(r);
            polygon([
                    [0,0],
                    [R * cos(a0), R * sin(a0)],
                    [R * cos(a1), R * sin(a1)],
                    [R * cos(a2), R * sin(a2)],
                    [R * cos(a3), R * sin(a3)],
                    [R * cos(a4), R * sin(a4)],
                    [0,0]
            ]);
        }
    }
}

module pie_slice(r, start_angle, end_angle, h)
{
    linear_extrude(h)
    {
        pie_slice_shape(r, start_angle, end_angle);
    }
}

module hollow_cylinder(d=10, thickness=1, h=10, taper=false, orient=[0,0,1], align=[0,0,0])
{
    outer_d = d+thickness/2;
    inner_d = d-thickness/2;
    size_align(size=[outer_d, outer_d, h], orient=orient, align=align)
    difference()
    {
        hull()
        {
            taper_h = outer_d/2;
            if(taper)
            {
                for(z=[-1,1])
                translate([0,0,z*h/2])
                mirror([0,0,z==-1?1:0])
                difference()
                {
                    cylindera(d1=outer_d, d2=0, h=taper_h, align=[0,0,1]);
                    cylindera(d1=inner_d, d2=inner_d*2, h=taper_h, align=[0,0,1]);
                }
            }
        }

        cylindera(h=h+.2, d=inner_d, orient=[0,0,1], align=[0,0,0]);

    }
}

/*hollow_cylinder(thickness=2, h=9, taper=true, orient=[0,0,1], align=[0,0,1]);*/

/*%pie_slice(r=10, start_angle=-30, end_angle=270, h=10);*/

/*cubea([10,10,10],[1,0,0]);*/
/*%cubea([10,10,10],[1,0,0],[5,5,5],[1,1,1]);*/

/*%cubea([10,10,10],[-1,0,1]);*/
/*%cubea([10,10,10],[-1,0,1],[1,1,1],[-1,0,1]);*/
/*%cylindera(h=10, r=10/2, align=[-1,1,1], extra_r=5/2, extra_h=2, extra_align=[-1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[-1,1,1], extra_d=5, extra_h=2, extra_align=[-1,1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=15, extra_h=2, extra_align=[1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[1,-1,1], extra_d=5, extra_h=2, extra_align=[-1,-1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=5, extra_h=2, extra_align=[1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[1,0,0], extra_d=10);*/

/*hull_pairwise()*/
{
    /*sphere(30/2);*/

/*translate([30,0,0])*/
    /*rcubea(s=[35,35,35], rounding_radius=10);*/

/*translate([60,0,0])*/
    /*sphere(30/2);*/
}

use <misc.scad>

// translate children
module lineup(arr=undef)
{
    /*echo(arr);*/
    /*echo($children);*/
    if($children>0)
    {
        for (i = [0 : $children-1])
            translate(arr[i]) children(i);
    }
}

module stack(dist=10, distances=undef)
{
    if(dist == undef && distances != undef)
    {
        for (i = [0:len(separations)-1])
        {
            offset = v_sum(separations,i);
            /*echo("i",i,"offset",offset);*/
            translate ([0,0,offset])
            {
                child(i);
            }
        }
    }
    else if(dist != undef && distances == undef)
    {
      for (i = [0 : $children-1])
          translate([ dist*i, 0, 0 ]) children(i);
    }
}

module orient(zaxes, roll=0)
{
    zaxes = len(zaxes.x) == undef && zaxes.x != undef? [zaxes] : zaxes;
    for(zaxis=zaxes)
    {
        rotate(_orient_angles(zaxis))
        /*rotate(roll*z)*/
            children();
    }
}

module size_align(size=[10,10,10], align=[0,0,0], orient=[0,0,1])
{
    bounds = _rotate_matrix(_orient_angles(orient)) * [size.x,size.y,size.z,1];
    t=hadamard(align, [abs(bounds.x/2),abs(bounds.y/2),abs(bounds.z/2)]);
    translate(t)
    {
        orient(orient)
        {
            children();
        }
    }
}

module cubea(size=[10,10,10], align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            cube(size+extrasize, center=true);
        }
    }
}

module rcubea(size=[10,10,10], facets=32, rounding_radius=1, align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            rcube(size=size+extrasize, facets=facets, rounding_radius=rounding_radius);
        }
    }
}

module rcube(size=[20,20,20], rounding_radius=1)
{
    hull()
    for(x=[-(size[0]/2-rounding_radius),(size[0]/2-rounding_radius)])
    for(y=[-(size[1]/2-rounding_radius),(size[1]/2-rounding_radius)])
    for(z=[-(size[2]/2-rounding_radius),(size[2]/2-rounding_radius)])
    translate([x,y,z])
    sphere(r=rounding_radius);
}

module cylindera(
        h=10,
        r=undef,
        r1=undef,
        r2=undef,
        d=undef,
        d1=undef,
        d2=undef,
        align=[0,0,0],
        orient=[0,0,1],
        extra_h=0,
        extra_r=undef,
        extra_d=undef,
        extra_align=[0,0,1],
        round_radius=undef,
        debug=false
        )
{
    pi=3.1415926536;

    useDia = r == undef && (r1 == undef && r2 == undef);

    r1_ = useDia?((d1==undef?undef:d1)/2):r1;
    r2_ = useDia?((d2==undef?undef:d2)/2):r2;
    r_= useDia?d/2:(r==undef?0:r);
    r1r2max = max(r1,r2) == undef ? max(d1,d2)/2 : max(r1,r2);
    r__ = r_==undef? r1r2max : r_;
    extra_r_ = useDia?((extra_d==undef?0:extra_d)/2):((extra_r==undef)?0:extra_r);

    sizexy=r__*2;
    extra_sizexy=extra_r_*2;

    // some orient hax here to properly support extra_align
    orient(-orient)
    size_align([extra_sizexy,extra_sizexy,extra_h], align=extra_align, orient=orient)
    orient(orient)
    {
        if(debug)
        {
            echo(useDia, h, r_, r1_, r2_, extra_r_, align);
        }

        // some orient hax here to properly support extra_align
        orient(-orient)
        size_align([sizexy,sizexy,h], align=align, orient=orient)
        {
            if(round_radius==undef)
            {
                cylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, center=true);
            }
            else
            {
                rcylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, round_radius=round_radius);
            }
        }
    }
}

/*translate([10,0,0])*/
/*rotate_extrude()*/
        /*translate([10-2,2,0])*/
/*$fa = 5.6;*/
/*$fs = 0.3;*/
/*circle(r = 100);*/
/*torus(10, 2, align=[0,0,0], orient=[0,0,1]);*/

module torus(radius, radial_width, align=[0,0,0], orient=[0,0,1])
{
    size_align(size=[radius*2+radial_width*2, radius*2+radial_width*2, radial_width*2], align=align, orient=orient)
    rotate_extrude()
    translate([radius, 0, 0])
    circle(radial_width);
}

module rcylinder(d=10, r1=undef, r2=undef, h=10, round_radius=2)
{
    r_= (r1!=undef && r2!=undef) ? [r1,r2] : [d/2,d/2];
    /*translate([0,0,-h/2])*/
    hull()
    {
        /*a = r_[0]-r_[1];*/
        /*b = h;*/
        /*c = pythag_hyp(a,b);*/
        /*echo(c);*/
        /*d = c;//pythag_leg(a,c);*/
        /*echo(d);*/
        /*translate([0,r1-round_radius,0])*/
        /*cube([d,d,d]);*/
        /*angle2 = -atan2(-h, r1-r2);*/
        /*echo(angle2);*/
        /*x2 = r2-r1 < 0 ? (round_radius*2*cos(angle2)) : (round_radius*2*sin(angle2));*/
        /*echo(x2)*/
        /*translate([0, 0, h/2-round_radius])*/
        /*torus(radius=r_[1]-round_radius, radial_width=round_radius, align=[0,0,0]);*/

        for(z=[-1,1])
        translate([0, 0, z*(-h/2)])
        {
            /*rd = abs(r1-r2);*/
            /*angle1 = atan2(h, abs(r2-r1));*/
            /*x1 = round_radius*2*cos(angle1);*/
            /*echo(angle1, x1);*/
            r__=z!=-1?r_[0]:r_[1];
            torus(radius=r__-round_radius/2, radial_width=round_radius/2, align=[0,0,z]);

            /*translate([0, 0, -round_radius])*/
            /*cubea([r__*2,r__*2,5], align=[0,0,-z]);*/
        }
    }
}

module pie_slice_shape(r, start_angle, end_angle) {
    R = r * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    if(end_angle > start_angle)
    {
        intersection() {
            circle(r);
            polygon([
                    [0,0],
                    [R * cos(a0), R * sin(a0)],
                    [R * cos(a1), R * sin(a1)],
                    [R * cos(a2), R * sin(a2)],
                    [R * cos(a3), R * sin(a3)],
                    [R * cos(a4), R * sin(a4)],
                    [0,0]
            ]);
        }
    }
}

module pie_slice(r, start_angle, end_angle, h)
{
    linear_extrude(h)
    {
        pie_slice_shape(r, start_angle, end_angle);
    }
}

module hollow_cylinder(d=10, thickness=1, h=10, taper=false, orient=[0,0,1], align=[0,0,0])
{
    outer_d = d+thickness/2;
    inner_d = d-thickness/2;
    size_align(size=[outer_d, outer_d, h], orient=orient, align=align)
    difference()
    {
        hull()
        {
            taper_h = outer_d/2;
            if(taper)
            {
                for(z=[-1,1])
                translate([0,0,z*h/2])
                mirror([0,0,z==-1?1:0])
                difference()
                {
                    cylindera(d1=outer_d, d2=0, h=taper_h, align=[0,0,1]);
                    cylindera(d1=inner_d, d2=inner_d*2, h=taper_h, align=[0,0,1]);
                }
            }
        }

        cylindera(h=h+.2, d=inner_d, orient=[0,0,1], align=[0,0,0]);

    }
}

/*hollow_cylinder(thickness=2, h=9, taper=true, orient=[0,0,1], align=[0,0,1]);*/

/*%pie_slice(r=10, start_angle=-30, end_angle=270, h=10);*/

/*cubea([10,10,10],[1,0,0]);*/
/*%cubea([10,10,10],[1,0,0],[5,5,5],[1,1,1]);*/

/*%cubea([10,10,10],[-1,0,1]);*/
/*%cubea([10,10,10],[-1,0,1],[1,1,1],[-1,0,1]);*/
/*%cylindera(h=10, r=10/2, align=[-1,1,1], extra_r=5/2, extra_h=2, extra_align=[-1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[-1,1,1], extra_d=5, extra_h=2, extra_align=[-1,1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=15, extra_h=2, extra_align=[1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[1,-1,1], extra_d=5, extra_h=2, extra_align=[-1,-1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=5, extra_h=2, extra_align=[1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[1,0,0], extra_d=10);*/


rod protection cylinder

rod protection cylinder

h=15;
eps=0.01;
$fn=120;

module rod_protection()
{
  difference()
  {
    cylinder(r=10.5/2, h=h);
    translate([0,0,-eps])
      cylinder(r=8.5/2, h=h+2*eps);
  }
}

for(dx=[0:1])
  for(dy=[0:2])
    translate(12*[dx, dy, 0])
      rod_protection();

error: pathspec 'buggy_troley_mount/rod_protection.scad' did not match any file(s) known to git