Got the model working finely

Got the model working finely

/**
Program by Ankur Gupta
www.github.com/agupta231
Jan 2017

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
**/

init_cube_size = 50;
iteration_factor = 0.45;
iterations = 3;

echo("---- Gupta 2017 ----");
echo(version());
echo("--------------------");

module iter_cube(current_iter, starting_pos) {
  iter_size = init_cube_size * pow(iteration_factor, current_iter);
  displacement = (init_cube_size * pow(iteration_factor, current_iter - 1)) / 2;

  for(i = [
    [-1, -1, -1],
    [-1, -1, 1],
    [-1, 1, 1],
    [1, 1, 1],
    [1, 1, -1],
    [1, -1, -1],
    [1, -1, 1],
    [-1, 1, -1]]
  ){
    disp_vect = displacement * i;

    translate(starting_pos + disp_vect) {
      cube(iter_size, center = true);
    }

    if(current_iter < iterations) {
      iter_cube(current_iter + 1, starting_pos + disp_vect);
    }
  }
}

union() {
  cube(init_cube_size, center = true);

  iter_cube(1, [0, 0, 0]);
}

/**
Program by Ankur Gupta
www.github.com/agupta231
Jan 2017

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
**/

init_cube_size = 50;
iteration_factor = 0.5;


body: top_shoulder

body: top_shoulder

include <constants.scad>;
HEIGHT_BODY = 44.5;
DIAMETER_BODY = 10.4;
BORDER_RADIUS_BODY = 0.2;
HEIGHT_NIPPLE = 0.8;

module top_surface()
{
    position_z = -(HEIGHT_NIPPLE + BORDER_RADIUS_BODY);
    position = [0,0,position_z];

    correction_diameter_base = (2 * BORDER_RADIUS_BODY);
    diameter_base = DIAMETER_BODY - correction_diameter_base;

    translate(position)
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = diameter_base,
        $fn = FINE);
}

module top_shoulder()
{
   translate([0,0,-(HEIGHT_NIPPLE + BORDER_RADIUS_BODY)])
        rotate_extrude(convexity = CONVEXITY, $fn = FINE)
            translate([(DIAMETER_BODY/2)-BORDER_RADIUS_BODY, 0, 0])
                circle(r = BORDER_RADIUS_BODY, $fn = FINE);
}

module body()
{
    top_surface();
    top_shoulder();

//Main body cylinder
translate([0,0,-(HEIGHT_BODY - BORDER_RADIUS_BODY)])
    cylinder(
        h = (HEIGHT_BODY - (HEIGHT_NIPPLE + (2* BORDER_RADIUS_BODY))),
        d = DIAMETER_BODY,
        $fn = FINE);

//Body bottom shoulder
translate([0,0,-(HEIGHT_BODY - BORDER_RADIUS_BODY)])
    rotate_extrude(convexity = CONVEXITY, $fn = FINE)
    translate([(DIAMETER_BODY/2)-BORDER_RADIUS_BODY, 0, 0])
        circle(r = BORDER_RADIUS_BODY, $fn = FINE);

//Bottom face of body
translate([0,0,-(HEIGHT_BODY)])
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = (DIAMETER_BODY - (2 * BORDER_RADIUS_BODY)),
        $fn = FINE);
}

body();

include <constants.scad>;
HEIGHT_BODY = 44.5;
DIAMETER_BODY = 10.4;
BORDER_RADIUS_BODY = 0.2;
HEIGHT_NIPPLE = 0.8;

module top_surface()
{
    position_z = -(HEIGHT_NIPPLE + BORDER_RADIUS_BODY);
    position = [0,0,position_z];

    correction_diameter_base = (2 * BORDER_RADIUS_BODY);
    diameter_base = DIAMETER_BODY - correction_diameter_base;

    translate(position)
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = diameter_base,
        $fn = FINE);
}

module body()
{
    top_surface();

//Body top shoulder
translate([0,0,-(HEIGHT_NIPPLE + BORDER_RADIUS_BODY)])
    rotate_extrude(convexity = CONVEXITY, $fn = FINE)
    translate([(DIAMETER_BODY/2)-BORDER_RADIUS_BODY, 0, 0])
        circle(r = BORDER_RADIUS_BODY, $fn = FINE);

//Main body cylinder
translate([0,0,-(HEIGHT_BODY - BORDER_RADIUS_BODY)])
    cylinder(
        h = (HEIGHT_BODY - (HEIGHT_NIPPLE + (2* BORDER_RADIUS_BODY))),
        d = DIAMETER_BODY,
        $fn = FINE);

//Body bottom shoulder
translate([0,0,-(HEIGHT_BODY - BORDER_RADIUS_BODY)])
    rotate_extrude(convexity = CONVEXITY, $fn = FINE)
    translate([(DIAMETER_BODY/2)-BORDER_RADIUS_BODY, 0, 0])
        circle(r = BORDER_RADIUS_BODY, $fn = FINE);

//Bottom face of body
translate([0,0,-(HEIGHT_BODY)])
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = (DIAMETER_BODY - (2 * BORDER_RADIUS_BODY)),
        $fn = FINE);
}

body();


The parameter list was corrected.

The parameter list was corrected.

/**
 *
 *  some parts of this software were inspired by
 *
 * 	     http://www.thingiverse.com/thing:9347
 *
 */

/**
 * makes a rounded cube
 */
module roundedCube(cornerRadius=4,
				   cubeCentered=false,
				   sides=30,
				   sidesOnly=false,
				   size=[20,20,2])
{
    $fn=sides;

    x = size[0] - cornerRadius/2;
    y = size[1] - cornerRadius/2;
    z = size[2];

    minkowski()
    {
        cube(size=[x,y,z], center=cubeCentered);

        if(sidesOnly)
        {
            cylinder(r=cornerRadius);
        }
        else
        {
            sphere(r=cornerRadius);
        }
    };
}

/**
 *
 *  some parts of this software were inspired by
 *
 * 	     http://www.thingiverse.com/thing:9347
 *
 */

/**
 * makes a rounded cube
 */
module roundedCube(cornerRadius=4,
				   cubeCentered=false,
				   sides=30,
				   sidesOnly=false,
				   size=[20,20,2])
{
    $fn=sides;

    x = size[0] - cornerRadius/2;
    y = size[1] - cornerRadius/2;
    z = size[2];

    minkowski(size, cornerRadius)
    {
        cube(size=[x,y,z], center=cubeCentered);

        if(sidesOnly)
        {
            cylinder(r=cornerRadius);
        }
        else
        {
            sphere(r=cornerRadius);
        }
    };
}


shapes: add $preview_mode fallbacks

shapes: add $preview_mode fallbacks

include <system.scad>
include <units.scad>
use <misc.scad>
use <transforms.scad>

module cubea(size=[10,10,10], align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0], orient=[0,0,1], roll=0, extra_roll, extra_roll_orient)
{
    size_align(size=size,extra_size=extrasize, align=align, extra_align=extrasize_align, orient=orient, orient_ref=[0,0,1], roll=roll, , extra_roll=extra_roll, extra_roll_orient=extra_roll_orient)
    {
        cube(size+extrasize, center=true);
    }
}

module rcubea(size=[10,10,10], rounding_radius=1, align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0], orient=[0,0,1], roll=0, extra_roll, extra_roll_orient)
{
    size_align(size=size,extra_size=extrasize, align=align, extra_align=extrasize_align, orient=orient, orient_ref=[0,0,1], roll=roll, extra_roll=extra_roll, extra_roll_orient=extra_roll_orient)
    {
        rcube(size=size+extrasize, rounding_radius=rounding_radius);
    }
}

/*cubea(size=[10,20,30], align=[0,-1,0], orient=[0,0,1], roll=10, extra_roll=-30, extra_roll_orient=[1,0,0]);*/

module rcube(size=[20,20,20], rounding_radius=1)
{
    if($preview_mode || rounding_radius == 0 || true)
    {
        cubea(size);
    }
    else
    {
        hull()
        for(x=[-(size[0]/2-rounding_radius),(size[0]/2-rounding_radius)])
        for(y=[-(size[1]/2-rounding_radius),(size[1]/2-rounding_radius)])
        for(z=[-(size[2]/2-rounding_radius),(size[2]/2-rounding_radius)])
        translate([x,y,z])
        sphere(r=rounding_radius);
    }
}

module cylindera(
        h=10,
        r=undef,
        r1=undef,
        r2=undef,
        d=undef,
        d1=undef,
        d2=undef,
        align=[0,0,0],
        orient=[0,0,1],
        extra_h=0,
        extra_r=undef,
        extra_d=undef,
        extra_align=[0,0,0],
        round_radius=0,
        debug=false
        )
{
    pi=3.1415926536;

    d1_ = v_fallback(d1, [r*2, r1*2]);
    d2_ = v_fallback(d2, [r*2, r2*2]);

    r1_ = v_fallback(r1, [d1_/2, d/2, r]);
    r2_ = v_fallback(r2, [d2_/2, d/2, r]);

    r_max = v_fallback(r, [max(r1_,r2_)]);

    extra_r_ = v_fallback(extra_r, [0]);

    if(debug)
    {
        echo(useDia, h, r_, r1_, r2_, extra_r_, align);
    }

    size_align(size=[r_max*2,r_max*2,h], extra_size=[extra_r_*2, extra_r_*2, extra_h], orient=orient, orient_ref=[0,0,1], align=align, extra_align=extra_align)
    {
        if(round_radius>0)
        {
            rcylinder(h=h+extra_h, r1=r1_+extra_r_, r2=r2_+extra_r_, round_radius=round_radius);
        }
        else
        {
            cylinder(h=h+extra_h, r1=r1_+extra_r_, r2=r2_+extra_r_, center=true);
        }
    }
}

/*translate([10,0,0])*/
/*rotate_extrude()*/
        /*translate([10-2,2,0])*/
/*$fa = 5.6;*/
/*$fs = 0.3;*/
/*circle(r = 100);*/
/*torus(10, 2, align=[0,0,0], orient=[0,0,1]);*/

module torus(radius, radial_width, align=[0,0,0], orient=[0,0,1])
{
    size_align(size=[radius*2+radial_width*2, radius*2+radial_width*2, radial_width*2], align=align, orient=orient)
    rotate_extrude()
    translate([radius, 0, 0])
    circle(radial_width);
}

module rcylinder(d, d1, d2, r, r1, r2, h=10, round_radius=2, align=[0,0,0], orient=[0,0,1])
{
    if($preview_mode || round_radius == 0 || true)
    {
        cylindera(d=d, d1=d1, d2=d2, r=r, r1=r1, r2=r2, h=h, align=align, orient=orient);
    }
    else
    {
        d1_ = v_fallback(d1, [r*2, r1*2]);
        d2_ = v_fallback(d2, [r*2, r2*2]);

        r1_ = v_fallback(r1, [d/2, d1_/2]);
        r2_ = v_fallback(r2, [d/2, d2_/2]);

        r_ = [r1_,r2_];

        size_align(align=align, orient=orient)
            hull()
            {
                for(z=[-1,1])
                    translate([0, 0, z*(-h/2)])
                    {
                        r__=z!=-1?r_[0]:r_[1];
                        torus(radius=r__-round_radius/2, radial_width=round_radius/2, align=[0,0,z]);
                    }
            }
    }
}

// positive angles go from start to end counterclockwise
// negative angles are allowed
module pie_slice_shape(r, start_angle, end_angle) {
    R = r * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    intersection() {
        circle(r);
        polygon([
                [0,0],
                [R * cos(a0), R * sin(a0)],
                [R * cos(a1), R * sin(a1)],
                [R * cos(a2), R * sin(a2)],
                [R * cos(a3), R * sin(a3)],
                [R * cos(a4), R * sin(a4)],
                [0,0]
        ]);
    }
}

// positive angles go from start to end counterclockwise
// negative angles are allowed
module pie_slice(r, start_angle, end_angle, h, orient=[0,0,1], align=[0,0,0])
{
    size_align(size=[r*2, r*2, h], orient=orient, orient_ref=[0,0,1], align=align)
    linear_extrude(h)
    {
        pie_slice_shape(r, start_angle, end_angle);
    }
}

module hollow_cylinder(d=10, thickness=1, h=10, taper=false, taper_h=undef, orient=[0,0,1], align=[0,0,0])
{
    outer_d = d+thickness/2;
    inner_d = d-thickness/2;
    size_align(size=[outer_d, outer_d, h], orient=orient, align=align)
    difference()
    {
        /*hull()*/
        union()
        {
            cylindera(h=h-taper_h*2, d=outer_d, orient=[0,0,1], align=[0,0,0]);
            taper_h = taper_h == undef ? (outer_d-inner_d)/4 : taper_h;
            /*taper_h_ = pythag_leg(taper_h, outer_d-inner_d);*/
            /*echo(taper_h_);*/
            if(taper)
            {
                for(z=[-1,1])
                translate([0,0,z*(h/2-taper_h)])
                mirror([0,0,z==-1?1:0])
                difference()
                {
                    cylindera(d1=outer_d, d2=outer_d-inner_d/4, h=taper_h*2, align=[0,0,1]);
                    cylindera(d1=inner_d, d2=outer_d, h=taper_h*2+.1, align=[0,0,1]);
                }
            }
        }

        cylindera(h=h+.4, d=inner_d, orient=[0,0,1], align=[0,0,0]);
    }
}

/**
 * Standard right-angled triangle
 *
 * @param number o_len Lenght of the opposite side
 * @param number a_len Lenght of the adjacent side
 * @param number depth How wide/deep the triangle is in the 3rd dimension
 * @todo a better way ?
 */
module triangle(o_len, a_len, depth, align=[0,0,0], orient=[0,0,1])
{
    size_align(size=[a_len, depth, o_len], align=align, orient=orient)
    rotate([90,0,0])
    translate([-a_len/2, -o_len/2, -depth/2])
    linear_extrude(height=depth)
    {
        polygon(points=[[0,0],[a_len,0],[0,o_len]], paths=[[0,1,2]]);
    }
}

/**
 * Rounded Standard right-angled triangle
 *
 * @param number o_len Lenght of the opposite side
 * @param number a_len Lenght of the adjacent side
 * @param number depth How wide/deep the triangle is in the 3rd dimension
 * @todo a better way ?
 */
module rtriangle(o_len, a_len, depth, rounding_radius=2, align=[0,0,0], orient=[0,0,1])
{
    size = [a_len-rounding_radius, depth-rounding_radius, o_len-rounding_radius];
    r_x = rounding_radius;
    r_y = rounding_radius;
    r_z = -rounding_radius;

    hyp = pythag_hyp(o_len,a_len);
    a_z = atan(a_len/o_len);

    translate([0,0,size[2]+2])
    color([1,0,0])
    rotate([90,90,0])
    pie_slice(r=2, start_angle=0, end_angle=a_z, h=depth);

    /*translate([size[0]+4,0,0])*/
    /*color([1,0,0])*/
    /*rotate([90,90,0])*/
    /*pie_slice(r=2, start_angle=90, end_angle=90+a_z, h=depth);*/

    size_align(size=size, align=align, orient=orient)
    /*hull()*/
    for(x=[-(size[0]/2)+rounding_radius,(size[0]/2)-r_x])
    for(y=[-(size[1]/2)+rounding_radius,(size[1]/2)-r_y])
    for(z=[-(size[2]/2)+rounding_radius,(size[2]/2)-r_z])
    translate([x,y,z])
    if(x<=1 || z<=1)
    sphere(r=rounding_radius);
}

module teardrop(r, d, h=10, truncate=1, align=[0,0,0], orient=[0,1,0], roll=0)
{
    r_= v_fallback(r, [d/2]);

    sx1 = r_ * sin(-45);
    sx2 = r_ * -sin(-45);
    sy = r_ * -cos(-45);
    ex = 0;
    ey = (sin(-135) + cos(-135)) * r_;

    dx= ex-sx1;
    dy = ey-sy;

    eys = lerp(-r_,ey,1-truncate);

    dys = eys-sy;
    ex1 = sy+dys*dx/dy;
    ex2 = -ex1;

    size_align(size=[d,d,h], align=align, orient=orient, orient_ref=[0,0,1], roll=roll)
    union()
    {
        linear_extrude(height = h, center = true, convexity = r_, twist = 0)
        circle(r = r_, center = true);

        linear_extrude(height = h, center = true, convexity = r_, twist = 0)
        polygon(points = [
                [sy, sx1],
                [sy, sx2],
                [eys, ex2],
                [eys, ex1]],
                paths = [[0, 1, 2, 3]]);
    }
}

// test teardrop
if(false)
{
    r=5*mm;
    for(axis=concat(AXES,-AXES))
    translate(axis*r*2)
    {
        c= v_abs(axis*.3 + v_clamp(v_sign(axis),0,1)*.7);
        color(c)
        teardrop(r=r, h=20, orient=axis, align=axis);
    }
}

// test cubea
if(false)
{
    w=5*mm;
    h=2*mm;
    for(axis=concat(AXES,-AXES))
    /*translate(axis)*/
    {
        c= v_abs(axis*.3 + v_clamp(v_sign(axis),0,1)*.7);
        color(c)
        cubea([w,w,h], orient=axis, align=axis*3);
    }
}
/**
/*debug();*/

module debug()
{
    $fs = 0.1;
    $fa = 1;

    /*triangle_a(45, 5, 5);*/
    /*triangle(15, 10, 5, align=[1,1,1], orient=[0,0,-1]);*/
    /*triangle(15, 10, 5, align=[1,1,1], orient=[0,0,1]);*/

    triangle(10, 30, 5, align=[1,1,1], orient=[0,0,1]);
    translate([0,-10,0])
    rtriangle(10, 30, 5, align=[1,1,1], orient=[0,0,1]);
}

/**
 * Standard right-angled triangle (tangent version)
 *
 * @param number angle of adjacent to hypotenuse (ie tangent)
 * @param number a_len Lenght of the adjacent side
 * @param number depth How wide/deep the triangle is in the 3rd dimension
 */
module triangle_a(tan_angle, a_len, depth)
{
    linear_extrude(height=depth)
    {
        polygon(points=[[0,0],[a_len,0],[0,tan(tan_angle) * a_len]], paths=[[0,1,2]]);
    }
}

// Tests:
module test_triangles()
{
    // Generate a bunch of triangles by sizes
    for (i = [1:10])
    {
        translate([i*7, -30, i*7])
        {
            triangle(i*5, sqrt(i*5+pow(i,2)), 5);
        }
    }

    // Generate a bunch of triangles by angle
    for (i = [1:85/5])
    {
        translate([i*7, 22, i*7])
        {
            triangle_a(i*5, 10, 5);
        }
    }
}

if(false)
{
    /*hollow_cylinder(thickness=5, h=10, taper=true, orient=[0,0,1], align=[0,0,1]);*/
    /*cylindera(d=10, h=10, orient=[0,0,1], align=[0,0,1]);*/
    /*translate([10,0,0])*/
    /*{*/
    /*hollow_cylinder(d=10, thickness=4, h=10, taper=true, taper_h=.5, orient=[0,0,1], align=[0,0,1]);*/
    /*cylindera(d=8, h=10, orient=[0,0,1], align=[0,0,1]);*/
    /*}*/

    /*%pie_slice(r=10, start_angle=-30, end_angle=270, h=10);*/

    /*cubea([10,10,10],[1,0,0]);*/
    /*%cubea([10,10,10],[1,0,0],[5,5,5],[1,1,1]);*/

    /*%cubea([10,10,10],[-1,0,1]);*/
    /*%cubea([10,10,10],[-1,0,1],[1,1,1],[-1,0,1]);*/
    /*%cylindera(h=10, r=10/2, align=[-1,1,1], extra_r=5/2, extra_h=2, extra_align=[-1,1,1], $fn=100);*/

    /*%cylindera(h=10, d=10, align=[-1,1,1], extra_d=5, extra_h=2, extra_align=[-1,1,1], $fn=100);*/
    /*%cylindera(h=10, d=10, align=[1,1,1], extra_d=15, extra_h=2, extra_align=[1,1,1], $fn=100);*/

    /*%cylindera(h=10, d=10, align=[1,-1,1], extra_d=5, extra_h=2, extra_align=[-1,-1,1], $fn=100);*/
    /*%cylindera(h=10, d=10, align=[1,1,1], extra_d=5, extra_h=2, extra_align=[1,1,1], $fn=100);*/

    /*%cylindera(h=10, d=10, align=[1,0,0], extra_d=10);*/

    /*hull_pairwise()*/
    /*sphere(30/2);*/

    /*translate([30,0,0])*/
    /*rcubea(s=[35,35,35], rounding_radius=10);*/
    /*rcubea(s=[35,35,35], align=[0,-1,0]);*/

    /*translate([60,0,0])*/
    /*sphere(30/2);*/

    cylindera(h=20, r=5*mm, align=[0,1,0], orient=[0,0,1], $fn=100);

/*size_align(size=[5,5,20], orient=[0,1,0], orient_ref=[0,0,1])*/
/*size_align(size=[5,5,20], orient=[0,1,0], orient_ref=[0,1,0], align=[0,1,0])*/
/*size_align(size=[5,20,5], orient=[0,0,1], orient_ref=[0,1,0], align=[0,0,0])*/
/*rotate([90,0,0])*/
/*cylinder(d=5, h=20, center=true);*/

/*cylindera(d=10, h=10, orient=[0,1,0], align=[0,0,1]);*/
}

if(false)
{
    r=5*mm;
    for(axis=concat(AXES,-AXES))
    translate(axis*r*2)
    {
        c= v_abs(axis*.3 + v_clamp(v_sign(axis),0,1)*.7);
        color(c)
        /*cylindera(h=20, r=r, align=axis, orient=axis, extra_h=r, extra_align=-axis, $fn=100);*/
        cylindera(h=20, r1=r, r2=r/2, align=axis, orient=axis, extra_h=r, extra_align=-axis, $fn=16, round_radius=2);
    }
}

if(false)
{
    stack(dist=50, axis=[0,1,0])
    {
        stack(dist=10, axis=[0,0,-1])
        {
            /*cylindera(orient=[0,0,-1], align=[0,0,-1]);*/
            pie_slice(r=30, h=5, start_angle=0, end_angle=120, orient=[0,0,1], align=[0,0,-1]);
            pie_slice(r=30, h=5, start_angle=0, end_angle=120, orient=[0,0,-1], align=[0,0,1]);
            /*pie_slice(r=30, h=5, start_angle=-90, end_angle=180, align=[0,0,-1]);*/
            /*pie_slice(r=30, h=5, start_angle=90, end_angle=270, align=[0,0,-1]);*/
            /*pie_slice(r=30, h=5, start_angle=0, end_angle=270, align=[0,0,-1]);*/
        }

        stack(dist=10, axis=[0,1,0])
        {
            /*cylindera(orient=[0,1,0], align=[0,1,0]);*/
            pie_slice(r=30, h=5, start_angle=0, end_angle=120, orient=[0,-1,0], align=[0,1,0]);
            pie_slice(r=30, h=5, start_angle=0, end_angle=120, orient=[0,1,0], align=[0,1,0]);
            pie_slice(r=30, h=5, start_angle=-90, end_angle=180, orient=[0,1,0], align=[0,1,0]);
            pie_slice(r=30, h=5, start_angle=90, end_angle=270, orient=[0,1,0], align=[0,1,0]);
            pie_slice(r=30, h=5, start_angle=0, end_angle=270, orient=[0,1,0], align=[0,1,0]);
        }
    }
}

include <system.scad>
include <units.scad>
use <misc.scad>
use <transforms.scad>

module cubea(size=[10,10,10], align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0], orient=[0,0,1], roll=0, extra_roll, extra_roll_orient)
{
    size_align(size=size,extra_size=extrasize, align=align, extra_align=extrasize_align, orient=orient, orient_ref=[0,0,1], roll=roll, , extra_roll=extra_roll, extra_roll_orient=extra_roll_orient)
    {
        cube(size+extrasize, center=true);
    }
}

module rcubea(size=[10,10,10], rounding_radius=1, align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0], orient=[0,0,1], roll=0, extra_roll, extra_roll_orient)
{
    size_align(size=size,extra_size=extrasize, align=align, extra_align=extrasize_align, orient=orient, orient_ref=[0,0,1], roll=roll, extra_roll=extra_roll, extra_roll_orient=extra_roll_orient)
    {
        rcube(size=size+extrasize, rounding_radius=rounding_radius);
    }
}

/*cubea(size=[10,20,30], align=[0,-1,0], orient=[0,0,1], roll=10, extra_roll=-30, extra_roll_orient=[1,0,0]);*/

module rcube(size=[20,20,20], rounding_radius=1)
{
    hull()
    for(x=[-(size[0]/2-rounding_radius),(size[0]/2-rounding_radius)])
    for(y=[-(size[1]/2-rounding_radius),(size[1]/2-rounding_radius)])
    for(z=[-(size[2]/2-rounding_radius),(size[2]/2-rounding_radius)])
    translate([x,y,z])
    sphere(r=rounding_radius);
}

module cylindera(
        h=10,
        r=undef,
        r1=undef,
        r2=undef,
        d=undef,
        d1=undef,
        d2=undef,
        align=[0,0,0],
        orient=[0,0,1],
        extra_h=0,
        extra_r=undef,
        extra_d=undef,
        extra_align=[0,0,0],
        round_radius=0,
        debug=false
        )
{
    pi=3.1415926536;

    d1_ = v_fallback(d1, [r*2, r1*2]);
    d2_ = v_fallback(d2, [r*2, r2*2]);

    r1_ = v_fallback(r1, [d1_/2, d/2, r]);
    r2_ = v_fallback(r2, [d2_/2, d/2, r]);

    r_max = v_fallback(r, [max(r1_,r2_)]);

    extra_r_ = v_fallback(extra_r, [0]);

    if(debug)
    {
        echo(useDia, h, r_, r1_, r2_, extra_r_, align);
    }

    size_align(size=[r_max*2,r_max*2,h], extra_size=[extra_r_*2, extra_r_*2, extra_h], orient=orient, orient_ref=[0,0,1], align=align, extra_align=extra_align)
    {
        if(round_radius>0)
        {
            rcylinder(h=h+extra_h, r1=r1_+extra_r_, r2=r2_+extra_r_, round_radius=round_radius);
        }
        else
        {
            cylinder(h=h+extra_h, r1=r1_+extra_r_, r2=r2_+extra_r_, center=true);
        }
    }
}

/*translate([10,0,0])*/
/*rotate_extrude()*/
        /*translate([10-2,2,0])*/
/*$fa = 5.6;*/
/*$fs = 0.3;*/
/*circle(r = 100);*/
/*torus(10, 2, align=[0,0,0], orient=[0,0,1]);*/

module torus(radius, radial_width, align=[0,0,0], orient=[0,0,1])
{
    size_align(size=[radius*2+radial_width*2, radius*2+radial_width*2, radial_width*2], align=align, orient=orient)
    rotate_extrude()
    translate([radius, 0, 0])
    circle(radial_width);
}

module rcylinder(d, d1, d2, r, r1, r2, h=10, round_radius=2, align=[0,0,0], orient=[0,0,1])
{
    d1_ = v_fallback(d1, [r*2, r1*2]);
    d2_ = v_fallback(d2, [r*2, r2*2]);

    r1_ = v_fallback(r1, [d/2, d1_/2]);
    r2_ = v_fallback(r2, [d/2, d2_/2]);

    r_ = [r1_,r2_];

    size_align(align=align, orient=orient)
    hull()
    {
        for(z=[-1,1])
        translate([0, 0, z*(-h/2)])
        {
            r__=z!=-1?r_[0]:r_[1];
            torus(radius=r__-round_radius/2, radial_width=round_radius/2, align=[0,0,z]);
        }
    }
}

// positive angles go from start to end counterclockwise
// negative angles are allowed
module pie_slice_shape(r, start_angle, end_angle) {
    R = r * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    intersection() {
        circle(r);
        polygon([
                [0,0],
                [R * cos(a0), R * sin(a0)],
                [R * cos(a1), R * sin(a1)],
                [R * cos(a2), R * sin(a2)],
                [R * cos(a3), R * sin(a3)],
                [R * cos(a4), R * sin(a4)],
                [0,0]
        ]);
    }
}

// positive angles go from start to end counterclockwise
// negative angles are allowed
module pie_slice(r, start_angle, end_angle, h, orient=[0,0,1], align=[0,0,0])
{
    size_align(size=[r*2, r*2, h], orient=orient, orient_ref=[0,0,1], align=align)
    linear_extrude(h)
    {
        pie_slice_shape(r, start_angle, end_angle);
    }
}

module hollow_cylinder(d=10, thickness=1, h=10, taper=false, taper_h=undef, orient=[0,0,1], align=[0,0,0])
{
    outer_d = d+thickness/2;
    inner_d = d-thickness/2;
    size_align(size=[outer_d, outer_d, h], orient=orient, align=align)
    difference()
    {
        /*hull()*/
        union()
        {
            cylindera(h=h-taper_h*2, d=outer_d, orient=[0,0,1], align=[0,0,0]);
            taper_h = taper_h == undef ? (outer_d-inner_d)/4 : taper_h;
            /*taper_h_ = pythag_leg(taper_h, outer_d-inner_d);*/
            /*echo(taper_h_);*/
            if(taper)
            {
                for(z=[-1,1])
                translate([0,0,z*(h/2-taper_h)])
                mirror([0,0,z==-1?1:0])
                difference()
                {
                    cylindera(d1=outer_d, d2=outer_d-inner_d/4, h=taper_h*2, align=[0,0,1]);
                    cylindera(d1=inner_d, d2=outer_d, h=taper_h*2+.1, align=[0,0,1]);
                }
            }
        }

        cylindera(h=h+.4, d=inner_d, orient=[0,0,1], align=[0,0,0]);
    }
}

/**
 * Standard right-angled triangle
 *
 * @param number o_len Lenght of the opposite side
 * @param number a_len Lenght of the adjacent side
 * @param number depth How wide/deep the triangle is in the 3rd dimension
 * @todo a better way ?
 */
module triangle(o_len, a_len, depth, align=[0,0,0], orient=[0,0,1])
{
    size_align(size=[a_len, depth, o_len], align=align, orient=orient)
    rotate([90,0,0])
    translate([-a_len/2, -o_len/2, -depth/2])
    linear_extrude(height=depth)
    {
        polygon(points=[[0,0],[a_len,0],[0,o_len]], paths=[[0,1,2]]);
    }
}

/**
 * Rounded Standard right-angled triangle
 *
 * @param number o_len Lenght of the opposite side
 * @param number a_len Lenght of the adjacent side
 * @param number depth How wide/deep the triangle is in the 3rd dimension
 * @todo a better way ?
 */
module rtriangle(o_len, a_len, depth, rounding_radius=2, align=[0,0,0], orient=[0,0,1])
{
    size = [a_len-rounding_radius, depth-rounding_radius, o_len-rounding_radius];
    r_x = rounding_radius;
    r_y = rounding_radius;
    r_z = -rounding_radius;

    hyp = pythag_hyp(o_len,a_len);
    a_z = atan(a_len/o_len);

    translate([0,0,size[2]+2])
    color([1,0,0])
    rotate([90,90,0])
    pie_slice(r=2, start_angle=0, end_angle=a_z, h=depth);

    /*translate([size[0]+4,0,0])*/
    /*color([1,0,0])*/
    /*rotate([90,90,0])*/
    /*pie_slice(r=2, start_angle=90, end_angle=90+a_z, h=depth);*/

    size_align(size=size, align=align, orient=orient)
    /*hull()*/
    for(x=[-(size[0]/2)+rounding_radius,(size[0]/2)-r_x])
    for(y=[-(size[1]/2)+rounding_radius,(size[1]/2)-r_y])
    for(z=[-(size[2]/2)+rounding_radius,(size[2]/2)-r_z])
    translate([x,y,z])
    if(x<=1 || z<=1)
    sphere(r=rounding_radius);
}

module teardrop(r, d, h=10, truncate=1, align=[0,0,0], orient=[0,1,0], roll=0)
{
    r_= v_fallback(r, [d/2]);

    sx1 = r_ * sin(-45);
    sx2 = r_ * -sin(-45);
    sy = r_ * -cos(-45);
    ex = 0;
    ey = (sin(-135) + cos(-135)) * r_;

    dx= ex-sx1;
    dy = ey-sy;

    eys = lerp(-r_,ey,1-truncate);

    dys = eys-sy;
    ex1 = sy+dys*dx/dy;
    ex2 = -ex1;

    size_align(size=[d,d,h], align=align, orient=orient, orient_ref=[0,0,1], roll=roll)
    union()
    {
        linear_extrude(height = h, center = true, convexity = r_, twist = 0)
        circle(r = r_, center = true);

        linear_extrude(height = h, center = true, convexity = r_, twist = 0)
        polygon(points = [
                [sy, sx1],
                [sy, sx2],
                [eys, ex2],
                [eys, ex1]],
                paths = [[0, 1, 2, 3]]);
    }
}

// test teardrop
if(false)
{
    r=5*mm;
    for(axis=concat(AXES,-AXES))
    translate(axis*r*2)
    {
        c= v_abs(axis*.3 + v_clamp(v_sign(axis),0,1)*.7);
        color(c)
        teardrop(r=r, h=20, orient=axis, align=axis);
    }
}

// test cubea
if(false)
{
    w=5*mm;
    h=2*mm;
    for(axis=concat(AXES,-AXES))
    /*translate(axis)*/
    {
        c= v_abs(axis*.3 + v_clamp(v_sign(axis),0,1)*.7);
        color(c)
        cubea([w,w,h], orient=axis, align=axis*3);
    }
}
/**
/*debug();*/

module debug()
{
    $fs = 0.1;
    $fa = 1;

    /*triangle_a(45, 5, 5);*/
    /*triangle(15, 10, 5, align=[1,1,1], orient=[0,0,-1]);*/
    /*triangle(15, 10, 5, align=[1,1,1], orient=[0,0,1]);*/

    triangle(10, 30, 5, align=[1,1,1], orient=[0,0,1]);
    translate([0,-10,0])
    rtriangle(10, 30, 5, align=[1,1,1], orient=[0,0,1]);
}

/**
 * Standard right-angled triangle (tangent version)
 *
 * @param number angle of adjacent to hypotenuse (ie tangent)
 * @param number a_len Lenght of the adjacent side
 * @param number depth How wide/deep the triangle is in the 3rd dimension
 */
module triangle_a(tan_angle, a_len, depth)
{
    linear_extrude(height=depth)
    {
        polygon(points=[[0,0],[a_len,0],[0,tan(tan_angle) * a_len]], paths=[[0,1,2]]);
    }
}

// Tests:
module test_triangles()
{
    // Generate a bunch of triangles by sizes
    for (i = [1:10])
    {
        translate([i*7, -30, i*7])
        {
            triangle(i*5, sqrt(i*5+pow(i,2)), 5);
        }
    }

    // Generate a bunch of triangles by angle
    for (i = [1:85/5])
    {
        translate([i*7, 22, i*7])
        {
            triangle_a(i*5, 10, 5);
        }
    }
}

if(false)
{
    /*hollow_cylinder(thickness=5, h=10, taper=true, orient=[0,0,1], align=[0,0,1]);*/
    /*cylindera(d=10, h=10, orient=[0,0,1], align=[0,0,1]);*/
    /*translate([10,0,0])*/
    /*{*/
    /*hollow_cylinder(d=10, thickness=4, h=10, taper=true, taper_h=.5, orient=[0,0,1], align=[0,0,1]);*/
    /*cylindera(d=8, h=10, orient=[0,0,1], align=[0,0,1]);*/
    /*}*/

    /*%pie_slice(r=10, start_angle=-30, end_angle=270, h=10);*/

    /*cubea([10,10,10],[1,0,0]);*/
    /*%cubea([10,10,10],[1,0,0],[5,5,5],[1,1,1]);*/

    /*%cubea([10,10,10],[-1,0,1]);*/
    /*%cubea([10,10,10],[-1,0,1],[1,1,1],[-1,0,1]);*/
    /*%cylindera(h=10, r=10/2, align=[-1,1,1], extra_r=5/2, extra_h=2, extra_align=[-1,1,1], $fn=100);*/

    /*%cylindera(h=10, d=10, align=[-1,1,1], extra_d=5, extra_h=2, extra_align=[-1,1,1], $fn=100);*/
    /*%cylindera(h=10, d=10, align=[1,1,1], extra_d=15, extra_h=2, extra_align=[1,1,1], $fn=100);*/

    /*%cylindera(h=10, d=10, align=[1,-1,1], extra_d=5, extra_h=2, extra_align=[-1,-1,1], $fn=100);*/
    /*%cylindera(h=10, d=10, align=[1,1,1], extra_d=5, extra_h=2, extra_align=[1,1,1], $fn=100);*/

    /*%cylindera(h=10, d=10, align=[1,0,0], extra_d=10);*/

    /*hull_pairwise()*/
    /*sphere(30/2);*/

    /*translate([30,0,0])*/
    /*rcubea(s=[35,35,35], rounding_radius=10);*/
    /*rcubea(s=[35,35,35], align=[0,-1,0]);*/

    /*translate([60,0,0])*/
    /*sphere(30/2);*/

    cylindera(h=20, r=5*mm, align=[0,1,0], orient=[0,0,1], $fn=100);

/*size_align(size=[5,5,20], orient=[0,1,0], orient_ref=[0,0,1])*/
/*size_align(size=[5,5,20], orient=[0,1,0], orient_ref=[0,1,0], align=[0,1,0])*/
/*size_align(size=[5,20,5], orient=[0,0,1], orient_ref=[0,1,0], align=[0,0,0])*/
/*rotate([90,0,0])*/
/*cylinder(d=5, h=20, center=true);*/

/*cylindera(d=10, h=10, orient=[0,1,0], align=[0,0,1]);*/
}

if(false)
{
    r=5*mm;
    for(axis=concat(AXES,-AXES))
    translate(axis*r*2)
    {
        c= v_abs(axis*.3 + v_clamp(v_sign(axis),0,1)*.7);
        color(c)
        /*cylindera(h=20, r=r, align=axis, orient=axis, extra_h=r, extra_align=-axis, $fn=100);*/
        cylindera(h=20, r1=r, r2=r/2, align=axis, orient=axis, extra_h=r, extra_align=-axis, $fn=16, round_radius=2);
    }
}

if(false)
{
    stack(dist=50, axis=[0,1,0])
    {
        stack(dist=10, axis=[0,0,-1])
        {
            /*cylindera(orient=[0,0,-1], align=[0,0,-1]);*/
            pie_slice(r=30, h=5, start_angle=0, end_angle=120, orient=[0,0,1], align=[0,0,-1]);
            pie_slice(r=30, h=5, start_angle=0, end_angle=120, orient=[0,0,-1], align=[0,0,1]);
            /*pie_slice(r=30, h=5, start_angle=-90, end_angle=180, align=[0,0,-1]);*/
            /*pie_slice(r=30, h=5, start_angle=90, end_angle=270, align=[0,0,-1]);*/
            /*pie_slice(r=30, h=5, start_angle=0, end_angle=270, align=[0,0,-1]);*/
        }

        stack(dist=10, axis=[0,1,0])
        {
            /*cylindera(orient=[0,1,0], align=[0,1,0]);*/
            pie_slice(r=30, h=5, start_angle=0, end_angle=120, orient=[0,-1,0], align=[0,1,0]);
            pie_slice(r=30, h=5, start_angle=0, end_angle=120, orient=[0,1,0], align=[0,1,0]);
            pie_slice(r=30, h=5, start_angle=-90, end_angle=180, orient=[0,1,0], align=[0,1,0]);
            pie_slice(r=30, h=5, start_angle=90, end_angle=270, orient=[0,1,0], align=[0,1,0]);
            pie_slice(r=30, h=5, start_angle=0, end_angle=270, orient=[0,1,0], align=[0,1,0]);
        }
    }
}


The font name list annotation is now used.

The Customizer parameters were updated a little bit.

/* [Base] */

// This parameter is all about that base color.
baseColor = "black"; // [pink, red, black, white, yellow, blue, green]

baseThickness = 2; // [1 : 5]

// This determines how wide the name tag is.
baseWidth = 228;	// [50:600]

// This determines the height of the name tag.
baseHeight = 15; // [54:150]

/* [Border] */
borderColor = "yellow"; // [pink, red, black, white, yellow, blue, green]
showBorder = "No"; // [Yes, No]

/* [Bottom Text] */
bottomText = "Fun Enthusiast";
bottomTextFont = "Arial"; // @FontNamesReplacement@
bottomTextOffsetX = 0; // [-315 : 315]
bottomTextOffsetY = -15; // [-315 : 315]
bottomTextSize = 12; // [0 : 40]

/* [Chain Loop]*/
chainLoop = true;
chainLoopLengthZ = 6;
chainLoopType = "square"; // [rounded, square]
chainLoopPosition = "bottom"; // [bottom, top]

/* [General] */
letterThickness = 3; // [1 : 15]

/* [Icons] */
iconColor = "white"; // [pink, red, black, white, yellow, blue, green]

// This is the x off set of the icons
xIconOffset = -100; // [-200:200]

// This is the y off set of the icons
yIconOffset = 3;  // [1:200]

/* [Left Icon] */
//TODO: Where is the heart icon, man?  "Put your heart into it."
leftIconType = "Moon";   // [Bass Clef, Creeper, Light Bulb, Moon, Rebel, Trooper, Aqua Dude, Cat, Fan, Spur, Mario, Luigi, Sun, Thundercat, Treble Clef]

// This is the X,Y scale of the icons.
leftIconXyScale = 0.99;  // [0.1 : 0.05 : 5]

leftIconHeight = 2.5; // [0.1: 0.1 :5]

/* [Right Icon] */
rightIconHeight = 4.0; // [0.1: 0.1 :5]

//TODO: Where is the heart icon, man?  "Put your heart into it."
rightIconType = "Sun";          // [Bass Clef, Creeper, Light Bulb, Moon, Rebel, Trooper, Aqua Dude, Cat, Fan, Spur, Mario, Luigi, Sun, Thundercat, Treble Clef]

rightIconXyScale = 1.3; // [0.1 : 0.05 : 5]

/* [Top Text] */
topText = "Firstnesto Lastquez";
topTextColor = "white"; // [pink, red, black, white, yellow, blue, green]
topTextFont = "Bauhaus 93"; // @FontNamesReplacement@
topTextSize = 15; // [0 : 40]

/* [Hidden] */

use <../name-tag.scad>

nametag(baseColor = baseColor,
        baseThickness = baseThickness,
        borderColor = borderColor,
        chainLoop = chainLoop,
        chainLoopLengthZ = chainLoopLengthZ,
        chainLoopPosition = chainLoopPosition,
		chainLoopType = chainLoopType,
        iconColor = iconColor,
        letterThickness = letterThickness,
        roundedCorners = true,
        topText = topText,
		topTextOffsetY = 6,
        topTextSize = topTextSize,
        topTextColor = topTextColor,
        topTextFont = topTextFont,
        bottomText = bottomText,
        bottomTextFont = bottomTextFont,
        bottomTextOffsetX = bottomTextOffsetX,
        bottomTextOffsetY = bottomTextOffsetY,
		bottomTextSize = bottomTextSize,
		leftIconXyScale = leftIconXyScale,
        leftIconType = leftIconType,
        leftIconHeight = leftIconHeight,
        rightIconHeight = rightIconHeight,
		rightIconXyScale = rightIconXyScale,
        rightIconType = rightIconType,
        xIconOffset = xIconOffset,
        yIconOffset = yIconOffset,
        baseWidth = baseWidth,
        showBorder = showBorder);

/* [Base] */

// This parameter is all about that base color.
baseColor = "black"; // [pink, red, black, white, yellow, blue, green]

baseThickness = 2; // [1 : 5]

// This determines how wide the name tag is.
baseWidth = 228;	// [228:600]

// This determines the height of the name tag.
baseHeight = 15; // [54:150]

/* [Border] */
borderColor = "yellow"; // [pink, red, black, white, yellow, blue, green]
showBorder = "No"; // [Yes, No]

/* [Bottom Text] */
bottomText = "Fun Enthusiast";
bottomTextFont = "Arial"; // "Wingdings";
bottomTextOffsetX = 0; // [-315 : 315]
bottomTextOffsetY = -15; // [-315 : 315]
bottomTextSize = 12; // [0 : 40]

/* [Chain Loop]*/
chainLoop = true;
chainLoopLengthZ = 6;
chainLoopType = "square"; // [rounded, square]
chainLoopPosition = "bottom"; // [bottom, top]

/* [General] */
letterThickness = 3; // [1 : 15]

/* [Icons] */
iconColor = "white"; // [pink, red, black, white, yellow, blue, green]

// This is the x off set of the icons
xIconOffset = -100; // [10:200]

// This is the y off set of the icons
yIconOffset = 3;  // [1:200]

/* [Left Icon] */
//TODO: Where is the heart icon, man?  "Put your heart into it."
leftIconType = "Moon";   // [Bass Clef, Creeper, Light Bulb, Moon, Rebel, Trooper, Aqua Dude, Cat, Fan, Spur, Mario, Luigi, Sun, Thundercat, Treble Clef]

// This is the X,Y scale of the icons.
leftIconXyScale = 0.99;  // [0.1 : 0.05 : 5]

leftIconHeight = 2.5; // [0.1: 0.1 :5]

/* [Right Icon] */
rightIconHeight = 4.0; // [0.1: 0.1 :5]

//TODO: Where is the heart icon, man?  "Put your heart into it."
rightIconType = "Sun";          // [Bass Clef, Creeper, Light Bulb, Moon, Rebel, Trooper, Aqua Dude, Cat, Fan, Spur, Mario, Luigi, Sun, Thundercat, Treble Clef]

rightIconXyScale = 1.3; // [0.1 : 0.05 : 5]

/* [Top Text] */
topText = "Firstnesto Lastquez";
topTextColor = "white"; // [pink, red, black, white, yellow, blue, green]
topTextFont = "Bauhaus 93";
topTextSize = 15; // [0 : 40]

/* [Hidden] */

use <../name-tag.scad>

nametag(baseColor = baseColor,
        baseThickness = baseThickness,
        borderColor = borderColor,
        chainLoop = chainLoop,
        chainLoopLengthZ = chainLoopLengthZ,
        chainLoopPosition = chainLoopPosition,
		chainLoopType = chainLoopType,
        iconColor = iconColor,
        letterThickness = letterThickness,
        roundedCorners = true,
        topText = topText,
		topTextOffsetY = 6,
        topTextSize = topTextSize,
        topTextColor = topTextColor,
        topTextFont = topTextFont,
        bottomText = bottomText,
        bottomTextFont = bottomTextFont,
        bottomTextOffsetX = bottomTextOffsetX,
        bottomTextOffsetY = bottomTextOffsetY,
		bottomTextSize = bottomTextSize,
		leftIconXyScale = leftIconXyScale,
        leftIconType = leftIconType,
        leftIconHeight = leftIconHeight,
        rightIconHeight = rightIconHeight,
		rightIconXyScale = rightIconXyScale,
        rightIconType = rightIconType,
        xIconOffset = xIconOffset,
        yIconOffset = yIconOffset,
        baseWidth = baseWidth,
        showBorder = showBorder);


Added bigger dumplings cutter

Added bigger dumplings cutter

draft = false;

show_intersection = false;

form_r = 40;
flange_width = 5;
flange_height = 3;
flange_notches_count = floor(form_r*1.1);
flange_notch_r = 1.5;
inner_r = form_r - flange_width;
outer_r = form_r + 1;
handle_top = 50;
handle_bottom = 0.99;
handle_bottom_width = outer_r-inner_r;
handle_bottom_x = (outer_r+inner_r)/2;

function cp25(r,w) = [[r,-1000,w],
        [r,0,w],
        [r-15,30,2],
        [r-5,48,8]
    ];

function cp40(r,w) = [[r,-100,w],
        [r,1,w],
        [r-25,35,2],
        [r-15,47,8]
    ];

function cp(r,w) = r<30 ? cp25(r,w) : cp40(r,w);
handle_control_points = cp(handle_bottom_x, handle_bottom_width);

$fs = draft ? 2 : 0.2;
$fa = draft ? 12 : 2 ;
steps_per_bezier = draft ? 10 : 40;
rotate_extrude_steps = draft ? 60 : 360;

module flange() {
    module flange_shell() {
        rotate_extrude() {
            polygon([
                [inner_r, 0],
                [inner_r, 1],
                [outer_r, 1],
                [outer_r, -flange_height/2],
                [(form_r + outer_r)/2, -flange_height],
                [form_r, -flange_height],
                [form_r, 0]
            ]);
        }
    }
    module flange_notches() {
        intersection() {
            for(i=[0:360/flange_notches_count:359]) {
                rotate([0,0,i])
                    translate([inner_r,0,0]) {
                        intersection() {
                            union() {
                                translate([flange_notch_r,0,0])
                                    sphere(r=flange_notch_r);
                                translate([flange_width/2+flange_notch_r,0,0])
                                    rotate([0,90,0])
                                        cylinder(r=flange_notch_r,h=flange_width,center=true);
                            }
                        }
                    }
            }
            translate([0,0,-4.5]) cylinder(r=form_r+0.1,h=10,center=true);
        }
    }
    flange_shell();
    flange_notches();
}

module handle_silhouette() {
    intersection() {
        Line2d(Curve(handle_control_points));
        translate([0,handle_bottom])
            scale([1000,handle_top-handle_bottom])
                translate([-0.5,0])
                    square(1);
    }
}

module handle() {
    rotate_extrude() {
        handle_silhouette();
    }
}

module cutter() {
    handle();
    flange();
}

intersection() {
    cutter();
    if (show_intersection) cube([1000,1,1000],true);
}

//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------

// Bezier functions taken from http://www.thingiverse.com/thing:8443/
function BEZ03(u) = pow((1-u), 3);
function BEZ13(u) = 3*u*(pow((1-u),2));
function BEZ23(u) = 3*(pow(u,2))*(1-u);
function BEZ33(u) = pow(u,3);

function PointAlongBez4(p0, p1, p2, p3, u) = [
	BEZ03(u)*p0[0]+BEZ13(u)*p1[0]+BEZ23(u)*p2[0]+BEZ33(u)*p3[0],
	BEZ03(u)*p0[1]+BEZ13(u)*p1[1]+BEZ23(u)*p2[1]+BEZ33(u)*p3[1],
	BEZ03(u)*p0[2]+BEZ13(u)*p1[2]+BEZ23(u)*p2[2]+BEZ33(u)*p3[2],];

function length(v) = sqrt(v*v);

function Curve(points, steps=steps_per_bezier) = [
    for (i = [ 0 : len(points) - 2 ])
    let (   prev = points[i>0?i-1:i],
            p0 = points[i],
            p3 = points[i+1],
            next = points[i+2<len(points)?i+2:i+1])
    let (   v0 = p3 - prev,
            v3 = next - p0)
    let (   s0 = length(p3-p0)/(length(p3-p0) + length(p0-prev)),
            s3 = length(p3-p0)/(length(p3-p0) + length(next-p3)))
    let (   p1 = p0+v0*s0*0.5,
            p2 = p3-v3*s3*0.5)
    for (u = [ 0 : 1/steps : 1])
    PointAlongBez4(p0, p1, p2, p3, u)
];

module Line2d(path) {
    for (i = [0 : len(path)-2]) hull() {
        translate([path[i][0],path[i][1]]) circle(d=path[i][2],$fn=30);
        translate([path[i+1][0],path[i+1][1]]) circle(d=path[i+1][2],$fn=30);
    }
}

draft = false;

show_intersection = false;

form_r = 25;
flange_width = 5;
flange_height = 3;
flange_notches_count = floor(form_r*1.1);
flange_notch_r = 1.5;
inner_r = form_r - flange_width;
outer_r = form_r + 1;
handle_top = 50;
handle_bottom = 0.99;
handle_bottom_width = outer_r-inner_r;
handle_bottom_x = (outer_r+inner_r)/2;

handle_control_points =[[handle_bottom_x,-1000,handle_bottom_width],
        [handle_bottom_x,0,handle_bottom_width],
        [handle_bottom_x-15,30,2],
        [handle_bottom_x-5,48,8]
    ];

$fs = draft ? 2 : 0.2;
$fa = draft ? 12 : 2 ;
steps_per_bezier = draft ? 10 : 40;
rotate_extrude_steps = draft ? 60 : 360;

module flange() {
    module flange_shell() {
        rotate_extrude() {
            polygon([
                [inner_r, 0],
                [inner_r, 1],
                [outer_r, 1],
                [outer_r, -flange_height/2],
                [(form_r + outer_r)/2, -flange_height],
                [form_r, -flange_height],
                [form_r, 0]
            ]);
        }
    }
    module flange_notches() {
        intersection() {
            for(i=[0:360/flange_notches_count:359]) {
                rotate([0,0,i])
                    translate([inner_r,0,0]) {
                        intersection() {
                            union() {
                                translate([flange_notch_r,0,0])
                                    sphere(r=flange_notch_r);
                                translate([flange_width/2+flange_notch_r,0,0])
                                    rotate([0,90,0])
                                        cylinder(r=flange_notch_r,h=flange_width,center=true);
                            }
                        }
                    }
            }
            translate([0,0,-4.5]) cylinder(r=form_r+0.1,h=10,center=true);
        }
    }
    flange_shell();
    flange_notches();
}

module handle_silhouette() {
    intersection() {
        Line2d(Curve(handle_control_points));
        translate([0,handle_bottom])
            scale([1000,handle_top-handle_bottom])
                translate([-0.5,0])
                    square(1);
    }
}

module handle() {
    rotate_extrude() {
        handle_silhouette();
    }
}

module cutter() {
    handle();
    flange();
}

intersection() {
    cutter();
    if (show_intersection) cube([1000,1,1000],true);
}

//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------

// Bezier functions taken from http://www.thingiverse.com/thing:8443/
function BEZ03(u) = pow((1-u), 3);
function BEZ13(u) = 3*u*(pow((1-u),2));
function BEZ23(u) = 3*(pow(u,2))*(1-u);
function BEZ33(u) = pow(u,3);

function PointAlongBez4(p0, p1, p2, p3, u) = [
	BEZ03(u)*p0[0]+BEZ13(u)*p1[0]+BEZ23(u)*p2[0]+BEZ33(u)*p3[0],
	BEZ03(u)*p0[1]+BEZ13(u)*p1[1]+BEZ23(u)*p2[1]+BEZ33(u)*p3[1],
	BEZ03(u)*p0[2]+BEZ13(u)*p1[2]+BEZ23(u)*p2[2]+BEZ33(u)*p3[2],];

function length(v) = sqrt(v*v);

function Curve(points, steps=steps_per_bezier) = [
    for (i = [ 0 : len(points) - 2 ])
    let (   prev = points[i>0?i-1:i],
            p0 = points[i],
            p3 = points[i+1],
            next = points[i+2<len(points)?i+2:i+1])
    let (   v0 = p3 - prev,
            v3 = next - p0)
    let (   s0 = length(p3-p0)/(length(p3-p0) + length(p0-prev)),
            s3 = length(p3-p0)/(length(p3-p0) + length(next-p3)))
    let (   p1 = p0+v0*s0*0.5,
            p2 = p3-v3*s3*0.5)
    for (u = [ 0 : 1/steps : 1])
    PointAlongBez4(p0, p1, p2, p3, u)
];

module Line2d(path) {
    for (i = [0 : len(path)-2]) hull() {
        translate([path[i][0],path[i][1]]) circle(d=path[i][2],$fn=30);
        translate([path[i+1][0],path[i+1][1]]) circle(d=path[i+1][2],$fn=30);
    }
}


bearing/data: add more bushing data

bearing/data: add more bushing data


gantry/upper: Add rounding

gantry/upper: Add rounding

include <config.scad>
include <thing_libutils/metric-screw.scad>

module gantry_upper_connector()
{
    // how much bigger/smaller is the upper gantry (on each side)
    upper_gantry_width_diff  = (main_upper_width-main_width)/2;
    difference()
    {
        union()
        {
            hull()
            {
                // attach to z rod
                translate([zmotor_mount_rod_offset_x,0,0])
                {
                    rcubea([gantry_connector_thickness, zmotor_mount_clamp_width, extrusion_size+gantry_connector_thickness], align=[-1,0,1]);
                }

                // connect upper gantry
                translate([upper_gantry_width_diff, 0, 0])
                    translate([0,0,extrusion_size/2])
                    rcubea([gantry_connector_thickness,main_upper_dist_y+extrusion_size,extrusion_size], align=[1,0,0], extrasize=[0,0,gantry_connector_thickness], extrasize_align=[0,0,1]);
            }

            translate([upper_gantry_width_diff, 0, 0])
                translate([0,0,extrusion_size])
                rcubea([extrusion_size*2,main_upper_dist_y+extrusion_size,gantry_connector_thickness], align=[-1,0,1], extrasize=[gantry_connector_thickness,0,0], extrasize_align=[1,0,0]);

        }

        // cut out z rod mounting clamp nut traps and screw holes
        translate([zmotor_mount_rod_offset_x, 0, extrusion_size/2])
        for(i=[-1,1])
        {
            translate([-.1, i*zmotor_mount_clamp_dist/2, 0])
            {
                screw_cut(
                        nut=zmotor_mount_clamp_nut,
                        h=zmotor_mount_rod_offset_x-(extrusion_size*2),
                        orient=[-1,0,0],
                        align=[-1,0,0]
                        );
            }
        }

        translate([upper_gantry_width_diff/2, 0, extrusion_size+gantry_connector_thickness])
        for(x=[-1,1])
        for(y=[-1,1])
        {
            translate([x*extrusion_thread_dia*2, y*main_upper_dist_y/2, 0])
            {
                screw_cut(extrusion_nut, h=gantry_connector_thickness+.1, nut_offset=true, orient=[0,0,-1], align=[0,0,-1]);
            }
        }

        // cutout for z rod
        translate([zmotor_mount_rod_offset_x,0,extrusion_size])
        cylindera(d=zaxis_rod_d*1.01, h=extrusion_size*3, align=[0,0,0], orient=[0,0,1]);
    }
}

/*rotate([0,180,0])*/
/*gantry_upper_connector();*/

include <config.scad>
include <thing_libutils/metric-screw.scad>

module gantry_upper_connector()
{
    // how much bigger/smaller is the upper gantry (on each side)
    upper_gantry_width_diff  = (main_upper_width-main_width)/2;
    difference()
    {
        union()
        {
            hull()
            {
                // attach to z rod
                translate([zmotor_mount_rod_offset_x,0,0])
                {
                    cubea([gantry_connector_thickness, zmotor_mount_clamp_width, extrusion_size+gantry_connector_thickness], align=[-1,0,1]);
                }

                // connect upper gantry
                translate([upper_gantry_width_diff, 0, 0])
                    translate([0,0,extrusion_size/2])
                    cubea([gantry_connector_thickness,main_upper_dist_y+extrusion_size,extrusion_size], align=[1,0,0], extrasize=[0,0,gantry_connector_thickness], extrasize_align=[0,0,1]);
            }

            translate([upper_gantry_width_diff, 0, 0])
                translate([0,0,extrusion_size])
                cubea([extrusion_size*2,main_upper_dist_y+extrusion_size,gantry_connector_thickness], align=[-1,0,1]);

        }

        // cut out z rod mounting clamp nut traps and screw holes
        translate([zmotor_mount_rod_offset_x, 0, extrusion_size/2])
        for(i=[-1,1])
        {
            translate([-.1, i*zmotor_mount_clamp_dist/2, 0])
            {
                screw_cut(
                        nut=zmotor_mount_clamp_nut,
                        h=zmotor_mount_rod_offset_x-(extrusion_size*2),
                        orient=[-1,0,0],
                        align=[-1,0,0]
                        );
            }
        }

        translate([upper_gantry_width_diff/2, 0, extrusion_size+gantry_connector_thickness])
        for(x=[-1,1])
        for(y=[-1,1])
        {
            translate([x*extrusion_thread_dia*2, y*main_upper_dist_y/2, 0])
            {
                screw_cut(extrusion_nut, h=gantry_connector_thickness+.1, nut_offset=true, orient=[0,0,-1], align=[0,0,-1]);
            }
        }

        // cutout for z rod
        translate([zmotor_mount_rod_offset_x,0,extrusion_size])
        cylindera(d=zaxis_rod_d*1.01, h=extrusion_size*3, align=[0,0,0], orient=[0,0,1]);
    }
}

/*rotate([0,180,0])*/
/*zaxis_upper_gantry_zrod_connector();*/


gantry/upper/connector: fix/rewrite

gantry/upper/connector: fix/rewrite

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

module gantry_upper_connector(part)
{
    // how much bigger/smaller is the upper gantry (on each side)
    upper_gantry_width_diff  = (main_upper_width-main_width)/2;
    if(part==U)
    {
        difference()
        {
            gantry_upper_connector("pos");
            gantry_upper_connector("neg");
        }
    }
    else if(part=="pos")
    material(Mat_Plastic)
    {
        union()
        {
            hull()
            {
                // attach to z rod
                t(zaxis_rod_offset)
                tx(zmotor_mount_rod_offset_x)
                rcubea([gantry_connector_thickness, zmotor_mount_clamp_width, extrusion_size+gantry_connector_thickness], align=[-1,0,1]);

                // connect upper gantry
                tx(upper_gantry_width_diff)
                tz(extrusion_size/2)
                rcubea([gantry_connector_thickness,main_upper_dist_y+extrusion_size,extrusion_size], align=X, extra_size=[0,0,gantry_connector_thickness], extra_align=Z);
            }

            tx(upper_gantry_width_diff)
            tz(extrusion_size)
            rcubea([extrusion_size*2,main_upper_dist_y+extrusion_size,gantry_connector_thickness], align=[-1,0,1], extra_size=[gantry_connector_thickness,0,0], extra_align=X);

        }
    }
    else if(part=="neg")
    {
        // cut out z rod mounting clamp nut traps and screw holes
        t(zaxis_rod_offset)
        tx(zmotor_mount_rod_offset_x)
        tz(extrusion_size/2)
        for(y=[-1,1])
        tx(-.1)
        ty(y*zmotor_mount_clamp_dist/2)
        screw_cut(
            nut=zmotor_mount_clamp_nut,
            h=zmotor_mount_rod_offset_x-(extrusion_size*2),
            orient=[-1,0,0],
            align=[-1,0,0]
            );

        tx(upper_gantry_width_diff/2)
        tz(extrusion_size+gantry_connector_thickness)
        for(x=[-1,1])
        for(y=[-1,1])
        tx(x*extrusion_thread_dia*2)
        ty(y*main_upper_dist_y/2)
        screw_cut(nut=extrusion_nut, h=12*mm, head="button", orient=-Z, align=-Z);

        // cutout for z rod
        t(zaxis_rod_offset)
        tx(zmotor_mount_rod_offset_x)
        tx(extrusion_size)
        cylindera(d=zaxis_rod_d*1.01, h=extrusion_size*3, align=N, orient=Z);
    }
}

module part_gantry_upper_connector()
{
    gantry_upper_connector();
}

if(false)
{
    rotate([0,180,0])
    gantry_upper_connector();
}

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

module gantry_upper_connector()
{
    // how much bigger/smaller is the upper gantry (on each side)
    upper_gantry_width_diff  = (main_upper_width-main_width)/2;
    difference()
    {
        material(Mat_Plastic)
        union()
        {
            hull()
            {
                // attach to z rod
                translate(zaxis_rod_offset)
                translate([zmotor_mount_rod_offset_x,0,0])
                {
                    rcubea([gantry_connector_thickness, zmotor_mount_clamp_width, extrusion_size+gantry_connector_thickness], align=[-1,0,1]);
                }

                // connect upper gantry
                translate([upper_gantry_width_diff, 0, 0])
                    translate([0,0,extrusion_size/2])
                    rcubea([gantry_connector_thickness,main_upper_dist_y+extrusion_size,extrusion_size], align=X, extra_size=[0,0,gantry_connector_thickness], extra_align=Z);
            }

            translate([upper_gantry_width_diff, 0, 0])
                translate([0,0,extrusion_size])
                rcubea([extrusion_size*2,main_upper_dist_y+extrusion_size,gantry_connector_thickness], align=[-1,0,1], extra_size=[gantry_connector_thickness,0,0], extra_align=X);

        }

        // cut out z rod mounting clamp nut traps and screw holes
        translate(zaxis_rod_offset)
        translate([zmotor_mount_rod_offset_x, 0, extrusion_size/2])
        for(i=[-1,1])
        {
            translate([-.1, i*zmotor_mount_clamp_dist/2, 0])
            {
                screw_cut(
                        nut=zmotor_mount_clamp_nut,
                        h=zmotor_mount_rod_offset_x-(extrusion_size*2),
                        orient=[-1,0,0],
                        align=[-1,0,0]
                        );
            }
        }

        translate([upper_gantry_width_diff/2, 0, extrusion_size+gantry_connector_thickness])
        for(x=[-1,1])
        for(y=[-1,1])
        {
            translate([x*extrusion_thread_dia*2, y*main_upper_dist_y/2, 0])
            {
                screw_cut(nut=extrusion_nut, h=12*mm, head="button", nut_offset=true, orient=[0,0,-1], align=[0,0,-1]);
            }
        }

        // cutout for z rod
        translate(zaxis_rod_offset)
        translate([zmotor_mount_rod_offset_x,0,extrusion_size])
        cylindera(d=zaxis_rod_d*1.01, h=extrusion_size*3, align=N, orient=Z);
    }
}

module part_gantry_upper_connector()
{
    rotate([0,180,0])
    gantry_upper_connector();
}

/*rotate([0,180,0])*/
/*gantry_upper_connector();*/


Small cable chain, with slot for under wanhao i3

error: pathspec 'cable-chain-ends/cable-chain-end.scad' did not match any file(s) known to git


closet door stop model

closet door stop model

N=2;
M=2;
spacing=3;

module door_stop()
{
  span=10;
  difference()
  {
    union()
    {
      scale([0.5, 1, 1])
        rotate([-90, 0, 0])
          cylinder(r=10, h=span, $fn=50);
      cube([10, span, 10]);
    }
    // cutt bottom part
    translate([-10, -5, -15])
      cube([30, span+10, 15]);
    // drill
    translate([5, span/2, -5])
      cylinder(d=3.5, h=20, $fn=50);
  }
}

for(i=[0:N-1])
  for(j=[0:M-1])
    translate([i*(15+spacing), j*(10+spacing), 0])
      door_stop();

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


shoulder

shoulder

include <constants.scad>;
HEIGHT_BODY = 44.5;
DIAMETER_BODY = 10.4;
BORDER_RADIUS_BODY = 0.2;
HEIGHT_NIPPLE = 0.8;

HEIGHT_TOP = 2 * BORDER_RADIUS_BODY;

function top_position_z () = -(HEIGHT_NIPPLE + BORDER_RADIUS_BODY);
function main_position_z() = -(HEIGHT_BODY - BORDER_RADIUS_BODY);

module top_surface()
{
    position = [0,0,top_position_z()];

    diameter_base = DIAMETER_BODY - HEIGHT_TOP;

    translate(position)
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = diameter_base,
        $fn = FINE);
}

module shoulder(position_z)
{
    position_ring = [0,0,position_z];

    position_circle_x = radius(DIAMETER_BODY)-BORDER_RADIUS_BODY;
    posision_circle = [position_circle_x, 0, 0];

    translate(position_ring)
        rotate_extrude(convexity = CONVEXITY, $fn = FINE)
            translate(posision_circle)
                circle(r = BORDER_RADIUS_BODY, $fn = FINE);
}

module main_cylinder()
{
    position = [0,0,main_position_z()];

    heigh_main = HEIGHT_BODY - (HEIGHT_NIPPLE + HEIGHT_TOP);

    translate(position)
        cylinder(
            h = heigh_main,
            d = DIAMETER_BODY,
            $fn = FINE);
}

module body()
{
    top_surface();
    shoulder(top_position_z());

    main_cylinder();
    shoulder(main_position_z());

//Bottom face of body
translate([0,0,-(HEIGHT_BODY)])
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = (DIAMETER_BODY - (2 * BORDER_RADIUS_BODY)),
        $fn = FINE);
}

body();

include <constants.scad>;
HEIGHT_BODY = 44.5;
DIAMETER_BODY = 10.4;
BORDER_RADIUS_BODY = 0.2;
HEIGHT_NIPPLE = 0.8;

HEIGHT_TOP = 2 * BORDER_RADIUS_BODY;

function top_position_z () = -(HEIGHT_NIPPLE + BORDER_RADIUS_BODY);
function main_position_z() = -(HEIGHT_BODY - BORDER_RADIUS_BODY);

module top_surface()
{
    position = [0,0,top_position_z()];

    diameter_base = DIAMETER_BODY - HEIGHT_TOP;

    translate(position)
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = diameter_base,
        $fn = FINE);
}

module top_shoulder()
{
    position_ring = [0,0,top_position_z()];

    position_circle_x = radius(DIAMETER_BODY)-BORDER_RADIUS_BODY;
    position_circle = [position_circle_x, 0, 0];

    translate(position_ring)
        rotate_extrude(convexity = CONVEXITY, $fn = FINE)
            translate(position_circle)
                circle(r = BORDER_RADIUS_BODY, $fn = FINE);
}

module main_cylinder()
{
    heigh_main = HEIGHT_BODY - (HEIGHT_NIPPLE + HEIGHT_TOP);

    position = [0,0,main_position_z()];

    translate(position)
        cylinder(
            h = heigh_main,
            d = DIAMETER_BODY,
            $fn = FINE);
}

module bottom_shoulder()
{
    position_ring = [0,0,main_position_z()];

    position_circle_x = radius(DIAMETER_BODY)-BORDER_RADIUS_BODY;
    posision_circle = [position_circle_x, 0, 0];

    translate(position_ring)
        rotate_extrude(convexity = CONVEXITY, $fn = FINE)
            translate(posision_circle)
                circle(r = BORDER_RADIUS_BODY, $fn = FINE);
}
module body()
{
    top_surface();
    top_shoulder();
    main_cylinder();
    bottom_shoulder();

//Bottom face of body
translate([0,0,-(HEIGHT_BODY)])
    cylinder(
        h = BORDER_RADIUS_BODY,
        d = (DIAMETER_BODY - (2 * BORDER_RADIUS_BODY)),
        $fn = FINE);
}

body();


fix: properly use the build box and the render mode in the sample tube-cap

/**
 * Samples using the camelSCAD library.
 *
 * A parametric tube cap.
 *
 * @author jsconan
 * @license CC0-1.0
 */

// As we need to use some shapes, use the right entry point of the library
use <../shapes.scad>
include <../core/constants.scad>

// We will render the object using the specifications of this mode
renderMode = MODE_PROD;

// Defines the dimensions of the object
thickness = 1;
rimDiameter = 40;
holeDiameter = 30;
tubeDiameter = holeDiameter + 2 * thickness;
tubeDepth = 5;

// Displays a build box visualization to preview the printer area.
buildBox(center=true);

// Sets the minimum facet angle and size using the defined render mode.
applyMode(mode=renderMode) {
    difference() {
        union() {
            pipe(d=tubeDiameter, w=thickness, h=tubeDepth + thickness);
            cylinder(d=rimDiameter, h=thickness);
        }
        translateZ(-ALIGN) {
            cylinder(d1=tubeDiameter, d2=holeDiameter, h=thickness + ALIGN2);
        }
    }
}

/**
 * Samples using the camelSCAD library.
 *
 * A parametric tube cap.
 *
 * @author jsconan
 * @license CC0-1.0
 */

// As we need to use some shapes, use the right entry point of the library
use <../shapes.scad>
include <../core/constants.scad>

// We will render the object using the specifications of this mode
renderMode = MODE_PROD;

// Defines the dimensions of the object
thickness = 1;
rimDiameter = 40;
holeDiameter = 30;
tubeDiameter = holeDiameter + 2 * thickness;
tubeDepth = 5;

// Sets the minimum facet angle and size using the defined render mode.
// Displays a build box visualization to preview the printer area.
buildBox(mode=renderMode) {
    difference() {
        union() {
            pipe(d=tubeDiameter, w=thickness, h=tubeDepth + thickness);
            cylinder(d=rimDiameter, h=thickness);
        }
        translateZ(-ALIGN) {
            cylinder(d1=tubeDiameter, d2=holeDiameter, h=thickness + ALIGN2);
        }
    }
}


both cuts placed

both cuts placed

// closing nails' parameters
nail_thickness = 1;
nail_head      = 3.5;
nail_span      = 43;
nail_outstand  = 3;

module cut(height, length, span_up, span_down)
{
  up_offset = (span_down-span_up)/2;
  polyhedron(
    points = [
               [ 0,                 0,       0],      // 0
               [ up_offset,         length,  0],      // 1
               [ up_offset+span_up, length,  0],      // 2
               [ span_down,         0,       0],      // 3
               [ 0,                 0,       height], // 4
               [ up_offset,         length,  height], // 5
               [ up_offset+span_up, length,  height], // 6
               [ span_down,         0,       height]  // 7
             ],
    faces = [
              // bottom
              [4,5,7],
              [5,6,7],
              // top
              [2,1,0],
              [0,3,2],
              // upper wall
              [1,2,5],
              [6,5,2],
              // lower wall
              [4,3,0],
              [3,4,7],
              // left wall
              [0,1,4],
              [5,4,1],
              // right wall
              [2,3,7],
              [7,6,2]
            ]
  );
}

spacing = 2;
top     = 1.5*nail_thickness;
bottom  = 2*nail_head;
cut_h   = (nail_head-nail_thickness)*8;
h       = cut_h + 2*spacing;
l       = nail_span + bottom/2*2 + 2*5;
thick   = nail_outstand/2;

difference()
{
  cube([l, h, thick]);
  for(dx = [spacing, l-spacing-bottom])
    translate([dx, (h-cut_h)/2, 0])
      cut(thick, cut_h, top, bottom);
}

// closing nails' parameters
nail_thickness = 1;
nail_head      = 3.5;
nail_span      = 43;
nail_outstand  = 3;

module cut(height, length, span_up, span_down)
{
  up_offset = (span_down-span_up)/2;
  polyhedron(
    points = [
               [ 0,                 0,       0],      // 0
               [ up_offset,         length,  0],      // 1
               [ up_offset+span_up, length,  0],      // 2
               [ span_down,         0,       0],      // 3
               [ 0,                 0,       height], // 4
               [ up_offset,         length,  height], // 5
               [ up_offset+span_up, length,  height], // 6
               [ span_down,         0,       height]  // 7
             ],
    faces = [
              // bottom
              [4,5,7],
              [5,6,7],
              // top
              [2,1,0],
              [0,3,2],
              // upper wall
              [1,2,5],
              [6,5,2],
              // lower wall
              [4,3,0],
              [3,4,7],
              // left wall
              [0,1,4],
              [5,4,1],
              // right wall
              [2,3,7],
              [7,6,2]
            ]
  );
}

top    = 1.5*nail_thickness;
bottom = 2*nail_head;
cut_h  = (nail_head-nail_thickness)*6;
h      = cut_h + 2*5;
l      = nail_span + bottom/2*2 + 2*5;
side   = nail_outstand/2;

difference()
{
  cube([l, h, side]);
  translate([0, (h-cut_h)/2, 0])
    cut(2*side, cut_h, top, bottom);
}


screw: fixes for orient

screw: fixes for orient

include <system.scad>
include <shapes.scad>
include <transforms.scad>
include <misc.scad>

include <metric-thread-data.scad>
include <metric-hexnut-data.scad>
include <metric-knurlnut-data.scad>

use <scad-utils/transformations.scad>

// naive, assume head height is same as thread size (generally true for cap heads)
function get_screw_head_h(nut) = lookup(ThreadSize, nut);
function get_screw_head_d(nut) = 2 * lookup(ThreadSize, nut);

module screw(nut=MHexNutM3, h=10, tolerance=1.05, head_embed=false, with_nut=true, nut_offset=0, orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, nut);
    head_h = get_screw_head_h(nut);
    nut_h = lookup(MHexNutThickness,nut)*tolerance;
    thread = get(MHexNutThread, nut);

    s = threadsize*tolerance;
    total_h = h;
    size_align(size=[s, s, total_h], orient=orient, orient_ref=[0,0,-1], align=align)
    {
        translate([0,0,head_embed?-head_h:0])
        {
            translate([0,0,h/2+.01])
            {
                screw_head(nut, orient=[0,0,1], align=[0,0,1]);
            }
            screw_thread(thread=thread, h=h+.1, tolerance=tolerance, orient=[0,0,1], align=[0,0,0]);

            if(with_nut)
            {
                translate([0,0,-h/2+nut_h+nut_offset+(head_embed?head_h:0)])
                screw_nut(nut=nut, tolerance=tolerance, orient=[0,0,1], align=[0,0,-1]);
            }
        }
    }
}

module screw_cut(nut=MHexNutM3, h=10, tolerance=1.05, head_embed=false, with_nut=true, nut_offset=0, cut_access=true, orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, nut);
    head_h = get_screw_head_h(nut);
    nut_h = lookup(MHexNutThickness,nut)*tolerance;
    thread = get(MHexNutThread, nut);

    s = threadsize*tolerance;
    total_h = h;
    size_align(size=[s, s, total_h], orient=-orient, orient_ref=[0,0,1], align=align)
    {
        translate([0,0,head_embed?-head_h:0])
        {
            translate([0,0,h/2+.01])
            {
                screw_head_cut(nut, tolerance=1.25, override_h=1000, align=[0,0,1]);
            }
            screw_thread_cut(thread=thread, h=h+.1, tolerance=tolerance, align=[0,0,0]);

            if(with_nut)
            {
                translate([0,0,-h/2+nut_h+nut_offset+(head_embed?head_h:0)])
                screw_nut_cut(nut=nut, tolerance=tolerance, align=[0,0,-1]);
            }
        }
    }

    if($show_vit)
    {
        %screw(nut, h, tolerance, head_embed, with_nut, nut_offset, orient, align);
    }
}

module screw_thread(thread=ThreadM3, h=10, tolerance=1.00, orient=[0,0,1], align=[0,0,0])
{
    // TODO render thread
    threadsize = lookup(ThreadSize, thread[1]);
    cylindera(d=threadsize, h=h, orient=orient, align=align);
}

module screw_thread_cut(thread=ThreadM3, h=10, tolerance=1.05, orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, thread[1]);
    cylindera(d=threadsize*tolerance, h=h, orient=orient, align=align);
}

module screw_head(nut=MHexNutM3, tolerance=1.00, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, nut);
    head_h = get_screw_head_h(nut);
    head_d = get_screw_head_d(nut);
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    difference()
    {
        cylindera(d=head_d, h = override_h==undef?head_h:override_h);
        translate([0,0,head_h/2])
        cylindera(d=threadsize, h = head_d/2);
    }
}

module screw_head_cut(nut=MHexNutM3, tolerance=1.05, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, nut);
    head_h = get_screw_head_h(nut);
    head_d = get_screw_head_d(nut)*tolerance;
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    translate([0,0,-head_h/2])
    cylindera(d=head_d, h=override_h==undef?head_h:override_h, align=[0,0,1]);
}

module screw_nut(nut=MHexNutM3, tolerance=1.00, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    thickness = lookup(MHexNutThickness,nut)*tolerance;
    d = lookup(MHexNutWidthMin, nut)*tolerance;
    facets = lookup(MHexNutFacets, nut);
    cylindera($fn=lookup(MHexNutFacets, nut), d=d, h=override_h==undef?thickness:override_h, orient=orient, align=align);
}

module screw_nut_cut(nut=MHexNutM3, tolerance=1.05, h=1000, orient=[0,0,1], align=[0,0,0])
{
    thickness = lookup(MHexNutThickness,nut)*tolerance;
    d = lookup(MHexNutWidthMin, nut)*tolerance;
    size_align([d,d,thickness], orient=orient, align=align)
    {
        translate([0,0,thickness/2])
        {
            screw_nut(nut, tolerance, orient=[0,0,1], align=[0,0,-1]);
            translate([0,0,-thickness+.01])
            {
                cylindera(d=d*1.1, h=h, orient=[0,0,1], align=[0,0,-1]);
            }
        }
    }
}

module nut_trap_cut(nut=MHexNutM3, trap_offset=10, screw_l=10*mm, screw_l_extra=2*mm, trap_h=10, trap_axis=[0,-1,0], orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, nut);
    head_h = get_screw_head_h(nut);
    nut_h = lookup(MHexNutThickness,nut)+.5*mm;
    thread = get(MHexNutThread, nut);

    nut_width_min = lookup(MHexNutWidthMin, nut)+.2*mm;
    nut_width_max = lookup(MHexNutWidthMax, nut)+.2*mm;
    s = nut_width_min;
    total_h = nut_h;

    size_align(size=[s, s, total_h], orient=orient, orient_ref=[0,0,1], align=align)
    {
        translate([0,0,nut_h/2-.1])
        screw_thread_cut(thread=thread, tolerance=1.1, h=screw_l, orient=[0,0,-1], align=[0,0,1]);

        if(screw_l_extra>0)
        translate([0,0,-nut_h/2+.1])
        screw_thread_cut(thread=thread, tolerance=1.1, h=screw_l_extra+.1, orient=[0,0,1], align=[0,0,-1]);

        hull()
        {
            orient(-orient)
            stack(dist=trap_h, axis=trap_axis)
            {
                orient(orient)
                cylindera($fn=lookup(MHexNutFacets, nut), d=nut_width_max, h=nut_h, align=[0,0,0]);

                orient(orient)
                cubea(size=[nut_width_min,nut_width_min,nut_h], align=[0,0,0]);
            }
        }

        if($show_vit)
        {
            translate([0,0, screw_l])
            translate([0,0, -nut_h/2])
            %screw(nut, tolerance=1, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);

            %screw_nut(nut, tolerance=1, orient=[0,0,-1], align=[0,0,0]);
        }

    }

}

function get(key, dict) =
    let(x= search(MHexNutThread, MHexNutM3))
    dict[x[0]];

if(false)
{
    nut1 = MHexNutM3;
    nut2 = MHexNutM5;
    nut3 = MKnurlInsertNutM3_3_42;
    nut4 = MKnurlInsertNutM3_5_42;

    /*translate([0,20,0])*/
    /*translate([0,20,0])*/
    /*for(axis1=[0:len(AXES)-1])*/
    /*[>for(axis2=AXES)<]*/
    /*translate(20*AXES[axis1])*/
    /*{*/
        /*ta = v_rotate(90, AXES[axis1])*AXES[axis1];*/
        /*echo(AXES[axis1], ta);*/
        /*nut_trap_cut(nut=nut1, trap_axis=ta, orient=AXES[axis1]);*/
    /*}*/

    /*stack(d=30, axis=[1,0,0])*/
    /*{*/
        /*stack(d=20, axis=[0,1,0])*/
        /*{*/
            /*nut_trap_cut(nut=nut1, trap_axis=[0,0,1], orient=[1,0,0]);*/
            /*nut_trap_cut(nut=nut1, trap_axis=[0,0,1], orient=[-1,0,0]);*/
        /*}*/

        /*stack(d=20, axis=[1,0,0])*/
        /*{*/
            /*nut_trap_cut(nut=nut1, trap_axis=[0,0,1], orient=[0,1,0]);*/

            /*nut_trap_cut(nut=nut1, trap_axis=[0,0,1], orient=[0,-1,0]);*/
        /*}*/
    /*}*/

    box_w = 100;
    box_h = 10;
    box_d = 10;
    o = 10;

    /*$show_vit = true;*/
    $fs= 0.5;
    $fa = 4;

    difference()
    {
        cubea([box_w,box_d/2,box_h], align=[1,1,1]);

        test_cuts();
    }
    /*difference()*/
    /*{*/
        /*cubea([box_w,box_d/2,box_h], align=[1,-1,1]);*/

        /*test_cuts();*/
    /*}*/

}

module test_cuts()
{
    union()
    {
        offset = 0;
        /*offset = -5;*/
        translate([0,offset,0])
        translate([5,0,0])
        stack(dist=10,axis=[1,0,0])
        {
            screw_cut(nut=nut1, h=box_h, head_embed=false, orient=[0,0,-1], align=[0,0,1]);
            screw_cut(nut=nut1, h=box_h, head_embed=false, orient=[0,0,1], align=[0,0,1]);

            screw_cut(nut=nut1, h=box_h*mm, nut_offset=0*mm, head_embed=true, orient=[0,0,-1], align=[0,0,1]);
            screw_cut(nut=nut2, h=box_h*mm, nut_offset=3*mm, head_embed=false, orient=[0,0,-1], align=[0,0,1]);
            screw_cut(nut=nut3, h=box_h, head_embed=false, orient=[0,0,-1], align=[0,0,1]);
            screw_cut(nut=nut4, h=box_h, head_embed=false, orient=[0,0,-1], align=[0,0,1]);

            /*translate([0,5,0])*/
            translate([0,0,box_h/2])
                nut_trap_cut(nut=nut1, h=5, head_embed=false, trap_h=10, trap_axis=[0,-1,0], orient=[0,0,-1], align=[0,0,0]);

            translate([0,0,box_h/2])
                nut_trap_cut(nut=nut1, h=5, head_embed=false, trap_h=10, trap_axis=[0,1,0], orient=[0,0,1], align=[0,0,0]);

            translate([0,0,box_h/2])
                nut_trap_cut(nut=nut1, h=box_d, head_embed=false, trap_h=10, screw_l_extra=2*mm, trap_axis=[0,0,1], orient=[0,1,0], align=[0,0,0]);

            translate([0,0,box_h/2])
                nut_trap_cut(nut=nut1, h=box_d, head_embed=false, trap_h=10, screw_l_extra=2*mm, trap_axis=[0,0,-1], orient=[0,1,0], align=[0,0,0]);
        }
    }
}

include <shapes.scad>
include <transforms.scad>

include <metric-thread-data.scad>
include <metric-hexnut-data.scad>
include <metric-knurlnut-data.scad>

// naive, assume head height is same as thread size (generally true for cap heads)
function get_screw_head_h(nut) = lookup(ThreadSize, nut);
function get_screw_head_d(nut) = 2 * lookup(ThreadSize, nut);

module screw(nut=MHexNutM3, h=10, tolerance=1.05, head_embed=false, with_nut=true, nut_offset=0, orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, nut);
    head_h = get_screw_head_h(nut);
    nut_h = lookup(MHexNutThickness,nut)*tolerance;
    thread = get(MHexNutThread, nut);

    s = threadsize*tolerance;
    total_h = h;
    size_align(size=[s, s, total_h], orient=orient, orient_ref=[0,0,-1], align=align)
    {
        translate([0,0,head_embed?-head_h:0])
        {
            translate([0,0,h/2+.01])
            {
                screw_head(nut, orient=[0,0,1], align=[0,0,1]);
            }
            screw_thread(thread=thread, h=h+.1, tolerance=tolerance, orient=[0,0,1], align=[0,0,0]);

            if(with_nut)
            {
                translate([0,0,-h/2+nut_h+nut_offset+(head_embed?head_h:0)])
                screw_nut(nut=nut, tolerance=tolerance, orient=[0,0,1], align=[0,0,-1]);
            }
        }
    }
}

module screw_cut(nut=MHexNutM3, h=10, tolerance=1.05, head_embed=false, with_nut=true, nut_offset=0, cut_access=true, orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, nut);
    head_h = get_screw_head_h(nut);
    nut_h = lookup(MHexNutThickness,nut)*tolerance;
    thread = get(MHexNutThread, nut);

    s = threadsize*tolerance;
    total_h = h;
    size_align(size=[s, s, total_h], orient=orient, orient_ref=[0,0,-1], align=align)
    {
        translate([0,0,head_embed?-head_h:0])
        {
            translate([0,0,h/2+.01])
            {
                screw_head_cut(nut, tolerance=1.25, override_h=1000, align=[0,0,1]);
            }
            screw_thread_cut(thread=thread, h=h+.1, tolerance=tolerance, align=[0,0,0]);

            if(with_nut)
            {
                translate([0,0,-h/2+nut_h+nut_offset+(head_embed?head_h:0)])
                screw_nut_cut(nut=nut, tolerance=tolerance, align=[0,0,-1]);
            }
        }
    }

    if($show_vit)
    {
        %screw(nut, h, tolerance, head_embed, with_nut, nut_offset, orient, align);
    }
}

module screw_thread(thread=ThreadM3, h=10, tolerance=1.00, orient=[0,0,1], align=[0,0,0])
{
    // TODO render thread
    threadsize = lookup(ThreadSize, thread[1]);
    cylindera(d=threadsize, h=h, orient=orient, align=align);
}

module screw_thread_cut(thread=ThreadM3, h=10, tolerance=1.05, orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, thread[1]);
    cylindera(d=threadsize*tolerance, h=h, orient=orient, align=align);
}

module screw_head(nut=MHexNutM3, tolerance=1.00, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, nut);
    head_h = get_screw_head_h(nut);
    head_d = get_screw_head_d(nut);
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    difference()
    {
        cylindera(d=head_d, h = override_h==undef?head_h:override_h);
        translate([0,0,head_h/2])
        cylindera(d=threadsize, h = head_d/2);
    }
}

module screw_head_cut(nut=MHexNutM3, tolerance=1.05, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, nut);
    head_h = get_screw_head_h(nut);
    head_d = get_screw_head_d(nut)*tolerance;
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    translate([0,0,-head_h/2])
    cylindera(d=head_d, h=override_h==undef?head_h:override_h, align=[0,0,1]);
}

module screw_nut(nut=MHexNutM3, tolerance=1.00, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    thickness = lookup(MHexNutThickness,nut)*tolerance;
    d = lookup(MHexNutWidthMin, nut)*tolerance;
    facets = lookup(MHexNutFacets, nut);
    cylindera($fn=lookup(MHexNutFacets, nut), d=d, h=override_h==undef?thickness:override_h, orient=orient, align=align);
}

module screw_nut_cut(nut=MHexNutM3, tolerance=1.05, h=1000, orient=[0,0,1], align=[0,0,0])
{
    thickness = lookup(MHexNutThickness,nut)*tolerance;
    d = lookup(MHexNutWidthMin, nut)*tolerance;
    size_align([d,d,thickness], orient=orient, align=align)
    {
        translate([0,0,thickness/2])
        {
            screw_nut(nut, tolerance, orient=[0,0,1], align=[0,0,-1]);
            translate([0,0,-thickness+.01])
            {
                cylindera(d=d*1.1, h=h, orient=[0,0,1], align=[0,0,-1]);
            }
        }
    }
}

module nut_trap_cut(nut=MHexNutM3, trap_offset=10, screw_l=10*mm, screw_l_extra=2*mm, trap_h=10, trap_axis=[0,-1,0], orient=[0,0,1], align=[0,0,0])
{
    threadsize = lookup(ThreadSize, nut);
    head_h = get_screw_head_h(nut);
    nut_h = lookup(MHexNutThickness,nut)+.5*mm;
    thread = get(MHexNutThread, nut);

    nut_width_min = lookup(MHexNutWidthMin, nut)+.2*mm;
    nut_width_max = lookup(MHexNutWidthMax, nut)+.2*mm;
    s = nut_width_min;
    total_h = nut_h;

    size_align(size=[s, s, total_h], orient=trap_axis, align=align)
    {
        hull()
        {
            stack(dist=trap_h)
            {
                orient(trap_axis)
                orient(orient)
                cylindera($fn=lookup(MHexNutFacets, nut), d=nut_width_max, h=nut_h, align=[0,0,0]);

                orient(trap_axis)
                orient(orient)
                cubea(size=[nut_width_min,nut_width_min,nut_h], align=[0,0,0]);
            }
        }
    }

    size_align(size=[s, s, total_h], orient=orient, orient_ref=[0,0,-1], align=align)
    {
        translate([0,0,nut_h/2-.1])
        screw_thread_cut(thread=thread, tolerance=1.1, h=screw_l, orient=[0,0,-1], align=[0,0,1]);

        if(screw_l_extra>0)
        translate([0,0,-nut_h/2+.1])
        screw_thread_cut(thread=thread, tolerance=1.1, h=screw_l_extra+.1, orient=[0,0,1], align=[0,0,-1]);

        if($show_vit)
        {
            translate([0,0, screw_l])
            translate([0,0, -nut_h/2])
            %screw(nut, tolerance=1, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);

            %screw_nut(nut, tolerance=1, orient=[0,0,-1], align=[0,0,0]);
        }

    }

}

function get(key, dict) =
    let(x= search(MHexNutThread, MHexNutM3))
    dict[x[0]];

/*if(false)*/
{
    nut1 = MHexNutM3;
    nut2 = MHexNutM5;
    nut3 = MKnurlInsertNutM3_3_42;
    nut4 = MKnurlInsertNutM3_5_42;

    translate([0,20,0])
    stack(d=30, axis=[1,0,0])
    {
        stack(d=20, axis=[0,1,0])
        {
            nut_trap_cut(nut=nut1, trap_axis=[0,0,1], orient=[1,0,0]);
            nut_trap_cut(nut=nut1, trap_axis=[0,0,1], orient=[-1,0,0]);
        }

        stack(d=20, axis=[1,0,0])
        {
            nut_trap_cut(nut=nut1, trap_axis=[0,0,1], orient=[0,1,0]);

            nut_trap_cut(nut=nut1, trap_axis=[0,0,1], orient=[0,-1,0]);
        }
    }

    box_w = 100;
    box_h = 10;
    box_d = 10;
    o = 10;

    /*$show_vit = true;*/
    $fs= 0.5;
    $fa = 4;

    difference()
    {
        cubea([box_w,box_d/2,box_h], align=[1,1,1]);

        test_cuts();
    }
    /*difference()*/
    /*{*/
        /*cubea([box_w,box_d/2,box_h], align=[1,-1,1]);*/

        /*test_cuts();*/
    /*}*/

}

module test_cuts()
{
    union()
    {
        offset = 0;
        /*offset = -5;*/
        translate([0,offset,0])
        translate([5,0,0])
        stack(dist=10,axis=[1,0,0])
        {
            screw_cut(nut=nut1, h=box_h, head_embed=false, orient=[0,0,-1], align=[0,0,1]);
            screw_cut(nut=nut1, h=box_h, head_embed=false, orient=[0,0,1], align=[0,0,1]);

            screw_cut(nut=nut1, h=box_h*mm, nut_offset=0*mm, head_embed=true, orient=[0,0,-1], align=[0,0,1]);
            screw_cut(nut=nut2, h=box_h*mm, nut_offset=3*mm, head_embed=false, orient=[0,0,-1], align=[0,0,1]);
            screw_cut(nut=nut3, h=box_h, head_embed=false, orient=[0,0,-1], align=[0,0,1]);
            screw_cut(nut=nut4, h=box_h, head_embed=false, orient=[0,0,-1], align=[0,0,1]);

            /*translate([0,5,0])*/
            translate([0,0,box_h/2])
                nut_trap_cut(nut=nut1, h=5, head_embed=false, trap_h=10, trap_axis=[0,-1,0], orient=[0,0,-1], align=[0,0,0]);

            translate([0,0,box_h/2])
                nut_trap_cut(nut=nut1, h=box_d, head_embed=false, trap_h=10, screw_l_extra=2*mm, trap_axis=[0,0,1], orient=[0,1,0], align=[0,0,0]);
        }
    }
}


"PARAMETRIZE ALL THE VARIABLES!!!!"

"PARAMETRIZE ALL THE VARIABLES!!!!"

http://knowyourmeme.com/memes/x-all-the-y

// Mockup of OmmatiDiag
/*
 * The mockup was done after the first crude drawing with
 * [Tinkrecad](https://tinkercad.com/things/3utMiKsZhx9) proved to be too
 * inflexible.
 * The basic unit of the detecotor will be the scintillator size, which we
 * chose to be 17" x 17" translating to 430 x 430 mm in SI units.
*/

// Basic length variables [mm]
unitlength = 430;
padding = 20;
height = 100;
semitransparent = 0.618;
nearlytransparent = 0.25;

// Housing
module Housing()
  color ("gray", semitransparent) {
    // box bottom
    cube([unitlength + padding, unitlength + padding,1]);
    // box back walls
    cube([unitlength + padding, 1, height]);
    cube([1, unitlength + padding, height]);
    }
    // box front walls, can (and should be turned off for increased visibility)
    //~ color ("gray", 0.6) {
      //~ translate(v = [0, unitlength + padding, 0]) {
        //~ cube([unitlength + padding, 1, height]);
      //~ }
      //~ translate(v = [unitlength + padding, 0, 0]) {
        //~ cube([1, unitlength + padding, height]); //
      //~ }
    //~ }
Housing();

// Scintillator
module Scintillator()
  translate([padding/2, padding/2, 1]) {
    color ("green", 1) {
      cube([unitlength,unitlength,1]);
      }
    }
Scintillator();

// Ommatidium
module Ommatidium() {
  // FOV of one Ommatidium
  FOVSize = ([unitlength/4, unitlength/3]);
  module FOV()
    color("pink",0.5) cube([FOVSize[0], FOVSize[1], 1], center=true);

  // CMOS (Aptina AR0130)
  CMOSSize = ([1280, 960]);
  pixelsize = 3.75 / 1000; // [um]
  module CMOS()
    color ("blue", semitransparent)
    cube([CMOSSize[0] * pixelsize, CMOSSize[1] * pixelsize, 0.5], center=true);
  translate ([0,0,0]) CMOS();

  // FOV CMOS
  d_cmos_lens = 15;
  d_lens_scintillator = height - d_cmos_lens - 15;
  module CMOSCone()
      color("orange",nearlytransparent)
      cylinder(h = d_cmos_lens,
                r1 = CMOSSize[0] * pixelsize / 2 ,
                r2 = lensdiameter * 2, center=true);
  module CMOSCross() {
    color("red", 1) polyhedron(
      points=[ [0, 0, 0], //origin
        [-CMOSSize[0]*pixelsize/2, 0, d_cmos_lens],     // horizontal_1
        [CMOSSize[0]*pixelsize/2, 0,d_cmos_lens],       // horizontal_2
        [0, -CMOSSize[1] * pixelsize / 2,d_cmos_lens],  // vertical_1
        [0,  CMOSSize[1] * pixelsize / 2,d_cmos_lens]], // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }

  mirror([0,0,1]) translate([0,0,-d_cmos_lens])CMOSCross();
  translate([0,0,d_cmos_lens/2])CMOSCone();

  // Lens
  lensdiameter = 4;
  module Lens()
    // the lens is a squashed sphere: http://is.gd/4H9sZf
      scale([2,2,0.5]) sphere(lensdiameter, $fn=50, center=true);
  translate([0, 0, d_cmos_lens]) Lens();

  // FOV Lens
  module LensCone()
    color("orange",nearlytransparent)
    scale([1, 4/3, 1])
    cylinder(h = d_lens_scintillator,
              r1 = lensdiameter * 2,
              r2 = FOVSize[1]/2 * 1.2);
  module LensCross() {
    color("red", 1) polyhedron(
      points=[ [0, 0, 0], //origin
        [-FOVSize[0]/2, 0, d_lens_scintillator],   // horizontal_1
        [FOVSize[0]/2, 0,d_lens_scintillator],     // horizontal_2
        [0, -FOVSize[1]/2 ,d_lens_scintillator],   // vertical_1
        [0,  FOVSize[1]/2 ,d_lens_scintillator]],  // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }
  translate([0,0,d_cmos_lens]) LensCross();
  translate([0,0,d_cmos_lens]) LensCone();
  translate([0,0,d_cmos_lens + d_lens_scintillator]) FOV();
}

translate([unitlength/4/2 + padding/2, unitlength/3/2 + padding/2, height-14])
mirror([0,0,1])
for (xpos=[0:3], ypos = [0:2]) // iterate over x and y
  translate([xpos*unitlength/4, ypos*unitlength/3, 0]) Ommatidium();

// Mockup of OmmatiDiag
/*
 * The mockup was done after the first crude drawing with
 * [Tinkrecad](https://tinkercad.com/things/3utMiKsZhx9) proved to be too
 * inflexible.
 * The basic unit of the detecotor will be the scintillator size, which we
 * chose to be 17" x 17" translating to 430 x 430 mm in SI units.
*/

// Basic length variables [mm]
length = 430;
padding = 20;
height = 100;

// Housing
module Housing()
  color ("gray", 0.618) {
    // box bottom
    cube([length + padding, length + padding,1]);
    // box back walls
    cube([length + padding, 1, height]);
    cube([1, length + padding, height]);
    }

    // box front walls, can (and should be turned off for increased visibility)
    /*
    color ("gray", 0.6) {
      translate(v = [0, length + padding, 0]) {
        cube([length + padding, 1, height]);
      }
      translate(v = [length + padding, 0, 0]) {
        cube([1, length + padding, height]); //
      }
    }
    */

Housing();

// Scintillator
module Scintillator()
  translate(v = [padding/2, padding/2, 1]) {
    color ("green", 0.25) {
      cube([length,length,1]);
      }
    }
Scintillator();

// Ommatidium
module Ommatidium() {
  // FOV of one Ommatidium
  FOVSize = ([430/4, 430/3]);
  module FOV()
    color("pink",0.5) cube([FOVSize[0], FOVSize[1], 1], center=true);

  // CMOS (Aptina AR0130)
  CMOSSize = ([1280,960]);
  pixelsize = 3.75 / 1000; // [um]
  module CMOS()
    color ("blue", 0.618) cube([CMOSSize[0] * pixelsize ,CMOSSize[1] * pixelsize, 0.5], center=true);
  translate ([0,0,0]) CMOS();

  // FOV CMOS
  d_cmos_lens = 15;
  d_lens_scintillator = height - d_cmos_lens - 15;
  module CMOSCone()
      color("green",0.5) cylinder(h = d_cmos_lens, r1 = CMOSSize[0] * pixelsize / 2 , r2 = lensdiameter * 2, center=true);
  module CMOSCross() {
    color("red", 1) polyhedron(
      points=[ [0, 0, 0], //origin
        [-CMOSSize[0]*pixelsize/2, 0, d_cmos_lens],                 // horizontal_1
        [CMOSSize[0]*pixelsize/2, 0,d_cmos_lens], // horizontal_2
        [0, -CMOSSize[1] * pixelsize / 2,d_cmos_lens],                    // vertical_1
        [0,  CMOSSize[1] * pixelsize / 2,d_cmos_lens]],  // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }

  mirror([0,0,1]) translate([0,0,-d_cmos_lens])CMOSCross();
  translate([0,0,d_cmos_lens/2])CMOSCone();

  // Lens (http://is.gd/4H9sZf)
  lensdiameter = 2;
  module Lens()
    // the lens is a squashed sphere which we translate to the middle of the CMOS
      scale([2,2,0.5]) sphere(lensdiameter, $fn=50, center=true);
  translate([0, 0, d_cmos_lens]) Lens();

  // FOV Lens
  module LensCone()
    color("green",0.5) cylinder(h = d_lens_scintillator, r1 = lensdiameter * 2 , r2 = FOVSize[1]/2);
  module LensCross() {
    color("red", 1) polyhedron(
      points=[ [0, 0, 0], //origin
        [-FOVSize[0]/2, 0, d_lens_scintillator],   // horizontal_1
        [FOVSize[0]/2, 0,d_lens_scintillator],     // horizontal_2
        [0, -FOVSize[1]/2 ,d_lens_scintillator],   // vertical_1
        [0,  FOVSize[1]/2 ,d_lens_scintillator]],  // vertical_2
      triangles=[[0,1,2], [0,3,4]]);
    }
  translate([0,0,d_cmos_lens]) LensCross();
  translate([0,0,d_cmos_lens]) LensCone();
  translate([0,0,d_cmos_lens + d_lens_scintillator]) FOV();
}

translate([430/4/2,430/3/2,height-15])
mirror([0,0,1])
for (xpos=[0:3], ypos = [0:2]) // do twelve iterations, using each xpos with each ypos
   translate([xpos*430/4, ypos*430/3, 0]) Ommatidium();