make echo statements compatible with convert-2d.sh

UP = 0;
DOWN = 180;
LEFT = 90;
RIGHT = 270;
MID = 360;
kerf=0.0;// Hacky global for kerf

generate = $generate == undef ? 0: $generate;

if (generate == 1)
{
    // openscad examples.scad -D generate=1 -o /tmp/d.csg 2>&1 >/dev/null  | sed 's/ECHO: \"\[LC\] //' | sed 's/"$//' | sed '$a;' >./generate.scad ; openscad ./generate.scad -o generate.dxf
    // (from http://forum.openscad.org/Sharing-Dump-echo-output-to-a-file-td12529.html)
//    echo("[LC] use <lasercut.scad>; \nprojection(cut = false) \n\t");
}

module lasercutoutSquare(thickness, x=0, y=0,
        simple_tabs=[], simple_tab_holes=[],
        captive_nuts=[], captive_nut_holes = [],
        finger_joints = [],
        bumpy_finger_joints = [],
        screw_tabs=[], screw_tab_holes=[],
        twist_holes=[], twist_connect=[],
        clips=[], clip_holes=[],
        circles_add = [],
        circles_remove = [],
        slits = [],
        cutouts = [],
        flat_adjust = [],
        milling_bit = 0.0,
)
{
    points = [[0,0], [x,0], [x,y], [0,y], [0,0]];
lasercutout(thickness=thickness,
        points = points,
        simple_tabs = simple_tabs,
        simple_tab_holes = simple_tab_holes,
        captive_nuts = captive_nuts,
        captive_nut_holes = captive_nut_holes,
        finger_joints = finger_joints,
        bumpy_finger_joints = bumpy_finger_joints,
        screw_tabs= screw_tabs, screw_tab_holes= screw_tab_holes,
        twist_holes=twist_holes, twist_connect=twist_connect,
        clips=clips, clip_holes=clip_holes,
        circles_add = circles_add,
        circles_remove = circles_remove,
        slits = slits,
        cutouts = cutouts,
        flat_adjust = flat_adjust,
        milling_bit = milling_bit
    );
}

module lasercutout(thickness,  points= [],
        simple_tabs=[], simple_tab_holes=[],
        captive_nuts=[], captive_nut_holes = [],
        finger_joints = [],
        bumpy_finger_joints = [],
        screw_tabs=[], screw_tab_holes=[],
        twist_holes=[], twist_connect=[],
        clips=[], clip_holes=[],
        circles_add = [],
        circles_remove = [],
        slits = [],
        cutouts = [],
        flat_adjust = [],
        milling_bit = 0.0,
)
{
    path_total = len(points);
    path = [ for (p = [0 : 1 : path_total]) p ];

    function max_y(points) = max([for (a = [0:1:len(points)-1])  points[a][1]]);
    function min_y(points) = min([for (a = [0:1:len(points)-1])  points[a][1]]);
    function max_x(points) = max([for (a = [0:1:len(points)-1])  points[a][0]]);
    function min_x(points) = min([for (a = [0:1:len(points)-1])  points[a][0]]);

    max_y = max_y(points);
    min_y = min_y(points);
    max_x = max_x(points);
    min_x = min_x(points);

    difference()
    {
        union()
        {
            linear_extrude(height = thickness , center = false)  polygon(points=points, path=path);
            for (t = [0:1:len(simple_tabs)-1])
            {
                simpleTab(simple_tabs[t][0], simple_tabs[t][1], simple_tabs[t][2], thickness);
            }
            for (t = [0:1:len(captive_nuts)-1])
            {
                captiveNutTab(captive_nuts[t][0], captive_nuts[t][1], captive_nuts[t][2], thickness);
            }
            for (t = [0:1:len(circles_add)-1])
            {
                circlesAdd(circles_add[t][0], circles_add[t][1], circles_add[t][2], thickness);
            }
            for (t = [0:1:len(finger_joints)-1])
            {
                fingerJoint(finger_joints[t][0], finger_joints[t][1], finger_joints[t][2], thickness, max_y, min_y, max_x, min_x);
            }
            for (t = [0:1:len(bumpy_finger_joints)-1])
            {
                fingerJoint(bumpy_finger_joints[t][0], bumpy_finger_joints[t][1], bumpy_finger_joints[t][2], thickness, max_y, min_y, max_x, min_x, bumps=true);
            }
            for (t = [0:1:len(screw_tabs)-1])
            {
                screwTab(screw_tabs[t][0], screw_tabs[t][1], screw_tabs[t][2], screw_tabs[t][3], thickness);
            }
             for (t = [0:1:len(clips)-1])
            {
                clipTab(clips[t][0], clips[t][1], clips[t][2], thickness);
            }
        } // end union

        for (t = [0:1:len(simple_tab_holes)-1])
        {
            simpleTabHole(simple_tab_holes[t][0], simple_tab_holes[t][1], simple_tab_holes[t][2], thickness);
        }
        for (t = [0:1:len(captive_nuts)-1])
        {
            if (len(captive_nuts) < 4) {
                captiveNutBoltHole(captive_nuts[t][0], captive_nuts[t][1], captive_nuts[t][2], thickness*3, thickness);
            } else {
                captiveNutBoltHole(captive_nuts[t][0], captive_nuts[t][1], captive_nuts[t][2], captive_nuts[t][3], thickness);
            }
        }
        for (t = [0:1:len(captive_nut_holes)-1])
        {
            captiveNutHole(captive_nut_holes[t][0], captive_nut_holes[t][1], captive_nut_holes[t][2], thickness);
        }
        for (t = [0:1:len(twist_holes)-1])
        {
            twistHole(twist_holes[t][0], twist_holes[t][1], twist_holes[t][2], twist_holes[t][3], thickness);
        }
        for (t = [0:1:len(twist_connect)-1])
        {
            twistConnect(twist_connect[t][0], twist_connect[t][1], twist_connect[t][2], thickness, max_y, min_y, max_x, min_x);
        }
        for (t = [0:1:len(clips)-1])
        {
            clipInner(clips[t][0], clips[t][1], clips[t][2], thickness);
        }
        for (t = [0:1:len(clip_holes)-1])
        {
            clipHole(clip_holes[t][0], clip_holes[t][1], clip_holes[t][2], thickness);
        }
        for (t = [0:1:len(circles_remove)-1])
        {
            circlesRemove(circles_remove[t][0], circles_remove[t][1], circles_remove[t][2], thickness);
        }
        for (t = [0:1:len(slits)-1])
        {
               simpleSlit(slits[t][0], slits[t][1], slits[t][2], slits[t][3], thickness);
        }
        for (t = [0:1:len(cutouts)-1])
        {
               simpleCutouts(cutouts[t][0], cutouts[t][1], cutouts[t][2], cutouts[t][3], thickness);
        }
        for (t = [0:1:len(screw_tabs)-1])
        {
               screwTabHoleForScrew(screw_tabs[t][0], screw_tabs[t][1], screw_tabs[t][2], screw_tabs[t][3], thickness);
        }
        for (t = [0:1:len(screw_tab_holes)-1])
        {
               screwTabHole(screw_tab_holes[t][0], screw_tab_holes[t][1], screw_tab_holes[t][2], screw_tab_holes[t][3], thickness);
        }
        // Used for milling (not lasercutting) fingerJoint,
        if (milling_bit > 0.0)
        {
            for (t = [0:1:len(finger_joints)-1])
            {
                    fingerJoint(finger_joints[t][0], finger_joints[t][1], finger_joints[t][2], thickness, max_y, min_y, max_x, min_x, not_mill=false, milling_bit=milling_bit);
            }
        }
    }

    if (flat_adjust)
    {
        if ($children) translate([0 + flat_adjust[0], max_y(points) + thickness*3 + milling_bit*2 + flat_adjust[1], 0])
                children();
    }
    else
    {
        if ($children) translate([0, max_y(points) + thickness*2.5 + milling_bit*2, 0])
                children();
    }

    if (generate == 1)
    {
        echo(str("[LC] lasercutout(thickness = ",thickness,", \n          points = ",points));
        if(simple_tabs)
            echo(str("[LC]         , simple_tabs = ", simple_tabs));
        if(simple_tab_holes)
            echo(str("[LC]         , simple_tab_holes = ", simple_tab_holes));
        if(captive_nuts)
            echo(str("[LC]         , captive_nuts = ", captive_nuts));
        if(captive_nut_holes)
            echo(str("[LC]         , captive_nut_holes = ", captive_nut_holes));
        if(finger_joints)
            echo(str("[LC]         , finger_joints = ", finger_joints));
        if(bumpy_finger_joints)
            echo(str("[LC]         , bumpy_finger_joints = ", bumpy_finger_joints));
        if(screw_tabs)
            echo(str("[LC]         , screw_tabs = ", screw_tabs));
        if(screw_tab_holes)
            echo(str("[LC]         , screw_tab_holes = ", screw_tab_holes));
        if(twist_holes)
            echo(str("[LC]         , twist_holes = ", twist_holes));
        if(twist_connect)
            echo(str("[LC]         , twist_connect = ", twist_connect));
        if(clips)
            echo(str("[LC]         , clips = ", clips));
        if(clip_holes)
            echo(str("[LC]         , clip_holes = ", clip_holes));
        if(circles_add)
            echo(str("[LC]         , circles_add = ", circles_add));
        if(circles_remove)
            echo(str("[LC]         , circles_remove = ", circles_remove));
        if(slits)
            echo(str("[LC]         , slits = ", slits));
        if(cutouts)
            echo(str("[LC]         , cutouts = ", cutouts));
        if(flat_adjust)
            echo(str("[LC]         , flat_adjust = ", flat_adjust));
        if(milling_bit>0)
            echo(str("[LC]         , milling_bit = ", milling_bit));
        echo("[LC]         ) \n");
    }
}

module simpleTab(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) translate([-thickness/2,0,0]) cube([thickness, thickness, thickness]);
}

module simpleTabHole(angle, x, y, thickness)
{
     // Special case does not go past edge - so make only 1 thickness y
     if (angle == 360)
     {
         translate([x,y,0]) rotate([0,0,0]) translate([0,0,-thickness]) cube([thickness, thickness, thickness*3]);
     }
     else
     {
         translate([x,y,0]) rotate([0,0,angle-180]) translate([-thickness/2,-thickness,-thickness]) cube([thickness, screw*2, thickness*3]);
     }
}

module captiveNutBoltHole(angle, x, y, nut_flat_width, thickness)
{
    translate([x,y,0]) rotate([0,0,angle-180]) union()
    {
        translate([-thickness/2,-thickness,-thickness]) cube([thickness, thickness*4, thickness*3]);
        echo(str("[LC] // screw thread major dia must be < ", thickness));
        echo(str("[LC] // screw thread length must be < ", thickness*5));
        translate([-nut_flat_width/2,thickness,-thickness]) cube([nut_flat_width, thickness, thickness*3]);
        echo(str("[LC] // nut thickness must be < ", thickness));
        echo(str("[LC] // nut flats must be < ", nut_flat_width));
    }
}

module fingerJoint(angle, start_up, fingers, thickness, max_y, min_y, max_x, min_x, bumps = false, not_mill=true, milling_bit=0)
{
    if ( angle == UP )
    {
        range_min = min_x;
        range_max = max_x;
        t_x = min_x;
        t_y = max_y;
        if(not_mill)
        {
            fingers(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bumps = bumps);
        }
        else
        {
            fingers_mill(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bit=milling_bit);
        }
    }
    if ( angle == DOWN )
    {
        range_min = min_x;
        range_max = max_x;
        t_x = max_x;
        t_y = min_y;
        if(not_mill)
        {
            fingers(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bumps = bumps);
        }
        else
        {
            fingers_mill(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bit=milling_bit);
        }
    }
    if ( angle == LEFT )
    {
        range_min = min_y;
        range_max = max_y;
        t_x = min_x;
        t_y = min_y;
        if(not_mill)
        {
            fingers(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bumps = bumps);
        }
        else
        {
            fingers_mill(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bit=milling_bit);
        }
    }
    if ( angle == RIGHT )
    {
        range_min = min_y;
        range_max = max_y;
        t_x = max_x;
        t_y = max_y;
        if(not_mill)
        {
            fingers(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bumps = bumps);
        }
        else
        {
            fingers_mill(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bit=milling_bit);
        }
    }

}

module fingers(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bumps = false)
{

    // The tweaks to y translate([0, -thickness,0]) ... thickness*2 rather than *1
    // Are to avoid edge cases and make the dxf export better.
    // All fun
    translate([t_x, t_y,0]) rotate([0,0,angle]) translate([0, -thickness,0])
    {
        for ( p = [ 0 : 1 : fingers-1] )
		{

			kerfSize = (p > 0) ? kerf/2 : kerf/2 ;
			kerfMove = (p > 0) ? kerf/4 : 0;

			i=range_min + ((range_max-range_min)/fingers)*p;
            if(start_up == 1)
            {

                translate([i-kerfMove,0,0])
                {
                    cube([ (range_max-range_min)/(fingers*2) + kerfSize, thickness*2, thickness]);
                    if(bumps == true)
                    {
                        translate([(range_max-range_min)/(fingers*2), thickness*1.5, 0]) cylinder(h=thickness, r=thickness/10);
                    }
                }
            }
            else
            {
                translate([i+(range_max-range_min)/(fingers*2)-kerfMove,0,0])
                {
                    cube([ (range_max-range_min)/(fingers*2)+kerfSize, thickness*2, thickness]);
                    if(bumps == true)
                    {
                        if (i < (range_max - (range_max-range_min)/fingers ))
                        {
                            translate([(range_max-range_min)/(fingers*2), thickness*1.5, 0]) cylinder(h=thickness, r=thickness/10);
                        }
                    }
                }
            }
        }
    }

}

module fingers_mill(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bit=6.35/2)
{

    // The tweaks to y translate([0, -thickness,0]) ... thickness*2 rather than *1
    // Are to avoid edge cases and make the dxf export better.
    // All fun
    translate([t_x, t_y,0]) rotate([0,0,angle]) translate([0, -thickness,0])
    {
        for ( p = [ 0 : 1 : fingers-1] )
		{
            if(start_up == 1)
            {
                translate([((range_max-range_min)/fingers)*p,0,0])
                {
                    translate([(range_max-range_min)/(fingers*2) + bit/2,thickness,0]) cylinder(h=thickness*4, d=bit, center=true );
                    translate([2*(range_max-range_min)/(fingers*2) - bit/2,thickness,0]) cylinder(h=thickness*4, d=bit, center=true );
                }
            }
            else
            {
                translate([((range_max-range_min)/fingers)*p,0,0])
                {
                    translate([bit/2,thickness,0]) cylinder(h=thickness*4, d=bit, center=true );
                    translate([(range_max-range_min)/(fingers*2) - bit/2,thickness,0]) cylinder(h=thickness*4, d=bit, center=true );
                }
            }
        }
    }

}

module screwTab(angle, x, y, screw, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) translate([-screw/2,0,0]) cube([screw*2, thickness+screw*2, thickness]);
}

module screwTabHoleForScrew(angle, x, y, screw, thickness)
{
    // not to be confused with screwTabHole
    translate([x,y,0]) rotate([0,0,angle]) translate([screw/2,thickness+screw,-thickness]) cylinder(h=thickness*3, r=screw/2);
}

module screwTabHole(angle, x, y, screw, thickness)
{
     // Special case does not go past edge - so make only 1 thickness y
     if (angle == 360)
     {
         translate([x,y,0]) rotate([0,0,0]) translate([0,0,-thickness]) cube([screw*2, thickness, thickness*3]);
     }
     else
     {
         translate([x,y,0]) rotate([0,0,angle-180]) translate([-thickness/2,-thickness,-thickness]) cube([thickness, thickness*2, thickness*3]);
     }
}

module captiveNutTab(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) union()
    {
        translate([-thickness/2+thickness*2,-thickness,0]) cube([thickness*3, thickness*2, thickness]);
        translate([-thickness/2-thickness*4,-thickness,0]) cube([thickness*3, thickness*2, thickness]);
    }
}

module captiveNutHole(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) union()
    {
        translate([-thickness/2,-thickness*2,-thickness]) cube([thickness, thickness, thickness*3]);
        translate([-thickness/2+thickness*2,-thickness*2,-thickness]) cube([thickness*3, thickness, thickness*3]);
        translate([-thickness/2-thickness*4,-thickness*2,-thickness]) cube([thickness*3, thickness, thickness*3]);
    }
}

module twistHole(angle, x, y, width, thickness)
{
// http://msraynsford.blogspot.co.uk/2012/06/panel-joinery-10.html
    translate([x,y,0]) rotate([0,0,angle-90]) union()
    {
        cube([width, thickness, thickness*3], center=true);
        difference()
        {
            // Need some trig,  radius is hypo of triangle
            // Other sides are thinkness/2 and thinkness*3
            //
            //
           radius = sqrt(  ((thickness/2)*(thickness/2)) + (thickness*1.5*thickness*1.5) );
           translate([0,0, -thickness]) cylinder(h=thickness*3, r=radius);
           translate([-thickness*3/2,thickness,0]) cube([thickness*2, thickness, thickness*3], center=true);
           translate([thickness*3/2,-thickness,0]) cube([thickness*2, thickness, thickness*3], center=true);
        }
    }
}

module twistConnect(angle, x, y, thickness, max_y, min_y, max_x, min_x)
{
    // Really should do trianometry for non-90 Angles, but hey ho
    if( (angle == LEFT) || (angle == RIGHT) )
    {
        translate([0,y,-thickness]) rotate([0,0,angle+90]) union()
        {
            gap = max_x - min_x;
            translate([-gap/2-(thickness*3/2),0,0]) cube([gap, thickness, thickness*3]);
            translate([+gap/2+(thickness*3/2),0,0]) cube([gap, thickness, thickness*3]);
        }
    }
    if( (angle == UP) || (angle == DOWN) )
    {
        translate([x,0,-thickness]) rotate([0,0,angle+90]) union()
        {
            gap = max_y - min_y;
            translate([-gap/2-(thickness*3/2),0,0]) cube([gap, thickness, thickness*3]);
            translate([+gap/2+(thickness*3/2),0,0]) cube([gap, thickness, thickness*3]);
        }
    }
}

module clipInner(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) union()
    {
        translate([-thickness/2-1,0,0])
        {
            translate([-(1+thickness)/2,-thickness*10,-thickness]) cube([1, thickness*11, thickness*3]);
            translate([(1+thickness)/2+1,-thickness*8,0])  linear_extrude(height = thickness*3, center = true)  polygon(points=[[0,0],[0,9*thickness],[-(thickness-1), 9*thickness]]);
            translate([(1+thickness)/2+1-thickness+1,thickness-1,-thickness]) cube([thickness/2, thickness, thickness*3]);
            translate([-thickness*3/2,0,-thickness]) cube([thickness, thickness, thickness*3]);
        }
    }
}

module clipTab(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) union()
    {
        // make off-center
        translate([-thickness/2-1,0,0])
        {
            difference()
            {
                 translate([0,thickness/2,thickness/2]) cube([thickness+1,thickness,thickness], center=true);
                 translate([(1+thickness)/2+1,-thickness*8,0])  linear_extrude(height = thickness*3, center = true)  polygon(points=[[0,0],[0,9*thickness],[-(thickness-1), 9*thickness]]);
            }
           translate([-thickness,thickness,0])  linear_extrude(height = thickness)  polygon(points=[[0,0],[thickness+1,0],[thickness,thickness-1],[1,thickness-1]]);
        }
        translate([0.5,0,0]) cube([thickness,thickness,thickness]);
*       cube([thickness*2+1,thickness,thickness], center=true);
    }
}

module clipHole(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) union()
    {
        translate([0,-thickness/2,thickness/2]) cube([thickness*2+1,thickness,thickness*3], center=true);
    }
}

module circlesAdd(radius, x, y, thickness)
{
    translate([x,y,0]) cylinder(h=thickness, r=radius);
}

module circlesRemove(radius, x, y, thickness)
{
    translate([x,y,-thickness]) cylinder(h=thickness*3, r=radius);
}

module simpleSlit(angle, x, y, length, thickness)
{
     translate([x,y,0]) rotate([0,0,angle-180]) translate([-thickness/2,-thickness,-thickness]) cube([thickness, length+thickness, thickness*3]);
}

module simpleCutouts(x, y, width, height, thickness)
{
     translate([x,y,0]) rotate([0,0,0]) translate([0,0,-thickness]) cube([width, height, thickness*3]);
}

module lasercutoutBox(thickness, x=0, y=0, z=0, sides=6, num_fingers=2,
        simple_tab_holes_a=[],
        captive_nuts_a=[], captive_nut_holes_a=[],
        screw_tab_holes_a=[],
        twist_holes_a=[],
        clip_holes_a=[],
        circles_add_a=[],
        circles_remove_a=[],
        slits_a = [],
        cutouts_a = [],
        milling_bit = 0.0
)
{

    if (sides==4)
    {
        fj = [
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers],    ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers],    ],
            [ [UP, 1, num_fingers], [DOWN, 0, num_fingers],    ],
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers],    ],
        ];
        translate([0,thickness,0]) lasercutoutBoxAdjustedFJ(thickness = thickness, x=x, y=y-thickness*2 , z=z-thickness*2, sides=sides, fj=fj,
            simple_tab_holes_a=simple_tab_holes_a,
            captive_nuts_a=captive_nuts_a, captive_nut_holes_a=captive_nut_holes_a,
            screw_tab_holes_a=screw_tab_holes_a,
            twist_holes_a=twist_holes_a,
            clip_holes_a=clip_holes_a,
            circles_add_a=circles_add_a,
            circles_remove_a=circles_remove_a,
            slits_a=slits_a,
            cutouts_a=cutouts_a,
            milling_bit = milling_bit
        );
    }
    if (sides==5)
    {
        st = [
        [[DOWN, -thickness/2, 0], [DOWN, -thickness/2, y-thickness] ],
        [[DOWN, -thickness/2, 0], ],
        [[UP, -thickness/2, z-thickness*2], ],
        ];
        fj = [
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers],   ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers],   ],
            [ [UP, 1, num_fingers], [DOWN, 0, num_fingers], [LEFT, 1, num_fingers],   ],
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers],   ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers], [LEFT, 0, num_fingers], [RIGHT, 1, num_fingers]  ],
        ];

        translate([thickness,thickness,0]) lasercutoutBoxAdjustedFJ(thickness = thickness, x=x-thickness, y=y-thickness*2 , z=z-thickness*2, sides=sides, fj=fj, st=st,
            simple_tab_holes_a=simple_tab_holes_a,
            captive_nuts_a=captive_nuts_a, captive_nut_holes_a=captive_nut_holes_a,
            screw_tab_holes_a=screw_tab_holes_a,
            twist_holes_a=twist_holes_a,
            clip_holes_a=clip_holes_a,
            circles_add_a=circles_add_a,
            circles_remove_a=circles_remove_a,
            slits_a=slits_a,
            cutouts_a=cutouts_a,
            milling_bit = milling_bit
        );

        }
    if (sides==6)
    {
        st = [
        [[DOWN, -thickness/2, 0], [DOWN, -thickness/2, y-thickness] , [RIGHT, x-thickness*2, -thickness/2]],
        [[DOWN, -thickness/2, 0], [RIGHT, x-thickness*2, -thickness/2]],
        [[UP, -thickness/2, z-thickness*2], [DOWN, x-thickness*1.5, 0], ],
        [[UP, z-thickness*1.5, y-thickness*2], ],
        ];
        fj = [
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers], [RIGHT, 0, num_fingers]  ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers], [RIGHT, 0, num_fingers]  ],
            [ [UP, 1, num_fingers], [DOWN, 0, num_fingers], [LEFT, 1, num_fingers], [RIGHT, 0, num_fingers]  ],
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers], [RIGHT, 0, num_fingers]  ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers], [LEFT, 0, num_fingers], [RIGHT, 1, num_fingers]  ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers], [LEFT, 0, num_fingers], [RIGHT, 1, num_fingers]  ],
        ];
        translate([thickness,thickness,0]) lasercutoutBoxAdjustedFJ(thickness = thickness, x=x-thickness*2, y=y-thickness*2 , z=z-thickness*2, sides=sides, fj=fj, st=st,
            simple_tab_holes_a=simple_tab_holes_a,
            captive_nuts_a=captive_nuts_a, captive_nut_holes_a=captive_nut_holes_a,
            screw_tab_holes_a=screw_tab_holes_a,
            twist_holes_a=twist_holes_a,
            clip_holes_a=clip_holes_a,
            circles_add_a=circles_add_a,
            circles_remove_a=circles_remove_a,
            slits_a=slits_a,
            cutouts_a=cutouts_a,
            milling_bit = milling_bit
        );

    }
}

module lasercutoutBoxAdjustedFJ(thickness, x=0, y=0, z=0, sides=6, fj=[], st=[],
        simple_tab_holes_a=[],
        captive_nuts_a=[], captive_nut_holes_a = [],
        circles_add_a = [],
        circles_remove_a = [],
        slits_a = [],
        cutouts_a = [],
        milling_bit = 0.0
)
{

    translate([0,0,0]) lasercutoutSquare(thickness=thickness,x=x, y=y, simple_tabs = st[0], finger_joints = fj[0],
                                simple_tab_holes=simple_tab_holes_a[0], captive_nuts=captive_nuts_a[0],
                                captive_nut_holes = captive_nut_holes_a[0],
                                screw_tab_holes = screw_tab_holes_a[0],
                                twist_holes = twist_holes_a[0],
                                clip_holes = clip_holes_a[0],
                                circles_add = circles_add_a[0], circles_remove = circles_remove_a[0],
                                slits = slits_a[0],
                                cutouts = cutouts_a[0],
                                milling_bit = milling_bit);

    translate([0,0,z+thickness]) lasercutoutSquare(thickness=thickness,x=x, y=y, simple_tabs = st[1], finger_joints = fj[1],
                                simple_tab_holes=simple_tab_holes_a[1], captive_nuts=captive_nuts_a[1],
                                captive_nut_holes = captive_nut_holes_a[1],
                                screw_tab_holes = screw_tab_holes_a[1],
                                twist_holes = twist_holes_a[1],
                                clip_holes = clip_holes_a[1],
                                circles_add = circles_add_a[1], circles_remove = circles_remove_a[1],
                                slits = slits_a[1],
                                cutouts = cutouts_a[1],
                                milling_bit = milling_bit);

    translate([0,0,thickness]) rotate([90,0,0]) lasercutoutSquare(thickness=thickness,x=x, y=z, finger_joints = fj[2],
                                simple_tab_holes=simple_tab_holes_a[2], captive_nuts=captive_nuts_a[2],
                                captive_nut_holes = captive_nut_holes_a[2],
                                screw_tab_holes = screw_tab_holes_a[2],
                                twist_holes = twist_holes_a[2],
                                clip_holes = clip_holes_a[2],
                                circles_add = circles_add_a[2], circles_remove = circles_remove_a[2],
                                slits = slits_a[2],
                                cutouts = cutouts_a[2],
                                milling_bit = milling_bit);

    translate([0,y+thickness,thickness]) rotate([90,0,0]) lasercutoutSquare(thickness=thickness,x=x, y=z, simple_tabs = st[2],
                                finger_joints = fj[3],
                                simple_tab_holes=simple_tab_holes_a[3], captive_nuts=captive_nuts_a[3],
                                captive_nut_holes = captive_nut_holes_a[3],
                                screw_tab_holes = screw_tab_holes_a[3],
                                twist_holes = twist_holes_a[3],
                                clip_holes = clip_holes_a[3],
                                circles_add = circles_add_a[3], circles_remove = circles_remove_a[3],
                                slits = slits_a[3],
                                cutouts = cutouts_a[3],
                                milling_bit = milling_bit
                                );

    if (sides>4)
    {
        translate([0,0,thickness]) rotate([0,-90,0]) lasercutoutSquare(thickness=thickness,x=z, y=y, finger_joints = fj[4],
                                simple_tab_holes=simple_tab_holes_a[4], captive_nuts=captive_nuts_a[4],
                                captive_nut_holes = captive_nut_holes_a[4],
                                screw_tab_holes = screw_tab_holes_a[4],
                                twist_holes = twist_holes_a[4],
                                clip_holes = clip_holes_a[4],
                                circles_add = circles_add_a[4], circles_remove = circles_remove_a[4],
                                slits = slits_a[4],
                                cutouts = cutouts_a[4],
                                milling_bit = milling_bit);
        }

    if (sides>5)
    {
        translate([x+thickness,0,thickness]) rotate([0,-90,0]) lasercutoutSquare(thickness=thickness,x=z, y=y,
                                simple_tabs = st[3], finger_joints = fj[5],
                                simple_tab_holes=simple_tab_holes_a[5], captive_nuts=captive_nuts_a[5],
                                captive_nut_holes = captive_nut_holes_a[5],
                                screw_tab_holes = screw_tab_holes_a[5],
                                twist_holes = twist_holes_a[5],
                                clip_holes = clip_holes_a[5],
                                circles_add = circles_add_a[5], circles_remove = circles_remove_a[5],
                                slits = slits_a[5],
                                cutouts = cutouts_a[5],
                                milling_bit = milling_bit);
    }
}

UP = 0;
DOWN = 180;
LEFT = 90;
RIGHT = 270;
MID = 360;
kerf=0.0;// Hacky global for kerf

generate = $generate == undef ? 0: $generate;

if (generate == 1)
{
    // openscad examples.scad -D generate=1 -o /tmp/d.csg 2>&1 >/dev/null  | sed 's/ECHO: \"\[LC\] //' | sed 's/"$//' | sed '$a;' >./generate.scad ; openscad ./generate.scad -o generate.dxf
    // (from http://forum.openscad.org/Sharing-Dump-echo-output-to-a-file-td12529.html)
//    echo("[LC] use <lasercut.scad>; \nprojection(cut = false) \n\t");
}

module lasercutoutSquare(thickness, x=0, y=0,
        simple_tabs=[], simple_tab_holes=[],
        captive_nuts=[], captive_nut_holes = [],
        finger_joints = [],
        bumpy_finger_joints = [],
        screw_tabs=[], screw_tab_holes=[],
        twist_holes=[], twist_connect=[],
        clips=[], clip_holes=[],
        circles_add = [],
        circles_remove = [],
        slits = [],
        cutouts = [],
        flat_adjust = [],
        milling_bit = 0.0,
)
{
    points = [[0,0], [x,0], [x,y], [0,y], [0,0]];
lasercutout(thickness=thickness,
        points = points,
        simple_tabs = simple_tabs,
        simple_tab_holes = simple_tab_holes,
        captive_nuts = captive_nuts,
        captive_nut_holes = captive_nut_holes,
        finger_joints = finger_joints,
        bumpy_finger_joints = bumpy_finger_joints,
        screw_tabs= screw_tabs, screw_tab_holes= screw_tab_holes,
        twist_holes=twist_holes, twist_connect=twist_connect,
        clips=clips, clip_holes=clip_holes,
        circles_add = circles_add,
        circles_remove = circles_remove,
        slits = slits,
        cutouts = cutouts,
        flat_adjust = flat_adjust,
        milling_bit = milling_bit
    );
}

module lasercutout(thickness,  points= [],
        simple_tabs=[], simple_tab_holes=[],
        captive_nuts=[], captive_nut_holes = [],
        finger_joints = [],
        bumpy_finger_joints = [],
        screw_tabs=[], screw_tab_holes=[],
        twist_holes=[], twist_connect=[],
        clips=[], clip_holes=[],
        circles_add = [],
        circles_remove = [],
        slits = [],
        cutouts = [],
        flat_adjust = [],
        milling_bit = 0.0,
)
{
    path_total = len(points);
    path = [ for (p = [0 : 1 : path_total]) p ];

    function max_y(points) = max([for (a = [0:1:len(points)-1])  points[a][1]]);
    function min_y(points) = min([for (a = [0:1:len(points)-1])  points[a][1]]);
    function max_x(points) = max([for (a = [0:1:len(points)-1])  points[a][0]]);
    function min_x(points) = min([for (a = [0:1:len(points)-1])  points[a][0]]);

    max_y = max_y(points);
    min_y = min_y(points);
    max_x = max_x(points);
    min_x = min_x(points);

    difference()
    {
        union()
        {
            linear_extrude(height = thickness , center = false)  polygon(points=points, path=path);
            for (t = [0:1:len(simple_tabs)-1])
            {
                simpleTab(simple_tabs[t][0], simple_tabs[t][1], simple_tabs[t][2], thickness);
            }
            for (t = [0:1:len(captive_nuts)-1])
            {
                captiveNutTab(captive_nuts[t][0], captive_nuts[t][1], captive_nuts[t][2], thickness);
            }
            for (t = [0:1:len(circles_add)-1])
            {
                circlesAdd(circles_add[t][0], circles_add[t][1], circles_add[t][2], thickness);
            }
            for (t = [0:1:len(finger_joints)-1])
            {
                fingerJoint(finger_joints[t][0], finger_joints[t][1], finger_joints[t][2], thickness, max_y, min_y, max_x, min_x);
            }
            for (t = [0:1:len(bumpy_finger_joints)-1])
            {
                fingerJoint(bumpy_finger_joints[t][0], bumpy_finger_joints[t][1], bumpy_finger_joints[t][2], thickness, max_y, min_y, max_x, min_x, bumps=true);
            }
            for (t = [0:1:len(screw_tabs)-1])
            {
                screwTab(screw_tabs[t][0], screw_tabs[t][1], screw_tabs[t][2], screw_tabs[t][3], thickness);
            }
             for (t = [0:1:len(clips)-1])
            {
                clipTab(clips[t][0], clips[t][1], clips[t][2], thickness);
            }
        } // end union

        for (t = [0:1:len(simple_tab_holes)-1])
        {
            simpleTabHole(simple_tab_holes[t][0], simple_tab_holes[t][1], simple_tab_holes[t][2], thickness);
        }
        for (t = [0:1:len(captive_nuts)-1])
        {
            if (len(captive_nuts) < 4) {
                captiveNutBoltHole(captive_nuts[t][0], captive_nuts[t][1], captive_nuts[t][2], thickness*3, thickness);
            } else {
                captiveNutBoltHole(captive_nuts[t][0], captive_nuts[t][1], captive_nuts[t][2], captive_nuts[t][3], thickness);
            }
        }
        for (t = [0:1:len(captive_nut_holes)-1])
        {
            captiveNutHole(captive_nut_holes[t][0], captive_nut_holes[t][1], captive_nut_holes[t][2], thickness);
        }
        for (t = [0:1:len(twist_holes)-1])
        {
            twistHole(twist_holes[t][0], twist_holes[t][1], twist_holes[t][2], twist_holes[t][3], thickness);
        }
        for (t = [0:1:len(twist_connect)-1])
        {
            twistConnect(twist_connect[t][0], twist_connect[t][1], twist_connect[t][2], thickness, max_y, min_y, max_x, min_x);
        }
        for (t = [0:1:len(clips)-1])
        {
            clipInner(clips[t][0], clips[t][1], clips[t][2], thickness);
        }
        for (t = [0:1:len(clip_holes)-1])
        {
            clipHole(clip_holes[t][0], clip_holes[t][1], clip_holes[t][2], thickness);
        }
        for (t = [0:1:len(circles_remove)-1])
        {
            circlesRemove(circles_remove[t][0], circles_remove[t][1], circles_remove[t][2], thickness);
        }
        for (t = [0:1:len(slits)-1])
        {
               simpleSlit(slits[t][0], slits[t][1], slits[t][2], slits[t][3], thickness);
        }
        for (t = [0:1:len(cutouts)-1])
        {
               simpleCutouts(cutouts[t][0], cutouts[t][1], cutouts[t][2], cutouts[t][3], thickness);
        }
        for (t = [0:1:len(screw_tabs)-1])
        {
               screwTabHoleForScrew(screw_tabs[t][0], screw_tabs[t][1], screw_tabs[t][2], screw_tabs[t][3], thickness);
        }
        for (t = [0:1:len(screw_tab_holes)-1])
        {
               screwTabHole(screw_tab_holes[t][0], screw_tab_holes[t][1], screw_tab_holes[t][2], screw_tab_holes[t][3], thickness);
        }
        // Used for milling (not lasercutting) fingerJoint,
        if (milling_bit > 0.0)
        {
            for (t = [0:1:len(finger_joints)-1])
            {
                    fingerJoint(finger_joints[t][0], finger_joints[t][1], finger_joints[t][2], thickness, max_y, min_y, max_x, min_x, not_mill=false, milling_bit=milling_bit);
            }
        }
    }

    if (flat_adjust)
    {
        if ($children) translate([0 + flat_adjust[0], max_y(points) + thickness*3 + milling_bit*2 + flat_adjust[1], 0])
                children();
    }
    else
    {
        if ($children) translate([0, max_y(points) + thickness*2.5 + milling_bit*2, 0])
                children();
    }

    if (generate == 1)
    {
        echo(str("[LC] lasercutout(thickness = ",thickness,", \n          points = ",points));
        if(simple_tabs)
            echo(str("[LC]         , simple_tabs = ", simple_tabs));
        if(simple_tab_holes)
            echo(str("[LC]         , simple_tab_holes = ", simple_tab_holes));
        if(captive_nuts)
            echo(str("[LC]         , captive_nuts = ", captive_nuts));
        if(captive_nut_holes)
            echo(str("[LC]         , captive_nut_holes = ", captive_nut_holes));
        if(finger_joints)
            echo(str("[LC]         , finger_joints = ", finger_joints));
        if(bumpy_finger_joints)
            echo(str("[LC]         , bumpy_finger_joints = ", bumpy_finger_joints));
        if(screw_tabs)
            echo(str("[LC]         , screw_tabs = ", screw_tabs));
        if(screw_tab_holes)
            echo(str("[LC]         , screw_tab_holes = ", screw_tab_holes));
        if(twist_holes)
            echo(str("[LC]         , twist_holes = ", twist_holes));
        if(twist_connect)
            echo(str("[LC]         , twist_connect = ", twist_connect));
        if(clips)
            echo(str("[LC]         , clips = ", clips));
        if(clip_holes)
            echo(str("[LC]         , clip_holes = ", clip_holes));
        if(circles_add)
            echo(str("[LC]         , circles_add = ", circles_add));
        if(circles_remove)
            echo(str("[LC]         , circles_remove = ", circles_remove));
        if(slits)
            echo(str("[LC]         , slits = ", slits));
        if(cutouts)
            echo(str("[LC]         , cutouts = ", cutouts));
        if(flat_adjust)
            echo(str("[LC]         , flat_adjust = ", flat_adjust));
        if(milling_bit>0)
            echo(str("[LC]         , milling_bit = ", milling_bit));
        echo("[LC]         ) \n");
    }
}

module simpleTab(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) translate([-thickness/2,0,0]) cube([thickness, thickness, thickness]);
}

module simpleTabHole(angle, x, y, thickness)
{
     // Special case does not go past edge - so make only 1 thickness y
     if (angle == 360)
     {
         translate([x,y,0]) rotate([0,0,0]) translate([0,0,-thickness]) cube([thickness, thickness, thickness*3]);
     }
     else
     {
         translate([x,y,0]) rotate([0,0,angle-180]) translate([-thickness/2,-thickness,-thickness]) cube([thickness, screw*2, thickness*3]);
     }
}

module captiveNutBoltHole(angle, x, y, nut_flat_width, thickness)
{
    translate([x,y,0]) rotate([0,0,angle-180]) union()
    {
        translate([-thickness/2,-thickness,-thickness]) cube([thickness, thickness*4, thickness*3]);
        echo("screw thread major dia must be < ", thickness);
        echo("screw thread length must be < ", thickness*5);
        translate([-nut_flat_width/2,thickness,-thickness]) cube([nut_flat_width, thickness, thickness*3]);
        echo("nut thickness must be < ", thickness);
        echo("nut flats must be < ", nut_flat_width);
    }
}

module fingerJoint(angle, start_up, fingers, thickness, max_y, min_y, max_x, min_x, bumps = false, not_mill=true, milling_bit=0)
{
    if ( angle == UP )
    {
        range_min = min_x;
        range_max = max_x;
        t_x = min_x;
        t_y = max_y;
        if(not_mill)
        {
            fingers(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bumps = bumps);
        }
        else
        {
            fingers_mill(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bit=milling_bit);
        }
    }
    if ( angle == DOWN )
    {
        range_min = min_x;
        range_max = max_x;
        t_x = max_x;
        t_y = min_y;
        if(not_mill)
        {
            fingers(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bumps = bumps);
        }
        else
        {
            fingers_mill(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bit=milling_bit);
        }
    }
    if ( angle == LEFT )
    {
        range_min = min_y;
        range_max = max_y;
        t_x = min_x;
        t_y = min_y;
        if(not_mill)
        {
            fingers(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bumps = bumps);
        }
        else
        {
            fingers_mill(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bit=milling_bit);
        }
    }
    if ( angle == RIGHT )
    {
        range_min = min_y;
        range_max = max_y;
        t_x = max_x;
        t_y = max_y;
        if(not_mill)
        {
            fingers(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bumps = bumps);
        }
        else
        {
            fingers_mill(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bit=milling_bit);
        }
    }

}

module fingers(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bumps = false)
{

    // The tweaks to y translate([0, -thickness,0]) ... thickness*2 rather than *1
    // Are to avoid edge cases and make the dxf export better.
    // All fun
    translate([t_x, t_y,0]) rotate([0,0,angle]) translate([0, -thickness,0])
    {
        for ( p = [ 0 : 1 : fingers-1] )
		{

			kerfSize = (p > 0) ? kerf/2 : kerf/2 ;
			kerfMove = (p > 0) ? kerf/4 : 0;

			i=range_min + ((range_max-range_min)/fingers)*p;
            if(start_up == 1)
            {

                translate([i-kerfMove,0,0])
                {
                    cube([ (range_max-range_min)/(fingers*2) + kerfSize, thickness*2, thickness]);
                    if(bumps == true)
                    {
                        translate([(range_max-range_min)/(fingers*2), thickness*1.5, 0]) cylinder(h=thickness, r=thickness/10);
                    }
                }
            }
            else
            {
                translate([i+(range_max-range_min)/(fingers*2)-kerfMove,0,0])
                {
                    cube([ (range_max-range_min)/(fingers*2)+kerfSize, thickness*2, thickness]);
                    if(bumps == true)
                    {
                        if (i < (range_max - (range_max-range_min)/fingers ))
                        {
                            translate([(range_max-range_min)/(fingers*2), thickness*1.5, 0]) cylinder(h=thickness, r=thickness/10);
                        }
                    }
                }
            }
        }
    }

}

module fingers_mill(angle, start_up, fingers, thickness, range_min, range_max, t_x, t_y, bit=6.35/2)
{

    // The tweaks to y translate([0, -thickness,0]) ... thickness*2 rather than *1
    // Are to avoid edge cases and make the dxf export better.
    // All fun
    translate([t_x, t_y,0]) rotate([0,0,angle]) translate([0, -thickness,0])
    {
        for ( p = [ 0 : 1 : fingers-1] )
		{
            if(start_up == 1)
            {
                translate([((range_max-range_min)/fingers)*p,0,0])
                {
                    translate([(range_max-range_min)/(fingers*2) + bit/2,thickness,0]) cylinder(h=thickness*4, d=bit, center=true );
                    translate([2*(range_max-range_min)/(fingers*2) - bit/2,thickness,0]) cylinder(h=thickness*4, d=bit, center=true );
                }
            }
            else
            {
                translate([((range_max-range_min)/fingers)*p,0,0])
                {
                    translate([bit/2,thickness,0]) cylinder(h=thickness*4, d=bit, center=true );
                    translate([(range_max-range_min)/(fingers*2) - bit/2,thickness,0]) cylinder(h=thickness*4, d=bit, center=true );
                }
            }
        }
    }

}

module screwTab(angle, x, y, screw, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) translate([-screw/2,0,0]) cube([screw*2, thickness+screw*2, thickness]);
}

module screwTabHoleForScrew(angle, x, y, screw, thickness)
{
    // not to be confused with screwTabHole
    translate([x,y,0]) rotate([0,0,angle]) translate([screw/2,thickness+screw,-thickness]) cylinder(h=thickness*3, r=screw/2);
}

module screwTabHole(angle, x, y, screw, thickness)
{
     // Special case does not go past edge - so make only 1 thickness y
     if (angle == 360)
     {
         translate([x,y,0]) rotate([0,0,0]) translate([0,0,-thickness]) cube([screw*2, thickness, thickness*3]);
     }
     else
     {
         translate([x,y,0]) rotate([0,0,angle-180]) translate([-thickness/2,-thickness,-thickness]) cube([thickness, thickness*2, thickness*3]);
     }
}

module captiveNutTab(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) union()
    {
        translate([-thickness/2+thickness*2,-thickness,0]) cube([thickness*3, thickness*2, thickness]);
        translate([-thickness/2-thickness*4,-thickness,0]) cube([thickness*3, thickness*2, thickness]);
    }
}

module captiveNutHole(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) union()
    {
        translate([-thickness/2,-thickness*2,-thickness]) cube([thickness, thickness, thickness*3]);
        translate([-thickness/2+thickness*2,-thickness*2,-thickness]) cube([thickness*3, thickness, thickness*3]);
        translate([-thickness/2-thickness*4,-thickness*2,-thickness]) cube([thickness*3, thickness, thickness*3]);
    }
}

module twistHole(angle, x, y, width, thickness)
{
// http://msraynsford.blogspot.co.uk/2012/06/panel-joinery-10.html
    translate([x,y,0]) rotate([0,0,angle-90]) union()
    {
        cube([width, thickness, thickness*3], center=true);
        difference()
        {
            // Need some trig,  radius is hypo of triangle
            // Other sides are thinkness/2 and thinkness*3
            //
            //
           radius = sqrt(  ((thickness/2)*(thickness/2)) + (thickness*1.5*thickness*1.5) );
           translate([0,0, -thickness]) cylinder(h=thickness*3, r=radius);
           translate([-thickness*3/2,thickness,0]) cube([thickness*2, thickness, thickness*3], center=true);
           translate([thickness*3/2,-thickness,0]) cube([thickness*2, thickness, thickness*3], center=true);
        }
    }
}

module twistConnect(angle, x, y, thickness, max_y, min_y, max_x, min_x)
{
    // Really should do trianometry for non-90 Angles, but hey ho
    if( (angle == LEFT) || (angle == RIGHT) )
    {
        translate([0,y,-thickness]) rotate([0,0,angle+90]) union()
        {
            gap = max_x - min_x;
            translate([-gap/2-(thickness*3/2),0,0]) cube([gap, thickness, thickness*3]);
            translate([+gap/2+(thickness*3/2),0,0]) cube([gap, thickness, thickness*3]);
        }
    }
    if( (angle == UP) || (angle == DOWN) )
    {
        translate([x,0,-thickness]) rotate([0,0,angle+90]) union()
        {
            gap = max_y - min_y;
            echo(gap);
            translate([-gap/2-(thickness*3/2),0,0]) cube([gap, thickness, thickness*3]);
            translate([+gap/2+(thickness*3/2),0,0]) cube([gap, thickness, thickness*3]);
        }
    }
}

module clipInner(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) union()
    {
        translate([-thickness/2-1,0,0])
        {
            translate([-(1+thickness)/2,-thickness*10,-thickness]) cube([1, thickness*11, thickness*3]);
            translate([(1+thickness)/2+1,-thickness*8,0])  linear_extrude(height = thickness*3, center = true)  polygon(points=[[0,0],[0,9*thickness],[-(thickness-1), 9*thickness]]);
            translate([(1+thickness)/2+1-thickness+1,thickness-1,-thickness]) cube([thickness/2, thickness, thickness*3]);
            translate([-thickness*3/2,0,-thickness]) cube([thickness, thickness, thickness*3]);
        }
    }
}

module clipTab(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) union()
    {
        // make off-center
        translate([-thickness/2-1,0,0])
        {
            difference()
            {
                 translate([0,thickness/2,thickness/2]) cube([thickness+1,thickness,thickness], center=true);
                 translate([(1+thickness)/2+1,-thickness*8,0])  linear_extrude(height = thickness*3, center = true)  polygon(points=[[0,0],[0,9*thickness],[-(thickness-1), 9*thickness]]);
            }
           translate([-thickness,thickness,0])  linear_extrude(height = thickness)  polygon(points=[[0,0],[thickness+1,0],[thickness,thickness-1],[1,thickness-1]]);
        }
        translate([0.5,0,0]) cube([thickness,thickness,thickness]);
*       cube([thickness*2+1,thickness,thickness], center=true);
    }
}

module clipHole(angle, x, y, thickness)
{
    translate([x,y,0]) rotate([0,0,angle]) union()
    {
        translate([0,-thickness/2,thickness/2]) cube([thickness*2+1,thickness,thickness*3], center=true);
    }
}

module circlesAdd(radius, x, y, thickness)
{
    translate([x,y,0]) cylinder(h=thickness, r=radius);
}

module circlesRemove(radius, x, y, thickness)
{
    translate([x,y,-thickness]) cylinder(h=thickness*3, r=radius);
}

module simpleSlit(angle, x, y, length, thickness)
{
     translate([x,y,0]) rotate([0,0,angle-180]) translate([-thickness/2,-thickness,-thickness]) cube([thickness, length+thickness, thickness*3]);
}

module simpleCutouts(x, y, width, height, thickness)
{
     translate([x,y,0]) rotate([0,0,0]) translate([0,0,-thickness]) cube([width, height, thickness*3]);
}

module lasercutoutBox(thickness, x=0, y=0, z=0, sides=6, num_fingers=2,
        simple_tab_holes_a=[],
        captive_nuts_a=[], captive_nut_holes_a=[],
        screw_tab_holes_a=[],
        twist_holes_a=[],
        clip_holes_a=[],
        circles_add_a=[],
        circles_remove_a=[],
        slits_a = [],
        cutouts_a = [],
        milling_bit = 0.0
)
{

    if (sides==4)
    {
        fj = [
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers],    ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers],    ],
            [ [UP, 1, num_fingers], [DOWN, 0, num_fingers],    ],
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers],    ],
        ];
        translate([0,thickness,0]) lasercutoutBoxAdjustedFJ(thickness = thickness, x=x, y=y-thickness*2 , z=z-thickness*2, sides=sides, fj=fj,
            simple_tab_holes_a=simple_tab_holes_a,
            captive_nuts_a=captive_nuts_a, captive_nut_holes_a=captive_nut_holes_a,
            screw_tab_holes_a=screw_tab_holes_a,
            twist_holes_a=twist_holes_a,
            clip_holes_a=clip_holes_a,
            circles_add_a=circles_add_a,
            circles_remove_a=circles_remove_a,
            slits_a=slits_a,
            cutouts_a=cutouts_a,
            milling_bit = milling_bit
        );
    }
    if (sides==5)
    {
        st = [
        [[DOWN, -thickness/2, 0], [DOWN, -thickness/2, y-thickness] ],
        [[DOWN, -thickness/2, 0], ],
        [[UP, -thickness/2, z-thickness*2], ],
        ];
        fj = [
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers],   ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers],   ],
            [ [UP, 1, num_fingers], [DOWN, 0, num_fingers], [LEFT, 1, num_fingers],   ],
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers],   ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers], [LEFT, 0, num_fingers], [RIGHT, 1, num_fingers]  ],
        ];

        translate([thickness,thickness,0]) lasercutoutBoxAdjustedFJ(thickness = thickness, x=x-thickness, y=y-thickness*2 , z=z-thickness*2, sides=sides, fj=fj, st=st,
            simple_tab_holes_a=simple_tab_holes_a,
            captive_nuts_a=captive_nuts_a, captive_nut_holes_a=captive_nut_holes_a,
            screw_tab_holes_a=screw_tab_holes_a,
            twist_holes_a=twist_holes_a,
            clip_holes_a=clip_holes_a,
            circles_add_a=circles_add_a,
            circles_remove_a=circles_remove_a,
            slits_a=slits_a,
            cutouts_a=cutouts_a,
            milling_bit = milling_bit
        );

        }
    if (sides==6)
    {
        st = [
        [[DOWN, -thickness/2, 0], [DOWN, -thickness/2, y-thickness] , [RIGHT, x-thickness*2, -thickness/2]],
        [[DOWN, -thickness/2, 0], [RIGHT, x-thickness*2, -thickness/2]],
        [[UP, -thickness/2, z-thickness*2], [DOWN, x-thickness*1.5, 0], ],
        [[UP, z-thickness*1.5, y-thickness*2], ],
        ];
        fj = [
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers], [RIGHT, 0, num_fingers]  ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers], [RIGHT, 0, num_fingers]  ],
            [ [UP, 1, num_fingers], [DOWN, 0, num_fingers], [LEFT, 1, num_fingers], [RIGHT, 0, num_fingers]  ],
            [ [UP, 1, num_fingers], [DOWN, 1, num_fingers], [LEFT, 1, num_fingers], [RIGHT, 0, num_fingers]  ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers], [LEFT, 0, num_fingers], [RIGHT, 1, num_fingers]  ],
            [ [UP, 0, num_fingers], [DOWN, 1, num_fingers], [LEFT, 0, num_fingers], [RIGHT, 1, num_fingers]  ],
        ];
        translate([thickness,thickness,0]) lasercutoutBoxAdjustedFJ(thickness = thickness, x=x-thickness*2, y=y-thickness*2 , z=z-thickness*2, sides=sides, fj=fj, st=st,
            simple_tab_holes_a=simple_tab_holes_a,
            captive_nuts_a=captive_nuts_a, captive_nut_holes_a=captive_nut_holes_a,
            screw_tab_holes_a=screw_tab_holes_a,
            twist_holes_a=twist_holes_a,
            clip_holes_a=clip_holes_a,
            circles_add_a=circles_add_a,
            circles_remove_a=circles_remove_a,
            slits_a=slits_a,
            cutouts_a=cutouts_a,
            milling_bit = milling_bit
        );

    }
}

module lasercutoutBoxAdjustedFJ(thickness, x=0, y=0, z=0, sides=6, fj=[], st=[],
        simple_tab_holes_a=[],
        captive_nuts_a=[], captive_nut_holes_a = [],
        circles_add_a = [],
        circles_remove_a = [],
        slits_a = [],
        cutouts_a = [],
        milling_bit = 0.0
)
{

    translate([0,0,0]) lasercutoutSquare(thickness=thickness,x=x, y=y, simple_tabs = st[0], finger_joints = fj[0],
                                simple_tab_holes=simple_tab_holes_a[0], captive_nuts=captive_nuts_a[0],
                                captive_nut_holes = captive_nut_holes_a[0],
                                screw_tab_holes = screw_tab_holes_a[0],
                                twist_holes = twist_holes_a[0],
                                clip_holes = clip_holes_a[0],
                                circles_add = circles_add_a[0], circles_remove = circles_remove_a[0],
                                slits = slits_a[0],
                                cutouts = cutouts_a[0],
                                milling_bit = milling_bit);

    translate([0,0,z+thickness]) lasercutoutSquare(thickness=thickness,x=x, y=y, simple_tabs = st[1], finger_joints = fj[1],
                                simple_tab_holes=simple_tab_holes_a[1], captive_nuts=captive_nuts_a[1],
                                captive_nut_holes = captive_nut_holes_a[1],
                                screw_tab_holes = screw_tab_holes_a[1],
                                twist_holes = twist_holes_a[1],
                                clip_holes = clip_holes_a[1],
                                circles_add = circles_add_a[1], circles_remove = circles_remove_a[1],
                                slits = slits_a[1],
                                cutouts = cutouts_a[1],
                                milling_bit = milling_bit);

    translate([0,0,thickness]) rotate([90,0,0]) lasercutoutSquare(thickness=thickness,x=x, y=z, finger_joints = fj[2],
                                simple_tab_holes=simple_tab_holes_a[2], captive_nuts=captive_nuts_a[2],
                                captive_nut_holes = captive_nut_holes_a[2],
                                screw_tab_holes = screw_tab_holes_a[2],
                                twist_holes = twist_holes_a[2],
                                clip_holes = clip_holes_a[2],
                                circles_add = circles_add_a[2], circles_remove = circles_remove_a[2],
                                slits = slits_a[2],
                                cutouts = cutouts_a[2],
                                milling_bit = milling_bit);

    translate([0,y+thickness,thickness]) rotate([90,0,0]) lasercutoutSquare(thickness=thickness,x=x, y=z, simple_tabs = st[2],
                                finger_joints = fj[3],
                                simple_tab_holes=simple_tab_holes_a[3], captive_nuts=captive_nuts_a[3],
                                captive_nut_holes = captive_nut_holes_a[3],
                                screw_tab_holes = screw_tab_holes_a[3],
                                twist_holes = twist_holes_a[3],
                                clip_holes = clip_holes_a[3],
                                circles_add = circles_add_a[3], circles_remove = circles_remove_a[3],
                                slits = slits_a[3],
                                cutouts = cutouts_a[3],
                                milling_bit = milling_bit
                                );

    if (sides>4)
    {
        translate([0,0,thickness]) rotate([0,-90,0]) lasercutoutSquare(thickness=thickness,x=z, y=y, finger_joints = fj[4],
                                simple_tab_holes=simple_tab_holes_a[4], captive_nuts=captive_nuts_a[4],
                                captive_nut_holes = captive_nut_holes_a[4],
                                screw_tab_holes = screw_tab_holes_a[4],
                                twist_holes = twist_holes_a[4],
                                clip_holes = clip_holes_a[4],
                                circles_add = circles_add_a[4], circles_remove = circles_remove_a[4],
                                slits = slits_a[4],
                                cutouts = cutouts_a[4],
                                milling_bit = milling_bit);
        }

    if (sides>5)
    {
        translate([x+thickness,0,thickness]) rotate([0,-90,0]) lasercutoutSquare(thickness=thickness,x=z, y=y,
                                simple_tabs = st[3], finger_joints = fj[5],
                                simple_tab_holes=simple_tab_holes_a[5], captive_nuts=captive_nuts_a[5],
                                captive_nut_holes = captive_nut_holes_a[5],
                                screw_tab_holes = screw_tab_holes_a[5],
                                twist_holes = twist_holes_a[5],
                                clip_holes = clip_holes_a[5],
                                circles_add = circles_add_a[5], circles_remove = circles_remove_a[5],
                                slits = slits_a[5],
                                cutouts = cutouts_a[5],
                                milling_bit = milling_bit);
    }
}


Transitioning to a more elegant design w.r.t. the push buttons

function pythag(a, b) = sqrt(a*a + b*b);
function angle(a, b) = atan(a/b);

visualizeInternalComponents = false;

// this is the accuracy value for Shapeways' "Strong & Flexible Plastics" option
error = 0.15;

// note: AFAIK, "clearance" is a minimum gap in printed parts.  Here, however, it is used
// as a lesser/safer accuracy for gaps between the printed part and foreign objects such as
// circuit boards, which may not have been cut or measured with the same degree of precision.
clearance = 0.5;

containmentWallThick = 1;

nanoLength = 43.2;
nanoWidth = 18.0;
nanoHeightWithoutUsb = 5.4;
nanoHeightToUsbBase = 3.3;
nanoUsbWidth = 7.6;
nanoUsbHeight = 3.9;
nanoLeftMargin = 5;

chargerHeaderLength = 5.10;
chargerHeaderWidth = 2.56;

powerSwitchLength = 11.6;
powerSwitchWidth = 4.0;
powerSwitchDepth = 7.5;
powerSwitchOffset = 12;

ledDomeRadius = 2.5;
ledRimRadius = 2.9;

caseWidth = 70;
caseLength = 130;
caseHeight = 11;

wallThick = caseHeight/2;
lidThick = 1.5;
floorThick = 1.5;
lidMargin = 1;

fingerHeightOffset = 5;
fingerWellDepth = 10;
fingerRad = 15;
thumbWellDepth = wallThick;
thumbWellRadius = 30;
pushButtonWellWidth = 7;
pushButtonWellDepth = 4;
pushButtonBaseThick = 1;
pushButtonLegLength = 4;
pushButtonHeight = 5.0;
pushButtonPressDepth = 0.3;
//pushButtonRadius = 3.5/2;
pushButtonLegProtrusion = pushButtonLegLength - pushButtonBaseThick;
buttonThick = 8;
buttonWidth = pushButtonWellWidth;
buttonLength = 25;
buttonStabilizerWellWidth = 3;
buttonStabilizerRodHeight = pushButtonHeight - (pushButtonPressDepth + 0.5 + error);
totalFingerWellDepth = fingerWellDepth + buttonThick/2 + pushButtonPressDepth + pushButtonWellDepth;
totalThumbWellDepth = thumbWellDepth + buttonThick/2 + pushButtonPressDepth + pushButtonWellDepth;

buttonClearance = 0.3;

thumbBevelLength = 48;
thumbBevelWidth = 31;

thumbBevelAngle = angle(thumbBevelLength-wallThick,thumbBevelWidth-wallThick);
thumbBevelStretch = pythag(thumbBevelLength-wallThick, thumbBevelWidth-wallThick);

thumbKeyOffset = 23;

cavityWidth = caseWidth - wallThick - totalFingerWellDepth - pushButtonBaseThick;
cavityLength = caseLength - (2 * wallThick);

lidWidth = caseWidth - wallThick + lidMargin - totalFingerWellDepth + 3;
lidLength = caseLength - thumbBevelLength - wallThick + 2*lidMargin;

// button well with origin at the center of the base of the switch
// legs of the switch run along the x axis
module pushButtonWell(depth) {
    translate([-pushButtonWellWidth/2, -pushButtonWellWidth/2, 0]) {

		// square well for body of switch
        cube([pushButtonWellWidth,pushButtonWellWidth, depth]);

		// channels for legs/wires of switch
        translate([0,0,-pushButtonLegLength]) {
                translate([-1,0,0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([pushButtonWellWidth-1,0, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([-1,pushButtonWellWidth-2, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([pushButtonWellWidth-1,pushButtonWellWidth-2, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
        }
    }

    // rectangular well for button body, and stabilizer wells
    translate([-buttonLength/2,-buttonWidth/2,pushButtonWellDepth]) {
        cube([buttonLength,buttonWidth,buttonThick+pushButtonPressDepth+10]);

        translate([0,0,-pushButtonWellDepth]) {
            cube([buttonStabilizerWellWidth, buttonWidth, pushButtonWellDepth]);
		}

        translate([buttonLength-buttonStabilizerWellWidth,0,-pushButtonWellDepth]) {
            cube([buttonStabilizerWellWidth, buttonWidth, pushButtonWellDepth]);
		}
    }
}

module fingerWell(depth, radius) {
    translate([radius - depth,0,0]) {
        cylinder(h=caseHeight,r=radius);
    }

    translate([radius - depth, 0, wallThick]) {
        cylinder(h=wallThick+.001, r1=radius-wallThick/2, r2=radius+wallThick/2);
    }

    translate([radius - depth,0,0]) {
        cylinder(h=wallThick+.001, r2=radius-wallThick/2, r1=radius+wallThick/2);
    }
}

// create the lid
// buffer: hyper-extends the lid, for better rendering
// shrinkage: clearance around the edges of the lid
module lid(buffer, shrinkage) {
    translate([0,0,-buffer]) {
        translate([wallThick-lidMargin+shrinkage,wallThick-lidMargin+shrinkage,0]) {
            cube([lidWidth,lidLength,lidThick+buffer]);
        }
        translate([thumbBevelWidth,wallThick-lidMargin+shrinkage,0]) {
            cube([lidWidth-thumbBevelWidth+wallThick,cavityLength+(lidMargin-shrinkage)*2,lidThick+buffer]);
        }

        // note: currently no "shrinkage" on this edge
        translate([thumbBevelWidth,caseLength-wallThick,caseHeight]) {
            rotate([0,0,180+thumbBevelAngle]) {
                rotate([0,90,0]) {
                    translate([0,0,thumbKeyOffset]) {
                        rotate([0,90,-90]) {
                            translate([0,wallThick,wallThick-totalThumbWellDepth]) {
                                rotate([180,0,0]) {
                                    translate([-27,-wallThick,pushButtonBaseThick]) {
                                        translate([0,0,-6]) {
                                            cube([47,lidThick+buffer,20]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

module button() {
    difference() {
        union() {
                    translate([buttonClearance,buttonWidth/2,buttonWidth/2]) {
                        rotate([0,90,0]) { cylinder(h=buttonLength-2*buttonClearance,r=buttonWidth/2-buttonClearance); }
                    }

                    translate([buttonClearance,buttonClearance,buttonWidth/2]) {
                        cube([buttonLength-2*buttonClearance,buttonWidth-2*buttonClearance,buttonThick-buttonWidth/2]);
                    }

                    translate([buttonClearance,buttonClearance,buttonThick]) {
                        cube([buttonStabilizerWellWidth-2*buttonClearance, buttonWidth-2*buttonClearance, buttonStabilizerRodHeight]);
		            }

                    translate([buttonLength-buttonStabilizerWellWidth+buttonClearance,buttonClearance,buttonThick]) {
                        cube([buttonStabilizerWellWidth-2*buttonClearance, buttonWidth-2*buttonClearance, buttonStabilizerRodHeight]);
		            }
        }

        translate([buttonClearance+1,0,0]) { cube([1,buttonWidth,2]); }
        translate([buttonLength-buttonClearance-2,0,0]) { cube([1,buttonWidth,2]); }

        //translate([0,buttonWidth/2,buttonWidth/2]) {
        //    rotate([0,90,0]) { cylinder(h=buttonLength+1,r=buttonWidth/3); }
        //}

        //translate([buttonLength/2,buttonWidth/2,buttonThick-0.5]) {
        //    cylinder(h=1,r=pushButtonRadius);
        //}
    }
}

module screwHoles() {
    translate([0,0,-1]) {
        translate([15,caseLength-thumbBevelLength-wallThick+9,0]) { cylinder(h=caseHeight+2,r=1.5); }

        translate([wallThick+cavityWidth+2.5,caseLength-fingerHeightOffset-fingerRad*2,0]) { cylinder(h=caseHeight+2,r=1.5); }
        translate([wallThick+cavityWidth+2.5,caseLength-fingerHeightOffset-fingerRad*4,0]) { cylinder(h=caseHeight+2,r=1.5); }
        translate([wallThick+cavityWidth+2.5,caseLength-fingerHeightOffset-fingerRad*6,0]) { cylinder(h=caseHeight+2,r=1.5); }
    }
}

module caseConvexHull() {
		// box with thumb bevel
        difference() {
            translate([wallThick, wallThick,0]) {
                cube([caseWidth-caseHeight,caseLength-caseHeight,caseHeight]);
            }
            translate([thumbBevelWidth,caseLength-wallThick,-1]) {
                rotate([0,0,thumbBevelAngle]) {
                    rotate([0,-90,0]) {
                        cube([caseHeight+1, 100, thumbBevelStretch]);
                    }
                }
            }
        }

        translate([wallThick,wallThick,wallThick]) {
            sphere(wallThick);
            rotate([-90,0,0]) {
                cylinder(h=caseLength-thumbBevelLength-wallThick, r=wallThick);
            }
            rotate([0,90,0]) {
                cylinder(h=caseWidth-caseHeight, r=wallThick);
            }
        }
        translate([caseWidth-wallThick,wallThick,wallThick]) {
            sphere(wallThick);
            rotate([-90,0,0]) {
                cylinder(h=caseLength-caseHeight, r=wallThick);
            }
        }
        translate([caseWidth-wallThick,caseLength-wallThick,wallThick]) {
            sphere(wallThick);
        }

		// thumb bevel
		translate([wallThick,caseLength-thumbBevelLength,wallThick]) {
            sphere(wallThick);
        }
        translate([thumbBevelWidth,caseLength-wallThick,wallThick]) {
            sphere(wallThick);
            rotate([0,90,0]) {
                cylinder(h=caseWidth-thumbBevelWidth-wallThick, r=wallThick);
            }
            rotate([0,0,180+thumbBevelAngle]) {
                rotate([0,90,0]) {
                    cylinder(h=thumbBevelStretch, r=wallThick);
                }
            }
        }
}

module basicCase() {
  difference() {
    caseConvexHull();

    // inner compartment
    translate([wallThick,wallThick,lidThick]) {
        cube([cavityWidth,caseLength-thumbBevelLength-wallThick,caseHeight-floorThick-lidThick]);
    }
    translate([thumbBevelWidth+2,wallThick,lidThick]) {
        cube([cavityWidth-thumbBevelWidth+wallThick-2,cavityLength,caseHeight-floorThick-lidThick]);
    }

    /*
    // depression for lid
    lid(1,0);
    */

    screwHoles();

    // finger button wells
    for (i = [0:3]) {
        translate([
            caseWidth,
            caseLength - fingerHeightOffset - fingerRad * (1 + 2 * i),
        0]) {

            fingerWell(fingerWellDepth, fingerRad);

            // well and channels for push button switch and wires
            translate([-totalFingerWellDepth,0,caseHeight/2]) {
                rotate([0,90,0]) { rotate([0,0,90]) {
                    pushButtonWell(pushButtonWellDepth+fingerRad);
                }}
            }
        }
    }

    // thumb button well
    translate([thumbBevelWidth,caseLength-wallThick,caseHeight]) {
        rotate([0,0,180+thumbBevelAngle]) {
            rotate([0,90,0]) {
                translate([0,0,thumbKeyOffset]) {
                    rotate([0,90,0]) { rotate([0,0,-90]) {
                        //cube([50,100,200]);

                        translate([wallThick,0,0]) {
                            fingerWell(thumbWellDepth, thumbWellRadius);
                        }
                    }}

                    rotate([0,90,-90]) {
                        translate([0,wallThick,wallThick-totalThumbWellDepth]) {
                            pushButtonWell(pushButtonWellDepth+100);

                            rotate([180,0,0]) {
                                translate([-27,-wallThick+lidThick,pushButtonBaseThick]) {
                                    cube([39,caseHeight-floorThick-lidThick,15]);
                                    cube([22,caseHeight-floorThick-lidThick,20]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // hole for status LED
    translate([cavityWidth+wallThick-ledRimRadius-3,caseLength+1,wallThick]) {
    	    rotate(a=[90,0,0]) {
            cylinder(h=wallThick+2,r=ledDomeRadius+error);

            // note: the rim depression uses a larger error/clearance, since it doesn't need
            // to fit tightly and can't be filed down
            translate([0,0,wallThick]) {
                cylinder(h=10+1,r=ledRimRadius+clearance);
            }
        }
    }

    // hole for battery charger headers
	translate([wallThick,0,caseHeight-floorThick-chargerHeaderLength-2*error]) {
        cube([chargerHeaderWidth+2*error,wallThick,chargerHeaderLength+2*error]);
    }

    // hole for SPDT Mini Power Switch
    translate([powerSwitchOffset,0,wallThick-powerSwitchWidth/2-error]) {
        cube([powerSwitchLength+2*error,wallThick,powerSwitchWidth+2*error]);
    }

    // hole for USB port
    translate([wallThick+cavityWidth-nanoLeftMargin-nanoWidth/2-nanoUsbWidth/2-clearance,0,caseHeight-floorThick-nanoHeightToUsbBase-nanoUsbHeight-clearance]) {
        cube([nanoUsbWidth+2*clearance,wallThick,nanoUsbHeight+clearance]);
    }
    // trim off the thin remainder above the USB port which would be problematic to print,
    // and make it harder to get the Nano into its socket anyway
    translate([wallThick+cavityWidth-nanoLeftMargin-nanoWidth/2-nanoUsbWidth/2-clearance,wallThick-lidMargin,0]) {
        cube([nanoUsbWidth+2*clearance,lidMargin,2]);
    }
  }
}

difference() {
    basicCase();
    cube([caseWidth, caseLength, (caseHeight-buttonWidth)/2+0.0001]);
}

translate([caseWidth + 10, 0, 0]) {
    difference() {
        basicCase();
        translate([0,0,(caseHeight-buttonWidth)/2]) {
            cube([caseWidth, caseLength, caseHeight]);
        }
    }
}

/*
// lid
translate([0,0,caseHeight + 2]) {
    difference() {
       // the gap of 0.4 was determined by taking into account the 0.15mm accuracy of
       // the device and the 0.15% error by longest axis of the material, keeping in mind
	   // that there are always a pair of gaps across the lid from each other.
       // 0.4mm is actually larger than necessary in the horizontal (narrower) dimension.
       lid(0,0.4);

       screwHoles();
    }
}
*/

// buttons
// Note: the buttons are oriented so as to make the longest surfaces the most smooth
translate([-5,0,10]) {
    for (i = [0:4]) {
        translate([0,i*(buttonLength+2),0]) { rotate([90,180,-90]) {
            //cube([10,20,40]);

            button();
        }}
    }
}

// electronic components
translate([wallThick,wallThick,0]) {
    // power switch
    translate([powerSwitchOffset-wallThick,0,wallThick-powerSwitchWidth/2-error]) {
        translate([-containmentWallThick,0,0]) {
            cube([containmentWallThick,powerSwitchDepth-wallThick+error+containmentWallThick,caseHeight-floorThick-wallThick+powerSwitchWidth/2+error]);
        }
        translate([powerSwitchLength+2*error,0,0]) {
            cube([containmentWallThick,powerSwitchDepth-wallThick+error+containmentWallThick,caseHeight-floorThick-wallThick+powerSwitchWidth/2+error]);
        }
        translate([-containmentWallThick,0,powerSwitchWidth+2*error]) {
            cube([powerSwitchLength+2*(containmentWallThick+error),powerSwitchDepth-wallThick+error+containmentWallThick,caseHeight-floorThick-wallThick-powerSwitchWidth/2-error]);
        }
        translate([-containmentWallThick,powerSwitchDepth-wallThick+error,powerSwitchWidth+2*error-1]) {
            cube([powerSwitchLength+2*(containmentWallThick+error),containmentWallThick,1]);
        }
    }

    // container for Arduino Nano v3.0
    translate([cavityWidth-nanoLeftMargin-nanoWidth,0,0]) {
        translate([0,0,caseHeight-floorThick-nanoHeightToUsbBase-error]) {
            translate([-containmentWallThick-clearance,0,0]) {
                cube([containmentWallThick,nanoLength+clearance+containmentWallThick,nanoHeightToUsbBase+error]);
            }
            translate([nanoWidth+clearance,0,0]) {
                cube([containmentWallThick,nanoLength+clearance+containmentWallThick,nanoHeightToUsbBase+error]);
            }
            translate([-containmentWallThick-clearance,nanoLength+clearance,0]) {
                cube([nanoWidth+2*(clearance+containmentWallThick),containmentWallThick,nanoHeightToUsbBase+error]);
            }
        }
    }

    if (visualizeInternalComponents) {
        // Arduino Nano v3.0
        translate([0,0,-10]) {
            cube([nanoWidth,nanoLength,nanoHeightWithoutUsb]);
        }

        // Surface Transducer - Small
        translate([thumbBevelWidth-wallThick+4,caseLength-2*wallThick-21.4-4,-10]) {
           cube([13.8,21.4,7.9]);
        }
        // Bluetooth Modem - BlueSMiRF Silver -- 42.0 x 16.0 x 3.9
        translate([1,31,-10]) { cube([16,42,3.9]); }
        // Polymer Lithium Ion Battery - 110mAh
        translate([-40,3,-10]) { cube([12,28,5.7]); }
        // Polymer Lithium Ion Battery - 400mAh
	    translate([18,47,-10]) { cube([25,35,5]); }
        // Triple Axis Accelerometer & Gyro Breakout - MPU-6050
        translate([1,4,-10]) { cube([15.5, 25.7, 2.5]); }
    }
}

function pythag(a, b) = sqrt(a*a + b*b);
function angle(a, b) = atan(a/b);

includeInternalComponents = true;

// this is the accuracy value for Shapeways' "Strong & Flexible Plastics" option
error = 0.15;

// note: AFAIK, "clearance" is a minimum gap in printed parts.  Here, however, it is used
// as a lesser/safer accuracy for gaps between the printed part and foreign objects such as
// circuit boards, which may not have been cut or measured with the same degree of precision.
clearance = 0.5;

containmentWallThick = 1;

nanoLength = 43.2;
nanoWidth = 18.0;
nanoHeightWithoutUsb = 5.4;
nanoHeightToUsbBase = 3.3;
nanoUsbWidth = 7.6;
nanoUsbHeight = 3.9;
nanoLeftMargin = 5;

chargerHeaderLength = 5.10;
chargerHeaderWidth = 2.56;

powerSwitchLength = 11.6;
powerSwitchWidth = 4.0;
powerSwitchDepth = 7.5;
powerSwitchOffset = 12;

caseWidth = 70;
caseLength = 130;
caseHeight = 11;

wallThick = caseHeight/2;
lidThick = 1.5;
floorThick = 1.5;
lidMargin = 1;

fingerHeightOffset = 5;
fingerWellDepth = 10;
fingerRad = 15;
thumbWellDepth = wallThick;
thumbWellRadius = 30;
pushButtonWellWidth = 7;
pushButtonWellDepth = 4;
pushButtonBaseThick = 1;
pushButtonLegLength = 4;
pushButtonRadius = 3.5/2;
pushButtonLegProtrusion = pushButtonLegLength - pushButtonBaseThick;
buttonThick = 8;
buttonPressDepth = 0.3;
buttonWidth = pushButtonWellWidth;
buttonLength = 25;
buttonStabilizerWellWidth = 3;
buttonStabilizerRodHeight = pushButtonWellDepth - 1;
totalFingerWellDepth = fingerWellDepth + buttonThick/2 + buttonPressDepth + pushButtonWellDepth;
totalThumbWellDepth = thumbWellDepth + buttonThick/2 + buttonPressDepth + pushButtonWellDepth;

ledDomeRadius = 2.6;
ledRimRadius = 3.1;

thumbBevelLength = 48;
thumbBevelWidth = 31;

thumbBevelAngle = angle(thumbBevelLength-wallThick,thumbBevelWidth-wallThick);
thumbBevelStretch = pythag(thumbBevelLength-wallThick, thumbBevelWidth-wallThick);

thumbKeyOffset = 23;

cavityWidth = caseWidth - wallThick - totalFingerWellDepth - pushButtonBaseThick;
cavityLength = caseLength - (2 * wallThick);

lidWidth = caseWidth - wallThick + lidMargin - totalFingerWellDepth + 3;
lidLength = caseLength - thumbBevelLength - wallThick + 2*lidMargin;

// button well with origin at the center of the base of the switch
// legs of the switch run along the x axis
module pushButtonWell(depth) {
    translate([-pushButtonWellWidth/2, -pushButtonWellWidth/2, 0]) {

		// square well for body of switch
        cube([pushButtonWellWidth,pushButtonWellWidth, depth]);

		// channels for legs/wires of switch
        translate([0,0,-pushButtonLegLength]) {
                translate([-1,0,0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([pushButtonWellWidth-1,0, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([-1,pushButtonWellWidth-2, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([pushButtonWellWidth-1,pushButtonWellWidth-2, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
        }
    }

    // rectangular well for button body, and stabilizer wells
    translate([-buttonLength/2,-buttonWidth/2,pushButtonWellDepth]) {
        cube([buttonLength,buttonWidth,buttonThick+buttonPressDepth+10]);

        translate([0,0,-pushButtonWellDepth]) {
            cube([buttonStabilizerWellWidth, buttonWidth, pushButtonWellDepth]);
		}

        translate([buttonLength-buttonStabilizerWellWidth,0,-pushButtonWellDepth]) {
            cube([buttonStabilizerWellWidth, buttonWidth, pushButtonWellDepth]);
		}
    }
}

module fingerWell(depth, radius) {
    translate([radius - depth,0,0]) {
        cylinder(h=caseHeight,r=radius);
    }

    translate([radius - depth, 0, wallThick]) {
        cylinder(h=wallThick+.001, r1=radius-wallThick/2, r2=radius+wallThick/2);
    }

    translate([radius - depth,0,0]) {
        cylinder(h=wallThick+.001, r2=radius-wallThick/2, r1=radius+wallThick/2);
    }
}

// create the lid
// buffer: hyper-extends the lid, for better rendering
// shrinkage: clearance around the edges of the lid
module lid(buffer, shrinkage) {
    translate([0,0,-buffer]) {
        translate([wallThick-lidMargin+shrinkage,wallThick-lidMargin+shrinkage,0]) {
            cube([lidWidth,lidLength,lidThick+buffer]);
        }
        translate([thumbBevelWidth,wallThick-lidMargin+shrinkage,0]) {
            cube([lidWidth-thumbBevelWidth+wallThick,cavityLength+(lidMargin-shrinkage)*2,lidThick+buffer]);
        }

        // note: currently no "shrinkage" on this edge
        translate([thumbBevelWidth,caseLength-wallThick,caseHeight]) {
            rotate([0,0,180+thumbBevelAngle]) {
                rotate([0,90,0]) {
                    translate([0,0,thumbKeyOffset]) {
                        rotate([0,90,-90]) {
                            translate([0,wallThick,wallThick-totalThumbWellDepth]) {
                                rotate([180,0,0]) {
                                    translate([-27,-wallThick,pushButtonBaseThick]) {
                                        translate([0,0,-6]) {
                                            cube([47,lidThick+buffer,20]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

module screwHoles() {
    translate([0,0,-1]) {
        translate([15,caseLength-thumbBevelLength-wallThick+9,0]) { cylinder(h=caseHeight+2,r=1.5); }

        translate([wallThick+cavityWidth+3.5,caseLength-fingerHeightOffset-fingerRad*2,0]) { cylinder(h=caseHeight+2,r=1.5); }
        translate([wallThick+cavityWidth+3.5,caseLength-fingerHeightOffset-fingerRad*4,0]) { cylinder(h=caseHeight+2,r=1.5); }
        translate([wallThick+cavityWidth+3.5,caseLength-fingerHeightOffset-fingerRad*6,0]) { cylinder(h=caseHeight+2,r=1.5); }
    }
}

difference() {
    // basic shape of the case
    union() {
		// box with thumb bevel
        difference() {
            translate([wallThick, wallThick,0]) {
                cube([caseWidth-caseHeight,caseLength-caseHeight,caseHeight]);
            }
            translate([thumbBevelWidth,caseLength-wallThick,-1]) {
                rotate([0,0,thumbBevelAngle]) {
                    rotate([0,-90,0]) {
                        cube([caseHeight+1, 100, thumbBevelStretch]);
                    }
                }
            }
        }

        translate([wallThick,wallThick,wallThick]) {
            sphere(wallThick);
            rotate([-90,0,0]) {
                cylinder(h=caseLength-thumbBevelLength-wallThick, r=wallThick);
            }
            rotate([0,90,0]) {
                cylinder(h=caseWidth-caseHeight, r=wallThick);
            }
        }
        translate([caseWidth-wallThick,wallThick,wallThick]) {
            sphere(wallThick);
            rotate([-90,0,0]) {
                cylinder(h=caseLength-caseHeight, r=wallThick);
            }
        }
        translate([caseWidth-wallThick,caseLength-wallThick,wallThick]) {
            sphere(wallThick);
        }

		// thumb bevel
		translate([wallThick,caseLength-thumbBevelLength,wallThick]) {
            sphere(wallThick);
        }
        translate([thumbBevelWidth,caseLength-wallThick,wallThick]) {
            sphere(wallThick);
            rotate([0,90,0]) {
                cylinder(h=caseWidth-thumbBevelWidth-wallThick, r=wallThick);
            }
            rotate([0,0,180+thumbBevelAngle]) {
                rotate([0,90,0]) {
                    cylinder(h=thumbBevelStretch, r=wallThick);
                }
            }
        }
    }

    // inner compartment
    translate([wallThick,wallThick,0]) {
        cube([cavityWidth,caseLength-thumbBevelLength-wallThick,caseHeight-floorThick]);
    }
    translate([thumbBevelWidth+2,wallThick,0]) {
        cube([cavityWidth-thumbBevelWidth+wallThick-2,cavityLength,caseHeight-floorThick]);
    }

    // depression for lid
    lid(1,0);

    screwHoles();

    // finger button wells
    for (i = [0:3]) {
        translate([
            caseWidth,
            caseLength - fingerHeightOffset - fingerRad * (1 + 2 * i),
        0]) {

            fingerWell(fingerWellDepth, fingerRad);

            // well and channels for push button switch and wires
            translate([-totalFingerWellDepth,0,caseHeight/2]) {
                rotate([0,90,0]) { rotate([0,0,90]) {
                    pushButtonWell(pushButtonWellDepth+fingerRad);
                }}
            }
        }
    }

    // thumb button well
    translate([thumbBevelWidth,caseLength-wallThick,caseHeight]) {
        rotate([0,0,180+thumbBevelAngle]) {
            rotate([0,90,0]) {
                translate([0,0,thumbKeyOffset]) {
                    rotate([0,90,0]) { rotate([0,0,-90]) {
                        //cube([50,100,200]);

                        translate([wallThick,0,0]) {
                            fingerWell(thumbWellDepth, thumbWellRadius);
                        }
                    }}

                    rotate([0,90,-90]) {
                        translate([0,wallThick,wallThick-totalThumbWellDepth]) {
                            pushButtonWell(pushButtonWellDepth+100);

                            rotate([180,0,0]) {
                                translate([-27,-wallThick-1,pushButtonBaseThick]) {
                                    cube([39,caseHeight-floorThick+1,15]);
                                    cube([22,caseHeight-floorThick+1,20]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // hole for status LED
    translate([cavityWidth+wallThick-ledRimRadius-3,caseLength+1,wallThick]) {
    	    rotate(a=[90,0,0]) {
            cylinder(h=wallThick+2,r=ledDomeRadius);

            translate([0,0,wallThick]) {
                cylinder(h=10+1,r=ledRimRadius);
            }
        }
    }

    // hole for battery charger headers
	translate([wallThick,0,caseHeight-floorThick-chargerHeaderLength-2*error]) {
        cube([chargerHeaderWidth+2*error,wallThick,chargerHeaderLength+2*error]);
    }

    // hole for SPDT Mini Power Switch
    translate([powerSwitchOffset,0,wallThick-powerSwitchWidth/2-error]) {
        cube([powerSwitchLength+2*error,wallThick,powerSwitchWidth+2*error]);
    }

    // hole for USB port
    translate([wallThick+cavityWidth-nanoLeftMargin-nanoWidth/2-nanoUsbWidth/2-clearance,0,caseHeight-floorThick-nanoHeightToUsbBase-nanoUsbHeight-clearance]) {
        cube([nanoUsbWidth+2*clearance,wallThick,nanoUsbHeight+clearance]);
    }
    // trim off the thin remainder above the USB port which would be problematic to print,
    // and make it harder to get the Nano into its socket anyway
    translate([wallThick+cavityWidth-nanoLeftMargin-nanoWidth/2-nanoUsbWidth/2-clearance,wallThick-lidMargin,0]) {
        cube([nanoUsbWidth+2*clearance,lidMargin,2]);
    }
}

// lid
translate([0,0,caseHeight + 2]) {
    difference() {
       // the gap of 0.4 was determined by taking into account the 0.15mm accuracy of
       // the device and the 0.15% error by longest axis of the material, keeping in mind
	   // that there are always a pair of gaps across the lid from each other.
       // 0.4mm is actually larger than necessary in the horizontal (narrower) dimension.
       lid(0,0.4);

       screwHoles();
    }
}

// buttons
// Note: the buttons are oriented so as to make the longest surfaces the most smooth
translate([-5,0,10]) {
    for (i = [0:4]) {
        translate([0,i*(buttonLength+2),0]) { rotate([90,180,-90]) {
            //cube([10,20,40]);

            difference() {
                union() {
                    translate([0,buttonWidth/2,buttonWidth/2]) {
                        rotate([0,90,0]) { cylinder(h=buttonLength,r=buttonWidth/2); }
                    }

                    translate([0,0,buttonWidth/2]) {
                        cube([buttonLength,buttonWidth,buttonThick-buttonWidth/2]);
                    }

                    translate([0,0,buttonThick]) {
                        cube([buttonStabilizerWellWidth, buttonWidth, buttonStabilizerRodHeight]);
		            }

                    translate([buttonLength-buttonStabilizerWellWidth,0,buttonThick]) {
                        cube([buttonStabilizerWellWidth, buttonWidth, buttonStabilizerRodHeight]);
		            }
                }

                translate([buttonLength/2,buttonWidth/2,buttonThick-0.5]) {
                    cylinder(h=1,r=pushButtonRadius);
                }
            }
        }}
    }
}

// electronic components
translate([wallThick,wallThick,0]) {
    // power switch
    translate([powerSwitchOffset-wallThick,0,wallThick-powerSwitchWidth/2-error]) {
        translate([-containmentWallThick,0,0]) {
            cube([containmentWallThick,powerSwitchDepth-wallThick+error+containmentWallThick,caseHeight-floorThick-wallThick+powerSwitchWidth/2+error]);
        }
        translate([powerSwitchLength+2*error,0,0]) {
            cube([containmentWallThick,powerSwitchDepth-wallThick+error+containmentWallThick,caseHeight-floorThick-wallThick+powerSwitchWidth/2+error]);
        }
        translate([-containmentWallThick,0,powerSwitchWidth+2*error]) {
            cube([powerSwitchLength+2*(containmentWallThick+error),powerSwitchDepth-wallThick+error+containmentWallThick,caseHeight-floorThick-wallThick-powerSwitchWidth/2-error]);
        }
        translate([-containmentWallThick,powerSwitchDepth-wallThick+error,powerSwitchWidth+2*error-1]) {
            cube([powerSwitchLength+2*(containmentWallThick+error),containmentWallThick,1]);
        }
    }

    // Arduino Nano v3.0
    translate([cavityWidth-nanoLeftMargin-nanoWidth,0,0]) {
        if (includeInternalComponents) {
            translate([0,0,-10]) {
                cube([nanoWidth,nanoLength,nanoHeightWithoutUsb]);
            }
        }

        translate([0,0,caseHeight-floorThick-nanoHeightToUsbBase-error]) {
            translate([-containmentWallThick-clearance,0,0]) {
                cube([containmentWallThick,nanoLength+clearance+containmentWallThick,nanoHeightToUsbBase+error]);
            }
            translate([nanoWidth+clearance,0,0]) {
                cube([containmentWallThick,nanoLength+clearance+containmentWallThick,nanoHeightToUsbBase+error]);
            }
            translate([-containmentWallThick-clearance,nanoLength+clearance,0]) {
                cube([nanoWidth+2*(clearance+containmentWallThick),containmentWallThick,nanoHeightToUsbBase+error]);
            }
        }
    }

    if (includeInternalComponents) {
    // Surface Transducer - Small
    translate([thumbBevelWidth-wallThick+4,caseLength-2*wallThick-21.4-4,-10]) {
       cube([13.8,21.4,7.9]);
    }
    // Bluetooth Modem - BlueSMiRF Silver -- 42.0 x 16.0 x 3.9
    translate([1,31,-10]) { cube([16,42,3.9]); }
    // Polymer Lithium Ion Battery - 110mAh
    translate([-40,3,-10]) { cube([12,28,5.7]); }
    // Polymer Lithium Ion Battery - 400mAh
	translate([18,47,-10]) { cube([25,35,5]); }
    // Triple Axis Accelerometer & Gyro Breakout - MPU-6050
    translate([1,4,-10]) { cube([15.5, 25.7, 2.5]); }
    }
}


Add possibility to use colsons

Add possibility to use colsons

tube_diameter = 28;
space_margin = 1;
thickness = 2;
screw_diameter = 5;
screw_head_thickness = 2;

a = tube_diameter + 2* space_margin +2*thickness;
difference(){
	union(){
		//Main part
		difference(){
		cube(size=[a,a,a+4], center = true);
		translate([a/4, 0,0]) cube(size=[4,2*a, 2*a], center = true);
		translate([-a/4, 0,0]) cube(size=[4,2*a, 2*a], center = true);
		}
		//Screw tube
		translate([0, a/2+screw_diameter/2,0]) difference(){
			cylinder(r = screw_diameter/2+thickness, h = a, center=				true);
			cylinder(r = screw_diameter/2, h = a, center=true);
		}
		//Second screw tube
		translate([0, -a/2-screw_diameter/2,0]) difference(){
			cylinder(r = screw_diameter/2+thickness, h = a, center=				true);
			cylinder(r = screw_diameter/2, h = a, center=true);

		}
	rotate([0,90,0])  cylinder(r=tube_diameter/2. + space_margin+thickness, h= a, center = 	true);
	}
	rotate([0,90,0])  cylinder(r=tube_diameter/2. + space_margin, h= 2*a, center = true);
   cube(size =[2*a, 2*a,tube_diameter/5.], center = true);
	translate([0,-a/2-screw_diameter/2,a/2]) cylinder(r = screw_diameter/2+thickness+0.1, h = 2*screw_head_thickness, center=				true);
	translate([0,-a/2-screw_diameter/2,-a/2]) cylinder(r = screw_diameter/2+thickness+0.1, h = 2*screw_head_thickness, center=				true);
	translate([0,+a/2+screw_diameter/2,a/2]) cylinder(r = screw_diameter/2+thickness+0.1, h = 2*screw_head_thickness, center=				true);
	translate([0,+a/2+screw_diameter/2,-a/2]) cylinder(r = screw_diameter/2+thickness+0.1, h = 2*screw_head_thickness, center=				true);

	// To erase one half
	translate([0, 0, a]) cube([2*a,2*a,2*a], center = true);
}

tube_diameter = 28;
space_margin = 1;
thickness = 5;
screw_diameter = 5;
screw_head_thickness = 5;

a = tube_diameter + 2* space_margin +2*thickness;
difference(){
	union(){
		//Main part
		cube(size=[a,a,a], center = true);

		//Screw tube
		translate([0, a/2+screw_diameter/2,0]) difference(){
			cylinder(r = screw_diameter/2+thickness, h = a, center=				true);
			cylinder(r = screw_diameter/2, h = a, center=true);
		}
		//Second screw tube
		translate([0, -a/2-screw_diameter/2,0]) difference(){
			cylinder(r = screw_diameter/2+thickness, h = a, center=				true);
			cylinder(r = screw_diameter/2, h = a, center=true);

		}
	}
	rotate([0,90,0])  cylinder(r=tube_diameter/2. + space_margin, h= 2*a, center = true);
   cube(size =[2*a, 2*a,tube_diameter/5.], center = true);
	translate([0,-a/2-screw_diameter/2,a/2]) cylinder(r = screw_diameter/2+thickness+0.1, h = 2*screw_head_thickness, center=				true);
	translate([0,-a/2-screw_diameter/2,-a/2]) cylinder(r = screw_diameter/2+thickness+0.1, h = 2*screw_head_thickness, center=				true);
	translate([0,+a/2+screw_diameter/2,a/2]) cylinder(r = screw_diameter/2+thickness+0.1, h = 2*screw_head_thickness, center=				true);
	translate([0,+a/2+screw_diameter/2,-a/2]) cylinder(r = screw_diameter/2+thickness+0.1, h = 2*screw_head_thickness, center=				true);
}