Add module `section` to shape utils

Add module `section` to shape utils

// moreShapes library
// 2D and 3D utility shape functions

// some borrowed from nophead / Mendel90 utils.scad

// fudge
eta = 0.01;

module line(start, end, r) {
	hull() {
		translate(start) sphere(r=r);
		translate(end) sphere(r=r);
	}
}

module roundedSquare(size, radius, center=false, shell=0) {
    x = size[0];
	y = size[1];

	translate([center?-x/2:0, center?-y/2:0, 0])
	difference() {
		hull() {
			translate([radius, radius, 0])
			circle(r=radius);

			translate([x - radius, radius, 0])
			circle(r=radius);

			translate([x - radius, y - radius, 0])
			circle(r=radius);

			translate([radius, y - radius, 0])
			circle(r=radius);
		}

		if (shell > 0) {
			hull() {
			translate([radius + shell, radius + shell, 0])
			circle(r=radius);

			translate([x - radius - shell, radius + shell, 0])
			circle(r=radius);

			translate([x - radius - shell, y - radius - shell, 0])
			circle(r=radius);

			translate([radius + shell, y - radius - shell, 0])
			circle(r=radius);
		}
		}
	}
}

module roundedRect(size, radius, center=false, shell=0) {
	z = size[2];

	translate([0, 0, center?-z/2:0])
	    linear_extrude(height=z)
	    roundedSquare(size=size, radius=radius, center=center, shell=shell);
}

module roundedRectX(size, radius, center=false, shell=0) {
	// X-axis aligned roundedRect
	translate([0,0,center?0:size[2]]) rotate([0,90,0]) roundedRect([size[2],size[1],size[0]], radius, center, shell);
}

module roundedRectY(size, radius, center=false, shell=0) {
	// Y-axis aligned roundedRect
	translate([0,0,center?0:size[2]]) rotate([-90,0,0]) roundedRect([size[0],size[2],size[1]], radius, center, shell);
}

module allRoundedRect(size, radius, center=false) {
	// lazy implementation - must do better
	// runs VERY slow
	translate([center?-size[0]/2:0, center?-size[1]/2:0, center?-size[2]/2:0])
	hull() {
		for (x=[0,size[0]], y=[0,size[1]], z=[0,size[2]]) {
			translate([x,y,z]) sphere(r=radius);
		}
	}
}

module chamferedSquare(size, chamfer, center=false) {
	hull() {
		translate([0,center?0:chamfer,0])
			square([size[0],size[1]-2*chamfer],center);

		translate([center?0:chamfer,0,0])
			square([size[0]-2*chamfer,size[1]],center);
	}
}

module chamferedCube(size, chamfer, center=false) {
	translate([0,0, center ? -size[2]/2 : 0])
		linear_extrude(size[2])
		chamferedSquare(size, chamfer, center=center);
}

// show cross section along axis (x)
module section()
{
    // TODO: optionally pass in vector and size
    size=1000;
    difference() {
        children();

        color("white")
        translate([0, -size/2, 0])
            cube(size, center=true);
    }
}

// Extended rotational extrude, allows control of start/end angle

// Child 2D shape is used for the rotational extrusion
// Child 2D shape should lie in xy plane, centred on z axis
// Child y axis will be aligned to z axis in the extrusion

// NB: Internal render command is necessary to correclty display
// complex child objects (e.g. differences)

// r = Radius of rotational extrusion
// childH = height of child object (approx)
// childW = width of child object (approx)

// Example usage:

//   rotate_extrude_ext(r=50, childW=20, childH=20, start_angle=0, end_angle=180) {
//			difference() {
//				square([20,20],center=true);
//				translate([10,0,0]) circle(5);
//			}
//		}

module rotate_extrude_ext(r, childW, childH, convexity) {
	or = (r + childW/2) * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    if(end_angle > start_angle)
		render()
        intersection() {
			rotate_extrude(convexity=convexity) translate([r,0,0]) children(0);

			translate([0,0,-childH/2 - 1])
			linear_extrude(height=childH+2)
        		polygon([
		            [0,0],
		            [or * cos(a0), or * sin(a0)],
		            [or * cos(a1), or * sin(a1)],
		            [or * cos(a2), or * sin(a2)],
		            [or * cos(a3), or * sin(a3)],
		            [or * cos(a4), or * sin(a4)],
		            [0,0]
		       ]);
    }
}

module torusSlice(r1, r2, start_angle, end_angle, convexity=10, r3=0, $fn=64) {
	difference() {
		rotate_extrude_ext(r=r1, childH=2*r2, childW=2*r2, start_angle=start_angle, end_angle=end_angle, convexity=convexity) difference() circle(r2, $fn=$fn/4);

		rotate_extrude(convexity) translate([r1,0,0]) circle(r3, $fn=$fn/4);
	}
}

module torus(r1, r2, $fn=64) {
	rotate_extrude()
		translate([r1,0,0])
		circle(r2, $fn=$fn/4);
}

module trapezoid(a,b,h,aOffset=0,center=false) {
	// lies in x/y plane
	// edges a,b are parallel to x axis
	// h is in direction of y axis
	// b is anchored at origin, extends along positive x axis
	// a is offset along y by h, extends along positive x axis
	// a if offset along x axis, from y axis, by aOffset
	// centering is relative to edge b

	translate([center?-b/2:0, center?-h/2:0, 0])
	polygon(points=[	[0,0],
					[aOffset,h],
					[aOffset + a, h],
					[b,0]]);
}

module trapezoidPrism(a,b,h,aOffset,height,center=false) {
	translate([0,0, center?-height/2:0]) linear_extrude(height=height) trapezoid(a,b,h,aOffset,center);
}

module arrangeShapesOnAxis(axis=[1,0,0], spacing=50) {
	for (i=[0:$children-1]) {
		translate([spacing * axis[0] *i,
					spacing * axis[1]*i,
					spacing * axis[2]*i]) children(i);
	}
}

module arrangeShapesOnGrid(xSpacing=50, ySpacing=50, cols=3, showLocalAxes=false) {
	// layout is cols, rows
	for (i=[0:$children-1]) {
		translate([(i - floor(i / cols)*cols) * xSpacing, floor(i / cols) * ySpacing, 0]) {
			children(i);

			if (showLocalAxes) {
				color("red") line([0,0,0], [xSpacing/2,0,0], 0.2);
				color("green") line([0,0,0], [0, ySpacing/2,0], 0.2);
				color("blue") line([0,0,0], [0, 0,xSpacing], 0.2);
			}
		}
	}
}

module slot(h, r, l, center = true)
    linear_extrude(height = h, convexity = 6, center = center)
        hull() {
            translate([l/2,0,0])
                circle(r = r, center = true);
            translate([-l/2,0,0])
                circle(r = r, center = true);
        }

module fillet(r, h) {
	// ready to be unioned onto another part, eta fudge included
	// extends along x, y, z

    translate([r / 2, r / 2, 0])
        difference() {
            cube([r + eta, r + eta, h], center = true);
            translate([r/2, r/2, 0])
                cylinder(r = r, h = h + 1, center = true);
        }
}

module right_triangle_2d(width,height,center=true) {
    polygon(points = [[0,0], [width, 0], [0, height]]);
}

module right_triangle(width, height, h, center = true) {
    linear_extrude(height = h, center = center)
        right_triangle_2d(width,height,center=center);
}

module roundedRightTriangle(width, height, h, r=[1,1,1], center = true, $fn=12) {
    linear_extrude(height = h, center = center)
    	hull() {
        	translate([r[0],r[0],0]) circle(r[0]);
        	translate([width-r[1],r[1],0]) circle(r[1]);
        	translate([r[2],height-r[2],0]) circle(r[2]);
        }
}

module rounded_square(w, h, r, center=true)
{
	// 2D
    union() {
        translate([center?0:r,0,0])
        	square([w - 2 * r, h], center=center);
        translate([0,center?0:r,0])
        	square([w, h - 2 * r], center=center);
        for(x = [(center?-w/2:0) + r, (center?w/2:w) - r])
            for(y = [(center?-h/2:0) + r, (center?h/2:h) - r])
                translate([x, y])
                    circle(r = r);
    }
}

//
// Cylinder with rounded ends
//
module rounded_cylinder(r, h, r2, roundBothEnds=false)
{
    rotate_extrude()
        union() {
            square([r - r2, h]);
            translate([0,roundBothEnds?r2:0,0]) square([r, roundBothEnds? h-2*r2 : h - r2]);
            translate([r - r2, h - r2])
                circle(r = r2);
			if (roundBothEnds) {
				translate([r - r2, r2])
                circle(r = r2);
			}

        }
}

module sector(r, a, h, center = true) {
    linear_extrude(height = h, center = center)
        sector2D(r=r, a=a, center=center);
}

module sector2D(r, a, center = true) {
    intersection() {
            circle(r = r, center = true);
                polygon(points = [
                    [0, 0],
                    [2 * r * cos(0),  2 * r * sin(0)],
                    [2 * r * cos(a * 0.2),  2 * r * sin(a * 0.2)],
                    [2 * r * cos(a * 0.4),  2 * r * sin(a * 0.4)],
                    [2 * r * cos(a * 0.6),  2 * r * sin(a * 0.6)],
                    [2 * r * cos(a * 0.8),  2 * r * sin(a * 0.8)],
                    [2 * r * cos(a), 2 * r * sin(a)],
                ]);
        }
}

module donutSector2D(or,ir,a, center=true) {
	difference() {
		sector2D(or,a,center);

		circle(ir);
	}

}

module tube(or, ir, h, center = true) {
    linear_extrude(height = h, center = center, convexity = 5)
        difference() {
            circle(or);
            circle(ir);
        }
}

// tube that tapers
module conicalTube(or1,ir1,or2,ir2,h) {
	difference() {
		cylinder(r1=or1, r2=or2, h=h);

		translate([0,0,-eta])
			cylinder(r1=ir1, r2=ir2, h=h+2*eta);
	}
}

module moreShapesExamples() {
	arrangeShapesOnGrid(xSpacing=100, ySpacing=80, cols=4, showLocalAxes=true) {
		roundedRect([50,30,20], 5);
		roundedRectX([50,30,20], 5);
		roundedRectY([50,30,20], 5);
		//allRoundedRect([50,30,20], 5);

		roundedRect([50,30,20], 5, true);
		roundedRectX([50,30,20], 5, true);
		roundedRectY([50,30,20], 5, true);
		//allRoundedRect([50,30,20], 5, true);

		torusSlice(50, 6, 0, 120, $fn=64);
		torusSlice(r1=50, r2=6, r3=4, start_angle=0, end_angle=120, $fn=64);   // define r3 for a hollow torus

		trapezoidPrism(20,50,20,10,20);
		trapezoidPrism(20,50,20,10,20,true);

		// to be differenced
		slot(h=20, r=5, l=10);

		// to be unioned
		fillet(r=5, h=50);

		right_triangle(width=30, height=20, h=10, center = false);
		rounded_square(w=30, h=20, r=5);
		rounded_cylinder(r=10, h=50, r2=5, roundBothEnds=false);
		rounded_cylinder(r=10, h=50, r2=5, roundBothEnds=true);

		// same as extruded pieSlice
		sector(r=10, a=70, h=20, center = false);

		tube(or=10, ir=5, h=50, center = false);

		rotate_extrude_ext(r=50, childW=20, childH=20, start_angle=0, end_angle=180) {
			difference() {
				square([20,20],center=true);
				translate([10,0,0]) circle(5);
			}
		}
	}
}

*moreShapesExamples();

module overhangFreeCircle(r, ang) {
	// produces a circle with no overhang ready for extrusion
	// overhang infill is along y axis

	x1 = r*cos(ang);
	y1 = r*sin(ang);
	x2 = tan(ang) * (r-y1);

	union() {
		circle(r);

		for (i=[0,1])
			mirror([0,i,0])
			polygon(points=[[0,0],[x1,y1],[x1-x2,r],[-x1+x2,r],[-x1,y1]]);
	}
}

// supports span x axis
module minSupportBeam(size=[0,0,0], bridge=5, air=0, center=false) {
	w = size[0] > bridge ? (size[0] - bridge)/2 : 0;
	h = w > air ? air : w;

	union() {
		cube(size, center=center);

		// triangular supports
		for (i=[0,1])
			translate([i*size[0],0,eta])
			mirror([i,0,0]) {
				translate([w-h, 0, 0])
					rotate([-90,0,0])
					right_triangle(h, h, size[1], center=false);

				translate([0, 0, -h])
					cube([w-h+eta, size[1], h+eta]);

			}
	}
}

module minSupportBeamY(size=[0,0,0], bridge=5, air=0, center=false) {
	translate([size[0], 0, 0])
		rotate([0,0,90])
		minSupportBeam([size[1], size[0], size[2]], bridge, air, center=center);
}

// moreShapes library
// 2D and 3D utility shape functions

// some borrowed from nophead / Mendel90 utils.scad

// fudge
eta = 0.01;

module line(start, end, r) {
	hull() {
		translate(start) sphere(r=r);
		translate(end) sphere(r=r);
	}
}

module roundedSquare(size, radius, center=false, shell=0) {
    x = size[0];
	y = size[1];

	translate([center?-x/2:0, center?-y/2:0, 0])
	difference() {
		hull() {
			translate([radius, radius, 0])
			circle(r=radius);

			translate([x - radius, radius, 0])
			circle(r=radius);

			translate([x - radius, y - radius, 0])
			circle(r=radius);

			translate([radius, y - radius, 0])
			circle(r=radius);
		}

		if (shell > 0) {
			hull() {
			translate([radius + shell, radius + shell, 0])
			circle(r=radius);

			translate([x - radius - shell, radius + shell, 0])
			circle(r=radius);

			translate([x - radius - shell, y - radius - shell, 0])
			circle(r=radius);

			translate([radius + shell, y - radius - shell, 0])
			circle(r=radius);
		}
		}
	}
}

module roundedRect(size, radius, center=false, shell=0) {
	z = size[2];

	translate([0, 0, center?-z/2:0])
	    linear_extrude(height=z)
	    roundedSquare(size=size, radius=radius, center=center, shell=shell);
}

module roundedRectX(size, radius, center=false, shell=0) {
	// X-axis aligned roundedRect
	translate([0,0,center?0:size[2]]) rotate([0,90,0]) roundedRect([size[2],size[1],size[0]], radius, center, shell);
}

module roundedRectY(size, radius, center=false, shell=0) {
	// Y-axis aligned roundedRect
	translate([0,0,center?0:size[2]]) rotate([-90,0,0]) roundedRect([size[0],size[2],size[1]], radius, center, shell);
}

module allRoundedRect(size, radius, center=false) {
	// lazy implementation - must do better
	// runs VERY slow
	translate([center?-size[0]/2:0, center?-size[1]/2:0, center?-size[2]/2:0])
	hull() {
		for (x=[0,size[0]], y=[0,size[1]], z=[0,size[2]]) {
			translate([x,y,z]) sphere(r=radius);
		}
	}
}

module chamferedSquare(size, chamfer, center=false) {
	hull() {
		translate([0,center?0:chamfer,0])
			square([size[0],size[1]-2*chamfer],center);

		translate([center?0:chamfer,0,0])
			square([size[0]-2*chamfer,size[1]],center);
	}
}

module chamferedCube(size, chamfer, center=false) {
	translate([0,0, center ? -size[2]/2 : 0])
		linear_extrude(size[2])
		chamferedSquare(size, chamfer, center=center);
}

// Extended rotational extrude, allows control of start/end angle

// Child 2D shape is used for the rotational extrusion
// Child 2D shape should lie in xy plane, centred on z axis
// Child y axis will be aligned to z axis in the extrusion

// NB: Internal render command is necessary to correclty display
// complex child objects (e.g. differences)

// r = Radius of rotational extrusion
// childH = height of child object (approx)
// childW = width of child object (approx)

// Example usage:

//   rotate_extrude_ext(r=50, childW=20, childH=20, start_angle=0, end_angle=180) {
//			difference() {
//				square([20,20],center=true);
//				translate([10,0,0]) circle(5);
//			}
//		}

module rotate_extrude_ext(r, childW, childH, convexity) {
	or = (r + childW/2) * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    if(end_angle > start_angle)
		render()
        intersection() {
			rotate_extrude(convexity=convexity) translate([r,0,0]) children(0);

			translate([0,0,-childH/2 - 1])
			linear_extrude(height=childH+2)
        		polygon([
		            [0,0],
		            [or * cos(a0), or * sin(a0)],
		            [or * cos(a1), or * sin(a1)],
		            [or * cos(a2), or * sin(a2)],
		            [or * cos(a3), or * sin(a3)],
		            [or * cos(a4), or * sin(a4)],
		            [0,0]
		       ]);
    }
}

module torusSlice(r1, r2, start_angle, end_angle, convexity=10, r3=0, $fn=64) {
	difference() {
		rotate_extrude_ext(r=r1, childH=2*r2, childW=2*r2, start_angle=start_angle, end_angle=end_angle, convexity=convexity) difference() circle(r2, $fn=$fn/4);

		rotate_extrude(convexity) translate([r1,0,0]) circle(r3, $fn=$fn/4);
	}
}

module torus(r1, r2, $fn=64) {
	rotate_extrude()
		translate([r1,0,0])
		circle(r2, $fn=$fn/4);
}

module trapezoid(a,b,h,aOffset=0,center=false) {
	// lies in x/y plane
	// edges a,b are parallel to x axis
	// h is in direction of y axis
	// b is anchored at origin, extends along positive x axis
	// a is offset along y by h, extends along positive x axis
	// a if offset along x axis, from y axis, by aOffset
	// centering is relative to edge b

	translate([center?-b/2:0, center?-h/2:0, 0])
	polygon(points=[	[0,0],
					[aOffset,h],
					[aOffset + a, h],
					[b,0]]);
}

module trapezoidPrism(a,b,h,aOffset,height,center=false) {
	translate([0,0, center?-height/2:0]) linear_extrude(height=height) trapezoid(a,b,h,aOffset,center);
}

module arrangeShapesOnAxis(axis=[1,0,0], spacing=50) {
	for (i=[0:$children-1]) {
		translate([spacing * axis[0] *i,
					spacing * axis[1]*i,
					spacing * axis[2]*i]) children(i);
	}
}

module arrangeShapesOnGrid(xSpacing=50, ySpacing=50, cols=3, showLocalAxes=false) {
	// layout is cols, rows
	for (i=[0:$children-1]) {
		translate([(i - floor(i / cols)*cols) * xSpacing, floor(i / cols) * ySpacing, 0]) {
			children(i);

			if (showLocalAxes) {
				color("red") line([0,0,0], [xSpacing/2,0,0], 0.2);
				color("green") line([0,0,0], [0, ySpacing/2,0], 0.2);
				color("blue") line([0,0,0], [0, 0,xSpacing], 0.2);
			}
		}
	}
}

module slot(h, r, l, center = true)
    linear_extrude(height = h, convexity = 6, center = center)
        hull() {
            translate([l/2,0,0])
                circle(r = r, center = true);
            translate([-l/2,0,0])
                circle(r = r, center = true);
        }

module fillet(r, h) {
	// ready to be unioned onto another part, eta fudge included
	// extends along x, y, z

    translate([r / 2, r / 2, 0])
        difference() {
            cube([r + eta, r + eta, h], center = true);
            translate([r/2, r/2, 0])
                cylinder(r = r, h = h + 1, center = true);
        }
}

module right_triangle_2d(width,height,center=true) {
    polygon(points = [[0,0], [width, 0], [0, height]]);
}

module right_triangle(width, height, h, center = true) {
    linear_extrude(height = h, center = center)
        right_triangle_2d(width,height,center=center);
}

module roundedRightTriangle(width, height, h, r=[1,1,1], center = true, $fn=12) {
    linear_extrude(height = h, center = center)
    	hull() {
        	translate([r[0],r[0],0]) circle(r[0]);
        	translate([width-r[1],r[1],0]) circle(r[1]);
        	translate([r[2],height-r[2],0]) circle(r[2]);
        }
}

module rounded_square(w, h, r, center=true)
{
	// 2D
    union() {
        translate([center?0:r,0,0])
        	square([w - 2 * r, h], center=center);
        translate([0,center?0:r,0])
        	square([w, h - 2 * r], center=center);
        for(x = [(center?-w/2:0) + r, (center?w/2:w) - r])
            for(y = [(center?-h/2:0) + r, (center?h/2:h) - r])
                translate([x, y])
                    circle(r = r);
    }
}

//
// Cylinder with rounded ends
//
module rounded_cylinder(r, h, r2, roundBothEnds=false)
{
    rotate_extrude()
        union() {
            square([r - r2, h]);
            translate([0,roundBothEnds?r2:0,0]) square([r, roundBothEnds? h-2*r2 : h - r2]);
            translate([r - r2, h - r2])
                circle(r = r2);
			if (roundBothEnds) {
				translate([r - r2, r2])
                circle(r = r2);
			}

        }
}

module sector(r, a, h, center = true) {
    linear_extrude(height = h, center = center)
        sector2D(r=r, a=a, center=center);
}

module sector2D(r, a, center = true) {
    intersection() {
            circle(r = r, center = true);
                polygon(points = [
                    [0, 0],
                    [2 * r * cos(0),  2 * r * sin(0)],
                    [2 * r * cos(a * 0.2),  2 * r * sin(a * 0.2)],
                    [2 * r * cos(a * 0.4),  2 * r * sin(a * 0.4)],
                    [2 * r * cos(a * 0.6),  2 * r * sin(a * 0.6)],
                    [2 * r * cos(a * 0.8),  2 * r * sin(a * 0.8)],
                    [2 * r * cos(a), 2 * r * sin(a)],
                ]);
        }
}

module donutSector2D(or,ir,a, center=true) {
	difference() {
		sector2D(or,a,center);

		circle(ir);
	}

}

module tube(or, ir, h, center = true) {
    linear_extrude(height = h, center = center, convexity = 5)
        difference() {
            circle(or);
            circle(ir);
        }
}

// tube that tapers
module conicalTube(or1,ir1,or2,ir2,h) {
	difference() {
		cylinder(r1=or1, r2=or2, h=h);

		translate([0,0,-eta])
			cylinder(r1=ir1, r2=ir2, h=h+2*eta);
	}
}

module moreShapesExamples() {
	arrangeShapesOnGrid(xSpacing=100, ySpacing=80, cols=4, showLocalAxes=true) {
		roundedRect([50,30,20], 5);
		roundedRectX([50,30,20], 5);
		roundedRectY([50,30,20], 5);
		//allRoundedRect([50,30,20], 5);

		roundedRect([50,30,20], 5, true);
		roundedRectX([50,30,20], 5, true);
		roundedRectY([50,30,20], 5, true);
		//allRoundedRect([50,30,20], 5, true);

		torusSlice(50, 6, 0, 120, $fn=64);
		torusSlice(r1=50, r2=6, r3=4, start_angle=0, end_angle=120, $fn=64);   // define r3 for a hollow torus

		trapezoidPrism(20,50,20,10,20);
		trapezoidPrism(20,50,20,10,20,true);

		// to be differenced
		slot(h=20, r=5, l=10);

		// to be unioned
		fillet(r=5, h=50);

		right_triangle(width=30, height=20, h=10, center = false);
		rounded_square(w=30, h=20, r=5);
		rounded_cylinder(r=10, h=50, r2=5, roundBothEnds=false);
		rounded_cylinder(r=10, h=50, r2=5, roundBothEnds=true);

		// same as extruded pieSlice
		sector(r=10, a=70, h=20, center = false);

		tube(or=10, ir=5, h=50, center = false);

		rotate_extrude_ext(r=50, childW=20, childH=20, start_angle=0, end_angle=180) {
			difference() {
				square([20,20],center=true);
				translate([10,0,0]) circle(5);
			}
		}
	}
}

*moreShapesExamples();

module overhangFreeCircle(r, ang) {
	// produces a circle with no overhang ready for extrusion
	// overhang infill is along y axis

	x1 = r*cos(ang);
	y1 = r*sin(ang);
	x2 = tan(ang) * (r-y1);

	union() {
		circle(r);

		for (i=[0,1])
			mirror([0,i,0])
			polygon(points=[[0,0],[x1,y1],[x1-x2,r],[-x1+x2,r],[-x1,y1]]);
	}
}

// supports span x axis
module minSupportBeam(size=[0,0,0], bridge=5, air=0, center=false) {
	w = size[0] > bridge ? (size[0] - bridge)/2 : 0;
	h = w > air ? air : w;

	union() {
		cube(size, center=center);

		// triangular supports
		for (i=[0,1])
			translate([i*size[0],0,eta])
			mirror([i,0,0]) {
				translate([w-h, 0, 0])
					rotate([-90,0,0])
					right_triangle(h, h, size[1], center=false);

				translate([0, 0, -h])
					cube([w-h+eta, size[1], h+eta]);

			}
	}
}

module minSupportBeamY(size=[0,0,0], bridge=5, air=0, center=false) {
	translate([size[0], 0, 0])
		rotate([0,0,90])
		minSupportBeam([size[1], size[0], size[2]], bridge, air, center=center);
}


more bracing at fork

more bracing at fork

// $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.

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 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);
   }
   hull() {
     translate([dRight-5,6,0]) cylinder(h=2,r1=1.5,r2=1,$fn=6);
     translate([dRight+1,2,0]) cylinder(h=2,r1=1.5,r2=1,$fn=6);
   }
}}

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

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

}

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

// $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.

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 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);
   }
   hull() {
     translate([dRight-5,6,0]) cylinder(h=2,r1=1.5,r2=1,$fn=6);
     translate([dRight+1,2,0]) cylinder(h=2,r1=1.5,r2=1,$fn=6);
   }
}}

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=.6,$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,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]);
}

// custom support
sW=0.41;  // support width
sH=4.4;  // support height
sH2=sH/2;
color("Cyan") union() {
  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=2,r2=5,h=3.6,$fn=11);
    translate([-29,0.5,0]) rotate([0,0,15])
        scale([1,3,1]) cylinder(r1=.3,r2=1.5,h=3.6,$fn=6);
  }
}

}

//------------------------------------- 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
BED1main(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);
}


config: fix missing include

config: fix missing include

include <MCAD/stepper.scad>
include <bearings.scad>
include <screws.scad>
include <thing_libutils/metric-thread.scad>
include <thing_libutils/metric-hexnut.scad>

e=0.01;

// resolution of any round object (segment length)
fnr                         = 0.4;

extrusion_height            = 0.4*mm;

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

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

thick_wall_factor           = 4;

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

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

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

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

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

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

ziptie_thickness = 4;
ziptie_width = 4;
ziptie_bearing_distance=2;

xaxis_rod_distance = 60*mm;
xaxis_rod_d = 9.975*mm;
xaxis_rod_l = 500*mm;
xaxis_bearing=bearing_igus_rj4jp_01_10;
xaxis_pulley_d = 12.2;
xaxis_belt_width = 6*mm;

xaxis_carriage_bearing_offset_z = ziptie_thickness/2;
xaxis_carriage_beltpath_offset = xaxis_carriage_bearing_offset_z+xaxis_bearing[1]/2;

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing=bearing_igus_rj4jp_01_12;
ycarriage_size=[220*mm,220*mm,5*mm];

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

// NEMA17 motor w/340mm leadscrew
zaxis_motor = [
                [NemaModel, 17],
                [NemaLengthShort, 33*mm],
                [NemaLengthMedium, 39*mm],
                [NemaLengthLong, 47*mm],
                [NemaSideSize, 42.20*mm],
                [NemaDistanceBetweenMountingHoles, 31.04*mm],
                [NemaMountingHoleDiameter, 4*mm],
                [NemaMountingHoleDepth, 4.5*mm],
                [NemaMountingHoleLip, -1*mm],
                [NemaMountingHoleCutoutRadius, 0*mm],
                [NemaEdgeRoundingRadius, 7*mm],
                [NemaRoundExtrusionDiameter, 22*mm],
                [NemaRoundExtrusionHeight, 1.9*mm],
                [NemaAxleDiameter, 8*mm],
                // custom front axle length
                [NemaFrontAxleLength, 340*mm],
                [NemaBackAxleLength, 15*mm],
                [NemaAxleFlatDepth, 0.5*mm],
                [NemaAxleFlatLengthFront, 15*mm],
                [NemaAxleFlatLengthBack, 14*mm]
         ];

zaxis_motor_offset_z = 10*mm;

// inner_d, outer_d, thread
zaxis_nut = [20*mm, 36.5*mm, 8*mm];

zaxis_nut_mount_outer = zaxis_nut[1]/2 + zaxis_bearing[1]/2 + 3;

// place z rod on edge of motor
/*zaxis_rod_screw_distance_x = max(zaxis_nut_mount_outer, zaxis_rod_d/2 + lookup(NemaSideSize,zaxis_motor)/2);*/
zaxis_rod_screw_distance_x = zaxis_nut_mount_outer;

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

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_mount_thickness = 5;
zmotor_mount_thickness_h = 10;
zmotor_mount_thread_dia = lookup(ThreadSize, extrusion_thread);
zmotor_mount_width = zmotor_w+zmotor_mount_thickness*2 + zmotor_mount_thread_dia*8;
zmotor_mount_h = main_lower_dist_z+extrusion_size+zaxis_motor_offset_z;
zmotor_mount_motor_offset=5;
zmotor_mount_rod_offset_x = zmotor_w/2+zaxis_rod_screw_distance_x+zmotor_mount_motor_offset;

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

zmotor_mount_conn_motor=[[-zmotor_mount_motor_offset, 0, 0],[0,1,0]];
zmotor_mount_clamp_width = zmotor_mount_clamp_dist+zmotor_mount_clamp_thread_dia*3;

zaxis_leadscrew_offset_x = zmotor_w/2 + zmotor_mount_motor_offset;

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

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

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

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

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

include <MCAD/stepper.scad>
include <bearings.scad>
include <screws.scad>
include <thing_libutils/metric-thread.scad>

e=0.01;

// resolution of any round object (segment length)
fnr                         = 0.4;

extrusion_height            = 0.4*mm;

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

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

thick_wall_factor           = 4;

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

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

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

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

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

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

ziptie_thickness = 4;
ziptie_width = 4;
ziptie_bearing_distance=2;

xaxis_rod_distance = 60*mm;
xaxis_rod_d = 9.975*mm;
xaxis_rod_l = 500*mm;
xaxis_bearing=bearing_igus_rj4jp_01_10;
xaxis_pulley_d = 12.2;
xaxis_belt_width = 6*mm;

xaxis_carriage_bearing_offset_z = ziptie_thickness/2;
xaxis_carriage_beltpath_offset = xaxis_carriage_bearing_offset_z+xaxis_bearing[1]/2;

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing=bearing_igus_rj4jp_01_12;
ycarriage_size=[220*mm,220*mm,5*mm];

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

// NEMA17 motor w/340mm leadscrew
zaxis_motor = [
                [NemaModel, 17],
                [NemaLengthShort, 33*mm],
                [NemaLengthMedium, 39*mm],
                [NemaLengthLong, 47*mm],
                [NemaSideSize, 42.20*mm],
                [NemaDistanceBetweenMountingHoles, 31.04*mm],
                [NemaMountingHoleDiameter, 4*mm],
                [NemaMountingHoleDepth, 4.5*mm],
                [NemaMountingHoleLip, -1*mm],
                [NemaMountingHoleCutoutRadius, 0*mm],
                [NemaEdgeRoundingRadius, 7*mm],
                [NemaRoundExtrusionDiameter, 22*mm],
                [NemaRoundExtrusionHeight, 1.9*mm],
                [NemaAxleDiameter, 8*mm],
                // custom front axle length
                [NemaFrontAxleLength, 340*mm],
                [NemaBackAxleLength, 15*mm],
                [NemaAxleFlatDepth, 0.5*mm],
                [NemaAxleFlatLengthFront, 15*mm],
                [NemaAxleFlatLengthBack, 14*mm]
         ];

zaxis_motor_offset_z = 10*mm;

// inner_d, outer_d, thread
zaxis_nut = [20*mm, 36.5*mm, 8*mm];

zaxis_nut_mount_outer = zaxis_nut[1]/2 + zaxis_bearing[1]/2 + 3;

// place z rod on edge of motor
/*zaxis_rod_screw_distance_x = max(zaxis_nut_mount_outer, zaxis_rod_d/2 + lookup(NemaSideSize,zaxis_motor)/2);*/
zaxis_rod_screw_distance_x = zaxis_nut_mount_outer;

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

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_mount_thickness = 5;
zmotor_mount_thickness_h = 10;
zmotor_mount_thread_dia = lookup(ThreadSize, extrusion_thread);
zmotor_mount_width = zmotor_w+zmotor_mount_thickness*2 + zmotor_mount_thread_dia*8;
zmotor_mount_h = main_lower_dist_z+extrusion_size+zaxis_motor_offset_z;
zmotor_mount_motor_offset=5;
zmotor_mount_rod_offset_x = zmotor_w/2+zaxis_rod_screw_distance_x+zmotor_mount_motor_offset;

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

zmotor_mount_conn_motor=[[-zmotor_mount_motor_offset, 0, 0],[0,1,0]];
zmotor_mount_clamp_width = zmotor_mount_clamp_dist+zmotor_mount_clamp_thread_dia*3;

zaxis_leadscrew_offset_x = zmotor_w/2 + zmotor_mount_motor_offset;

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

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

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

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

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