psu: tweaks to dimensions

psu: tweaks to dimensions

use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
include <thing_libutils/metric-thread.scad>;
include <thing_libutils/metric-hexnut.scad>;

include <config.scad>

psu_w=11.5*cm;
psu_d=21.5*cm;
psu_h=5*cm;
psu_screw_side_dist_z = 2.5*cm;
psu_screw_dist_y = 15*cm;
psu_screw_bottom_dist_x = 5*cm;

psu_screw_thread = ThreadM4;
psu_screw_thread_dia = lookup(ThreadSize, psu_screw_thread);

psu_mount_bottom_height = 5*mm;

module psu(align=[0,0,0])
{
    size_align([psu_w,psu_d,psu_h], align)
    difference()
    {
        cubea([psu_w,psu_d,psu_h]);

        // screw holes, sides
        for(x=[-1,1])
        for(y=[-1,1])
        for(z=[-1,1])
        translate([x*(psu_w/2+1), y*(psu_screw_dist_y/2), z*psu_screw_side_dist_z/2])
        fncylindera(d=psu_screw_thread_dia, h=0.5*cm, orient=[1,0,0], align=[-x,0,0]);

        // screw holes, bottom
        for(x=[-1,1])
        for(y=[-1,1])
        translate([x*(psu_screw_bottom_dist_x/2), y*(psu_screw_dist_y/2), -psu_h/2-1])
        fncylindera(d=psu_screw_thread_dia, h=1*cm, orient=[0,0,1], align=[0,0,1]);
    }
}

module psu_extrusion_bracket_side()
{
    extrusion_side_screw_dist = 3*cm;
    difference()
    {
        hull()
        {
            for(x=[-1,1])
                translate([x*(psu_screw_bottom_dist_x/2), 0, -psu_h/2])
                    fncylindera(d=psu_screw_thread_dia*4, h=psu_mount_bottom_height, align=[0,0,-1]);

            for(y=[-1,1])
                translate([psu_w/2+extrusion_size/2, y*extrusion_side_screw_dist/2, -psu_h/2])
                    fncylindera(d=extrusion_thread_dia*4, h=psu_mount_bottom_height, align=[0,0,-1]);
        }

        for(x=[-1,1])
            translate([x*(psu_screw_bottom_dist_x/2), 0, -psu_h/2+1])
                fncylindera(d=psu_screw_thread_dia, h=psu_mount_bottom_height*2, align=[0,0,-1]);

        for(y=[-1,1])
            translate([psu_w/2+extrusion_size/2, y*extrusion_side_screw_dist/2, -psu_h/2+1])
                fncylindera(d=extrusion_thread_dia, h=psu_mount_bottom_height*2, align=[0,0,-1]);
    }
}

module psu_extrusion_bracket_back()
{
    extrusion_side_screw_dist = 3*cm;
    difference()
    {
        hull()
        {
            for(x=[-1,1])
                translate([x*(psu_screw_bottom_dist_x/2), 0, -psu_h/2])
                    fncylindera(d=psu_screw_thread_dia*4, h=psu_mount_bottom_height, align=[0,0,-1]);

            for(x=[-1,1])
                translate([x*psu_screw_bottom_dist_x/2, -psu_screw_dist_y/2+psu_d/2+extrusion_size/2, -psu_h/2])
                    fncylindera(d=extrusion_thread_dia*4, h=psu_mount_bottom_height, align=[0,0,-1]);
        }

        for(x=[-1,1])
            translate([x*(psu_screw_bottom_dist_x/2), 0, -psu_h/2+1])
                fncylindera(d=psu_screw_thread_dia, h=psu_mount_bottom_height*2, align=[0,0,-1]);

        for(x=[-1,1])
            translate([x*psu_screw_bottom_dist_x/2, -psu_screw_dist_y/2+psu_d/2+extrusion_size/2, -psu_h/2+1])
                fncylindera(d=extrusion_thread_dia, h=psu_mount_bottom_height*2, align=[0,0,-1]);
    }
}

/*psu();*/

/*translate([0, -psu_screw_dist_y/2, 0])*/
/*psu_extrusion_bracket_side();*/

/*translate([0, psu_screw_dist_y/2, 0])*/
/*psu_extrusion_bracket_back();*/

use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
include <thing_libutils/metric-thread.scad>;
include <thing_libutils/metric-hexnut.scad>;

include <config.scad>

psu_w=11*cm;
psu_d=21.5*cm;
psu_h=5*cm;
psu_screw_side_dist_z = 2.5*cm;
psu_screw_dist_y = 15*cm;
psu_screw_bottom_dist_x = 5*cm;

psu_screw_thread = ThreadM4;
psu_screw_thread_dia = lookup(ThreadSize, psu_screw_thread);

psu_mount_bottom_height = 3*mm;

module psu(align=[0,0,0])
{
    size_align([psu_w,psu_d,psu_h], align)
    difference()
    {
        cubea([psu_w,psu_d,psu_h]);

        // screw holes, sides
        for(x=[-1,1])
        for(y=[-1,1])
        for(z=[-1,1])
        translate([x*(psu_w/2+1), y*(psu_screw_dist_y/2), z*psu_screw_side_dist_z/2])
        fncylindera(d=psu_screw_thread_dia, h=0.5*cm, orient=[1,0,0], align=[-x,0,0]);

        // screw holes, bottom
        for(x=[-1,1])
        for(y=[-1,1])
        translate([x*(psu_screw_bottom_dist_x/2), y*(psu_screw_dist_y/2), -psu_h/2-1])
        fncylindera(d=psu_screw_thread_dia, h=1*cm, orient=[0,0,1], align=[0,0,1]);
    }
}

module psu_extrusion_bracket_side()
{
    extrusion_side_screw_dist = 3*cm;
    difference()
    {
        hull()
        {
            for(x=[-1,1])
                translate([x*(psu_screw_bottom_dist_x/2), 0, -psu_h/2])
                    fncylindera(d=psu_screw_thread_dia*4, h=psu_mount_bottom_height, align=[0,0,-1]);

            for(y=[-1,1])
                translate([psu_w/2+extrusion_size/2, y*extrusion_side_screw_dist/2, -psu_h/2])
                    fncylindera(d=extrusion_thread_dia*4, h=psu_mount_bottom_height, align=[0,0,-1]);
        }

        for(x=[-1,1])
            translate([x*(psu_screw_bottom_dist_x/2), 0, -psu_h/2+1])
                fncylindera(d=psu_screw_thread_dia, h=psu_mount_bottom_height*2, align=[0,0,-1]);

        for(y=[-1,1])
            translate([psu_w/2+extrusion_size/2, y*extrusion_side_screw_dist/2, -psu_h/2+1])
                fncylindera(d=extrusion_thread_dia, h=psu_mount_bottom_height*2, align=[0,0,-1]);
    }
}

module psu_extrusion_bracket_back()
{
    extrusion_side_screw_dist = 3*cm;
    difference()
    {
        hull()
        {
            for(x=[-1,1])
                translate([x*(psu_screw_bottom_dist_x/2), 0, -psu_h/2])
                    fncylindera(d=psu_screw_thread_dia*4, h=psu_mount_bottom_height, align=[0,0,-1]);

            for(x=[-1,1])
                translate([x*psu_screw_bottom_dist_x/2, -psu_screw_dist_y/2+psu_d/2+extrusion_size/2, -psu_h/2])
                    fncylindera(d=extrusion_thread_dia*4, h=psu_mount_bottom_height, align=[0,0,-1]);
        }

        for(x=[-1,1])
            translate([x*(psu_screw_bottom_dist_x/2), 0, -psu_h/2+1])
                fncylindera(d=psu_screw_thread_dia, h=psu_mount_bottom_height*2, align=[0,0,-1]);

        for(x=[-1,1])
            translate([x*psu_screw_bottom_dist_x/2, -psu_screw_dist_y/2+psu_d/2+extrusion_size/2, -psu_h/2+1])
                fncylindera(d=extrusion_thread_dia, h=psu_mount_bottom_height*2, align=[0,0,-1]);
    }
}

/*psu();*/

/*translate([0, -psu_screw_dist_y/2, 0])*/
/*psu_extrusion_bracket_side();*/

/*translate([0, psu_screw_dist_y/2, 0])*/
/*psu_extrusion_bracket_back();*/


added additional prolonging for the support part

eps=0.01;

module support()
{
  rotate([90, 0, 0])
  {
    // main block
    intersection()
    {
      difference()
      {
        cube([30, 30, 10]);
        // magnet hole
        translate([5, -eps, 10/2])
          rotate([-90, 0, 0])
            cylinder(d=5+0.5, h=5+0.5+eps, $fn=25);
        // main rounding
        translate([30, 30, -eps])
          cylinder(r=30, h=10+2*eps, $fn=200);
      }
      // truncating sharp edges
      cube([25, 25, 10+2*eps]);
    }
    // support prolonging
    cube([1.2, 35, 10]);
  }
}

support();

eps=0.01;

module support()
{
  rotate([90, 0, 0])
    intersection()
    {
      difference()
      {
        cube([30, 30, 10]);
        // magnet hole
        translate([5, -eps, 10/2])
          rotate([-90, 0, 0])
            cylinder(d=5+0.5, h=5+0.5+eps, $fn=25);
        // main rounding
        translate([30, 30, -eps])
          cylinder(r=30, h=10+2*eps, $fn=200);
      }
      // truncating sharp edges
      cube([25, 25, 10+2*eps]);
    }
}

support();


config: tiny refactor preview mode variables

include <MCAD/stepper.scad>
include <screws.scad>
include <pulley.scad>
include <thing_libutils/bearing_data.scad>
include <thing_libutils/metric-thread-data.scad>
include <thing_libutils/metric-hexnut-data.scad>
include <thing_libutils/misc.scad>

e=0.01;

// minimum size of a fragment
// resolution of any round object (segment length)
// Because of this variable very small circles have a smaller number of fragments than specified using $fa.
// The default value is 2.
$fs = 2;

// minimum angle for a fragment.
// The default value is 12 (i.e. 30 fragments for a full circle)
$fa = 12;

//hq
if(false)
{
    $fs= 0.5;
    $fa = 4;
}

// enable preview model (faster openscad)
preview_mode=false;

extrusion_height            = 0.4*mm;

// width of a single wall, should match your slicer settings
extrusion_width             = 0.4*mm;

// how many lines should a normal wall have (i.e. 0.6(extrusion_width)*6(normal_wall_factor)= 3.6mm wall width)
normal_wall_factor          = 3;

thick_wall_factor           = 4;

// diameter of your filament.
filament_d                  = 1.75*mm;
filament_r                  = filament_d/2;

main_width = 340*mm;
main_depth = 420*mm;
main_height = 400*mm;
main_upper_width = 420*mm;

extrusion_color = [0.5,0.5,0.5];
extrusion_size = 20*mm;
extrusion_thread = ThreadM5;
extrusion_thread_dia = lookup(ThreadSize, extrusion_thread);
extrusion_nut = MHexNutM5;
extrusion_nut_dia = lookup(MHexNutWidthMax, extrusion_nut);

main_lower_dist_z= 80*mm;
main_upper_dist_y= 160*mm;

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

ziptie_type = [1.1*mm, 2.4*mm];
ziptie_thickness = ziptie_type[0];
ziptie_width = ziptie_type[1]+0.6*mm;
ziptie_bearing_distance=3*mm;

xaxis_rod_distance = 60*mm;
xaxis_rod_d = 9.975*mm;
xaxis_rod_l = 500*mm;
xaxis_rod_offset_x = 20*mm;
xaxis_bearing=bearing_igus_rj4jp_01_10;

xaxis_pulley = pulley_2GT_20T;
xaxis_pulley_inner_d = xaxis_pulley[2];
xaxis_idler_pulley = pulley_2GT_20T_idler;
xaxis_idler_pulley_inner_d = xaxis_idler_pulley[2];
xaxis_idler_pulley_outer_d = xaxis_idler_pulley[3];

xaxis_belt_width = 6*mm;
xaxis_beltpath_height = xaxis_pulley_inner_d+5*mm;
xaxis_beltpath_width = max(xaxis_belt_width+3*mm, xaxis_pulley[0]+2*mm);

xaxis_carriage_bearing_offset_y = ziptie_thickness+3*mm;
xaxis_carriage_beltpath_offset = xaxis_carriage_bearing_offset_y+xaxis_bearing[1]/2;

xaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing=bearing_igus_rj4jp_01_12;
yaxis_bearing_distance_y = 7*cm;

yaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);

yaxis_pulley = pulley_2GT_20T;
yaxis_pulley_inner_d = yaxis_pulley[2];
ymotor_mount_thickness = 5;
ymotor_mount_thickness_h = 5;
yaxis_motor_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_motor_offset_z = -5*mm;
yaxis_belt_path_offset_x = -yaxis_pulley_inner_d/2;
yaxis_belt_path_offset_z = yaxis_motor_offset_z + 15*mm;

yaxis_idler_pulley = pulley_2GT_20T_idler;
yaxis_idler_pulley_inner_d = yaxis_idler_pulley[2];
yaxis_idler_pulley_outer_d = yaxis_idler_pulley[3];
yaxis_idler_pulley_h = yaxis_idler_pulley[0];
yaxis_idler_mount_thickness = 5;
yaxis_idler_pulley_tight_len = 20*mm;
yaxis_idler_pulley_offset_y = yaxis_idler_mount_thickness + yaxis_pulley_inner_d/2 + yaxis_idler_pulley_tight_len;
yaxis_idler_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_idler_offset_z = 10*mm;

yaxis_carriage_size=[220*mm,220*mm,5*mm];

zaxis_rod_d = 11.975*mm;
zaxis_rod_l = 500*mm;
zaxis_bearing=bearing_igus_rj4jp_01_12;

// Nema17 motor w/340mm long 8*mm leadscrew
zaxis_motor = dict_replace_multiple(Nema17,
        [
        [NemaAxleDiameter, 8*mm],
        [NemaFrontAxleLength, 340*mm],
        ]);

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_h = lookup(NemaLengthLong,zaxis_motor);

// inner_d, outer_d, thread, outer_h, full_h
zaxis_nut = [20*mm, 36*mm, 8*mm, 5*mm, 23*mm];

zaxis_motor_offset_z = 10*mm;
zmotor_mount_thickness = 5;
zmotor_mount_thickness_h = 10;
zmotor_mount_motor_offset=5;

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_h = lookup(NemaLengthLong,zaxis_motor);
zmotor_mount_thread_dia = lookup(ThreadSize, extrusion_thread);
zmotor_mount_width = zmotor_w+zmotor_mount_thickness*2 + zmotor_mount_thread_dia*8;
zmotor_mount_h = main_lower_dist_z+extrusion_size+zaxis_motor_offset_z;

zmotor_mount_clamp_dist = zaxis_rod_d*2.5;
zmotor_mount_clamp_thread = ThreadM4;
zmotor_mount_clamp_nut = MHexNutM4;
zmotor_mount_clamp_thread_dia = lookup(ThreadSize, zmotor_mount_clamp_thread);
zmotor_mount_clamp_nut_dia = lookup(MHexNutWidthMin, zmotor_mount_clamp_nut);
zmotor_mount_clamp_nut_thick = lookup(MHexNutThickness, zmotor_mount_clamp_nut);
zmotor_mount_clamp_width = zmotor_mount_clamp_dist+zmotor_mount_clamp_thread_dia*3;

xaxis_zaxis_distance_y = 1*mm + xaxis_rod_d/2 + zaxis_bearing[1]/2;

zaxis_nut_mount_outer = zaxis_nut[1]/2 + zaxis_rod_d/2 + 1*mm;

// offset between Z motor screw and z rod
// place z rod as close as possible (depends on z nut and also motor etc)
zaxis_rod_screw_distance_x = max(zaxis_nut_mount_outer, zaxis_rod_d/2 + zmotor_w/2 + 1*mm);

// z rod offset from lower extrusion (outer)
zmotor_mount_rod_offset_x = zmotor_w/2+zaxis_rod_screw_distance_x+zmotor_mount_motor_offset;

// z screw offset from lower extrusion (outer)
zmotor_mount_screw_offset_x = zmotor_mount_rod_offset_x - zaxis_rod_screw_distance_x ;

// GT2
// there is bunch of GT2 belts with different tooth-to-tooth distance
// this one is most common in reprap world
// adjust to your needs.
belt_width = 6.5;
belt_tooth_distance = 2;
belt_tooth_ratio = 0.5;
belt_thickness = 0.8;

//T2.5
//belt_tooth_distance = 2.5;
//belt_tooth_ratio = 0.5;

//T5 (strongly discouraged)
//belt_tooth_distance = 5;
//belt_tooth_ratio = 0.75;

//HTD3
//belt_tooth_distance = 3;
//belt_tooth_ratio = 0.75;

//MXL
//belt_tooth_distance = 2.032;
//belt_tooth_ratio = 0.64;

include <MCAD/stepper.scad>
include <screws.scad>
include <pulley.scad>
include <thing_libutils/bearing_data.scad>
include <thing_libutils/metric-thread-data.scad>
include <thing_libutils/metric-hexnut-data.scad>
include <thing_libutils/misc.scad>

e=0.01;

// minimum size of a fragment
// resolution of any round object (segment length)
// Because of this variable very small circles have a smaller number of fragments than specified using $fa.
// The default value is 2.
$fs                         = 2;
/*$fs                         = 0.5;*/

// minimum angle for a fragment.
// The default value is 12 (i.e. 30 fragments for a full circle)
$fa = 12;
/*$fa = 4;*/

extrusion_height            = 0.4*mm;

// width of a single wall, should match your slicer settings
extrusion_width             = 0.4*mm;

// how many lines should a normal wall have (i.e. 0.6(extrusion_width)*6(normal_wall_factor)= 3.6mm wall width)
normal_wall_factor          = 3;

thick_wall_factor           = 4;

// diameter of your filament.
filament_d                  = 1.75*mm;
filament_r                  = filament_d/2;

// enable preview model (faster openscad)
preview_mode=true;

main_width = 340*mm;
main_depth = 420*mm;
main_height = 400*mm;
main_upper_width = 420*mm;

extrusion_color = [0.5,0.5,0.5];
extrusion_size = 20*mm;
extrusion_thread = ThreadM5;
extrusion_thread_dia = lookup(ThreadSize, extrusion_thread);
extrusion_nut = MHexNutM5;
extrusion_nut_dia = lookup(MHexNutWidthMax, extrusion_nut);

main_lower_dist_z= 80*mm;
main_upper_dist_y= 160*mm;

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

ziptie_type = [1.1*mm, 2.4*mm];
ziptie_thickness = ziptie_type[0];
ziptie_width = ziptie_type[1]+0.6*mm;
ziptie_bearing_distance=3*mm;

xaxis_rod_distance = 60*mm;
xaxis_rod_d = 9.975*mm;
xaxis_rod_l = 500*mm;
xaxis_rod_offset_x = 20*mm;
xaxis_bearing=bearing_igus_rj4jp_01_10;

xaxis_pulley = pulley_2GT_20T;
xaxis_pulley_inner_d = xaxis_pulley[2];
xaxis_idler_pulley = pulley_2GT_20T_idler;
xaxis_idler_pulley_inner_d = xaxis_idler_pulley[2];
xaxis_idler_pulley_outer_d = xaxis_idler_pulley[3];

xaxis_belt_width = 6*mm;
xaxis_beltpath_height = xaxis_pulley_inner_d+5*mm;
xaxis_beltpath_width = max(xaxis_belt_width+3*mm, xaxis_pulley[0]+2*mm);

xaxis_carriage_bearing_offset_y = ziptie_thickness+3*mm;
xaxis_carriage_beltpath_offset = xaxis_carriage_bearing_offset_y+xaxis_bearing[1]/2;

xaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing=bearing_igus_rj4jp_01_12;
yaxis_bearing_distance_y = 7*cm;

yaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);

yaxis_pulley = pulley_2GT_20T;
yaxis_pulley_inner_d = yaxis_pulley[2];
ymotor_mount_thickness = 5;
ymotor_mount_thickness_h = 5;
yaxis_motor_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_motor_offset_z = -5*mm;
yaxis_belt_path_offset_x = -yaxis_pulley_inner_d/2;
yaxis_belt_path_offset_z = yaxis_motor_offset_z + 15*mm;

yaxis_idler_pulley = pulley_2GT_20T_idler;
yaxis_idler_pulley_inner_d = yaxis_idler_pulley[2];
yaxis_idler_pulley_outer_d = yaxis_idler_pulley[3];
yaxis_idler_pulley_h = yaxis_idler_pulley[0];
yaxis_idler_mount_thickness = 5;
yaxis_idler_pulley_tight_len = 20*mm;
yaxis_idler_pulley_offset_y = yaxis_idler_mount_thickness + yaxis_pulley_inner_d/2 + yaxis_idler_pulley_tight_len;
yaxis_idler_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_idler_offset_z = 10*mm;

yaxis_carriage_size=[220*mm,220*mm,5*mm];

zaxis_rod_d = 11.975*mm;
zaxis_rod_l = 500*mm;
zaxis_bearing=bearing_igus_rj4jp_01_12;

// Nema17 motor w/340mm long 8*mm leadscrew
zaxis_motor = dict_replace_multiple(Nema17,
        [
        [NemaAxleDiameter, 8*mm],
        [NemaFrontAxleLength, 340*mm],
        ]);

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_h = lookup(NemaLengthLong,zaxis_motor);

// inner_d, outer_d, thread, outer_h, full_h
zaxis_nut = [20*mm, 36*mm, 8*mm, 5*mm, 23*mm];

zaxis_motor_offset_z = 10*mm;
zmotor_mount_thickness = 5;
zmotor_mount_thickness_h = 10;
zmotor_mount_motor_offset=5;

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_h = lookup(NemaLengthLong,zaxis_motor);
zmotor_mount_thread_dia = lookup(ThreadSize, extrusion_thread);
zmotor_mount_width = zmotor_w+zmotor_mount_thickness*2 + zmotor_mount_thread_dia*8;
zmotor_mount_h = main_lower_dist_z+extrusion_size+zaxis_motor_offset_z;

zmotor_mount_clamp_dist = zaxis_rod_d*2.5;
zmotor_mount_clamp_thread = ThreadM4;
zmotor_mount_clamp_nut = MHexNutM4;
zmotor_mount_clamp_thread_dia = lookup(ThreadSize, zmotor_mount_clamp_thread);
zmotor_mount_clamp_nut_dia = lookup(MHexNutWidthMin, zmotor_mount_clamp_nut);
zmotor_mount_clamp_nut_thick = lookup(MHexNutThickness, zmotor_mount_clamp_nut);
zmotor_mount_clamp_width = zmotor_mount_clamp_dist+zmotor_mount_clamp_thread_dia*3;

xaxis_zaxis_distance_y = 1*mm + xaxis_rod_d/2 + zaxis_bearing[1]/2;

zaxis_nut_mount_outer = zaxis_nut[1]/2 + zaxis_rod_d/2 + 1*mm;

// offset between Z motor screw and z rod
// place z rod as close as possible (depends on z nut and also motor etc)
zaxis_rod_screw_distance_x = max(zaxis_nut_mount_outer, zaxis_rod_d/2 + zmotor_w/2 + 1*mm);

// z rod offset from lower extrusion (outer)
zmotor_mount_rod_offset_x = zmotor_w/2+zaxis_rod_screw_distance_x+zmotor_mount_motor_offset;

// z screw offset from lower extrusion (outer)
zmotor_mount_screw_offset_x = zmotor_mount_rod_offset_x - zaxis_rod_screw_distance_x ;

// GT2
// there is bunch of GT2 belts with different tooth-to-tooth distance
// this one is most common in reprap world
// adjust to your needs.
belt_width = 6.5;
belt_tooth_distance = 2;
belt_tooth_ratio = 0.5;
belt_thickness = 0.8;

//T2.5
//belt_tooth_distance = 2.5;
//belt_tooth_ratio = 0.5;

//T5 (strongly discouraged)
//belt_tooth_distance = 5;
//belt_tooth_ratio = 0.75;

//HTD3
//belt_tooth_distance = 3;
//belt_tooth_ratio = 0.75;

//MXL
//belt_tooth_distance = 2.032;
//belt_tooth_ratio = 0.64;


/ ‘Impression 3D/2016 - Trocar/trocar-test1.scad’


main: rename variables

main: rename variables

include <thing_libutils/metric-thread.scad>;
include <thing_libutils/metric-hexnut.scad>;
use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/triangles.scad>
use <thing_libutils/linear-extrusion.scad>;

include <MCAD/stepper.scad>
include <MCAD/motors.scad>

include <config.scad>
include <extruder-direct.scad>

axis_pos_x = -225/2*mm;
axis_range_z=[85,380];
axis_pos_z = axis_range_z[1]*mm/2;

main();

module main()
{
    color(extrusion_color)
    gantry_lower();

    color(extrusion_color)
    translate([0,0,-main_lower_dist_z])
    gantry_lower();

    color(extrusion_color)
    for(i=[-1,1])
    translate([0,i*(main_upper_dist_y/2),0])
    gantry_upper();

    // x axis
    translate([0,0,axis_pos_z])
    {
        translate([axis_pos_x,0,0])
        {
            xaxis_bearing_dist = 10;
            translate([0,xaxis_zaxis_distance_y,0])
            translate([0,xaxis_bearing[1]/2,0])
            cubea([xaxis_bearing[2]*2+xaxis_bearing_dist,5,xaxis_rod_distance+xaxis_bearing[1]], align=[0,1,0]);

            attach([[-8,-15,-16],[-1,0,0]],extruder_conn_xcarriage)
                extruder();

            // x carriage
            for(i=[-1,1])
                for(j=[-1,1])
                    translate([j*(xaxis_bearing_dist+xaxis_bearing[2])/2,xaxis_zaxis_distance_y,i*(xaxis_rod_distance/2)])
                        rotate([0,90,0])
                        bearing(xaxis_bearing);
        }

        // x smooth rods
        for(i=[-1,1])
            translate([0,xaxis_zaxis_distance_y,i*(xaxis_rod_distance/2)])
                fncylindera(h=xaxis_rod_l,d=xaxis_rod_d, orient=[1,0,0]);
    }

    // y smooth rods
    translate([0,0,yaxis_bearing[0]/2])
    {
        for(i=[-1,1])
        translate([i*(yaxis_rod_distance/2), 0, 0])
        {
            fncylindera(h=yaxis_rod_l,d=yaxis_rod_d, orient=[0,1,0]);

            for(j=[-1,1])
                translate([0,j*(yaxis_rod_distance/2),0])
                    rotate([90,0,0])
                    bearing(yaxis_bearing);
        }

        translate([0,0,yaxis_bearing[1]/2])
        {
            // y axis plate
            cubea(ycarriage_size, align=[0,0,1]);
        }
    }

    // z axis
    for(i=[-1,1])
    translate([i*(main_width/2 + lookup(NemaSideSize,zaxis_motor)/2), 0, 0])
    {
        translate([0,0,zaxis_motor_offset_z])
        mirror([i==-1?1:0,0,0])
        {
            zmotor_mount();

            attach([[0,0,0],[0,0,0]],zmotor_mount_conn_motor)
            {
                // z motor/leadscrews
                motor(zaxis_motor, NemaMedium, dualAxis=false, orientation=[0,180,0]);
            }
        }

        // z smooth rods
        translate([i*(zaxis_rod_screw_distance_x+zmotor_mount_motor_offset),0,0])
        {
            translate([0,0,zaxis_motor_offset_z])
                fncylindera(h=zaxis_rod_l,d=zaxis_rod_d,align=[0,0,1]);

            for(j=[-1,1])
                translate([0,0,axis_pos_z-j*xaxis_rod_distance/2])
                    bearing(zaxis_bearing);
        }

        translate([i*zmotor_mount_motor_offset, 0, axis_pos_z-xaxis_rod_distance/2-10])
        {
            difference()
            {
                fncylindera(h=10, d=zaxis_nut[1], align=[0,0,0]);
                union()
                {
                    fncylindera(h=10+1, d=zaxis_nut[0], center= false);
                    translate([0, 13.5, -1]) fncylindera(h=5, r=1.6);
                    translate([0, -13.5, -1]) fncylindera(h=5, r=1.6);
                }
            }
        }
    }
}

zmotor_mount_motor_offset=5;
zmotor_mount_conn_motor=[[-zmotor_mount_motor_offset, 0, 0],[0,1,0]];

module zmotor_mount()
{
    motor_w = lookup(NemaSideSize,zaxis_motor);

    mount_thickness = 5;
    mount_thickness_h = 8;
    mount_thread_dia = lookup(ThreadSize, extrusion_thread);
    mount_width = motor_w+mount_thickness*2 + mount_thread_dia*8;
    mount_h = main_lower_dist_z+extrusion_size+zaxis_motor_offset_z;

    // side triangles
    translate([-motor_w/2, 0, 0])
    for(i=[-1,1])
    {
        translate([mount_thickness, i*((motor_w/2)+mount_thickness/2), 0])
        rotate([90,90,0])
        Right_Angled_Triangle(a=motor_w-mount_thickness+zmotor_mount_motor_offset, b=main_lower_dist_z+extrusion_size+zaxis_motor_offset_z, height=mount_thickness, centerXYZ=[0,0,1]);

        translate([0, i*((motor_w/2)+mount_thickness/2), 0])
        cubea([mount_thickness, mount_thickness, mount_h], align=[1,0,-1]);
    }

    // top mount plate
    difference()
    {
        translate([-motor_w/2,0,-extrusion_size-zaxis_motor_offset_z])
            cubea([mount_thickness, mount_width, extrusion_size], align=[1,0,1]);

        for(i=[-1,1])
            translate([-motor_w/2,i*(motor_w/2+mount_thread_dia*3),-extrusion_size])
                fncylindera(h=mount_thickness*3,d=mount_thread_dia, orient=[1,0,0]);
    }

    // bottom mount plate
    difference()
    {
        translate([-motor_w/2,0,-main_lower_dist_z-extrusion_size-zaxis_motor_offset_z])
            cubea([mount_thickness, mount_width, extrusion_size], align=[1,0,1]);

        for(i=[-1,1])
            translate([-motor_w/2,i*(motor_w/2+mount_thread_dia*3),-extrusion_size-main_lower_dist_z])
                fncylindera(h=mount_thickness*3,d=mount_thread_dia,align=[0,0,0], orient=[1,0,0]);
    }

/*#    cubea([motor_w+mount_thickness,motor_w+mount_thickness,zaxis_motor_offset_z], align=[0,0,-1]);*/

    // top plate
    difference()
    {
        cubea([motor_w, motor_w+mount_thickness*2, mount_thickness_h], align=[0,0,1], extrasize=[5,0,0], extrasize_align=[1,0,0]);

        translate([zmotor_mount_motor_offset,0,-1])
        linear_extrude(mount_thickness_h+2)
        stepper_motor_mount(17, slide_distance=0, mochup=false);
    }
}

module gantry_upper()
{
    for(i=[-1,1])
    translate([i*(main_width/2), 0])
    linear_extrusion(h=main_height, align=[-i,0,1], orient=[0,0,1]);

    translate([0, 0, main_height])
    linear_extrusion(h=main_upper_width, align=[0,0,1], orient=[1,0,0]);
}

module gantry_lower()
{
    for(i=[-1,1])
    translate([0,  i*(main_depth/2), 0])
    linear_extrusion(h=main_width, align=[0,i,-1], orient=[1,0,0]);

    for(i=[-1,1])
    translate([i*(main_width/2), 0, 0])
    linear_extrusion(h=main_depth, align=[-i,0,-1], orient=[0,1,0]);
}

include <thing_libutils/metric-thread.scad>;
include <thing_libutils/metric-hexnut.scad>;
use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/triangles.scad>
use <thing_libutils/linear-extrusion.scad>;

include <MCAD/stepper.scad>
include <MCAD/motors.scad>

include <config.scad>
include <extruder-direct.scad>

xaxis_pos_x = -225/2*mm;
xaxis_range_z=[85,350];
xaxis_pos_z = 350*mm;

main();

module main()
{
    color(extrusion_color)
    gantry_lower();

    color(extrusion_color)
    translate([0,0,-main_lower_dist_z])
    gantry_lower();

    color(extrusion_color)
    for(i=[-1,1])
    translate([0,i*(main_upper_dist_y/2),0])
    gantry_upper();

    // x axis
    translate([0,0,xaxis_pos_z])
    {
        translate([xaxis_pos_x,0,0])
        {
            xaxis_bearing_dist = 10;
            translate([0,xaxis_zaxis_distance_y,0])
            translate([0,xaxis_bearing[1]/2,0])
            cubea([xaxis_bearing[2]*2+xaxis_bearing_dist,5,xaxis_rod_distance+xaxis_bearing[1]], align=[0,1,0]);

            attach([[-8,-15,-16],[-1,0,0]],extruder_conn_xcarriage)
                extruder();

            // x carriage
            for(i=[-1,1])
                for(j=[-1,1])
                    translate([j*(xaxis_bearing_dist+xaxis_bearing[2])/2,xaxis_zaxis_distance_y,i*(xaxis_rod_distance/2)])
                        rotate([0,90,0])
                        bearing(xaxis_bearing);
        }

        // x smooth rods
        for(i=[-1,1])
            translate([0,xaxis_zaxis_distance_y,i*(xaxis_rod_distance/2)])
                fncylindera(h=xaxis_rod_l,d=xaxis_rod_d, orient=[1,0,0]);
    }

    // y smooth rods
    translate([0,0,yaxis_bearing[0]/2])
    {
        for(i=[-1,1])
        translate([i*(yaxis_rod_distance/2), 0, 0])
        {
            fncylindera(h=yaxis_rod_l,d=yaxis_rod_d, orient=[0,1,0]);

            for(j=[-1,1])
                translate([0,j*(yaxis_rod_distance/2),0])
                    rotate([90,0,0])
                    bearing(yaxis_bearing);
        }

        translate([0,0,yaxis_bearing[1]/2])
        {
            // y axis plate
            cubea(ycarriage_size, align=[0,0,1]);
        }
    }

    // z axis
    for(i=[-1,1])
    translate([i*(main_width/2 + lookup(NemaSideSize,zaxis_motor)/2), 0, 0])
    {
        translate([0,0,zaxis_motor_offset_z])
        mirror([i==-1?1:0,0,0])
        {
            zmotor_mount();

            attach([[0,0,0],[0,0,0]],zmotor_mount_conn_motor)
            {
                // z motor/leadscrews
                motor(zaxis_motor, NemaMedium, dualAxis=false, orientation=[0,180,0]);
            }
        }

        // z smooth rods
        translate([i*(zaxis_rod_screw_distance_x+zmotor_mount_motor_offset),0,0])
        {
            translate([0,0,zaxis_motor_offset_z])
                fncylindera(h=zaxis_rod_l,d=zaxis_rod_d,align=[0,0,1]);

            for(j=[-1,1])
                translate([0,0,xaxis_pos_z-j*xaxis_rod_distance/2])
                    bearing(zaxis_bearing);
        }

        translate([i*zmotor_mount_motor_offset, 0, xaxis_pos_z-xaxis_rod_distance/2-10])
        {
            difference()
            {
                fncylindera(h=10, d=zaxis_nut[1], align=[0,0,0]);
                union()
                {
                    fncylindera(h=10+1, d=zaxis_nut[0], center= false);
                    translate([0, 13.5, -1]) fncylindera(h=5, r=1.6);
                    translate([0, -13.5, -1]) fncylindera(h=5, r=1.6);
                }
            }
        }
    }
}

zmotor_mount_motor_offset=5;
zmotor_mount_conn_motor=[[-zmotor_mount_motor_offset, 0, 0],[0,1,0]];

module zmotor_mount()
{
    motor_w = lookup(NemaSideSize,zaxis_motor);

    mount_thickness = 5;
    mount_thickness_h = 8;
    mount_thread_dia = lookup(ThreadSize, extrusion_thread);
    mount_width = motor_w+mount_thickness*2 + mount_thread_dia*8;
    mount_h = main_lower_dist_z+extrusion_size+zaxis_motor_offset_z;

    // side triangles
    translate([-motor_w/2, 0, 0])
    for(i=[-1,1])
    {
        translate([mount_thickness, i*((motor_w/2)+mount_thickness/2), 0])
        rotate([90,90,0])
        Right_Angled_Triangle(a=motor_w-mount_thickness+zmotor_mount_motor_offset, b=main_lower_dist_z+extrusion_size+zaxis_motor_offset_z, height=mount_thickness, centerXYZ=[0,0,1]);

        translate([0, i*((motor_w/2)+mount_thickness/2), 0])
        cubea([mount_thickness, mount_thickness, mount_h], align=[1,0,-1]);
    }

    // top mount plate
    difference()
    {
        translate([-motor_w/2,0,-extrusion_size-zaxis_motor_offset_z])
            cubea([mount_thickness, mount_width, extrusion_size], align=[1,0,1]);

        for(i=[-1,1])
            translate([-motor_w/2,i*(motor_w/2+mount_thread_dia*3),-extrusion_size])
                fncylindera(h=mount_thickness*3,d=mount_thread_dia, orient=[1,0,0]);
    }

    // bottom mount plate
    difference()
    {
        translate([-motor_w/2,0,-main_lower_dist_z-extrusion_size-zaxis_motor_offset_z])
            cubea([mount_thickness, mount_width, extrusion_size], align=[1,0,1]);

        for(i=[-1,1])
            translate([-motor_w/2,i*(motor_w/2+mount_thread_dia*3),-extrusion_size-main_lower_dist_z])
                fncylindera(h=mount_thickness*3,d=mount_thread_dia,align=[0,0,0], orient=[1,0,0]);
    }

/*#    cubea([motor_w+mount_thickness,motor_w+mount_thickness,zaxis_motor_offset_z], align=[0,0,-1]);*/

    // top plate
    difference()
    {
        cubea([motor_w, motor_w+mount_thickness*2, mount_thickness_h], align=[0,0,1], extrasize=[5,0,0], extrasize_align=[1,0,0]);

        translate([zmotor_mount_motor_offset,0,-1])
        linear_extrude(mount_thickness_h+2)
        stepper_motor_mount(17, slide_distance=0, mochup=false);
    }
}

module gantry_upper()
{
    for(i=[-1,1])
    translate([i*(main_width/2), 0])
    linear_extrusion(h=main_height, align=[-i,0,1], orient=[0,0,1]);

    translate([0, 0, main_height])
    linear_extrusion(h=main_upper_width, align=[0,0,1], orient=[1,0,0]);
}

module gantry_lower()
{
    for(i=[-1,1])
    translate([0,  i*(main_depth/2), 0])
    linear_extrusion(h=main_width, align=[0,i,-1], orient=[1,0,0]);

    for(i=[-1,1])
    translate([i*(main_width/2), 0, 0])
    linear_extrusion(h=main_depth, align=[-i,0,-1], orient=[0,1,0]);
}


main: fix x axis range

main: fix x axis range

include <config.scad>

include <thing_libutils/system.scad>
include <thing_libutils/units.scad>
include <thing_libutils/materials.scad>

use <thing_libutils/screws.scad>
use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/transforms.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/linear-extrusion.scad>;
use <thing_libutils/timing-belts.scad>;

use <x-end.scad>
include <x-end.h>

use <x-carriage.scad>
include <x-carriage.h>

use <y-carriage.scad>
include <y-carriage.h>

use <y-motor-mount.scad>
include <y-motor-mount.h>

use <y-carriage-bearing-mount.scad>
include <y-carriage-bearing-mount.h>

use <y-carriage-belt-clamp.scad>
include <y-carriage-belt-clamp.h>

use <y-idler.scad>
include <y-idler.h>

use <z-motor-mount.scad>
include <z-motor-mount.h>

use <gantry-upper-connector.scad>
use <gantry-lower-connector.scad>

use <rod-clamps.scad>
include <rod-clamps.h>

use <printbed.scad>
include <printbed.h>

/*use <psu.scad>*/
/*include <psu.h>*/

/*use <lcd2004.scad>*/
/*use <power-panel-iec320.scad>*/

// x carriage
axis_range_x_ = main_width/2 - extrusion_size - zaxis_rod_d/2 - xaxis_end_width_right(true) - x_carriage_w/2;
axis_range_x = [-1,1] *  axis_range_x_;
axis_printrange_x = [-1, 1] * (printbed_size[0]/2+extruder_b_hotend_mount_offset.x);
axis_x_pos_relative=[1,0];
axis_x_parked = [false, true];

axis_range_y=[0*mm,200*mm];
axis_pos_y = -axis_range_y[0]/2-30*mm;
axis_range_z=[-extruder_offset.z-extruder_offset_b.z-extruder_b_hotend_mount_offset.z+hotend_height+yaxis_carriage_offset.z+yaxis_carriage_bearing_mount_conn_bearing[0].z+yaxis_carriage_printbed_offset.z+printbed_size.z,353*mm];
axis_pos_z = axis_range_z[0];

echo(str("Axis range X: " , axis_range_x[0], " ", axis_range_x[1]," mm"));
echo(str("Axis range Y: " , axis_range_y[0], " ", axis_range_y[1]," mm"));
echo(str("Axis range Z: " , axis_range_z[0], " ", axis_range_z[1]," mm"));

echo(str("Build area Z: " , axis_range_z[1]-axis_range_z[0] , " mm"));

home_offset_x0 = axis_range_x[0] - axis_printrange_x[0] + v_x(extruder_b_filapath_offset)[0];
echo(str("Home offset X0: " , home_offset_x0));
echo(str("Tool offset X: " , axis_range_x_+x_carriage_w/2));

module x_axis()
{
    // x axis
    tz(axis_pos_z)
    {
        zrod_offset = zmotor_mount_rod_offset_x;
        for(z=xaxis_beltpath_z_offsets)
        tz(z)
        ty(xaxis_zaxis_distance_y)
        tx(-sign(z)*(-main_width/2+extrusion_size+zaxis_rod_d/2+xaxis_end_motor_offset.x))
        rotate(90*X)
        belt_path(
            len=-xaxis_end_motor_offset.x+extrusion_size+zaxis_rod_d/2+(main_width-2*extrusion_size-2*zaxis_rod_d/2),
            belt_width=xaxis_belt_width,
            belt=xaxis_belt,
            pulley_d=xaxis_pulley_inner_d,
            orient=X, align=-sign(z)*X);

        for(x=[0:len(axis_range_x)-1])
        {
            /*#cubea(size=[x_carriage_w,10,100]);*/

            pos = axis_x_parked[x] ? axis_range_x[x] : (axis_printrange_x[x]+axis_x_pos_relative[x]*printbed_size[0]);
            echo("x carriage", x, pos);

            tx(pos)
            attach(xaxis_carriage_conn, [[0,-xaxis_zaxis_distance_y,0],N])
            {
                $show_vit=true;

                mirror([x==0?0:1,0,0])
                x_carriage_withmounts(beltpath_sign=x==0?-1:1, with_sensormount=x==0);

                x_carriage_extruder(x==0?-1:1);
            }
        }

        // x smooth rods
        for(z=[-1,1])
        translate([xaxis_rod_offset_x,xaxis_zaxis_distance_y,z*(xaxis_rod_distance/2)])
        material(Mat_Chrome)
        cylindera(h=xaxis_rod_l,d=xaxis_rod_d+.1, orient=X);

        for(x=[-1,1])
        tx(x*(main_width/2))
        ty(xaxis_zaxis_distance_y)
        tx(-x*(extrusion_size+zaxis_rod_d/2))
        mirror([max(0,x),0,0])
        {
            xaxis_end(with_motor=true, beltpath_index=max(0,x), show_motor=true, show_nut=true);

            xaxis_end_bucket();
        }
    }
}

module y_axis()
{
    // y axis
    attach([[yaxis_belt_path_offset_x,main_depth/2+extrusion_size,yaxis_motor_offset_z], Y], yaxis_motor_mount_conn)
    yaxis_motor_mount();

    extrusion_idler_conn = [[yaxis_belt_path_offset_x, -main_depth/2-extrusion_size, -extrusion_size+yaxis_idler_offset_z], [0,-1,0]];
    attach(extrusion_idler_conn, yaxis_idler_conn)
    {
        yaxis_idler();

        attach(yaxis_idler_conn_pulleyblock, yaxis_idler_pulleyblock_conn)
        yaxis_idler_pulleyblock(show_pulley=true);
    }

    translate([yaxis_belt_path_offset_x,0,yaxis_belt_path_offset_z])
    translate([0,main_depth/2+extrusion_size+yaxis_motor_offset_x,0])
    rotate(90*Y)
    belt_path(
        len=main_depth+yaxis_motor_offset_x-yaxis_idler_pulley_offset_y+extrusion_size,
        belt_width=yaxis_belt_width,
        pulley_d=yaxis_pulley_inner_d,
        belt=yaxis_belt,
        align=-Y, orient=Y);

    translate([0,-axis_pos_y,get(LinearBearingInnerDiameter, yaxis_bearing)/2])
    attach(yaxis_carriage_bearing_mount_conn_bearing, yaxis_belt_mount_conn)
    yaxis_belt_holder();

    t(yaxis_carriage_offset)
    {
        // y smooth rod clamps to frame
        for(x=[-1,1])
        for(y=[-1,1])
        attach([[x*(yaxis_rod_distance/2),y*(main_depth/2+extrusion_size/2),0],Z],mount_rod_clamp_conn_rod)
        mount_rod_clamp_full(rod_d=zaxis_rod_d, thick=4, width=extrusion_size, thread=extrusion_thread, orient=Y);

        for(x=[-1,1])
        tx(x*(yaxis_rod_distance/2))
        {
            // y smooth rods
            material(Mat_Chrome)
            cylindera(h=yaxis_rod_l,d=yaxis_rod_d, orient=Y);

            // y bearing mounts
            for(y=[-1,1])
            attach([[0,y*(yaxis_bearing_distance_y/2)-axis_pos_y,0],-Z], yaxis_carriage_bearing_mount_conn_bearing)
            {
                yaxis_carriage_bearing_mount();
            }
        }

        attach(yaxis_carriage_bearing_mount_conn_bearing, [Y*axis_pos_y,Z])
        {
            yaxis_carriage();

            t(yaxis_carriage_printbed_offset)
            printbed(align=Z);
        }
    }

}

module z_axis()
{
    // z axis
    for(x=[-1,1])
    {
        tx(x*(main_width/2))
        mirror([x==-1?0:1,0,0])
        {
            tz(main_height)
            tx(extrusion_size)
            tx(+zaxis_rod_d/2)
            tz(extrusion_size/2)
            mount_rod_clamp_full(
            rod_d=zaxis_rod_d,
            screw_dist=zmotor_mount_clamp_dist,
            thick=5,
            base_thick=5,
                width=extrusion_size,
                thread=extrusion_mount_thread
                );

            /*tx(zmotor_mount_rod_offset_x)*/
            tx(extrusion_size)
            tx(+zaxis_rod_d/2)
            tz(-extrusion_size/2)
            mount_rod_clamp_full(
                    rod_d=zaxis_rod_d,
                    screw_dist=zmotor_mount_clamp_dist,
                    thick=5,
                    base_thick=5,
                width=extrusion_size,
                    thread=zmotor_mount_clamp_thread);
            }

        tx(x*(main_width/2))
        mirror([x==-1?0:1,0,0])
        {
            tz(zaxis_motor_offset_z)
            mirror(X)
            zaxis_motor_mount(show_motor=true);

            // z smooth rods
            tx(extrusion_size+zaxis_rod_d/2)
            tz(zaxis_motor_offset_z-80*mm)
            material(Mat_Chrome)
            cylindera(h=zaxis_rod_l,d=zaxis_rod_d, align=Z);
        }
    }
}

module gantry_upper()
{
    for(y=[-1,1])
    ty(y*(main_upper_dist_y/2+extrusion_size/2))
    {
        for(x=[-1,1])
        tx(x*(main_width/2))
        linear_extrusion(h=main_height, align=-x*X+Z, orient=Z);

        tz(main_height)
        linear_extrusion(h=main_upper_width, align=Z, orient=X);
    }

    ty(-gantry_upper_offset_y)
    for(x=[-1,1])
    tx(x*(main_width/2))
    tz(main_height)
        linear_extrusion(h=main_upper_dist_y, align=-x*X+Z, orient=Y);

    // upper gantry connectors
    /*for(x=[-1,1])*/
    /*translate([x*(main_width/2),0,main_height])*/
    /*mirror([x==-1?1:0,0,0])*/
    /*gantry_upper_connector();*/
}

module gantry_lower()
{
    for(z=[-1,1])
    translate([0,0,z*-main_lower_dist_z/2])
    {
        for(y=[-1,1])
        translate([0, y*(main_depth/2), 0])
        linear_extrusion(h=main_width, align=[0,y,-1], orient=X);

        for(x=[-1,1])
        translate([x*(main_width/2), 0, 0])
        linear_extrusion(h=main_depth, align=-x*X-Z, orient=Y);
    }

    // lower gantry connectors
    for(x=[-1,1])
    for(y=[-1,1])
    translate([x*(main_width/2),y*(main_depth/2),-extrusion_size/2])
    mirror([x==1?0:-1,0,0])
    mirror([0,y==1?1:0,0])
    gantry_lower_connector();

}

module enclosure()
{
    // inner
    w=56*cm;
    h=56*cm;
    d=58*cm;
    wallthick=2*cm;
    backthick=0.5*cm;

    translate([0, 0, h/2+wallthick])
    {
        // left/right walls
        for(x=[-1,1])
        translate([x*w/2,0,0])
        cubea([wallthick,d,h], align=[x, 0, 0]);

        // back plate
        translate([0,d/2,0])
        cubea([w,backthick,h], align=[0,-1, 0]);

        // top/bottom plate
        for(z=[-1,1])
        translate([0,0,z*h/2])
        cubea([w+wallthick*2,d,wallthick], align=[0,0, z]);
    }
}

module main()
{
    /*render()*/
    tz(-main_lower_dist_z/2)
    gantry_lower();

    /*render()*/
    translate(-zaxis_rod_offset)
    ty(gantry_upper_offset_y)
    gantry_upper();

    /*render()*/
    x_axis();

    /*render()*/
    y_axis();

    /*render()*/
    z_axis();

    /*render()*/
    /*translate([-75*mm,0,0])*/
    /*translate([0,main_depth/2,0])*/
    /*translate([0,extrusion_size,0])*/
    /*translate([0,0,-main_lower_dist_z/2-extrusion_size/2])*/
    /*power_panel_iec320(orient=[0,-1,0], align=Y);*/

    if(!$preview_mode)
    {
        render()
        ty(-main_depth/2)
        ty(-extrusion_size/2)
        tz(-main_lower_dist_z/2)
        mount_lcd2004(show_gantry=true);

        for(x=[-1,1])
        translate([x*(main_width/2-extrusion_size),main_depth/2,-main_lower_dist_z-extrusion_size])
        translate([-x*psu_a_w/2, -psu_a_d/2, psu_a_h/2])
        {
            render()
            psu_a();

            render()
            mirror([x==-1?1:0,0,0])
            ty(-psu_a_screw_dist_y/2)
            psu_a_extrusion_bracket_side();

            render()
            translate(psu_a_screw_dist_y/2)
            psu_a_extrusion_bracket_back();
        }
    }
}

feet_height = 8*mm;
translate([0, 0, main_lower_dist_z+extrusion_size*2+feet_height])
main();

/*psu();*/

/*%enclosure();*/

include <config.scad>

include <thing_libutils/system.scad>
include <thing_libutils/units.scad>
include <thing_libutils/materials.scad>

use <thing_libutils/screws.scad>
use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/transforms.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/linear-extrusion.scad>;
use <thing_libutils/timing-belts.scad>;

use <x-end.scad>
include <x-end.h>

use <x-carriage.scad>
include <x-carriage.h>

use <y-carriage.scad>
include <y-carriage.h>

use <y-motor-mount.scad>
include <y-motor-mount.h>

use <y-carriage-bearing-mount.scad>
include <y-carriage-bearing-mount.h>

use <y-carriage-belt-clamp.scad>
include <y-carriage-belt-clamp.h>

use <y-idler.scad>
include <y-idler.h>

use <z-motor-mount.scad>
include <z-motor-mount.h>

use <gantry-upper-connector.scad>
use <gantry-lower-connector.scad>

use <rod-clamps.scad>
include <rod-clamps.h>

use <printbed.scad>
include <printbed.h>

/*use <psu.scad>*/
/*include <psu.h>*/

/*use <lcd2004.scad>*/
/*use <power-panel-iec320.scad>*/

// x carriage
axis_range_x_ = main_width/2 - extrusion_size - zaxis_rod_d/2 - xaxis_end_width_right(true) - x_carriage_w/2 - .5*mm;
axis_range_x = [-1,1] *  axis_range_x_;
axis_printrange_x = [-1, 1] * (printbed_size[0]/2+extruder_b_hotend_mount_offset.x);
axis_x_pos_relative=[1,0];
axis_x_parked = [false, true];

axis_range_y=[0*mm,200*mm];
axis_pos_y = -axis_range_y[0]/2-30*mm;
axis_range_z=[-extruder_offset.z-extruder_offset_b.z-extruder_b_hotend_mount_offset.z+hotend_height+yaxis_carriage_offset.z+yaxis_carriage_bearing_mount_conn_bearing[0].z+yaxis_carriage_printbed_offset.z+printbed_size.z,353*mm];
axis_pos_z = axis_range_z[0];

echo(str("Axis range X: " , axis_range_x[0], " ", axis_range_x[1]," mm"));
echo(str("Axis range Y: " , axis_range_y[0], " ", axis_range_y[1]," mm"));
echo(str("Axis range Z: " , axis_range_z[0], " ", axis_range_z[1]," mm"));

echo(str("Build area Z: " , axis_range_z[1]-axis_range_z[0] , " mm"));

home_offset_x0 = axis_range_x[0] - axis_printrange_x[0] + v_x(extruder_b_filapath_offset)[0];
echo(str("Home offset X0: " , home_offset_x0));
echo(str("Tool offset X: " , axis_range_x_+x_carriage_w/2));

module x_axis()
{
    // x axis
    tz(axis_pos_z)
    {
        zrod_offset = zmotor_mount_rod_offset_x;
        for(z=xaxis_beltpath_z_offsets)
        tz(z)
        ty(xaxis_zaxis_distance_y)
        tx(-sign(z)*(-main_width/2+extrusion_size+zaxis_rod_d/2+xaxis_end_motor_offset.x))
        rotate(90*X)
        belt_path(
            len=-xaxis_end_motor_offset.x+extrusion_size+zaxis_rod_d/2+(main_width-2*extrusion_size-2*zaxis_rod_d/2),
            belt_width=xaxis_belt_width,
            belt=xaxis_belt,
            pulley_d=xaxis_pulley_inner_d,
            orient=X, align=-sign(z)*X);

        for(x=[0:len(axis_range_x)-1])
        {
            /*#cubea(size=[x_carriage_w,10,100]);*/

            pos = axis_x_parked[x] ? axis_range_x[x] : (axis_printrange_x[x]+axis_x_pos_relative[x]*printbed_size[0]);
            echo("x carriage", x, pos);

            tx(pos)
            attach(xaxis_carriage_conn, [[0,-xaxis_zaxis_distance_y,0],N])
            {
                $show_vit=true;

                mirror([x==0?0:1,0,0])
                x_carriage_withmounts(beltpath_sign=x==0?-1:1, with_sensormount=x==0);

                x_carriage_extruder(x==0?-1:1);
            }
        }

        // x smooth rods
        for(z=[-1,1])
        translate([xaxis_rod_offset_x,xaxis_zaxis_distance_y,z*(xaxis_rod_distance/2)])
        material(Mat_Chrome)
        cylindera(h=xaxis_rod_l,d=xaxis_rod_d+.1, orient=X);

        for(x=[-1,1])
        tx(x*(main_width/2))
        ty(xaxis_zaxis_distance_y)
        tx(-x*(extrusion_size+zaxis_rod_d/2))
        mirror([max(0,x),0,0])
        {
            xaxis_end(with_motor=true, beltpath_index=max(0,x), show_motor=true, show_nut=true);

            xaxis_end_bucket();
        }
    }
}

module y_axis()
{
    // y axis
    attach([[yaxis_belt_path_offset_x,main_depth/2+extrusion_size,yaxis_motor_offset_z], Y], yaxis_motor_mount_conn)
    yaxis_motor_mount();

    extrusion_idler_conn = [[yaxis_belt_path_offset_x, -main_depth/2-extrusion_size, -extrusion_size+yaxis_idler_offset_z], [0,-1,0]];
    attach(extrusion_idler_conn, yaxis_idler_conn)
    {
        yaxis_idler();

        attach(yaxis_idler_conn_pulleyblock, yaxis_idler_pulleyblock_conn)
        yaxis_idler_pulleyblock(show_pulley=true);
    }

    translate([yaxis_belt_path_offset_x,0,yaxis_belt_path_offset_z])
    translate([0,main_depth/2+extrusion_size+yaxis_motor_offset_x,0])
    rotate(90*Y)
    belt_path(
        len=main_depth+yaxis_motor_offset_x-yaxis_idler_pulley_offset_y+extrusion_size,
        belt_width=yaxis_belt_width,
        pulley_d=yaxis_pulley_inner_d,
        belt=yaxis_belt,
        align=-Y, orient=Y);

    translate([0,-axis_pos_y,get(LinearBearingInnerDiameter, yaxis_bearing)/2])
    attach(yaxis_carriage_bearing_mount_conn_bearing, yaxis_belt_mount_conn)
    yaxis_belt_holder();

    t(yaxis_carriage_offset)
    {
        // y smooth rod clamps to frame
        for(x=[-1,1])
        for(y=[-1,1])
        attach([[x*(yaxis_rod_distance/2),y*(main_depth/2+extrusion_size/2),0],Z],mount_rod_clamp_conn_rod)
        mount_rod_clamp_full(rod_d=zaxis_rod_d, thick=4, width=extrusion_size, thread=extrusion_thread, orient=Y);

        for(x=[-1,1])
        tx(x*(yaxis_rod_distance/2))
        {
            // y smooth rods
            material(Mat_Chrome)
            cylindera(h=yaxis_rod_l,d=yaxis_rod_d, orient=Y);

            // y bearing mounts
            for(y=[-1,1])
            attach([[0,y*(yaxis_bearing_distance_y/2)-axis_pos_y,0],-Z], yaxis_carriage_bearing_mount_conn_bearing)
            {
                yaxis_carriage_bearing_mount();
            }
        }

        attach(yaxis_carriage_bearing_mount_conn_bearing, [Y*axis_pos_y,Z])
        {
            yaxis_carriage();

            t(yaxis_carriage_printbed_offset)
            printbed(align=Z);
        }
    }

}

module z_axis()
{
    // z axis
    for(x=[-1,1])
    {
        tx(x*(main_width/2))
        mirror([x==-1?0:1,0,0])
        {
            tz(main_height)
            tx(extrusion_size)
            tx(+zaxis_rod_d/2)
            tz(extrusion_size/2)
            mount_rod_clamp_full(
            rod_d=zaxis_rod_d,
            screw_dist=zmotor_mount_clamp_dist,
            thick=5,
            base_thick=5,
                width=extrusion_size,
                thread=extrusion_mount_thread
                );

            /*tx(zmotor_mount_rod_offset_x)*/
            tx(extrusion_size)
            tx(+zaxis_rod_d/2)
            tz(-extrusion_size/2)
            mount_rod_clamp_full(
                    rod_d=zaxis_rod_d,
                    screw_dist=zmotor_mount_clamp_dist,
                    thick=5,
                    base_thick=5,
                width=extrusion_size,
                    thread=zmotor_mount_clamp_thread);
            }

        tx(x*(main_width/2))
        mirror([x==-1?0:1,0,0])
        {
            tz(zaxis_motor_offset_z)
            mirror(X)
            zaxis_motor_mount(show_motor=true);

            // z smooth rods
            tx(extrusion_size+zaxis_rod_d/2)
            tz(zaxis_motor_offset_z-80*mm)
            material(Mat_Chrome)
            cylindera(h=zaxis_rod_l,d=zaxis_rod_d, align=Z);
        }
    }
}

module gantry_upper()
{
    for(y=[-1,1])
    ty(y*(main_upper_dist_y/2+extrusion_size/2))
    {
        for(x=[-1,1])
        tx(x*(main_width/2))
        linear_extrusion(h=main_height, align=-x*X+Z, orient=Z);

        tz(main_height)
        linear_extrusion(h=main_upper_width, align=Z, orient=X);
    }

    ty(-gantry_upper_offset_y)
    for(x=[-1,1])
    tx(x*(main_width/2))
    tz(main_height)
        linear_extrusion(h=main_upper_dist_y, align=-x*X+Z, orient=Y);

    // upper gantry connectors
    /*for(x=[-1,1])*/
    /*translate([x*(main_width/2),0,main_height])*/
    /*mirror([x==-1?1:0,0,0])*/
    /*gantry_upper_connector();*/
}

module gantry_lower()
{
    for(z=[-1,1])
    translate([0,0,z*-main_lower_dist_z/2])
    {
        for(y=[-1,1])
        translate([0, y*(main_depth/2), 0])
        linear_extrusion(h=main_width, align=[0,y,-1], orient=X);

        for(x=[-1,1])
        translate([x*(main_width/2), 0, 0])
        linear_extrusion(h=main_depth, align=-x*X-Z, orient=Y);
    }

    // lower gantry connectors
    for(x=[-1,1])
    for(y=[-1,1])
    translate([x*(main_width/2),y*(main_depth/2),-extrusion_size/2])
    mirror([x==1?0:-1,0,0])
    mirror([0,y==1?1:0,0])
    gantry_lower_connector();

}

module enclosure()
{
    // inner
    w=56*cm;
    h=56*cm;
    d=58*cm;
    wallthick=2*cm;
    backthick=0.5*cm;

    translate([0, 0, h/2+wallthick])
    {
        // left/right walls
        for(x=[-1,1])
        translate([x*w/2,0,0])
        cubea([wallthick,d,h], align=[x, 0, 0]);

        // back plate
        translate([0,d/2,0])
        cubea([w,backthick,h], align=[0,-1, 0]);

        // top/bottom plate
        for(z=[-1,1])
        translate([0,0,z*h/2])
        cubea([w+wallthick*2,d,wallthick], align=[0,0, z]);
    }
}

module main()
{
    /*render()*/
    tz(-main_lower_dist_z/2)
    gantry_lower();

    /*render()*/
    translate(-zaxis_rod_offset)
    ty(gantry_upper_offset_y)
    gantry_upper();

    /*render()*/
    x_axis();

    /*render()*/
    y_axis();

    /*render()*/
    z_axis();

    /*render()*/
    /*translate([-75*mm,0,0])*/
    /*translate([0,main_depth/2,0])*/
    /*translate([0,extrusion_size,0])*/
    /*translate([0,0,-main_lower_dist_z/2-extrusion_size/2])*/
    /*power_panel_iec320(orient=[0,-1,0], align=Y);*/

    if(!$preview_mode)
    {
        render()
        ty(-main_depth/2)
        ty(-extrusion_size/2)
        tz(-main_lower_dist_z/2)
        mount_lcd2004(show_gantry=true);

        for(x=[-1,1])
        translate([x*(main_width/2-extrusion_size),main_depth/2,-main_lower_dist_z-extrusion_size])
        translate([-x*psu_a_w/2, -psu_a_d/2, psu_a_h/2])
        {
            render()
            psu_a();

            render()
            mirror([x==-1?1:0,0,0])
            ty(-psu_a_screw_dist_y/2)
            psu_a_extrusion_bracket_side();

            render()
            translate(psu_a_screw_dist_y/2)
            psu_a_extrusion_bracket_back();
        }
    }
}

feet_height = 8*mm;
translate([0, 0, main_lower_dist_z+extrusion_size*2+feet_height])
main();

/*psu();*/

/*%enclosure();*/


misc: add dict_replace and dict_replace_multiple

use <scad-utils/linalg.scad>
use <scad-utils/lists.scad>

function posvec(path_vec) = [for(v=path_vec) translation_part(v)];
function posvec_x(path_vec) = [for(v=path_vec) translation_part(v)[0]];
function posvec_y(path_vec) = [for(v=path_vec) translation_part(v)[1]];
function posvec_z(path_vec) = [for(v=path_vec) translation_part(v)[2]];

function vec_i(v3,i) = [for(v=v3) v[i]];
function vec_0(v3) = vec_i(v3,0);
function vec_1(v3) = vec_i(v3,1);
function vec_2(v3) = vec_i(v3,2);

function vec_add(vec,v) = [for(vv=vec) vv+v];

function v_itrlen(vec) = [0:1:len(vec)-1];

function range1(v1) = [min(v1), max(v1)];
function range3(v3) = [range1(vec_0(v3)), range1(vec_1(v3)), range1(vec_2(v3))];
function bbox(r) = [ [r[0][0],r[1][0],r[2][0]], [r[0][1],r[1][1],r[2][1]] ];
function transform_pp(vec_m, t_pre, t_post) = [for(m=vec_m) (t_pre*m)*t_post];
function transform_pre(vec_m, t) = [for(m=vec_m) t*m];
function transform_post(vec_m, t) = [for(m=vec_m) m*t];

// sum a vector up to position i
function v_sum(v, i) = i >= 0 ? v[i] + v_sum(v, i - 1) : 0;

// cumulative sum of vector [1,2,3] = [1,3,6]
function v_cumsum(v, start=0) = [for(i=[start:1:len(v)-1]) v_sum(v,i)];

// filter/remove a val from a vec
function filter(vec,val=undef) = [for(v=vec) if(v!=val) v];

function vec_pair_double_transform_post(vec,t1,t2)=
    flatten(
        [for(v=vec)
            [transform_post(v,t1),transform_post(v,t2)]
        ]);

function vec_pair_double(vec)=flatten([for(v=vec) [v,v] ]);

/** Calculates length of hypotenuse according to pythagoras */
function pythag_hyp(a, b)=sqrt(a*a+b*b);
function pythag_leg(b, c)=sqrt(c*c-b*b);

//-- Calculate the module of a vector
function v_mod(v) = (sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]));

//-- Calculate the cros product of two vectors
function v_cross(u,v) = [
  u[1]*v[2] - v[1]*u[2],
  -(u[0]*v[2] - v[0]*u[2]) ,
  u[0]*v[1] - v[0]*u[1]];

//-- Calculate the dot product of two vectors
function v_dot(u,v) = u[0]*v[0]+u[1]*v[1]+u[2]*v[2];

//-- Return the unit vector of a vector
function v_unitv(v) = v/v_mod(v);

//-- Return the angle between two vectores
function v_anglev(u,v) = acos( v_dot(u,v) / (v_mod(u)*v_mod(v)) );

function _orient_angles(zaxis)=
[-asin(zaxis.y / norm(zaxis)),
    atan2(zaxis.x, zaxis.z),
    0];

//matrix rotation functions
function _rotate_x_matrix(a)=
[[1,0,0,0],
    [0,cos(a),-sin(a),0],
    [0,sin(a),cos(a),0],
    [0,0,0,1]];

function _rotate_y_matrix(a)=
[[cos(a),0,sin(a),0],
    [0,1,0,0],
    [-sin(a),0,cos(a),0],
    [0,0,0,1]];

function _rotate_z_matrix(a)=
[[cos(a),-sin(a),0,0],
    [sin(a),cos(a),0,0],
    [0,0,1,0],
    [0,0,0,1]];

function _rotate_matrix(a)=_rotate_z_matrix(a.z)*_rotate_y_matrix(a.y)*_rotate_x_matrix(a.x);

//hadamard product (aka "component-wise" product) for vectors
function hadamard(v1,v2) = [v1.x*v2.x, v1.y*v2.y, v1.z*v2.z];

// search in a dictionary (vector w/key-value pairs) and replace the value for a given key
function dict_replace(dict, key, newvalue)=[
        for(kv=dict)
        kv[0] == key ?
            [key, newvalue]
            :
            kv
        ];

function dict_replace_multiple(dict, newvaluesdict)=[
    for(kv_old=dict)
    let(r = search(kv_old[0], newvaluesdict, num_returns_per_match=0, index_col_num=0))
    r==[]?kv_old:newvaluesdict[r[0]]
    ];


Corrected Typo

Corrected Typo

// Mockup of OmmatiDiag
/*
 * The mockup was done after the first crude drawing with
 * [Tinkercad](https://tinkercad.com/things/3utMiKsZhx9) proved to be too
 * inflexible.
 * The basic unit of the detector will be the scintillator size, which we
 * chose to be 17" x 17" translating to 430 x 430 mm in SI units.
*/

// Basic length variables [mm]
unitlength = 430;
padding = 20;
height = 100;
semitransparent = 0.618;
nearlytransparent = 0.309;

// dimlines.scad is used to easily draw dimensional measurements
// http://www.cannymachines.com/entries/9/openscad_dimensioned_drawings
include <dimlines.scad>

DIM_LINE_WIDTH = .025 * unitlength;
DIM_SPACE = .1 * unitlength;

//~ translate([unitlength + 50 , padding/2, 0])
//~ rotate([0,0,90])
  //~ dimensions(unitlength, line_width=DIM_LINE_WIDTH, loc=0);

// Housing
module Housing()
  color ("gray", semitransparent) {
    // box bottom
    cube([unitlength + padding, unitlength + padding,1]);
    // box back walls
    cube([unitlength + padding, 1, height]);
    cube([1, unitlength + padding, height]);
    // box front walls, can (and should be turned off for increased visibility)
    translate(v = [0, unitlength + padding, 0]) {
      cube([unitlength + padding, 1, height]);
    }
    translate(v = [unitlength + padding, 0, 0]) {
      cube([1, unitlength + padding, height]); //
    }
    }
Housing();

// Scintillator
module Scintillator()
  translate([padding/2, padding/2, 1]) {
    color ("green", 1) {
      cube([unitlength,unitlength,1]);
      }
    }
Scintillator();

// CMOS Backplate
module Backplate()
  translate([(unitlength+padding)/2 + 5, (unitlength+padding)/2 + 5, height-15]) {
    color ("red", semitransparent) {
      cube([350,320,1],center=true);
      }
    }
Backplate();

// Ommatidium
module Ommatidium() {
  // FOV of one Ommatidium
  FOVSize = ([unitlength/4, unitlength/3]);
  module FOV()
    color("pink",0.5) cube([FOVSize[0], FOVSize[1], 1], center=true);

  // CMOS (Aptina AR0130)
  CMOSSize = ([1280, 960]);
  pixelsize = 3.75 / 1000; // [um]
  module CMOS()
    color ("blue")
      cube([CMOSSize[0] * pixelsize, CMOSSize[1] * pixelsize, 0.5], center=true);
  translate ([0,0,0]) CMOS();

  // Ommatidium back plate
  module Ommatidiumplate()
    color ("red", semitransparent)
      cube([15, 20, 1], center=true);
  translate ([5,7,0]) Ommatidiumplate();

  // FOV CMOS
  d_cmos_lens = 15;
  d_lens_scintillator = height - d_cmos_lens - 15;
  module CMOSCone()
      color("orange", nearlytransparent)
      cylinder(h = d_cmos_lens,
                r1 = CMOSSize[0] * pixelsize / 2 ,
                r2 = lensdiameter * 2, center=true);
  module CMOSCross() {
    color("red", 1)
    polyhedron(
      points=[ [0, 0, 0], //origin
        [-CMOSSize[0]*pixelsize/2, 0, d_cmos_lens],     // horizontal_1
        [CMOSSize[0]*pixelsize/2, 0,d_cmos_lens],       // horizontal_2
        [0, -CMOSSize[1] * pixelsize / 2,d_cmos_lens],  // vertical_1
        [0,  CMOSSize[1] * pixelsize / 2,d_cmos_lens]], // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }

  mirror([0,0,1]) translate([0,0,-d_cmos_lens])CMOSCross();
  translate([0,0,d_cmos_lens/2]) CMOSCone();

  // Lens
  lensdiameter = 4;
  module Lens()
    // the lens is a squashed sphere: http://is.gd/4H9sZf
    scale([2,2,0.5]) sphere(lensdiameter, $fn=50, center=true);
  translate([0, 0, d_cmos_lens]) Lens();

  // FOV Lens
  module LensCone()
    color("orange",nearlytransparent)
    scale([1, 4/3, 1])
    cylinder(h = d_lens_scintillator,
              r1 = lensdiameter * 2,
              r2 = FOVSize[1]/2 * 1.2);
  module LensCross() {
    color("red", 1) polyhedron(
      points=[ [0, 0, 0], //origin
        [-FOVSize[0]/2, 0, d_lens_scintillator],   // horizontal_1
        [FOVSize[0]/2, 0,d_lens_scintillator],     // horizontal_2
        [0, -FOVSize[1]/2 ,d_lens_scintillator],   // vertical_1
        [0,  FOVSize[1]/2 ,d_lens_scintillator]],  // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }
  translate([0,0,d_cmos_lens]) LensCross();
  translate([0,0,d_cmos_lens]) LensCone();
  translate([0,0,d_cmos_lens + d_lens_scintillator]) FOV();
}

translate([unitlength/4/2 + padding/2, unitlength/3/2 + padding/2, height-14])
mirror([0,0,1])
for (xpos=[0:3], ypos = [0:2]) // iterate over x and y
  translate([xpos*unitlength/4, ypos*unitlength/3, 0]) Ommatidium();

// Mockup of OmmatiDiag
/*
 * The mockup was done after the first crude drawing with
 * [Tinkrecad](https://tinkercad.com/things/3utMiKsZhx9) proved to be too
 * inflexible.
 * The basic unit of the detector will be the scintillator size, which we
 * chose to be 17" x 17" translating to 430 x 430 mm in SI units.
*/

// Basic length variables [mm]
unitlength = 430;
padding = 20;
height = 100;
semitransparent = 0.618;
nearlytransparent = 0.309;

// dimlines.scad is used to easily draw dimensional measurements
// http://www.cannymachines.com/entries/9/openscad_dimensioned_drawings
include <dimlines.scad>

DIM_LINE_WIDTH = .025 * unitlength;
DIM_SPACE = .1 * unitlength;

//~ translate([unitlength + 50 , padding/2, 0])
//~ rotate([0,0,90])
  //~ dimensions(unitlength, line_width=DIM_LINE_WIDTH, loc=0);

// Housing
module Housing()
  color ("gray", semitransparent) {
    // box bottom
    cube([unitlength + padding, unitlength + padding,1]);
    // box back walls
    cube([unitlength + padding, 1, height]);
    cube([1, unitlength + padding, height]);
    // box front walls, can (and should be turned off for increased visibility)
    translate(v = [0, unitlength + padding, 0]) {
      cube([unitlength + padding, 1, height]);
    }
    translate(v = [unitlength + padding, 0, 0]) {
      cube([1, unitlength + padding, height]); //
    }
    }
Housing();

// Scintillator
module Scintillator()
  translate([padding/2, padding/2, 1]) {
    color ("green", 1) {
      cube([unitlength,unitlength,1]);
      }
    }
Scintillator();

// CMOS Backplate
module Backplate()
  translate([(unitlength+padding)/2 + 5, (unitlength+padding)/2 + 5, height-15]) {
    color ("red", semitransparent) {
      cube([350,320,1],center=true);
      }
    }
Backplate();

// Ommatidium
module Ommatidium() {
  // FOV of one Ommatidium
  FOVSize = ([unitlength/4, unitlength/3]);
  module FOV()
    color("pink",0.5) cube([FOVSize[0], FOVSize[1], 1], center=true);

  // CMOS (Aptina AR0130)
  CMOSSize = ([1280, 960]);
  pixelsize = 3.75 / 1000; // [um]
  module CMOS()
    color ("blue")
      cube([CMOSSize[0] * pixelsize, CMOSSize[1] * pixelsize, 0.5], center=true);
  translate ([0,0,0]) CMOS();

  // Ommatidium back plate
  module Ommatidiumplate()
    color ("red", semitransparent)
      cube([15, 20, 1], center=true);
  translate ([5,7,0]) Ommatidiumplate();

  // FOV CMOS
  d_cmos_lens = 15;
  d_lens_scintillator = height - d_cmos_lens - 15;
  module CMOSCone()
      color("orange", nearlytransparent)
      cylinder(h = d_cmos_lens,
                r1 = CMOSSize[0] * pixelsize / 2 ,
                r2 = lensdiameter * 2, center=true);
  module CMOSCross() {
    color("red", 1)
    polyhedron(
      points=[ [0, 0, 0], //origin
        [-CMOSSize[0]*pixelsize/2, 0, d_cmos_lens],     // horizontal_1
        [CMOSSize[0]*pixelsize/2, 0,d_cmos_lens],       // horizontal_2
        [0, -CMOSSize[1] * pixelsize / 2,d_cmos_lens],  // vertical_1
        [0,  CMOSSize[1] * pixelsize / 2,d_cmos_lens]], // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }

  mirror([0,0,1]) translate([0,0,-d_cmos_lens])CMOSCross();
  translate([0,0,d_cmos_lens/2]) CMOSCone();

  // Lens
  lensdiameter = 4;
  module Lens()
    // the lens is a squashed sphere: http://is.gd/4H9sZf
    scale([2,2,0.5]) sphere(lensdiameter, $fn=50, center=true);
  translate([0, 0, d_cmos_lens]) Lens();

  // FOV Lens
  module LensCone()
    color("orange",nearlytransparent)
    scale([1, 4/3, 1])
    cylinder(h = d_lens_scintillator,
              r1 = lensdiameter * 2,
              r2 = FOVSize[1]/2 * 1.2);
  module LensCross() {
    color("red", 1) polyhedron(
      points=[ [0, 0, 0], //origin
        [-FOVSize[0]/2, 0, d_lens_scintillator],   // horizontal_1
        [FOVSize[0]/2, 0,d_lens_scintillator],     // horizontal_2
        [0, -FOVSize[1]/2 ,d_lens_scintillator],   // vertical_1
        [0,  FOVSize[1]/2 ,d_lens_scintillator]],  // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }
  translate([0,0,d_cmos_lens]) LensCross();
  translate([0,0,d_cmos_lens]) LensCone();
  translate([0,0,d_cmos_lens + d_lens_scintillator]) FOV();
}

translate([unitlength/4/2 + padding/2, unitlength/3/2 + padding/2, height-14])
mirror([0,0,1])
for (xpos=[0:3], ypos = [0:2]) // iterate over x and y
  translate([xpos*unitlength/4, ypos*unitlength/3, 0]) Ommatidium();


misc: add take3 and vec3

misc: add take3 and vec3

include <system.scad>
use <scad-utils/linalg.scad>
use <scad-utils/lists.scad>

function posvec(path_vec) = [for(v=path_vec) translation_part(v)];
function posvec_x(path_vec) = [for(v=path_vec) translation_part(v)[0]];
function posvec_y(path_vec) = [for(v=path_vec) translation_part(v)[1]];
function posvec_z(path_vec) = [for(v=path_vec) translation_part(v)[2]];

function vec_i(v3,i) = [for(v=v3) v[i]];
function vec_0(v3) = vec_i(v3,0);
function vec_1(v3) = vec_i(v3,1);
function vec_2(v3) = vec_i(v3,2);

// if V is array and len == 1, return single value, otherwise return V
function singlify(V) = len(V)==1?V[0]:V;

function v_itrlen(vec) = [0:1:len(vec)-1];

function range1(v1) = [min(v1), max(v1)];
function range3(v3) = [range1(vec_0(v3)), range1(vec_1(v3)), range1(vec_2(v3))];
function bbox(r) = [ [r[0][0],r[1][0],r[2][0]], [r[0][1],r[1][1],r[2][1]] ];
function transform_pp(vec_m, t_pre, t_post) = [for(m=vec_m) (t_pre*m)*t_post];
function transform_pre(vec_m, t) = [for(m=vec_m) t*m];
function transform_post(vec_m, t) = [for(m=vec_m) m*t];

function clamp(v, v1, v2) = min(max(v,v1),v2);

// from the start (or s'th element) to the e'th element - remember elements are zero based
function v_sum(v,e=U,start=0) =
let(e_= fallback(e, len(v)-1))
(e==start ? v[e] : v[e_] + v_sum(v,e_-1,start));

function get(key, dict) =
    let(x = search(key, dict))
    let(kv = dict[x[0]])
    kv[1];

function v_i(vec,i) = [for(vv=vec) vv[i]];
function v_get(vec,key) = [for(vv=vec) get(key, vv)];
function v_add(vec,v) = [for(vv=vec) vv+v];
function v_sub(vec,v) = [for(vv=vec) vv+v];
function v_avg(v,e=U,start=0) = v_sum(v,e,start) / (len(v));
function v_abs(v, start=0) = [for(i=[start:1:len(v)-1]) abs(v[i])];
function v_sign(v, start=0) = [for(i=[start:1:len(v)-1]) sign(v[i])];
function v_max(v, m, start=0) = [for(i=[start:1:len(v)-1]) max(v[i],m)];
function v_min(v, m, start=0) = [for(i=[start:1:len(v)-1]) min(v[i],m)];
function v_clamp(v, v1, v2, start=0) = [for(i=[start:1:len(v)-1]) clamp(v[i],v1,v2)];

function v_slice(v, start, end) =
let(start_ = start==U?0:start)
let(end_ = end==U?len(v)-1:end)
[for(i=[start_:1:end_]) v[i]];

if($test_mode)
{
    v=[0,1,2];
    assert_v(v_slice(v), [0, 1,2]);
    assert_v(v_slice(v,start=1), [1,2]);
    assert_v(v_slice(v,end=1), [0, 1]);
    assert_v(v_slice(v,start=1,end=1), [1]);
}

// cumulative sum of vector [1,2,3] = [1,3,6]
function v_cumsum(v, start=0, end) = [for(i=[start:1:end==U?len(v)-1:end]) v_sum(v,i)];

// filter/remove a val from a vec
function filter(vec,val=U) = [for(v=vec) if(v!=val) v];

function vec_pair_double_transform_post(vec,t1,t2)=
    flatten(
        [for(v=vec)
            [transform_post(v,t1),transform_post(v,t2)]
        ]);

function vec_pair_double(vec)=flatten([for(v=vec) [v,v] ]);

/** Calculates length of hypotenuse according to pythagoras */
function pythag_hyp(a, b)=sqrt(a*a+b*b);
function pythag_leg(b, c)=sqrt(c*c-b*b);

function v_x(v) = [v[0],0,0];
function v_y(v) = [0,v[1],0];
function v_z(v) = [0,0,v[2]];

function v_xy(v) = [v[0],v[1],0];
function v_xyz(v) = [v[0],v[1],v[2]];
function v_yz(v) = [0,v[1],v[2]];
function v_z(v) = [0,0,v[2]];

//-- Calculate the module/magnitude of a vector
function v_mod(v) = (sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]));

//-- Calculate the cross product of two vectors
function v_cross(u,v) = [
  u[1]*v[2] - v[1]*u[2],
  u[2]*v[0] - v[2]*u[0],
  u[0]*v[1] - v[0]*u[1]
];

//-- Calculate the dot product of two vectors
function v_dot(u,v) = u[0]*v[0]+u[1]*v[1]+u[2]*v[2];

//-- Return the unit vector of a vector
function v_unitv(v) = v/v_mod(v);

//-- Return the angle between two vectores
function v_anglev(u,v) = acos( v_dot(u,v) / (v_mod(u)*v_mod(v)) );

function _orient_angles(zaxis)=
[
    -asin(zaxis.y / norm(zaxis)),
    atan2(zaxis.x, zaxis.z),
    0
];

/*function _orient_angles_(v)=*/
/*[*/
    /*-atan2(sqrt(v.x*v.x+v.y*v.y), v.z),*/
    /*0,*/
    /*-atan2(v.x, v.z)*/
/*];*/

//matrix rotation functions
function _rotate_x_matrix(a)=
[[1,0,0,0],
    [0,cos(a),-sin(a),0],
    [0,sin(a),cos(a),0],
    [0,0,0,1]];

function _rotate_y_matrix(a)=
[[cos(a),0,sin(a),0],
    [0,1,0,0],
    [-sin(a),0,cos(a),0],
    [0,0,0,1]];

function _rotate_z_matrix(a)=
[[cos(a),-sin(a),0,0],
    [sin(a),cos(a),0,0],
    [0,0,1,0],
    [0,0,0,1]];

function _rotate_matrix(a)=_rotate_z_matrix(a.z)*_rotate_y_matrix(a.y)*_rotate_x_matrix(a.x);

//hadamard product (aka "component-wise" product) for vectors
function hadamard(v1,v2) = [v1.x*v2.x, v1.y*v2.y, v1.z*v2.z];

// search in a dictionary (vector w/key-value pairs) and replace the value for a given key
function dict_replace(dict, key, newvalue)=[
        for(kv=dict)
        kv[0] == key ?
            [key, newvalue]
            :
            kv
        ];

function dict_replace_multiple(dict, newvaluesdict)=[
    for(kv_old=dict)
    let(r = search(kv_old[0], newvaluesdict, num_returns_per_match=0, index_col_num=0))
    r==[]?kv_old:newvaluesdict[r[0]]
    ];

function sinh(x) = (1 - pow(e, -2 * x)) / (2 * pow(e, -x));
function cosh(x) = (1 + pow(e, -2 * x)) / (2 * pow(e, -x));
function tanh(x) = sinh(x) / cosh(x);
function cot(x) = 1 / tan(x);

function factorial(n) = n == 0 ? 1 : factorial(n - 1) * n;

if(false)
{
    vec=[ 10, 20, 30, 40 ];
    echo("v_sum=", v_sum(vec,2,1)); // is 20+30=50
    echo("v_sum=", v_sum(vec));
    echo("v_cumsum=", v_cumsum(vec));
}

// FUNCTION: is_String(x)
//   Returns true if x is a string, false otherwise.
function is_string(x) =
	x == U || len(x) == U
		? false // if U, a boolean or a number
		: len(str(x,x)) == len(x)*2; // if an array, this is false

// FUNCTION: is_array(x)
//   Returns true if x is an array, false otherwise.
function is_array(x) = is_string(x) ? false : len(x) != U;

function identity(d)        = d == 0 ? 1 : [for(y=[1:d]) [for(x=[1:d]) x == y ? 1 : 0] ];
function unit_vector(v)     = let(x=v[0], y=v[1], z=v[2]) [x/norm(v), y/norm(v), z/norm(v)];
function skew_symmetric(v)  = let(x=v[0], y=v[1], z=v[2]) [[0, -z, y], [z, 0, -x], [-y, x, 0]];
function tensor_product1(u) = let(x=u[0], y=u[1], z=u[2]) [[x*x, x*y, x*z], [x*y, y*y, y*z], [x*z, y*z, z*z]];
function v_rotate(a, v)
    = is_array(a)
? let(rx=a[0], ry=a[1], rz=a[2])
    [[1, 0, 0],              [0, cos(rx), -sin(rx)], [0, sin(rx), cos(rx)]]
  * [[cos(ry), 0, sin(ry)],  [0, 1, 0],              [-sin(ry), 0, cos(ry)]]
  * [[cos(rz), -sin(rz), 0], [sin(rz), cos(rz), 0],  [0, 0, 1]]
    : let(uv=unit_vector(v))
    cos(a)*identity(3) + sin(a)*skew_symmetric(uv) + (1 - cos(a))*tensor_product1(uv);

 /*echo(rotate(90, X) * [1, 0, 0]);*/
 /*echo(rotate(90, X) * [0, 1, 0]);*/
 /*echo(rotate(90, X) * [0, 0, 1]);*/

function lerp(v0, v1, t) =  (1-t)*v0 + t*v1;

if($test_mode)
{
    assert(lerp(-1, 1, 0) == -1);
    assert(lerp1(-1, 1, .5) == 0);
    assert(lerp1(-1, 1, 1) == 1);
}

if($test_mode)
{
    assert_v(fallback(U,1), 1);
}

function fallback(a, b) = a==U?b:a;

// echo(fallback(U,[U, 1]));
function v_fallback(a,v,i=0) = (a!=U || i > len(v)-1) ? a : v_fallback(v[i],v,i+1);

function zip(a,b,start=0,end) = [for(i=[start:1:fallback(end,len(a)-1)]) [a[i],b[i]] ];
function zip_v(v,start=0,end) = [for(i=[start:1:fallback(end,len(v[0])-1)]) v_i(v,i) ];

if($test_mode)
{
    vec_a = [0,4];
    vec_b = [1,5];
    vec_c = [2,6];
    vec_d = [3,7];
    assert_v(zip(vec_a,vec_b),[[0,1],[4,5]]);
    assert_v(zip_v([vec_a,vec_b]),[[0,1],[4,5]]);
    assert_v(zip_v([vec_a,vec_b,vec_c,vec_d]), [[0,1,2,3],[4,5,6,7]]);
}

function vv_fallback(v,start=0,end) =
let(z = zip_v(v))
[
for(i=[start:1:fallback(end,len(v[0])-1)])
    v_fallback(v=z[i],i=0)
];

if($test_mode)
{
    vec_a=[ 10,  U,   U, 40 ];
    vec_b=[ 10,  U,  30,  U ];
    vec_c=[  U, 20,   U, 40 ];
    assert(v_fallback(a=5, v=vec_a), 5);
    assert_v(vv_fallback(v=[vec_a, vec_b,vec_c]), [10,20,30,40]);
}

function fn_from_r(r) =
                    $fn > 0.0 ?
                    ($fn >= 3 ? $fn : 3)
                    :
                    ceil(max(min(360.0 / $fa, r*2*PI / $fs), 5));

function fn_from_d(d) =
                    $fn > 0.0 ?
                    ($fn >= 3 ? $fn : 3)
                    :
                    ceil(max(min(360.0 / $fa, d*PI / $fs), 5));

module assert_v(val, expected, message)
{
    if(len(val) > 0)
    {
        if(len(val) != len(expected))
        {
            echo("assertion, not equal length of arrays", val, expected);
            assert(val == expected, message);
        }
        for(i=[0:len(val)])
        {
            if(val[i] != expected[i])
            {
                echo("assertion, unexpected value at index", i, val, expected);
                assert(val == expected, message);
            }
        }

    }
    else
    {
        if(val != expected)
        {
            echo("assertion, unexpected value", val, expected);
            assert(val == expected, message);
        }
    }
}

function spread(v0,v1,a) =
a>=2 ?
    [for(i=[0:1/(a-1):1]) lerp(v0,v1,i)]
:
    [lerp(v0,v1,.5)]
;

if($test_mode)
{
    assert_v(spread(-1, 1, 1), [0]);
    assert_v(spread(-1, 1, 2), [-1,1]);
    assert_v(spread(-1, 1, 3), [-1,0,1]);
    // fails because of float inaccuracy
    /*assert_v(spread(-1, 1, 4), [-1,-1/3,1/3,1]);*/
    assert_v(spread(-1, 1, 5), [-1,-.5,0,.5,1]);
}

// the apothem (inradius) is the distance from the center of a regular
// polygon to the flat side (not a vertex)
function apothem(circumradius, fn) = circumradius*cos(180/fn);
function inradius(circumradius, fn) = circumradius*cos(180/fn);;
// the circumradius (outradius) is the distance from the center of a regular
// polygon to a vertex
function circumradius(apothem, fn) = apothem / cos(180/fn);
function outradius(apothem, fn) = apothem / cos(180/fn);
function fn_radius(r, fn) = apothem(r,fn);
function hex_radius(r) = apothem(r, 6);

if($test_mode)
{
    assert_v(apothem(circumradius(5,6)), circumradius(apothem(5),6));
}

function header_col_index(v, col_keys) =
    singlify(
        [for(col_key=col_keys)
        let(result=search([col_key], v[0], index_col_number=0, num_returns_per_match=0))
        result[0][0]
        ]
    );

function geth(S, col_keys, row_index) =
    singlify(
        [for(col_key=col_keys)
            let(col_index = header_col_index(S, col_key))
            S[row_index+1][col_index]
        ]);

if($test_mode)
{
    A = [
    ["Tx", "Ty"],
    [1, 2],
    [3, 4],
    ];

    assert_v(header_col_index(A, "Tx"), 0);
    assert_v(header_col_index(A, "Ty"), 1);

    assert_v(header_col_index(A, ["Ty"]), 1);
    assert_v(header_col_index(A, ["Tx"]), 0);
    assert_v(header_col_index(A, ["Tx", "Ty"]), [0,1]);

    assert_v(geth(A, "Tx", 0), 1);
    assert_v(geth(A, "Tx", 1), 3);
    assert_v(geth(A, "Ty", 0), 2);
    assert_v(geth(A, "Ty", 1), 4);

    assert_v(geth(A, ["Tx","Ty"], 0), [1,2]);
    assert_v(geth(A, ["Tx","Ty"], 1), [3,4]);

}

function v_contains(V, val, start=0, end=U) =
    let(e=end==U?len(V):end)
    V[start]==val ? true :
    start == len(V)-1 ? false :
    v_contains(V,val,start+1,end);

if($test_mode)
{
    assert_v(v_contains([0,1], 0), true);
    assert_v(v_contains([0,1], 1), true);
    assert_v(v_contains([0,1], 2), false);
}

// helper functions to work on headered-arrays (where first entry is column headers)
function reverse_header(V) = concat([V[0]], reverse(v_slice(V,start=1)));
function concat_header(A,B) =concat([A[0]], v_slice(A,start=1),v_slice(B,start=1));

function take3(v) = [v[0],v[1],v[2]];

function vec3(V) =
let(l = len(V))
l == 3 ? V :
l < 3 ? vec3(concat(V,0)) :
take3(V);

if($test_mode)
{
    assert_v(take3([0,1,0,1]), [0,1,0]);

    assert_v(vec3([0,1]), [0,1,0]);
    assert_v(vec3([0]), [0,0,0]);
    assert_v(vec3([1]), [1,0,0]);
    assert_v(vec3([0,0,1]), [0,0,1]);
    assert_v(vec3([0,0,1,0]), [0,0,1]);
}


дезоксирибоза

дезоксирибоза


change to nema connector from pc power supply

include <../util/slots.scad>
include <../util/rounded_square.scad>
$fn=20;
power_supply_length=215;
power_supply_width=115;
power_supply_height=50;

overall_length=300;
overall_height=70;
stepper_power_width=30;

part_separation=5;
material_thickness=3.04;
corner_radius=10;
hole_size=3.2;

base_plate_length=150 + 70;
base_plate_width=power_supply_width + 2*corner_radius+material_thickness;
module m4_holes(){
  hole_radius = 4.2/2;
  x_offset = 150/2;
  y_offset = 50/2;
  translate([x_offset, y_offset]){
    circle(hole_radius);
  }
  translate([-x_offset, y_offset]){
    circle(hole_radius);
  }
  translate([x_offset, -y_offset]){
    circle(hole_radius);
  }
  translate([-x_offset, -y_offset]){
    circle(hole_radius);
  }

}
module power_supply(){
  difference(){
    %square([215, 115], center=true);
    m4_holes();
  }
}
module power_supply_side_holes(){
  hole_diameter = 4.2;
  x_offset = 150/2;
  y_offset = 13;
  translate([x_offset, y_offset]){
    circle(d=hole_diameter);
  }
  translate([-x_offset, y_offset]){
    circle(d=hole_diameter);
  }
}
module power_supply_side(){
  difference(){
    %square([215, 50], center=true);
    power_supply_side_holes();
  }
}

module nema_with_switch(){
  square([27, 42.3], center=true);
}

module nema(){
  hole_diameter=3.2;
  square([27, 19.1], center=true);
  %square([49.5,22.5], center=true);
  translate([-20, 0]) circle(d=hole_diameter);
  translate([20, 0]) circle(d=hole_diameter);

}

module vent_legs(count=3, radius=10){
  for(x=[1:count]){
    translate([x*overall_length/(count + 1), 0]){
      hull(){
          translate([-1.5*radius, 0])circle(radius);
          translate([1.5*radius, 0]) circle(radius);
      }
    }
  }
}

module power_switch(){
  circle(12);
  %square([30, 37], center=true);
}

module stepper_power(){
  square([stepper_power_width, 110]);
}

module stepper_power_side_dc(){
  %square([stepper_power_width, 48]);
  translate([stepper_power_width/2, 9]) circle(d=10);
}

module stepper_power_side_ac(){
  %square([stepper_power_width, 48]);
  translate([stepper_power_width/2, 15.5]) square([15,20], center=true);
}

module ac_side(){
  difference(){
    side();
    translate([material_thickness, material_thickness]) stepper_power_side_ac();
    translate([material_thickness + stepper_power_width + 25, power_supply_height/2 + 10]) nema();
    translate([material_thickness + stepper_power_width + 10, 9]) circle(d=7.5);
  }
}

module dc_side(){
  difference(){
    side();
    translate([material_thickness, material_thickness]) stepper_power_side_dc();
    translate([material_thickness + stepper_power_width + 25, 2*power_supply_height/3]) circle(d=19.7);
    translate([material_thickness + stepper_power_width + 5, 17]) circle(d=7.5);
  }
}

module screw_terminal(n=2){
  terminal_height=18.6;
  divider_height=21.8;

  hole_locations = [[ 2, 28.7], [3, 38.2], [4, 47.7], [5, 57.2], [6, 66.7], [7, 76.2], [8, 85.7]];
  lengths =        [[2, 36.2], [3, 45.7], [4, 55.2], [5, 64.7], [6, 74.2], [7, 83.7], [8, 93.2]];
  hole_distance = lookup(n, hole_locations);
  length =        lookup(n, lengths);
  // translate([length/2, divider_height/2]){
      %square([length, divider_height], center=true);
      translate([-hole_distance/2, 4]) circle(d=4);
      translate([-hole_distance/2, -4]) circle(d=4);
      translate([hole_distance/2, 4]) circle(d=4);
      translate([hole_distance/2, -4]) circle(d=4);
  // }
}

module side(){
  leg_holes = floor(overall_length/5);
  difference(){
    square([overall_length, overall_height]);
    make_slots(overall_length - power_supply_length, 5, material_thickness, true);
    translate([0, overall_height]) vent_legs();
    translate([material_thickness, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
    translate([material_thickness, power_supply_height + 1.5]) make_slots(overall_length - power_supply_length - material_thickness, 5, material_thickness, true);
    translate([overall_length - power_supply_length, 0]){
      translate([power_supply_length/2, power_supply_height/2]) rotate(180) power_supply_side();
    }
  }
}

module front(){
  translate([0, material_thickness]) square([power_supply_width, overall_height - material_thickness]);
  translate([power_supply_width + material_thickness, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
  translate([0, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
  make_slots(power_supply_width, 5, material_thickness, true);
}

module top(){
  difference(){
    union(){
      square([overall_length - power_supply_length, power_supply_width]);
      translate([0, power_supply_width]) make_slots(overall_length - power_supply_length, 5, material_thickness, true);
      translate([0, -material_thickness]) make_slots(overall_length - power_supply_length, 5, material_thickness, true);
    }
    translate([material_thickness, 0]) rotate(90) make_slots(power_supply_width, 5, material_thickness, true);
    translate([(overall_length - power_supply_length + 13)/2, 2.4*power_supply_width/5]) power_switch();
    translate([(overall_length - power_supply_length + 30)/2, 4*power_supply_width/5]) screw_terminal(2);
    % translate([material_thickness, 0]) stepper_power();
  }
}

module bottom(){
  bottom_length = overall_length - power_supply_length - material_thickness;
  square([bottom_length, power_supply_width]);
  translate([0, power_supply_width]) make_slots(bottom_length, 5, material_thickness, true);
  translate([0, -material_thickness]) make_slots(bottom_length, 5, material_thickness, true);
}

ac_side();
translate([0, -part_separation]) mirror([0,1,0]) dc_side();
translate([0, -(overall_height + power_supply_width + 2* part_separation)]) top();
translate([-power_supply_width - part_separation, 0]) front();
translate([material_thickness, overall_height + part_separation]) bottom();

include <../util/slots.scad>
include <../util/rounded_square.scad>
$fn=20;
power_supply_length=215;
power_supply_width=115;
power_supply_height=50;

overall_length=300;
overall_height=70;
stepper_power_width=30;

part_separation=5;
material_thickness=3.04;
corner_radius=10;
hole_size=3.2;

base_plate_length=150 + 70;
base_plate_width=power_supply_width + 2*corner_radius+material_thickness;
module m4_holes(){
  hole_radius = 4.2/2;
  x_offset = 150/2;
  y_offset = 50/2;
  translate([x_offset, y_offset]){
    circle(hole_radius);
  }
  translate([-x_offset, y_offset]){
    circle(hole_radius);
  }
  translate([x_offset, -y_offset]){
    circle(hole_radius);
  }
  translate([-x_offset, -y_offset]){
    circle(hole_radius);
  }

}
module power_supply(){
  difference(){
    %square([215, 115], center=true);
    m4_holes();
  }
}
module power_supply_side_holes(){
  hole_diameter = 4.2;
  x_offset = 150/2;
  y_offset = 13;
  translate([x_offset, y_offset]){
    circle(d=hole_diameter);
  }
  translate([-x_offset, y_offset]){
    circle(d=hole_diameter);
  }
}
module power_supply_side(){
  difference(){
    %square([215, 50], center=true);
    power_supply_side_holes();
  }
}

module nema(){
  square([27, 42.3], center=true);
}

module vent_legs(count=3, radius=10){
  for(x=[1:count]){
    translate([x*overall_length/(count + 1), 0]){
      hull(){
          translate([-1.5*radius, 0])circle(radius);
          translate([1.5*radius, 0]) circle(radius);
      }
    }
  }
}

module power_switch(){
  circle(12);
  %square([30, 37], center=true);
}

module stepper_power(){
  square([stepper_power_width, 110]);
}

module stepper_power_side_dc(){
  %square([stepper_power_width, 48]);
  translate([stepper_power_width/2, 9]) circle(d=10);
}

module stepper_power_side_ac(){
  %square([stepper_power_width, 48]);
  translate([stepper_power_width/2, 15.5]) square([15,20], center=true);
}

module ac_side(){
  difference(){
    side();
    translate([material_thickness, material_thickness]) stepper_power_side_ac();
    translate([material_thickness + stepper_power_width + 25, power_supply_height/2 + 10]) rotate(90) nema();
    translate([material_thickness + stepper_power_width + 10, 9]) circle(d=7.5);
  }
}

module dc_side(){
  difference(){
    side();
    translate([material_thickness, material_thickness]) stepper_power_side_dc();
    translate([material_thickness + stepper_power_width + 25, 2*power_supply_height/3]) circle(d=19.7);
    translate([material_thickness + stepper_power_width + 5, 17]) circle(d=7.5);
  }
}

module screw_terminal(n=2){
  terminal_height=18.6;
  divider_height=21.8;

  hole_locations = [[ 2, 28.7], [3, 38.2], [4, 47.7], [5, 57.2], [6, 66.7], [7, 76.2], [8, 85.7]];
  lengths =        [[2, 36.2], [3, 45.7], [4, 55.2], [5, 64.7], [6, 74.2], [7, 83.7], [8, 93.2]];
  hole_distance = lookup(n, hole_locations);
  length =        lookup(n, lengths);
  // translate([length/2, divider_height/2]){
      %square([length, divider_height], center=true);
      translate([-hole_distance/2, 4]) circle(d=4);
      translate([-hole_distance/2, -4]) circle(d=4);
      translate([hole_distance/2, 4]) circle(d=4);
      translate([hole_distance/2, -4]) circle(d=4);
  // }
}

module side(){
  leg_holes = floor(overall_length/5);
  difference(){
    square([overall_length, overall_height]);
    make_slots(overall_length - power_supply_length, 5, material_thickness, true);
    translate([0, overall_height]) vent_legs();
    translate([material_thickness, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
    translate([material_thickness, power_supply_height + 1.5]) make_slots(overall_length - power_supply_length - material_thickness, 5, material_thickness, true);
    translate([overall_length - power_supply_length, 0]){
      translate([power_supply_length/2, power_supply_height/2]) rotate(180) power_supply_side();
    }
  }
}

module front(){
  translate([0, material_thickness]) square([power_supply_width, overall_height - material_thickness]);
  translate([power_supply_width + material_thickness, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
  translate([0, 0]) rotate(90) make_slots(overall_height, 5, material_thickness, true);
  make_slots(power_supply_width, 5, material_thickness, true);
}

module top(){
  difference(){
    union(){
      square([overall_length - power_supply_length, power_supply_width]);
      translate([0, power_supply_width]) make_slots(overall_length - power_supply_length, 5, material_thickness, true);
      translate([0, -material_thickness]) make_slots(overall_length - power_supply_length, 5, material_thickness, true);
    }
    translate([material_thickness, 0]) rotate(90) make_slots(power_supply_width, 5, material_thickness, true);
    translate([(overall_length - power_supply_length + 13)/2, 2.4*power_supply_width/5]) power_switch();
    translate([(overall_length - power_supply_length + 30)/2, 4*power_supply_width/5]) screw_terminal(2);
    % translate([material_thickness, 0]) stepper_power();
  }
}

module bottom(){
  bottom_length = overall_length - power_supply_length - material_thickness;
  square([bottom_length, power_supply_width]);
  translate([0, power_supply_width]) make_slots(bottom_length, 5, material_thickness, true);
  translate([0, -material_thickness]) make_slots(bottom_length, 5, material_thickness, true);
}

ac_side();
translate([0, -part_separation]) mirror([0,1,0]) dc_side();
translate([0, -(overall_height + power_supply_width + 2* part_separation)]) top();
translate([-power_supply_width - part_separation, 0]) front();
translate([material_thickness, overall_height + part_separation]) bottom();


bearing/data: add 683 and M83

bearing/data: add 683 and M83


Added cadcorn-camera.scad

Added cadcorn-camera.scad

// Cadcorn Camera, a 3D-printable unicorn webcam holder
// ©2015 Paul Houghton, paul.houghton@futurice.com, CC-attribution-sharealike license, http://creativecommons.org/licenses/by-sa/4.0/

use <cadcorn.scad>;
use <creative-HD-1080p-webcam.scad>;

low_poly = 8;
high_poly = 128;

poly=high_poly;
scale=1.8;

cut_size=300;

front();
back();

module camera() {
    rotate([25,0,0]) {
    minkowski() {
        creative_hd();
        sphere($fn=8, r=1);
    }
    lens_space();
}
}

module corn() {
    translate([-50,0,50]) scale([scale,scale,scale])
        cadcorn(poly=poly);
}

module front() {
    difference() {
        corn();
        union() {
            cut();
            camera();
        }
    }
}

module back() {
    difference() {
        corn();
        union() {
            uncut();
            camera();
        }
    }
}

module cut() {
    translate([cut_size/2,0,0]) cube([cut_size,cut_size,cut_size], center=true);
}

module uncut() {
    difference() {
       translate([cut_size/2,0,0]) cube([2*cut_size,cut_size,cut_size], center=true);
        cut();
    }
}

error: pathspec 'vor-3d-models/cadcorn-camera.scad' did not match any file(s) known to git