rodclamps: make tighter/clamp more

rodclamps: make tighter/clamp more

include <thing_libutils/attach.scad>
include <config.scad>

mount_rod_clamp_conn_rod = [[0,0,0],[1,0,0]];

module mount_rod_clamp_half(rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4, orient=[0,0,1])
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?outer_d+thread_dia+thick_:screw_dist;
    base_thick_=base_thick==undef?thick_*1.5:base_thick;

    orient(orient)
    difference()
    {
        clamp_tolerance = 0.5*mm;
        union()
        {
            // cylinder around rod
            fncylindera(d=outer_d, h=width, orient=[0,0,1], align=[0,0,0]);

            // base
            cubea([base_thick_, screw_dist_+thread_dia*2.5, width], align=[1,0,0]);
        }

        // cut bottom of cylinder
        cubea([outer_d/2+.1, screw_dist_+thread_dia*2.5+.1, width+1], align=[-1,0,0], extrasize=[clamp_tolerance,0,0], extrasize_align=[1,0,0]);

        // cut clamp screw holes
        for(i=[-1,1])
        translate([0, i*screw_dist_/2, 0])
        {
            fncylindera(d=thread_dia, h=base_thick_*3, orient=[1,0,0]);
        }

        // cut zrod
        fncylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=[0,0,1]);
    }
}

module mount_rod_clamp_full(rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4, orient=[0,0,1])
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?outer_d+thread_dia*2+thick_:screw_dist;
    base_thick_=base_thick==undef?thick_*1.5:base_thick;

    orient(orient)
    difference()
    {
        clamp_tolerance = 0.5*mm;
        base_cut = -rod_d/2 + clamp_tolerance;
        union()
        {
            // cylinder around rod
            fncylindera(d=outer_d, h=width, orient=[0,0,1], align=[0,0,0]);

            // base
            translate([base_cut,0,0])
            cubea([base_thick_, screw_dist_+thread_dia*2.5, width], align=[1,0,0]);
        }

        // cut bottom of cylinder
        translate([base_cut,0,0])
            cubea([outer_d/2+.1, outer_d+.1, width+1], align=[-1,0,0]);

        // cut clamp screw holes
        for(i=[-1,1])
        translate([0, i*screw_dist_/2, 0])
        {
            fncylindera(d=thread_dia, h=base_thick_*3, orient=[1,0,0]);
        }

        // cut zrod
        fncylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=[0,0,1]);
    }
}

/*translate([20,0,0])*/
/*mount_rod_clamp_half(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5);*/
/*mount_rod_clamp_full(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5);*/

include <thing_libutils/attach.scad>
include <config.scad>

mount_rod_clamp_conn_rod = [[0,0,0],[1,0,0]];

module mount_rod_clamp_half(rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4, orient=[0,0,1])
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?outer_d+thread_dia+thick_:screw_dist;
    base_thick_=base_thick==undef?thick_*1.5:base_thick;

    orient(orient)
    difference()
    {
        union()
        {
            // cylinder around rod
            fncylindera(d=outer_d, h=width, orient=[0,0,1], align=[0,0,0]);

            // base
            cubea([base_thick_, screw_dist_+thread_dia*2.5, width], align=[1,0,0]);
        }

        // cut bottom of cylinder
        cubea([outer_d/2+.1, outer_d+.1, width+1], align=[-1,0,0]);

        // cut clamp screw holes
        for(i=[-1,1])
        translate([0, i*screw_dist_/2, 0])
        {
            fncylindera(d=thread_dia, h=base_thick_*3, orient=[1,0,0]);
        }

        // cut zrod
        fncylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=[0,0,1]);
    }
}

module mount_rod_clamp_full(rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4, orient=[0,0,1])
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?outer_d+thread_dia*2+thick_:screw_dist;
    base_thick_=base_thick==undef?thick_*1.5:base_thick;

    orient(orient)
    difference()
    {
        union()
        {
            // cylinder around rod
            fncylindera(d=outer_d, h=width, orient=[0,0,1], align=[0,0,0]);

            // base
            translate([-rod_d/2,0,0])
            cubea([base_thick_, screw_dist_+thread_dia*2.5, width], align=[1,0,0]);
        }

        // cut bottom of cylinder
        translate([-rod_d/2,0,0])
            cubea([outer_d/2+.1, outer_d+.1, width+1], align=[-1,0,0]);

        // cut clamp screw holes
        for(i=[-1,1])
        translate([0, i*screw_dist_/2, 0])
        {
            fncylindera(d=thread_dia, h=base_thick_*3, orient=[1,0,0]);
        }

        // cut zrod
        fncylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=[0,0,1]);
    }
}

/*translate([20,0,0])*/
/*mount_rod_clamp_half(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5);*/
/*mount_rod_clamp_full(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5);*/


box + bruses

box + bruses

use <controller.scad>
use <screw.scad>

module side_bruse_impl()
{
  for(sig = [-1, +1])
    for(i = [1, 2, 3])
      translate([0, i*18, -1])
        rotate([sig*20, 0, 0])
          cube([3, 2, 26]);
}

module junction_box_impl()
{
  wall = 2;
  extra_depth = 5;
  int_size = [70, 70, 24+3+extra_depth];

  difference()
  {
    // main box
    cube(int_size + [2,2,1]*wall);
    translate([1,1,1]*wall)
      cube(int_size);
    // place for cables
    cable_cut_in = [20, 10, wall];
    #translate([(int_size[0]+2*wall-cable_cut_in[0])/2, wall, 0])
      cube(cable_cut_in);
  }

  // screw drivers
  dist_from_center = 59/2;
  for(dx = [-1, +1])
  {
    translate([(int_size[0]+2*wall)/2+dx*dist_from_center, wall+30, wall])
    {
      difference()
      {
        // main screw corridor
        union()
        {
          cylinder(r=10/2, h=int_size[2]-2);
          #translate([12/2/2*(dx-1), -10/2, 0])
            cube([12/2, 10, int_size[2]-2]);
        }
        cylinder(r=(3+1)/2, h=int_size[2]-2, $fs=1);
        // nut cut-in
        translate([0, 0, int_size[2]-2-13])
          scale(1.1)
            hull()
            {
              screw();
              translate([0, 9, 0])
                screw();
              translate([0, 9, 7])
                screw();
            }
      }
    }
  }

  // side bruses for better mounting - left/right
  for(dx = [-3, int_size[0]+2*wall])
    translate([dx, 0, 0])
      side_bruse_impl();
  // side bruses for better mounting - up/down
  for(dy = [-3, int_size[0]+2*wall])
    translate([75, dy, 0])
      rotate([0, 0, 90])
        side_bruse_impl();
}

module junction_box()
{
  difference()
  {
    junction_box_impl();
    translate([-10, -10, -5])
      cube([100,100,5]);
  }
}

if(false)
  translate([-7, -6, 10*2])
    controller();

junction_box();

use <controller.scad>

module junction_box()
{
  wall = 2;
  extra_depth = 5;
  int_size = [70, 70, 24+3+extra_depth];

  difference()
  {
    // main box
    cube(int_size + [2,2,1]*wall);
    translate([1,1,1]*wall)
      cube(int_size);
    // place for cables
    cable_cut_in = [20, 10, wall];
    #translate([(int_size[0]+2*wall-cable_cut_in[0])/2, wall, 0])
      cube(cable_cut_in);
  }

  // screw drivers
  dist_from_center = 59/2;
  translate([-20, 0, 0])
  for(dx = [-dist_from_center, +dist_from_center])
  {
    translate([(int_size[0]+2*wall)/2+dx, wall+30, wall])
      difference()
      {
        cylinder(r=9/2, h=int_size[2]-2);
        cylinder(r=(3+1)/2, h=int_size[2]-2, $fs=1);
        #hull()
        {
          cube([9, 6, 3]);
        }
      }

  }
}

if(false)
  translate([-7, -6, 10*2])
    controller();

junction_box();


added the genericScaledPlanet to explain the argument mapping

/** This file defines all the entities needed to create a solar system.
 *
 * @filename planets.scad
 */

/**
 * The scale of this solarSystem.
 */
globalScale = 10;

/**
 * A generic planet.
 *
 * @param distance The distance from the center.
 * @param diameter The diameter of the planet.
 * @show a Planet.
 * @function-dependency r_from_dia Calculate radius from diameter.
 */
module genericPlanet(distance, diameter){
  translate([distance,0,0]) sphere(r=r_from_dia(diameter));
}

/**
 * A generic scaled planet.
 * This planet already is scaled according to global Scale.
 *
 * @param distance The distance from the center.
 * @param diameter The diameter of the planet.
 * @show a Planet.
 * @module-dependency genericPlanet A generic planet.
 */
module genericScaledPlanet(distance, diameter){
  genericPlanet(distance*globalScale, diameter*globalScale);
}

/**
 * Calculates the radius from the given diameter.
 *
 * @param dia a diameter.
 * @return the radius.
 *
 */
function r_from_dia(dia) = dia / 2;

/**
 *  The Sun.
 * @module-dependency: genericPlanet
 * @variable-dependency: globalScale
 */
module sunPlanet(){
  diameter = 200*globalScale;
  genericPlanet(0,diameter);
  }

/**
 *  The first Planet.
 * @module-dependency: genericPlanet
 * @variable-dependency: globalScale
 */
module firstPlanet(){
  diameter = 20*globalScale;
  distanceFromSun = 500*globalScale;
  genericPlanet(distanceFromSun,(diameter));
  }

/**
 *  The second Planet.
 * @module-dependency: genericPlanet
 * @variable-dependency: globalScale
 */
module secondPlanet(){
  diameter = 80*globalScale;
  distanceFromSun = 800*globalScale;
  genericPlanet(distanceFromSun,(diameter));
  }

/** This file defines all the entities needed to create a solar system.
 *
 * @filename planets.scad
 */

/**
 * The scale of this solarSystem.
 */
globalScale = 10;

/**
 * A generic planet.
 *
 * @param distance The distance from the center.
 * @param diameter The diameter of the planet.
 * @show a Planet.
 * @function-dependency r_from_dia Calculate radius from diameter.
 * @variable-dependency globalScale Scale of the solar system.
 */
module genericPlanet(distance, diameter){
  translate([distance,0,0]) sphere(r=r_from_dia(diameter));
}

/**
 * Calculates the radius from the given diameter.
 *
 * @param dia a diameter.
 * @return the radius.
 *
 */
function r_from_dia(dia) = dia / 2;

/**
 *  The Sun.
 * @module-dependency: genericPlanet
 * @variable-dependency: globalScale
 */
module sunPlanet(){
  diameter = 200*globalScale;
  genericPlanet(0,diameter);
  }

/**
 *  The first Planet.
 * @module-dependency: genericPlanet
 * @variable-dependency: globalScale
 */
module firstPlanet(){
  diameter = 20*globalScale;
  distanceFromSun = 500*globalScale;
  genericPlanet(distanceFromSun,(diameter));
  }

/**
 *  The second Planet.
 * @module-dependency: genericPlanet
 * @variable-dependency: globalScale
 */
module secondPlanet(){
  diameter = 80*globalScale;
  distanceFromSun = 800*globalScale;
  genericPlanet(distanceFromSun,(diameter));
  }


Added kerf correction to Finger Joins (as global), Fixed issue with missing last Finger Join tab, and fixed issue with thickness not working correctly in lasercutbox()

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 = [],
)
{
    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
    );
}

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 = [],
)
{
    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])
        {
            captiveNutBoltHole(captive_nuts[t][0], captive_nuts[t][1], captive_nuts[t][2], 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);
        }
    }

    if (flat_adjust)
    {
        if ($children) translate([0 + flat_adjust[0], max_y(points) + thickness*3 + flat_adjust[1], 0])
                children();
    }
    else
    {
        if ($children) translate([0, max_y(points) + thickness*2.5, 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));
        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, thickness)
{
    translate([x,y,0]) rotate([0,0,angle-180]) union()
    {
        translate([-thickness/2,-thickness,-thickness]) cube([thickness, thickness*4, thickness*3]);
        translate([-thickness/2-thickness,thickness,-thickness]) cube([thickness*3, thickness, thickness*3]);
    }
}

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

}

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])
    {

	/*
		if(start_up == 1)
		{

			translate([range_min,0,0])
			{
				cube([ (range_max-range_min)/(fingers*2) + kerf/4, 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([(range_max-range_min)/(fingers*2),0,0])
			{
				cube([ (range_max-range_min)/(fingers*2)+ kerf/4, 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);
					}
				}
			}
		}
	*/
 //       for ( i = [range_min + ((range_max-range_min)/fingers) : (range_max-range_min)/fingers : range_max - (range_max-range_min)/fingers] )
        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 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,
        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 = [],
)
{

    if (sides==4)
    {
        fj = [
            [ [UP, 1, 4], [DOWN, 1, 4],    ],
            [ [UP, 0, 4], [DOWN, 1, 4],    ],
            [ [UP, 1, 4], [DOWN, 0, 4],    ],
            [ [UP, 1, 4], [DOWN, 1, 4],    ],
        ];
        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);
    }
    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, 4], [DOWN, 1, 4], [LEFT, 1, 4],   ],
            [ [UP, 0, 4], [DOWN, 1, 4], [LEFT, 1, 4],   ],
            [ [UP, 1, 4], [DOWN, 0, 4], [LEFT, 1, 4],   ],
            [ [UP, 1, 4], [DOWN, 1, 4], [LEFT, 1, 4],   ],
            [ [UP, 0, 4], [DOWN, 1, 4], [LEFT, 0, 4], [RIGHT, 1, 4]  ],
        ];

        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);
        }
    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, 4], [DOWN, 1, 4], [LEFT, 1, 4], [RIGHT, 0, 4]  ],
            [ [UP, 0, 4], [DOWN, 1, 4], [LEFT, 1, 4], [RIGHT, 0, 4]  ],
            [ [UP, 1, 4], [DOWN, 0, 4], [LEFT, 1, 4], [RIGHT, 0, 4]  ],
            [ [UP, 1, 4], [DOWN, 1, 4], [LEFT, 1, 4], [RIGHT, 0, 4]  ],
            [ [UP, 0, 4], [DOWN, 1, 4], [LEFT, 0, 4], [RIGHT, 1, 4]  ],
            [ [UP, 0, 4], [DOWN, 1, 4], [LEFT, 0, 4], [RIGHT, 1, 4]  ],
        ];
        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);
    }
}

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 = [])
{

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

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

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

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

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

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

UP = 0;
DOWN = 180;
LEFT = 90;
RIGHT = 270;
MID = 360;

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=3.1, 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 = [],
)
{
    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
    );
}

module lasercutout(thickness=3.1,  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 = [],
)
{
    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])
        {
            captiveNutBoltHole(captive_nuts[t][0], captive_nuts[t][1], captive_nuts[t][2], 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);
        }
    }

    if (flat_adjust)
    {
        if ($children) translate([0 + flat_adjust[0], max_y(points) + thickness*3 + flat_adjust[1], 0])
                children();
    }
    else
    {
        if ($children) translate([0, max_y(points) + thickness*2.5, 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));
        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, thickness)
{
    translate([x,y,0]) rotate([0,0,angle-180]) union()
    {
        translate([-thickness/2,-thickness,-thickness]) cube([thickness, thickness*4, thickness*3]);
        translate([-thickness/2-thickness,thickness,-thickness]) cube([thickness*3, thickness, thickness*3]);
    }
}

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

}

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 ( i = [range_min : (range_max-range_min)/fingers : range_max - (range_max-range_min)/fingers] )
        {
            if(start_up == 1)
            {
                translate([i,0,0])
                {
                    cube([ (range_max-range_min)/(fingers*2), 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),0,0])
                {
                    cube([ (range_max-range_min)/(fingers*2), 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 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 = 3.1, x=0, y=0, z=0, sides=6,
        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 = [],
)
{
    if (sides==4)
    {
        fj = [
            [ [UP, 1, 4], [DOWN, 1, 4],    ],
            [ [UP, 0, 4], [DOWN, 1, 4],    ],
            [ [UP, 1, 4], [DOWN, 0, 4],    ],
            [ [UP, 1, 4], [DOWN, 1, 4],    ],
        ];
        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);
    }
    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, 4], [DOWN, 1, 4], [LEFT, 1, 4],   ],
            [ [UP, 0, 4], [DOWN, 1, 4], [LEFT, 1, 4],   ],
            [ [UP, 1, 4], [DOWN, 0, 4], [LEFT, 1, 4],   ],
            [ [UP, 1, 4], [DOWN, 1, 4], [LEFT, 1, 4],   ],
            [ [UP, 0, 4], [DOWN, 1, 4], [LEFT, 0, 4], [RIGHT, 1, 4]  ],
        ];

        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);
        }
    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, 4], [DOWN, 1, 4], [LEFT, 1, 4], [RIGHT, 0, 4]  ],
            [ [UP, 0, 4], [DOWN, 1, 4], [LEFT, 1, 4], [RIGHT, 0, 4]  ],
            [ [UP, 1, 4], [DOWN, 0, 4], [LEFT, 1, 4], [RIGHT, 0, 4]  ],
            [ [UP, 1, 4], [DOWN, 1, 4], [LEFT, 1, 4], [RIGHT, 0, 4]  ],
            [ [UP, 0, 4], [DOWN, 1, 4], [LEFT, 0, 4], [RIGHT, 1, 4]  ],
            [ [UP, 0, 4], [DOWN, 1, 4], [LEFT, 0, 4], [RIGHT, 1, 4]  ],
        ];
        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);
    }
}

module lasercutoutBoxAdjustedFJ(thickness = 3.1, 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 = [])
{
    translate([0,0,0]) lasercutoutSquare(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]);

    translate([0,0,z+thickness]) lasercutoutSquare(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]);

    translate([0,0,thickness]) rotate([90,0,0]) lasercutoutSquare(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]);

    translate([0,y+thickness,thickness]) rotate([90,0,0]) lasercutoutSquare(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]);

    if (sides>4)
    {
        translate([0,0,thickness]) rotate([0,-90,0]) lasercutoutSquare(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]);
        }

    if (sides>5)
    {
        translate([x+thickness,0,thickness]) rotate([0,-90,0]) lasercutoutSquare(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]);
    }
}


adjust the width of the shade

adjust the width of the shade

bottomOuterRadius = 52;

intersection_xTranslate = -51;

outerRadius = 90;
//outerRadius = 36;

squareLength = 59;  //28;

xScale = 0.2;       // 0.3;

yScale = 0.7;       // 0.7;

use <../christmas-story-lamp-shade.scad>

//translate([-120, 0, 0])
// translate([9, 18, 0])
// %import("/home/roberto/Versioning/world/betoland/household/lamps/christmas-story-leg-lamp/jetpuf/files/LegLamp_Shade130.stl");

legLampShade(intersection_xTranslate = intersection_xTranslate,
             bottomOuterRadius = bottomOuterRadius,
             outerRadius = outerRadius,
             squareLength = squareLength,
             xScale = xScale,
             yScale = yScale);

bottomOuterRadius = 52;

intersection_xTranslate = -20;

outerRadius = 90;
//outerRadius = 36;

squareLength = 50;  //28;

xScale = 0.1;       // 0.3;

yScale = 0.3;       // 0.7;

use <../christmas-story-lamp-shade.scad>

//translate([-120, 0, 0])
// translate([9, 18, 0])
// import("/home/roberto/Versioning/world/betoland/household/lamps/christmas-story-leg-lamp/jetpuf/files/LegLamp_Shade130.stl");

legLampShade(intersection_xTranslate = intersection_xTranslate,
             bottomOuterRadius = bottomOuterRadius,
             outerRadius = outerRadius,
             squareLength = squareLength,
             xScale = xScale,
             yScale = yScale);


transforms: refactoring

transforms: refactoring

use <misc.scad>

// translate children
module linup(arr=undef)
{
    if($children>0)
    {
        for (i = [0 : $children-1])
        translate(arr[i]) children(i);
    }
}

module stack(dist=10, distances=undef, axis=[0,0,1])
{
    if($children>0)
    {
        if(dist == undef && distances != undef)
        {
            for (i = [0:len(distances)-1])
            {
                offset = v_sum(distances,i);
                translate(axis*offset)
                    child(i);
            }
        }
        else if(dist != undef && distances == undef)
        {
            for (i = [0 : $children-1])
                translate(axis*(dist*i))
                    children(i);
        }
    }
}

module orient(zaxes, roll=0)
{
    zaxes = len(zaxes.x) == undef && zaxes.x != undef? [zaxes] : zaxes;
    for(zaxis=zaxes)
    {
        rotate(_orient_angles(zaxis))
        /*rotate(roll*z)*/
            children();
    }
}

function _orient_bounds(orient, size) =
    (_rotate_matrix(_orient_angles(orient)) * [size.x,size.y,size.z,1]);

function _orient_t(orient, align, size) =
    let(bounds = _orient_bounds(orient, size))
    (hadamard(align, [abs(bounds.x/2),abs(bounds.y/2),abs(bounds.z/2)]));

module size_align(size=[10,10,10], align=[0,0,0], orient=[0,0,1])
{
    t = _orient_t(orient, align, size);
    translate(t)
    {
        orient(orient)
        {
            children();
        }
    }
}

module hull_pairwise()
{
    for (i= [1:1:$children-1])
    {
        hull()
        {
            children(i-1);
            children(i);
        }
    }
}

use <misc.scad>

// translate children
module lineup(arr=undef)
{
    /*echo(arr);*/
    /*echo($children);*/
    if($children>0)
    {
        for (i = [0 : $children-1])
            translate(arr[i]) children(i);
    }
}

module stack(dist=10, distances=undef)
{
    if(dist == undef && distances != undef)
    {
        for (i = [0:len(separations)-1])
        {
            offset = v_sum(separations,i);
            /*echo("i",i,"offset",offset);*/
            translate ([0,0,offset])
            {
                child(i);
            }
        }
    }
    else if(dist != undef && distances == undef)
    {
      for (i = [0 : $children-1])
          translate([ dist*i, 0, 0 ]) children(i);
    }
}

module orient(zaxes, roll=0)
{
    zaxes = len(zaxes.x) == undef && zaxes.x != undef? [zaxes] : zaxes;
    for(zaxis=zaxes)
    {
        rotate(_orient_angles(zaxis))
        /*rotate(roll*z)*/
            children();
    }
}

module size_align(size=[10,10,10], align=[0,0,0], orient=[0,0,1])
{
    bounds = _rotate_matrix(_orient_angles(orient)) * [size.x,size.y,size.z,1];
    t=hadamard(align, [abs(bounds.x/2),abs(bounds.y/2),abs(bounds.z/2)]);
    translate(t)
    {
        orient(orient)
        {
            children();
        }
    }
}

module hull_pairwise()
{
    for (i= [1:1:$children-1])
    {
        hull()
        {
            children(i-1);
            children(i);
        }
    }
}


splitted frontal part of rally chassis

splitted frontal part of rally chassis

/**
 * rally.scad
 *
 * Created by Diego Viejo
 *
 * 11/Dic/2015
 *
 * This is my attemp on creating a chassis for a rally slot car
 *
 */

//guide arm's holder
//work in progress: checking all sizes is still needed
numSlots = 1;
guideWidth = 32;
guideInternalWidth = 21.5;
guideHeight = 7;
guideHoleHeight = 2.5;
guideSupportLength = 7;
guideLength = 32; //guideSupportLength + numSlots*4- 2;
engineHolderHoleSep = 20;

//front axle
axleLength = 27;
bearingDiam = 5;
axleHeight = 6.75;

module guide(chassisLink=1)
difference()
{
    union()
    {
        cube([guideWidth, guideLength, guideHeight], center=true);
        translate([0, -guideLength/2 + axleLength, 0]) hull()
        {
            cube([guideWidth, bearingDiam*2.5, guideHeight], center = true);
            translate([0, 0, axleHeight+1]) cube([guideWidth, bearingDiam*1.85, 2], center=true);
        }
    }

    //main holes
    translate([0, guideSupportLength-1.5, 0]) cube([guideInternalWidth, guideLength, guideHeight*2], center=true);
    translate([0, 0, 3.25]) cube([guideInternalWidth, guideLength+2, guideHeight], center=true);
    translate([0, -(guideLength-6)/2-0.25, 3.25]) cube([25, 6, guideHeight], center=true);
    translate([0, guideSupportLength+6, 0]) cube([guideWidth - 2*2.5, guideLength, guideHeight*3], center=true);

    for(i=[1:numSlots])
    {
        translate([-guideWidth/2-1, -guideLength/2 + guideSupportLength +i*4-4, -guideHeight/2+guideHoleHeight])
            rotate([0, 90, 0]) cylinder(d=2, h=guideWidth+2);
    }

    if(chassisLink==1)
    for(i=[-1,1])
    {
        translate([i*engineHolderHoleSep/2, (guideSupportLength-guideLength)/2-0.75, -guideHeight/2-1+guideHeight/4+1.5+0.3]) cylinder(d=2.5, h=guideHeight/2+2);
        translate([i*engineHolderHoleSep/2, (guideSupportLength-guideLength)/2-0.75, -guideHeight/2-1]) cylinder(d=5, h=guideHeight/4+1.5);
    }

    translate([0, -guideLength/2 + axleLength, axleHeight-bearingDiam/2])
    {
        translate([0, 0, guideHeight/2]) cube([guideWidth+2, bearingDiam*0.8, guideHeight], center = true);
        translate([0, 0, -0.5]) cube([guideWidth+2, 1.5, guideHeight], center = true);
        rotate([0, 90, 0]) hull()
        {
            cylinder(d=bearingDiam, h=guideWidth+2, center=true, $fn=20);
            translate([-1.75, 0, 0]) cylinder(d=bearingDiam, h=guideWidth+2, center=true, $fn=20);
        }
    }
}

module lateral(side=-1)
difference()
{
    guide();
    translate([side*2.5, 0, 0]) cube([guideWidth, guideLength+6, guideHeight*3], center=true);
}

translate([0, 0, guideHeight/2])
difference()
{
    guide();
    translate([guideWidth/2-2.51, -30, -10]) cube([10, 60, 30]);
    translate([-guideWidth/2-0.005, -30, -10]) cube([2.51, 60, 30]);
}

translate([30, 0, 2.5/2])
    rotate([0, 90, 0]) translate([-(guideWidth-2.5)/2, 0, 0]) lateral();
translate([-30, 0, 2.5/2])
    rotate([0, -90, 0]) translate([(guideWidth-2.5)/2, 0, 0]) lateral(side=1);

difference()
{
    translate([-guideWidth/2, 0, 0]) cube([guideWidth, 6, 2.0]);
    translate([-guideInternalWidth/2+1.5, 6/2, -1]) cylinder(d=2, h=4);
    translate([guideInternalWidth/2-1.5, 6/2, -1]) cylinder(d=2, h=4);
}

/**
 * rally.scad
 *
 * Created by Diego Viejo
 *
 * 11/Dic/2015
 *
 * This is my attemp on creating a chassis for a rally slot car
 *
 */

//guide arm's holder
//work in progress: checking all sizes is still needed
numSlots = 1;
guideWidth = 32;
guideInternalWidth = 21.5;
guideHeight = 7;
guideHoleHeight = 2.5;
guideSupportLength = 7;
guideLength = 32; //guideSupportLength + numSlots*4- 2;
engineHolderHoleSep = 20;

//front axle
axleLength = 27;
bearingDiam = 5;
axleHeight = 6.75;

module guide(chassisLink=1)
difference()
{
    union()
    {
        cube([guideWidth, guideLength, guideHeight], center=true);
        translate([0, -guideLength/2 + axleLength, 0]) hull()
        {
            cube([guideWidth, bearingDiam*2.5, guideHeight], center = true);
            translate([0, 0, axleHeight+1]) cube([guideWidth, bearingDiam*1.85, 2], center=true);
        }
    }

    //main holes
    translate([0, guideSupportLength-1.5, 0]) cube([guideInternalWidth, guideLength, guideHeight*2], center=true);
    translate([0, 0, 3.25]) cube([guideInternalWidth, guideLength+2, guideHeight], center=true);
    translate([0, -(guideLength-6)/2-0.25, 3.25]) cube([25, 6, guideHeight], center=true);
    translate([0, guideSupportLength+6, 0]) cube([guideWidth - 2*2.5, guideLength, guideHeight*3], center=true);

    for(i=[1:numSlots])
    {
        translate([-guideWidth/2-1, -guideLength/2 + guideSupportLength +i*4-4, -guideHeight/2+guideHoleHeight])
            rotate([0, 90, 0]) cylinder(d=2, h=guideWidth+2);
    }

    if(chassisLink==1)
    for(i=[-1,1])
    {
        translate([i*engineHolderHoleSep/2, (guideSupportLength-guideLength)/2-0.75, -guideHeight/2-1+guideHeight/4+1.5+0.3]) cylinder(d=2.5, h=guideHeight/2+2);
        translate([i*engineHolderHoleSep/2, (guideSupportLength-guideLength)/2-0.75, -guideHeight/2-1]) cylinder(d=5, h=guideHeight/4+1.5);
    }

    translate([0, -guideLength/2 + axleLength, axleHeight-bearingDiam/2])
    {
        translate([0, 0, guideHeight/2]) cube([guideWidth+2, bearingDiam*0.8, guideHeight], center = true);
        translate([0, 0, -0.5]) cube([guideWidth+2, 1.5, guideHeight], center = true);
        rotate([0, 90, 0]) hull()
        {
            cylinder(d=bearingDiam, h=guideWidth+2, center=true, $fn=20);
            translate([-1.75, 0, 0]) cylinder(d=bearingDiam, h=guideWidth+2, center=true, $fn=20);
        }
    }
}

guide();