add another arch example

add another arch example

// This was inspired by the post found here:
//	http://forum.openscad.org/Parabolic-tube-tp28894p28897.html

module parabola()
{
//    projection(cut=false)
    projection(cut=true)
        rotate([0, 70, 0])
            cylinder(d1=20, d2=0, h = 30);
}

    linear_extrude(50)
        difference()
    {
            parabola();

            translate([-1,0,0])
            parabola()
//            offset(-1)
                parabola();
    }

error: pathspec 'openscad/models/src/main/openscad/shapes/geometry/arc/projection/parabola.scad' did not match any file(s) known to git


Basic model of a single switch with assumed values

/*
    Vitamin: SlideSwitch
    Model of various Slide Switches

    Derived from: http://www.maplin.co.uk/p/double-pole-miniature-fh36p

    Authors:
        Jamie Osborne (@jmeosbn)

    Local Frame:
        Point of origin is through the centre of the bottom hole

    Parameters: none

    Returns:
        Model of a slide switch with mounting holes
*/

module SlideSwitch()
{

    plate_w = 12.5;
    plate_l = 35.0;
    plate_h =  1.0;         // FIXME: ASSUMED VALUE
    centres = 28.0;         // distance between mounting holes

    tang_w  =  5.0;         // FIXME: ASSUMED VALUE
    tang_d  =  5.0;         // FIXME: ASSUMED VALUE
    tang_h  = 10.0;
    tthrow  =  5.5;         // amount tang moves to actuate switch

    body_w  = 24.0;         // FIXME: ASSUMED VALUE
    body_d  = 12.5;         // FIXME: ASSUMED VALUE
    body_h  =  8.0;         // FIXME: ASSUMED VALUE

    tags_w  =  2.5;
    tags_h  =  5.0;
    tags_d  =  1.0;         // FIXME: ASSUMED VALUE
    tags_x  =  8.0;         // FIXME: ASSUMED VALUE
    tags_y  =  8.0;         // FIXME: ASSUMED VALUE

    tags_a  =    2;         // switch poles
    tags_b  =    3;         // switch throw

    // Mounting Plate

    color(Grey60)
    translate([0, centres/2, 0])    // move origin to bottom hole
    linear_extrude(plate_h)
    {
        difference()
        {
            // mounting plate
            // TODO: Show rounded corners?
            square(size=[plate_w, plate_l], center=true);

            // mounting holes (M3 tapped)
            translate([0, centres/2, 0])
                circle(d=3);
            translate([0, -centres/2, 0])
                circle(d=3);

            // tang hole
            square(size=[tang_w, tang_d + tthrow], center=true);
        }
    }

    // Switch Tang

    color(Grey50)
    translate([0, centres/2 + tthrow/2, 0])
    linear_extrude(tang_h)
    {
        square(size=[tang_w, tang_d], center=true);
    }

    // Switch Body

    color(Grey50)
    translate([0, centres/2, -body_h])
    linear_extrude(body_h)
    {
        square(size=[body_d, body_w], center=true);
    }

    // Switch Tags

    color("silver")
    translate([-tags_x * (tags_a-1)/2, centres/2-tags_y*(tags_b-1)/2, -body_h - tags_h])
    linear_extrude(tags_h)
    {
        for (x=[0 : tags_a-1], y=[0 : tags_b-1]) {
            translate([x * tags_x, y * tags_y, 0]) {
                square(size=[tags_d, tags_w], center=true);
            }
        }
    }
}

// Example Usage
// SlideSwitch();

/*
    Vitamin: SlideSwitch
    Model of various Slide Switches

    Derived from: http://www.maplin.co.uk/p/double-pole-miniature-fh36p

    Authors:
        Jamie Osborne (@jmeosbn)

    Local Frame:
        Point of origin is through the centre of the bottom hole

    Parameters: none

    Returns:
        Model of a slide switch with mounting holes
*/

module SlideSwitch()
{

}

// Example Usage
// SlideSwitch();


zaxis/motormount: refactoring

zaxis/motormount: refactoring

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

use <thing_libutils/triangles.scad>

include <config.scad>

// inner_d, outer_d, thread
zaxis_nut = [20*mm, 36.5*mm, 8*mm];

zaxis_nut_mount_outer = zaxis_nut[1]/2 + zaxis_bearing[1]/2 + 3;

// place z rod on edge of motor
/*zaxis_rod_screw_distance_x = max(zaxis_nut_mount_outer, zaxis_rod_d/2 + lookup(NemaSideSize,zaxis_motor)/2);*/
zaxis_rod_screw_distance_x = zaxis_nut_mount_outer;

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

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

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

zmotor_mount_clamp_width = zmotor_mount_clamp_dist+zmotor_mount_clamp_thread_dia*3;

zaxis_leadscrew_offset_x = zmotor_w/2 + zmotor_mount_motor_offset;

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])
                            rotate([90,90,0])
                            Right_Angled_Triangle(a=zmotor_mount_rod_offset_x-zmotor_mount_thickness, b=main_lower_dist_z+extrusion_size+zaxis_motor_offset_z, height=zmotor_mount_thickness, centerXYZ=[0,0,1]);

                        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])
                        fncylindera(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])
                        fncylindera(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_w/2+zmotor_mount_motor_offset,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])
            fncylindera(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.1, zmotor_mount_clamp_nut_dia*1.01, zmotor_mount_clamp_nut_dia*1.01], extrasize=[0,0,zmotor_mount_thickness_h], extrasize_align=[0,0,1]);

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

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

use <thing_libutils/triangles.scad>

include <config.scad>

// inner_d, outer_d, thread
zaxis_nut = [20*mm, 36.5*mm, 8*mm];

zaxis_nut_mount_outer = zaxis_nut[1]/2 + zaxis_bearing[1]/2 + 3;

// place z rod on edge of motor
/*zaxis_rod_screw_distance_x = max(zaxis_nut_mount_outer, zaxis_rod_d/2 + lookup(NemaSideSize,zaxis_motor)/2);*/
zaxis_rod_screw_distance_x = zaxis_nut_mount_outer;

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

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

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

zmotor_mount_clamp_width = zmotor_mount_clamp_dist+zmotor_mount_clamp_thread_dia*3;

zaxis_leadscrew_offset_x = zmotor_w/2 + zmotor_mount_motor_offset;

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

module zaxis_motor_mount(show_motor=false)
{

    difference()
    {
        // top plate
        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
            difference()
            {
                cubea([zmotor_mount_thickness, zmotor_w, zmotor_h], align=[1,0,-1]);
                // cutout for motor cables
                translate([0,0,-20*mm])
                cubea([zmotor_mount_thickness*3, 20*mm, zmotor_h], align=[0,0,-1]);
            }

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

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

            // bottom mount plate
            difference()
            {
                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]);

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

            // side triangles
            for(i=[-1,1])
            {
                translate([zmotor_mount_thickness, i*((zmotor_w/2)+zmotor_mount_thickness/2), 0])
                    rotate([90,90,0])
                    Right_Angled_Triangle(a=zmotor_mount_rod_offset_x-zmotor_mount_thickness, b=main_lower_dist_z+extrusion_size+zaxis_motor_offset_z, height=zmotor_mount_thickness, centerXYZ=[0,0,1]);

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

        // cut out motor mount holes etc
        translate([zmotor_w/2+zmotor_mount_motor_offset,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])
            fncylindera(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.1, zmotor_mount_clamp_nut_dia*1.01, zmotor_mount_clamp_nut_dia*1.01], extrasize=[0,0,zmotor_mount_thickness_h], extrasize_align=[0,0,1]);

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


misc: Rename sum_vec to v_sum

misc: Rename sum_vec to v_sum

use <scad-utils/linalg.scad>
use <scad-utils/lists.scad>

function posvec(path_vec) = [for(v=path_vec) translation_part(v)];
function posvec_x(path_vec) = [for(v=path_vec) translation_part(v)[0]];
function posvec_y(path_vec) = [for(v=path_vec) translation_part(v)[1]];
function posvec_z(path_vec) = [for(v=path_vec) translation_part(v)[2]];

function vec_i(v3,i) = [for(v=v3) v[i]];
function vec_0(v3) = vec_i(v3,0);
function vec_1(v3) = vec_i(v3,1);
function vec_2(v3) = vec_i(v3,2);

function vec_add(vec,v) = [for(vv=vec) vv+v];

function v_itrlen(vec) = [0:1:len(vec)-1];

function range1(v1) = [min(v1), max(v1)];
function range3(v3) = [range1(vec_0(v3)), range1(vec_1(v3)), range1(vec_2(v3))];
function bbox(r) = [ [r[0][0],r[1][0],r[2][0]], [r[0][1],r[1][1],r[2][1]] ];
function transform_pp(vec_m, t_pre, t_post) = [for(m=vec_m) (t_pre*m)*t_post];
function transform_pre(vec_m, t) = [for(m=vec_m) t*m];
function transform_post(vec_m, t) = [for(m=vec_m) m*t];

// sum a vector up to position i
function v_sum(v, i) = i >= 0 ? v[i] + sum_vec(v, i - 1) : 0;

// filter/remove a val from a vec
function filter(vec,val=undef) = [for(v=vec) if(v!=val) v];

function vec_pair_double_transform_post(vec,t1,t2)=
    flatten(
        [for(v=vec)
            [transform_post(v,t1),transform_post(v,t2)]
        ]);

function vec_pair_double(vec)=flatten([for(v=vec) [v,v] ]);

use <scad-utils/linalg.scad>
use <scad-utils/lists.scad>

function posvec(path_vec) = [for(v=path_vec) translation_part(v)];
function posvec_x(path_vec) = [for(v=path_vec) translation_part(v)[0]];
function posvec_y(path_vec) = [for(v=path_vec) translation_part(v)[1]];
function posvec_z(path_vec) = [for(v=path_vec) translation_part(v)[2]];

function vec_i(v3,i) = [for(v=v3) v[i]];
function vec_0(v3) = vec_i(v3,0);
function vec_1(v3) = vec_i(v3,1);
function vec_2(v3) = vec_i(v3,2);

function vec_add(vec,v) = [for(vv=vec) vv+v];

function v_itrlen(vec) = [0:1:len(vec)-1];

function range1(v1) = [min(v1), max(v1)];
function range3(v3) = [range1(vec_0(v3)), range1(vec_1(v3)), range1(vec_2(v3))];
function bbox(r) = [ [r[0][0],r[1][0],r[2][0]], [r[0][1],r[1][1],r[2][1]] ];
function transform_pp(vec_m, t_pre, t_post) = [for(m=vec_m) (t_pre*m)*t_post];
function transform_pre(vec_m, t) = [for(m=vec_m) t*m];
function transform_post(vec_m, t) = [for(m=vec_m) m*t];

// sum a vector up to position iV
function sum_vec(v, i) = i >= 0 ? v[i] + sum_vec(v, i - 1) : 0;

// filter/remove a val from a vec
function filter(vec,val=undef) = [for(v=vec) if(v!=val) v];

function vec_pair_double_transform_post(vec,t1,t2)=
    flatten(
        [for(v=vec)
            [transform_post(v,t1),transform_post(v,t2)]
        ]);

function vec_pair_double(vec)=flatten([for(v=vec) [v,v] ]);


metric/screw: fix nut

metric/screw: fix nut

include <shapes.scad>

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

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

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

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

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

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

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

module screw_head_cut(nut=MHexNutM3, tolerance=1.05, h=1000, orient=[0,0,1], align=[0,0,0])
{
    screw_head(nut=nut, tolerance=tolerance, override_h=1000, orient=orient, align=align);
}

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

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

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

if(false)
{
    nut1 = MHexNutM3;
    nut2 = MHexNutM5;

    box_h = 10;
    difference()
    {
        cubea([50,10,box_h], align=[1,1,-1]);

    #union()
        {
            translate([5,0,0])
                screw_cut(nut=nut1, h=box_h, head_embed=false, orient=[0,0,-1], align=[0,0,-1]);

            translate([15,0,0])
                screw_cut(nut=nut1, h=box_h*mm, nut_offset=0*mm, head_embed=true, orient=[0,0,-1], align=[0,0,-1]);

            translate([25,0,0])
                screw_cut(nut=nut1, h=box_h*mm, nut_offset=3*mm, head_embed=false, orient=[0,0,-1], align=[0,0,-1]);
        }

    }

}

include <shapes.scad>

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

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

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

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

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

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

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

module screw_head_cut(nut=MHexNutM3, tolerance=1.05, h=1000, orient=[0,0,1], align=[0,0,0])
{
    screw_head(nut=nut, tolerance=tolerance, override_h=1000, orient=orient, align=align);
}

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

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

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

if(false)
{
    nut1 = MHexNutM3;
    nut2 = MHexNutM5;

    box_h = 10;
    difference()
    {
        cubea([50,10,box_h], align=[1,1,-1]);

    #union()
        {
            translate([5,0,0])
                screw_cut(nut=nut1, h=box_h, head_embed=false, orient=[0,0,-1], align=[0,0,-1]);

            translate([15,0,0])
                screw_cut(nut=nut1, h=box_h*mm, nut_offset=0*mm, head_embed=true, orient=[0,0,-1], align=[0,0,-1]);

            translate([25,0,0])
                screw_cut(nut=nut1, h=box_h*mm, nut_offset=3*mm, head_embed=false, orient=[0,0,-1], align=[0,0,-1]);
        }

    }

}


One piece version of E3D fan duct

One piece version of E3D fan duct

$fa=3;
$fs=0.2;

radiator_height = 26;
radiator_diameter = 22;
radiator_radius = radiator_diameter / 2;
thin_wall_radius = 1;
radiator_cut_angle = 65;

//%translate([-22, -19.6, 25.9])
//    rotate([-90, 0, 0])
//        import("Part1 - E3D_DoubleDuct2.stl");
//color("green") cylinder(r = radiator_diameter/2, h = radiator_height);
//%translate([0,0,40]) import("Effector_E3d.stl");

//%rotate([0,0,90]) translate([5.195,-3.384,24.52]) import("E3D_v6_To_Spec.stl");
//%translate([19.35,0,26.2]) rotate([0,142,180]) import("Optional - Duct_40mm.stl");

//cylinder(r=1.4, h=10, center=true);

// fan mount part
fan_width = 40;
fan_wall_thickness = 1;
fan_wall_spacing = 1;
fan_mount_corner_radius = 3;
fan_mount_distance_to_center = 35;
fan_plate_thickness = 1;
fan_duct_height = fan_width + 2 * fan_wall_thickness + 2 * fan_wall_spacing;

module fan_mount() {
    fan_mount_thickness = 5 + fan_plate_thickness;
    module outer_hull() {
        linear_extrude(height=fan_mount_thickness) {
            offset(r=fan_mount_corner_radius + fan_wall_spacing + fan_wall_thickness)
            offset(delta=-fan_mount_corner_radius)
                square([fan_width, fan_width], true);
        };
    }
    module inner_hull() {
        translate([0,0,fan_plate_thickness])
        linear_extrude(height=fan_mount_thickness) {
            offset(r=fan_mount_corner_radius + fan_wall_spacing)
            offset(delta=-fan_mount_corner_radius)
                square([fan_width, fan_width], true);
        };
    }
   // cube([fan_width, fan_width, fan_plate_thickness], true);
    difference() {
        outer_hull();
        inner_hull();
    }
}
//!fan_mount();

module fan_screws_mold() {
    hole_dia = 4;
    hole_screw_head_dia = 8;
    hole_spacing = 32;

    for(x=[-hole_spacing/2:hole_spacing:hole_spacing/2])
        for(y=[-hole_spacing/2:hole_spacing:hole_spacing/2])
            union() {
                translate([x,y,50-1])
                    cylinder(r=hole_dia/2, h=100, center=true);
                translate([x*2,y*2,0])
                    mirror([0,0,1])
                    linear_extrude(height=fan_mount_distance_to_center, scale=0.7) {
                        minkowski() {
                            square([hole_spacing, hole_spacing],true);
                            circle(r=hole_screw_head_dia/2, center=true);
                        }
                    }
            }
}
//!fan_screws_mold();

module fan_mount_outer_hull_mold() {
    module outer_hull() {
        linear_extrude(height=200) {
            offset(r=fan_mount_corner_radius + fan_wall_spacing + fan_wall_thickness)
            offset(delta=-fan_mount_corner_radius)
                square([fan_width, fan_width], true);
        };
    }
    translate([0,0,-100])
        outer_hull();
}
//!fan_mount_outer_hull_mold();

module fan_mount_position() {
    translate([0,-fan_mount_distance_to_center,0])
        rotate([80,0,0])
            translate([0,fan_duct_height/2,0])
                children();
}

module fan_mount_duct_part_mold() {
    fan_mount_position()
        translate([0,0,-50+fan_plate_thickness])
            cube([100,100,100],true);
}
//!fan_mount_duct_part_mold();

// A form of a radiator to be cut from other parts
module radiator_trunk() {
    module holding_ring() {
        ring_number = 4;
        translate([0, 0, 0.75 + 2.5 * ring_number])
            rotate_extrude($fn=100)
                translate([radiator_diameter / 2, 0, 0])
                    polygon ([[-1,0.5], [-1,1.5], [1,2], [1,0]]);
    }

    difference () {
        translate([0, 0, - 2*radiator_height])
            cylinder(r = radiator_diameter / 2, h = radiator_height * 4);
        holding_ring();
    }
}
//!radiator_trunk();

module mounting_plates() {
    width = 44;
    height = 22;
    thickness = 5;
    hole_x_distance = width / 2 - 4;
    hole_y1_distance = 6;
    hole_y2_distance = hole_y1_distance + 10;
    hole_radius = 1.25;
    difference() {
        minkowski() {
            translate([0, -thickness, height / 2]) cube([width - 2, thickness - 1, height - 2], center=true);
            rotate([90,0,0]) cylinder(r=1, h=1, center=true);
        }
        translate([hole_x_distance,0,hole_y1_distance])
            rotate([90,0,0]) cylinder(r=hole_radius, h=thickness*100, center=true);
        translate([hole_x_distance,0,hole_y2_distance])
            rotate([90,0,0]) cylinder(r=hole_radius, h=thickness*100, center=true);
        translate([-hole_x_distance,0,hole_y1_distance])
            rotate([90,0,0]) cylinder(r=hole_radius, h=thickness*100, center=true);
        translate([-hole_x_distance,0,hole_y2_distance])
            rotate([90,0,0]) cylinder(r=hole_radius, h=thickness*100, center=true);
        //radiator_trunk();
    };
}
//!mounting_plates();

// A triangle-like shape cut from the front so air output is free
module radiator_cut_2D() {
    polygon([[0,0],
        [-r*sin(radiator_cut_angle),r*cos(radiator_cut_angle)],
        [-r,r],
        [r,r],
        [r*sin(radiator_cut_angle),r*cos(radiator_cut_angle)]]);
};

module holding_arms_half_2D() {
    minkowski() {
            r = radiator_diameter;  // much bigger then radiator radius
        intersection() {
            circle(radiator_radius + thin_wall_radius, center = true);
            polygon([[0,0],
                [r*sin(radiator_cut_angle),r*cos(radiator_cut_angle)],
                [r,r],
                [r,-r],
                [0,-r]]);
        }
        circle(r = thin_wall_radius);
    };
};

module trunk_half_2D() {
    hull () {
        translate([0, -fan_mount_distance_to_center, 0]) square([fan_width + fan_wall_thickness*2+ fan_wall_spacing*2,1],center=true);
        holding_arms_half_2D();
    }
}

module trunk_2D() {
    trunk_half_2D();
    mirror([1,0,0]) trunk_half_2D();
}

module holding_arms() {
    linear_extrude(height=26) {
        holding_arms_half_2D();
        mirror([1,0,0]) holding_arms_half_2D();
    }
}

module fan_duct_zy_mold() {
    rotate([90,0,90])
        linear_extrude(h=200,center=true)
            polygon([
                [100,0],
                [100,radiator_height],
                [0,radiator_height],
                [-9,radiator_height+1],
                [-9,100],
                [-100,0]]);
}

module fan_duct_trunk() {
    difference() {
        union() {
            intersection() {
                union() {
                    air_duct_wall_mold();
                    holding_arms();
                }
                //linear_extrude(height=50) trunk_2D();
                //fan_mount_position() fan_mount_outer_hull_mold();
                fan_duct_zy_mold();
                fan_mount_duct_part_mold();

            }
            fan_mount_position() fan_mount();
        }
        fan_mount_position() fan_screws_mold();
        radiator_trunk();
    }
}

module fan_screws_walls_mold() {
    intersection() {
        fan_duct_trunk();
        fan_mount_position() minkowski() {
            fan_screws_mold();
            cube([1,1,fan_plate_thickness*2],true);
        }
    }
}

module air_duct_mold() {
    module back_plate() {
        fan_mount_position() translate([0,0,1]) cylinder(r=fan_width/2-1, h=0.1, center=true);
    }
    module front_plate() {
        translate([-radiator_diameter/2,-radiator_diameter/2,1])
            cube([radiator_diameter, radiator_diameter/2, radiator_height-2]);
    }
    module ideal_duct() {
        hull() {
            front_plate();
            back_plate();
        }
    }
    intersection() {
        ideal_duct();
        rotate([90,0,90])
        linear_extrude(h=200,center=true)
            polygon([
                [100,0],
                [100,radiator_height-1],
                [-radiator_diameter/2+1,radiator_height-1],
                [-100,100],
                [-100,0]]);

    }
}

module air_duct_wall_mold() {
    minkowski() {
        air_duct_mold();
        //cube([4,4,4],true);
        sphere(r=2);
    }
}

module final_part() {
    union() {
        difference() {
            fan_duct_trunk();
            air_duct_mold();
        }
        fan_screws_walls_mold();
//        difference() {
//            mounting_plates();
//            radiator_trunk();
//            air_duct_mold();
//        }
    }
}

color("lightblue")final_part();
//            color("lightblue") mounting_plates();

module side_fan_mount_position() {
    translate([29,0,1])
        rotate([0,60,0])
            //translate([0,fan_duct_height/2,0])
                children();
}

module side_fan_mount_duct_part_mold() {
    side_fan_mount_position()
        translate([0,0,-50+fan_plate_thickness])
            cube([100,100,100],true);
}

module side_air_duct_mold() {
    module back_plate() {
        side_fan_mount_position() translate([0,0,1]) cylinder(r=fan_width/2-1, h=0.1, center=true);
    }
    module front_plate() {
        translate([14,0,-15.5])
            cube([0.1,fan_width-10, 3],true);
    }
    module ideal_duct() {
        hull() {
            front_plate();
            back_plate();
        }
    }
    difference() {
        ideal_duct();
        rotate([90,0,0])
        linear_extrude(h=200,center=true)
            polygon([
                [21,30],
                [19,-1],
                [12, -20],
                [-100,0]]);

    }
}

module side_air_duct_wall_mold() {
    minkowski() {
        side_air_duct_mold();
        //cube([4,4,4],true);
        sphere(r=1.5);
    }
}

module side_fan_duct_trunk() {
    difference() {
        union() {
            intersection() {
                side_air_duct_wall_mold();
                side_fan_mount_duct_part_mold();
                translate([64,0,32]) cube([100,100,100],true);
            }
            side_fan_mount_position() fan_mount();
        }
        side_fan_mount_position() fan_screws_mold();
    }
}
module side_fan_screws_walls_mold() {
    intersection() {
        side_fan_duct_trunk();
        side_fan_mount_position() minkowski() {
            fan_screws_mold();
            cube([1,1,fan_plate_thickness*2],true);
        }
    }
}

module side_joint() {
    difference() {
        intersection() {
            translate([0,-9,0])
                rotate([90,0,0])
                    linear_extrude(height=5,center=true)
                        polygon([
                            [30,20],
                            [30,0],
                            [10, 0],
                            [10,20]]);
            side_fan_mount_duct_part_mold();
        }
        side_air_duct_mold();
        radiator_trunk();
        air_duct_mold();
    }

}

module side_final_part() {
    union() {
        difference() {
            side_fan_duct_trunk();
            side_air_duct_mold();
        }
        side_fan_screws_walls_mold();
        side_joint();
    }
}
side_final_part();
mirror([1,0,0]) side_final_part();

//side_fan_duct_trunk();
//side_fan_mount_position() fan_mount();
//color("green")side_air_duct_wall_mold();
//side_air_duct_wall_mold();
//color("red")cube([30,1,1]);
//translate([0,0,-20])color("red") cube([100,40,2], true);
module side_mounting_plates() {
    width = 9;
    height = 22;
    thickness = 5;
    hole_x_distance = width / 2 - 4;
    hole_y1_distance = 6;
    hole_y2_distance = hole_y1_distance + 10;
    hole_radius = 1.5;
    translate([18.5,0,0])
    difference() {
        minkowski() {
            translate([0, 0, height / 2]) cube([width - 2, thickness - 1, height - 2], center=true);
            rotate([90,0,0]) cylinder(r=1, h=1, center=true);
        }
        translate([-hole_x_distance,0,hole_y1_distance])
            rotate([90,0,0]) cylinder(r=hole_radius, h=thickness*100, center=true);
        translate([-hole_x_distance,0,hole_y2_distance])
            rotate([90,0,0]) cylinder(r=hole_radius, h=thickness*100, center=true);
        //radiator_trunk();
    };
}
//side_mounting_plates();

error: pathspec 'kossel/e3d-fan-duct-joined.scad' did not match any file(s) known to git