added new version of GearClock Gears3

added new version of GearClock Gears3

include <Parametric_Involute__Bevel_and_Spur_Gears/parametric_involute_gear_v5.0.scad>

$fn=50;
mm = 1;
inch = 25.4 * mm;

ACRYLIC_THICKNESS = 5.3 * mm;
ACRYLIC_TOL = .5 * mm;
PITCH = 360 * mm;
PRESSURE_ANGLE = 28;

RIM_THICKNESS = 2 * mm;
EXTRA_RIM_R = 3 * mm;

module hex(r, h){
  rotate(a=30, v=[0, 0, 1])
  linear_extrude(height=h)
    polygon(points=[[r,0],
		    [r * cos(60),r * sin(60)],
		    [r * cos(120),r * sin(120)],
		    [r * cos(180),r * sin(180)],
		    [r * cos(240),r * sin(240)],
		    [r * cos(300),r * sin(300)],
		    ],paths=[ [0, 1, 2, 3, 4, 5] ]);
}

module stepper_gear(N_TEETH=6){
  PITCH_R = N_TEETH * PITCH / 360.;
  PITCH_D = 2 * PITCH_R;
  PITCH_DIAMETRIAL = N_TEETH / PITCH_D;
  // Addendum: Radial distance from pitch circle to outside circle.
  ADDENDUM = 1 / PITCH_DIAMETRIAL;

  thickness = ACRYLIC_THICKNESS + 4.7 * mm;// + RIM_THICKNESS;
  //Outer Circle
  OUTER_RADIUS = PITCH_R + ADDENDUM;
  translate([0, 0, RIM_THICKNESS])
  difference(){
    union(){
      rotate(a=360/6/2., v=[0, 0, 1])
	intersection(){
	gear(number_of_teeth=6,
	     circular_pitch = PITCH,
	     gear_thickness = thickness,
	     rim_thickness = thickness,
	     hub_thickness = thickness,
	     bore_diameter=0. * mm,
	     circles=4,
	     pressure_angle=28,
	     backlash=1
	     );
	cylinder(h=thickness, r=OUTER_RADIUS - .5*mm);
      }
      translate([0, 0, -RIM_THICKNESS])cylinder(r=OUTER_RADIUS, h=RIM_THICKNESS);
      // translate([0, 0, 6.5*mm])cylinder(r=OUTER_RADIUS, h=RIM_THICKNESS);
      translate([0, 0, -3 * RIM_THICKNESS])cylinder(r=OUTER_RADIUS + EXTRA_RIM_R, h=2 * RIM_THICKNESS);
    }
    translate([0, 0, -1])cylinder(r=3 * mm/2 + .05 * mm, h=ACRYLIC_THICKNESS + ACRYLIC_TOL + 2 + 100);
  }
}

module outer_gear(N_TEETH=66, lash=0){
  PITCH_R = N_TEETH * PITCH / 360.;
  PITCH_D = 2 * PITCH_R;
  PITCH_DIAMETRIAL = N_TEETH / PITCH_D;
  // Addendum: Radial distance from pitch circle to outside circle.
  ADDENDUM = 1 / PITCH_DIAMETRIAL;

  //Outer Circle
  OUTER_RADIUS = PITCH_R + ADDENDUM;
  OUTER_DIAMETER = 2 * OUTER_RADIUS;

  MARGIN = 1 * inch;
  intersection(){
    scale([.995, .995, 1])
      cylinder(h=ACRYLIC_THICKNESS, r=70*mm);
difference() {
    cylinder(r=OUTER_RADIUS  +  MARGIN, h=ACRYLIC_THICKNESS + ACRYLIC_TOL);
    //cylinder(r=OUTER_RADIUS + 3, h=ACRYLIC_THICKNESS + ACRYLIC_TOL);
    translate([0, 0, -1])
      scale([1.005, 1.005, 1])gear(number_of_teeth=N_TEETH,
	   circular_pitch = PITCH,
	   gear_thickness = ACRYLIC_THICKNESS + ACRYLIC_TOL + 2,
	   rim_thickness = ACRYLIC_THICKNESS + ACRYLIC_TOL + 2,
	   hub_thickness = ACRYLIC_THICKNESS + ACRYLIC_TOL + 2,
	   bore_diameter=0. * mm,
	   circles=0,
	   pressure_angle=28,
	   backlash=0 // play with this
	   );
    cylinder(h=ACRYLIC_THICKNESS + ACRYLIC_TOL, r=OUTER_RADIUS-3); // trim teeth
  }
  }
  //for(i=[0:12])rotate(a=i*360/12, v=[0, 0, 1])translate([69*mm,-.8*mm,0])cube([3*mm, 1.6*mm, ACRYLIC_THICKNESS]);
  for(i=[0:12])rotate(a=i*360/12, v=[0, 0, 1])translate([69*mm,0*mm,0])
		 difference(){
      cylinder(r=3*mm, h = ACRYLIC_THICKNESS);
      translate([-6*mm,-3*mm, -1])cube([6*mm, 6*mm, ACRYLIC_THICKNESS + 2]);
      translate([-0*mm,-0*mm, -1])cube([6*mm, 6*mm, ACRYLIC_THICKNESS + 2]);
    }
}

module anti_lash_gear(minute, N_TEETH=30, h=ACRYLIC_THICKNESS, lash=0){
  ACRYLIC_THICKNESS = h;
  PITCH_R = N_TEETH * PITCH / 360.;
  PITCH_D = 2 * PITCH_R;
  PITCH_DIAMETRIAL = N_TEETH / PITCH_D;
  // Addendum: Radial distance from pitch circle to outside circle.
  ADDENDUM = 1 / PITCH_DIAMETRIAL;

  //Outer Circle
  OUTER_RADIUS = PITCH_R + ADDENDUM;
  OUTER_DIAMETER = 2 * OUTER_RADIUS;
  rad = 10 * mm;
  d1 = (rad + .0) * [1,0,0];
  d2 = (rad + .0) * [sin(30), cos(30), 0];
  translate([0, 0, -2*ACRYLIC_THICKNESS + ACRYLIC_TOL])union(){
    translate([0, 36  * mm, 0])
    intersection(){
      difference(){
	intersection(){
	  cylinder(r1=40, r2=26.5, h=ACRYLIC_THICKNESS); // taper the teeth
	  difference(){
	    gear(number_of_teeth=N_TEETH,
		 circular_pitch = PITCH,
		 gear_thickness = ACRYLIC_THICKNESS,
		 rim_thickness = ACRYLIC_THICKNESS, //   - ACRYLIC_TOL,
		 hub_thickness = ACRYLIC_THICKNESS, //  - ACRYLIC_TOL,
		 bore_diameter=0. * mm,
		 circles=0,
		 pressure_angle=28,
		 backlash=lash // play with this
		 );
	    translate([0, 0, -1])scale([.95, .95, 1.5])gear(number_of_teeth=N_TEETH,
		 circular_pitch = PITCH,
		 gear_thickness = ACRYLIC_THICKNESS,
		 rim_thickness = ACRYLIC_THICKNESS, //   - ACRYLIC_TOL,
		 hub_thickness = ACRYLIC_THICKNESS, //  - ACRYLIC_TOL,
		 bore_diameter=0. * mm,
		 circles=0,
		 pressure_angle=28,
		 backlash=lash // play with this
		 );
	  }
	}
      translate([0, 0, -1])cylinder(r=6 * mm/2, h=ACRYLIC_THICKNESS + ACRYLIC_TOL + 2 + 100);

      // hollow out
      translate([0, 0, -1])cylinder(r=N_TEETH - 5, h=ACRYLIC_THICKNESS + ACRYLIC_TOL + 2 + 100);
    }
      translate([0, 0, -1])cylinder(r=OUTER_RADIUS - .5, h=100);
    }
    // add spokes
    difference(){
      union(){
	for(i=[0:4]){
	  // translate([0, 36 * mm, 0])rotate(a=360/5 * i + 3, v=[0, 0, 1])translate([-1 *mm, -27 * mm, 0])cube([2 * mm, 30 * mm, ACRYLIC_THICKNESS]);  // streight spokes
	  translate([0, 36 * mm, 0])rotate(a=360/5 * i + 3, v=[0, 0, 1])translate([0 *mm, 15 * mm, 0])difference(){
 	    cylinder(r=11 * mm, h = ACRYLIC_THICKNESS/2);
	    translate([0, 0, -1])cylinder(r=10.2 * mm, h = ACRYLIC_THICKNESS+2);
	    // translate([0, -12, -1])cube([12, 24, 2 * ACRYLIC_THICKNESS]);
	  }
	}
      }
      translate([0, 36*mm, -1])cylinder(r = 4*mm, h=ACRYLIC_THICKNESS+2);
    }
    union(){
    difference(){ // outer rim support
      translate([0, 36*mm, 0])cylinder(r = 1*inch, h=ACRYLIC_THICKNESS + 1.25);
      translate([0, 36*mm, -1])cylinder(r = inch - 1*mm, h=ACRYLIC_THICKNESS + 10);
    }
    difference(){ // inner hub support
      translate([0, 36*mm, 0])cylinder(r = 4.5*mm, h=ACRYLIC_THICKNESS + 1);
      translate([0, 36*mm, -2])cylinder(r = 3*mm, h=ACRYLIC_THICKNESS + 10);
     }
    /*
    translate([0, 36*mm, 0])
      intersection(){
      cylinder(r1=40, r2=26.5, h=ACRYLIC_THICKNESS); // taper the teeth
      difference(){ // outer rim tooth support
	cylinder(r=27, h=ACRYLIC_THICKNESS);
	translate([0, 0, -1])cylinder(r=1*inch, h=ACRYLIC_THICKNESS+2);
      }
    }
    */
    translate([0, 36*mm, 0])
      intersection(){
      cylinder(r1=40, r2=26.5, h=ACRYLIC_THICKNESS); // taper the teeth
      for(i=[0:N_TEETH]){
	rotate(v=[0, 0, 1],a=i * 360./N_TEETH + 180./N_TEETH)translate([25*mm, -.5*mm, 0])cube([1.5*mm, 1*mm, ACRYLIC_THICKNESS]);
      }
    }
  }

  }
}

module anti_lash_gear_top(minute, N_TEETH=30, h=ACRYLIC_THICKNESS/2, lash=0){
  ACRYLIC_THICKNESS = h;
  PITCH_R = N_TEETH * PITCH / 360.;
  PITCH_D = 2 * PITCH_R;
  PITCH_DIAMETRIAL = N_TEETH / PITCH_D;
  // Addendum: Radial distance from pitch circle to outside circle.
  ADDENDUM = 1 / PITCH_DIAMETRIAL;

  //Outer Circle
  OUTER_RADIUS = PITCH_R + ADDENDUM;
  OUTER_DIAMETER = 2 * OUTER_RADIUS;
  rad = 10 * mm;
  d1 = (rad + .0) * [1,0,0];
  d2 = (rad + .0) * [sin(30), cos(30), 0];
  translate([0, 36  * mm, 0])
    // rotate(a=360/30/4 - 66./30 * minute/60 * 360 + minute/60.*720, v=[0, 0,1])
    // rotate(-4, v=[0, 0,1])
    difference(){
    intersection(){
      cylinder(r1=40, r2=26.5, h=ACRYLIC_THICKNESS); // taper the teeth
      gear(number_of_teeth=N_TEETH,
	   circular_pitch = PITCH,
	   gear_thickness = ACRYLIC_THICKNESS,
	   rim_thickness = ACRYLIC_THICKNESS, //   - ACRYLIC_TOL,
	   hub_thickness = ACRYLIC_THICKNESS, //  - ACRYLIC_TOL,
	   bore_diameter=0. * mm,
	   circles=0,
	   pressure_angle=28,
	   backlash=lash
	   );
      translate([0, 0, -1])cylinder(r=OUTER_RADIUS - .5, h=100);
    }
    translate([0, 0, -1])cylinder(r=6 * mm/2, h=ACRYLIC_THICKNESS + ACRYLIC_TOL + 2 + 100);
    // hollow out
    translate([0, 0, -1])cylinder(r=N_TEETH - 5, h=ACRYLIC_THICKNESS + ACRYLIC_TOL + 2 + 100);

  }
  // add tensioners
  translate([0, 36*mm, 0])
  for(i=[0:4]){
    rotate(a=360/5 * i + 3, v=[0, 0, 1])translate([0, 16, 0])difference(){
      cylinder(r=6 * mm + 4 * .4*mm, h=ACRYLIC_THICKNESS);
      translate([0, 0, -1])cylinder(r=6 * mm, h=ACRYLIC_THICKNESS + 2);
    // scale([1, 1, .3])translate([0, 0, ])rotate(a=360/5 * i, v=[0, 0, 1])translate([0, 18, -1])sphere(r=11 * mm);
    }
  }
  // add in rim strip to support hour hand
  translate([0, 0, 0])
    union(){
    difference(){ // outer rim support
      translate([0, 36*mm, 0])cylinder(r = 1*inch, h=ACRYLIC_THICKNESS + 1.25);
      translate([0, 36*mm, -1])cylinder(r = 7 * inch/8, h=ACRYLIC_THICKNESS + 10);
    }
    difference(){ // inner hub support
      translate([0, 36*mm, 0])cylinder(r = 9*mm, h=ACRYLIC_THICKNESS + 1);
      translate([0, 36*mm, -2])cylinder(r = 3*mm, h=ACRYLIC_THICKNESS + 10);
     }
  }
}

module inner_gear(minute, N_TEETH=30, h=ACRYLIC_THICKNESS){
  ACRYLIC_THICKNESS = h;
  PITCH_R = N_TEETH * PITCH / 360.;
  PITCH_D = 2 * PITCH_R;
  PITCH_DIAMETRIAL = N_TEETH / PITCH_D;
  // Addendum: Radial distance from pitch circle to outside circle.
  ADDENDUM = 1 / PITCH_DIAMETRIAL;

  //Outer Circle
  OUTER_RADIUS = PITCH_R + ADDENDUM;
  OUTER_DIAMETER = 2 * OUTER_RADIUS;
  rad = 10 * mm;
  d1 = (rad + .0) * [1,0,0];
  d2 = (rad + .0) * [sin(30), cos(30), 0];
  translate([0, 36  * mm, 0])
    difference(){
    intersection(){
      cylinder(r1=40, r2=26.5, h=ACRYLIC_THICKNESS); // taper the teeth
      gear(number_of_teeth=N_TEETH,
	   circular_pitch = PITCH,
	   gear_thickness = ACRYLIC_THICKNESS,
	   rim_thickness = ACRYLIC_THICKNESS, //   - ACRYLIC_TOL,
	   hub_thickness = ACRYLIC_THICKNESS, //  - ACRYLIC_TOL,
	   bore_diameter=0. * mm,
	   circles=0,
	   pressure_angle=28
	   );
    }
    translate([0, 0, -1])cylinder(r=6 * mm/2, h=ACRYLIC_THICKNESS + ACRYLIC_TOL + 2 + 100);

    // lighten the load
    for(i=[0:4]){
      rotate(a=360/5 * i, v=[0, 0, 1])translate([0, 16, -1])cylinder(r=6 * mm, h=ACRYLIC_THICKNESS + ACRYLIC_TOL + 2 + 100);
      // scale([1, 1, .3])translate([0, 0, ])rotate(a=360/5 * i, v=[0, 0, 1])translate([0, 18, -1])sphere(r=11 * mm);
    }
  }
  // add in rim strip to support hour hand
  translate([0, 0, 1])
    union(){
    difference(){ // outer rim support
      translate([0, 36*mm, 0])cylinder(r = 1*inch, h=ACRYLIC_THICKNESS);
      translate([0, 36*mm, -1])cylinder(r = 7 * inch/8, h=ACRYLIC_THICKNESS+2);
    }
    difference(){ // inner hub support
      translate([0, 36*mm, 0])cylinder(r = 8*mm, h=ACRYLIC_THICKNESS);
      translate([0, 36*mm, -1])cylinder(r = 3*mm, h=ACRYLIC_THICKNESS+2);
    }
  }
}

module minute_hand(r=65*mm, w=21.5*mm, h=RIM_THICKNESS - 0.5*mm,filagree=false){
//linear_extrude(height = 2, center=true)
//polygon(points=[[-5*mm/2, 0], [0, 65*mm], [5*mm/2, 0]]);
  difference(){
    union(){
      stepper_gear(N_TEETH=6);
      translate([0, 2*mm, -2*RIM_THICKNESS])
	linear_extrude(height=h)

        if (filagree){

	  translate([0,8.2,0])scale([1.0,1,1])import("filagreeminute.dxf");

        }

        else
            polygon(points=[[-w/2, 0], [0, r], [w/2, 0]]);
    }
    translate([0, 0, 0])cylinder(r=2.5 * mm, h=ACRYLIC_THICKNESS + ACRYLIC_TOL + 2 + 100);
    // translate([0, r - 15 * mm, -50])cylinder(h=100, r=3.00/2*mm); //hole for hall effect magnet
  }
}

module hour_hand(r=50*mm, w=21.5*mm, h=1.5*mm, filagree = false){
  difference(){
    union(){
      translate([0, RIM_THICKNESS, -RIM_THICKNESS])
	linear_extrude(height=h)

        if (filagree){

	  translate([0,8.2,0])scale([1.,1.025,1])import("filagreehour.dxf");
        }else{
	  polygon(points=[[-w/2, 0], [0, r], [w/2, 0]]);
	}
      // translate([0, 36, -RIM_THICKNESS])cylinder(r=5.5 * mm/2, h=ACRYLIC_THICKNESS + RIM_THICKNESS + .5*mm);
      translate([0, 36, -RIM_THICKNESS])cylinder(r=5.5 * mm/2, h=ACRYLIC_THICKNESS + RIM_THICKNESS + 1);
      translate([0, 36, ACRYLIC_THICKNESS + .75*mm])scale([1, .8, 1])cylinder(r1=7/2. * mm, r2=3.2*mm, h=1.5*mm); // clip
      translate([0, 0, -RIM_THICKNESS])cylinder(r=11, h=h);
    }
    translate([0, 0, -RIM_THICKNESS - 1])cylinder(r=8.25, h=2*h);
    translate([-.5 * mm, 36 * mm-5 * mm, 2])cube([1 * mm, 10 * mm, 10 * mm]); // slot
    translate([0 * mm, 36 * mm * mm, 0])cylinder(r=3.12/2 * mm, h=30.15 * mm);// hall effect magnet slot
  }
}

HOUR = 9;
MINUTE = $t * 60;
//MINUTE = HOUR * 60 + 15;
// translate([0,0, 2])rotate(v=[0, 1, 0], a=180)
// translate([0, -0, -RIM_THICKNESS])rotate(a=MINUTE/720 * 360, v=[0, 0, 1])color([.1, 1, 0])inner_gear(MINUTE);
// color([.1, .1, 1])outer_gear();
// translate([0, 0, -1.5*mm])rotate(a=MINUTE/720 * 360, v=[0, 0, 1])color([1, 0, 0])rotate(a=0, v=[0, 0, 1])hour_hand(w=11,filagree=true);
translate([0, 0, -2*RIM_THICKNESS])translate([0, 0, 0])rotate(a=MINUTE/60 * 360, v=[0, 0, 1])minute_hand(w=12,filagree=true);

lash = 0;
//      anti_lash_gear(lash=lash);
// color([1, 0, 1])translate([0, -0, +ACRYLIC_THICKNESS/2 + ACRYLIC_TOL])anti_lash_gear_top(lash=lash, H=ACRYLIC_THICKNESS);
// translate([130, 0, 0])cylinder(r=50*mm, h=1*mm); // for scale

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


x/ends: use material system

x/ends: use material system

use <thing_libutils/misc.scad>
use <thing_libutils/bearing.scad>
use <thing_libutils/screws.scad>
use <thing_libutils/timing-belts.scad>
use <thing_libutils/bearing-linear.scad>

include <thing_libutils/bearing_data.scad>
include <thing_libutils/pulley.scad>
include <thing_libutils/materials.scad>

include <x-end.h>

module xaxis_end_body(part, with_motor, beltpath_index=0, nut_top=false, with_xrod_adjustment=true)
{
    nut_h = zaxis_nut[4];
    bearing_sizey = zaxis_bearing_OD + 5*mm;

    xaxis_end_xrod_offset_z = xaxis_rod_l/2 - (main_width/2 + zmotor_mount_rod_offset_x);
    xaxis_rod_d_support = xaxis_rod_d+5*mm;
    xaxis_rod_l_support = xaxis_end_xrod_offset_z + 8*mm + (with_xrod_adjustment?8*mm:0);

    if(part==undef)
    {
        difference()
        {
            xaxis_end_body(part="pos", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
            xaxis_end_body(part="neg", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
        }
        %xaxis_end_body(part="vit", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
    }
    else if(part=="pos")
    material(Mat_Plastic)
    {
        if(with_motor)
        {
            screw_dist = lookup(NemaDistanceBetweenMountingHoles, xaxis_motor);
            for(x=[-1,1])
            for(z=[-1,1])
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                translate([x*screw_dist/2, 0, z*screw_dist/2])
                cylindera(d=lookup(ThreadSize,xaxis_motor_thread)+4*mm, h=motor_mount_wall_thick, orient=Y, align=[0,-1,0], rounding_radius=2);
            }
        }

        // nut mount
        mirror([0,0,nut_top?1:0])
        translate([zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2])
        {
            // main nut support
            rcylindera(h=zaxis_nut[4], d=zaxis_nut[0]+5*mm, align=Z);

            // nut screw holes support
            rotate(Z*90)
            for(x=[-1,1])
            translate([x*zaxis_nut[5], 0, 0])
            rcylindera(h=zaxis_nut[4], d=lookup(ThreadSize, zaxis_nut[6])+5*mm, align=Z);

            // lead screw
            // ensure some support for the leadscrew cutout all the way to the top
            /*rcylindera(h=xaxis_end_wz, d=zaxis_nut[2]*2, align=Z);*/
        }

        // x axis rod holders
        for(z=[-1,1])
        translate([0,0,z*(xaxis_rod_distance/2)])
        rcylindera(h=xaxis_end_width(with_motor), d=xaxis_rod_d_support, orient=X, align=X);

        // endstops mount support
        if(xaxis_endstop_type == "SWITCH")
        {
            translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
            {
                rcubea(xaxis_endstop_size_switch, align=-XAXIS-ZAXIS);
            }
        }
        else if(xaxis_endstop_type == "SN04")
        {
            translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
            {
                translate(xaxis_endstop_offset_SN04)
                rcubea(xaxis_endstop_size_SN04, align=-XAXIS-ZAXIS);
            }
        }

        // belt idler screw cut support
        for(z=[-1,1])
        for(y=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0,y*-xaxis_beltpath_width/2,0])
            cylindera(orient=Y, d=15*mm, h=7*mm, align=-y*Y);
        }
    }
    else if(part=="neg")
    {
        for(z=[-1,1])
        translate([0,0*mm,z*(xaxis_rod_distance/2)])
        {
            xoff = - xaxis_end_xrod_offset_z -(with_xrod_adjustment?6:0)*mm;
            translate([xoff,0,0])
            cylindera(h=abs(xoff)+xaxis_end_width(with_motor)+1,d=xaxis_rod_d+.5*mm, orient=X, align=X);

            if(with_xrod_adjustment)
            {
                translate(X*5*mm)
                nut_trap_cut(nut=NutHexM4, trap_axis=Y, orient=-X, align=X);

                translate(X*-7*mm)
                cylindera(d=10, h=10, orient=X);
            }
        }
    }
    else if(part=="vit")
    {
    }
}

module xaxis_end(part, with_motor=false, stop_x_rods=true, beltpath_index=0, show_motor=false, nut_top=false, show_nut=false, show_rods=false, show_bearings=false, with_xrod_adjustment=false)
{
    nut_h = zaxis_nut[4];
    extrasize = with_motor?0*mm:0*mm;
    extrasize_align = 1;

    if(part==undef)
    {
        difference()
        {
            xaxis_end(part="pos", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
            xaxis_end(part="neg", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
        }
        %xaxis_end(part="vit", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
    }
    else if(part=="pos")
    {
        // projection against z, ensure easy print
        material(Mat_Plastic)
        proj_extrude_axis(axis=Z, offset=xaxis_end_wz/2)
        {
            xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

            // z smooth bearing mounts support
            translate(-xaxis_zaxis_distance_y*Y)
            translate(-Z*(xaxis_end_wz/2))
            {
                linear_bearing_mount(
                    part=part,
                    bearing=zaxis_bearing,
                    ziptie_type=ziptie_type,
                    ziptie_bearing_distance=ziptie_bearing_distance,
                    orient=Z,
                    align=Z,
                    with_zips=true,
                    offset_flange=true,
                    mount_dir_align=xaxis_z_bearing_mount_dir,
                    mount_style=xaxis_z_bearing_mount_style
                    );
            }

        }
    }
    else if(part=="neg")
    {
        xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

        // belt idler screw cut
        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0, -xaxis_beltpath_width/2 - 7*mm, 0])
            {
                screw_cut(nut=NutHexM5, h=xaxis_beltpath_width+13*mm, with_nut=true, orient=Y, align=Y);
            }
        }

        //endstop mount screw cuts
        if(xaxis_endstop_type == "SWITCH")
        {
            translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
            translate(xaxis_endstop_screw_offset_switch)
            for(y=[-1,1])
            translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size_switch[2]])
            {
                screw_cut(nut=NutHexM2_5, h=10*mm, embed_head=false, with_head=true, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
            }
        }
        else if(xaxis_endstop_type == "SN04")
        {
            translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
            translate(xaxis_endstop_screw_offset_SN04)
            for(y=[-1,1])
            translate([-0*mm,y*10.5*mm/2,xaxis_endstop_size_SN04[2]])
            {
                translate(xaxis_endstop_offset_SN04)
                screw_cut(nut=NutHexM3, h=20*mm, embed_head=false, with_head=true, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
            }
        }

        xaxis_end_beltpath(height=xaxis_beltpath_height_body, width=xaxis_beltpath_width);

        // z smooth bearing mounts cut
        translate(-xaxis_zaxis_distance_y*Y)
        translate(-Z*(xaxis_end_wz/2))
        {
            linear_bearing_mount(
                part=part,
                bearing=zaxis_bearing,
                ziptie_type=ziptie_type,
                ziptie_bearing_distance=ziptie_bearing_distance,
                orient=Z,
                align=Z,
                with_zips=true,
                offset_flange=true,
                mount_dir_align=xaxis_z_bearing_mount_dir,
                mount_style=xaxis_z_bearing_mount_style
                );
        }

        if(with_motor)
        {
            screw_dist = lookup(NemaDistanceBetweenMountingHoles, xaxis_motor);

            // axle
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                round_d=1.1*lookup(NemaRoundExtrusionDiameter, xaxis_motor);
                translate([0, .1, 0])
                translate(Y)
                teardrop(d=round_d,h=motor_mount_wall_thick, tear_orient=Z, orient=Y, align=-Y, roll=90, truncate=0.9);

                // motor axle
                translate([0, .1, 0])
                cylindera(d=1.2*lookup(NemaAxleDiameter, xaxis_motor), h=lookup(NemaFrontAxleLength, xaxis_motor)+3*mm, orient=Y, align=Y);

                // bearing for offloading force on motor shaft
                translate([0, -2.5*mm-xaxis_pulley[1]-.1, 0])
                scale(1.03)
                cylindera(d=bearing_MR105[1], h=6*mm, orient=Y, align=[0,-1,0]);

                for(x=[-1,1])
                for(z=[-1,1])
                translate([0,-xaxis_end_motor_offset[1],0])
                translate([x*screw_dist/2, -(xaxis_beltpath_width/2+3*mm), z*screw_dist/2])
                {
                    if(!(x==1 && z == (beltpath_index==0?1:-1)))
                    screw_cut(xaxis_motor_nut, h=25, with_nut=false, orient=Y, align=Y);
                }
            }

        }

        // nut mount
        mirror([0,0,nut_top?1:0])
        translate([zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2])
        rotate(90*Z)
        {
            union()
            {
                translate([0,0,-.1])
                {
                    // nut
                    cylindera(h=nut_h+1, d=zaxis_nut[0]*1.05, align=Z);

                    // lead screw
                    translate([0,0,-.1])
                    cylindera(h=lookup(NemaFrontAxleLength,zaxis_motor), d=zaxis_nut[2]*1.5, align=Z);

                    for(i=[-1,1])
                    translate([i*zaxis_nut[5], 0, -zaxis_nut[3]])
                    screw_cut(thread=zaxis_nut[6], h=16*mm, with_nut=false, orient=Z, align=Z);
                }
            }
        }
    }
    else if(part=="vit")
    {
        xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

        translate(-xaxis_zaxis_distance_y*Y)
        translate(-Z*(xaxis_end_wz/2))
        {
            linear_bearing_mount(
                part=part,
                bearing=zaxis_bearing,
                ziptie_type=ziptie_type,
                ziptie_bearing_distance=ziptie_bearing_distance,
                orient=Z,
                align=Z,
                with_zips=true,
                offset_flange=true,
                mount_dir_align=xaxis_z_bearing_mount_dir,
                mount_style=xaxis_z_bearing_mount_style
                );
        }

        if(with_motor)
        {
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                // 1mm due to motor offset
                translate([0,-1*mm,0])
                {
                    // 1mm between pulley and motor
                    translate([0,-1*mm,0])
                    pulley(xaxis_pulley, flip=false, orient=Y, align=[0,-1,0]);

                    if(show_motor)
                    {
                        motor(xaxis_motor, NemaMedium, dualAxis=false, orientation=[-90,0,0]);
                    }
                }
            }
        }

        //endstop
        if($show_vit)
        {
            if(xaxis_endstop_type == "SWITCH")
            {
                translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
                difference()
                {
                    material(Mat_PlasticBlack)
                    rcubea(xaxis_endstop_size_switch, align=[-1,0,1]);

                    translate(xaxis_endstop_screw_offset_switch)
                    for(y=[-1,1])
                    translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size_switch[2]])
                    screw(nut=NutHexM2_5, with_nut=false, h=10*mm, orient=[0,0,-1], align=[0,0,-1]);
                }
            }
            else if(xaxis_endstop_type == "SN04")
            {
                translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
                translate(xaxis_endstop_offset_SN04)
                translate([-36,-9,0])
                rotate(ZAXIS*-90)
                import("stl/SN04-N_Inductive_Proximity_Sensor_3528_0.stl");
            }
        }

        // belt idler pulley screw
        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0, -xaxis_beltpath_width/2 - 7*mm, 0])
            {
                screw(nut=NutHexM5, h=25*mm, with_nut=true, orient=Y, align=Y);
            }
        }

        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            pulley(xaxis_idler_pulley, orient=Y);
        }

        if(show_nut)
        {
            mirror([0,0,nut_top?1:0])
            translate([zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2-zaxis_nut[3]])
            xaxis_end_znut();
        }

        if(show_rods)
        {
            for(z=[-1,1])
                translate([0,0,z*xaxis_rod_distance/2])
                translate([0, -xaxis_zaxis_distance_y, 0])
                cylindera(d=zaxis_rod_d, h=zaxis_rod_l, orient=Z);
        }
    }
}

module xaxis_end_beltpath(height, width, length = 1000, align=N, orient=X)
{
    hull()
    for(z=[-1,1])
    translate([0,0,z*height/2])
    teardrop(h=length, d=width, orient=orient, align=align, roll=-180*min(0,z), truncate=1);
}

module xaxis_end_znut()
{
    difference()
    {
        material(zaxis_nut_mat)
        union()
        {
            cylindera(d=zaxis_nut[1], h=zaxis_nut[3], orient=Z, align=Z);
            cylindera(d=zaxis_nut[0], h=zaxis_nut[4], orient=Z, align=Z);
        }

        translate([0,0,-.1])
        cylindera(d=zaxis_nut[2], h=zaxis_nut[4]+.2, orient=Z, align=Z);
    }
}

if(false)
{
    // x axis
    /*translate([0,0,axis_pos_z])*/
    {
        /*if(!$preview_mode)*/
        {
            zrod_offset = zmotor_mount_rod_offset_x;
            for(x=[-1,1])
            {
                z=xaxis_beltpath_z_offsets[x<0?0:x];
                xo = x>0?xaxis_end_pulley_offset:xaxis_end_motor_offset[0];
                xw = x<0?xaxis_end_pulley_offset:xaxis_end_motor_offset[0];
                translate([-main_width/2-xo/2, xaxis_zaxis_distance_y, z])
                color("black")
                belt_path(main_width+xw, 6, xaxis_pulley_inner_d, orient=X, align=X);
            }
        }

        /*translate([axis_pos_x,0,0])*/
        /*{*/
            // x carriage
            /*attach(xaxis_carriage_conn, [[0,-xaxis_zaxis_distance_y,0],N])*/
            /*{*/
                /*x_carriage_full();*/
            /*}*/
        /*}*/

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

        for(x=[-1,1])
        translate([x*(main_width/2), 0, 0])
        translate([x*(zmotor_mount_rod_offset_x),0,0])
        cylindera(h=zaxis_rod_l,d=zaxis_rod_d, orient=Z, align=N);

        for(x=[-1,1])
        {
            translate([x*(main_width/2), 0, 0])
            {
                translate([0, xaxis_zaxis_distance_y, 0])
                translate([x*zmotor_mount_rod_offset_x, 0, 0])
                mirror([max(0,x),0,0])
                {
                    xaxis_end(with_motor=true, beltpath_index=max(0,x), show_nut=true, show_motor=true, show_nut=true);
                }
            }
        }
    }

}

if(false)
{
    for(x=[-1,1])
    translate([x*100*mm,0,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    {
        xaxis_end(with_motor=true, beltpath_index=max(0,x), show_motor=false, show_nut=false, show_bearings=false, with_xrod_adjustment=true);
    }
}

module part_x_end_right()
{
    x=1;
    translate([0,0,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    xaxis_end(with_motor=true, beltpath_index=max(0,x), with_xrod_adjustment=true);
}

module part_x_end_left()
{
    x=-1;
    translate([0,0,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    xaxis_end(with_motor=true, beltpath_index=max(0,x), with_xrod_adjustment=true);
}

use <thing_libutils/misc.scad>
use <thing_libutils/bearing.scad>
use <thing_libutils/screws.scad>
use <thing_libutils/timing-belts.scad>
use <thing_libutils/bearing-linear.scad>

include <thing_libutils/bearing_data.scad>
include <thing_libutils/pulley.scad>

include <x-end.h>

module xaxis_end_body(part, with_motor, beltpath_index=0, nut_top=false, with_xrod_adjustment=true)
{
    nut_h = zaxis_nut[4];
    bearing_sizey = zaxis_bearing_OD + 5*mm;

    xaxis_end_xrod_offset_z = xaxis_rod_l/2 - (main_width/2 + zmotor_mount_rod_offset_x);
    xaxis_rod_d_support = xaxis_rod_d+5*mm;
    xaxis_rod_l_support = xaxis_end_xrod_offset_z + 8*mm + (with_xrod_adjustment?8*mm:0);

    if(part==undef)
    {
        difference()
        {
            xaxis_end_body(part="pos", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
            xaxis_end_body(part="neg", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
        }
        %xaxis_end_body(part="vit", with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);
    }
    else if(part=="pos")
    {
        if(with_motor)
        {
            screw_dist = lookup(NemaDistanceBetweenMountingHoles, xaxis_motor);
            for(x=[-1,1])
            for(z=[-1,1])
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                translate([x*screw_dist/2, 0, z*screw_dist/2])
                cylindera(d=lookup(ThreadSize,xaxis_motor_thread)+4*mm, h=motor_mount_wall_thick, orient=Y, align=[0,-1,0], rounding_radius=2);
            }
        }

        // nut mount
        mirror([0,0,nut_top?1:0])
        translate([zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2])
        {
            // main nut support
            rcylindera(h=zaxis_nut[4], d=zaxis_nut[0]+5*mm, align=Z);

            // nut screw holes support
            rotate(Z*90)
            for(x=[-1,1])
            translate([x*zaxis_nut[5], 0, 0])
            rcylindera(h=zaxis_nut[4], d=lookup(ThreadSize, zaxis_nut[6])+5*mm, align=Z);

            // lead screw
            // ensure some support for the leadscrew cutout all the way to the top
            /*rcylindera(h=xaxis_end_wz, d=zaxis_nut[2]*2, align=Z);*/
        }

        // x axis rod holders
        for(z=[-1,1])
        translate([0,0,z*(xaxis_rod_distance/2)])
        rcylindera(h=xaxis_end_width(with_motor), d=xaxis_rod_d_support, orient=X, align=X);

        // endstops mount support
        if(xaxis_endstop_type == "SWITCH")
        {
            translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
            {
                rcubea(xaxis_endstop_size_switch, align=-XAXIS-ZAXIS);
            }
        }
        else if(xaxis_endstop_type == "SN04")
        {
            translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
            {
                translate(xaxis_endstop_offset_SN04)
                rcubea(xaxis_endstop_size_SN04, align=-XAXIS-ZAXIS);
            }
        }

        // belt idler screw cut support
        for(z=[-1,1])
        for(y=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0,y*-xaxis_beltpath_width/2,0])
            cylindera(orient=Y, d=15*mm, h=7*mm, align=-y*Y);
        }
    }
    else if(part=="neg")
    {
        for(z=[-1,1])
        translate([0,0*mm,z*(xaxis_rod_distance/2)])
        {
            xoff = - xaxis_end_xrod_offset_z -(with_xrod_adjustment?6:0)*mm;
            translate([xoff,0,0])
            cylindera(h=abs(xoff)+xaxis_end_width(with_motor)+1,d=xaxis_rod_d+.5*mm, orient=X, align=X);

            if(with_xrod_adjustment)
            {
                translate(X*5*mm)
                nut_trap_cut(nut=NutHexM4, trap_axis=Y, orient=-X, align=X);

                translate(X*-7*mm)
                cylindera(d=10, h=10, orient=X);
            }
        }
    }
    else if(part=="vit")
    {
    }
}

module xaxis_end(part, with_motor=false, stop_x_rods=true, beltpath_index=0, show_motor=false, nut_top=false, show_nut=false, show_rods=false, show_bearings=false, with_xrod_adjustment=false)
{
    nut_h = zaxis_nut[4];
    extrasize = with_motor?0*mm:0*mm;
    extrasize_align = 1;

    if(part==undef)
    {
        difference()
        {
            xaxis_end(part="pos", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
            xaxis_end(part="neg", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
        }
        %xaxis_end(part="vit", with_motor=with_motor, stop_x_rods=stop_x_rods, beltpath_index=beltpath_index, show_motor=show_motor, nut_top=nut_top, show_nut=show_nut, show_rods=show_rods, show_bearings=show_bearings, with_xrod_adjustment=with_xrod_adjustment);
    }
    else if(part=="pos")
    {
        // projection against z, ensure easy print
        proj_extrude_axis(axis=Z, offset=xaxis_end_wz/2)
        {
            xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

            // z smooth bearing mounts support
            translate(-xaxis_zaxis_distance_y*Y)
            translate(-Z*(xaxis_end_wz/2))
            {
                linear_bearing_mount(
                    part=part,
                    bearing=zaxis_bearing,
                    ziptie_type=ziptie_type,
                    ziptie_bearing_distance=ziptie_bearing_distance,
                    orient=Z,
                    align=Z,
                    with_zips=true,
                    offset_flange=true,
                    mount_dir_align=xaxis_z_bearing_mount_dir,
                    mount_style=xaxis_z_bearing_mount_style
                    );
            }

        }
    }
    else if(part=="neg")
    {
        xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

        // belt idler screw cut
        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0, -xaxis_beltpath_width/2 - 7*mm, 0])
            {
                screw_cut(nut=NutHexM5, h=xaxis_beltpath_width+13*mm, with_nut=true, orient=Y, align=Y);
            }
        }

        //endstop mount screw cuts
        if(xaxis_endstop_type == "SWITCH")
        {
            translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
            translate(xaxis_endstop_screw_offset_switch)
            for(y=[-1,1])
            translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size_switch[2]])
            {
                screw_cut(nut=NutHexM2_5, h=10*mm, embed_head=false, with_head=true, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
            }
        }
        else if(xaxis_endstop_type == "SN04")
        {
            translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
            translate(xaxis_endstop_screw_offset_SN04)
            for(y=[-1,1])
            translate([-0*mm,y*10.5*mm/2,xaxis_endstop_size_SN04[2]])
            {
                translate(xaxis_endstop_offset_SN04)
                screw_cut(nut=NutHexM3, h=20*mm, embed_head=false, with_head=true, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
            }
        }

        xaxis_end_beltpath(height=xaxis_beltpath_height_body, width=xaxis_beltpath_width);

        // z smooth bearing mounts cut
        translate(-xaxis_zaxis_distance_y*Y)
        translate(-Z*(xaxis_end_wz/2))
        {
            linear_bearing_mount(
                part=part,
                bearing=zaxis_bearing,
                ziptie_type=ziptie_type,
                ziptie_bearing_distance=ziptie_bearing_distance,
                orient=Z,
                align=Z,
                with_zips=true,
                offset_flange=true,
                mount_dir_align=xaxis_z_bearing_mount_dir,
                mount_style=xaxis_z_bearing_mount_style
                );
        }

        if(with_motor)
        {
            screw_dist = lookup(NemaDistanceBetweenMountingHoles, xaxis_motor);

            // axle
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                round_d=1.1*lookup(NemaRoundExtrusionDiameter, xaxis_motor);
                translate([0, .1, 0])
                translate(Y)
                teardrop(d=round_d,h=motor_mount_wall_thick, tear_orient=Z, orient=Y, align=-Y, roll=90, truncate=0.9);

                // motor axle
                translate([0, .1, 0])
                cylindera(d=1.2*lookup(NemaAxleDiameter, xaxis_motor), h=lookup(NemaFrontAxleLength, xaxis_motor)+3*mm, orient=Y, align=Y);

                // bearing for offloading force on motor shaft
                translate([0, -2.5*mm-xaxis_pulley[1]-.1, 0])
                scale(1.03)
                cylindera(d=bearing_MR105[1], h=6*mm, orient=Y, align=[0,-1,0]);

                for(x=[-1,1])
                for(z=[-1,1])
                translate([0,-xaxis_end_motor_offset[1],0])
                translate([x*screw_dist/2, -(xaxis_beltpath_width/2+3*mm), z*screw_dist/2])
                {
                    if(!(x==1 && z == (beltpath_index==0?1:-1)))
                    screw_cut(xaxis_motor_nut, h=25, with_nut=false, orient=Y, align=Y);
                }
            }

        }

        // nut mount
        mirror([0,0,nut_top?1:0])
        translate([zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2])
        rotate(90*Z)
        {
            union()
            {
                translate([0,0,-.1])
                {
                    // nut
                    cylindera(h=nut_h+1, d=zaxis_nut[0]*1.05, align=Z);

                    // lead screw
                    translate([0,0,-.1])
                    cylindera(h=lookup(NemaFrontAxleLength,zaxis_motor), d=zaxis_nut[2]*1.5, align=Z);

                    for(i=[-1,1])
                    translate([i*zaxis_nut[5], 0, -zaxis_nut[3]])
                    screw_cut(thread=zaxis_nut[6], h=16*mm, with_nut=false, orient=Z, align=Z);
                }
            }
        }
    }
    else if(part=="vit")
    {
        xaxis_end_body(part=part, with_motor=with_motor, beltpath_index=beltpath_index, nut_top=nut_top, with_xrod_adjustment=with_xrod_adjustment);

        translate(-xaxis_zaxis_distance_y*Y)
        translate(-Z*(xaxis_end_wz/2))
        {
            linear_bearing_mount(
                part=part,
                bearing=zaxis_bearing,
                ziptie_type=ziptie_type,
                ziptie_bearing_distance=ziptie_bearing_distance,
                orient=Z,
                align=Z,
                with_zips=true,
                offset_flange=true,
                mount_dir_align=xaxis_z_bearing_mount_dir,
                mount_style=xaxis_z_bearing_mount_style
                );
        }

        if(with_motor)
        {
            translate([0,0,xaxis_beltpath_z_offsets[beltpath_index]])
            translate(xaxis_end_motor_offset)
            {
                // 1mm due to motor offset
                translate([0,-1*mm,0])
                {
                    // 1mm between pulley and motor
                    translate([0,-1*mm,0])
                    pulley(xaxis_pulley, flip=false, orient=Y, align=[0,-1,0]);

                    if(show_motor)
                    {
                        motor(xaxis_motor, NemaMedium, dualAxis=false, orientation=[-90,0,0]);
                    }
                }
            }
        }

        //endstop
        if($show_vit)
        {
            if(xaxis_endstop_type == "SWITCH")
            {
                translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
                difference()
                {
                    rcubea(xaxis_endstop_size_switch, align=[-1,0,1]);

                    translate(xaxis_endstop_screw_offset_switch)
                    for(y=[-1,1])
                    translate([-5*mm,y*9.5*mm/2,xaxis_endstop_size_switch[2]])
                    screw(nut=NutHexM2_5, with_nut=false, h=10*mm, orient=[0,0,-1], align=[0,0,-1]);
                }
            }
            else if(xaxis_endstop_type == "SN04")
            {
                translate([xaxis_end_width(with_motor),0,xaxis_end_wz/2])
                translate(xaxis_endstop_offset_SN04)
                translate([-36,-9,0])
                rotate(ZAXIS*-90)
                import("stl/SN04-N_Inductive_Proximity_Sensor_3528_0.stl");
            }
        }

        // belt idler pulley screw
        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            translate([0, -xaxis_beltpath_width/2 - 7*mm, 0])
            {
                screw(nut=NutHexM5, h=25*mm, with_nut=true, orient=Y, align=Y);
            }
        }

        for(z=[-1,1])
        translate([xaxis_end_pulley_offset,0,-xaxis_beltpath_z_offsets[max(0,beltpath_index)]])
        {
            pulley(xaxis_idler_pulley, orient=Y);
        }

        if(show_nut)
        {
            mirror([0,0,nut_top?1:0])
            translate([zaxis_rod_screw_distance_x, -xaxis_zaxis_distance_y, -xaxis_end_wz/2-zaxis_nut[3]])
            xaxis_end_znut();
        }

        if(show_rods)
        {
            for(z=[-1,1])
                translate([0,0,z*xaxis_rod_distance/2])
                translate([0, -xaxis_zaxis_distance_y, 0])
                cylindera(d=zaxis_rod_d, h=zaxis_rod_l, orient=Z);
        }
    }
}

module xaxis_end_beltpath(height, width, length = 1000, align=N, orient=X)
{
    hull()
    for(z=[-1,1])
    translate([0,0,z*height/2])
    teardrop(h=length, d=width, orient=orient, align=align, roll=-180*min(0,z), truncate=1);
}

module xaxis_end_znut()
{
    difference()
    {
        union()
        {
            cylindera(d=zaxis_nut[1], h=zaxis_nut[3], orient=Z, align=Z);
            cylindera(d=zaxis_nut[0], h=zaxis_nut[4], orient=Z, align=Z);
        }

        translate([0,0,-.1])
        cylindera(d=zaxis_nut[2], h=zaxis_nut[4]+.2, orient=Z, align=Z);
    }
}

if(false)
{
    // x axis
    /*translate([0,0,axis_pos_z])*/
    {
        /*if(!$preview_mode)*/
        {
            zrod_offset = zmotor_mount_rod_offset_x;
            for(x=[-1,1])
            {
                z=xaxis_beltpath_z_offsets[x<0?0:x];
                xo = x>0?xaxis_end_pulley_offset:xaxis_end_motor_offset[0];
                xw = x<0?xaxis_end_pulley_offset:xaxis_end_motor_offset[0];
                translate([-main_width/2-xo/2, xaxis_zaxis_distance_y, z])
                color("black")
                belt_path(main_width+xw, 6, xaxis_pulley_inner_d, orient=X, align=X);
            }
        }

        /*translate([axis_pos_x,0,0])*/
        /*{*/
            // x carriage
            /*attach(xaxis_carriage_conn, [[0,-xaxis_zaxis_distance_y,0],N])*/
            /*{*/
                /*x_carriage_full();*/
            /*}*/
        /*}*/

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

        for(x=[-1,1])
        translate([x*(main_width/2), 0, 0])
        translate([x*(zmotor_mount_rod_offset_x),0,0])
        cylindera(h=zaxis_rod_l,d=zaxis_rod_d, orient=Z, align=N);

        for(x=[-1,1])
        {
            translate([x*(main_width/2), 0, 0])
            {
                translate([0, xaxis_zaxis_distance_y, 0])
                translate([x*zmotor_mount_rod_offset_x, 0, 0])
                mirror([max(0,x),0,0])
                {
                    xaxis_end(with_motor=true, beltpath_index=max(0,x), show_nut=true, show_motor=true, show_nut=true);
                }
            }
        }
    }

}

if(false)
{
    for(x=[-1,1])
    translate([x*100*mm,0,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    {
        xaxis_end(with_motor=true, beltpath_index=max(0,x), show_motor=false, show_nut=false, show_bearings=false, with_xrod_adjustment=true);
    }
}

module part_x_end_right()
{
    x=1;
    translate([0,0,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    xaxis_end(with_motor=true, beltpath_index=max(0,x), with_xrod_adjustment=true);
}

module part_x_end_left()
{
    x=-1;
    translate([0,0,xaxis_end_wz/2])
    mirror([max(0,x),0,0])
    xaxis_end(with_motor=true, beltpath_index=max(0,x), with_xrod_adjustment=true);
}


beefed up rails.  DE was a bit flexy

beefed up rails.  DE was a bit flexy

// $URL: svn+ssh://mrwhat@ssh.boim.com/home/mrwhat/svn/Walker/trunk/JansenBED.scad $
// $Id: JansenBED.scad 435 2015-03-02 15:21:04Z mrwhat $

// main BED code, more injection-mold-like model

// Uses a ton of stuff from Jansen.scad.
// Use from an #include in  Jansen.scad.

// for testing, reproduce included stuff:
//include <util.scad>
//BED(34,66.4,34);Drad=2.4;NodeHeight3=12.5;NodeHeight=4.3;Brad=2.4;BradFree=2.5;ForkHeight=NodeHeight;rad4=1.4;LinkRad=3;

forkLen = 3.5*LinkRad;  // forks around linkage in BED
nf=24;  // faces for hull components

module BEDhull(dLeft,dPerp,dRight,ph,rp) { hull() {
translate([-dLeft,-1,    0]) cylinder(h=1,r1=1,r2=.1,$fn=nf);
translate([dRight,-1,    0]) cylinder(h=1,r1=1,r2=.1,$fn=nf);
translate([ rp,dPerp+1,0]) cylinder(h=1,r1=1,r2=.1,$fn=nf);
translate([-rp,dPerp+1,0]) cylinder(h=1,r1=1,r2=.1,$fn=nf);
translate([ 0,dPerp-rp,ph-1]) sphere(r=1,$fn=nf);
translate([4-dLeft ,1,2]) sphere(r=1,$fn=nf);
translate([dRight-4,1,2]) sphere(r=1,$fn=nf);
}}

module BEDsideRail(x,dPerp,ph) {
hull() {
   translate([x,-1,  0]) {
     cylinder(h=1,r1=1.2,r2=.1,$fn=nf);
     translate([0,0,2]) sphere(r=.6,$fn=nf); }
   translate([0,dPerp+2,0]) {
     cylinder(h=1,r1=1.5,r2=.1,$fn=nf);
     translate([0,0,ph-.6]) sphere(r=.6,$fn=nf); }
   }
hull() {
   if (x < 0) { translate([x+2,0,0]) cylinder(h=2,r1=2.5,r2=2,$fn=nf); }
   else       { translate([x-2,0,0]) cylinder(h=2,r1=2.5,r2=2,$fn=nf); }
   translate([0,dPerp,0]) cylinder(h=2,r1=2.5,r2=2,$fn=nf);
   }
}

module BEDmainSideRail(x,dPerp,ph) {
x2=(x<0)?x+2:x-2;
x1=(x<0)?x-1:x+1;
  blade([x2,0,.6],2.5,1.5,  [0,dPerp,0.4],3,1.5);
  blade([x1,-1,.4],1,3.5,   [0,dPerp+2,1],1,ph,fn=16);
}

/*
module BEDrails(dLeft,dPerp,dRight,ph,rp) {
union() {
   BEDsideRail(-dLeft,dPerp,ph);
   BEDsideRail(dRight,dPerp,ph);
   hull() { // vert bar part, DE
     translate([-dLeft,-1,0]) { cylinder(h=1,r1=1.5,r2=.1,$fn=6);
     translate([0,0,3]) sphere(r=.6,$fn=nf); }
     translate([dRight,-1,0]) { cylinder(h=1,r1=1.5,r2=.1,$fn=6);
     translate([0,0,3]) sphere(r=.6,$fn=nf); }
   }
   hull() { // horiz, flat part of DE segment
     translate([-dLeft+2,0,0]) cylinder(h=2,r1=2.5,r2=2,$fn=6);
     translate([dRight-2,0,0]) cylinder(h=2,r1=2.5,r2=2,$fn=6);
   }
   // extra brace on D node
   hull() {
     translate([dRight-6,6,0]) cylinder(h=3,r1=1,r2=0.5,$fn=6);
     translate([dRight+2,1,0]) cylinder(h=4,r1=3,r2=2,$fn=6);
   }
}}
*/

module BEDmainRails(dLeft,dPerp,dRight,ph,rp) union() {
   BEDmainSideRail(-dLeft,dPerp,ph);
   BEDmainSideRail(dRight,dPerp,ph);

   blade([-dLeft  ,-1,1.5],1,6,     // vert DE
         [dRight+3,-1,0.5],1.5,NodeHeight-1,fn=17);
   blade([-dLeft+1,0,.4],3.5,1.5,   // DE horiz
         [dRight-2,0,.4],3,2);

   // extra brace on D node
   hull() {
     translate([dRight-4,6,0]) scale([1,1,4]) sphere(1,$fn=16);
     translate([dRight+4,1,0]) sphereSection(3,4);
   }
}

module forkTab(h,r1,r2,len) {
difference(){
hull() { cylinder(h=h,r1=r1,r2=r2,$fn=48);
  translate([len+2,0,0]) cylinder(h=2,r1=2,r2=1,$fn=12); }
translate([len,0,-1]) cylinder(h=3*NodeHeight,r=.8,$fn=6);
    drillHole(rad4);
}}

module forkTabF(h,r1,r2,len) difference() {
  union() {
    linkNode(r1+0.5,h,ar=.9,dx=len+3);
    // add flat section, easier to clamp
    hull() {
      cylinder(r1=3.5,r2=2.5,h=3,$fn=12);
      translate([len,0,0]) cylinder(r1=3,r2=1.8,h=3,$fn=18);
    }
  }
  translate([len,0,-1]) cylinder(h=3*NodeHeight,r=.8,$fn=6);
  drillHole(rad4);
}

module imBEDmain(dLeft,dBase,dPerp) { //------------------------------------ BED
perpHeight = NodeHeight3; //3*TrueNodeHeight;  // same height as long hinge-pin
difference() { union() {
  difference() { union() {
     BEDhull(dLeft*.8,dPerp,.75*(dBase-dLeft),perpHeight,Brad);

     translate([-dLeft,0,0]) {
        rotate([0,0,5]) hull() {
           translate([0,0,NodeHeight+0.3]) forkTab(ForkHeight,Drad+2,rad4+1.4,forkLen);
           translate([NodeHeight, 0 , 0 ]) forkTab(    2     ,Drad+2,rad4+1.4,forkLen); }

        translate([dBase,0,0]) rotate([0,0,-5]) difference() {
           hull() { translate([-5*Drad,0,1.5]) sphere(r=1.5,$fn=12);
               cylinder(h=NodeHeight,r1=Drad+2, r2=Drad+1.8, $fn=48); }
           // hollow out hull a but...  injction mold style
           translate([0,0,-1.5]) { difference() { hull() {
               translate([-4*Drad+3,0,0]) cylinder(h=NodeHeight-1,r1=.4,r2=.2,$fn=6);
               cylinder(h=NodeHeight,r1=Drad-.1 ,r2=Drad-.4,$fn=24); }
               cylinder(h=NodeHeight,r1=Drad+1.7,r2=Drad+1.9,$fn=24); }}
       }

     } // end translate
   } // union

   translate([0,2,-1])
      BEDhull(dLeft*.8-3,dPerp-3,.75*(dBase-dLeft)-3,perpHeight-2,Drad-1);
   } // inner diff

   translate([0,dPerp,0])
      cylinder(h=perpHeight,r1=Brad+2.4,r2=Brad+1.8,$fn=48);
   }   // end second union

   //------------- main holes/knock outs
   translate([0,dPerp,0])drillHole(BradFree); // a little larger to move freely
   translate([(dBase-dLeft),0,0]) drillHole(Drad);

   // for Maxi version, drill hole in top half of "fork" node,
   // and knock out slot for in-plane CD linkage
   translate([-dLeft,0,0]) {

      translate([0,0,-.1]) {
         difference() { cube([28,33,2*(NodeHeight+.3)],center=true);
            hull() {
              translate([Drad+7,1,0]) cylinder(h=NodeHeight+.31,r=3,$fn=16);
              translate([Drad+14,2,0]) cylinder(h=NodeHeight+3,r=5,$fn=6);
              translate([Drad+14,10,0]) cylinder(h=NodeHeight+3,r=5,$fn=6);
            }
         }
      }
      drillHole(rad4);

      // drill hole to help allign fork linkage, must match linkage length below
      rotate([0,0,5]) translate([forkLen,0,0]) cylinder(h=3*NodeHeight,r=.6,$fn=6);
   }

  // diagnostic slice to examine walls
  //translate([0,-2,-2]) cube([4,44,33]);
}

// add other side of fork
//translate([-dLeft+0.7*forkLen,1.2*forkLen,0]) rotate([0,0,40])
//    forkTab(ForkHeight,Drad+2,rad4+1.4,forkLen);
}
//------------------------------------- end of imBEDmain

module BED1main(dLeft,dBase,dPerp) { //------------------------------------ BED
perpHeight = NodeHeight3; //3*TrueNodeHeight;  // same height as long hinge-pin
difference() { union() {
  difference() { union() {
     BEDrails(dLeft*.8,dPerp,.75*(dBase-dLeft),perpHeight,Brad);

     translate([-dLeft,0,0]) {
        rotate([0,0,5]) hull() {
           translate([0,0,NodeHeight+0.3]) forkTab(ForkHeight,Drad+2,rad4+1.4,forkLen-2);
           translate([NodeHeight, 0 , 0 ]) forkTab(    2     ,Drad+2,rad4+1.4,forkLen-2); }

        translate([dBase,0,0]) rotate([0,0,-5]) //difference() {
           hull() { translate([-4*Drad-4,-1,2]) sphere(r=2,$fn=12);
               cylinder(h=NodeHeight,r1=Drad+2, r2=Drad+1.8, $fn=48); }
           // hollow out hull a but...  injction mold style
           //#translate([0,0,-1.5]) { difference() { hull() {
           //    translate([-4*Drad+3,0,0]) cylinder(h=NodeHeight-1,r1=.4,r2=.2,$fn=6);
           //    cylinder(h=NodeHeight,r1=Drad-.1 ,r2=Drad-.4,$fn=24); }
           //    cylinder(h=NodeHeight,r1=Drad+1.7,r2=Drad+1.9,$fn=24); }}
       //}

     } // end translate
   } // union

   //translate([0,2,-1])
   //   BEDhull(dLeft*.8-3,dPerp-3,.75*(dBase-dLeft)-3,perpHeight-2,Drad-1);
   } // inner diff

   // main B-axis node cylinder
   translate([0,dPerp,0])
      cylinder(h=perpHeight,r1=Brad+2.4,r2=Brad+1.8,$fn=48);

   // more bracing for fork
   hull() {
     translate([-dLeft+8,0,0]) cylinder(r=3,h=NodeHeight+3,$fn=6);
     translate([-dLeft+17,11,0]) cylinder(r=2,h=1,$fn=6);
   }
   hull() {
     translate([-dLeft+1,-1.5,0]) cylinder(r=2,h=NodeHeight+3.5,$fn=6);
     translate([-dLeft+8,-1,0]) cylinder(r=3,h=NodeHeight+3,$fn=6);
     translate([-dLeft+21,0,0]) cylinder(r=2,h=1,$fn=6);
   }

   }   // end second union

   //------------- main holes/knock outs
   translate([0,dPerp,0])drillHole(BradFree+.2); // a little larger to move freely
   translate([(dBase-dLeft),0,0]) drillHole(Drad);

   // for Maxi version, drill hole in top half of "fork" node,
   // and knock out slot for in-plane CD linkage
   translate([-dLeft,0,0]) {

      translate([0,0,-.1]) {
         difference() { cube([28,33,2*(NodeHeight+.3)],center=true);
            hull() {
              translate([Drad+7,1,0]) cylinder(h=NodeHeight+.31,r=3,$fn=16);
              translate([Drad+9,-6,0]) cylinder(h=NodeHeight+3,r=5,$fn=6);
              translate([Drad+13.5,10,0]) cylinder(h=NodeHeight+3,r=8,$fn=6);
            }
         }
      }
      drillHole(rad4);

      // drill hole to help allign fork linkage, must match linkage length below
      rotate([0,0,5]) translate([forkLen,0,-1]) cylinder(h=3*NodeHeight,r=.8,$fn=6);
   }

  // diagnostic slice to examine walls
  //translate([0,-2,-2]) cube([4,44,33]);
}

// custom support
sW=0.41;  // support width
sH=4.4;  // support height
sH2=sH/2;
color("Cyan") union() {
/* stuff parallel to perimiter adhered too well
  translate([-28,1,sH2]) rotate([0,0,10]) cube([sW,8,sH],center=true);
  //translate([-29.5,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  translate([-31,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  //translate([-32.5,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  translate([-34,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  //translate([-35.5,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  translate([-37,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  translate([-36.5,-2.5,sH2]) rotate([0,0,40]) cube([sW,7,sH],center=true);
  translate([-36.5,2.5,sH2]) rotate([0,0,-40]) cube([sW,7,sH],center=true);
  translate([-30,-2.5,sH2]) rotate([0,0,10]) cube([8,sW,sH],center=true);
  translate([-31,3.5,sH2]) rotate([0,0,-10]) cube([8,sW,sH],center=true);
*/
  hull() {
    translate([-34,0,0]) cylinder(r1=3,r2=5,h=2,$fn=11);
    #translate([-29,0.5,0]) scale([1,5,1])
        cylinder(r1=.3,r2=1,h=2,$fn=6);
  }
  translate([-34,0,sH-1.5]) {
    translate([3.6,0,0]) cube([5,sW,2],center=true);
    for (a=[-30,30]) rotate([0,0,a]) translate([4,0,0]) cube([6,sW,3],center=true);
    for (a=[60:30:322]) rotate([0,0,a])
      translate([3,0,0]) cube([4,sW,3],center=true);
  }
}

}

module BEDmainFrame(dLeft,dPerp,dBase,perpHeight) union() {

  // main B-axis node cylinder
  translate([0,dPerp,0]) {
    linkNode(Brad+2.5,perpHeight,ar=3.5,off=-.2,dx= 3*Brad,dy=-3*Brad);
    linkNode(Brad+2.5,perpHeight,ar=3.5,off=-.2,dx=-3*Brad,dy=-3*Brad);
  }

  BEDmainRails(dLeft*.8,dPerp,.75*(dBase-dLeft),perpHeight,Brad);

  translate([-dLeft,0,0]) {
    rotate([0,0,5]) translate([0,0,NodeHeight+0.3])
        forkTabF(ForkHeight,Drad+2,rad4+1.4,forkLen);

    translate([dBase,0,0]) linkNode(Drad+2.2,NodeHeight,off=-.2,
       dx=-7*Drad,dy=-2);
  } // end translate

  // more bracing for fork
  hull() {
     translate([-dLeft+8,0,3.3]) scale([4,2,NodeHeight]) sphere(1,$fn=16);
     translate([-dLeft+16,11,1]) scale([1,1,2]) sphere(1,$fn=16);
  }
  hull() {
     translate([-dLeft+1,-1.5,NodeHeight+2.5]) sphere(2,$fn=24);
     translate([-dLeft+8,0,NodeHeight-1]) sphere(4,$fn=24);//cylinder(r=3,h=NodeHeight+3,$fn=6);
     translate([-dLeft+19,-1,-1]) scale([1,1,3]) sphere(1,$fn=16);
  }

}

module BEDmain(dLeft,dBase,dPerp) { //------------------------------------ BED
perpHeight = NodeHeight3; //3*TrueNodeHeight;  // same height as long hinge-pin
  difference() {
    BEDmainFrame(dLeft,dPerp,dBase,perpHeight);

    //------------- main holes/knock outs
    translate([0,dPerp,0])drillHole(BradFree+.2); // a little larger to move freely
    translate([(dBase-dLeft),0,0]) drillHole(Drad);

    // for Maxi version, drill hole in top half of "fork" node,
    // and knock out slot for in-plane CD linkage
    translate([-dLeft,0,0]) {

       translate([0,0,-.1]) {
         difference() { cube([28,33,2*(NodeHeight+.3)],center=true);
            hull() {
              translate([Drad+7,1,0]) cylinder(h=NodeHeight+.31,r=3,$fn=16);
              translate([Drad+9,-6,0]) cylinder(h=NodeHeight+3,r=5,$fn=6);
              translate([Drad+13.5,10,0]) cylinder(h=NodeHeight+3,r=8,$fn=6);
            }
         }
       }
       drillHole(rad4);

      // drill hole to help allign fork linkage, must match linkage length below
      rotate([0,0,5]) translate([forkLen,0,-1]) cylinder(h=3*NodeHeight,r=.8,$fn=6);
   }

  // diagnostic slice to examine walls
  //translate([0,-2,-2]) cube([4,44,33]);

    // chop off any junk below bottom
    translate([-dLeft-20,-20,-30]) cube([dBase+40,dPerp+40,30]);
  }

  color("Cyan") forkSupport(); // custom support
}

module forkSupport() {
sW=0.41;  // support width
sH=4.4;  // support height
sH2=sH/2;
  union() {
/* stuff parallel to perimiter adhered too well
  translate([-28,1,sH2]) rotate([0,0,10]) cube([sW,8,sH],center=true);
  //translate([-29.5,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  translate([-31,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  //translate([-32.5,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  translate([-34,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  //translate([-35.5,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  translate([-37,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  translate([-36.5,-2.5,sH2]) rotate([0,0,40]) cube([sW,7,sH],center=true);
  translate([-36.5,2.5,sH2]) rotate([0,0,-40]) cube([sW,7,sH],center=true);
  translate([-30,-2.5,sH2]) rotate([0,0,10]) cube([8,sW,sH],center=true);
  translate([-31,3.5,sH2]) rotate([0,0,-10]) cube([8,sW,sH],center=true);
*/
    hull() {
      translate([-34,0,0]) cylinder(r1=3,r2=5,h=2,$fn=11);
      #translate([-29,0.5,0]) scale([1,5,1])
          cylinder(r1=.3,r2=1,h=2,$fn=6);
    }
    translate([-34,0,sH-1.5]) {
      translate([3.6,0,0]) cube([5,sW,2],center=true);
      for (a=[-30,30]) rotate([0,0,a]) translate([4,0,0]) cube([6,sW,3],center=true);
      for (a=[60:30:322]) rotate([0,0,a])
        translate([3,0,0]) cube([4,sW,3],center=true);
    }
  }
}

//------------------------------------- end of BED1main

module imBED(dLeft,dBase,dPerp) { //------------------------------------ BED
imBEDmain(dLeft,dBase,dPerp);

// add other side of fork
translate([-dLeft+0.7*forkLen,1.2*forkLen,0]) rotate([0,0,40])
    forkTab(ForkHeight+.1,Drad+2,rad4+1.4,forkLen);
}

// Complete (Joined) version of BED, with in-place fork
module imBEDj(dLeft,dBase,dPerp) { //------------------------------------ BED
union() {
imBEDmain(dLeft,dBase,dPerp);

// add other side of fork, in place
translate([-dLeft,0,-.01]) { rotate([0,0,5]) {
    rotate([180,0,0]) forkTab(ForkHeight+.2,Drad+2,rad4+1.4,forkLen);

#hull(){
  translate([forkLen  ,0,0])cylinder(h=NodeHeight-2,r=2.8,$fn=12);
  translate([forkLen+1.5,4,1.1])sphere(r=1,$fn=6);
  translate([forkLen+2,0,0])cylinder(h=NodeHeight-2,r=2.2,$fn=12);}
}}

}}

//imBED(DEleft,DE,DEperp);

// version of BED intended for one-sided injection mold
module BED1(dLeft,dBase,dPerp) { //------------------------------------ BED
echo("BED1:",dLeft,dBase,dPerp);
BED1main(dLeft,dBase,dPerp);

// add other side of fork
//translate([-dLeft+0.7*forkLen,1.2*forkLen,0]) rotate([0,0,40])
translate([-10,8,0]) rotate([0,0,55])
    forkTab(ForkHeight+.1,Drad+2,rad4+1.4,forkLen);
}

module BED(dLeft,dBase,dPerp) { //------------------------------------ BED
//%BED1main(dLeft,dBase,dPerp);
BEDmain(dLeft,dBase,dPerp);

// add other side of fork
//translate([-dLeft+0.7*forkLen,1.2*forkLen,0]) rotate([0,0,40])
translate([0,14,0]) rotate([0,0,220])
    forkTabF(ForkHeight+.1,Drad+2,rad4+1.4,forkLen);
}

// $URL: svn+ssh://mrwhat@ssh.boim.com/home/mrwhat/svn/Walker/trunk/JansenBED.scad $
// $Id: JansenBED.scad 435 2015-03-02 15:21:04Z mrwhat $

// main BED code, more injection-mold-like model

// Uses a ton of stuff from Jansen.scad.
// Use from an #include in  Jansen.scad.

// for testing, reproduce included stuff:
//include <util.scad>
//BED(34,66.4,34);Drad=2.4;NodeHeight3=12.5;NodeHeight=4.3;Brad=2.4;BradFree=2.5;ForkHeight=NodeHeight;rad4=1.4;LinkRad=3;

forkLen = 3.5*LinkRad;  // forks around linkage in BED
nf=24;  // faces for hull components

module BEDhull(dLeft,dPerp,dRight,ph,rp) { hull() {
translate([-dLeft,-1,    0]) cylinder(h=1,r1=1,r2=.1,$fn=nf);
translate([dRight,-1,    0]) cylinder(h=1,r1=1,r2=.1,$fn=nf);
translate([ rp,dPerp+1,0]) cylinder(h=1,r1=1,r2=.1,$fn=nf);
translate([-rp,dPerp+1,0]) cylinder(h=1,r1=1,r2=.1,$fn=nf);
translate([ 0,dPerp-rp,ph-1]) sphere(r=1,$fn=nf);
translate([4-dLeft ,1,2]) sphere(r=1,$fn=nf);
translate([dRight-4,1,2]) sphere(r=1,$fn=nf);
}}

module BEDsideRail(x,dPerp,ph) {
hull() {
   translate([x,-1,  0]) {
     cylinder(h=1,r1=1.2,r2=.1,$fn=nf);
     translate([0,0,2]) sphere(r=.6,$fn=nf); }
   translate([0,dPerp+2,0]) {
     cylinder(h=1,r1=1.5,r2=.1,$fn=nf);
     translate([0,0,ph-.6]) sphere(r=.6,$fn=nf); }
   }
hull() {
   if (x < 0) { translate([x+2,0,0]) cylinder(h=2,r1=2.5,r2=2,$fn=nf); }
   else       { translate([x-2,0,0]) cylinder(h=2,r1=2.5,r2=2,$fn=nf); }
   translate([0,dPerp,0]) cylinder(h=2,r1=2.5,r2=2,$fn=nf);
   }
}

module BEDmainSideRail(x,dPerp,ph) {
x2=(x<0)?x+2:x-2;
  hull() {
    translate([x2,0,.6]) scale([3,1,1.5]) sphere(1,$fn=36);
    translate([0,dPerp,0.6]) scale(3,1,1.5) sphere(1,$fn=36);
  }
  hull() {
     translate([x,-1,  0]) scale([1,1,2]) sphere(1,$fn=16);
     translate([0,dPerp+2,1]) scale([1,1,ph]) sphere(1,$fn=16);
  }
}

module BEDrails(dLeft,dPerp,dRight,ph,rp) {
union() {
   BEDsideRail(-dLeft,dPerp,ph);
   BEDsideRail(dRight,dPerp,ph);
   hull() { // vert bar part, DE
     translate([-dLeft,-1,0]) { cylinder(h=1,r1=1.5,r2=.1,$fn=6);
     translate([0,0,3]) sphere(r=.6,$fn=nf); }
     translate([dRight,-1,0]) { cylinder(h=1,r1=1.5,r2=.1,$fn=6);
     translate([0,0,3]) sphere(r=.6,$fn=nf); }
   }
   hull() { // horiz, flat part of DE segment
     translate([-dLeft+2,0,0]) cylinder(h=2,r1=2.5,r2=2,$fn=6);
     translate([dRight-2,0,0]) cylinder(h=2,r1=2.5,r2=2,$fn=6);
   }
   // extra brace on D node
   hull() {
     translate([dRight-6,6,0]) cylinder(h=3,r1=1,r2=0.5,$fn=6);
     translate([dRight+2,1,0]) cylinder(h=4,r1=3,r2=2,$fn=6);
   }
}}

module BEDmainRails(dLeft,dPerp,dRight,ph,rp) union() {
   BEDmainSideRail(-dLeft,dPerp,ph);
   BEDmainSideRail(dRight,dPerp,ph);
   hull() { // vert bar part, DE
     translate([-dLeft,-1,1]) scale([1,1,5]) sphere(1,$fn=36);
     translate([dRight+1,-1,1]) scale([1,1,NodeHeight-2]) sphere(1,$fn=36);
   }
   // horiz, flat part of DE segment
   hull() {
     translate([-dLeft+1,0,.4]) scale([2,3,1.5]) sphere(1,$fn=36);
     translate([dRight-2,0,.4]) scale([2,2,1.5]) sphere(1,$fn=36);
   }

   // extra brace on D node
   hull() {
     translate([dRight-4,6,0]) scale([1,1,3]) sphere(1,$fn=16);
     translate([dRight+4,1,0]) sphereSection(3,4);
   }
}

module forkTab(h,r1,r2,len) {
difference(){
hull() { cylinder(h=h,r1=r1,r2=r2,$fn=48);
  translate([len+2,0,0]) cylinder(h=2,r1=2,r2=1,$fn=12); }
translate([len,0,-1]) cylinder(h=3*NodeHeight,r=.8,$fn=6);
    drillHole(rad4);
}}

module forkTabF(h,r1,r2,len) difference() {
  union() {
    linkNode(r1+0.5,h,ar=.9,dx=len+3);
    // add flat section, easier to clamp
    hull() {
      cylinder(r1=3.5,r2=2.5,h=3,$fn=12);
      translate([len,0,0]) cylinder(r1=3,r2=1.8,h=3,$fn=18);
    }
  }
  translate([len,0,-1]) cylinder(h=3*NodeHeight,r=.8,$fn=6);
  drillHole(rad4);
}

module imBEDmain(dLeft,dBase,dPerp) { //------------------------------------ BED
perpHeight = NodeHeight3; //3*TrueNodeHeight;  // same height as long hinge-pin
difference() { union() {
  difference() { union() {
     BEDhull(dLeft*.8,dPerp,.75*(dBase-dLeft),perpHeight,Brad);

     translate([-dLeft,0,0]) {
        rotate([0,0,5]) hull() {
           translate([0,0,NodeHeight+0.3]) forkTab(ForkHeight,Drad+2,rad4+1.4,forkLen);
           translate([NodeHeight, 0 , 0 ]) forkTab(    2     ,Drad+2,rad4+1.4,forkLen); }

        translate([dBase,0,0]) rotate([0,0,-5]) difference() {
           hull() { translate([-5*Drad,0,1.5]) sphere(r=1.5,$fn=12);
               cylinder(h=NodeHeight,r1=Drad+2, r2=Drad+1.8, $fn=48); }
           // hollow out hull a but...  injction mold style
           translate([0,0,-1.5]) { difference() { hull() {
               translate([-4*Drad+3,0,0]) cylinder(h=NodeHeight-1,r1=.4,r2=.2,$fn=6);
               cylinder(h=NodeHeight,r1=Drad-.1 ,r2=Drad-.4,$fn=24); }
               cylinder(h=NodeHeight,r1=Drad+1.7,r2=Drad+1.9,$fn=24); }}
       }

     } // end translate
   } // union

   translate([0,2,-1])
      BEDhull(dLeft*.8-3,dPerp-3,.75*(dBase-dLeft)-3,perpHeight-2,Drad-1);
   } // inner diff

   translate([0,dPerp,0])
      cylinder(h=perpHeight,r1=Brad+2.4,r2=Brad+1.8,$fn=48);
   }   // end second union

   //------------- main holes/knock outs
   translate([0,dPerp,0])drillHole(BradFree); // a little larger to move freely
   translate([(dBase-dLeft),0,0]) drillHole(Drad);

   // for Maxi version, drill hole in top half of "fork" node,
   // and knock out slot for in-plane CD linkage
   translate([-dLeft,0,0]) {

      translate([0,0,-.1]) {
         difference() { cube([28,33,2*(NodeHeight+.3)],center=true);
            hull() {
              translate([Drad+7,1,0]) cylinder(h=NodeHeight+.31,r=3,$fn=16);
              translate([Drad+14,2,0]) cylinder(h=NodeHeight+3,r=5,$fn=6);
              translate([Drad+14,10,0]) cylinder(h=NodeHeight+3,r=5,$fn=6);
            }
         }
      }
      drillHole(rad4);

      // drill hole to help allign fork linkage, must match linkage length below
      rotate([0,0,5]) translate([forkLen,0,0]) cylinder(h=3*NodeHeight,r=.6,$fn=6);
   }

  // diagnostic slice to examine walls
  //translate([0,-2,-2]) cube([4,44,33]);
}

// add other side of fork
//translate([-dLeft+0.7*forkLen,1.2*forkLen,0]) rotate([0,0,40])
//    forkTab(ForkHeight,Drad+2,rad4+1.4,forkLen);
}
//------------------------------------- end of imBEDmain

module BED1main(dLeft,dBase,dPerp) { //------------------------------------ BED
perpHeight = NodeHeight3; //3*TrueNodeHeight;  // same height as long hinge-pin
difference() { union() {
  difference() { union() {
     BEDrails(dLeft*.8,dPerp,.75*(dBase-dLeft),perpHeight,Brad);

     translate([-dLeft,0,0]) {
        rotate([0,0,5]) hull() {
           translate([0,0,NodeHeight+0.3]) forkTab(ForkHeight,Drad+2,rad4+1.4,forkLen-2);
           translate([NodeHeight, 0 , 0 ]) forkTab(    2     ,Drad+2,rad4+1.4,forkLen-2); }

        translate([dBase,0,0]) rotate([0,0,-5]) //difference() {
           hull() { translate([-4*Drad-4,-1,2]) sphere(r=2,$fn=12);
               cylinder(h=NodeHeight,r1=Drad+2, r2=Drad+1.8, $fn=48); }
           // hollow out hull a but...  injction mold style
           //#translate([0,0,-1.5]) { difference() { hull() {
           //    translate([-4*Drad+3,0,0]) cylinder(h=NodeHeight-1,r1=.4,r2=.2,$fn=6);
           //    cylinder(h=NodeHeight,r1=Drad-.1 ,r2=Drad-.4,$fn=24); }
           //    cylinder(h=NodeHeight,r1=Drad+1.7,r2=Drad+1.9,$fn=24); }}
       //}

     } // end translate
   } // union

   //translate([0,2,-1])
   //   BEDhull(dLeft*.8-3,dPerp-3,.75*(dBase-dLeft)-3,perpHeight-2,Drad-1);
   } // inner diff

   // main B-axis node cylinder
   translate([0,dPerp,0])
      cylinder(h=perpHeight,r1=Brad+2.4,r2=Brad+1.8,$fn=48);

   // more bracing for fork
   hull() {
     translate([-dLeft+8,0,0]) cylinder(r=3,h=NodeHeight+3,$fn=6);
     translate([-dLeft+17,11,0]) cylinder(r=2,h=1,$fn=6);
   }
   hull() {
     translate([-dLeft+1,-1.5,0]) cylinder(r=2,h=NodeHeight+3.5,$fn=6);
     translate([-dLeft+8,-1,0]) cylinder(r=3,h=NodeHeight+3,$fn=6);
     translate([-dLeft+21,0,0]) cylinder(r=2,h=1,$fn=6);
   }

   }   // end second union

   //------------- main holes/knock outs
   translate([0,dPerp,0])drillHole(BradFree+.2); // a little larger to move freely
   translate([(dBase-dLeft),0,0]) drillHole(Drad);

   // for Maxi version, drill hole in top half of "fork" node,
   // and knock out slot for in-plane CD linkage
   translate([-dLeft,0,0]) {

      translate([0,0,-.1]) {
         difference() { cube([28,33,2*(NodeHeight+.3)],center=true);
            hull() {
              translate([Drad+7,1,0]) cylinder(h=NodeHeight+.31,r=3,$fn=16);
              translate([Drad+9,-6,0]) cylinder(h=NodeHeight+3,r=5,$fn=6);
              translate([Drad+13.5,10,0]) cylinder(h=NodeHeight+3,r=8,$fn=6);
            }
         }
      }
      drillHole(rad4);

      // drill hole to help allign fork linkage, must match linkage length below
      rotate([0,0,5]) translate([forkLen,0,-1]) cylinder(h=3*NodeHeight,r=.8,$fn=6);
   }

  // diagnostic slice to examine walls
  //translate([0,-2,-2]) cube([4,44,33]);
}

// custom support
sW=0.41;  // support width
sH=4.4;  // support height
sH2=sH/2;
color("Cyan") union() {
/* stuff parallel to perimiter adhered too well
  translate([-28,1,sH2]) rotate([0,0,10]) cube([sW,8,sH],center=true);
  //translate([-29.5,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  translate([-31,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  //translate([-32.5,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  translate([-34,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  //translate([-35.5,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  translate([-37,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  translate([-36.5,-2.5,sH2]) rotate([0,0,40]) cube([sW,7,sH],center=true);
  translate([-36.5,2.5,sH2]) rotate([0,0,-40]) cube([sW,7,sH],center=true);
  translate([-30,-2.5,sH2]) rotate([0,0,10]) cube([8,sW,sH],center=true);
  translate([-31,3.5,sH2]) rotate([0,0,-10]) cube([8,sW,sH],center=true);
*/
  hull() {
    translate([-34,0,0]) cylinder(r1=3,r2=5,h=2,$fn=11);
    #translate([-29,0.5,0]) scale([1,5,1])
        cylinder(r1=.3,r2=1,h=2,$fn=6);
  }
  translate([-34,0,sH-1.5]) {
    translate([3.6,0,0]) cube([5,sW,2],center=true);
    for (a=[-30,30]) rotate([0,0,a]) translate([4,0,0]) cube([6,sW,3],center=true);
    for (a=[60:30:322]) rotate([0,0,a])
      translate([3,0,0]) cube([4,sW,3],center=true);
  }
}

}

module BEDmainFrame(dLeft,dPerp,dBase,perpHeight) union() {

  // main B-axis node cylinder
  translate([0,dPerp,0]) {
    linkNode(Brad+2.5,perpHeight,ar=3.5,off=-.2,dx= 3*Brad,dy=-3*Brad);
    linkNode(Brad+2.5,perpHeight,ar=3.5,off=-.2,dx=-3*Brad,dy=-3*Brad);
  }

  BEDmainRails(dLeft*.8,dPerp,.75*(dBase-dLeft),perpHeight,Brad);

  translate([-dLeft,0,0]) {
    rotate([0,0,5]) translate([0,0,NodeHeight+0.3])
        forkTabF(ForkHeight,Drad+2,rad4+1.4,forkLen);

    translate([dBase,0,0]) linkNode(Drad+2.2,NodeHeight,off=-.2,
       dx=-7*Drad,dy=-2);
  } // end translate

  // more bracing for fork
  hull() {
     translate([-dLeft+8,0,3.3]) scale([4,2,NodeHeight]) sphere(1,$fn=16);
     translate([-dLeft+16,11,1]) scale([1,1,2]) sphere(1,$fn=16);
  }
  hull() {
     translate([-dLeft+1,-1.5,NodeHeight+2.5]) sphere(2,$fn=24);
     translate([-dLeft+8,0,NodeHeight-1]) sphere(4,$fn=24);//cylinder(r=3,h=NodeHeight+3,$fn=6);
     translate([-dLeft+19,-1,-1]) scale([1,1,3]) sphere(1,$fn=16);
  }

}

module BEDmain(dLeft,dBase,dPerp) { //------------------------------------ BED
perpHeight = NodeHeight3; //3*TrueNodeHeight;  // same height as long hinge-pin
  difference() {
    BEDmainFrame(dLeft,dPerp,dBase,perpHeight);

    //------------- main holes/knock outs
    translate([0,dPerp,0])drillHole(BradFree+.2); // a little larger to move freely
    translate([(dBase-dLeft),0,0]) drillHole(Drad);

    // for Maxi version, drill hole in top half of "fork" node,
    // and knock out slot for in-plane CD linkage
    translate([-dLeft,0,0]) {

       translate([0,0,-.1]) {
         difference() { cube([28,33,2*(NodeHeight+.3)],center=true);
            hull() {
              translate([Drad+7,1,0]) cylinder(h=NodeHeight+.31,r=3,$fn=16);
              translate([Drad+9,-6,0]) cylinder(h=NodeHeight+3,r=5,$fn=6);
              translate([Drad+13.5,10,0]) cylinder(h=NodeHeight+3,r=8,$fn=6);
            }
         }
       }
       drillHole(rad4);

      // drill hole to help allign fork linkage, must match linkage length below
      rotate([0,0,5]) translate([forkLen,0,-1]) cylinder(h=3*NodeHeight,r=.8,$fn=6);
   }

  // diagnostic slice to examine walls
  //translate([0,-2,-2]) cube([4,44,33]);

    // chop off any junk below bottom
    translate([-dLeft-20,-20,-30]) cube([dBase+40,dPerp+40,30]);
  }

  color("Cyan") forkSupport(); // custom support
}

module forkSupport() {
sW=0.41;  // support width
sH=4.4;  // support height
sH2=sH/2;
  union() {
/* stuff parallel to perimiter adhered too well
  translate([-28,1,sH2]) rotate([0,0,10]) cube([sW,8,sH],center=true);
  //translate([-29.5,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  translate([-31,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  //translate([-32.5,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  translate([-34,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  //translate([-35.5,0,sH2]) rotate([0,0,5]) cube([sW,10,sH],center=true);
  translate([-37,0,sH2]) rotate([0,0,5]) cube([sW,9,sH],center=true);
  translate([-36.5,-2.5,sH2]) rotate([0,0,40]) cube([sW,7,sH],center=true);
  translate([-36.5,2.5,sH2]) rotate([0,0,-40]) cube([sW,7,sH],center=true);
  translate([-30,-2.5,sH2]) rotate([0,0,10]) cube([8,sW,sH],center=true);
  translate([-31,3.5,sH2]) rotate([0,0,-10]) cube([8,sW,sH],center=true);
*/
    hull() {
      translate([-34,0,0]) cylinder(r1=3,r2=5,h=2,$fn=11);
      #translate([-29,0.5,0]) scale([1,5,1])
          cylinder(r1=.3,r2=1,h=2,$fn=6);
    }
    translate([-34,0,sH-1.5]) {
      translate([3.6,0,0]) cube([5,sW,2],center=true);
      for (a=[-30,30]) rotate([0,0,a]) translate([4,0,0]) cube([6,sW,3],center=true);
      for (a=[60:30:322]) rotate([0,0,a])
        translate([3,0,0]) cube([4,sW,3],center=true);
    }
  }
}

//------------------------------------- end of BED1main

module imBED(dLeft,dBase,dPerp) { //------------------------------------ BED
imBEDmain(dLeft,dBase,dPerp);

// add other side of fork
translate([-dLeft+0.7*forkLen,1.2*forkLen,0]) rotate([0,0,40])
    forkTab(ForkHeight+.1,Drad+2,rad4+1.4,forkLen);
}

// Complete (Joined) version of BED, with in-place fork
module imBEDj(dLeft,dBase,dPerp) { //------------------------------------ BED
union() {
imBEDmain(dLeft,dBase,dPerp);

// add other side of fork, in place
translate([-dLeft,0,-.01]) { rotate([0,0,5]) {
    rotate([180,0,0]) forkTab(ForkHeight+.2,Drad+2,rad4+1.4,forkLen);

#hull(){
  translate([forkLen  ,0,0])cylinder(h=NodeHeight-2,r=2.8,$fn=12);
  translate([forkLen+1.5,4,1.1])sphere(r=1,$fn=6);
  translate([forkLen+2,0,0])cylinder(h=NodeHeight-2,r=2.2,$fn=12);}
}}

}}

//imBED(DEleft,DE,DEperp);

// version of BED intended for one-sided injection mold
module BED1(dLeft,dBase,dPerp) { //------------------------------------ BED
echo("BED1:",dLeft,dBase,dPerp);
BED1main(dLeft,dBase,dPerp);

// add other side of fork
//translate([-dLeft+0.7*forkLen,1.2*forkLen,0]) rotate([0,0,40])
translate([-10,8,0]) rotate([0,0,55])
    forkTab(ForkHeight+.1,Drad+2,rad4+1.4,forkLen);
}

module BED(dLeft,dBase,dPerp) { //------------------------------------ BED
//%BED1main(dLeft,dBase,dPerp);
BEDmain(dLeft,dBase,dPerp);

// add other side of fork
//translate([-dLeft+0.7*forkLen,1.2*forkLen,0]) rotate([0,0,40])
translate([-9,8,0]) rotate([0,0,55])
    forkTabF(ForkHeight+.1,Drad+2,rad4+1.4,forkLen);
}


model/Capture/JumpOffTrigger: Fix error introduced by RX changes

include <y-idler.h>

include <thing_libutils/materials.scad>
use <thing_libutils/screws.scad>

module yaxis_idler(part)
{
    tighten_screw_dia_outer = yaxis_idler_mount_tightscrew_dia*4;
    mount_screw_dist = (yidler_w/2+yaxis_idler_mount_thread_dia*3)*1.3;

    if(part==U)
    {
        difference()
        {
            yaxis_idler(part="pos");
            yaxis_idler(part="neg");
        }
        yaxis_idler(part="vit");
    }
    else if(part=="pos")
    material(Mat_Plastic)
    {
        // front plate
        tx(-extrusion_size/2)
        rcubea(
            size=[yaxis_idler_mount_thickness, yidler_mount_width, extrusion_size],
            align=-X,
            extra_size=Z*yaxis_idler_mount_thickness,
            extra_align=Z
            );

        // top mount plate
        translate([-yaxis_idler_mount_thickness,0,extrusion_size/2])
        rcubea(
            size=[extrusion_size, yidler_mount_width, yaxis_idler_mount_thickness],
            align=Z,
            extra_size=[yaxis_idler_mount_thickness,0,0],
            extra_align=X
            );

        intersection()
        {
            tz(extrusion_size/2)
            cubea([100, yidler_mount_width, 100], align=Z);

            hull()
            {
                for(y=[-1,1])
                ty(y*yaxis_idler_tightscrew_dist)
                tx(-yaxis_idler_mount_thickness)
                tz(extrusion_size/2)
                {
                    translate([yaxis_idler_mount_thickness/2,0,yaxis_belt_path_offset_z])
                    rcylindera(
                        h=extrusion_size+yaxis_idler_mount_thickness,
                        d=tighten_screw_dia_outer,
                        align=N,
                        orient=X
                        );
                    rcubea(
                        size=[extrusion_size, mount_screw_dist-yaxis_idler_mount_tightscrew_dia*3, yaxis_idler_mount_thickness],
                        align=Z,
                        extra_size=[yaxis_idler_mount_thickness,0,0],
                        extra_align=X
                        );
                }
            }

        }

    }
    else if(part=="neg")
    {
        // top/vertical mount screws (to extrusion)
        translate([0,0,extrusion_size/2+yaxis_idler_mount_thickness])
        for(y=[-1,0,1])
        ty(y*mount_screw_dist/2)
        screw_cut(nut=extrusion_nut, head="button", h=yaxis_idler_mount_thickness+5*mm, with_nut=false, orient=-Z, align=-Z);

        // mount screws for pulley block
        for(y=[-1,1])
        translate([
            -extrusion_size/2-yaxis_idler_mount_thickness,
            y*yaxis_idler_tightscrew_dist,
            extrusion_size/2+yaxis_belt_path_offset_z])
        screw_cut(yaxis_idler_mount_tightscrew_hexnut, head_embed=false, h=extrusion_size+yaxis_idler_mount_thickness+10*mm, with_nut=false, orient=X, align=X);

        // front/horizontal mount screws (to extrusion)
        tx(-extrusion_size/2)
        tx(-yaxis_idler_mount_thickness)
        for(y=[-1,1])
        ty(y*(yaxis_idler_mount_thread_dia*2.5))
        screw_cut(nut=extrusion_nut, head="button", h=yaxis_idler_mount_thickness+5*mm, with_nut=false, orient=X, align=X);
    }
}

module yaxis_idler_pulleyblock(part, show_pulley=false)
{
    h = yaxis_idler_pulley_h + 3*mm*2;
    if(part==U)
    {
        difference()
        {
            yaxis_idler_pulleyblock(part="pos");
            yaxis_idler_pulleyblock(part="neg");
        }
        %yaxis_idler_pulleyblock(part="vit");
    }
    else if(part=="pos")
    material(Mat_Plastic)
    {
        rcubea([yaxis_idler_pulleyblock_supportsize, 2*yaxis_idler_pulleyblock_supportsize, h],
            align=N,
            extra_size=[yaxis_idler_pulley_tight_len,0,0],
            extra_align=[-1,0,0]
            );
    }
    else if(part=="neg")
    {
        // pulley cutout
        tx(-3*mm)
        cubea(
            size=[yaxis_idler_pulley_outer_d, yaxis_idler_pulley_outer_d*3, yaxis_idler_pulley_h+0.5],
            align=N,
            extra_size=[20*mm,0,0], extra_align=X
            );

        // pulley screw
        tz(h/2)
        screw_cut(yaxis_idler_pulley_nut, head="button", h=h+5*mm, orient=-Z, align=-Z);

        /*cylindera(d=yaxis_idler_pulley_thread_dia, h=h*2, orient=Z, align=N);*/

        for(y=[-1,1])
        translate([
            -yaxis_idler_pulleyblock_supportsize/2-yaxis_idler_pulley_tight_len,
            y*yaxis_idler_tightscrew_dist,
            0
        ])
        screw_cut(yaxis_idler_mount_tightscrew_hexnut, head_embed=true, nut_offset=5*mm, h=yaxis_idler_pulley_tight_len, orient=X, align=X);
    }
    else if(part=="vit")
    {
        pulley(pulley_2GT_20T_idler);
    }

}

module part_y_idler()
{
    attach([N, [0,0,-1]], yaxis_idler_conn)
    {
        yaxis_idler();
    }
}

module part_y_idler_pulleyblock()
{
    attach([N, [0,0,-1]], yaxis_idler_pulleyblock_conn_print)
    {
        yaxis_idler_pulleyblock(show_pulley=false);
    }
}

/*yaxis_idler();*/
/*yaxis_idler_pulleyblock();*/

/*print_yaxis_idler();*/
/*print_yaxis_idler_pulleyblock();*/

/*attach([N,[-1,0,0]], yaxis_idler_conn)*/
/*{*/
    /*yaxis_idler();*/
    /*attach(yaxis_idler_conn_pulleyblock, yaxis_idler_pulleyblock_conn)*/
    /*{*/
        /*yaxis_idler_pulleyblock(show_pulley=true);*/
    /*}*/
/*}*/

include <y-idler.h>

include <thing_libutils/materials.scad>
use <thing_libutils/screws.scad>

module yaxis_idler(part)
{
    tighten_screw_dia_outer = yaxis_idler_mount_tightscrew_dia*4;
    mount_screw_dist = (yidler_w/2+yaxis_idler_mount_thread_dia*3)*1.3;

    if(part==U)
    {
        difference()
        {
            yaxis_idler(part="pos");
            yaxis_idler(part="neg");
        }
        yaxis_idler(part="vit");
    }
    else if(part=="pos")
    material(Mat_Plastic)
    {
        // front plate
        tx(-extrusion_size/2)
        rcubea(
            size=[yaxis_idler_mount_thickness, yidler_mount_width, extrusion_size],
            align=-X,
            extra_size=Z*yaxis_idler_mount_thickness,
            extra_align=Z
            );

        // top mount plate
        translate([-yaxis_idler_mount_thickness,0,extrusion_size/2])
        rcubea(
            size=[extrusion_size, yidler_mount_width, yaxis_idler_mount_thickness],
            align=Z,
            extra_size=[yaxis_idler_mount_thickness,0,0],
            extra_align=X
            );

        intersection()
        {
            tz(extrusion_size/2)
            cubea([100, yidler_mount_width, 100], align=Z);

            hull()
            {
                for(y=[-1,1])
                ty(y*yaxis_idler_tightscrew_dist)
                tx(-yaxis_idler_mount_thickness)
                tz(extrusion_size/2)
                {
                    translate([yaxis_idler_mount_thickness/2,0,yaxis_belt_path_offset_z])
                    rcylindera(
                        h=extrusion_size+yaxis_idler_mount_thickness,
                        d=tighten_screw_dia_outer,
                        align=N,
                        orient=X
                        );
                    rcubea(
                        size=[extrusion_size, mount_screw_dist-yaxis_idler_mount_tightscrew_dia*3, yaxis_idler_mount_thickness],
                        align=Z,
                        extra_size=[yaxis_idler_mount_thickness,0,0],
                        extra_align=X
                        );
                }
            }

        }

    }
    else if(part=="neg")
    {
        // top/vertical mount screws (to extrusion)
        translate([0,0,extrusion_size/2+yaxis_idler_mount_thickness])
        for(y=[-1,0,1])
        ty(y*mount_screw_dist/2)
        screw_cut(nut=extrusion_nut, head="button", h=yaxis_idler_mount_thickness+5*mm, with_nut=false, orient=-Z, align=-Z);

        // mount screws for pulley block
        for(y=[-1,1])
        translate([
            -extrusion_size/2-yaxis_idler_mount_thickness,
            y*yaxis_idler_tightscrew_dist,
            extrusion_size/2+yaxis_belt_path_offset_z])
        screw_cut(yaxis_idler_mount_tightscrew_hexnut, head_embed=false, h=extrusion_size+yaxis_idler_mount_thickness+10*mm, with_nut=false, orient=X, align=X);

        // front/horizontal mount screws (to extrusion)
        tx(-extrusion_size/2)
        tx(-yaxis_idler_mount_thickness)
        for(y=[-1,1])
        ty(y*(yaxis_idler_mount_thread_dia*2.5))
        screw_cut(nut=extrusion_nut, head="button", h=yaxis_idler_mount_thickness+5*mm, with_nut=false, orient=X, align=X);
    }
}

module yaxis_idler_pulleyblock(part, show_pulley=false)
{
    h = yaxis_idler_pulley_h + 3*mm*2;
    if(part==U)
    {
        difference()
        {
            yaxis_idler_pulleyblock(part="pos");
            yaxis_idler_pulleyblock(part="neg");
        }
        %yaxis_idler_pulleyblock(part="vit");
    }
    else if(part=="pos")
    material(Mat_Plastic)
    {
        rcubea([yaxis_idler_pulleyblock_supportsize, 2*yaxis_idler_pulleyblock_supportsize, h],
            align=N,
            extra_size=[yaxis_idler_pulley_tight_len,0,0],
            extra_align=[-1,0,0]
            );
    }
    else if(part=="neg")
    {
        // pulley cutout
        tx(-3*mm)
        cubea(
            size=[yaxis_idler_pulley_outer_d, yaxis_idler_pulley_outer_d*3, yaxis_idler_pulley_h+0.5],
            align=N,
            extra_size=[20*mm,0,0], extra_align=X
            );

        // pulley screw
        tz(h/2)
        screw_cut(yaxis_idler_pulley_nut, head="button", h=h+5*mm, orient=[0,0,-1], align=[0,0,-1]);

        cylindera(d=yaxis_idler_pulley_thread_dia, h=h*2, orient=Z, align=N);

        for(y=[-1,1])
        translate([
            -yaxis_idler_pulleyblock_supportsize/2-yaxis_idler_pulley_tight_len,
            y*yaxis_idler_tightscrew_dist,
            0
        ])
        screw_cut(yaxis_idler_mount_tightscrew_hexnut, head_embed=true, nut_offset=5*mm, h=yaxis_idler_pulley_tight_len, orient=X, align=X);
    }
    else if(part=="vit")
    {
        pulley(pulley_2GT_20T_idler);
    }

}

module part_y_idler()
{
    attach([N, [0,0,-1]], yaxis_idler_conn)
    {
        yaxis_idler();
    }
}

module part_y_idler_pulleyblock()
{
    attach([N, [0,0,-1]], yaxis_idler_pulleyblock_conn_print)
    {
        yaxis_idler_pulleyblock(show_pulley=false);
    }
}

/*yaxis_idler();*/
/*yaxis_idler_pulleyblock();*/

/*print_yaxis_idler();*/
/*print_yaxis_idler_pulleyblock();*/

/*attach([N,[-1,0,0]], yaxis_idler_conn)*/
/*{*/
    /*yaxis_idler();*/
    /*attach(yaxis_idler_conn_pulleyblock, yaxis_idler_pulleyblock_conn)*/
    /*{*/
        /*yaxis_idler_pulleyblock(show_pulley=true);*/
    /*}*/
/*}*/


Create module and try to get projection Reduce resolution to get circles instead of polygons

module tender()
{
difference(){
	cube(size=[20, 40, thickness], center=true);
	translate([2, 0, 0]) cylinder(r=2.5, h=thickness, center = true);
		translate([0-4, 1, 0]) rotate([0,0, -20]) cube(size=[15, 3, thickness], center=true);
		translate([0+2, 12, 0]) cylinder(r=2.5, h=thickness, center = true);
		translate([0-4, 12+1, 0]) rotate([0,0, -20]) cube(size=[15, 3, thickness], center=true);
		translate([0+2, -12, 0]) cylinder(r=2.5, h=thickness, center = true);
		translate([0-4, -12-1, 0]) rotate([0,0, 20]) cube(size=[15, 3, thickness], center=true);
		translate([0-5, -6, 0]) cylinder(r=2.5, h=thickness, center = true);

	}
}

module mobile_support()
{
	width = 97; // External width (except clipping mechanism)
	height = 146; // External height (except clipping mechanism)
	corner_radius = 14; // Round corner at the bottom corners
	top_width = 114; // Clipping mechanism width
	top_height = 20; // Clipping mechanism height
	thickness = 5; // Thickness
	clip_height = 14;

	//Main pocket
	difference()
	{
		union(){
			cube(size = [width,height,thickness], center = true);
			difference(){
				translate([-width/2, 0,0]) cylinder(r=20, h=thickness, center = true, $fs=0.03);
				translate([-width/2-5, 0,0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
				translate([-width/2-1.5, -10,0]) cube(size =[3,26,thickness], center = true);
			}
			difference(){
				translate([width/2, 0,0]) cylinder(r=20, h=thickness, center = true, $fs=0.03);
				translate([width/2+5, 0,0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
				translate([width/2+1.5, -10,0]) cube(size =[3,26,thickness], center = true);
	}
		}
		cube(size = [width-20,height-24,thickness], center = true);
	}

	// Existing top clip
	//translate([0, height/2 + top_height/2, 0]) cube(size = [top_width,top_height,thickness], center = true);

	clip_width = width +20;
	// Top clip support
	difference(){
		translate([0, height/2 - clip_height/2, 0]) cube(size = [clip_width+20, clip_height, thickness], center = true);
	// Holes for the clip
		translate([-clip_width/2+7, height/2- clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
		translate([+clip_width/2-7, height/2- clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
	// Holes to attach a line
		translate([-clip_width/2-3, height/2- clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
		translate([+clip_width/2+3, height/2- clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
	}

	// Top clip
	difference()
	{
		translate([-clip_height/2-1, 0 , 0]) cube(size = [clip_height, clip_width, thickness], center = true);
		translate([-clip_height/2-1, clip_width/2-7, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
		translate([-clip_height/2-1, -clip_width/2+7, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
	}

	// Bottom clip support
	difference(){
		translate([0, -height/2+clip_height/2, 0]) cube(size = [clip_width+20, clip_height, thickness], center = true);
		translate([-clip_width/2+7, -height/2+ clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
		translate([+clip_width/2-7, -height/2+ clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
		translate([-clip_width/2-3, -height/2+ clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
		translate([+clip_width/2+3, -height/2+ clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
	}
	// Bottom clip
	difference(){
	 translate([clip_height/2+1, 0, 0]) cube(size = [clip_height, clip_width, thickness], center = true);
		translate([clip_height/2+1, clip_width/2-7, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
		translate([clip_height/2+1, -clip_width/2+7, 0]) cylinder(r=2.5, h=thickness, center = true, $fs=0.03);
	}
	translate([clip_width/4-2,clip_width/4,0]) tender();
	translate([clip_width/4-2,-clip_width/4,0]) tender();
	translate([-clip_width/4+2,-clip_width/4,0]) tender();
	translate([-clip_width/4+2,clip_width/4,0]) tender();
}

projection() mobile_support();

width = 97; // External width (except clipping mechanism)
height = 146; // External height (except clipping mechanism)
corner_radius = 14; // Round corner at the bottom corners
top_width = 114; // Clipping mechanism width
top_height = 20; // Clipping mechanism height
thickness = 5; // Thickness
clip_height = 14;

//Main pocket
difference()
{
	union(){
		cube(size = [width,height,thickness], center = true);
		difference(){
			translate([-width/2, 0,0]) cylinder(r=20, h=thickness, center = true);
			translate([-width/2-5, 0,0]) cylinder(r=2.5, h=thickness, center = true);
			translate([-width/2-1.5, -10,0]) cube(size =[3,26,thickness], center = true);
		}
		difference(){
			translate([width/2, 0,0]) cylinder(r=20, h=thickness, center = true);
			translate([width/2+5, 0,0]) cylinder(r=2.5, h=thickness, center = true);
			translate([width/2+1.5, -10,0]) cube(size =[3,26,thickness], center = true);
}
	}
	cube(size = [width-20,height-24,thickness], center = true);
}

// Existing top clip
//translate([0, height/2 + top_height/2, 0]) cube(size = [top_width,top_height,thickness], center = true);

clip_width = width +20;
// Top clip support
difference(){
	translate([0, height/2 - clip_height/2, 0]) cube(size = [clip_width, clip_height, thickness], center = true);
	translate([-clip_width/2+7, height/2- clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true);
	translate([+clip_width/2-7, height/2- clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true);
}

// Top clip
difference()
{
	translate([-clip_height/2-1, 0 , 0]) cube(size = [clip_height, clip_width, thickness], center = true);
	translate([-clip_height/2-1, clip_width/2-7, 0]) cylinder(r=2.5, h=thickness, center = true);
	translate([-clip_height/2-1, -clip_width/2+7, 0]) cylinder(r=2.5, h=thickness, center = true);
}

// Bottom clip support
difference(){
	translate([0, -height/2+clip_height/2, 0]) cube(size = [clip_width, clip_height, thickness], center = true);
	translate([-clip_width/2+7, -height/2+ clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true);
	translate([+clip_width/2-7, -height/2+ clip_height/2, 0]) cylinder(r=2.5, h=thickness, center = true);
}
// Bottom clip
difference(){
 translate([clip_height/2+1, 0, 0]) cube(size = [clip_height, clip_width, thickness], center = true);
	translate([clip_height/2+1, clip_width/2-7, 0]) cylinder(r=2.5, h=thickness, center = true);
	translate([clip_height/2+1, -clip_width/2+7, 0]) cylinder(r=2.5, h=thickness, center = true);
}

module tender()
{
difference(){
	cube(size=[20, 40, thickness], center=true);
	translate([2, 0, 0]) cylinder(r=2.5, h=thickness, center = true);
		translate([0-4, 1, 0]) rotate([0,0, -20]) cube(size=[15, 3, thickness], center=true);
		translate([0+2, 12, 0]) cylinder(r=2.5, h=thickness, center = true);
		translate([0-4, 12+1, 0]) rotate([0,0, -20]) cube(size=[15, 3, thickness], center=true);
		translate([0+2, -12, 0]) cylinder(r=2.5, h=thickness, center = true);
		translate([0-4, -12-1, 0]) rotate([0,0, 20]) cube(size=[15, 3, thickness], center=true);
		translate([0-5, -6, 0]) cylinder(r=2.5, h=thickness, center = true);

	}
}
translate([clip_width/4-2,clip_width/4,0]) tender();
translate([clip_width/4-2,-clip_width/4,0]) tender();
translate([-clip_width/4+2,-clip_width/4,0]) tender();
translate([-clip_width/4+2,clip_width/4,0]) tender();