bearings: add align param

bearings: add align param

use <thing_libutils/shapes.scad>;

// radial bearings
// inner_d, outer_d, length/width (thickness)
bearing_608 = [8,22,7];
bearing_626 = [8,19,6];
bearing_625 = [5,16,5];
bearing_608 = [8,22,7];
bearing_MR128 = [8,12,3.5];
bearing_MR115 = [5,11,4];
bearing_MR105 = [5,10,4];

// linear bearings
// inner_d, outer_d, length, clips_len, clips_d

// http://www.igus.eu/wpck/12157/Motek14_N14_6_3_Vollkunststofflager?L=en
bearing_igus_rj4jp_01_08 = [8,15,24,17.5,14.3];
bearing_igus_rj4jp_01_10 = [10,19,29,22.5,18];
bearing_igus_rj4jp_01_12 = [12,21,30,23.5,20];
bearing_igus_rj4jp_01_16 = [16,28,37,26.5,26.6];
bearing_igus_rj4jp_01_20 = [20,32,42,30.5,30.3];

module bearing(bearing_type, orient=[0,0,1], align=[0,0,0])
{
    size_align(size=[bearing_type[1],bearing_type[1],bearing_type[2]], align=align ,orient=orient)
    difference()
    {
        // outer
        fncylindera(h=bearing_type[2], d=bearing_type[1], align=[0,0,0]);
        // inner
        fncylindera(h=bearing_type[2]+1, d=bearing_type[0], align=[0,0,0]);
        // clips
        if(len(bearing_type) > 3)
        {
            clip_depth=.5;
            for(j=[-1,1])
            translate([0,0,j*bearing_type[3]/2])
            difference()
            {
                fncylindera(h=1, d=bearing_type[2]+1, align=[0,0,0]);
                fncylindera(h=2, d=bearing_type[4]-clip_depth, align=[0,0,0]);
            }

        }
    }
}

module bearing_mount_holes(bearing_type, orient=[1,0,0], ziptie_dist=undef, show_zips=false)
{
    ziptie_dist_ = ziptie_dist==undef?bearing_type[3]/2:ziptie_dist;
    orient(orient)
    {
        // Main bearing cut
        difference()
        {
            fncylindera(h=bearing_type[2], d=bearing_type[1]*rod_fit_tolerance, orient=[0,0,1]);
        }

        difference()
        {
            union()
            {
                for(i=[-1,1])
                translate([0,0,i*ziptie_dist_])
                fncylindera(h=ziptie_width, d=bearing_type[1]+ziptie_bearing_distance+ziptie_thickness, orient=[0,0,1]);
            }
            fncylindera(h=bearing_type[2], d=bearing_type[1]+ziptie_bearing_distance, orient=[0,0,1]);
        }

        // for linear rod
        fncylindera(d=bearing_type[0]*1.5, h=100, orient=[0,0,1]);

        %if(show_zips)
        {
            for(i=[-1,1])
            translate([0,0,i*ziptie_dist_])
            fncylindera(h=ziptie_width, d=bearing_type[1]+ziptie_thickness, orient=[0,0,1]);
        }
    }
}

use <thing_libutils/shapes.scad>;

// radial bearings
// inner_d, outer_d, length/width (thickness)
bearing_608 = [8,22,7];
bearing_626 = [8,19,6];
bearing_625 = [5,16,5];
bearing_608 = [8,22,7];
bearing_MR128 = [8,12,3.5];
bearing_MR115 = [5,11,4];
bearing_MR105 = [5,10,4];

// linear bearings
// inner_d, outer_d, length, clips_len, clips_d

// http://www.igus.eu/wpck/12157/Motek14_N14_6_3_Vollkunststofflager?L=en
bearing_igus_rj4jp_01_08 = [8,15,24,17.5,14.3];
bearing_igus_rj4jp_01_10 = [10,19,29,22.5,18];
bearing_igus_rj4jp_01_12 = [12,21,30,23.5,20];
bearing_igus_rj4jp_01_16 = [16,28,37,26.5,26.6];
bearing_igus_rj4jp_01_20 = [20,32,42,30.5,30.3];

module bearing(bearing_type, orient=[0,0,1])
{
    orient(orient)
    difference()
    {
        // outer
        fncylindera(h=bearing_type[2], d=bearing_type[1], align=[0,0,0]);
        // inner
        fncylindera(h=bearing_type[2]+1, d=bearing_type[0], align=[0,0,0]);
        // clips
        if(len(bearing_type) > 3)
        {
            clip_depth=.5;
            for(j=[-1,1])
            translate([0,0,j*bearing_type[3]/2])
            difference()
            {
                fncylindera(h=1, d=bearing_type[2]+1, align=[0,0,0]);
                fncylindera(h=2, d=bearing_type[4]-clip_depth, align=[0,0,0]);
            }

        }
    }
}

module bearing_mount_holes(bearing_type, orient=[1,0,0], ziptie_dist=undef, show_zips=false)
{
    ziptie_dist_ = ziptie_dist==undef?bearing_type[3]/2:ziptie_dist;
    orient(orient)
    {
        // Main bearing cut
        difference()
        {
            fncylindera(h=bearing_type[2], d=bearing_type[1]*rod_fit_tolerance, orient=[0,0,1]);
        }

        difference()
        {
            union()
            {
                for(i=[-1,1])
                translate([0,0,i*ziptie_dist_])
                fncylindera(h=ziptie_width, d=bearing_type[1]+ziptie_bearing_distance+ziptie_thickness, orient=[0,0,1]);
            }
            fncylindera(h=bearing_type[2], d=bearing_type[1]+ziptie_bearing_distance, orient=[0,0,1]);
        }

        // for linear rod
        fncylindera(d=bearing_type[0]*1.5, h=100, orient=[0,0,1]);

        %if(show_zips)
        {
            for(i=[-1,1])
            translate([0,0,i*ziptie_dist_])
            fncylindera(h=ziptie_width, d=bearing_type[1]+ziptie_thickness, orient=[0,0,1]);
        }
    }
}


pulley: misc

pulley: misc

include <thing_libutils/units.scad>
include <thing_libutils/shapes.scad>

// h, full_h, inner_d, outer_d, walls, bore
pulley_2GT_20T_idler = [8.65*mm, undef, 12*mm, 18*mm, 1*mm, 5*mm];
pulley_2GT_20T       = [8.65*mm, 16*mm, 12*mm, 16*mm, 1.15*mm, 5*mm];

module pulley(pulley=pulley_2GT_20T, flip=false, align=[0,0,0], orient = [0,0,1])
{
    is_idler = pulley[1] == undef;
    pulley_full(
            is_idler=is_idler,
            h=pulley[0],
            full_h=is_idler?undef:pulley[1],
            inner_d=pulley[2],
            outer_d=pulley[3],
            walls=pulley[4],
            bore=pulley[5],
            flip=flip,
            align=align,
            orient=orient
            );
}

module pulley_full(h, inner_d, outer_d, bore, walls, is_idler=false, full_h, flip=false, align=[0,0,0], orient = [0,0,1])
{
    size_align(size=[outer_d, outer_d, full_h==undef?h:full_h], align=align, orient=orient)
    {
        //for flipping
        mirror([0,0,flip?-1:0])
        //center
        translate([0,0,full_h==undef?-h/2:-full_h/2])
        difference()
        {
            union()
            {
                fncylindera(d = outer_d, h = walls, align=[0,0,1], orient=[0,0,1]);

                translate([0,0,0])
                fncylindera(d = inner_d, h = h, align=[0,0,1], orient=[0,0,1]);

                translate([0,0,h-walls])
                fncylindera(d = outer_d, h = walls, align=[0,0,1], orient=[0,0,1]);

                translate([0,0,h])
                if(!is_idler)
                {
                    fncylindera(d = outer_d, h = full_h-h, align=[0,0,1], orient=[0,0,1]);
                }
            }
            translate([0,0,-.1])
            fncylindera(d = bore, h = full_h+.2, align=[0,0,1], orient=[0,0,1]);
        }
    }
}

if(false)
{
    /*pulley(pulley_2GT_20T_idler, align=[0,0,1], orient=[0,0,1]);*/
    pulley(pulley_2GT_20T, align=[0,0,1], orient=[0,0,-1], flip=false);
    /*pulley(pulley_2GT_20T, align=[0,0,-1], orient=[0,0,1], flip=false);*/
}

include <thing_libutils/units.scad>
include <thing_libutils/shapes.scad>

// h, full_h, inner_d, outer_d, walls, bore
pulley_2GT_20T_idler = [8.65*mm, undef, 12*mm, 18*mm, 1*mm, 5*mm];
pulley_2GT_20T       = [8.65*mm, 16*mm, 12*mm, 16*mm, 1.15*mm, 5*mm];

module pulley(pulley=pulley_2GT_20T, flip=false, align=[0,0,0], orient = [0,0,1])
{
    is_idler = pulley[1] == undef;
    pulley_full(
            is_idler=is_idler,
            h=pulley[0],
            full_h=is_idler?undef:pulley[1],
            inner_d=pulley[2],
            outer_d=pulley[3],
            walls=pulley[4],
            bore=pulley[5],
            flip=flip,
            align=align,
            orient=orient
            );
}

module pulley_full(h, inner_d, outer_d, bore, walls, is_idler=false, full_h, flip=false, align=[0,0,0], orient = [0,0,1])
{
    size_align(size=[outer_d, outer_d, full_h==undef?h:full_h], align=align, orient=orient)
    {
        //for flipping
        mirror([0,0,flip?-1:0])
        //center
        translate([0,0,full_h==undef?-h/2:-full_h/2])
        difference()
        {
            union()
            {
                fncylindera(d = outer_d, h = walls, align=[0,0,1], orient=[0,0,1]);

                translate([0,0,0])
                fncylindera(d = inner_d, h = h, align=[0,0,1], orient=[0,0,1]);

                translate([0,0,h-walls])
                fncylindera(d = outer_d, h = walls, align=[0,0,1], orient=[0,0,1]);

                translate([0,0,h])
                if(!is_idler)
                {
                    fncylindera(d = outer_d, h = full_h-h, align=[0,0,1], orient=[0,0,1]);
                }
            }
            translate([0,0,-.1])
            fncylindera(d = bore, h = full_h+.2, align=[0,0,1], orient=[0,0,1]);
        }
    }
}

/*debug = true;*/
/*if(debug)*/
/*{*/
    /*pulley(pulley_2GT_20T_idler, align=[0,0,0], orient=[0,0,1]);*/
    /*pulley(pulley_2GT_20T, align=[0,0,1], orient=[0,0,1], flip=false);*/
    /*pulley(pulley_2GT_20T, align=[0,0,-1], orient=[0,0,1], flip=false);*/
/*}*/


extended 2d library

extended 2d library

//Simple Objects
module ring(r=5,d=1) {
	difference() {
		circle(r=r);
		circle(r=r-d);
	}
}
//Translation Modules
module tr_xy(x,y=0) {
	if(y==0) {
		for(i=[-1,1])for(j=[-1,1])translate([x*i,x*j])children();
	} else {
		for(i=[-1,1])for(j=[-1,1])translate([x*i,y*j])children();
	}
}
module rot_x(x=0,rotation=90,off=0) {
	for(i=[0:360/rotation-1])rotate(a=[0,0,rotation*i+off])translate([x,0])children();
}
//Support for Holowed Models
module support(comb=false) {
    intersection() {
        if(comb==false)support_raw();
        if(comb==true)support_honeycomb();
        children();
    }
}
module support_raw(x=20,y=20,d=1.1,t=0.15) {
    for(i=[-1,1])for(j=[0:d:x/2])translate([i*j,0])square([t,y],center=true);
    for(i=[-1,1])for(j=[0:d:x/2])translate([0,i*j])square([x,t],center=true);
}
module support_honeycomb(x=10,y=10,r=0.7,d=0.1,fn=6) {
    for(k=[-1,1])for(l=[0:2*(r+r*sin(30)-d):x]){
        for(i=[1,-1])for(j=[0:2*r*cos(30)-d:y]) {
            translate([k*l,i*j])comb(r,d,fn);
            translate([k*(l+r+r*sin(30)-d),i*(j+cos(30)*r-0.5*d)])comb(r,d,fn);
        }
    }
}
module comb(r,d,fn) {
    difference() {
        circle(r=r,$fn=fn);
        circle(r=r-d,$fn=fn);
    }
}

module ring(r=5,d=1) {
	difference() {
		circle(r=r);
		circle(r=r-d);
	}
}
module tr_xy(x,y=0) {
	if(y==0) {
		for(i=[-1,1])for(j=[-1,1])translate([x*i,x*j])children();
	} else {
		for(i=[-1,1])for(j=[-1,1])translate([x*i,y*j])children();
	}
}
module rot_x(x) {
	for(i=[0:3])rotate(a=[0,0,90*i])translate([x,0])children();
}


Start a redo of the switch mount in openscad

$fn=100;

button_radius = 49;
hole_radius = 14.5;
table_padding = 40;
extra_padding = 2;
bottom_padding = 30;

wall_thickness = 4;

mount_height = table_padding + extra_padding + button_radius + hole_radius + bottom_padding;
mount_depth = 50;
mount_width = (hole_radius * 2) + (bottom_padding * 2);

// difference() {
//     cube(size=[mount_width, mount_height, mount_depth]);

//     translate([wall_thickness, wall_thickness, wall_thickness])
//     cube(size=[mount_width - (wall_thickness*2), mount_height, mount_depth]);
// }

module screw_mount() {
    difference() {
        cube([10, wall_thickness, 10]);

        rotate([90, 0, 0])
        translate([5, 5, -wall_thickness-1])
        cylinder(r=2, h=wall_thickness+2);
    }
}

module bottom() {
    hull() {
        // lower left
        translate([wall_thickness*2, wall_thickness*2, 0])
        cylinder(r=wall_thickness*2, h=wall_thickness);

        // lower right
        translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
        cylinder(r=wall_thickness*2, h=wall_thickness);

        // upper right
        translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
        cube(size=[wall_thickness*2, wall_thickness*2, wall_thickness]);

        // upper left
        translate([0, mount_height-(wall_thickness*2), 0])
        cube(size=[wall_thickness*2, wall_thickness*2, wall_thickness]);
    }
}

module sides() {
    difference() {
        hull() {
            // lower left
            translate([wall_thickness*2, wall_thickness*2, 0])
            cylinder(r=wall_thickness*2, h=mount_depth);

            // lower right
            translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
            cylinder(r=wall_thickness*2, h=mount_depth);

            // upper right
            translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness*2, wall_thickness*2, mount_depth]);

            // upper left
            translate([0, mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness*2, wall_thickness*2, mount_depth]);
        }

        hull() {
            // lower left
            translate([wall_thickness*2, wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=mount_depth+1);

            // lower right
            translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=mount_depth+1);

            // upper right
            translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, mount_depth+1]);

            // upper left
            translate([wall_thickness, mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, mount_depth+1]);
        }
    }

    intersection() {
        translate([wall_thickness, wall_thickness, 0])
        cube([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), mount_depth]);

        union() {
            translate([wall_thickness, wall_thickness, mount_depth-6])
            cylinder(r=9, h=6);
            translate([wall_thickness, wall_thickness, mount_depth-10])
            cylinder(r1=3, r2=9, h=4);

            translate([mount_width-wall_thickness, wall_thickness, mount_depth-6])
            cylinder(r=9, h=6);
            translate([mount_width-wall_thickness, wall_thickness, mount_depth-10])
            cylinder(r1=3, r2=9, h=4);

            translate([mount_width-wall_thickness, mount_height-wall_thickness, mount_depth-6])
            cylinder(r=9, h=6);
            translate([mount_width-wall_thickness, mount_height-wall_thickness, mount_depth-10])
            cylinder(r1=3, r2=9, h=4);

            translate([wall_thickness, mount_height-wall_thickness, mount_depth-6])
            cylinder(r=9, h=6);
            translate([wall_thickness, mount_height-wall_thickness, mount_depth-10])
            cylinder(r1=3, r2=9, h=4);
        }
    }
}

module cover() {
    hole_center = mount_height - table_padding - button_radius;

    difference() {
        hull() {
            // lower left
            translate([wall_thickness*2, wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=wall_thickness);

            // lower right
            translate([mount_width-(wall_thickness*2), wall_thickness*2, 0])
            cylinder(r=wall_thickness, h=wall_thickness);

            // upper right
            translate([mount_width-(wall_thickness*2), mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, wall_thickness]);

            // upper left
            translate([wall_thickness, mount_height-(wall_thickness*2), 0])
            cube(size=[wall_thickness, wall_thickness, wall_thickness]);
        }

        translate([mount_width/2, hole_center, -1])
        cylinder(r=hole_radius, h=wall_thickness*2);
    }

    // Fake button
    // translate([mount_width/2, hole_center, 5])
    // cylinder(r=button_radius, h=20);
}

bottom();
sides();

translate([0, 0, mount_depth + 15])
cover();

error: pathspec 'models/switch-mount.scad' did not match any file(s) known to git


screws/screw_nut: fix thread cut

screws/screw_nut: fix thread cut

include <system.scad>
include <thread-data.scad>
include <nut-data.scad>
include <materials.scad>

use <shapes.scad>
use <transforms.scad>
use <misc.scad>

// for proper threads
use <naca_sweep.scad>

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

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

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

    s = threadsize*tolerance;
    total_h = h;
    size_align(size=[s, s, total_h], orient=-orient, orient_ref=Z, align=align)
    {
        tz(head_embed?-head_h:0)
        {
            difference()
            {
                union()
                {
                    if(with_head)
                    {
                        tz(h/2+.01)
                        screw_head(part="pos", head=head, thread=thread_, orient=Z, align=Z);
                    }

                    tz(-h/2+.01)
                    screw_thread(thread=thread_, head=head, h=h+.1, tolerance=tolerance, orient=Z, align=N);
                }
                if(with_head)
                tz(h/2+.01)
                screw_head(part="neg", head=head, thread=thread_, orient=Z, align=Z);
            }

            if(with_nut && nut != U)
            {
                tz(-h/2+nut_h+nut_offset+(head_embed?head_h:0))
                screw_nut(nut=nut, tolerance=tolerance, orient=Z, align=-Z);
            }
        }

        if($show_vit)
        {
            if(with_nut && nut != U)
            {
                tz(-h/2+nut_h+nut_offset+(head_embed?head_h:0))
                %screw_nut(nut=nut, align=-Z);
            }
        }
    }
}

module screw_cut(nut, thread, head="socket", h=10, tolerance=1.05, head_embed=false, with_nut=true, with_nut_access=true, nut_cut_h=1000, with_head=true, head_cut_h=1000, nut_offset=0, cut_access=true, orient=Z, align=N)
{
    nut_thread = get(NutThread, nut);
    thread_ = fallback(thread, nut_thread);
    assert(thread_ != U, "screw_cut: No nut or thread given");
    /*assert(nut!=U && thread!=U && nut_thread != thread_, "screw_cut: Mismatched nut and thread");*/

    nut_h = get(NutThickness,nut)*tolerance;
    assert(head != U, "screw_cut: head == U");

    head_h = get_screw_head_h(head=head, thread=thread_);
    assert(head_h != U, "screw_cut: head_h is U!");

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

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

            screw_thread_cut(thread=thread_, h=h+.1, tolerance=tolerance, orient=Z, align=N);

            if(with_nut && nut != U)
            {
                tz(-h/2+nut_h+nut_offset+(head_embed?head_h:0))
                screw_nut_cut(nut=nut, tolerance=tolerance, h=nut_cut_h, with_access=with_nut_access, align=-Z);
            }

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

module screw_thread(thread, h=10, tolerance=1.00, orient=Z, align=N)
{
    assert(thread!=U, "screw_thread: thread is undef");
    threadsize = get(ThreadSize, thread);
    d = get(ThreadSize, thread);
    pitch = get(ThreadPitchMm, thread);
    windings = ceil(h/pitch);

    size_align(size=[d,d,h], orient=orient, align=align)
    material(Mat_Steel)
    {
        if($preview_mode)
        {
            cylindera(d=d, h=h, align=Z);
        }
        else
        {
            intersection()
            {
                cylindera(d=d, h=h, align=Z);
                tz(-pitch)
                threading(angle=60, pitch=pitch, d=d, windings=windings, full=true);
            }
            /*inner_d = (get(ThreadInternalMinorDiaMin, thread) + get(ThreadInternalMinorDiaMin, thread))/2;*/
            /*cylindera(d=inner_d, h=h, align=Z);*/
        }
    }
}

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

module screw_head(part, head="socket", drive="hex", thread, tolerance=1.00, override_h=U, orient=Z, align=N)
{
    assert(head != U, "screw_head: head == U");
    assert(thread!=U, "screw_head: thread == undef");

    threadsize = get(ThreadSize, thread);
    head_h = get_screw_head_h(head=head, thread=thread);
    head_d = get_screw_head_d(head=head, thread=thread);

    if(part==U)
    {
        difference()
        {
            screw_head(part="pos", head=head, drive=drive, thread=thread, tolerance=tolerance, override_h=override_h, orient=orient, align=align);
            screw_head(part="neg", head=head, drive=drive, thread=thread, tolerance=tolerance, override_h=override_h, orient=orient, align=align);
        }
    }
    else if(part=="pos")
    material(Mat_Steel)
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    {
        if(head=="socket")
        {
            tz(-head_h/2)
            cylindera(d=head_d, h = fallback(override_h,head_h), align=Z);
        }
        else if(head=="button")
        {
            c = head_d;
            f = head_h*1.25;
            r = ( pow(c,2)/4 + pow(f,2) )/(2*f);

            d = r - f; // displacement to move sphere

            intersection()
            {
                tz(-head_h/2)
                scale([1,1,.5])
                spherea(r = head_h, align=N);

                tz(-head_h/2)
                cylindera(d=head_d, h = fallback(override_h,head_h)/2, align=Z);
            }
        }
    }
    else if(part=="neg")
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    {
        if(head=="socket")
        {
            if(drive == "hex")
            {
                cylindera(d = fn_radius(threadsize, 6), h = 1000, $fn = 6, align=Z);
            }
        }
        else if(head=="button")
        {
            if(drive == "hex")
            {
                // button head uses -0.5*mm smaller hex
                tz(-head_h/2)
                cylindera(d = fn_radius(threadsize-.5, 6), h = 1000, $fn = 6, align=Z);
            }
        }
        else if(head=="set")
        {
            if(drive == "hex")
            {
                // set head uses -1*mm smaller hex
                tz(-head_h)
                cylindera(d = fn_radius(threadsize-1, 6), h = 1000, $fn = 6, align=Z);
            }

        }
    }
}

module screw_head_cut(head="socket", thread, tolerance=1.05, override_h=U, orient=Z, align=N)
{
    assert(head != U, "screw_head: head == U");
    assert(thread!=U, "screw_head_cut: thread is undef");

    threadsize = get(ThreadSize, thread);
    head_h = get_screw_head_h(head=head, thread=thread);
    head_d = get_screw_head_d(head=head, thread=thread)*tolerance;
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    {
        if(head=="socket" || head=="button")
        {
            tz(-head_h/2)
            cylindera(d=head_d, h=fallback(override_h, head_h), align=Z);
        }
        else if(head=="set")
        {
            tz(-head_h/2)
            cylindera(d=threadsize, h=fallback(override_h, head_h), align=Z);
        }
        else
        {
            assert("head: not implemented");
        }
    }
}

module screw_nut(nut, thread, tolerance=1.00, override_h=U, orient=Z, align=N)
{
    assert(nut!=U, "screw_nut: nut is undef");

    nut_thick = get(NutThickness,nut)*tolerance;
    nut_facets = get(NutFacets, nut);
    nut_dia = nut_dia(nut);
    nut_thread = fallback(thread, get(NutThread, nut));
    h_ = fallback(override_h, nut_thick);
    material(Mat_Steel)
    size_align([nut_dia, nut_dia, h_], orient=orient, align=align)
    {
        difference()
        {
            cylindera($fn=nut_facets, d=nut_dia, h=h_);
            tz(-h_/2-.2)
            screw_thread(thread=nut_thread, h=h_+.1);
        }
    }
}

module screw_nut_cut(nut, tolerance=1.05, h=1000, with_access=true, orient=Z, align=N)
{
    assert(nut!=U, "screw_nut_cut: nut is undef");

    nut_thick = get(NutThickness,nut)*tolerance;
    nut_dia = nut_dia(nut);
    size_align(size=[nut_dia, nut_dia, nut_thick], orient=orient, align=align)
    {
        tz(nut_thick/2)
        {
            tz(-.1)
            screw_nut(nut=nut, tolerance=tolerance, orient=Z, align=-Z);

            if(with_access)
            tz(-nut_thick-.01)
            {
                cylindera(d=nut_dia+2*mm, h=h, orient=Z, align=-Z);
            }
        }
    }
}

function nut_radius(nut) = outradius(get(NutWidthMin, nut)/2, get(NutFacets, nut));
function nut_dia(nut) = 2*nut_radius(nut);

module nut_trap_cut(nut, thread, head, trap_offset=10, screw_l=10*mm, screw_offset=0*mm, cut_screw=false, trap_h=10, trap_axis=-Y, orient=Z, align=N)
{
    nut_thread = get(NutThread, nut);
    thread_ = fallback(thread, nut_thread);
    assert(thread_ != U, "nut_trap_cut: No nut or thread given");
    /*assert(nut!=U && thread!=U && nut_thread != thread_, "nut_trap_cut: Mismatched nut and thread");*/

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

    tolerance = -.2*mm;
    nut_width_min = get(NutWidthMin, nut)+tolerance;
    nut_facets = get(NutFacets, nut);
    nut_dia = nut_dia(nut)+tolerance;
    total_h = nut_h;
    size_align(size=[nut_dia, nut_dia, total_h], orient=orient, orient_ref=Z, align=align)
    {
        if(cut_screw)
        {
            tz(-nut_h/2)
            tz(screw_offset)
            screw_cut($show_vit=false, nut=nut, thread=thread_, with_nut=false, tolerance=1.1, h=screw_l, orient=-Z, align=Z);
        }
        else
        {
            tz(nut_h/2+screw_offset)
            screw_thread_cut($show_vit=false, thread=thread_, tolerance=1.1, h=screw_l, orient=-Z, align=Z);
        }

        hull()
        {
            orient(axis=Z, axis_ref=orient)
            translate(-.15*mm*trap_axis)
            stack(dist=trap_h, axis=trap_axis)
            {
                orient(axis=orient, axis_ref=Z)
                {
                    rotate([0,0,30])
                    cylindera($fn=nut_facets, d=nut_dia, h=nut_h, align=N);
                }

                orient(axis=orient, axis_ref=Z)
                cubea(size=[nut_width_min,nut_width_min,nut_h], align=N);
            }
        }

        if($show_vit)
        {
            if(cut_screw)
            {
                tz(-nut_h/2)
                tz(screw_offset)
                %screw(nut=nut, thread=thread_, with_nut=false, tolerance=1, h=screw_l, orient=-Z, align=Z);
            }

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

    }
}

if(false)
{
    all_axes()
    translate($axis*5*mm)
    color($color)
    screw(nut=NutHexM3, h=10*mm, orient=-$axis, align=$axis);
}

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

// From ParkinBots threading library
// https://www.thingiverse.com/thing:1659079
/*module Threading(D = 0, pitch = 1, d = 12, windings = 10, helices = 1, angle = 60, steps=40)*/
/*{*/
    /*R = D==0?d/2+2*pitch/PI:D/2; */
    /*translate([0,0,-pitch])*/
    /*difference()*/
    /*{*/
        /*translate([0,0,pitch])*/
        /*cylinder (r=R, h =pitch*(windings-helices));*/
        /*threading(pitch, d, windings, helices, angle, steps, true); */
    /*}*/
/*}*/

// From ParkinBots threading library
// https://www.thingiverse.com/thing:1659079
module threading(pitch = 1, d = 12, windings = 10, helices = 1, angle = 60, steps=40, full = false)
{
    // tricky: glue two 180° pieces together to get a proper manifold
    r = d/2;
    Steps = steps/2;
    Pitch = pitch*helices;
    if(full)
    {
        cylinder(r = r-.5-pitch/PI, h=pitch*(windings+helices), $fn=steps);
    }

    sweep(gen_dat(), planar_caps=true);   // half screw
    rz(180)
    tz(Pitch/2)
    sweep(gen_dat(), planar_caps=true);   // half screw

    function gen_dat() =
        let(ang = 180, bar = R_(180, -90, 0, Ty_(-r+.5, vec3D(pitch/PI*Rack(windings, angle)))))
        [for (i=[0:Steps]) Tz_(i/2/Steps*Pitch, -Rz_(i*ang/Steps, bar))];

    function Rack(w, angle) =
        concat([[0, 2]],
            [for (i=[0:w-1], j=[0:3])
            let(t = [ [0, 1], [2*tan(angle/2), -1], [PI/2, -1], [2*tan(angle/2)+PI/2, 1]])
            [t[j][0]+i*PI, t[j][1]]], [[w*PI, 1], [w*PI, 2]
            ]);
}

if(false)
{
    $fn=128;
    nut1 = NutHexM3;
    stack(axis=X, dist = 20)
    {
        screw(nut=NutHexM8, head="socket", h=25, orient=-Z);
        screw(nut=NutHexM8, head="button", h=25, orient=-Z);
        screw(nut=NutHexM8, head="button", h=25, with_head=1, with_nut=0, orient=-Z);
        screw(nut=NutHexM8, head="button", h=25, with_head=0, with_nut=0, orient=-Z);
        screw(nut=NutHexM8, head="set", h=25, with_nut=0, orient=-Z);

        threading(pitch = 1.25, d=8, windings=10, full=true);
    }
}

if(false)
{
    box_w = 150*mm;
    box_d = 10*mm;
    box_h = 10*mm;
    o = 10*mm;

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

    nut1 = NutHexM3;
    nut2 = NutHexM5;
    nut3 = NutKnurlM3_3_42;
    nut4 = NutKnurlM3_5_42;

    /*all_axes()*/
    /*for($axis=[X])*/
    /*color($color)*/
    /*translate($axis*15)*/
    /*echo($axis)*/

    /*orient(axis=$axis, axis_ref=-X)*/
    for(y=[-1,1])
    translate(-y*Y*20*mm)
    difference()
    {
        cubea([box_w,box_d,box_h], align=X+Z);
        test_cuts(orient=y*Z);
        /*%test_cuts(orient=y, axis_ref=-Z);*/
    }

}

module test_cuts(orient)
{
    union()
    {
        /*offset = 0;*/
        offset = -5;
        /*translate([0,offset,0])*/
        /*translate([5,0,-5])*/
        translate([5,0,0])
        stack(dist=10,axis=X)
        {
            screw_cut(nut=nut1, head="button", h=box_h, head_embed=false, orient=orient, align=Z);
            screw_cut(nut=nut1, head="socket", h=box_h, head_embed=false, orient=orient, align=Z);
            screw_cut(thread=ThreadM5, h=box_h, head_embed=false, orient=orient, align=Z);
            screw_cut(nut=nut1, h=box_h, head_embed=false, orient=orient, align=Z);

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

            translate([0,0,-5*mm])
            screw_cut(nut=nut3, h=box_h, head_embed=false, orient=orient, align=Z);

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

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

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

include <system.scad>
include <thread-data.scad>
include <nut-data.scad>
include <materials.scad>

use <shapes.scad>
use <transforms.scad>
use <misc.scad>

// for proper threads
use <naca_sweep.scad>

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

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

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

    s = threadsize*tolerance;
    total_h = h;
    size_align(size=[s, s, total_h], orient=-orient, orient_ref=Z, align=align)
    {
        tz(head_embed?-head_h:0)
        {
            difference()
            {
                union()
                {
                    if(with_head)
                    {
                        tz(h/2+.01)
                        screw_head(part="pos", head=head, thread=thread_, orient=Z, align=Z);
                    }

                    tz(-h/2+.01)
                    screw_thread(thread=thread_, head=head, h=h+.1, tolerance=tolerance, orient=Z, align=N);
                }
                if(with_head)
                tz(h/2+.01)
                screw_head(part="neg", head=head, thread=thread_, orient=Z, align=Z);
            }

            if(with_nut && nut != U)
            {
                tz(-h/2+nut_h+nut_offset+(head_embed?head_h:0))
                screw_nut(nut=nut, tolerance=tolerance, orient=Z, align=-Z);
            }
        }

        if($show_vit)
        {
            if(with_nut && nut != U)
            {
                tz(-h/2+nut_h+nut_offset+(head_embed?head_h:0))
                %screw_nut(nut=nut, align=-Z);
            }
        }
    }
}

module screw_cut(nut, thread, head="socket", h=10, tolerance=1.05, head_embed=false, with_nut=true, with_nut_access=true, nut_cut_h=1000, with_head=true, head_cut_h=1000, nut_offset=0, cut_access=true, orient=Z, align=N)
{
    nut_thread = get(NutThread, nut);
    thread_ = fallback(thread, nut_thread);
    assert(thread_ != U, "screw_cut: No nut or thread given");
    /*assert(nut!=U && thread!=U && nut_thread != thread_, "screw_cut: Mismatched nut and thread");*/

    nut_h = get(NutThickness,nut)*tolerance;
    assert(head != U, "screw_cut: head == U");

    head_h = get_screw_head_h(head=head, thread=thread_);
    assert(head_h != U, "screw_cut: head_h is U!");

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

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

            screw_thread_cut(thread=thread_, h=h+.1, tolerance=tolerance, orient=Z, align=N);

            if(with_nut && nut != U)
            {
                tz(-h/2+nut_h+nut_offset+(head_embed?head_h:0))
                screw_nut_cut(nut=nut, tolerance=tolerance, h=nut_cut_h, with_access=with_nut_access, align=-Z);
            }

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

module screw_thread(thread, h=10, tolerance=1.00, orient=Z, align=N)
{
    assert(thread!=U, "screw_thread: thread is undef");
    threadsize = get(ThreadSize, thread);
    d = get(ThreadSize, thread);
    pitch = get(ThreadPitchMm, thread);
    windings = ceil(h/pitch);

    size_align(size=[d,d,h], orient=orient, align=align)
    material(Mat_Steel)
    {
        if($preview_mode)
        {
            cylindera(d=d, h=h, align=Z);
        }
        else
        {
            intersection()
            {
                cylindera(d=d, h=h, align=Z);
                tz(-pitch)
                threading(angle=60, pitch=pitch, d=d, windings=windings, full=true);
            }
            /*inner_d = (get(ThreadInternalMinorDiaMin, thread) + get(ThreadInternalMinorDiaMin, thread))/2;*/
            /*cylindera(d=inner_d, h=h, align=Z);*/
        }
    }
}

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

module screw_head(part, head="socket", drive="hex", thread, tolerance=1.00, override_h=U, orient=Z, align=N)
{
    assert(head != U, "screw_head: head == U");
    assert(thread!=U, "screw_head: thread == undef");

    threadsize = get(ThreadSize, thread);
    head_h = get_screw_head_h(head=head, thread=thread);
    head_d = get_screw_head_d(head=head, thread=thread);

    if(part==U)
    {
        difference()
        {
            screw_head(part="pos", head=head, drive=drive, thread=thread, tolerance=tolerance, override_h=override_h, orient=orient, align=align);
            screw_head(part="neg", head=head, drive=drive, thread=thread, tolerance=tolerance, override_h=override_h, orient=orient, align=align);
        }
    }
    else if(part=="pos")
    material(Mat_Steel)
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    {
        if(head=="socket")
        {
            tz(-head_h/2)
            cylindera(d=head_d, h = fallback(override_h,head_h), align=Z);
        }
        else if(head=="button")
        {
            c = head_d;
            f = head_h*1.25;
            r = ( pow(c,2)/4 + pow(f,2) )/(2*f);

            d = r - f; // displacement to move sphere

            intersection()
            {
                tz(-head_h/2)
                scale([1,1,.5])
                spherea(r = head_h, align=N);

                tz(-head_h/2)
                cylindera(d=head_d, h = fallback(override_h,head_h)/2, align=Z);
            }
        }
    }
    else if(part=="neg")
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    {
        if(head=="socket")
        {
            if(drive == "hex")
            {
                cylindera(d = fn_radius(threadsize, 6), h = 1000, $fn = 6, align=Z);
            }
        }
        else if(head=="button")
        {
            if(drive == "hex")
            {
                // button head uses -0.5*mm smaller hex
                tz(-head_h/2)
                cylindera(d = fn_radius(threadsize-.5, 6), h = 1000, $fn = 6, align=Z);
            }
        }
        else if(head=="set")
        {
            if(drive == "hex")
            {
                // set head uses -1*mm smaller hex
                tz(-head_h)
                cylindera(d = fn_radius(threadsize-1, 6), h = 1000, $fn = 6, align=Z);
            }

        }
    }
}

module screw_head_cut(head="socket", thread, tolerance=1.05, override_h=U, orient=Z, align=N)
{
    assert(head != U, "screw_head: head == U");
    assert(thread!=U, "screw_head_cut: thread is undef");

    threadsize = get(ThreadSize, thread);
    head_h = get_screw_head_h(head=head, thread=thread);
    head_d = get_screw_head_d(head=head, thread=thread)*tolerance;
    size_align(size=[head_d, head_d, head_h], orient=orient, align=align)
    {
        if(head=="socket" || head=="button")
        {
            tz(-head_h/2)
            cylindera(d=head_d, h=fallback(override_h, head_h), align=Z);
        }
        else if(head=="set")
        {
            tz(-head_h/2)
            cylindera(d=threadsize, h=fallback(override_h, head_h), align=Z);
        }
        else
        {
            assert("head: not implemented");
        }
    }
}

module screw_nut(nut, thread, tolerance=1.00, override_h=U, orient=Z, align=N)
{
    assert(nut!=U, "screw_nut: nut is undef");

    nut_thick = get(NutThickness,nut)*tolerance;
    nut_facets = get(NutFacets, nut);
    nut_dia = nut_dia(nut);
    nut_thread = fallback(thread, get(NutThread, nut));
    h_ = fallback(override_h, nut_thick);
    material(Mat_Steel)
    size_align([nut_dia, nut_dia, h_], orient=orient, align=align)
    {
        difference()
        {
            cylindera($fn=nut_facets, d=nut_dia, h=h_);
            screw_thread(thread=nut_thread, h=h_+.2);
        }
    }
}

module screw_nut_cut(nut, tolerance=1.05, h=1000, with_access=true, orient=Z, align=N)
{
    assert(nut!=U, "screw_nut_cut: nut is undef");

    nut_thick = get(NutThickness,nut)*tolerance;
    nut_dia = nut_dia(nut);
    size_align(size=[nut_dia, nut_dia, nut_thick], orient=orient, align=align)
    {
        tz(nut_thick/2)
        {
            tz(-.1)
            screw_nut(nut=nut, tolerance=tolerance, orient=Z, align=-Z);

            if(with_access)
            tz(-nut_thick-.01)
            {
                cylindera(d=nut_dia+2*mm, h=h, orient=Z, align=-Z);
            }
        }
    }
}

function nut_radius(nut) = outradius(get(NutWidthMin, nut)/2, get(NutFacets, nut));
function nut_dia(nut) = 2*nut_radius(nut);

module nut_trap_cut(nut, thread, head, trap_offset=10, screw_l=10*mm, screw_offset=0*mm, cut_screw=false, trap_h=10, trap_axis=-Y, orient=Z, align=N)
{
    nut_thread = get(NutThread, nut);
    thread_ = fallback(thread, nut_thread);
    assert(thread_ != U, "nut_trap_cut: No nut or thread given");
    /*assert(nut!=U && thread!=U && nut_thread != thread_, "nut_trap_cut: Mismatched nut and thread");*/

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

    tolerance = -.2*mm;
    nut_width_min = get(NutWidthMin, nut)+tolerance;
    nut_facets = get(NutFacets, nut);
    nut_dia = nut_dia(nut)+tolerance;
    total_h = nut_h;
    size_align(size=[nut_dia, nut_dia, total_h], orient=orient, orient_ref=Z, align=align)
    {
        if(cut_screw)
        {
            tz(-nut_h/2)
            tz(screw_offset)
            screw_cut($show_vit=false, nut=nut, thread=thread_, with_nut=false, tolerance=1.1, h=screw_l, orient=-Z, align=Z);
        }
        else
        {
            tz(nut_h/2+screw_offset)
            screw_thread_cut($show_vit=false, thread=thread_, tolerance=1.1, h=screw_l, orient=-Z, align=Z);
        }

        hull()
        {
            orient(axis=Z, axis_ref=orient)
            translate(-.15*mm*trap_axis)
            stack(dist=trap_h, axis=trap_axis)
            {
                orient(axis=orient, axis_ref=Z)
                {
                    rotate([0,0,30])
                    cylindera($fn=nut_facets, d=nut_dia, h=nut_h, align=N);
                }

                orient(axis=orient, axis_ref=Z)
                cubea(size=[nut_width_min,nut_width_min,nut_h], align=N);
            }
        }

        if($show_vit)
        {
            if(cut_screw)
            {
                tz(-nut_h/2)
                tz(screw_offset)
                %screw(nut=nut, thread=thread_, with_nut=false, tolerance=1, h=screw_l, orient=-Z, align=Z);
            }

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

    }
}

if(false)
{
    all_axes()
    translate($axis*5*mm)
    color($color)
    screw(nut=NutHexM3, h=10*mm, orient=-$axis, align=$axis);
}

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

// From ParkinBots threading library
// https://www.thingiverse.com/thing:1659079
/*module Threading(D = 0, pitch = 1, d = 12, windings = 10, helices = 1, angle = 60, steps=40)*/
/*{*/
    /*R = D==0?d/2+2*pitch/PI:D/2; */
    /*translate([0,0,-pitch])*/
    /*difference()*/
    /*{*/
        /*translate([0,0,pitch])*/
        /*cylinder (r=R, h =pitch*(windings-helices));*/
        /*threading(pitch, d, windings, helices, angle, steps, true); */
    /*}*/
/*}*/

// From ParkinBots threading library
// https://www.thingiverse.com/thing:1659079
module threading(pitch = 1, d = 12, windings = 10, helices = 1, angle = 60, steps=40, full = false)
{
    // tricky: glue two 180° pieces together to get a proper manifold
    r = d/2;
    Steps = steps/2;
    Pitch = pitch*helices;
    if(full)
    {
        cylinder(r = r-.5-pitch/PI, h=pitch*(windings+helices), $fn=steps);
    }

    sweep(gen_dat(), planar_caps=true);   // half screw
    rz(180)
    tz(Pitch/2)
    sweep(gen_dat(), planar_caps=true);   // half screw

    function gen_dat() =
        let(ang = 180, bar = R_(180, -90, 0, Ty_(-r+.5, vec3D(pitch/PI*Rack(windings, angle)))))
        [for (i=[0:Steps]) Tz_(i/2/Steps*Pitch, -Rz_(i*ang/Steps, bar))];

    function Rack(w, angle) =
        concat([[0, 2]],
            [for (i=[0:w-1], j=[0:3])
            let(t = [ [0, 1], [2*tan(angle/2), -1], [PI/2, -1], [2*tan(angle/2)+PI/2, 1]])
            [t[j][0]+i*PI, t[j][1]]], [[w*PI, 1], [w*PI, 2]
            ]);
}

if(false)
{
    $fn=128;
    nut1 = NutHexM3;
    stack(axis=X, dist = 20)
    {
        screw(nut=NutHexM8, head="socket", h=25, orient=-Z);
        screw(nut=NutHexM8, head="button", h=25, orient=-Z);
        screw(nut=NutHexM8, head="button", h=25, with_head=1, with_nut=0, orient=-Z);
        screw(nut=NutHexM8, head="button", h=25, with_head=0, with_nut=0, orient=-Z);
        screw(nut=NutHexM8, head="set", h=25, with_nut=0, orient=-Z);

        threading(pitch = 1.25, d=8, windings=10, full=true);
    }
}

if(false)
{
    box_w = 150*mm;
    box_d = 10*mm;
    box_h = 10*mm;
    o = 10*mm;

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

    nut1 = NutHexM3;
    nut2 = NutHexM5;
    nut3 = NutKnurlM3_3_42;
    nut4 = NutKnurlM3_5_42;

    /*all_axes()*/
    /*for($axis=[X])*/
    /*color($color)*/
    /*translate($axis*15)*/
    /*echo($axis)*/

    /*orient(axis=$axis, axis_ref=-X)*/
    for(y=[-1,1])
    translate(-y*Y*20*mm)
    difference()
    {
        cubea([box_w,box_d,box_h], align=X+Z);
        test_cuts(orient=y*Z);
        /*%test_cuts(orient=y, axis_ref=-Z);*/
    }

}

module test_cuts(orient)
{
    union()
    {
        /*offset = 0;*/
        offset = -5;
        /*translate([0,offset,0])*/
        /*translate([5,0,-5])*/
        translate([5,0,0])
        stack(dist=10,axis=X)
        {
            screw_cut(nut=nut1, head="button", h=box_h, head_embed=false, orient=orient, align=Z);
            screw_cut(nut=nut1, head="socket", h=box_h, head_embed=false, orient=orient, align=Z);
            screw_cut(thread=ThreadM5, h=box_h, head_embed=false, orient=orient, align=Z);
            screw_cut(nut=nut1, h=box_h, head_embed=false, orient=orient, align=Z);

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

            translate([0,0,-5*mm])
            screw_cut(nut=nut3, h=box_h, head_embed=false, orient=orient, align=Z);

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

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

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


initial model

initial model

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


rcylinder: fix round_radius error

rcylinder: fix round_radius error

use <misc.scad>
use <transforms.scad>

module cubea(size=[10,10,10], align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            cube(size+extrasize, center=true);
        }
    }
}

module rcubea(size=[10,10,10], facets=32, rounding_radius=1, align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            rcube(size=size+extrasize, facets=facets, rounding_radius=rounding_radius);
        }
    }
}

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

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

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

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

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

    // some orient hax here to properly support extra_align
    orient(-orient)
    size_align([extra_sizexy,extra_sizexy,extra_h], align=extra_align, orient=orient)
    orient(orient)
    {
        if(debug)
        {
            echo(useDia, h, r_, r1_, r2_, extra_r_, align);
        }

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

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

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

module rcylinder(d=undef, r1=undef, r2=undef, h=10, round_radius=2)
{
    useDia = r == undef && (r1 == undef && r2 == undef);

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

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

            /*translate([0, 0, -round_radius])*/
            /*cubea([r__*2,r__*2,5], align=[0,0,-z]);*/
        }
    }
}

module pie_slice_shape(r, start_angle, end_angle) {
    R = r * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    if(end_angle > start_angle)
    {
        intersection() {
            circle(r);
            polygon([
                    [0,0],
                    [R * cos(a0), R * sin(a0)],
                    [R * cos(a1), R * sin(a1)],
                    [R * cos(a2), R * sin(a2)],
                    [R * cos(a3), R * sin(a3)],
                    [R * cos(a4), R * sin(a4)],
                    [0,0]
            ]);
        }
    }
}

module pie_slice(r, start_angle, end_angle, h)
{
    linear_extrude(h)
    {
        pie_slice_shape(r, start_angle, end_angle);
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

use <misc.scad>
use <transforms.scad>

module cubea(size=[10,10,10], align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            cube(size+extrasize, center=true);
        }
    }
}

module rcubea(size=[10,10,10], facets=32, rounding_radius=1, align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            rcube(size=size+extrasize, facets=facets, rounding_radius=rounding_radius);
        }
    }
}

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

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

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

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

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

    // some orient hax here to properly support extra_align
    orient(-orient)
    size_align([extra_sizexy,extra_sizexy,extra_h], align=extra_align, orient=orient)
    orient(orient)
    {
        if(debug)
        {
            echo(useDia, h, r_, r1_, r2_, extra_r_, align);
        }

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

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

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

module rcylinder(d=undef, r1=undef, r2=undef, h=10, round_radius=2)
{
    useDia = r == undef && (r1 == undef && r2 == undef);

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

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

            /*translate([0, 0, -round_radius])*/
            /*cubea([r__*2,r__*2,5], align=[0,0,-z]);*/
        }
    }
}

module pie_slice_shape(r, start_angle, end_angle) {
    R = r * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    if(end_angle > start_angle)
    {
        intersection() {
            circle(r);
            polygon([
                    [0,0],
                    [R * cos(a0), R * sin(a0)],
                    [R * cos(a1), R * sin(a1)],
                    [R * cos(a2), R * sin(a2)],
                    [R * cos(a3), R * sin(a3)],
                    [R * cos(a4), R * sin(a4)],
                    [0,0]
            ]);
        }
    }
}

module pie_slice(r, start_angle, end_angle, h)
{
    linear_extrude(h)
    {
        pie_slice_shape(r, start_angle, end_angle);
    }
}

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

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

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

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

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

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

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

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

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

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

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

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


added 2nd element (optimized for dual-element printing + fixed centering


yaxis/motor_mount: add cutout for belt path

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

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

ycarriage_bearing_mount_bottom_thick = 3;
ycarriage_bearing_mount_conn_bottom = [[0,0,0], [0,0,1]];
ycarriage_bearing_mount_conn_bearing = [[0,0,ycarriage_bearing_mount_bottom_thick+yaxis_bearing[1]/2], [0,0,1]];

module ycarriage_bearing_mount(show_bearing=false, show_zips=false)
{
    // x distance of holes
    screw_dx=28;
    // y distance of holes
    screw_dy=21;

    carriage_plate_thread=ThreadM4;
    carriage_plate_thread_d=lookup(ThreadSize, carriage_plate_thread);

    width = screw_dx+carriage_plate_thread_d*2;
    depth = max(yaxis_bearing[1], screw_dx+carriage_plate_thread_d*2);
    /*height = yaxis_bearing[1]/2+ycarriage_bearing_mount_bottom_thick;*/
    height = 5+ycarriage_bearing_mount_bottom_thick;

    difference()
    {
        union()
        {
            cubea ([width, depth, height], align=[0,0,1]);
        }

        translate ([+screw_dx/2, +screw_dy/2, -1]) fncylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([+screw_dx/2, -screw_dy/2, -1]) fncylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([-screw_dx/2, +screw_dy/2, -1]) fncylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([-screw_dx/2, -screw_dy/2, -1]) fncylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);

        translate([0,0,yaxis_bearing[1]/2+ycarriage_bearing_mount_bottom_thick])
        bearing_mount_holes(yaxis_bearing, orient=[0,1,0], ziptie_dist=5, show_zips=show_zips);
    }

    %if(show_bearing)
    {
        translate([0,0,yaxis_bearing[1]/2+ycarriage_bearing_mount_bottom_thick])
        bearing(yaxis_bearing, orient=[0,1,0]);
    }
}

/*c1=[[0,0,0],[0,0,-1]];*/
/*attach(c1,ycarriage_bearing_mount_conn)*/
/*{*/
    /*ycarriage_bearing_mount();*/
    /*#connector(ycarriage_bearing_mount_conn);*/
/*}*/

yaxis_motor_mount_conn = [[0,0,+extrusion_size/2+yaxis_motor_offset_z],[1,0,0]];
yaxis_motor_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_motor_mount_conn_motor = [[+yaxis_motor_offset_x, 0,+extrusion_size/2+yaxis_motor_offset_z],[0,0,1]];

ymotor_w = lookup(NemaSideSize, yaxis_motor);
ymotor_h = lookup(NemaLengthLong, yaxis_motor);
ymotor_mount_thread_dia = lookup(ThreadSize, extrusion_thread);
ymotor_mount_h = main_lower_dist_z+extrusion_size+yaxis_motor_offset_z;
ymotor_mount_width = ymotor_w+ymotor_mount_thickness*2 + ymotor_mount_thread_dia*8;

module yaxis_motor_mount(show_motor=false)
{
    difference()
    {
        // top plate
        union()
        {
            translate([0,0,yaxis_motor_offset_z])
            {
                // top plate
                translate([ymotor_mount_thickness,0,extrusion_size/2])
                {
                    translate([ymotor_w/2,0,0])
                    difference()
                    {
                        cubea([ymotor_w+ymotor_mount_thickness, ymotor_w+ymotor_mount_thickness*2, ymotor_mount_thickness_h], align=[0,0,1]);
                        ymotor_round_d = lookup(NemaRoundExtrusionDiameter, yaxis_motor);

                        // cutout for belt path
                        fncylindera(d=ymotor_round_d, h=ymotor_mount_thickness_h*2, orient=[0,0,1]);
                        translate([0, 0,-1])
                        cubea([1000, ymotor_round_d, ymotor_mount_thickness_h*2], align=[1,0,1]);

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

                translate([0,0,extrusion_size/2])
                {
                    difference()
                    {
                        // reinforcement plate between motor and extrusion
                        cubea([ymotor_mount_thickness, ymotor_w+ymotor_mount_thickness*2, ymotor_h], align=[1,0,-1], extrasize=[0,0,ymotor_mount_thickness_h], extrasize_align=[0,0,1]);

                        // cutout for motor cables
                        translate([0,0,-20*mm])
                            cubea([ymotor_mount_thickness*3, 20*mm, ymotor_h], align=[0,0,-1]);
                    }
                }

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

                    translate([0, i*((ymotor_w/2)+ymotor_mount_thickness/2), extrusion_size/2])
                        cubea([ymotor_mount_thickness, ymotor_mount_thickness, ymotor_mount_h], align=[1,0,-1]);
                }
            }

            // top mount plate
            difference()
            {
                cubea([ymotor_mount_thickness, ymotor_mount_width, extrusion_size], align=[1,0,0]);

                for(i=[-1,1])
                    translate([0, i*(ymotor_w/2+ymotor_mount_thread_dia*3), 0])
                        fncylindera(h=ymotor_mount_thickness*3,d=ymotor_mount_thread_dia, orient=[1,0,0]);
            }

            // bottom mount plate
            translate([0,0,-main_lower_dist_z])
            {
                difference()
                {
                    cubea([ymotor_mount_thickness, ymotor_w, extrusion_size], align=[1,0,0]);

                    for(i=[0])
                        translate([0, i*(ymotor_w/2+ymotor_mount_thread_dia*3), 0])
                            fncylindera(h=ymotor_mount_thickness*3,d=ymotor_mount_thread_dia,align=[0,0,0], orient=[1,0,0]);
                }
            }

        }

    }

    if(show_motor)
    {
        attach(yaxis_motor_mount_conn_motor,[[0,0,0],[0,0,0]])
        {
            motor(yaxis_motor, NemaMedium, dualAxis=false, orientation=[0,180,0]);

            translate([0,0,5*mm])
            fncylindera(d=yaxis_pulley_d, h=yaxis_motor_pulley_h, orient=[0,0,1]);
        }
    }
}

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

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

ycarriage_bearing_mount_bottom_thick = 3;
ycarriage_bearing_mount_conn_bottom = [[0,0,0], [0,0,1]];
ycarriage_bearing_mount_conn_bearing = [[0,0,ycarriage_bearing_mount_bottom_thick+yaxis_bearing[1]/2], [0,0,1]];

module ycarriage_bearing_mount(show_bearing=false, show_zips=false)
{
    // x distance of holes
    screw_dx=28;
    // y distance of holes
    screw_dy=21;

    carriage_plate_thread=ThreadM4;
    carriage_plate_thread_d=lookup(ThreadSize, carriage_plate_thread);

    width = screw_dx+carriage_plate_thread_d*2;
    depth = max(yaxis_bearing[1], screw_dx+carriage_plate_thread_d*2);
    /*height = yaxis_bearing[1]/2+ycarriage_bearing_mount_bottom_thick;*/
    height = 5+ycarriage_bearing_mount_bottom_thick;

    difference()
    {
        union()
        {
            cubea ([width, depth, height], align=[0,0,1]);
        }

        translate ([+screw_dx/2, +screw_dy/2, -1]) fncylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([+screw_dx/2, -screw_dy/2, -1]) fncylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([-screw_dx/2, +screw_dy/2, -1]) fncylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);
        translate ([-screw_dx/2, -screw_dy/2, -1]) fncylindera(d=carriage_plate_thread_d, h=height+2, align=[0,0,1]);

        translate([0,0,yaxis_bearing[1]/2+ycarriage_bearing_mount_bottom_thick])
        bearing_mount_holes(yaxis_bearing, orient=[0,1,0], ziptie_dist=5, show_zips=show_zips);
    }

    %if(show_bearing)
    {
        translate([0,0,yaxis_bearing[1]/2+ycarriage_bearing_mount_bottom_thick])
        bearing(yaxis_bearing, orient=[0,1,0]);
    }
}

/*c1=[[0,0,0],[0,0,-1]];*/
/*attach(c1,ycarriage_bearing_mount_conn)*/
/*{*/
    /*ycarriage_bearing_mount();*/
    /*#connector(ycarriage_bearing_mount_conn);*/
/*}*/

yaxis_motor_mount_conn = [[0,0,+extrusion_size/2+yaxis_motor_offset_z],[1,0,0]];
yaxis_motor_offset_x = lookup(NemaSideSize,yaxis_motor)/2+ymotor_mount_thickness;
yaxis_motor_mount_conn_motor = [[+yaxis_motor_offset_x, 0,+extrusion_size/2+yaxis_motor_offset_z],[0,0,1]];

ymotor_w = lookup(NemaSideSize, yaxis_motor);
ymotor_h = lookup(NemaLengthLong, yaxis_motor);
ymotor_mount_thread_dia = lookup(ThreadSize, extrusion_thread);
ymotor_mount_h = main_lower_dist_z+extrusion_size+yaxis_motor_offset_z;
ymotor_mount_width = ymotor_w+ymotor_mount_thickness*2 + ymotor_mount_thread_dia*8;

module yaxis_motor_mount(show_motor=false)
{
    difference()
    {
        // top plate
        union()
        {
            translate([0,0,yaxis_motor_offset_z])
            {
                // top plate
                translate([ymotor_mount_thickness,0,extrusion_size/2])
                {
                    difference()
                    {
                        cubea([ymotor_w+ymotor_mount_thickness, ymotor_w+ymotor_mount_thickness*2, ymotor_mount_thickness_h], align=[1,0,1]);

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

                translate([0,0,extrusion_size/2])
                {
                    difference()
                    {
                        // reinforcement plate between motor and extrusion
                        cubea([ymotor_mount_thickness, ymotor_w+ymotor_mount_thickness*2, ymotor_h], align=[1,0,-1], extrasize=[0,0,ymotor_mount_thickness_h], extrasize_align=[0,0,1]);

                        // cutout for motor cables
                        translate([0,0,-20*mm])
                            cubea([ymotor_mount_thickness*3, 20*mm, ymotor_h], align=[0,0,-1]);
                    }
                }

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

                    translate([0, i*((ymotor_w/2)+ymotor_mount_thickness/2), extrusion_size/2])
                        cubea([ymotor_mount_thickness, ymotor_mount_thickness, ymotor_mount_h], align=[1,0,-1]);
                }
            }

            // top mount plate
            difference()
            {
                cubea([ymotor_mount_thickness, ymotor_mount_width, extrusion_size], align=[1,0,0]);

                for(i=[-1,1])
                    translate([0, i*(ymotor_w/2+ymotor_mount_thread_dia*3), 0])
                        fncylindera(h=ymotor_mount_thickness*3,d=ymotor_mount_thread_dia, orient=[1,0,0]);
            }

            // bottom mount plate
            translate([0,0,-main_lower_dist_z])
            {
                difference()
                {
                    cubea([ymotor_mount_thickness, ymotor_w, extrusion_size], align=[1,0,0]);

                    for(i=[0])
                        translate([0, i*(ymotor_w/2+ymotor_mount_thread_dia*3), 0])
                            fncylindera(h=ymotor_mount_thickness*3,d=ymotor_mount_thread_dia,align=[0,0,0], orient=[1,0,0]);
                }
            }

        }

    }

    if(show_motor)
    {
        attach(yaxis_motor_mount_conn_motor,[[0,0,0],[0,0,0]])
        {
            motor(yaxis_motor, NemaMedium, dualAxis=false, orientation=[0,180,0]);

            translate([0,0,5*mm])
            fncylindera(d=yaxis_pulley_d, h=yaxis_motor_pulley_h, orient=[0,0,1]);
        }
    }
}