// To adjust the fit of the slider in the cover, the cut out for the slider
// is scaled fit times larger than the actual slider itself.  For a
// looser fit, increase fit_scale and decrease fit for a tighter fit.

fit = 1.02;

a  = 0.5; // Allowance to add to diameters for a "loose" fit
rd = ( 3 / 8 ) * 25.4;  // Diameter of the linear axis rods (3/8 inch)

l  = 28; // Rod cover's width x height
t  =  6; // Rod cover's thickness 
sp = 20; // Screw hole spacing on center
sd =  3; // M3 bolt diameter
cd =  6; // M3 bolt cap diameter

// Width of the slot to cut in the cover
sw = rd + 4*a;

$fn = 50;

// --- from MCAD/boxes.scad
module roundedBox(size, radius, sidesonly)
{
     rot = [ [0,0,0], [90,0,90], [90,90,0] ];
     if (sidesonly) {
	  cube(size - [2*radius,0,0], true);
	  cube(size - [0,2*radius,0], true);
	  for (x = [radius-size[0]/2, -radius+size[0]/2],
	       y = [radius-size[1]/2, -radius+size[1]/2]) {
	       translate([x,y,0]) cylinder(r=radius, h=size[2], center=true);
	  }
     }
     else {
	  cube([size[0], size[1]-radius*2, size[2]-radius*2], center=true);
	  cube([size[0]-radius*2, size[1], size[2]-radius*2], center=true);
	  cube([size[0]-radius*2, size[1]-radius*2, size[2]], center=true);

	  for (axis = [0:2]) {
	       for (x = [radius-size[axis]/2, -radius+size[axis]/2],
		    y = [radius-size[(axis+1)%3]/2, -radius+size[(axis+1)%3]/2]) {
		    rotate(rot[axis])
			 translate([x,y,0])
			     cylinder(h=size[(axis+2)%3]-2*radius, r=radius, center=true);
	       }
	  }
	  for (x = [radius-size[0]/2, -radius+size[0]/2],
	       y = [radius-size[1]/2, -radius+size[1]/2],
	       z = [radius-size[2]/2, -radius+size[2]/2]) {
	       translate([x,y,z]) sphere(radius);
	  }
     }
}

// --------------------------

// Slider portion of the end cap

module endcap_slider(grips=true) {
     difference() {
	  union() {
	       translate([0, 0, -t/2]) cylinder(r = (rd + a)/2, h=t);
	       translate([0, l/4, -t/4]) cube([(rd + a), l/2, t/2], center=true);
	       intersection() {
		    cube([sw*2, l, t], center=true);
		    // Dovetail finger with 1:4 ratio
		    translate([0, -a, 0])
			 rotate([90, 0, 0])
			     linear_extrude(h = l + 2*a, center=true, convexity=0, twist=0)
			         polygon(points=[[-(sw+t/6)/2, 0], [0, 3*sw + t/2], [(sw+t/6)/2, 0],
						 [-(sw+t/6)/2, 0]]);
	       }
	  }

	  // Gripping slot and hole
	  if (grips) {
	       translate([0, l/2 - 5, -t]) cylinder(r=2, h=2*t);
	       translate([0, l/4 + 1, 0])
		    rotate([0, -90, 0])
		        linear_extrude(h=l + 2*a, center=true, convexity=0, twist=0)
		            polygon(points=[[0, 0], [10, 0], [0, 3], [0, 0]]);
	  }
     }
}

// Fit adjusts how much bigger the slider slot: scale(fit) slider()

module endcap_base(fit=1.02) {
     difference() {
	  roundedBox([l, l, t], 2, true);

	  // Hole for axis rod
	  translate([0, 0, -t]) cylinder(r=(rd+a)/2, h=2*t);

	  // Slider
	  scale(fit) endcap_slider(false);

	  // Screw holes
	  translate([ sp/2,  sp/2, -t]) cylinder(r = (sd+a)/2, h = 2*t);
	  translate([ sp/2, -sp/2, -t]) cylinder(r = (sd+a)/2, h = 2*t);
	  translate([-sp/2, -sp/2, -t]) cylinder(r = (sd+a)/2, h = 2*t);
	  translate([-sp/2,  sp/2, -t]) cylinder(r = (sd+a)/2, h = 2*t);

	  // Screw cap holes
	  translate([ sp/2,  sp/2, 0]) cylinder(r = (cd+a)/2, h = t);
	  translate([ sp/2, -sp/2, 0]) cylinder(r = (cd+a)/2, h = t);
	  translate([-sp/2, -sp/2, 0]) cylinder(r = (cd+a)/2, h = t);
	  translate([-sp/2,  sp/2, 0]) cylinder(r = (cd+a)/2, h = t);

	  // Dovetail slot with 1:4 ratio
	  translate([0, -a, 0])
	       rotate([90, 0, 0])
	           linear_extrude(h = l + 2*a, center=true, convexity=0, twist=0)
	               polygon(points=[[-(sw+t/6)/2, 0], [0, 3*sw + t/2], [(sw+t/6)/2, 0],
				       [-(sw+t/6)/2, 0]]);
    }
}

translate([0, 0.50 * l, t/2]) endcap_base(fit);
translate([0, -0.35 * l, t/2]) rotate([0, 180, 90]) endcap_slider();
