shapes: fix rcylinder

shapes: fix rcylinder

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)
{
    size_align(size=size,extra_size=extrasize, align=align, extra_align=extrasize_align, orient=orient, orient_ref=[0,0,1], roll=roll)
    {
        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)
{
    size_align(size=size,extra_size=extrasize, align=align, extra_align=extrasize_align, orient=orient, orient_ref=[0,0,1], roll=roll)
    {
        rcube(size=size+extrasize, rounding_radius=rounding_radius);
    }
}

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;

    useDia = r == undef && (r1 == undef && r2 == undef);

    r1_ = useDia?((d1==undef?undef:d1)/2):r1;
    r2_ = useDia?((d2==undef?undef:d2)/2):r2;
    r_= useDia?d/2:(r==undef?0:r);
    r1r2max = max(r1,r2) == undef ? max(d1,d2)/2 : max(r1,r2);
    r__ = r_==undef? r1r2max : r_;
    extra_r_ = useDia?((extra_d==undef?0:extra_d)/2):((extra_r==undef)?0:extra_r);

    sizexy=r__*2;
    extra_sizexy=extra_r_*2;

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

    // some orient hax here to properly support extra_align
    size_align(size=[sizexy,sizexy,h], extra_size=[extra_sizexy, extra_sizexy, extra_h], orient=orient, orient_ref=[0,0,1], align=align, extra_align=extra_align)
    {
        if(round_radius>0)
        {
            rcylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, round_radius=round_radius);
        }
        else
        {
            cylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, 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_=d==undef?r:d/2;
    d_=r==undef?d:r*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)
{
    size_align(size=size,extra_size=extrasize, align=align, extra_align=extrasize_align, orient=orient, orient_ref=[0,0,1], roll=roll)
    {
        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)
{
    size_align(size=size,extra_size=extrasize, align=align, extra_align=extrasize_align, orient=orient, orient_ref=[0,0,1], roll=roll)
    {
        rcube(size=size+extrasize, rounding_radius=rounding_radius);
    }
}

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=undef,
        debug=false
        )
{
    pi=3.1415926536;

    useDia = r == undef && (r1 == undef && r2 == undef);

    r1_ = useDia?((d1==undef?undef:d1)/2):r1;
    r2_ = useDia?((d2==undef?undef:d2)/2):r2;
    r_= useDia?d/2:(r==undef?0:r);
    r1r2max = max(r1,r2) == undef ? max(d1,d2)/2 : max(r1,r2);
    r__ = r_==undef? r1r2max : r_;
    extra_r_ = useDia?((extra_d==undef?0:extra_d)/2):((extra_r==undef)?0:extra_r);

    sizexy=r__*2;
    extra_sizexy=extra_r_*2;

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

    // some orient hax here to properly support extra_align
    size_align(size=[sizexy,sizexy,h], extra_size=[extra_sizexy, extra_sizexy, extra_h], orient=orient, orient_ref=[0,0,1], align=align, extra_align=extra_align)
    {
        if(round_radius==undef)
        {
            cylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, center=true);
        }
        else
        {
            rcylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, round_radius=round_radius);
        }
    }
}

/*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=undef, r1=undef, r2=undef, h=10, round_radius=2, align=[0,0,0], orient=[0,0,1])
{
    useDia = r == undef && (r1 == undef && r2 == undef);

    r1_ = useDia?((d1==undef?undef:d1)/2):r1;
    r2_ = useDia?((d2==undef?undef:d2)/2):r2;
    r_= useDia?[d/2,d/2]:(r==undef?[r1_,r2_]:[r,r]);
    size_align(align=align, orient=orient)
    /*translate([0,0,-h/2])*/
    hull()
    {
        /*a = r_[0]-r_[1];*/
        /*b = h;*/
        /*c = pythag_hyp(a,b);*/
        /*echo(c);*/
        /*d = c;//pythag_leg(a,c);*/
        /*echo(d);*/
        /*translate([0,r1-round_radius,0])*/
        /*cube([d,d,d]);*/
        /*angle2 = -atan2(-h, r1-r2);*/
        /*echo(angle2);*/
        /*x2 = r2-r1 < 0 ? (round_radius*2*cos(angle2)) : (round_radius*2*sin(angle2));*/
        /*echo(x2)*/
        /*translate([0, 0, h/2-round_radius])*/
        /*torus(radius=r_[1]-round_radius, radial_width=round_radius, align=[0,0,0]);*/

        for(z=[-1,1])
        translate([0, 0, z*(-h/2)])
        {
            /*rd = abs(r1-r2);*/
            /*angle1 = atan2(h, abs(r2-r1));*/
            /*x1 = round_radius*2*cos(angle1);*/
            /*echo(angle1, x1);*/
            r__=z!=-1?r_[0]:r_[1];
            torus(radius=r__-round_radius/2, radial_width=round_radius/2, align=[0,0,z]);

            /*translate([0, 0, -round_radius])*/
            /*cubea([r__*2,r__*2,5], 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_=d==undef?r:d/2;
    d_=r==undef?d:r*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);
    }
}

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


corner roller holder started

corner roller holder started

// corner parts & rollers to guide cards & belts

cornershape();

partht = 14;
curve = 10.9;

module cornershape(diam=curve, ht=partht, rod=0.254*25.4/2){
    difference(){
        union(){
            cylinder(r=diam/2, h=ht, $fn=64, center=false);
            translate([0,diam/1.41, ht/2])
                cube([diam,diam*1.41,ht], center=true);
            translate([diam/1.41, 0, ht/2])
                cube([diam*1.41, diam, ht], center=true);
        }
    translate([0,0,-.05])
        #boltnut();
    }
}

module boltnut(rod=.254*25.4/2, ht=partht, nutrad=12.65/2, washrad=14/2, washthk=2, nutht=5.6){
    cylinder(r=rod, h=ht+0.1, $fn=24, center=false);
    translate([0,0,ht-nutht])
        cylinder(r=nutrad, h=partht, $fn=6, center=false);
}

module axles(rad=0.254*25.4/2, length=curve*1.41);

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


The syntax error was corrected.

The syntax error was corrected.

/**
 * Mike Hall showed and gave me afew of one day at work.
 *
 * The height of the board with cap touch plat is listed as 3mm.

 *		http://www.cnx-software.com/2017/07/27/httm-backlit-capacitive-touch-switch-button-sells-for-about-one-dollar/
 *
 *      From the link:
				 HTTM button specifications:

				 Voltage input range: + 2.7v to + 6v
				 Signal output – Voltage: + 3.3v; Current up to 500 mA
				 Header – 3-pin with GND, VCC, and OUT
				 Backlight color – red, blue (cyan), or yellow
				 Dimensions – 20.4 x 16.6 mm
				 Operating temperature range: -30 ℃ to + 70 ℃

	 https://www.aliexpress.com/item/10-pcs-red-color-HTTM-Series-2-7V-6V-Capacitive-Touch-Switch-Module-Strong-anti-interference/32814839036.html

		 From aliexpress:

			 Working voltage: + 2.7 ~ 6V
			 Working temperature: 30 ~ +70 °
			  OUT pin Output voltage: + 3.3V ± 0.1V
			 OUTPin maximum output current:500mA
 */

module httmBacklitCapacitiveTouchSwitchMountingHole(zLength = 3.0)
{
	xLength = 20.4;
	yLength = 16.6;

	cube([xLength, yLength, zLength]);
}

/**
 * Mike Hall showed and gave me afew of one day at work.
 *
 * The height of the board with cap touch plat is listed as 3mm.

 *		http://www.cnx-software.com/2017/07/27/httm-backlit-capacitive-touch-switch-button-sells-for-about-one-dollar/
 *
 *      From the link:
				 HTTM button specifications:

				 Voltage input range: + 2.7v to + 6v
				 Signal output – Voltage: + 3.3v; Current up to 500 mA
				 Header – 3-pin with GND, VCC, and OUT
				 Backlight color – red, blue (cyan), or yellow
				 Dimensions – 20.4 x 16.6 mm
				 Operating temperature range: -30 ℃ to + 70 ℃

	 https://www.aliexpress.com/item/10-pcs-red-color-HTTM-Series-2-7V-6V-Capacitive-Touch-Switch-Module-Strong-anti-interference/32814839036.html

		 From aliexpress:

			 Working voltage: + 2.7 ~ 6V
			 Working temperature: 30 ~ +70 °
			  OUT pin Output voltage: + 3.3V ± 0.1V
			 OUTPin maximum output current:500mA
 */

module httmBacklitCapacitiveTouchSwitchMountingHole(zLength = 3.0)
{
	xLength = 20.4;
	yLength = 16.6

	cube([xLength, yLength, zLength]);
}


code simplified and distances re-calculated

$fn = 100;
eps = 0.01;

module tester()
{
  module rise_for(h)
  {
    translate([0, 0, 11-h+eps])
      children();
  }
  module up()
  {
    translate([0, 9, 0])
      children();
  }
  module right()
  {
    translate([9, 0, 0])
      children();
  }
  module pair(d, h)
  {
    right()
    {
      rise_for(h)
      {
        cylinder(d=d, h=h);
        up()
          cylinder(d=d, h=h+10);
      }
      children();
    }
  }

  difference()
  {
    cube([37, 20, 11]);
    translate([-3, 5, 0])
    {
      pair(d=6.4, h=10.5)      // M5x9.5
        pair(d=6.4, h=6.8)     // M5x5.8
          pair(d=4.0, h=6.7)   // M3x5.7
            pair(d=4.0, h=4.0) // M3x3.0
        ;
    }
  }
}

tester();


positioned sides #1

positioned sides #1

module glass(w,d,h) {
  color([1,1,1,0.25])
  cube([w,d,h], center=true);
}

module side1(width, height, support_height, wall_thickness, cut_depth, glass_thickness) {
  gap_width = width + 2;
  color([1,0.1,0.0,0.75])
  difference() {
    cube([width,height,wall_thickness], center=true);
    translate([
      -1,
      height / 2 - support_height - glass_thickness / 2,
      wall_thickness-cut_depth
    ])
      cube([gap_width,glass_thickness,wall_thickness], center=true);
  }
}

module side2(width, height, support_height, wall_thickness, cut_depth, glass_thickness) {
  height2 = height + 2;
  color([1,0.1,0.0,0.75])
    difference() {
      side1(width, height, wall_thickness, cut_depth, glass_thickness);
      translate([width/2-wall_thickness/2+1,0,wall_thickness-cut_depth])
        cube([wall_thickness+2,height2,wall_thickness], center=true);
      translate([-width/2+wall_thickness/2-1,0,wall_thickness-cut_depth])
        cube([wall_thickness+2,height2,wall_thickness], center=true);
    }
}

width   = 120;
height  = 80;
glass_thickness = 8;
wall_height = 30;
wall_thickness = 3;
cut_depth = 1;
support_height = 1;

glass(width, height, glass_thickness);
rotate([-90,0,0])
  translate([0,support_height+glass_thickness/2-wall_height/2,cut_depth-(height+wall_thickness)/2])
    side1(width, wall_height, support_height, wall_thickness, cut_depth, glass_thickness);
rotate([90,180,0])
  translate([0,support_height+glass_thickness/2-wall_height/2,cut_depth-(height+wall_thickness)/2])
    side1(width, wall_height, support_height, wall_thickness, cut_depth, glass_thickness);
//  side2(width, 30, wall_thickness, cut_depth, glass_thickness);

module glass(w,d,h) {
  color([1,1,1,0.25])
  cube([w,d,h], center=true);
}

module side1(width, height, wall_thickness, cut_depth, glass_thickness) {
  gap_width = width + 2;
  support_width = 2;
  color([1,0.1,0.0,0.75])
  difference() {
    cube([width,height,wall_thickness], center=true);
    translate([
      -1,
      height / 2 - support_width - glass_thickness / 2,
      wall_thickness-cut_depth
    ])
      cube([gap_width,glass_thickness,wall_thickness], center=true);
  }
}

module side2(width, height, wall_thickness, cut_depth, glass_thickness) {
  height2 = height + 2;
  color([1,0.1,0.0,0.75])
    difference() {
      side1(width, height, wall_thickness, cut_depth, glass_thickness);
      translate([width/2-wall_thickness/2+1,0,wall_thickness-cut_depth])
        cube([wall_thickness+2,height2,wall_thickness], center=true);
      translate([-width/2+wall_thickness/2-1,0,wall_thickness-cut_depth])
        cube([wall_thickness+2,height2,wall_thickness], center=true);
    }
}

width  = 120;
depth  = 80;
glass_thickness = 4;
wall_thickness = 3;
cut_depth = 1;

//glass(width, depth, glass_thickness);
//rotate([90,00,0])
  side2(width, 30, wall_thickness, cut_depth, glass_thickness);


/ ‘Impression 3D/2016 - Trocar/trocar-test1.scad’


config: switch to sf1 bushings on X

config: switch to sf1 bushings on X

include <MCAD/stepper.scad>
include <screws.scad>
include <pulley.scad>
include <thing_libutils/bearing_data.scad>
include <thing_libutils/metric-thread-data.scad>
include <thing_libutils/metric-hexnut-data.scad>
include <thing_libutils/misc.scad>

e=0.01;

// minimum size of a fragment
// resolution of any round object (segment length)
// Because of this variable very small circles have a smaller number of fragments than specified using $fa.
// The default value is 2.
$fs = 2;

// minimum angle for a fragment.
// The default value is 12 (i.e. 30 fragments for a full circle)
$fa = 12;

//hq
if(false)
{
    $fs= 0.5;
    $fa = 4;
}

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

extrusion_height            = 0.4*mm;

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

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

thick_wall_factor           = 4;

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

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

extrusion_size = 20*mm;
extrusion_thread = ThreadM5;
extrusion_thread_dia = lookup(ThreadSize, extrusion_thread);
extrusion_nut = MHexNutM5;
extrusion_nut_dia = lookup(MHexNutWidthMax, extrusion_nut);

// for tapped ends
extrusion_end_nut = MHexNutM6;

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

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

ziptie_type = [1.1*mm, 2.4*mm];
ziptie_thickness = ziptie_type[0];
ziptie_width = ziptie_type[1]+0.6*mm;
ziptie_bearing_distance=3*mm;

xaxis_rod_distance = 60*mm;
xaxis_rod_d = 9.975*mm;
xaxis_rod_l = 500*mm;
xaxis_rod_offset_x = 20*mm;
xaxis_bearing=bearing_sf1_1010;
/*xaxis_bearing=bearing_igus_rj4jp_01_10;*/

xaxis_pulley = pulley_2GT_20T;
xaxis_pulley_inner_d = xaxis_pulley[2];
xaxis_idler_pulley = pulley_2GT_20T_idler;
xaxis_idler_pulley_inner_d = xaxis_idler_pulley[2];
xaxis_idler_pulley_outer_d = xaxis_idler_pulley[3];

xaxis_belt_width = 6*mm;
xaxis_beltpath_height = xaxis_pulley_inner_d+5*mm;
xaxis_beltpath_width = max(xaxis_belt_width+3*mm, xaxis_pulley[0]+2*mm);

xaxis_carriage_bearing_offset_y = ziptie_thickness+3*mm;
xaxis_carriage_beltpath_offset = xaxis_carriage_bearing_offset_y+xaxis_bearing[1]/2;

xaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing=bearing_igus_rj4jp_01_12;
/*yaxis_bearing=bearing_sf1_1212;*/
yaxis_bearing_distance_y = 7*cm;

yaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);

yaxis_pulley = pulley_2GT_20T;
yaxis_pulley_inner_d = yaxis_pulley[2];
ymotor_mount_thickness = 5;
ymotor_mount_thickness_h = 5;
yaxis_motor_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_motor_offset_z = -5*mm;
yaxis_belt_path_offset_x = -yaxis_pulley_inner_d/2;
yaxis_belt_path_offset_z = yaxis_motor_offset_z + 15*mm;

yaxis_idler_pulley = pulley_2GT_20T_idler;
yaxis_idler_pulley_inner_d = yaxis_idler_pulley[2];
yaxis_idler_pulley_outer_d = yaxis_idler_pulley[3];
yaxis_idler_pulley_h = yaxis_idler_pulley[0];
yaxis_idler_mount_thickness = 5;
yaxis_idler_pulley_tight_len = 20*mm;
yaxis_idler_pulley_offset_y = yaxis_idler_mount_thickness + yaxis_pulley_inner_d/2 + yaxis_idler_pulley_tight_len;
yaxis_idler_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_idler_offset_z = 10*mm;

yaxis_carriage_size=[220*mm,220*mm,5*mm];

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

// Nema17 motor w/340mm long 8*mm leadscrew
zaxis_motor = dict_replace_multiple(Nema17,
        [
        [NemaAxleDiameter, 8*mm],
        [NemaFrontAxleLength, 340*mm],
        ]);

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_h = lookup(NemaLengthLong,zaxis_motor);

// inner_d, outer_d, thread, outer_h, full_h
zaxis_nut = [20*mm, 36*mm, 8*mm, 5*mm, 23*mm];

zaxis_motor_offset_z = 10*mm;
zmotor_mount_thickness = 5;
zmotor_mount_thickness_h = 10;
zmotor_mount_motor_offset=5;

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_h = lookup(NemaLengthLong,zaxis_motor);
zmotor_mount_thread_dia = lookup(ThreadSize, extrusion_thread);
zmotor_mount_width = zmotor_w+zmotor_mount_thickness*2 + zmotor_mount_thread_dia*8;
zmotor_mount_h = main_lower_dist_z+extrusion_size+zaxis_motor_offset_z;

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

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

zaxis_nut_mount_outer = zaxis_nut[1]/2 + zaxis_rod_d/2 + 1*mm;

// offset between Z motor screw and z rod
// place z rod as close as possible (depends on z nut and also motor etc)
zaxis_rod_screw_distance_x = max(zaxis_nut_mount_outer, zaxis_rod_d/2 + zmotor_w/2 + 1*mm);

// z rod offset from lower extrusion (outer)
zmotor_mount_rod_offset_x = zmotor_w/2+zaxis_rod_screw_distance_x+zmotor_mount_motor_offset;

// z screw offset from lower extrusion (outer)
zmotor_mount_screw_offset_x = zmotor_mount_rod_offset_x - zaxis_rod_screw_distance_x ;

color_extrusion = "DimGray";
color_rods = "CornflowerBlue";
color_part = "DarkRed";
color_gantry_connectors = "OliveDrab";

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

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

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

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

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

include <MCAD/stepper.scad>
include <screws.scad>
include <pulley.scad>
include <thing_libutils/bearing_data.scad>
include <thing_libutils/metric-thread-data.scad>
include <thing_libutils/metric-hexnut-data.scad>
include <thing_libutils/misc.scad>

e=0.01;

// minimum size of a fragment
// resolution of any round object (segment length)
// Because of this variable very small circles have a smaller number of fragments than specified using $fa.
// The default value is 2.
$fs = 2;

// minimum angle for a fragment.
// The default value is 12 (i.e. 30 fragments for a full circle)
$fa = 12;

//hq
if(false)
{
    $fs= 0.5;
    $fa = 4;
}

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

extrusion_height            = 0.4*mm;

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

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

thick_wall_factor           = 4;

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

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

extrusion_size = 20*mm;
extrusion_thread = ThreadM5;
extrusion_thread_dia = lookup(ThreadSize, extrusion_thread);
extrusion_nut = MHexNutM5;
extrusion_nut_dia = lookup(MHexNutWidthMax, extrusion_nut);

// for tapped ends
extrusion_end_nut = MHexNutM6;

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

gantry_connector_thickness = 5;

rod_fit_tolerance=1.01;

ziptie_type = [1.1*mm, 2.4*mm];
ziptie_thickness = ziptie_type[0];
ziptie_width = ziptie_type[1]+0.6*mm;
ziptie_bearing_distance=3*mm;

xaxis_rod_distance = 60*mm;
xaxis_rod_d = 9.975*mm;
xaxis_rod_l = 500*mm;
xaxis_rod_offset_x = 20*mm;
/*xaxis_bearing=bearing_sf1_1010;*/
xaxis_bearing=bearing_igus_rj4jp_01_10;

xaxis_pulley = pulley_2GT_20T;
xaxis_pulley_inner_d = xaxis_pulley[2];
xaxis_idler_pulley = pulley_2GT_20T_idler;
xaxis_idler_pulley_inner_d = xaxis_idler_pulley[2];
xaxis_idler_pulley_outer_d = xaxis_idler_pulley[3];

xaxis_belt_width = 6*mm;
xaxis_beltpath_height = xaxis_pulley_inner_d+5*mm;
xaxis_beltpath_width = max(xaxis_belt_width+3*mm, xaxis_pulley[0]+2*mm);

xaxis_carriage_bearing_offset_y = ziptie_thickness+3*mm;
xaxis_carriage_beltpath_offset = xaxis_carriage_bearing_offset_y+xaxis_bearing[1]/2;

xaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing=bearing_igus_rj4jp_01_12;
/*yaxis_bearing=bearing_sf1_1212;*/
yaxis_bearing_distance_y = 7*cm;

yaxis_motor = dict_replace(Nema17, NemaFrontAxleLength, 22*mm);

yaxis_pulley = pulley_2GT_20T;
yaxis_pulley_inner_d = yaxis_pulley[2];
ymotor_mount_thickness = 5;
ymotor_mount_thickness_h = 5;
yaxis_motor_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_motor_offset_z = -5*mm;
yaxis_belt_path_offset_x = -yaxis_pulley_inner_d/2;
yaxis_belt_path_offset_z = yaxis_motor_offset_z + 15*mm;

yaxis_idler_pulley = pulley_2GT_20T_idler;
yaxis_idler_pulley_inner_d = yaxis_idler_pulley[2];
yaxis_idler_pulley_outer_d = yaxis_idler_pulley[3];
yaxis_idler_pulley_h = yaxis_idler_pulley[0];
yaxis_idler_mount_thickness = 5;
yaxis_idler_pulley_tight_len = 20*mm;
yaxis_idler_pulley_offset_y = yaxis_idler_mount_thickness + yaxis_pulley_inner_d/2 + yaxis_idler_pulley_tight_len;
yaxis_idler_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_idler_offset_z = 10*mm;

yaxis_carriage_size=[220*mm,220*mm,5*mm];

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

// Nema17 motor w/340mm long 8*mm leadscrew
zaxis_motor = dict_replace_multiple(Nema17,
        [
        [NemaAxleDiameter, 8*mm],
        [NemaFrontAxleLength, 340*mm],
        ]);

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_h = lookup(NemaLengthLong,zaxis_motor);

// inner_d, outer_d, thread, outer_h, full_h
zaxis_nut = [20*mm, 36*mm, 8*mm, 5*mm, 23*mm];

zaxis_motor_offset_z = 10*mm;
zmotor_mount_thickness = 5;
zmotor_mount_thickness_h = 10;
zmotor_mount_motor_offset=5;

zmotor_w = lookup(NemaSideSize,zaxis_motor);
zmotor_h = lookup(NemaLengthLong,zaxis_motor);
zmotor_mount_thread_dia = lookup(ThreadSize, extrusion_thread);
zmotor_mount_width = zmotor_w+zmotor_mount_thickness*2 + zmotor_mount_thread_dia*8;
zmotor_mount_h = main_lower_dist_z+extrusion_size+zaxis_motor_offset_z;

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

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

zaxis_nut_mount_outer = zaxis_nut[1]/2 + zaxis_rod_d/2 + 1*mm;

// offset between Z motor screw and z rod
// place z rod as close as possible (depends on z nut and also motor etc)
zaxis_rod_screw_distance_x = max(zaxis_nut_mount_outer, zaxis_rod_d/2 + zmotor_w/2 + 1*mm);

// z rod offset from lower extrusion (outer)
zmotor_mount_rod_offset_x = zmotor_w/2+zaxis_rod_screw_distance_x+zmotor_mount_motor_offset;

// z screw offset from lower extrusion (outer)
zmotor_mount_screw_offset_x = zmotor_mount_rod_offset_x - zaxis_rod_screw_distance_x ;

color_extrusion = "DimGray";
color_rods = "CornflowerBlue";
color_part = "DarkRed";
color_gantry_connectors = "OliveDrab";

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

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

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

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

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


moved link up a bit from foot to make a bit of an ankle

// $URL: svn+ssh://mrwhat@ssh.boim.com/home/mrwhat/svn/Walker/trunk/JansenFoot.scad $
// $Id: JansenFoot.scad 438 2015-03-03 14:39:59Z mrwhat $

padH = 0.3;  // extra clearance amount for H end of CH link

module bracedFoot(dLeft,dBase,dPerp) { // ---------------- foot with out-of-axis support
braceHeight = NodeHeight3; // 3*TrueNodeHeight-.4;  // A little shorter than the hinge-pin
dRight = 0.65 * (dBase-dLeft);  // scoot brace in a bit from foot
dLeft1 = dLeft-Frad-1-((0.5*Frad)/(dLeft-Frad-1));
union() { difference() { union() {
   translate([-dLeft,0,0]) {
      cylinder(h=NodeHeight,r1=Frad+.2,r2=Frad-.2,$fn=48); }
   hull() {
      translate([0,dPerp,0]) cylinder(h=braceHeight,r1=Hrad+2,r2=Hrad+1.6,$fn=48);
      translate([0,dPerp-3,0]) cylinder(h=braceHeight-1,r1=Hrad+1,r2=Hrad+0.5,$fn=32);
      translate([.22*dRight,.8*dPerp,1.1]) sphere(r=1,$fn=6); }
   hull() {
      translate([0,dPerp,0]) cylinder(h=braceHeight,r1=Hrad+1.9,r2=Hrad+1.4,$fn=48);
      translate([0,dPerp-3,0]) cylinder(h=braceHeight-1,r1=Hrad+1,r2=Hrad+0.5,$fn=32);
      translate([-.28*dLeft1,(1-.23)*dPerp,2]) sphere(r=1,$fn=6); }

   // foot
   translate([dBase-dLeft-LinkRad,0,0]) cylinder(h=NodeHeight+.5,r=LinkRad,$fn=80);

   hull() {
      translate([0,dPerp ,0]) cylinder(h=braceHeight  ,r1=1.6,r2=1,$fn=6);
      translate([dRight,0,0]) cylinder(h=BarHeight+0.8,r1=1.6,r2=1,$fn=6); }
   hull() {
      translate([0,dPerp ,0]) cylinder(h=BarHeight,r1=LinkRad,r2=LinkRad-.5,$fn=6);
      translate([dRight,0,0]) cylinder(h=BarHeight,r1=LinkRad,r2=LinkRad-.5,$fn=6); }
   hull() {
      translate([-dLeft1,-Frad*0.5,0])  cylinder(h=BarHeight+1.5,r1=1.6,r2=1,$fn=6);
      translate([0,dPerp,0])            cylinder(h=braceHeight  ,r1=1.6,r2=1,$fn=6); }
   hull() {
      translate([-dLeft1+((8*Frad)/(dLeft-Frad-1)),0,0])
                             cylinder(h=BarHeight,r1=LinkRad,r2=LinkRad-.5,$fn=6);
      translate([0,dPerp,0]) cylinder(h=BarHeight,r1=LinkRad,r2=LinkRad-.5,$fn=6); }
   hull() {     // re-inforcing pyramid over main, long leg
      translate([-dLeft+2*Frad,0,0]) cylinder(h=BarHeight,r1=Frad-1,r2=Frad-3,$fn=6);
      translate([dBase-dLeft-2*LinkRad,0,0]) cylinder(h=BarHeight,r1=LinkRad,r2=LinkRad-2,$fn=6);
      translate([0,0,1.5*NodeHeight-1]) sphere(r=1,$fn=16);   }

   difference() { hull() {   // main, long-leg segment
      translate([-dLeft,0,0]) {      nodeCyl(BarHeight,Frad-1);
      translate([dBase-LinkRad,0,0]) nodeCyl(BarHeight,LinkRad-1); }
     }
     translate([-dLeft,0,-1.5]) hull(){nodeCyl(BarHeight,Frad-2.4);
        translate([dBase-LinkRad-2,0,0])nodeCyl(BarHeight,.4);}
   }

   hull(){   // stop to keep "knee" from hyper-extending
      translate([-dLeft-Frad+2,0,0]) cylinder(h=BarHeight,r=2,$fn=8);
      translate([-dLeft,-Frad+2,0])  cylinder(h=BarHeight,r=2,$fn=8);
      translate([-dLeft-Frad+2,-Frad-3,0]) cylinder(h=BarHeight,r=2,$fn=12); }
   translate(   [-dLeft-Frad+2,-Frad-3,0]) cylinder(h=3*BarHeight,r1=3,r2=2,$fn=24);
   }
   translate([0,dPerp,0])  drillHole(Hrad);
   translate([-dLeft,0,0]) drillHole(Drad);

   // hollow out re-inforcing pyramid
   hull() { translate([-dLeft+2*Frad+2,0,-1.5]) cylinder(h=BarHeight,r1=Frad-2,r2=Frad-4,$fn=6);
      translate([dBase-dLeft-3*LinkRad,0,-1.5]) cylinder(h=BarHeight,r1=1.5,r2=.2,$fn=6);
      translate([0,0,1.5*NodeHeight-2.5]) sphere(r=0.5,$fn=16); }

   // had trouble with fill around braced link.  See if adding little hollows
   // helps slicer to fill better
   translate([-dLeft,0,NodeHeight/2]) {
      for(a=[0,30,60,90,120,150,180,210,240,270,300,330]) {
         translate([0.5*(Frad+Drad)*cos(a),0.5*(Frad+Drad)*sin(a),0])
            cylinder(h=NodeHeight-1.4,r=.4,$fn=6,center=true);
   }}

   // knock out a slot to take the CH linkage.
   translate([0,dPerp,NodeHeight-padH]) {
      cylinder(h=NodeHeight+2*padH,r=Hrad+3,$fn=48);
      hull() {
         translate([ 0,-4,0]) cube([.1,.1,NodeHeight+2*padH]);
         translate([ 7,-1,0]) cube([2,5,NodeHeight+2*padH]);
         translate([-7,-2,0]) cube([1,5,NodeHeight+2*padH]);
      }
   }

   //cube([3,11,11]);   // diagnostic slice to examine pyramid shell
   }
}

// custom support at H node
color("Cyan") union() {
  translate([0,29,NodeHeight-padH*.9]) difference() {
    cylinder(r2=4.4,r1=3.73,h=NodeHeight-.5,$fn=8);
    translate([0,0,-.1]) cylinder(r2=2.6,r1=3.4,h=5,$fn=8);
  }
if(0) {
  translate([0,29,NodeHeight*2-padH*2.5]) difference() {
    cylinder(r=4.55,h=1,$fn=8);
    translate([0,0,-.1]) cylinder(r=4.1,h=1.2,$fn=8);
  }
  translate([0,29.4,NodeHeight*2-padH*2.5]) difference() {
    cylinder(r=3.55,h=1,$fn=8);
    translate([0,0,-.1]) cylinder(r=3.1,h=1.2,$fn=8);
  }
  translate([4,28,NodeHeight*2-1.6]) rotate([0,0,60]) rotate([25,0,0]) cube([4,.35,4],center=true);
  translate([-3.5,27,NodeHeight*2-1.6]) rotate([0,0,-50]) rotate([25,0,0]) cube([4,.35,4],center=true);
} else {
  translate([0,dPerp,NodeHeight+2+padH]) {
    Hblade(4);
    rotate([0,0, 20]) Hblade();
    rotate([0,0, 50]) Hblade();
    rotate([0,0, 80]) Hblade();
    rotate([0,0,110]) Hblade();
    rotate([0,0,140]) Hblade();
    rotate([0,0,170]) Hblade();
    rotate([0,0,200]) Hblade(3.6);
    rotate([0,0,230]) Hblade(3.3);
    rotate([0,0,250]) Hblade(3.3);
    rotate([0,0,270]) Hblade(3.3);
    rotate([0,0,290]) Hblade(3.3);
    rotate([0,0,310]) Hblade(3.3);
    rotate([0,0,330]) Hblade(3.3);
    rotate([0,0,345]) Hblade(4.5);
  }
}
}

}

// Support blade for H node
lineW = 0.41;  // single line width
plateH = NodeHeight-2-padH*0.2;
module Hblade(len=3,h=plateH,w=lineW,cr=2) {
  translate([cr,-w/2,0]) cube([len,w,h]);
}

// example from config E, circa 140227
//bracedFoot(28.3675,75.792,29.3843);

// $URL: svn+ssh://mrwhat@ssh.boim.com/home/mrwhat/svn/Walker/trunk/JansenFoot.scad $
// $Id: JansenFoot.scad 438 2015-03-03 14:39:59Z mrwhat $

padH = 0.3;  // extra clearance amount for H end of CH link

module bracedFoot(dLeft,dBase,dPerp) { // ---------------- foot with out-of-axis support
braceHeight = NodeHeight3; // 3*TrueNodeHeight-.4;  // A little shorter than the hinge-pin
dRight = 0.9 * (dBase-dLeft);  // scoot brace in a bit from foot
dLeft1 = dLeft-Frad-1-((0.5*Frad)/(dLeft-Frad-1));
union() { difference() { union() {
   translate([-dLeft,0,0]) {
      cylinder(h=NodeHeight,r1=Frad+.2,r2=Frad-.2,$fn=48); }
   hull() {
      translate([0,dPerp,0]) cylinder(h=braceHeight,r1=Hrad+2,r2=Hrad+1.6,$fn=48);
      translate([0,dPerp-3,0]) cylinder(h=braceHeight-1,r1=Hrad+1,r2=Hrad+0.5,$fn=32);
      translate([.22*dRight,.85*dPerp,1.1]) sphere(r=1,$fn=6); }
   hull() {
      translate([0,dPerp,0]) cylinder(h=braceHeight,r1=Hrad+1.9,r2=Hrad+1.4,$fn=48);
      translate([0,dPerp-3,0]) cylinder(h=braceHeight-1,r1=Hrad+1,r2=Hrad+0.5,$fn=32);
      translate([-.28*dLeft1,(1-.23)*dPerp,2]) sphere(r=1,$fn=6); }

   // foot
   translate([dBase-dLeft-LinkRad,0,0]) cylinder(h=NodeHeight+.5,r=LinkRad,$fn=80);

   hull() {
      translate([0,dPerp ,0]) cylinder(h=braceHeight  ,r1=1.6,r2=1,$fn=6);
      translate([dRight,0,0]) cylinder(h=BarHeight+1.5,r1=1.6,r2=1,$fn=6); }
   hull() {
      translate([0,dPerp ,0]) cylinder(h=BarHeight,r1=LinkRad,r2=LinkRad-.5,$fn=6);
      translate([dRight,0,0]) cylinder(h=BarHeight,r1=LinkRad,r2=LinkRad-.5,$fn=6); }
   hull() {
      translate([-dLeft1,-Frad*0.5,0])  cylinder(h=BarHeight+1.5,r1=1.6,r2=1,$fn=6);
      translate([0,dPerp,0])            cylinder(h=braceHeight  ,r1=1.6,r2=1,$fn=6); }
   hull() {
      translate([-dLeft1+((8*Frad)/(dLeft-Frad-1)),0,0])
                             cylinder(h=BarHeight,r1=LinkRad,r2=LinkRad-.5,$fn=6);
      translate([0,dPerp,0]) cylinder(h=BarHeight,r1=LinkRad,r2=LinkRad-.5,$fn=6); }
   hull() {     // re-inforcing pyramid over main, long leg
      translate([-dLeft+2*Frad,0,0]) cylinder(h=BarHeight,r1=Frad-1,r2=Frad-3,$fn=6);
      translate([dBase-dLeft-2*LinkRad,0,0]) cylinder(h=BarHeight,r1=LinkRad,r2=LinkRad-2,$fn=6);
      translate([0,0,1.5*NodeHeight-1]) sphere(r=1,$fn=16);   }

   difference() { hull() {   // main, long-leg segment
      translate([-dLeft,0,0]) {      nodeCyl(BarHeight,Frad-1);
      translate([dBase-LinkRad,0,0]) nodeCyl(BarHeight,LinkRad-1); }
     }
     translate([-dLeft,0,-1.5]) hull(){nodeCyl(BarHeight,Frad-2.4);
        translate([dBase-LinkRad-2,0,0])nodeCyl(BarHeight,.4);}
   }

   hull(){   // stop to keep "knee" from hyper-extending
      translate([-dLeft-Frad+2,0,0]) cylinder(h=BarHeight,r=2,$fn=8);
      translate([-dLeft,-Frad+2,0])  cylinder(h=BarHeight,r=2,$fn=8);
      translate([-dLeft-Frad+2,-Frad-3,0]) cylinder(h=BarHeight,r=2,$fn=12); }
   translate(   [-dLeft-Frad+2,-Frad-3,0]) cylinder(h=3*BarHeight,r1=3,r2=2,$fn=24);
   }
   translate([0,dPerp,0])  drillHole(Hrad);
   translate([-dLeft,0,0]) drillHole(Drad);

   // hollow out re-inforcing pyramid
   hull() { translate([-dLeft+2*Frad+2,0,-1.5]) cylinder(h=BarHeight,r1=Frad-2,r2=Frad-4,$fn=6);
      translate([dBase-dLeft-3*LinkRad,0,-1.5]) cylinder(h=BarHeight,r1=1.5,r2=.2,$fn=6);
      translate([0,0,1.5*NodeHeight-2.5]) sphere(r=0.5,$fn=16); }

   // had trouble with fill around braced link.  See if adding little hollows
   // helps slicer to fill better
   translate([-dLeft,0,NodeHeight/2]) {
      for(a=[0,30,60,90,120,150,180,210,240,270,300,330]) {
         translate([0.5*(Frad+Drad)*cos(a),0.5*(Frad+Drad)*sin(a),0])
            cylinder(h=NodeHeight-1.4,r=.4,$fn=6,center=true);
   }}

   // knock out a slot to take the CH linkage.
   translate([0,dPerp,NodeHeight-padH]) {
      cylinder(h=NodeHeight+2*padH,r=Hrad+3,$fn=48);
      hull() {
         translate([ 0,-4,0]) cube([.1,.1,NodeHeight+2*padH]);
         translate([ 7,-1,0]) cube([2,5,NodeHeight+2*padH]);
         translate([-7,-2,0]) cube([1,5,NodeHeight+2*padH]);
      }
   }

   //cube([3,11,11]);   // diagnostic slice to examine pyramid shell
   }
}

// custom support at H node
color("Cyan") union() {
  translate([0,29,NodeHeight-padH*.9]) difference() {
    cylinder(r2=4.4,r1=3.73,h=NodeHeight-.5,$fn=8);
    translate([0,0,-.1]) cylinder(r2=2.6,r1=3.4,h=5,$fn=8);
  }
if(0) {
  translate([0,29,NodeHeight*2-padH*2.5]) difference() {
    cylinder(r=4.55,h=1,$fn=8);
    translate([0,0,-.1]) cylinder(r=4.1,h=1.2,$fn=8);
  }
  translate([0,29.4,NodeHeight*2-padH*2.5]) difference() {
    cylinder(r=3.55,h=1,$fn=8);
    translate([0,0,-.1]) cylinder(r=3.1,h=1.2,$fn=8);
  }
  translate([4,28,NodeHeight*2-1.6]) rotate([0,0,60]) rotate([25,0,0]) cube([4,.35,4],center=true);
  translate([-3.5,27,NodeHeight*2-1.6]) rotate([0,0,-50]) rotate([25,0,0]) cube([4,.35,4],center=true);
} else {
  translate([0,dPerp,NodeHeight+2+padH]) {
    Hblade(4);
    rotate([0,0, 20]) Hblade();
    rotate([0,0, 50]) Hblade();
    rotate([0,0, 80]) Hblade();
    rotate([0,0,110]) Hblade();
    rotate([0,0,140]) Hblade();
    rotate([0,0,170]) Hblade();
    rotate([0,0,200]) Hblade(3.6);
    rotate([0,0,230]) Hblade(3.3);
    rotate([0,0,250]) Hblade(3.3);
    rotate([0,0,270]) Hblade(3.3);
    rotate([0,0,290]) Hblade(3.3);
    rotate([0,0,310]) Hblade(3.3);
    rotate([0,0,330]) Hblade(3.3);
    rotate([0,0,345]) Hblade(4.5);
  }
}
}

}

// Support blade for H node
lineW = 0.41;  // single line width
plateH = NodeHeight-2-padH*0.2;
module Hblade(len=3,h=plateH,w=lineW,cr=2) {
  translate([cr,-w/2,0]) cube([len,w,h]);
}

// example from config E, circa 140227
//bracedFoot(28.3675,75.792,29.3843);


Created scad file for the BLE112 radio.

Created scad file for the BLE112 radio.

module BLE112(){

	board_width = 12.05;
	board_length = 18.10;
	board_thickness = 0.80;
	contact_radius = 0.35;
	contact_spacing = 1.25;
	shield_width = 10.85;
	shield_length = 11.85;
	shield_thickness = 1.5;
	shield_offset = 0.85;
	shield_corner = sqrt(2);
	antenna_width = 1.6;
	antenna_length = 3.2;
	antenna_thickness = 1.3;
	antenna_offset_x = 0.6;
	antenna_offset_y = 0.9;

	translate([0,-contact_spacing,0]){
		union(){
			// Board
			color([0.3,0.3,1])
				translate([0,0,board_thickness / 2])
					difference(){
						cube([board_width, board_length, board_thickness], center=true);
						union(){
							translate([-contact_spacing*3.5,-board_length/2,0])
								for (i = [0 : 7]){
									translate([contact_spacing*i,0,0])
										cylinder(h=board_thickness + 2,
											r = contact_radius, center=true, $fn=18);
								}
							translate([board_width/2,-contact_spacing*6,0])
								for (i = [0 : 8]){
									translate([0,contact_spacing*i,0])
										cylinder(h=board_thickness + 2,
											r = contact_radius, center=true, $fn=18);
								}
							translate([-board_width/2,-contact_spacing*6,0])
								for (i = [0 : 12]){
									translate([0,contact_spacing*i,0])
										cylinder(h=board_thickness + 2,
											r = contact_radius, center=true, $fn=18);
								}
						}
					}
			// Shield
			color([0.6,0.6,0.6])
				translate([0,-(board_length - shield_length) / 2 + shield_offset,
					board_thickness + shield_thickness / 2])
					difference(){
						cube([shield_width, shield_length, shield_thickness],
							center=true	);
						union(){
							translate([shield_width / 2, shield_length / 2,0])
								rotate([0,0,45])
									cube([shield_corner,shield_corner,shield_thickness + 2],
									center=true);
							translate([-shield_width / 2, shield_length / 2,0])
								rotate([0,0,45])
									cube([shield_corner,shield_corner,shield_thickness + 2],
									center=true);
							translate([shield_width / 2, -shield_length / 2,0])
								rotate([0,0,45])
									cube([shield_corner,shield_corner,shield_thickness + 2],
									center=true);
							translate([-shield_width / 2, -shield_length / 2,0])
								rotate([0,0,45])
									cube([shield_corner,shield_corner,shield_thickness + 2],
									center=true);
						}
					}
			// Antenna
			color([1,1,1])
				translate([(board_width - antenna_length) / 2 - antenna_offset_y,
					(board_length - antenna_width) / 2 - antenna_offset_x,
					board_thickness + antenna_thickness / 2])
					cube([antenna_length,antenna_width,antenna_thickness], center=true);
		}
	}
}

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


screws: add demo mode to show all screws

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

include <thread-data.scad>
include <nut-data.scad>
include <nut-knurl-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(thread) = get(ThreadSize, thread);
function get_screw_head_d(thread) = 2 * get(ThreadSize, thread);

module screw(nut, thread, h=10, tolerance=1.05, head_embed=false, with_nut=true, with_head=true, nut_offset=0, orient=[0,0,1], align=[0,0,0])
{
    nut_thread = get(NutThread, nut);
    thread_ = fallback(thread, nut_thread);
    assert(thread_ != undef, "screw: No nut or thread given");
    /*assert(nut!=undef && thread!=undef && nut_thread != thread_, "screw: Mismatched nut and thread");*/

    head_h = get_screw_head_h(nut);
    nut_h = get(NutThickness,nut)*tolerance;
    threadsize = get(ThreadSize, thread_);

    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])
        {
            if(with_head)
            {
                translate([0,0,h/2+.01])
                screw_head(thread=thread_, 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 && nut != undef)
            {
                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, thread, h=10, tolerance=1.05, head_embed=false, with_nut=true, nut_cut_h=1000, with_head=true, head_cut_h=1000, nut_offset=0, cut_access=true, orient=[0,0,1], align=[0,0,0])
{
    nut_thread = get(NutThread, nut);
    thread_ = fallback(thread, nut_thread);
    assert(thread_ != undef, "screw_cut: No nut or thread given");
    /*assert(nut!=undef && thread!=undef && nut_thread != thread_, "screw_cut: Mismatched nut and thread");*/

    nut_h = get(NutThickness,nut)*tolerance;
    head_h = get_screw_head_h(thread_);
    assert(head_h != undef, "screw_cut: head_h is undef!");

    threadsize = get(ThreadSize, thread_);
    assert(threadsize != undef, "screw_cut: threadsize is undef!");

    s = threadsize*tolerance;
    total_h = h;
    assert(s != undef, "screw_cut: s is undef!");
    size_align(size=[s, s, total_h], orient=-orient, orient_ref=[0,0,1], align=align)
    {
        translate([0,0,head_embed?-head_h:0])
        {
            if(with_head)
            {
                translate([0,0,h/2+.01])
                screw_head_cut(thread=thread_, tolerance=tolerance, override_h=head_cut_h, align=[0,0,1]);
            }

            screw_thread_cut(thread=thread_, h=h+.1, tolerance=tolerance, orient=[0,0,1], align=[0,0,0]);

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

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

module screw_thread(thread, h=10, tolerance=1.00, orient=[0,0,1], align=[0,0,0])
{
    assert(thread!=undef, "screw_thread: thread is undef");
    // TODO render thread
    threadsize = get(ThreadSize, thread);
    cylindera(d=threadsize, h=h, orient=orient, align=align);
}

module screw_thread_cut(thread, h=10, tolerance=1.05, orient=[0,0,1], align=[0,0,0])
{
    assert(thread!=undef, "screw_thread_cut: thread is undef");
    threadsize = get(ThreadSize, thread);
    cylindera(d=threadsize*tolerance, h=h, orient=orient, align=align);
}

module screw_head(thread, tolerance=1.00, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    assert(thread!=undef, "screw_head: thread is undef");

    threadsize = get(ThreadSize, thread);
    head_h = get_screw_head_h(thread);
    head_d = get_screw_head_d(thread);
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    difference()
    {
        cylindera(d=head_d, h = fallback(override_h,head_h));
        translate([0,0,head_h/2])
        cylindera(d=threadsize, h = head_d/2);
    }
}

module screw_head_cut(thread, tolerance=1.05, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    assert(thread!=undef, "screw_head_cut: thread is undef");

    threadsize = get(ThreadSize, thread);
    head_h = get_screw_head_h(thread);
    head_d = get_screw_head_d(thread)*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=fallback(override_h, head_h), align=[0,0,1]);
}

module screw_nut(nut, tolerance=1.00, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    assert(nut!=undef, "screw_nut: nut is undef");

    thickness = get(NutThickness,nut)*tolerance;
    d = get(NutWidthMin, nut)*tolerance;
    facets = get(NutFacets, nut);
    nut_hex_radius = hex_radius(get(NutWidthMax, nut))+.1;
    cylindera($fn=get(NutFacets, nut), r=nut_hex_radius, h=fallback(override_h, thickness), orient=orient, align=align);
}

module screw_nut_cut(nut, tolerance=1.05, h=1000, orient=[0,0,1], align=[0,0,0])
{
    assert(nut!=undef, "screw_nut_cut: nut is undef");

    thickness = get(NutThickness,nut)*tolerance;
    d = get(NutWidthMin, nut)*tolerance;
    size_align(size=[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]);
            }
        }
    }
}

function hex_radius(hexSize) = hexSize/2/sin(60);

module nut_trap_cut(nut, thread, 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])
{
    nut_thread = get(NutThread, nut);
    thread_ = fallback(thread, nut_thread);
    assert(thread_ != undef, "nut_trap_cut: No nut or thread given");
    /*assert(nut!=undef && thread!=undef && nut_thread != thread_, "nut_trap_cut: Mismatched nut and thread");*/

    threadsize = get(ThreadSize, thread_);
    head_h = get_screw_head_h(thread);
    nut_h = get(NutThickness, nut) +.5*mm;

    nut_width = get(NutWidthMin, nut);
    nut_hex_radius = hex_radius(nut_width)+.1*mm;
    s = nut_hex_radius;
    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)
            translate(-.15*mm*trap_axis)
            stack(dist=trap_h, axis=trap_axis)
            {
                orient(orient)
                {
                    rotate([0,0,30])
                    cylindera($fn=get(NutFacets, nut), r=nut_hex_radius, h=nut_h, align=[0,0,0]);
                }

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

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

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

    }
}

// all nuts
if(false)
{
    for(nuti=[0:1:len(AllNut)-1])
    {
        nut = AllNut[nuti];
        v_threadsize = v_get(AllNut,ThreadSize);
        v_nutwidth = v_get(AllNut,NutWidthMin);
        dist = v_cumsum(v_nutwidth, 0, nuti)[nuti]*1.2;
        translate(XAXIS*dist)
        rotate([0,0,30])
        screw(nut=nut, h=get(NutWidthMax, nut)*5, head_embed=false, orient=[0,0,-1], align=[0,0,1]);
    }
}

if(false)
{
    box_w = 40;
    box_h = 10;
    box_d = 10;
    o = 10;

    /*$show_vit = true;*/
    $fs= 0.1;
    $fa = 5;

    nut1 = NutHexM3;
    nut2 = NutHexM5;
    nut3 = NutKnurlInsertM3_3_42;
    nut4 = NutKnurlInsertM3_5_42;

    difference()
    {
        rcubea([box_w,box_d,box_h], align=[1,0,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(thread=ThreadM5, 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 <system.scad>
include <shapes.scad>
include <transforms.scad>
include <misc.scad>

include <thread-data.scad>
include <nut-data.scad>
include <nut-knurl-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(thread) = get(ThreadSize, thread);
function get_screw_head_d(thread) = 2 * get(ThreadSize, thread);

module screw(nut, thread, h=10, tolerance=1.05, head_embed=false, with_nut=true, with_head=true, nut_offset=0, orient=[0,0,1], align=[0,0,0])
{
    nut_thread = get(NutThread, nut);
    thread_ = fallback(thread, nut_thread);
    assert(thread_ != undef, "screw: No nut or thread given");
    /*assert(nut!=undef && thread!=undef && nut_thread != thread_, "screw: Mismatched nut and thread");*/

    head_h = get_screw_head_h(nut);
    nut_h = get(NutThickness,nut)*tolerance;
    threadsize = get(ThreadSize, thread_);

    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])
        {
            if(with_head)
            {
                translate([0,0,h/2+.01])
                screw_head(thread=thread_, 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 && nut != undef)
            {
                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, thread, h=10, tolerance=1.05, head_embed=false, with_nut=true, nut_cut_h=1000, with_head=true, head_cut_h=1000, nut_offset=0, cut_access=true, orient=[0,0,1], align=[0,0,0])
{
    nut_thread = get(NutThread, nut);
    thread_ = fallback(thread, nut_thread);
    assert(thread_ != undef, "screw_cut: No nut or thread given");
    /*assert(nut!=undef && thread!=undef && nut_thread != thread_, "screw_cut: Mismatched nut and thread");*/

    nut_h = get(NutThickness,nut)*tolerance;
    head_h = get_screw_head_h(thread_);
    assert(head_h != undef, "screw_cut: head_h is undef!");

    threadsize = get(ThreadSize, thread_);
    assert(threadsize != undef, "screw_cut: threadsize is undef!");

    s = threadsize*tolerance;
    total_h = h;
    assert(s != undef, "screw_cut: s is undef!");
    size_align(size=[s, s, total_h], orient=-orient, orient_ref=[0,0,1], align=align)
    {
        translate([0,0,head_embed?-head_h:0])
        {
            if(with_head)
            {
                translate([0,0,h/2+.01])
                screw_head_cut(thread=thread_, tolerance=tolerance, override_h=head_cut_h, align=[0,0,1]);
            }

            screw_thread_cut(thread=thread_, h=h+.1, tolerance=tolerance, orient=[0,0,1], align=[0,0,0]);

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

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

module screw_thread(thread, h=10, tolerance=1.00, orient=[0,0,1], align=[0,0,0])
{
    assert(thread!=undef, "screw_thread: thread is undef");
    // TODO render thread
    threadsize = get(ThreadSize, thread);
    cylindera(d=threadsize, h=h, orient=orient, align=align);
}

module screw_thread_cut(thread, h=10, tolerance=1.05, orient=[0,0,1], align=[0,0,0])
{
    assert(thread!=undef, "screw_thread_cut: thread is undef");
    threadsize = get(ThreadSize, thread);
    cylindera(d=threadsize*tolerance, h=h, orient=orient, align=align);
}

module screw_head(thread, tolerance=1.00, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    assert(thread!=undef, "screw_head: thread is undef");

    threadsize = get(ThreadSize, thread);
    head_h = get_screw_head_h(thread);
    head_d = get_screw_head_d(thread);
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    difference()
    {
        cylindera(d=head_d, h = fallback(override_h,head_h));
        translate([0,0,head_h/2])
        cylindera(d=threadsize, h = head_d/2);
    }
}

module screw_head_cut(thread, tolerance=1.05, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    assert(thread!=undef, "screw_head_cut: thread is undef");

    threadsize = get(ThreadSize, thread);
    head_h = get_screw_head_h(thread);
    head_d = get_screw_head_d(thread)*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=fallback(override_h, head_h), align=[0,0,1]);
}

module screw_nut(nut, tolerance=1.00, override_h=undef, orient=[0,0,1], align=[0,0,0])
{
    assert(nut!=undef, "screw_nut: nut is undef");

    thickness = get(NutThickness,nut)*tolerance;
    d = get(NutWidthMin, nut)*tolerance;
    facets = get(NutFacets, nut);
    nut_hex_radius = hex_radius(get(NutWidthMax, nut))+.1;
    cylindera($fn=get(NutFacets, nut), r=nut_hex_radius, h=fallback(override_h, thickness), orient=orient, align=align);
}

module screw_nut_cut(nut, tolerance=1.05, h=1000, orient=[0,0,1], align=[0,0,0])
{
    assert(nut!=undef, "screw_nut_cut: nut is undef");

    thickness = get(NutThickness,nut)*tolerance;
    d = get(NutWidthMin, nut)*tolerance;
    size_align(size=[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]);
            }
        }
    }
}

function hex_radius(hexSize) = hexSize/2/sin(60);

module nut_trap_cut(nut, thread, 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])
{
    nut_thread = get(NutThread, nut);
    thread_ = fallback(thread, nut_thread);
    assert(thread_ != undef, "nut_trap_cut: No nut or thread given");
    /*assert(nut!=undef && thread!=undef && nut_thread != thread_, "nut_trap_cut: Mismatched nut and thread");*/

    threadsize = get(ThreadSize, thread_);
    head_h = get_screw_head_h(thread);
    nut_h = get(NutThickness, nut) +.5*mm;

    nut_width = get(NutWidthMin, nut);
    nut_hex_radius = hex_radius(nut_width)+.1*mm;
    s = nut_hex_radius;
    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)
            translate(-.15*mm*trap_axis)
            stack(dist=trap_h, axis=trap_axis)
            {
                orient(orient)
                {
                    rotate([0,0,30])
                    cylindera($fn=get(NutFacets, nut), r=nut_hex_radius, h=nut_h, align=[0,0,0]);
                }

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

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

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

    }
}

if(false)
{
    nut1 = NutHexM3;
    nut2 = NutHexM5;
    nut3 = NutKnurlInsertM3_3_42;
    nut4 = NutKnurlInsertM3_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 = 40;
    box_h = 10;
    box_d = 10;
    o = 10;

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

    difference()
    {
        rcubea([box_w,box_d,box_h], align=[1,0,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(thread=ThreadM5, 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]);
        }
    }
}


*: replace MCAD stepper with libutils

*: replace MCAD stepper with libutils

include <z-motor-mount.h>
include <thing_libutils/materials.scad>
include <thing_libutils/stepper.scad>

use <thing_libutils/attach.scad>
use <thing_libutils/shapes.scad>
use <thing_libutils/screws.scad>
use <thing_libutils/transforms.scad>
use <thing_libutils/stepper.scad>

use <rod-clamps.scad>

module zaxis_motor_mount(part)
{
    if(part==U)
    {
        difference()
        {
            zaxis_motor_mount(part="pos");
            zaxis_motor_mount(part="neg");
        }
        if($show_vit)
        zaxis_motor_mount(part="vit");
    }
    else if(part=="pos")
    material(Mat_Plastic)
    {
        // top plate
        rcubea([zmotor_w+zmotor_mount_thickness, zmotor_w+zmotor_mount_thickness*2, zmotor_mount_thickness_h], align=X+Z);

        // reinforcement plate between motor and extrusion
        rcubea([zmotor_mount_thickness, zmotor_w+2, zmotor_h], align=X-Z, extra_size=[0,0,2], extra_align=Z);

        // top extrusion mount plate
        translate([0, 0,-extrusion_size-zaxis_motor_offset_z])
        rcubea([zmotor_mount_thickness, zmotor_mount_width, extrusion_size], align=X+Z);

        // bottom extrusion mount plate
        translate([0, 0, -main_lower_dist_z-extrusion_size-zaxis_motor_offset_z])
        rcubea([zmotor_mount_thickness, zmotor_w+2, extrusion_size], align=X+Z);

        // side triangles
        for(i=[-1,1])
        {
            translate([zmotor_mount_thickness, i*((zmotor_w/2)+zmotor_mount_thickness/2), 2])
            triangle(
                zmotor_w,
                main_lower_dist_z+extrusion_size+zaxis_motor_offset_z+2,
                depth=zmotor_mount_thickness,
                align=X-Z,
                orient=X
                );

            translate([0, i*((zmotor_w/2)+zmotor_mount_thickness/2), 2])
            cubea([zmotor_mount_thickness, zmotor_mount_thickness, zmotor_mount_h+2], align=X-Z);
        }

        attach([[get(NemaSideSize,zaxis_motor)/2,0,0],N],zmotor_mount_conn_motor)
        motor_mount(part=part, model=zaxis_motor, thickness=zmotor_mount_thickness_h);
    }
    else if(part=="neg")
    {
        // cutout for motor cables
        translate([0,0,-30*mm])
        cubea([zmotor_mount_thickness*3, 20*mm, zmotor_h], align=-Z);

        // screw holes top
        for(y=[-1,1])
        tx(zmotor_mount_thickness)
        ty(y*(zmotor_w/2+zmotor_mount_thread_dia*3))
        tz(-extrusion_size)
        screw_cut(nut=extrusion_nut, head="button", h=12*mm, orient=-X, align=-X);

        // screw hole bottom
        for(y=[0])
        tx(zmotor_mount_thickness)
        ty(y*(zmotor_w/2+zmotor_mount_thread_dia*3))
        tz(-extrusion_size-main_lower_dist_z)
        screw_cut(nut=extrusion_nut, head="button", h=12*mm, orient=-X, align=-X);

        // cut out z rod
        tx(zmotor_mount_rod_offset_x)
        cylindera(d=zaxis_rod_d*rod_fit_tolerance, h=100, orient=Z);
    }
    else if(part=="vit")
    {
    }

    attach([[get(NemaSideSize,zaxis_motor)/2,0,0],N],zmotor_mount_conn_motor)
    motor_mount(part=part, model=zaxis_motor, thickness=zmotor_mount_thickness_h);
}

module part_z_motor_mount()
{
    rotate([0,-90,0])
    zaxis_motor_mount();
}

if(false)
zaxis_motor_mount();

include <z-motor-mount.h>
include <thing_libutils/materials.scad>
include <thing_libutils/stepper.scad>

use <thing_libutils/attach.scad>
use <thing_libutils/shapes.scad>
use <thing_libutils/screws.scad>
use <thing_libutils/transforms.scad>
use <thing_libutils/stepper.scad>

use <rod-clamps.scad>

module zaxis_motor_mount(part)
{
    if(part==U)
    {
        difference()
        {
            zaxis_motor_mount(part="pos");
            zaxis_motor_mount(part="neg");
        }
        if($show_vit)
        zaxis_motor_mount(part="vit");
    }
    else if(part=="pos")
    material(Mat_Plastic)
    {
        // top plate
        rcubea([zmotor_w+zmotor_mount_thickness, zmotor_w+zmotor_mount_thickness*2, zmotor_mount_thickness_h], align=X+Z);

        // reinforcement plate between motor and extrusion
        rcubea([zmotor_mount_thickness, zmotor_w+2, zmotor_h], align=X-Z, extra_size=[0,0,2], extra_align=Z);

        // top extrusion mount plate
        translate([0, 0,-extrusion_size-zaxis_motor_offset_z])
        rcubea([zmotor_mount_thickness, zmotor_mount_width, extrusion_size], align=X+Z);

        // bottom extrusion mount plate
        translate([0, 0, -main_lower_dist_z-extrusion_size-zaxis_motor_offset_z])
        rcubea([zmotor_mount_thickness, zmotor_w+2, extrusion_size], align=X+Z);

        // side triangles
        for(i=[-1,1])
        {
            translate([zmotor_mount_thickness, i*((zmotor_w/2)+zmotor_mount_thickness/2), 2])
            triangle(
                zmotor_w,
                main_lower_dist_z+extrusion_size+zaxis_motor_offset_z+2,
                depth=zmotor_mount_thickness,
                align=X-Z,
                orient=X
                );

            translate([0, i*((zmotor_w/2)+zmotor_mount_thickness/2), 2])
            cubea([zmotor_mount_thickness, zmotor_mount_thickness, zmotor_mount_h+2], align=X-Z);
        }

        attach([[get(NemaSideSize,zaxis_motor)/2,0,0],N],zmotor_mount_conn_motor)
        motor_mount(part=part, model=zaxis_motor, thickness=zmotor_mount_thickness_h);
    }
    else if(part=="neg")
    {
        // cutout for motor cables
        translate([0,0,-30*mm])
        cubea([zmotor_mount_thickness*3, 20*mm, zmotor_h], align=-Z);

        // screw holes top
        for(y=[-1,1])
        tx(zmotor_mount_thickness)
        ty(y*(zmotor_w/2+zmotor_mount_thread_dia*3))
        tz(-extrusion_size)
        screw_cut(nut=extrusion_nut, head="button", h=12*mm, orient=-X, align=-X);

        // screw hole bottom
        for(y=[0])
        tx(zmotor_mount_thickness)
        ty(y*(zmotor_w/2+zmotor_mount_thread_dia*3))
        tz(-extrusion_size-main_lower_dist_z)
        screw_cut(nut=extrusion_nut, head="button", h=12*mm, orient=-X, align=-X);

        // cut out z rod
        tx(zmotor_mount_rod_offset_x)
        cylindera(d=zaxis_rod_d*rod_fit_tolerance, h=100, orient=Z);
    }
    else if(part=="vit")
    {
        attach([[get(NemaSideSize,zaxis_motor)/2,0,0],N],zmotor_mount_conn_motor)
        motor_mount(part=part, model=zaxis_motor, thickness=zmotor_mount_thickness_h);
    }
}

module part_z_motor_mount()
{
    rotate([0,-90,0])
    zaxis_motor_mount();
}


The include paths were corrected.

The include paths were corrected.

use <../../../../../../basics/rounded-edges/rounded-cube-enclosure/rounded-cube-enclosure.scad>

use <../../../../../../microcontrollers/adafruit/trinket-mini/mounting-standoffs/trinket-mini-mounting-standoffs.scad>

use <../../../../../../electronics/keyboards/switch-mounting-holes/keyboard-switch-mounting-holes.scad>

trinketMiniShortcutKeyboard();

module frameWithTrinketMounts(boardLengthZ, cornerRadius)
{
	union()
	{
		boardLengthX = 60;
		boardLengthY = 60;

		roundedCubeEnclosure(boardLengthX = boardLengthX,
							boardLengthY = boardLengthY,
							boardLengthZ = boardLengthZ,
							cornerRadius = cornerRadius,
							xAxisCutout_yPercentage = 0.8,
							xAxisCutout_zPercentage = 0.8,
							yAxisCutout_xPercentage = 0.85,
							yAxisCutout_zPercentage = 0.75);

		xTranslate = (boardLengthX + cornerRadius) * 0.6;
		yTranslate = (boardLengthY + cornerRadius) * 0.3;
		zTranslate = 2;

		color("red")
		translate([xTranslate, yTranslate, zTranslate])
		trinketMiniStandoffs();
	}
}

module trinketMiniShortcutKeyboard()
{
	boardLengthZ = 30;
	buttonSide = 12;
	cornerRadius = 3;

	difference()
	{
		frameWithTrinketMounts(boardLengthZ, cornerRadius);

		xTranslate = -12;
		yTranslate = 1;
		zTranslate = boardLengthZ * 0.8;
		translate([xTranslate, yTranslate, zTranslate])
		keyboardSwitchMountingHoles(buttonCount = 4,
					 buttonSide = buttonSide,
				 	 panelHeight = 5);

		 panelCutout_xLength = buttonSide + 4;
		 panelCutout_yLength = (panelCutout_xLength * 4) - 5;
		 panelCutout_zLength = 10;
		 panelCutout_xTranslate = 2;
		 panelCutout_yTranslate = 0;
		 panelCutout_zTranslate = (boardLengthZ + cornerRadius) - panelCutout_zLength - 1;  // the minus 1 is for the panel mount height
		 color("pink")
		 translate([panelCutout_xTranslate, panelCutout_yTranslate, panelCutout_zTranslate])
		 cube([panelCutout_xLength, panelCutout_yLength, panelCutout_zLength]);
	}
}

use <../../../../../basics/rounded-edges/rounded-cube-enclosure/rounded-cube-enclosure.scad>

use <../../../../../microcontrollers/adafruit/trinket-mini/mounting-standoffs/trinket-mini-mounting-standoffs.scad>

use <../../../../../electronics/keyboards/switch-mounting-holes/keyboard-switch-mounting-holes.scad>

trinketMiniShortcutKeyboard();

module frameWithTrinketMounts(boardLengthZ, cornerRadius)
{
	union()
	{
		boardLengthX = 60;
		boardLengthY = 60;

		roundedCubeEnclosure(boardLengthX = boardLengthX,
							boardLengthY = boardLengthY,
							boardLengthZ = boardLengthZ,
							cornerRadius = cornerRadius,
							xAxisCutout_yPercentage = 0.8,
							xAxisCutout_zPercentage = 0.8,
							yAxisCutout_xPercentage = 0.85,
							yAxisCutout_zPercentage = 0.75);

		xTranslate = (boardLengthX + cornerRadius) * 0.6;
		yTranslate = (boardLengthY + cornerRadius) * 0.3;
		zTranslate = 2;

		color("red")
		translate([xTranslate, yTranslate, zTranslate])
		trinketMiniStandoffs();
	}
}

module trinketMiniShortcutKeyboard()
{
	boardLengthZ = 30;
	buttonSide = 12;
	cornerRadius = 3;

	difference()
	{
		frameWithTrinketMounts(boardLengthZ, cornerRadius);

		xTranslate = -12;
		yTranslate = 1;
		zTranslate = boardLengthZ * 0.8;
		translate([xTranslate, yTranslate, zTranslate])
		keyboardSwitchMountingHoles(buttonCount = 4,
					 buttonSide = buttonSide,
				 	 panelHeight = 5);

		 panelCutout_xLength = buttonSide + 4;
		 panelCutout_yLength = (panelCutout_xLength * 4) - 5;
		 panelCutout_zLength = 10;
		 panelCutout_xTranslate = 2;
		 panelCutout_yTranslate = 0;
		 panelCutout_zTranslate = (boardLengthZ + cornerRadius) - panelCutout_zLength - 1;  // the minus 1 is for the panel mount height
		 color("pink")
		 translate([panelCutout_xTranslate, panelCutout_yTranslate, panelCutout_zTranslate])
		 cube([panelCutout_xLength, panelCutout_yLength, panelCutout_zLength]);
	}
}