x/extruder: wip, fixes after first print

use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/transforms.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/triangles.scad>
use <thing_libutils/linear-extrusion.scad>;
use <thing_libutils/bearing.scad>
use <thing_libutils/metric-screw.scad>

include <config.scad>

xaxis_carriage_bearing_distance = 8;
xaxis_carriage_padding = 2;
xaxis_carriage_mount_distance = 23;
xaxis_carriage_mount_offset_z = 0;
xaxis_carriage_teeth_height=xaxis_belt_width*1.5;
xaxis_carriage_mount_screws = ThreadM4;

xaxis_carriage_conn = [[0, -xaxis_bearing[1]/2 - xaxis_carriage_bearing_offset_y,0], [0,0,0]];

xaxis_carriage_beltfasten_w = 20;

hobbed_gear_d_outer = 12.65;
hobbed_gear_d_inner = 11.5;
hobbed_gear_h = 11;

extruder_gear_small_d_inner = 5.75*mm;
extruder_gear_big_d_inner = 29.35*mm;
extruder_gear_big_d_outer = 30.85*mm;
extruder_gear_big_h = [3.85*mm, 5*mm];

// 13t metal gear and 60t metal gear
extruder_gears_distance=extruder_gear_big_d_inner/2+extruder_gear_small_d_inner/2+.5*mm;

extruder_motor = dict_replace_multiple(Nema17,
        [
        [NemaLengthMedium, 11.75*mm],
        [NemaFrontAxleLength, 5*mm],
        ]);

// shaft from big gear to hobbed gear
extruder_shaft_d = 5*mm;

// dist between gear and motor
extruder_gear_motor_dist = .5*mm;
extruder_motor_angle = -80;
extruder_motor_offset_x = cos(extruder_motor_angle) * extruder_gears_distance;
extruder_motor_offset_z = sin(extruder_motor_angle) * extruder_gears_distance;
extruder_motor_holedist = lookup(NemaDistanceBetweenMountingHoles, extruder_motor);

extruder_gear_big_offset=[-extruder_motor_offset_x,0,extruder_motor_offset_z];

extruder_offset = [-2,0,10*mm];
extruder_offset_a = -extruder_gear_big_offset+[
    0,
    xaxis_bearing[1] + xaxis_carriage_bearing_offset_y + .2*mm,
    0];
extruder_filapath_offset = [hobbed_gear_d_inner/2, -12*mm, 0];

guidler_bearing = bearing_MR105;
extruder_hotmount_clamp_nut = MHexNutM3;
extruder_hotmount_clamp_thread = ThreadM3;

module x_carriage(mode=undef)
{
    bottom_width = xaxis_bearing[2] + 2*xaxis_carriage_padding;
    top_width = xaxis_bearing[2]*2 + xaxis_carriage_bearing_distance + 2*xaxis_carriage_padding;
    thickness = xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y;

    if(mode==undef)
    {
        difference()
        {
            x_carriage(mode="pos");
            x_carriage(mode="neg");
        }
    }
    else
    if(mode=="pos")
    {
        hull()
        {
            // top bearings
            translate([0,0,xaxis_rod_distance/2])
                rcubea([top_width, thickness, xaxis_bearing[1]+xaxis_carriage_padding+ziptie_bearing_distance*2], align=[0,1,0]);

            /*rcubea([top_width,thickness,xaxis_rod_distance/2], align=[0,1,0]);*/

            // bottom bearing
            translate([0,0,-xaxis_rod_distance/2])
                rcubea([bottom_width, thickness, xaxis_bearing[1]+xaxis_carriage_padding+ziptie_bearing_distance*2], align=[0,1,0]);

        }
        translate([0,xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y+xaxis_carriage_beltpath_offset+.1,0])
        {
            translate([0,-xaxis_beltpath_width/2,0])
                for(x=[-1,1])
                    translate([x*(xaxis_carriage_beltfasten_w/2+5),-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])
                        rcubea([xaxis_carriage_beltfasten_w,xaxis_beltpath_width,xaxis_beltpath_height/3], align=[0,0,-1]);
        }
    }
    else if(mode=="neg")
    {
        for(i=[-1,1])
        translate([
                i*(xaxis_bearing[2]/2+xaxis_carriage_bearing_distance/2),
                xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y,
                xaxis_rod_distance/2
        ])
        {
            bearing_mount_holes(xaxis_bearing, orient=[1,0,0]);
            cubea([xaxis_bearing[2]*2,xaxis_bearing[1]/2+10,xaxis_bearing[1]+1*mm], align=[0,1,0]);
        }

        translate([
                0,
                xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y,
                -xaxis_rod_distance/2])
        {
            bearing_mount_holes(xaxis_bearing, orient=[1,0,0]);
            cubea([xaxis_bearing[2]*2,xaxis_bearing[1]/2+10,xaxis_bearing[1]+1*mm], align=[0,1,0]);
        }

        // Extruder mounting holes
        /*translate([0,0,xaxis_carriage_mount_offset_z])*/
        /*for(j=[-1,1])*/
        /*for(i=[-1,1])*/
        /*{*/
            /*translate([i*xaxis_carriage_mount_distance/2,0,j*xaxis_carriage_mount_distance/2])*/
            /*{*/
                /*screw_dia = lookup(ThreadSize, xaxis_carriage_mount_screws);*/
                /*cylindera(d=screw_dia, h=100, orient=[0,1,0]);*/
            /*}*/
        /*}*/

        translate([0,xaxis_carriage_beltpath_offset+.1,0])
        {
            // Cut clearing space for the belt
            /*translate([0,-xaxis_beltpath_width/2,-xaxis_beltpath_height/2])*/
                /*#rcubea([500,xaxis_beltpath_width+1,5], align=[0,1,0], extrasize=[0,0,4], extrasize_align=[0,0,1]);*/

            translate([0,-xaxis_beltpath_width/2,0])
            {
                difference()
                {
                    rcubea([500,xaxis_beltpath_width*2,xaxis_beltpath_height], align=[0,1,0]);
                    for(x=[-1,1])
                    translate([x*(xaxis_carriage_beltfasten_w/2+5),-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])
                        rcubea([xaxis_carriage_beltfasten_w,xaxis_beltpath_width*2,xaxis_beltpath_height/3], align=[0,1,-1]);
                }
            }

            /*belt_thickness=1.5;*/
            /*for(i=[-1,1])*/
                /*translate([i*30,0,0])*/
                    /*rcubea([15,xaxis_beltpath_width,15-belt_thickness], align=[0,0,0]);*/

            // Cut in the middle for belt
            /*rcubea([7,xaxis_beltpath_width,xaxis_beltpath_height], align=[0,0,0]);*/

            /*translate([0,-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])*/
            /*{*/
                /*// Belt slit*/
                /*rcubea([500,xaxis_beltpath_width,belt_thickness], align=[0,1,0]);*/

                /*[>// Teeth cuts<]*/
                /*[>teeth = 50;<]*/
                /*[>teeth_height = 2;<]*/
                /*[>translate([-belt_tooth_distance/2*teeth-.5,0,0])<]*/
                /*[>for(i=[0:teeth])<]*/
                /*[>{<]*/
                    /*[>translate([i*belt_tooth_distance,0,0])<]*/
                        /*[>cubea([belt_tooth_distance*belt_tooth_ratio,xaxis_carriage_teeth_height,teeth_height], align=[0,0,-1]);<]*/
                /*[>}<]*/
            /*}*/
        }
    }
    else if(mode=="vit")
    {
        for(x=[-1,1])
        translate([
                x*(xaxis_carriage_bearing_distance+xaxis_bearing[2])/2,
                xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y,
                xaxis_rod_distance/2
        ])
            bearing(xaxis_bearing, orient=[1,0,0]);

        translate([
                0,
                xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y,
                -xaxis_rod_distance/2
        ])
            bearing(xaxis_bearing, orient=[1,0,0]);

        /*translate([0,xaxis_carriage_beltpath_offset,0])*/
        /*for(i=[-1,1])*/
        /*translate([i*100,0,0])*/
        /*pulley(xaxis_idler_pulley, orient=[0,1,0]);*/
    }
}

module extruder_gear_small()
{
    difference()
    {
        union()
        {
            hull()
            {
                cylindera(d=extruder_gear_small_d_inner, h=7*mm, orient=[0,1,0], align=[0,1,0]);
                cylindera(d=10*mm, h= 3*mm, orient=[0,1,0], align=[0,1,0]);
            }
            cylindera(d=extruder_gear_small_d_inner, h=13*mm, orient=[0,1,0], align=[0,1,0]);
        }
        cylindera(d=5*mm, h=13*mm+.1, orient=[0,1,0], align=[0,1,0]);
    }
}

module extruder_gear_big(align=[0,0,0], orient=[0,0,1])
{
    total_h = extruder_gear_big_h[0]+extruder_gear_big_h[1];
    size_align([extruder_gear_big_d_inner, extruder_gear_big_d_inner, total_h], align=align, orient=orient)
    translate([0,0,-extruder_gear_big_h[0] + total_h/2])
    difference()
    {
        union()
        {
            cylindera(d=extruder_gear_big_d_inner, h=extruder_gear_big_h[0], orient=[0,0,1], align=[0,0,1]);
            cylindera(d=12*mm, h=extruder_gear_big_h[1], orient=[0,0,1], align=[0,0,-1]);
        }
        translate([0,0,-.5])
        cylindera(d=5*mm, h=total_h+.2, orient=[0,0,1], align=[0,0,0]);
    }
}

module motor_mount_cut(motor=Nema17, h=10*mm)
{
    screw_dist = lookup(NemaDistanceBetweenMountingHoles, motor);

    // round dia
    translate([0, .1, 0])
    cylindera(d=1.1*lookup(NemaRoundExtrusionDiameter, motor), h=h, orient=[0,1,0], align=[0,1,0]);

    // motor axle
    translate([0, .1, 0])
    cylindera(d=1.2*lookup(NemaAxleDiameter, motor), h=lookup(NemaFrontAxleLength, motor)+2*mm, orient=[0,1,0], align=[0,1,0]);

    // bearing for offloading force on motor shaft
    /*translate([0, -1*mm-xaxis_pulley[1]-.1, 0])*/
    scale(1.03)
    bearing(bearing_MR105, override_h=h, orient=[0,1,0], align=[0,-1,0]);

    motor_thread=ThreadM3;
    motor_nut=MHexNutM3;
    for(x=[-1,1])
    for(z=[-1,1])
    translate([x*screw_dist/2, -h, z*screw_dist/2])
    {
        if(x!=-1 || z!=-1)
        screw_cut(motor_nut, h=h, with_nut=false, orient=[0,1,0], align=[0,1,0]);
    }
}
extruder_a_h = 14*mm;

module extruder_a(show_vitamins=false)
{
    difference()
    {
        hull()
        /*union()*/
        {
            side = 15*mm;
            rcubea([extruder_motor_holedist+side/2+5*mm,extruder_a_h,extruder_motor_holedist+side/2], align=[0,1,0]);
            /*hull()*/
            /*{*/
                /*for(x=[-1,1])*/
                /*for(z=[-1,1])*/
                /*translate([(extruder_motor_holedist/2)*x,0,(extruder_motor_holedist/2)*z])*/
                /*rotate([0,x*45,0])*/
                /*rcubea([side/2,extruder_a_h,side/2], align=[0,1,0]);*/
            /*}*/
            translate(extruder_gear_big_offset)
            cylindera(d=extruder_gear_big_d_outer+6*mm, h=extruder_a_h, orient=[0,1,0], align=[0,-1,0], round_radius=2);
        }

        translate([0,extruder_a_h,0])
        {
            translate(extruder_gear_big_offset)
            {
                /*scale([1.3,2.0,1.3])*/
                /*#extruder_gear_big(orient=[0,-1,0], align=[0,-1,0]);*/

                // big gear cutout
                translate([0,-bearing_MR105[2]+.1,0])
                cylindera(d=extruder_gear_big_d_outer+1*mm, h=extruder_a_h+.2, orient=[0,1,0], align=[0,1,0]);

                translate([0,.1,0])
                cylindera(d=extruder_shaft_d+.5*mm, h=extruder_a_h+.2, orient=[0,1,0], align=[0,1,0]);

                translate([0,.1,0])
                scale(1.03)
                bearing(bearing_MR105, override_h=6*mm, orient=[0,1,0], align=[0,-1,0]);
            }

            motor_mount_cut(extruder_motor, h=extruder_a_h+1);
        }

    }

    if(show_vitamins)
    translate([0,extruder_a_h,0])
    {
        translate([0,-extruder_gear_motor_dist,0])
        {
            extruder_gear_small();

            // big gear
            translate(extruder_gear_big_offset)
            {
                translate([0,1,0])
                translate([0,-bearing_MR105[2]+.1,0])
                extruder_gear_big(orient=[0,-1,0], align=[0,-1,0]);

                translate([0,1,0])
                bearing(bearing_MR105, orient=[0,1,0], align=[0,-1,0]);

                translate([0,bearing_MR105[2],0])
                {
                    cylindera(h=60*mm, d=extruder_shaft_d, orient=[0,1,0], align=[0,1,0]);
                }
            }
        }
        motor(extruder_motor, NemaMedium, dualAxis=false, orientation=[-90,0,0]);
    }
}

// from E3D V6 heatsink drawing
// http://wiki.e3d-online.com/wiki/File:DRAWING-V6-175-SINK.png
// each entry == dia + h
hotmount_d_h=[[16*mm,3.7*mm],[12*mm,6*mm],[16*mm,3*mm]];
hotmount_outer_size_xy=max(vec_i(hotmount_d_h,0))+5*mm;
hotmount_outer_size_h=max(vec_i(hotmount_d_h,1))+5*mm;
hotmount_offset_h=-3*mm;

// which side does hotend slide in (x-axis, i.e. -1 is left, 1 is right)
hotmount_tolerance=1.05*mm;

// hotmount clamp screws distance from center
hotmount_clamp_thread = ThreadM3;
hotmount_clamp_nut = MHexNutM3;

hotmount_clamp_screw_dia = lookup(ThreadSize, hotmount_clamp_thread);
hotmount_clamp_screws_dist = hotmount_d_h[1][1] + 1.2*hotmount_clamp_screw_dia;
hotmount_clamp_pad = 0;
hotmount_clamp_thickness = 5*mm;
hotmount_clamp_y = 2*(hotmount_clamp_screws_dist + hotmount_clamp_screw_dia + hotmount_clamp_pad);
hotmount_clamp_height = hotmount_d_h[1][1];

module hotmount_cutout(extend_cut=false)
{
    // cutout of j-head/e3d heatsink mount
    heights=vec_i(hotmount_d_h,1);
    for(e=v_itrlen(hotmount_d_h))
    {
        hs=v_sum(heights,e-1);
        translate([0,0,-hs])
        {
            d=hotmount_d_h[e][0]*hotmount_tolerance;
            h=hotmount_d_h[e][1]*hotmount_tolerance;
            cylindera(d=d,h=h,align=[0,0,-1]);
            if(extend_cut)
            {
                cubea([extruder_b_w/2+1,d,h],align=[1,0,-1]);
            }
        }
    }
}

module hotmount_clamp()
{
    difference()
    {
        union()
        {
            translate([extruder_b_w/2, 0, 0]);
            {
                rcubea([hotmount_clamp_thickness, hotmount_clamp_y, hotmount_clamp_height], align=[-1,0,0]);
            }

            difference()
            {
                translate([extruder_b_w/2 * 1, 0, 0]);
                {
                    rcubea([extruder_b_w/2, hotmount_d_h[1][0], hotmount_clamp_height], align=[-1,0,0]);
                }

                translate([(-extruder_b_w/2 * 1) + (-0.5*1), 0, hotmount_d_h[0][1]+hotmount_d_h[1][1]/2])
                {
                    hotmount_cutout(extend_cut = false);
                }
            }

        }

        // clamp mount screw holes
        for(i=[-1,1])
        {
            translate([.1, i*hotmount_clamp_screws_dist, 0])
                rotate([0,90,0])
                cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread), h=hotmount_clamp_thickness+.2, align=[0,0,-1], extra_h=2, round_radius=2);
        }
    }
}

extruder_b_bearing = bearing_MR105;
extruder_b_w = hobbed_gear_d_outer+15*mm;

guidler_mount_off = [0,-guidler_bearing[1]/1.8, -guidler_bearing[1]/1.7];
extruder_guidler_mount_off = [.5*mm -guidler_mount_off[1]+hobbed_gear_d_inner/2+guidler_bearing[1]/2,0,guidler_mount_off[2]];

module extruder_b(part=undef)
{
    extruder_b_mount_thick = 5*mm;
    if(part==undef)
    {
        difference()
        {
            extruder_b(part="pos");
            extruder_b(part="neg");
        }
    }
    else if(part=="pos")
    {
        // mount onto carriage
        translate([extruder_filapath_offset[0],0,-15*mm])
        {
            hull()
            for(x=[-1,1])
            translate([x*(extruder_b_w/2+4*mm),0,0])
            cylindera(d=10*mm, h=extruder_b_mount_thick, orient=[0,1,0], align=[0,1,0], round_radius=2);
        }

        hull()
        /*union()*/
        {
            // main house
            extruder_b_size=[
                hobbed_gear_d_outer+5*mm,
                abs(extruder_filapath_offset[1])+hobbed_gear_h/2+extruder_b_bearing[2]+4*mm,
                hobbed_gear_d_outer+5*mm
            ];
            /*translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])*/
            /*translate([hobbed_gear_d_inner/2,0,0])*/
            /*rcubea(extruder_b_size, align=[0,sign(extruder_filapath_offset[1]),0]);*/

            // gear support
            translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
            translate([0,-hobbed_gear_h/2,0])
            {
                // hobbed gear support
                cylindera(d=hobbed_gear_d_outer+5*mm, h=abs(extruder_filapath_offset[1])+hobbed_gear_h/2, align=[0,-1,0], orient=[0,1,0], round_radius=2);

                // bearing support
                cylindera(d=extruder_b_bearing[1]+5*mm, h=extruder_b_bearing[2]+3*mm, align=[0,1,0], orient=[0,1,0], round_radius=2);
            }

            // guidler screw nuts support
            translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
            translate([0, guidler_screws_mount_d_offset, house_guidler_screw_h_offset])
            {
                for(i=[-1,1])
                translate([0,i*(guidler_screws_distance),  0])
                cylindera(d=house_guidler_screw_h, d=guidler_screws_mount_d, orient=[1,0,0], round_radius=2);
            }

            // guidler mount
            translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
            translate(extruder_guidler_mount_off)
            {
                cylindera(d=guidler_mount_d, h=guidler_mount_w, orient=[0,1,0]);
            }

            // hotmount support
            translate(extruder_filapath_offset)
            translate([0,0,-hobbed_gear_d_outer/2 + hotmount_offset_h])
            {
                rcubea([extruder_b_w, hotmount_outer_size_xy, hotmount_outer_size_h], align=[0,0,-1]);

                translate([0,-extruder_filapath_offset[1],0])
                    rcubea([extruder_b_w, abs(extruder_filapath_offset[1]), hotmount_outer_size_h], align=[0,-1,-1]);
            }

            /*// clamp mount screw holes*/
            /*translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])*/
            /*translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h])*/
            /*for(i=[-1,1])*/
            /*{*/
            /*translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])*/
            /*cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread)+6*mm, h=extruder_b_w, orient=[1,0,0]);*/
            /*}*/
        }
    }
    else if(part=="neg")
    {
        // mount onto carriage
        translate([extruder_filapath_offset[0],0,-15*mm])
        {
            for(x=[-1,1])
            translate([x*(extruder_b_w/2+4*mm),0,0])
            translate([0, -extruder_b_mount_thick, 0])
            screw_cut(nut=MHexNutM3, h=extruder_b_mount_thick, head_embed=true, nut_offset=-10, orient=[0,1,0], align=[0,1,0]);
        }

        // guidler cutout
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        {
            guidler_w_cut = guidler_w+2*mm;
            guidler_w_cut_ext = 1000;
            difference()
            {
                union()
                {
                    hull()
                    {
                        translate([hobbed_gear_d_inner/2,0,0])
                        {
                            cubea([guidler_bearing[1]+1*mm,guidler_w_cut,guidler_bearing[1]*2], align=[1,0,1]);
                            cylindera(d=guidler_bearing[1]+1*mm, h=guidler_w_cut, orient=[0,1,0], align=[1,0,0]);
                        }

                        translate(extruder_guidler_mount_off)
                        {
                            for(y=[-1,1])
                            translate([0,y*guidler_mount_w/2,0])
                            {
                                cylindera(d=guidler_mount_d, h=guidler_mount_w, orient=[0,1,0], align=[0,-y,0]);
                                translate([0,0,-guidler_mount_d/2])
                                    cubea([10,(guidler_w-guidler_mount_w)/2+1*mm,10], align=[1,y,1]);
                            }
                        }
                    }
                    translate(extruder_guidler_mount_off)
                    {
                        cylindera(d=guidler_mount_d+2*mm, h=(guidler_w)+1*mm, orient=[0,1,0], align=[0,0,0]);
                        hull()
                        {
                            cylindera(d=guidler_screws_thread_dia+2*mm, h=guidler_w_cut_ext, orient=[0,1,0], align=[0,0,0]);
                            translate([0,0,-(guidler_screws_thread_dia+0*mm)])
                            cubea([10,guidler_w_cut_ext,100], align=[1,0,1]);
                        }
                    }
                }
                // dont cut away the guilder mount
                translate(extruder_guidler_mount_off)
                {
                    cylindera(d=guidler_mount_d, h=guidler_mount_w, orient=[0,1,0]);
                    cubea([guidler_mount_d, guidler_mount_w, 10], align=[0,0,-1]);
                }
            }
        }

        // guidler screws cutouts
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        for(y=[-1,1])
        translate([guidler_screws_mount_d_offset, y*(guidler_screws_distance), house_guidler_screw_h_offset])
        {
            r= guidler_screws_thread_dia/2 * 1.1;
            cubea([1000, r*2, r]);

            for(v=[-1,1])
                translate([0,0, v*r/2])
                    cylindera(r=r,h=1000, orient=[1,0,0]);

            // guidler screw nuts drop-in slots
            translate([0,0, -r*2])
                cubea([nut_m3[2]*1.25,nut_m3[1]*1.1,house_guidler_screw_h], align=[0,0,1], extrasize=[0,0,1], extrasize_align=[0,0,1]);
        }

        // guidler mount screw
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        translate(extruder_guidler_mount_off)
        {
            cylindera(d=lookup(ThreadSize, guidler_screws_thread), h=guidler_mount_w+.1, orient=[0,1,0]);
        }

        // cutout for hobbed gear (inner)
        cylindera(h=abs(extruder_filapath_offset[1])+hobbed_gear_h/2+1*mm, d=hobbed_gear_d_outer+2*mm, orient=[0,1,0], align=[0,1,0]);

        // cutout for bearing
        cylindera(h=abs(extruder_filapath_offset[1])+hobbed_gear_h/2+extruder_b_bearing[2]+1*mm, d=extruder_b_bearing[1]+.1*mm, orient=[0,1,0], align=[0,1,0]);

        // hotmount clamp screws
        translate([hobbed_gear_d_inner/2, 0,-hobbed_gear_d_outer/2 + hotmount_offset_h])
        for(i=[-1,1])
        {
            translate([i*hotmount_clamp_screws_dist, 0, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
                screw_cut(nut=extruder_hotmount_clamp_nut, h=1000, head_embed=false, orient=[0,1,0], align=[0,-1,0]);
        }

        // filament path
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        translate([hobbed_gear_d_outer/2,0,0])
        cylindera(h=1000, d=4*mm, orient=[0,0,1], align=[0,0,0]);

        // gear cutout
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        translate([0,-hobbed_gear_h/2-.5*mm,0])
        cylindera(d=extruder_b_bearing[1]+.3*mm, h=extruder_b_bearing[2]+.5*mm, align=[0,1,0], orient=[0,1,0]);

        // extruder shaft
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        translate([0,-extruder_filapath_offset[1]+.1,0])
        cylindera(h=1000, d=extruder_shaft_d, orient=[0,1,0], align=[0,1,0]);

        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h+.01])
        rotate([0,0,-90])
        {
            hotmount_cutout(extend_cut=true);

            // clamp mount screw holes
            for(i=[-1,1])
            {
                translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
                    cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread), h=extruder_b_w+1, orient=[1,0,0]);
            }

            // hotmount clamp cutout
            translate([extruder_b_w/2, 0, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
            {
                rcubea([hotmount_clamp_thickness+1.2, hotmount_clamp_y+0.2, hotmount_clamp_height+0.2], align=[-1,0,0], extrasize=[100,0,0], extrasize_align=[1,0,0]);
            }
        }
    }
    else if(part=="vit")
    {
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        {
            translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h+.01])
            translate([0, -extruder_b_w/2 * (1), -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
            rotate([0,0,-90])
            hotmount_clamp();

            translate([0,-hobbed_gear_h/2-extruder_b_bearing[2]-.5*mm,0])
            {
                cylindera(h=extruder_a_h+extruder_offset_a[1]-extruder_filapath_offset[1], d=extruder_shaft_d, orient=[0,1,0], align=[0,-1,0]);

                bearing(extruder_b_bearing, orient=[0,1,0], align=[0,1,0]);
            }

            // hobbed gear
            cylindera(h=hobbed_gear_h, d=hobbed_gear_d_inner, orient=[0,1,0], align=[0,0,0]);
            for(y=[-1,1])
            translate([0,y*hobbed_gear_h/2,0])
            {
                cylindera(h=hobbed_gear_h/3, d=hobbed_gear_d_outer, orient=[0,1,0], align=[0,y,0]);
            }
        }
    }
}

// Final part
module x_carriage_withmounts(show_vitamins=true)
{
    difference()
    {
        /*hull()*/
        union()
        {
            x_carriage(mode="pos");

            // extruder A mount
            translate(extruder_offset)
            translate(extruder_offset_a)
            {
                for(x=[-1,1])
                for(z=[-1,1])
                translate([x*extruder_motor_holedist/2,0,z*extruder_motor_holedist/2])
                cylindera(d=10*mm, h=extruder_offset_a[1], orient=[0,1,0], align=[0,1,0], round_radius=2);
            }
        }

        x_carriage(mode="neg");

        // rod between extruder part A and B
        translate(extruder_offset)
        {
            cylindera(h=100*mm, d=extruder_shaft_d+2*mm, orient=[0,1,0], align=[0,0,0]);
        }

        // extruder A mount cutout
        translate(extruder_offset)
        translate(extruder_offset_a)
        {
            for(x=[-1,1])
            for(z=[-1,1])
            translate([x*extruder_motor_holedist/2,0,z*extruder_motor_holedist/2])
            translate([0,.1,0])
            cylindera(d=3*mm, h=extruder_offset_a[1]+.2, orient=[0,1,0], align=[0,1,0]);
        }

        // extruder B mount cutout
        translate(extruder_offset)
        /*translate(extruder_offset_b)*/
        translate([extruder_filapath_offset[0],0,-15*mm])
        {
            for(x=[-1,1])
            translate([x*(extruder_b_w/2+4*mm),0,0])
            screw_cut(nut=MHexNutM3, h=5, head_embed=false, orient=[0,1,0], align=[0,1,0]);
        }
    }

    if(show_vitamins)
    {
        x_carriage(mode="vit");
    }
}

/*translate([0,-42,38])*/
/*rotate([0,0,90])*/
/*translate([0,-1,-42])*/
/*translate([-83,25,-42])*/
/*rotate([90,0,0])*/
/*import("stl/i3R_Compact_E3Dv6_Extruder_1.75_01.STL");*/

module x_extruder_hotend()
{
    hotend_conn =[[0,0,27.8-hotmount_offset_h],[0,0,1]];
    translate(extruder_filapath_offset)
    attach(extruder_conn_hotend, hotend_conn)
        rotate([90,0,90])
        %import("stl/E3D_V6_1.75mm_Universal_HotEnd_Mockup.stl");

}

house_w = 20;
house_h = 30;

// length of the guidler bearing bolt/screw

guidler_mount_w=guidler_bearing[2];
guidler_mount_d=6*mm;
guidler_bolt_h=guidler_bearing[2]+4*mm;

guidler_w=max(guidler_mount_w+7, guidler_bearing[2]*2.8);
guidler_d=5;
guidler_h=7;
guidler_extra_h_up=guidler_bearing[1]/2+hotmount_clamp_screw_dia/2;

guidler_screws_thread = ThreadM3;
guidler_screws_thread_dia= lookup(ThreadSize, guidler_screws_thread);
guidler_screws_distance=4*mm;
guidler_screws_mount_d = guidler_screws_thread_dia*3;
guidler_screws_mount_d_offset = 0*mm;

guidler_srew_distance = 10;

house_guidler_screw_h = guidler_screws_thread_dia+8*mm;
house_guidler_screw_h_offset = house_h/2 + guidler_screws_thread_dia -7*mm;

module extruder_guidler()
{
    // everything inside this module is relative to the center of the
    // bearing (that clamps the filament)
    difference()
    {
        union()
        {

            hull()
            {
                // guidler main block
                translate([0,guidler_mount_off[1]-guidler_mount_d/2, 0])
                cubea([guidler_w, guidler_d, guidler_h], align=[0,1,0]);

                // guidler bearing bolt holder
                cylindera(d=guidler_bearing[0]*1.5,h=guidler_w, orient=[1,0,0]);
            }

            hull()
            {
                // guidler main block
                translate([0,guidler_mount_off[1]-guidler_mount_d/2, 0])
                cubea([guidler_w, guidler_d, guidler_h], align=[0,1,0], extrasize=[0,0,guidler_extra_h_up], extrasize_align=[0,0,1]);

                // guidler mount point
                translate([0,guidler_mount_off[1], guidler_mount_off[2]])
                cylindera(d=guidler_mount_d,h=guidler_w, orient=[1,0,0]);
            }

            hull()
            {
                // guidler main block
                translate([0,guidler_mount_off[1]-guidler_mount_d/2, guidler_h])
                cubea([guidler_w, guidler_d, 1], align=[0,1,0]);

                // guidler screws mount
                for(i=[-1,1])
                translate([i*(guidler_screws_distance),guidler_mount_off[1]-guidler_mount_d/2, house_guidler_screw_h_offset])
                cylindera(r=guidler_screws_thread_dia/2*3,h=guidler_d, align=[0,-1,0], orient=[0,1,0]);

            }
        }

        // cutouts for clamping screws
        for(i=[-1,1])
        translate([i*(guidler_screws_distance),guidler_mount_off[1]-guidler_mount_d/2, house_guidler_screw_h_offset])
        {
            r= guidler_screws_thread_dia/2*1.1;
            cubea([r*2,house_w+.1,r]);
            for(v=[-1,1])
            translate([0, -0.1, v*r/2])
            {
                cylindera(r=r,h=house_w+1, align=[0,-1,0], orient=[0,1,0]);
            }
        }

        // port hole to see bearing
        translate([0,-guidler_bearing[1]/2,0])
        cubea([guidler_bearing[0]*1.1, 100, guidler_bearing[1]/2], align=[0,0,1]);

        // cutout middle mount point pivot
        translate([0,guidler_mount_off[1], guidler_mount_off[2]])
        cylindera(d=guidler_mount_d*1.25,h=guidler_mount_w*1.1, orient=[1,0,0]);

        // mount bolt hole
        translate([0,guidler_mount_off[1], guidler_mount_off[2]])
        cylindera(d=lookup(ThreadSize, guidler_screws_thread),h=100, orient=[1,0,0]);

        // guidler bearing bolt holder cutout
        union()
        {
            cubea([guidler_bolt_h*1.05+2*e,guidler_bearing[0]*1.05,guidler_bearing[0]*1.05],align=[0,1,0]);

            cylindera(d=guidler_bearing[0]*1.05, h=guidler_bolt_h*1.05, orient=[1,0,0]);
        }

        // guidler bearing cutout
        cylindera(d=guidler_bearing[1]*1.1, h=guidler_bearing[2]*1.1, orient=[1,0,0]);

    }

    %if(show_extras)
    {
        cylindera(d=guidler_bearing[1], h=guidler_bearing[2], orient=[1,0,0]);
        cylindera(d=guidler_bearing[0], h=guidler_bolt_h, orient=[1,0,0]);
    }
}

// extruder guidler mount point
extruder_conn_guidler = [ extruder_guidler_mount_off, [0,1,0]];

// guidler connection point
extruder_guidler_conn_mount = [ guidler_mount_off,  [1,0,0]];
extruder_guidler_roll = 45;

if(false)
attach(extruder_conn_guidler, extruder_guidler_conn_mount, extruder_guidler_roll)
{
    extruder_guidler(show_extras=true);
}

/*if(false)*/
{
    x_carriage_withmounts();

    translate(extruder_offset)
    {
        translate(extruder_offset_a)
        extruder_a(show_vitamins=true);

        difference()
        {
            extruder_b(part="pos");

            extruder_b(part="neg");
        }
        extruder_b(part="vit");

        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        attach(extruder_conn_guidler, extruder_guidler_conn_mount, extruder_guidler_roll)
        {
            %extruder_guidler(show_extras=true);
        }

        %x_extruder_hotend();
    }
    //filament path
    %translate(extruder_filapath_offset)
        cylindera(h=1000, d=1.75*mm, orient=[0,0,1], align=[0,0,0]);
}

if(false)
{
    rotate([90,0,0])
    x_carriage(show_bearings=false);

    /*rotate([-90,0,0])*/
    /*extruder_a();*/

    /*rotate([-90,0,0])*/
    /*extruder_b();*/

    guidler_conn_layflat = [ [0, guidler_mount_off[1]-guidler_mount_d/2, guidler_mount_off[2]],  [0,-1,0]];
    /*attach([[0*mm,0*mm,0],[0,0,-1]], guidler_conn_layflat)*/
    /*{*/
        /*extruder_guidler(show_extras=false);*/
    /*}*/

    /*hotmount_clamp();*/
}

use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/transforms.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/triangles.scad>
use <thing_libutils/linear-extrusion.scad>;
use <thing_libutils/bearing.scad>
use <thing_libutils/metric-screw.scad>

include <config.scad>

xaxis_carriage_bearing_distance = 8;
xaxis_carriage_padding = 2;
xaxis_carriage_mount_distance = 23;
xaxis_carriage_mount_offset_z = 0;
xaxis_carriage_teeth_height=xaxis_belt_width*1.5;
xaxis_carriage_mount_screws = ThreadM4;

xaxis_carriage_conn = [[0, -xaxis_bearing[1]/2 - xaxis_carriage_bearing_offset_y,0], [0,0,0]];

xaxis_carriage_beltfasten_w = 20;

hobbed_gear_d_outer = 12.65;
hobbed_gear_d_inner = 11.5;
hobbed_gear_h = 11;

extruder_gear_small_d_inner = 5.75*mm;
extruder_gear_big_d_inner = 29.35*mm;
extruder_gear_big_d_outer = 30.85*mm;
extruder_gear_big_h = [3.85*mm, 5*mm];

// 13t metal gear and 60t metal gear
extruder_gears_distance=extruder_gear_big_d_inner/2+extruder_gear_small_d_inner/2;

extruder_motor = dict_replace_multiple(Nema17,
        [
        [NemaLengthMedium, 11.75*mm],
        [NemaFrontAxleLength, 5*mm],
        ]);

// shaft from big gear to hobbed gear
extruder_shaft_d = 5*mm;

// dist between gear and motor
extruder_gear_motor_dist = .5*mm;
extruder_motor_angle = -80;
extruder_motor_offset_x = cos(extruder_motor_angle) * extruder_gears_distance;
extruder_motor_offset_z = sin(extruder_motor_angle) * extruder_gears_distance;
extruder_motor_holedist = lookup(NemaDistanceBetweenMountingHoles, extruder_motor);

extruder_gear_big_offset=[-extruder_motor_offset_x,0,extruder_motor_offset_z];

extruder_offset = [0,0,10*mm];
extruder_offset_a = -extruder_gear_big_offset+[
    0,
    xaxis_bearing[1] + xaxis_carriage_bearing_offset_y + 1*mm,
    0];
extruder_filapath_offset = [hobbed_gear_d_inner/2, -12*mm, 0];

guidler_bearing = bearing_MR105;
extruder_hotmount_clamp_nut = MHexNutM3;
extruder_hotmount_clamp_thread = ThreadM3;

module x_carriage_base(show_bearings=false)
{
    bottom_width = xaxis_bearing[2] + 2*xaxis_carriage_padding;
    top_width = xaxis_bearing[2]*2 + xaxis_carriage_bearing_distance + 2*xaxis_carriage_padding;
    thickness = xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y;

    hull()
    {
        // top bearings
        translate([0,0,xaxis_rod_distance/2])
            rcubea([top_width, thickness, xaxis_bearing[1]+xaxis_carriage_padding+ziptie_bearing_distance*2], align=[0,1,0]);

        /*rcubea([top_width,thickness,xaxis_rod_distance/2], align=[0,1,0]);*/

        // bottom bearing
        translate([0,0,-xaxis_rod_distance/2])
            rcubea([bottom_width, thickness, xaxis_bearing[1]+xaxis_carriage_padding+ziptie_bearing_distance*2], align=[0,1,0]);

    }
    translate([0,xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y+xaxis_carriage_beltpath_offset+.1,0])
    {
        translate([0,-xaxis_beltpath_width/2,0])
        for(x=[-1,1])
        translate([x*(xaxis_carriage_beltfasten_w/2+5),-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])
        rcubea([xaxis_carriage_beltfasten_w,xaxis_beltpath_width,xaxis_beltpath_height/3], align=[0,0,-1]);
    }

    if(show_bearings)
    {
        for(x=[-1,1])
        translate([
                x*(xaxis_carriage_bearing_distance+xaxis_bearing[2])/2,
                xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y,
                xaxis_rod_distance/2
        ])
        bearing(xaxis_bearing, orient=[1,0,0]);

        translate([
                0,
                xaxis_bearing[1]/2 + xaxis_carriage_bearing_offset_y,
                -xaxis_rod_distance/2
        ])
        bearing(xaxis_bearing, orient=[1,0,0]);

        /*translate([0,xaxis_carriage_beltpath_offset,0])*/
        /*for(i=[-1,1])*/
        /*translate([i*100,0,0])*/
        /*pulley(xaxis_idler_pulley, orient=[0,1,0]);*/
    }

}

module x_carriage_holes()
{
    for(i=[-1,1])
    translate([
            i*(xaxis_bearing[2]/2+xaxis_carriage_bearing_distance/2),
            xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y,
            xaxis_rod_distance/2
    ])
    {
        bearing_mount_holes(xaxis_bearing, orient=[1,0,0]);
        cubea([xaxis_bearing[2]*2,xaxis_bearing[1]/2+10,xaxis_bearing[1]+1*mm], align=[0,1,0]);
    }

    translate([
            0,
            xaxis_bearing[1]/2+xaxis_carriage_bearing_offset_y,
            -xaxis_rod_distance/2])
    {
        bearing_mount_holes(xaxis_bearing, orient=[1,0,0]);
        cubea([xaxis_bearing[2]*2,xaxis_bearing[1]/2+10,xaxis_bearing[1]+1*mm], align=[0,1,0]);
    }

    // Extruder mounting holes
    /*translate([0,0,xaxis_carriage_mount_offset_z])*/
    /*for(j=[-1,1])*/
    /*for(i=[-1,1])*/
    /*{*/
        /*translate([i*xaxis_carriage_mount_distance/2,0,j*xaxis_carriage_mount_distance/2])*/
        /*{*/
            /*screw_dia = lookup(ThreadSize, xaxis_carriage_mount_screws);*/
            /*cylindera(d=screw_dia, h=100, orient=[0,1,0]);*/
        /*}*/
    /*}*/

    translate([0,xaxis_carriage_beltpath_offset+.1,0])
    {
        // Cut clearing space for the belt
        /*translate([0,-xaxis_beltpath_width/2,-xaxis_beltpath_height/2])*/
            /*#rcubea([500,xaxis_beltpath_width+1,5], align=[0,1,0], extrasize=[0,0,4], extrasize_align=[0,0,1]);*/

        translate([0,-xaxis_beltpath_width/2,0])
        {
            difference()
            {
                rcubea([500,xaxis_beltpath_width*2,xaxis_beltpath_height], align=[0,1,0]);
                for(x=[-1,1])
                translate([x*(xaxis_carriage_beltfasten_w/2+5),-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])
                    rcubea([xaxis_carriage_beltfasten_w,xaxis_beltpath_width*2,xaxis_beltpath_height/3], align=[0,1,-1]);
            }
        }

        /*belt_thickness=1.5;*/
        /*for(i=[-1,1])*/
            /*translate([i*30,0,0])*/
                /*rcubea([15,xaxis_beltpath_width,15-belt_thickness], align=[0,0,0]);*/

        // Cut in the middle for belt
        /*rcubea([7,xaxis_beltpath_width,xaxis_beltpath_height], align=[0,0,0]);*/

        /*translate([0,-xaxis_beltpath_width/2,xaxis_pulley_inner_d/2])*/
        /*{*/
            /*// Belt slit*/
            /*rcubea([500,xaxis_beltpath_width,belt_thickness], align=[0,1,0]);*/

            /*[>// Teeth cuts<]*/
            /*[>teeth = 50;<]*/
            /*[>teeth_height = 2;<]*/
            /*[>translate([-belt_tooth_distance/2*teeth-.5,0,0])<]*/
            /*[>for(i=[0:teeth])<]*/
            /*[>{<]*/
                /*[>translate([i*belt_tooth_distance,0,0])<]*/
                    /*[>cubea([belt_tooth_distance*belt_tooth_ratio,xaxis_carriage_teeth_height,teeth_height], align=[0,0,-1]);<]*/
            /*[>}<]*/
        /*}*/
    }
}

module extruder_gear_small()
{
    difference()
    {
        union()
        {
            hull()
            {
                cylindera(d=extruder_gear_small_d_inner, h=7*mm, orient=[0,1,0], align=[0,1,0]);
                cylindera(d=10*mm, h= 3*mm, orient=[0,1,0], align=[0,1,0]);
            }
            cylindera(d=extruder_gear_small_d_inner, h=13*mm, orient=[0,1,0], align=[0,1,0]);
        }
        cylindera(d=5*mm, h=13*mm+.1, orient=[0,1,0], align=[0,1,0]);
    }
}

module extruder_gear_big(align=[0,0,0], orient=[0,0,1])
{
    total_h = extruder_gear_big_h[0]+extruder_gear_big_h[1];
    size_align([extruder_gear_big_d_inner, extruder_gear_big_d_inner, total_h], align=align, orient=orient)
    translate([0,0,-extruder_gear_big_h[0] + total_h/2])
    difference()
    {
        union()
        {
            cylindera(d=extruder_gear_big_d_inner, h=extruder_gear_big_h[0], orient=[0,0,1], align=[0,0,1]);
            cylindera(d=12*mm, h=extruder_gear_big_h[1], orient=[0,0,1], align=[0,0,-1]);
        }
        translate([0,0,-.5])
        cylindera(d=5*mm, h=total_h+.2, orient=[0,0,1], align=[0,0,0]);
    }
}

module motor_mount_cut(motor=Nema17, h=10*mm)
{
    screw_dist = lookup(NemaDistanceBetweenMountingHoles, motor);

    // round dia
    translate([0, .1, 0])
    cylindera(d=1.1*lookup(NemaRoundExtrusionDiameter, motor), h=h, orient=[0,1,0], align=[0,1,0]);

    // motor axle
    translate([0, .1, 0])
    cylindera(d=1.2*lookup(NemaAxleDiameter, motor), h=lookup(NemaFrontAxleLength, motor)+2*mm, orient=[0,1,0], align=[0,1,0]);

    // bearing for offloading force on motor shaft
    /*translate([0, -1*mm-xaxis_pulley[1]-.1, 0])*/
    scale(1.03)
    bearing(bearing_MR105, override_h=h, orient=[0,1,0], align=[0,-1,0]);

    motor_thread=ThreadM3;
    motor_nut=MHexNutM3;
    for(x=[-1,1])
    for(z=[-1,1])
    translate([x*screw_dist/2, -h, z*screw_dist/2])
    {
        if(x!=-1 || z!=-1)
        screw_cut(motor_nut, h=h, with_nut=false, orient=[0,1,0], align=[0,1,0]);
    }
}
extruder_a_h = 14*mm;

module extruder_a(show_vitamins=false)
{
    difference()
    {
        hull()
        /*union()*/
        {
            side = 15*mm;
            rcubea([extruder_motor_holedist+side/2,extruder_a_h,extruder_motor_holedist+side/2], align=[0,1,0]);
            /*hull()*/
            /*{*/
                /*for(x=[-1,1])*/
                /*for(z=[-1,1])*/
                /*translate([(extruder_motor_holedist/2)*x,0,(extruder_motor_holedist/2)*z])*/
                /*rotate([0,x*45,0])*/
                /*rcubea([side/2,extruder_a_h,side/2], align=[0,1,0]);*/
            /*}*/
            translate(extruder_gear_big_offset)
            cylindera(d=extruder_gear_big_d_outer+3*mm, h=extruder_a_h, orient=[0,1,0], align=[0,-1,0], round_radius=2);
        }

        translate([0,extruder_a_h,0])
        {
            translate(extruder_gear_big_offset)
            {
                /*scale([1.3,2.0,1.3])*/
                /*#extruder_gear_big(orient=[0,-1,0], align=[0,-1,0]);*/

                // big gear cutout
                translate([0,-bearing_MR105[2]+.1,0])
                cylindera(d=extruder_gear_big_d_outer+1*mm, h=extruder_a_h+.2, orient=[0,1,0], align=[0,1,0]);

                translate([0,.1,0])
                cylindera(d=extruder_shaft_d+.5*mm, h=extruder_a_h+.2, orient=[0,1,0], align=[0,1,0]);

                translate([0,.1,0])
                scale(1.03)
                bearing(bearing_MR105, override_h=6*mm, orient=[0,1,0], align=[0,-1,0]);
            }

            motor_mount_cut(extruder_motor, h=extruder_a_h+1);
        }

    }

    if(show_vitamins)
    translate([0,extruder_a_h,0])
    {
        translate([0,-extruder_gear_motor_dist,0])
        {
            extruder_gear_small();

            // big gear
            translate(extruder_gear_big_offset)
            {
                translate([0,1,0])
                translate([0,-bearing_MR105[2]+.1,0])
                extruder_gear_big(orient=[0,-1,0], align=[0,-1,0]);

                translate([0,1,0])
                bearing(bearing_MR105, orient=[0,1,0], align=[0,-1,0]);

                translate([0,bearing_MR105[2],0])
                {
                    cylindera(h=60*mm, d=extruder_shaft_d, orient=[0,1,0], align=[0,1,0]);
                }
            }
        }
        motor(extruder_motor, NemaMedium, dualAxis=false, orientation=[-90,0,0]);
    }
}

// from E3D V6 heatsink drawing
// http://wiki.e3d-online.com/wiki/File:DRAWING-V6-175-SINK.png
// each entry == dia + h
hotmount_d_h=[[16*mm,3.7*mm],[12*mm,6*mm],[16*mm,3*mm]];
hotmount_outer_size_xy=max(vec_i(hotmount_d_h,0))+5*mm;
hotmount_outer_size_h=max(vec_i(hotmount_d_h,1))+5*mm;
hotmount_offset_h=-3*mm;

// which side does hotend slide in (x-axis, i.e. -1 is left, 1 is right)
hotmount_tolerance=1.05*mm;

// hotmount clamp screws distance from center
hotmount_clamp_thread = ThreadM3;
hotmount_clamp_nut = MHexNutM3;

hotmount_clamp_screw_dia = lookup(ThreadSize, hotmount_clamp_thread);
hotmount_clamp_screws_dist = hotmount_d_h[1][1] + 1.2*hotmount_clamp_screw_dia;
hotmount_clamp_pad = 0;
hotmount_clamp_thickness = 5*mm;
hotmount_clamp_y = 2*(hotmount_clamp_screws_dist + hotmount_clamp_screw_dia + hotmount_clamp_pad);
hotmount_clamp_height = hotmount_d_h[1][1];

module hotmount_cutout(extend_cut=false)
{
    // cutout of j-head/e3d heatsink mount
    heights=vec_i(hotmount_d_h,1);
    for(e=v_itrlen(hotmount_d_h))
    {
        hs=v_sum(heights,e-1);
        translate([0,0,-hs])
        {
            d=hotmount_d_h[e][0]*hotmount_tolerance;
            h=hotmount_d_h[e][1]*hotmount_tolerance;
            cylindera(d=d,h=h,align=[0,0,-1]);
            if(extend_cut)
            {
                cubea([extruder_b_w/2+1,d,h],align=[1,0,-1]);
            }
        }
    }
}

module hotmount_clamp()
{
    difference()
    {
        union()
        {
            translate([extruder_b_w/2, 0, 0]);
            {
                rcubea([hotmount_clamp_thickness, hotmount_clamp_y, hotmount_clamp_height], align=[-1,0,0]);
            }

            difference()
            {
                translate([extruder_b_w/2 * 1, 0, 0]);
                {
                    rcubea([extruder_b_w/2, hotmount_d_h[1][0], hotmount_clamp_height], align=[-1,0,0]);
                }

                translate([(-extruder_b_w/2 * 1) + (-0.5*1), 0, hotmount_d_h[0][1]+hotmount_d_h[1][1]/2])
                {
                    hotmount_cutout(extend_cut = false);
                }
            }

        }

        // clamp mount screw holes
        for(i=[-1,1])
        {
            translate([.1, i*hotmount_clamp_screws_dist, 0])
                rotate([0,90,0])
                cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread), h=hotmount_clamp_thickness+.2, align=[0,0,-1], extra_h=2);
        }
    }
}

extruder_b_bearing = bearing_MR105;
extruder_b_w = hobbed_gear_d_outer+15*mm;

guidler_mount_off = [0,-guidler_bearing[1]/1.8, -guidler_bearing[1]/1.7];
extruder_guidler_mount_off = [.5*mm -guidler_mount_off[1]+hobbed_gear_d_inner/2+guidler_bearing[1]/2,0,guidler_mount_off[2]];

module extruder_b(show_vitamins=false)
{
    difference()
    {
        hull()
        /*union()*/
        {
            // main house
            extruder_b_size=[
                hobbed_gear_d_outer+5*mm,
                abs(extruder_filapath_offset[1])+hobbed_gear_h/2+extruder_b_bearing[2]+4*mm,
                hobbed_gear_d_outer+5*mm
            ];
            /*translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])*/
            /*translate([hobbed_gear_d_inner/2,0,0])*/
            /*rcubea(extruder_b_size, align=[0,sign(extruder_filapath_offset[1]),0]);*/

            // gear support
            translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
            translate([0,-hobbed_gear_h/2,0])
            {
                // hobbed gear support
                cylindera(d=hobbed_gear_d_outer+5*mm, h=abs(extruder_filapath_offset[1])+hobbed_gear_h/2, align=[0,-1,0], orient=[0,1,0]);

                // bearing support
                cylindera(d=extruder_b_bearing[1]+5*mm, h=extruder_b_bearing[2]+4*mm, align=[0,1,0], orient=[0,1,0]);

            }

            translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
            translate([0, guidler_screws_mount_d_offset, house_guidler_screw_h_offset])
            {
                /*cubea([guidler_screws_mount_d, house_w, house_guidler_screw_h], align=[0,0,0]);*/
                for(i=[-1,1])
                translate([0,i*(guidler_screws_distance),  0])
                cylindera(d=house_guidler_screw_h, h=guidler_screws_mount_d, orient=[1,0,0]);
            }

            // guidler mount
            translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
            translate(extruder_guidler_mount_off)
            {
                cylindera(d=guidler_mount_d, h=guidler_mount_w, orient=[0,1,0]);
            }

            // hotmount support
            translate(extruder_filapath_offset)
            translate([0,0,-hobbed_gear_d_outer/2 + hotmount_offset_h])
            {
                cubea([extruder_b_w, hotmount_outer_size_xy, hotmount_outer_size_h], align=[0,0,-1]);

                translate([0,-extruder_filapath_offset[1],0])
                cubea([extruder_b_w, abs(extruder_filapath_offset[1]), hotmount_outer_size_h], align=[0,-1,-1]);
            }

            /*// clamp mount screw holes*/
            /*translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])*/
            /*translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h])*/
            /*for(i=[-1,1])*/
            /*{*/
                /*translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])*/
                /*cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread)+6*mm, h=extruder_b_w, orient=[1,0,0]);*/
            /*}*/
        }

        // guidler cutout
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        {
            difference()
            {
                hull()
                {
                    translate([hobbed_gear_d_inner/2,0,0])
                    {
                        cubea([guidler_bearing[1]+1*mm,guidler_w+1*mm,guidler_bearing[1]*2], align=[1,0,1]);
                        cylindera(d=guidler_bearing[1]+1*mm, h=guidler_w+1*mm, orient=[0,1,0], align=[1,0,0]);
                    }

                    translate(extruder_guidler_mount_off)
                    {
                        for(y=[-1,1])
                        translate([0,y*guidler_mount_w/2,0])
                        {
                            cylindera(d=guidler_mount_d+.5*mm, h=guidler_mount_w, orient=[0,1,0], align=[0,-y,0]);
                            cubea([10,(guidler_w-guidler_mount_w)/2+.5*mm,10], align=[1,y,1]);
                        }
                    }
                }
                translate(extruder_guidler_mount_off)
                {
                    cylindera(d=guidler_mount_d, h=guidler_mount_w, orient=[0,1,0]);
                    cubea([guidler_mount_d, guidler_mount_w, 10], align=[0,0,-1]);
                }
            }
        }

        // guidler screws cutouts
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        for(y=[-1,1])
        translate([guidler_screws_mount_d_offset, y*(guidler_screws_distance), house_guidler_screw_h_offset])
        {
            r= guidler_screws_thread_dia/2 * 1.1;
            cubea([1000, r*2, r]);

            for(v=[-1,1])
            translate([0,0, v*r/2])
            cylindera(r=r,h=1000, orient=[1,0,0]);

            // guidler screw nuts drop-in slots
            translate([0,0, -r*2])
            cubea([nut_m3[2]*1.25,nut_m3[1]*1.1,house_guidler_screw_h], align=[0,0,1], extrasize=[0,0,1], extrasize_align=[0,0,1]);
        }

        // guidler mount screw
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        translate(extruder_guidler_mount_off)
        {
            cylindera(d=lookup(ThreadSize, guidler_screws_thread), h=guidler_mount_w+.1, orient=[0,1,0]);
        }

        // cutout for hobbed gear (inner)
        cylindera(h=abs(extruder_filapath_offset[1])+hobbed_gear_h/2+1*mm, d=hobbed_gear_d_outer+2*mm, orient=[0,1,0], align=[0,1,0]);

        // cutout for bearing
        cylindera(h=abs(extruder_filapath_offset[1])+hobbed_gear_h/2+extruder_b_bearing[2]+1*mm, d=extruder_b_bearing[1]+.1*mm, orient=[0,1,0], align=[0,1,0]);

        // hotmount clamp screws
        translate([hobbed_gear_d_inner/2, 0,-hobbed_gear_d_outer/2 + hotmount_offset_h])
        for(i=[-1,1])
        {
            translate([i*hotmount_clamp_screws_dist, 0, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
            screw_cut(nut=extruder_hotmount_clamp_nut, h=1000, head_embed=false, orient=[0,1,0], align=[0,-1,0]);
        }

        // filament path
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        translate([hobbed_gear_d_outer/2,0,0])
        cylindera(h=1000, d=4*mm, orient=[0,0,1], align=[0,0,0]);

        // gear cutout
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        translate([0,-hobbed_gear_h/2-.5*mm,0])
        cylindera(d=extruder_b_bearing[1]+.3*mm, h=extruder_b_bearing[2]+.5*mm, align=[0,1,0], orient=[0,1,0]);

        // extruder shaft
        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        translate([0,-extruder_filapath_offset[1]+.1,0])
        cylindera(h=1000, d=extruder_shaft_d, orient=[0,1,0], align=[0,1,0]);

        translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
        translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h+.01])
        rotate([0,0,-90])
        {
            hotmount_cutout(extend_cut=true);

            // clamp mount screw holes
            for(i=[-1,1])
            {
                translate([0, i*hotmount_clamp_screws_dist, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
                cylindera(d=lookup(ThreadSize, extruder_hotmount_clamp_thread), h=extruder_b_w+1, orient=[1,0,0]);
            }

            // hotmount clamp cutout
            translate([extruder_b_w/2, 0, -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
            {
                rcubea([hotmount_clamp_thickness+1.2, hotmount_clamp_y+0.2, hotmount_clamp_height+0.2], align=[-1,0,0], extrasize=[100,0,0], extrasize_align=[1,0,0]);
            }
        }
    }

    translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
    if(show_vitamins)
    {
        translate([hobbed_gear_d_inner/2,0,-hobbed_gear_d_outer/2 + hotmount_offset_h+.01])
        translate([0, -extruder_b_w/2 * (1), -hotmount_d_h[0][1]-hotmount_d_h[1][1]/2])
        rotate([0,0,-90])
        hotmount_clamp();

        translate([0,-hobbed_gear_h/2-extruder_b_bearing[2]-.5*mm,0])
        {
            cylindera(h=extruder_a_h+extruder_offset_a[1]-extruder_filapath_offset[1], d=extruder_shaft_d, orient=[0,1,0], align=[0,-1,0]);

            bearing(extruder_b_bearing, orient=[0,1,0], align=[0,1,0]);
        }

        // hobbed gear
        cylindera(h=hobbed_gear_h, d=hobbed_gear_d_inner, orient=[0,1,0], align=[0,0,0]);
        for(y=[-1,1])
            translate([0,y*hobbed_gear_h/2,0])
            {
                cylindera(h=hobbed_gear_h/3, d=hobbed_gear_d_outer, orient=[0,1,0], align=[0,y,0]);
            }
    }
}

// Final part
module x_carriage(show_bearings=true)
{
    difference()
    {
        /*hull()*/
        union()
        {
            x_carriage_base(show_bearings=show_bearings);
            translate(extruder_offset)
            translate(extruder_offset_a)
            {
                for(x=[-1,1])
                for(z=[-1,1])
                translate([x*extruder_motor_holedist/2,0,z*extruder_motor_holedist/2])
                cylindera(d=10*mm, h=extruder_offset_a[1], orient=[0,1,0], align=[0,1,0], round_radius=2);
            }
        }
        translate(extruder_offset)
        translate(extruder_offset_a)
        {
            for(x=[-1,1])
            for(z=[-1,1])
            translate([x*extruder_motor_holedist/2,0,z*extruder_motor_holedist/2])
            translate([0,.1,0])
            cylindera(d=3*mm, h=extruder_offset_a[1]+.2, orient=[0,1,0], align=[0,1,0]);
        }
        x_carriage_holes();
    }
}

/*translate([0,-42,38])*/
/*rotate([0,0,90])*/
/*translate([0,-1,-42])*/
/*translate([-83,25,-42])*/
/*rotate([90,0,0])*/
/*import("stl/i3R_Compact_E3Dv6_Extruder_1.75_01.STL");*/

module x_extruder_hotend()
{
    hotend_conn =[[0,0,27.8-hotmount_offset_h],[0,0,1]];
    translate(extruder_filapath_offset)
    attach(extruder_conn_hotend, hotend_conn)
        rotate([90,0,90])
        %import("stl/E3D_V6_1.75mm_Universal_HotEnd_Mockup.stl");

}

house_w = 20;
house_h = 30;

// length of the guidler bearing bolt/screw

guidler_mount_w=guidler_bearing[2];
guidler_mount_d=6*mm;
guidler_bolt_h=guidler_bearing[2]+4*mm;

guidler_w=max(guidler_mount_w+7, guidler_bearing[2]*2.8);
guidler_d=5;
guidler_h=7;
guidler_extra_h_up=guidler_bearing[1]/2+hotmount_clamp_screw_dia/2;

guidler_screws_thread = ThreadM3;
guidler_screws_thread_dia= lookup(ThreadSize, guidler_screws_thread);
guidler_screws_distance=4*mm;
guidler_screws_mount_d = 10*mm;
guidler_screws_mount_d_offset = 0*mm;

guidler_srew_distance = 10;

house_guidler_screw_h = guidler_screws_thread_dia+8*mm;
house_guidler_screw_h_offset = house_h/2 + guidler_screws_thread_dia -7*mm;

module extruder_guidler()
{
    // everything inside this module is relative to the center of the
    // bearing (that clamps the filament)
    difference()
    {
        union()
        {

            hull()
            {
                // guidler main block
                translate([0,guidler_mount_off[1]-guidler_mount_d/2, 0])
                cubea([guidler_w, guidler_d, guidler_h], align=[0,1,0]);

                // guidler bearing bolt holder
                cylindera(d=guidler_bearing[0]*1.5,h=guidler_w, orient=[1,0,0]);
            }

            hull()
            {
                // guidler main block
                translate([0,guidler_mount_off[1]-guidler_mount_d/2, 0])
                cubea([guidler_w, guidler_d, guidler_h], align=[0,1,0], extrasize=[0,0,guidler_extra_h_up], extrasize_align=[0,0,1]);

                // guidler mount point
                translate([0,guidler_mount_off[1], guidler_mount_off[2]])
                cylindera(d=guidler_mount_d,h=guidler_w, orient=[1,0,0]);
            }

            hull()
            {
                // guidler main block
                translate([0,guidler_mount_off[1]-guidler_mount_d/2, guidler_h])
                cubea([guidler_w, guidler_d, 1], align=[0,1,0]);

                // guidler screws mount
                for(i=[-1,1])
                translate([i*(guidler_screws_distance),guidler_mount_off[1]-guidler_mount_d/2, house_guidler_screw_h_offset])
                cylindera(r=guidler_screws_thread_dia/2*3,h=guidler_d, align=[0,-1,0], orient=[0,1,0]);

            }
        }

        // cutouts for clamping screws
        for(i=[-1,1])
        translate([i*(guidler_screws_distance),guidler_mount_off[1]-guidler_mount_d/2, house_guidler_screw_h_offset])
        {
            r= guidler_screws_thread_dia/2*1.1;
            cubea([r*2,house_w+.1,r]);
            for(v=[-1,1])
            translate([0, -0.1, v*r/2])
            {
                cylindera(r=r,h=house_w+1, align=[0,-1,0], orient=[0,1,0]);
            }
        }

        // port hole to see bearing
        translate([0,-guidler_bearing[1]/2,0])
        cubea([guidler_bearing[0]*1.1, 100, guidler_bearing[1]/2], align=[0,0,1]);

        // cutout middle mount point pivot
        translate([0,guidler_mount_off[1], guidler_mount_off[2]])
        cylindera(d=guidler_mount_d*1.25,h=guidler_mount_w*1.1, orient=[1,0,0]);

        // mount bolt hole
        translate([0,guidler_mount_off[1], guidler_mount_off[2]])
        cylindera(d=lookup(ThreadSize, guidler_screws_thread),h=100, orient=[1,0,0]);

        // guidler bearing bolt holder cutout
        union()
        {
            cubea([guidler_bolt_h*1.05+2*e,guidler_bearing[0]*1.05,guidler_bearing[0]*1.05],align=[0,1,0]);

            cylindera(d=guidler_bearing[0]*1.05, h=guidler_bolt_h*1.05, orient=[1,0,0]);
        }

        // guidler bearing cutout
        cylindera(d=guidler_bearing[1]*1.1, h=guidler_bearing[2]*1.1, orient=[1,0,0]);

    }

    %if(show_extras)
    {
        cylindera(d=guidler_bearing[1], h=guidler_bearing[2], orient=[1,0,0]);
        cylindera(d=guidler_bearing[0], h=guidler_bolt_h, orient=[1,0,0]);
    }
}

// extruder guidler mount point
extruder_conn_guidler = [ extruder_guidler_mount_off, [0,1,0]];

// guidler connection point
extruder_guidler_conn_mount = [ guidler_mount_off,  [1,0,0]];
extruder_guidler_roll = 45;

if(false)
attach(extruder_conn_guidler, extruder_guidler_conn_mount, extruder_guidler_roll)
{
    extruder_guidler(show_extras=true);
}

/*if(false)*/
{
    %x_carriage(show_bearings=false);

    translate(extruder_offset)
    {
        translate(extruder_offset_a)
        extruder_a(show_vitamins=true);

        {
            extruder_b(show_vitamins=true);

            translate(extruder_filapath_offset-[hobbed_gear_d_inner/2,0,0])
            attach(extruder_conn_guidler, extruder_guidler_conn_mount, extruder_guidler_roll)
            {
                %extruder_guidler(show_extras=true);
            }
        }

        %x_extruder_hotend();
    }
    //filament path
    %translate(extruder_filapath_offset)
        cylindera(h=1000, d=1.75*mm, orient=[0,0,1], align=[0,0,0]);
}


Citosine

Citosine


Код Дезоксирибозы с переменными

Код Дезоксирибозы с переменными


add setup for icons

add setup for icons

use <../../../basics/rounded-edges/doughnuts/doughnuts.scad>;

use <../../../basics/rounded-edges/rounded-pyramid/rounded-pyramid.scad>;

use <../../../shapes/geometry/arc/extruded/extruded-arc.scad>;

module halfCirclePhoneStand(height = 19.125,

                            iconColor = "red",
                            iconType = "None",
                            iconXyScale = 1.0,
                            iconHeight = 3.0,
                            icon_xOffset = 5,
                            icon_yOffset = 5,

                            minkowskiSphereRadius = 0.5,
                            arcRadius = 36,
                            arcRadiusExtension = 1.5)
{
    halfCirclePhoneStand_cradle(height = height,

                                iconColor = iconColor,
                                iconType = iconType,
                                iconXyScale = iconXyScale,
                                iconHeight = iconHeight,
                                icon_xOffset = icon_xOffset,
                                icon_yOffset = icon_yOffset,

                                minkowskiSphereRadius = minkowskiSphereRadius,
                                radius = arcRadius,
                                radiusExtension = arcRadiusExtension);

    halfCirclePhoneStand_stand(height = height,
                               minkowskiSphereRadius = minkowskiSphereRadius);
}

// sub-modules and functions follow

function halfCirclePhoneStand_cradle_cutout_zLength() = 4.2;

function halfCirclePhoneStand_cradle_cutout_zTranslate(minkowskiSphereRadius,
                                                        bedHeight,
                                                        zLength) = minkowskiSphereRadius + (bedHeight / 2.0) - (zLength / 2.0);

module halfCirclePhoneStand_cradle(height,

                                   iconColor, iconType, iconXyScale, iconHeight, icon_xOffset, icon_yOffset,

                                   minkowskiSphereRadius,
                                   radius,
                                   radiusExtension)
{
    xTranslate = 30;
    yTranslate = 32.7;

    difference()
    {
        halfCirclePhoneStand_cradle_bed(height = height,
                                           minkowskiSphereRadius = minkowskiSphereRadius,
                                           radius = radius,
                                           radiusExtension = radiusExtension,
                                           xTranslate = xTranslate,
                                           yTranslate = yTranslate);

        halfCirclePhoneStand_cradle_cutout(bedHeight = height,
                                        minkowskiSphereRadius = minkowskiSphereRadius,
                                        radius = radius,
                                        radiusExtension = radiusExtension,
                                        bed_xTranslate = xTranslate,
                                        bed_yTranslate = yTranslate);
    }

    halfCirclePhoneStand_cradle_icon(iconColor = iconColor,
                                     iconType = iconType,
                                     iconXyScale = iconXyScale,
                                     iconHeight = iconHeight,
                                     xOffset = icon_xOffset,
                                     yOffset = icon_yOffset);

    halfCirclePhoneStand_cradle_ends(height = height,
                                     minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_cradle_bed(height,
                                       minkowskiSphereRadius,
                                       radius,
                                       radiusExtension,
                                       xTranslate,
                                       yTranslate)
{
    zTranslate = minkowskiSphereRadius;
    color("magenta")
    translate([xTranslate, yTranslate, zTranslate])
    rotate([0, 0, 213])
    roundedRectangularArc(angle = 150,
                          height = height,
                          minkowskiRadius = minkowskiSphereRadius,
                          radius = radius,
                          radiusExtension = radiusExtension);
}

module halfCirclePhoneStand_cradle_cutout(bedHeight,
                                          minkowskiSphereRadius,
                                          radius,
                                          radiusExtension,
                                          bed_xTranslate,
                                          bed_yTranslate)
{
    zLength = halfCirclePhoneStand_cradle_cutout_zLength();

    cutoutRadiusExtension = radiusExtension + 3;

    xTranslate = bed_xTranslate + 0.2;
    yTranslate = bed_yTranslate + 0.2;
    zTranslate = halfCirclePhoneStand_cradle_cutout_zTranslate(minkowskiSphereRadius = minkowskiSphereRadius,
                                                                bedHeight = bedHeight,
                                                                zLength = zLength);

    color("DarkTurquoise")
    translate([xTranslate, yTranslate, zTranslate])
    rotate([0, 0, 227])
    roundedRectangularArc(angle = 37,
                          height = zLength,
                          minkowskiRadius = minkowskiSphereRadius,
                          radius = radius,
                          radiusExtension = cutoutRadiusExtension);
}

module halfCirclePhoneStand_cradle_ends(height,
                                        minkowskiSphereRadius)
{
    halfCirclePhoneStand_cradle_ends_top(height = height,
                                            minkowskiSphereRadius = minkowskiSphereRadius);

    halfCirclePhoneStand_cradle_ends_bottom(height = height,
                                            minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_cradle_ends_bottom(height,
                                               minkowskiSphereRadius)
{
    xTranslate = 2.8;
    yTranslate = 56.35;
    zTranslate = minkowskiSphereRadius;

    // bottom end
    color("PaleTurquoise")
    translate([xTranslate, yTranslate, zTranslate])
    halfCirclePhoneStand_cradle_ends_cylinder(height = height,
                                              minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_cradle_ends_top(height,
                                        minkowskiSphereRadius)
{
    xTranslate = 40.3;
    yTranslate = -2.5;
    zTranslate = minkowskiSphereRadius;

    // bottom end
    color("PaleTurquoise")
    translate([xTranslate, yTranslate, zTranslate])
    halfCirclePhoneStand_cradle_ends_cylinder(height = height,
                                              minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_cradle_ends_cylinder(height,
                                        minkowskiSphereRadius)
{
    roundedPyramid(h = height,
                   cornerRadius = minkowskiSphereRadius,
                   cylinderFn = 20,
                   r1 = 2.57,
                   r2 = 2.57,
                   sides = 30);
}

module halfCirclePhoneStand_cradle_icon(iconColor, iconType, iconXyScale, iconHeight, xOffset, yOffset)
{
    color(iconColor)
    translate([xOffset, yOffset, 0])
    scale([iconXyScale, iconXyScale, iconHeight])
    if(iconType == "Aqua Dude")
    {
        aquamanThumbnail(height=1.6);
    }
    else if(iconType == "Bass Clef")
    {
    	baseclef15scale(1.8);
    }
    else if(iconType == "Cat")
    {
        cat(1.8);
    }
    else if(iconType == "Creeper")
    {
        creeperFaceThumbnail(height = 1.7);
    }
    else if(iconType == "Fan")
    {
        scale([1, 1, 1.6])
        fanThumbnail();
    }
    else if(iconType == "Fish")
    {
        scale([1, 1, 1.6])
        fishThumbnail();
    }
    else if(iconType == "Light Bulb")
    {
        lightBulbThumbnail();
    }
    else if(iconType == "Mario")
    {
        marioThumbnail();
    }
    else if(iconType == "Luigi")
    {
        luigiThumbnail();
    }
    else if(iconType == "Moon")
    {
        crescentMoonThumbnail();
    }
    else if(iconType == "Rebel")
    {
        rebelAllianceThumbnail(height = 1.7);
    }
    else if(iconType == "Spur")
    {
        spurThumbnail();
    }
    else if(iconType == "Sun")
    {
        sunThumbnail(height = 1.6);
    }
    else if(iconType == "Trooper")
    {
        scrumtrooper(2);
    }
    else if(iconType == "Thundercat")
    {
        thundercatsLogoThumbnail(height = 1.7);
    }
    else if(iconType == "Treble Clef")
    {
        trebleClefScaledDownThumbnail(h=2);
    }
    else
    {
        echo("drawing no icon");
    }
}

module halfCirclePhoneStand_stand(height,
                                  minkowskiSphereRadius)
{
    halfCirclePhoneStand_stand_top(height = height,
                                   minkowskiSphereRadius = minkowskiSphereRadius);

    halfCirclePhoneStand_stand_connectorBar(bedHeight = height,
                                            minkowskiSphereRadius = minkowskiSphereRadius);

    halfCirclePhoneStand_stand_base(height = height,
                                    minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_stand_base(height,
                                       minkowskiSphereRadius)
{
    color("green")
    translate([0, 0, minkowskiSphereRadius])
    roundDoughnut(height = height,
                innerRadius = 4.9,      // 4.9
                outerRadius = 5.59,     // 5.59
                minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_stand_connectorBar(minkowskiSphereRadius, bedHeight)
{
    xLength = 5;
    yLength = 3;
    zLength = halfCirclePhoneStand_cradle_cutout_zLength() + minkowskiSphereRadius;

    xTranslate = 5;
    yTranslate = 5;
    zTranslate = halfCirclePhoneStand_cradle_cutout_zTranslate(minkowskiSphereRadius = minkowskiSphereRadius,
                                                                bedHeight = bedHeight,
                                                                zLength = zLength)
                    + (zLength / 2.0);

    color("blue")
    translate([xTranslate, yTranslate, zTranslate])
    rotate([0, 0, 45])
    cube([xLength, yLength, zLength], center = true);
}

module halfCirclePhoneStand_stand_top(height,
                                      minkowskiSphereRadius)
{
    xTranslate = 8.105;  // 8.05     // 8.1
    yTranslate = 8.85;  // 8.85     // 8.9

    color("green")
    translate([xTranslate, yTranslate, minkowskiSphereRadius])
    roundDoughnut(height = height,
                innerRadius = 1.9,  // 2.0
                outerRadius = 2.6,  // 2.6
                minkowskiSphereRadius = minkowskiSphereRadius);
}

use <../../../basics/rounded-edges/doughnuts/doughnuts.scad>;

use <../../../basics/rounded-edges/rounded-pyramid/rounded-pyramid.scad>;

use <../../../shapes/geometry/arc/extruded/extruded-arc.scad>;

module halfCirclePhoneStand(height = 19.125,
                            minkowskiSphereRadius = 0.5,
                            arcRadius = 36,
                            arcRadiusExtension = 1.5)
{
    halfCirclePhoneStand_cradle(height = height,
                                minkowskiSphereRadius = minkowskiSphereRadius,
                                radius = arcRadius,
                                radiusExtension = arcRadiusExtension);

    halfCirclePhoneStand_stand(height = height,
                               minkowskiSphereRadius = minkowskiSphereRadius);
}

// sub-modules and functions follow

function halfCirclePhoneStand_cradle_cutout_zLength() = 4.2;

function halfCirclePhoneStand_cradle_cutout_zTranslate(minkowskiSphereRadius,
                                                        bedHeight,
                                                        zLength) = minkowskiSphereRadius + (bedHeight / 2.0) - (zLength / 2.0);

module halfCirclePhoneStand_cradle(height,
                                   minkowskiSphereRadius,
                                   radius,
                                   radiusExtension)
{
    xTranslate = 30;
    yTranslate = 32.7;

    difference()
    {
        halfCirclePhoneStand_cradle_bed(height = height,
                                           minkowskiSphereRadius = minkowskiSphereRadius,
                                           radius = radius,
                                           radiusExtension = radiusExtension,
                                           xTranslate = xTranslate,
                                           yTranslate = yTranslate);

        halfCirclePhoneStand_cradle_cutout(bedHeight = height,
                                        minkowskiSphereRadius = minkowskiSphereRadius,
                                        radius = radius,
                                        radiusExtension = radiusExtension,
                                        bed_xTranslate = xTranslate,
                                        bed_yTranslate = yTranslate);
    }

    halfCirclePhoneStand_cradle_ends(height = height,
                                     minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_cradle_bed(height,
                                       minkowskiSphereRadius,
                                       radius,
                                       radiusExtension,
                                       xTranslate,
                                       yTranslate)
{
    zTranslate = minkowskiSphereRadius;
    color("magenta")
    translate([xTranslate, yTranslate, zTranslate])
    rotate([0, 0, 213])
    roundedRectangularArc(angle = 150,
                          height = height,
                          minkowskiRadius = minkowskiSphereRadius,
                          radius = radius,
                          radiusExtension = radiusExtension);
}

module halfCirclePhoneStand_cradle_cutout(bedHeight,
                                          minkowskiSphereRadius,
                                          radius,
                                          radiusExtension,
                                          bed_xTranslate,
                                          bed_yTranslate)
{
    zLength = halfCirclePhoneStand_cradle_cutout_zLength();

    cutoutRadiusExtension = radiusExtension + 3;

    xTranslate = bed_xTranslate + 0.2;
    yTranslate = bed_yTranslate + 0.2;
    zTranslate = halfCirclePhoneStand_cradle_cutout_zTranslate(minkowskiSphereRadius = minkowskiSphereRadius,
                                                                bedHeight = bedHeight,
                                                                zLength = zLength);

    color("DarkTurquoise")
    translate([xTranslate, yTranslate, zTranslate])
    rotate([0, 0, 227])
    roundedRectangularArc(angle = 37,
                          height = zLength,
                          minkowskiRadius = minkowskiSphereRadius,
                          radius = radius,
                          radiusExtension = cutoutRadiusExtension);
}

module halfCirclePhoneStand_cradle_ends(height,
                                        minkowskiSphereRadius)
{
    halfCirclePhoneStand_cradle_ends_top(height = height,
                                            minkowskiSphereRadius = minkowskiSphereRadius);

    halfCirclePhoneStand_cradle_ends_bottom(height = height,
                                            minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_cradle_ends_bottom(height,
                                        minkowskiSphereRadius)
{
    xTranslate = 2.8;
    yTranslate = 56.35;
    zTranslate = minkowskiSphereRadius;

    // bottom end
    color("PaleTurquoise")
    translate([xTranslate, yTranslate, zTranslate])
    halfCirclePhoneStand_cradle_ends_cylinder(height = height,
                                              minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_cradle_ends_top(height,
                                        minkowskiSphereRadius)
{
    xTranslate = 40.3;
    yTranslate = -2.5;
    zTranslate = minkowskiSphereRadius;

    // bottom end
    color("PaleTurquoise")
    translate([xTranslate, yTranslate, zTranslate])
    halfCirclePhoneStand_cradle_ends_cylinder(height = height,
                                              minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_cradle_ends_cylinder(height,
                                        minkowskiSphereRadius)
{
    roundedPyramid(h = height,
                   cornerRadius = minkowskiSphereRadius,
                   cylinderFn = 20,
                   r1 = 2.57,
                   r2 = 2.57,
                   sides = 30);
}

module halfCirclePhoneStand_stand(height,
                                  minkowskiSphereRadius)
{
    halfCirclePhoneStand_stand_top(height = height,
                                   minkowskiSphereRadius = minkowskiSphereRadius);

    halfCirclePhoneStand_stand_connectorBar(bedHeight = height,
                                            minkowskiSphereRadius = minkowskiSphereRadius);

    halfCirclePhoneStand_stand_base(height = height,
                                    minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_stand_base(height,
                                       minkowskiSphereRadius)
{
    color("green")
    translate([0, 0, minkowskiSphereRadius])
    roundDoughnut(height = height,
                innerRadius = 4.9,      // 4.9
                outerRadius = 5.59,     // 5.59
                minkowskiSphereRadius = minkowskiSphereRadius);
}

module halfCirclePhoneStand_stand_connectorBar(minkowskiSphereRadius, bedHeight)
{
    xLength = 5;
    yLength = 3;
    zLength = halfCirclePhoneStand_cradle_cutout_zLength() + minkowskiSphereRadius;

    xTranslate = 5;
    yTranslate = 5;
    zTranslate = halfCirclePhoneStand_cradle_cutout_zTranslate(minkowskiSphereRadius = minkowskiSphereRadius,
                                                                bedHeight = bedHeight,
                                                                zLength = zLength)
                    + (zLength / 2.0);

    color("blue")
    translate([xTranslate, yTranslate, zTranslate])
    rotate([0, 0, 45])
    cube([xLength, yLength, zLength], center = true);
}

module halfCirclePhoneStand_stand_top(height,
                                      minkowskiSphereRadius)
{
    xTranslate = 8.105;  // 8.05     // 8.1
    yTranslate = 8.85;  // 8.85     // 8.9

    color("green")
    translate([xTranslate, yTranslate, minkowskiSphereRadius])
    roundDoughnut(height = height,
                innerRadius = 1.9,  // 2.0
                outerRadius = 2.6,  // 2.6
                minkowskiSphereRadius = minkowskiSphereRadius);
}


zaxis/motor-mount: Use nut_trap_cut

zaxis/motor-mount: Use nut_trap_cut

include <MCAD/stepper.scad>
include <MCAD/motors.scad>

use <thing_libutils/shapes.scad>
use <thing_libutils/metric-screw.scad>

include <config.scad>
include <rod-clamps.scad>

zmotor_mount_conn_motor=[[-zmotor_mount_motor_offset, 0, 0],[0,1,0]];

module zaxis_motor_mount(show_motor=false)
{

    difference()
    {
        // top plate
        union()
        {

            difference()
            {
                union()
                {
                    // top plate
                    cubea([zmotor_mount_rod_offset_x-zmotor_mount_thickness, zmotor_w+zmotor_mount_thickness*2, zmotor_mount_thickness_h], align=[1,0,1]);
                    translate([zmotor_mount_rod_offset_x, 0, 0])
                    {
                        cubea([gantry_connector_thickness, zmotor_w+zmotor_mount_thickness*2, zmotor_mount_thickness_h], align=[-1,0,1]);
                    }

                    // reinforcement plate between motor and extrusion
                    cubea([zmotor_mount_thickness, zmotor_w, zmotor_h], align=[1,0,-1]);

                    // top extrusion mount plate
                    translate([0, 0,-extrusion_size-zaxis_motor_offset_z])
                        cubea([zmotor_mount_thickness, zmotor_mount_width, extrusion_size], align=[1,0,1]);

                    // bottom extrusion mount plate
                    translate([0, 0, -main_lower_dist_z-extrusion_size-zaxis_motor_offset_z])
                        cubea([zmotor_mount_thickness, zmotor_w, extrusion_size], align=[1,0,1]);

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

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

                }

                // cutout for motor cables
                translate([0,0,-30*mm])
                cubea([zmotor_mount_thickness*3, 20*mm, zmotor_h], align=[0,0,-1]);

                // screw holes top
                for(i=[-1,1])
                    translate([0, i*(zmotor_w/2+zmotor_mount_thread_dia*3), -extrusion_size])
                        cylindera(h=zmotor_mount_thickness*3,d=zmotor_mount_thread_dia, orient=[1,0,0]);

                // screw hole bottom
                for(i=[0])
                    translate([0, i*(zmotor_w/2+zmotor_mount_thread_dia*3), -extrusion_size-main_lower_dist_z])
                        cylindera(h=zmotor_mount_thickness*3,d=zmotor_mount_thread_dia,align=[0,0,0], orient=[1,0,0]);
            }

        }

        // cut out motor mount holes etc
        translate([zmotor_mount_screw_offset_x, 0, 0])
        translate([0,0,-1])
            linear_extrude(zmotor_mount_thickness_h+2)
            stepper_motor_mount(17, slide_distance=0, mochup=false);

        // cut out z rod
        translate([zmotor_mount_rod_offset_x, 0, 0])
            cylindera(d=zaxis_rod_d*rod_fit_tolerance, h=100, orient=[0,0,1]);

        // cut out z rod mounting clamp nut traps
        for(i=[-1,1])
        {
            translate([zmotor_mount_rod_offset_x-5, i*zmotor_mount_clamp_dist/2, zmotor_mount_thickness_h/2])
            {
                #nut_trap_cut(nut=zmotor_mount_clamp_nut, h=10, head_embed=false, trap_h=10, screw_l_extra=2*mm, trap_axis=[0,0,1], orient=[1,0,0], align=[0,0,0]);
            }
        }

        %if(show_motor)
        {
            attach([[lookup(NemaSideSize,zaxis_motor)/2,0,0],[0,0,0]],zmotor_mount_conn_motor)
            {
                // z motor/leadscrews
                motor(zaxis_motor, NemaMedium, dualAxis=false, orientation=[0,180,0]);
            }
        }
    }
}

/*print = true;*/
/*if(print)*/
/*{*/
    /*rotate([0,-90,0])*/
        /*zaxis_motor_mount();*/

    /*translate([-25,0,zmotor_mount_thickness_h/2])*/
        /*mount_rod_clamp_half(*/
                /*rod_d=zaxis_rod_d,*/
                /*screw_dist=zmotor_mount_clamp_dist,*/
                /*thick=5,*/
                /*base_thick=5,*/
                /*width=zmotor_mount_thickness_h,*/
                /*thread=zmotor_mount_clamp_thread);*/
/*}*/

include <MCAD/stepper.scad>
include <MCAD/motors.scad>

use <thing_libutils/shapes.scad>

include <config.scad>
include <rod-clamps.scad>

zmotor_mount_conn_motor=[[-zmotor_mount_motor_offset, 0, 0],[0,1,0]];

module zaxis_motor_mount(show_motor=false)
{

    difference()
    {
        // top plate
        union()
        {

            difference()
            {
                union()
                {
                    // top plate
                    cubea([zmotor_mount_rod_offset_x-zmotor_mount_thickness, zmotor_w+zmotor_mount_thickness*2, zmotor_mount_thickness_h], align=[1,0,1]);
                    translate([zmotor_mount_rod_offset_x, 0, 0])
                    {
                        cubea([gantry_connector_thickness, zmotor_w+zmotor_mount_thickness*2, zmotor_mount_thickness_h], align=[-1,0,1]);
                    }

                    // reinforcement plate between motor and extrusion
                    cubea([zmotor_mount_thickness, zmotor_w, zmotor_h], align=[1,0,-1]);

                    // top extrusion mount plate
                    translate([0, 0,-extrusion_size-zaxis_motor_offset_z])
                        cubea([zmotor_mount_thickness, zmotor_mount_width, extrusion_size], align=[1,0,1]);

                    // bottom extrusion mount plate
                    translate([0, 0, -main_lower_dist_z-extrusion_size-zaxis_motor_offset_z])
                        cubea([zmotor_mount_thickness, zmotor_w, extrusion_size], align=[1,0,1]);

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

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

                }

                // cutout for motor cables
                translate([0,0,-30*mm])
                cubea([zmotor_mount_thickness*3, 20*mm, zmotor_h], align=[0,0,-1]);

                // screw holes top
                for(i=[-1,1])
                    translate([0, i*(zmotor_w/2+zmotor_mount_thread_dia*3), -extrusion_size])
                        cylindera(h=zmotor_mount_thickness*3,d=zmotor_mount_thread_dia, orient=[1,0,0]);

                // screw hole bottom
                for(i=[0])
                    translate([0, i*(zmotor_w/2+zmotor_mount_thread_dia*3), -extrusion_size-main_lower_dist_z])
                        cylindera(h=zmotor_mount_thickness*3,d=zmotor_mount_thread_dia,align=[0,0,0], orient=[1,0,0]);
            }

        }

        // cut out motor mount holes etc
        translate([zmotor_mount_screw_offset_x, 0, 0])
        translate([0,0,-1])
            linear_extrude(zmotor_mount_thickness_h+2)
            stepper_motor_mount(17, slide_distance=0, mochup=false);

        // cut out z rod
        translate([zmotor_mount_rod_offset_x, 0, 0])
            cylindera(d=zaxis_rod_d*rod_fit_tolerance, h=100, orient=[0,0,1]);

        // cut out z rod mounting clamp nut traps
        for(i=[-1,1])
        {
            translate([zmotor_mount_rod_offset_x-7, i*zmotor_mount_clamp_dist/2, zmotor_mount_thickness_h/2])
            {
                cubea([zmotor_mount_clamp_nut_thick*1.3, zmotor_mount_clamp_nut_dia*1.1, zmotor_mount_clamp_nut_dia*1.01], extrasize=[0,0,zmotor_mount_thickness_h], extrasize_align=[0,0,1]);

                translate([-zmotor_mount_clamp_nut_thick*1.3/2,0,0])
                cylindera(d=zmotor_mount_clamp_thread_dia, h=20, orient=[1,0,0], align=[1,0,0]);
            }
        }

        %if(show_motor)
        {
            attach([[lookup(NemaSideSize,zaxis_motor)/2,0,0],[0,0,0]],zmotor_mount_conn_motor)
            {
                // z motor/leadscrews
                motor(zaxis_motor, NemaMedium, dualAxis=false, orientation=[0,180,0]);
            }
        }
    }
}

/*print = true;*/
/*if(print)*/
/*{*/
    /*rotate([0,-90,0])*/
        /*zaxis_motor_mount();*/

    /*translate([-25,0,zmotor_mount_thickness_h/2])*/
        /*mount_rod_clamp_half(*/
                /*rod_d=zaxis_rod_d,*/
                /*screw_dist=zmotor_mount_clamp_dist,*/
                /*thick=5,*/
                /*base_thick=5,*/
                /*width=zmotor_mount_thickness_h,*/
                /*thread=zmotor_mount_clamp_thread);*/
/*}*/


Smaller (125mm square) and with thinner base - 1mm instead of 2mm

4 of these per chair. I've printed 7 of these on the Pulse. Takes about 3 hours per unit.

// Cushion Grabber - see README.md for details.
// Author: Joseph M. Joy

function range(stop, start=0,  step=1) = [start: step: stop-1];

// Coords of an isoceles right triangle
function ir_tri(base) = [[0,0], [0, base], [base, 0]];

tri_height = 5;
base_thickness = 1;

// Extruded version
module rt_prism(base, height)  {
    linear_extrude(height) polygon(ir_tri(base));
}

// A row of extruded triangles
module prism_rows(base, height, n) {
    for (i = range(n)) {
         translate([3*base*i, 0, 0]) rt_prism(base, height);
    }
}

// Dome - used for differencing
module dome(width) {
    r = 7;
    ceiling_height = tri_height + base_thickness; // inner height;
    outer_height = r; // height of top of dome from above
    scale([1, ceiling_height/r, 1])
        difference() {
            translate([-r, -r, -r]) cube([width+2*r, 3*outer_height, width+2*r]);
            translate([r, -r, r]) minkowski() {
                cube([width-2*r, r, width-2*r]);
                sphere(r);
            }
        }
}

// Final grabber structure
module cushion_grabber(width) {
    n = width / (3*tri_height); // each row is 3*tri_height, including space
    translate([0, width, 0]) rotate([90, 0, 0])
    difference() {
        union() {
            cube([width, base_thickness, width]);
            translate([tri_height, base_thickness, 0]) prism_rows(tri_height, width, n);
        }
        dome(width);
    }
}

cushion_grabber(125);
//dome(100);

// Cushion Grabber - see README.md for details.
// Author: Joseph M. Joy

function range(stop, start=0,  step=1) = [start: step: stop-1];

// Coords of an isoceles right triangle
function ir_tri(base) = [[0,0], [0, base], [base, 0]];

tri_height = 5;
base_thickness = 2;

// Extruded version
module rt_prism(base, height)  {
    linear_extrude(height) polygon(ir_tri(base));
}

// A row of extruded triangles
module prism_rows(base, height, n) {
    for (i = range(n)) {
         translate([3*base*i, 0, 0]) rt_prism(base, height);
    }
}

// Dome - used for differencing
module dome(width) {
    r = 7;
    ceiling_height = tri_height + base_thickness; // inner height;
    outer_height = r; // height of top of dome from above
    scale([1, ceiling_height/r, 1])
        difference() {
            translate([-r, -r, -r]) cube([width+2*r, 3*outer_height, width+2*r]);
            translate([r, -r, r]) minkowski() {
                cube([width-2*r, r, width-2*r]);
                sphere(r);
            }
        }
}

// Final grabber structure
module cushion_grabber(width) {
    n = width / (3*tri_height); // each row is 3*tri_height, including space
    translate([0, width, 0]) rotate([90, 0, 0])
    difference() {
        union() {
            cube([width, base_thickness, width]);
            translate([tri_height, base_thickness, 0]) prism_rows(tri_height, width, n);
        }
        dome(width);
    }
}

cushion_grabber(200);
//dome(100);


Add OpenSCAD model of a tinwhistle mouthpiece.

//The MIT License (MIT)
//
//Copyright (c) 2014 Loïc Fejoz
//
//Permission is hereby granted, free of charge, to any person obtaining a copy of
//this software and associated documentation files (the "Software"), to deal in
//the Software without restriction, including without limitation the rights to
//use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
//the Software, and to permit persons to whom the Software is furnished to do so,
//subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
//FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
//COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
//IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

inner_tolerance=0.3; // Tolerance for hole

total_length=58;
big_cylinder_length=19;
big_cylinder_radius=16 / 2;
mouthpiece_height=6;
mouthpiece_width=14.5;
mouthpiece_length=12;
bigger_part_length=33;
step_length=5;
pipe_radius=(12.8 / 2) + inner_tolerance;
mouthpiece_inner_height=1.8;
mouthpiece_inner_width=8.8;
hole_width=8.5;
hole_length=6;
hole_angle=25;

sc = 100;
epsilon=5;
really_long=total_length;
difference() {
	union() {
        // Mouthpiece part
        // PROFILE_B = ellipse... =
		translate([0, big_cylinder_radius - mouthpiece_height/2, big_cylinder_length])
		  scale([mouthpiece_width/sc,mouthpiece_height/sc,1])
			cylinder(h = total_length-big_cylinder_length, r1 = sc/2, r2 = sc/2, center = false);

       // big cylinder part
		cylinder(h = big_cylinder_length, r1 = big_cylinder_radius, r2 = big_cylinder_radius, center = false);

       // connection to mouthpiece
		hull() {
          // PROFILE_B =
		  translate([0, big_cylinder_radius - mouthpiece_height/2, total_length-mouthpiece_length])
		    scale([mouthpiece_width/sc,mouthpiece_height/sc,1])
		      cylinder(h = 1, r1 = sc/2, r2 = sc/2, center = false);
		  // PROFILE_A =
		  translate([0,0, bigger_part_length])
		    hull() {
		      translate([0, big_cylinder_radius - mouthpiece_height/2, 0])
		        scale([mouthpiece_width/sc,mouthpiece_height/sc,1])
		          cylinder(h = 1, r1 = sc/2, r2 = sc/2, center = false);
		      cylinder(h = 1, r1 = big_cylinder_radius, r2 = big_cylinder_radius, center = false);
		    }
		}
		// connection to big cylinder
		hull() {
		  // PROFILE_A =
		  translate([0, 0, big_cylinder_length])
		    hull() {
		      translate([0, big_cylinder_radius - mouthpiece_height/2, 0])
		        scale([mouthpiece_width/sc,mouthpiece_height/sc,1])
		          cylinder(h = 1, r1 = sc/2, r2 = sc/2, center = false);
		      cylinder(h = 1, r1 = big_cylinder_radius, r2 = big_cylinder_radius, center = false);
		    }
		  translate([0, 0, big_cylinder_length-step_length])
		     cylinder(h = 1, r1 = big_cylinder_radius, r2 = big_cylinder_radius, center = false);
		}

		// Middle part
		// scale([1, 1, bigger_part_length - big_cylinder_length]) * PROFILE_A =
		translate([0, 0, big_cylinder_length])
		  hull() {
		    translate([0, big_cylinder_radius - mouthpiece_height/2, 0])
		      scale([mouthpiece_width/sc,mouthpiece_height/sc,1])
		        cylinder(h = bigger_part_length - big_cylinder_length, r1 = sc/2, r2 = sc/2, center = false);
		    cylinder(h = bigger_part_length - big_cylinder_length, r1 = big_cylinder_radius, r2 = big_cylinder_radius, center = false);
		  };
		// BOX_1 =
		translate([0, big_cylinder_radius-mouthpiece_inner_height, bigger_part_length-hole_length])
			cube(size=[hole_width, mouthpiece_inner_height, 2*hole_length], center=true);
	};
    // Now create holes...
	translate([0, 0, -epsilon])
		difference() {
			cylinder(h = bigger_part_length+epsilon, r1 = pipe_radius, r2 = pipe_radius, center = false);
           // minus BOX_1
			translate([-hole_width/2, big_cylinder_radius - mouthpiece_height/2, bigger_part_length-hole_length])
				cube(size=[hole_width, 2*mouthpiece_inner_height, 2*hole_length], center=false);
		};
	translate([0, big_cylinder_radius - mouthpiece_height/2, bigger_part_length+total_length/2-epsilon])
		cube(size=[mouthpiece_inner_width, mouthpiece_inner_height, total_length], center =true);
	translate([0, really_long/2, bigger_part_length-hole_length/2])
		cube(size=[hole_width, really_long, hole_length], center=true);
	translate([0, big_cylinder_radius , bigger_part_length - hole_length + sin(hole_angle)*hole_length/2 ])
		rotate([-90+hole_angle, 0, 0])
			translate([0, really_long/2, 0])
				cube(size=[hole_width, really_long, hole_length], center=true);
}

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