yaxis/idler: Rewrite to be smaller/more compact

use <thing_libutils/metric-screw.scad>
include <thing_libutils/attach.scad>
include <config.scad>
include <pulley.scad>

yaxis_idler_conn = [[-extrusion_size/2, 0, 0], [-1,0,0]];

yidler_w = 2*yaxis_idler_pulley_inner_d;
yaxis_idler_mount_thread_dia = lookup(ThreadSize, extrusion_thread);

yaxis_idler_mount_tightscrew_dia = lookup(ThreadSize, ThreadM4);
yaxis_idler_mount_tightscrew_hexnut = MHexNutM4;
yaxis_idler_mount_tightscrew_hexnut_dia = lookup(MHexNutWidthMax, yaxis_idler_mount_tightscrew_hexnut);
yaxis_idler_mount_tightscrew_hexnut_thick = lookup(MHexNutThickness, yaxis_idler_mount_tightscrew_hexnut);

yidler_mount_width = yidler_w+yaxis_idler_mount_thickness*2 + yaxis_idler_mount_thread_dia*3;

module yaxis_idler()
{
    difference()
    {
        // top plate
        union()
        {
            // top mount plate
            difference()
            {
                tighten_screw_dia_outer = yaxis_idler_mount_tightscrew_dia*4;
                mount_screw_dist = (yidler_w/2+yaxis_idler_mount_thread_dia*3)*1.3;
                union()
                {
                    translate([-yaxis_idler_mount_thickness,0,extrusion_size/2])
                    {
                        cubea(
                                size=[extrusion_size, yidler_mount_width, yaxis_idler_mount_thickness],
                                align=[0,0,1],
                                extrasize=[yaxis_idler_mount_thickness,0,0],
                                extrasize_align=[1,0,0]
                                );
                    }

                    difference()
                    {
                        hull()
                        {
                            for(y=[-1,1])
                            translate([0, y*yaxis_idler_tightscrew_dist, 0])
                            translate([-yaxis_idler_mount_thickness,0,extrusion_size/2])
                            {
                                translate([yaxis_idler_mount_thickness/2,0,yaxis_belt_path_offset_z])
                                cylindera(
                                        h=extrusion_size+yaxis_idler_mount_thickness,
                                        d=tighten_screw_dia_outer,
                                        align=[0,0,0],
                                        orient=[1,0,0]
                                        );
                                cubea(
                                        size=[extrusion_size, mount_screw_dist-yaxis_idler_mount_tightscrew_dia*3, yaxis_idler_mount_thickness],
                                        align=[0,0,1],
                                        extrasize=[yaxis_idler_mount_thickness,0,0],
                                        extrasize_align=[1,0,0]
                                        );
                            }
                        }

                        translate([-yaxis_idler_mount_thickness,0,extrusion_size/2])
                        {
                            cubea(
                                size=[1000, 1000, 1000],
                                align=[0,0,-1]
                                );
                        }

                    }
                }

                // top/vertical mount screws (to extrusion)
                translate([0,0,extrusion_size/2+yaxis_idler_mount_thickness])
                {
                    for(i=[-1,0,1])
                    translate([0, i*mount_screw_dist/2, 0])
                    screw_cut(extrusion_nut, head_embed=false, h=extrusion_size+yaxis_idler_mount_thickness, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
                }

                // mount screws for pulley block
                for(y=[-1,1])
                translate([
                        -extrusion_size/2-yaxis_idler_mount_thickness,
                        y*yaxis_idler_tightscrew_dist,
                        extrusion_size/2+yaxis_belt_path_offset_z])
                    screw_cut(yaxis_idler_mount_tightscrew_hexnut, head_embed=true, h=extrusion_size+yaxis_idler_mount_thickness, with_nut=false, orient=[1,0,0], align=[1,0,0]);

                translate([0,0,extrusion_size/2])
                cubea(size=[extrusion_size+1, yidler_mount_width, tighten_screw_dia_outer/2],
                        extrasize=[yaxis_idler_mount_thickness,0,0],
                        extrasize_align=[1,0,0],
                        align=[-1,0,-1]);
            }

            translate([-extrusion_size/2,0,0])
            difference()
            {
                cubea([yaxis_idler_mount_thickness, yidler_mount_width, extrusion_size], align=[-1,0,0]);

                // front/horizontal mount screws (to extrusion)
                for(i=[-1,1])
                translate([0, i*(yaxis_idler_mount_thread_dia*2.5), 0])
                screw_cut(yaxis_idler_mount_tightscrew_hexnut, h=yaxis_idler_mount_thickness, with_nut=false, orient=[-1,0,0], align=[-1,0,0]);
            }
        }
    }
}

yaxis_idler_tightscrew_dist = 10*mm;
yaxis_idler_pulley_nut = MHexNutM5;
yaxis_idler_pulley_thread = ThreadM5;
yaxis_idler_pulley_thread_dia = lookup(ThreadSize, yaxis_idler_pulley_thread);
yaxis_idler_pulleyblock_supportsize = yaxis_idler_pulley_outer_d*1.2;
yaxis_idler_pulleyblock_wallthick = 5*mm;
yaxis_idler_pulleyblock_lenfrompulley = yaxis_idler_pulleyblock_supportsize/2 + yaxis_idler_pulley_tight_len;

module yaxis_idler_pulleyblock(show_pulley=false)
{
    if(show_pulley)
    {
        %pulley(pulley_2GT_20T_idler);
    }

    h = yaxis_idler_pulley_h + 3*mm*2;
    difference()
    {
        hull()
        {
            /*cylindera(d=yaxis_idler_pulley_inner_d*1.5, h=h, orient=[0,0,1], align=[0,0,0]);*/
            rcubea([yaxis_idler_pulleyblock_supportsize, 2*yaxis_idler_pulleyblock_supportsize, h],
                    align=[0,0,0],
                    extrasize=[yaxis_idler_pulley_tight_len,0,0],
                    extrasize_align=[-1,0,0]
                 );
            /*translate([-yaxis_idler_pulley_tight_len,0,0])*/
                /*cubea([yaxis_idler_pulley_inner_d, yaxis_idler_pulley_inner_d*1.5, h]);*/
        }

        // pulley cutout
        translate([-3*mm,0,0])
            cubea(
                    size=[yaxis_idler_pulley_outer_d, yaxis_idler_pulley_outer_d*3, yaxis_idler_pulley_h+0.5],
                    align=[0,0,0],
                    extrasize=[20*mm,0,0], extrasize_align=[1,0,0]
                 );

        // pulley screw
        translate([0,0,h/2])
        {
            screw_cut(yaxis_idler_pulley_nut, h=h+5*mm, orient=[0,0,-1], align=[0,0,-1]);
        }

        cylindera(d=yaxis_idler_pulley_thread_dia, h=h*2, orient=[0,0,1], align=[0,0,0]);

        for(y=[-1,1])
        {
            translate([
                    -yaxis_idler_pulleyblock_supportsize/2-yaxis_idler_pulley_tight_len,
                    y*yaxis_idler_tightscrew_dist,
                    0
            ])
            {
                screw_cut(yaxis_idler_mount_tightscrew_hexnut, head_embed=true, nut_offset=5*mm, h=yaxis_idler_pulley_tight_len, orient=[1,0,0], align=[1,0,0]);
            }
        }
    }

}

// the pulley block mounting point (mounting point in pulley block frame)
yaxis_idler_pulleyblock_conn = [[-yaxis_idler_pulleyblock_lenfrompulley, 0, 0], [-1,0,0]];

yaxis_idler_pulleyblock_conn_print = [[-yaxis_idler_pulleyblock_lenfrompulley, yaxis_idler_pulleyblock_supportsize/2, 0], [0,1,0]];

// the idler pulley block mounting point (mounting point in idler frame)
yaxis_idler_conn_pulleyblock = [[extrusion_size/2+yaxis_idler_mount_thickness, 0, extrusion_size/2+yaxis_belt_path_offset_z], [1,0,0]];

module print_yaxis_idler()
{
    attach([[0,0,0], [0,0,-1]], yaxis_idler_conn)
    {
        yaxis_idler();
    }
}

module print_yaxis_idler_pulleyblock()
{
    attach([[0,0,0], [0,0,-1]], yaxis_idler_pulleyblock_conn_print)
    {
        yaxis_idler_pulleyblock(show_pulley=false);
    }
}

/*yaxis_idler();*/
/*yaxis_idler_pulleyblock();*/

/*print_yaxis_idler();*/
/*print_yaxis_idler_pulleyblock();*/

/*attach([[0,0,0],[-1,0,0]], yaxis_idler_conn)*/
/*{*/
    /*yaxis_idler();*/
    /*attach(yaxis_idler_conn_pulleyblock, yaxis_idler_pulleyblock_conn)*/
    /*{*/
        /*yaxis_idler_pulleyblock(show_pulley=true);*/
    /*}*/
/*}*/

use <thing_libutils/metric-screw.scad>
include <thing_libutils/attach.scad>
include <config.scad>
include <pulley.scad>

yaxis_idler_conn = [[-extrusion_size/2, 0, 0], [-1,0,0]];

yidler_w = 2*yaxis_idler_pulley_inner_d;
yaxis_idler_mount_thread_dia = lookup(ThreadSize, extrusion_thread);

yaxis_idler_mount_tightscrew_dia = lookup(ThreadSize, ThreadM4);
yaxis_idler_mount_tightscrew_hexnut = MHexNutM4;
yaxis_idler_mount_tightscrew_hexnut_dia = lookup(MHexNutWidthMax, yaxis_idler_mount_tightscrew_hexnut);
yaxis_idler_mount_tightscrew_hexnut_thick = lookup(MHexNutThickness, yaxis_idler_mount_tightscrew_hexnut);

yidler_mount_width = yidler_w+yaxis_idler_mount_thickness*2 + yaxis_idler_mount_thread_dia*3.5*2;

module yaxis_idler()
{
    difference()
    {
        // top plate
        union()
        {
            // top mount plate
            difference()
            {
                tighten_screw_dia_outer = yaxis_idler_mount_tightscrew_dia*4;
                mount_screw_dist = (yidler_w/2+yaxis_idler_mount_thread_dia*3)*1.5;
                union()
                {
                    translate([-yaxis_idler_mount_thickness,0,extrusion_size/2])
                    {
                        cubea(
                                size=[extrusion_size, yidler_mount_width, yaxis_idler_mount_thickness],
                                align=[0,0,1],
                                extrasize=[yaxis_idler_mount_thickness,0,0],
                                extrasize_align=[1,0,0]
                                );
                    }

                    hull()
                    {
                        for(y=[-1,1])
                        translate([0, y*yaxis_idler_tightscrew_dist, 0])
                        translate([-yaxis_idler_mount_thickness,0,extrusion_size/2])
                        {
                            translate([yaxis_idler_mount_thickness/2,0,yaxis_belt_path_offset_z])
                            cylindera(
                                    h=extrusion_size+yaxis_idler_mount_thickness,
                                    d=tighten_screw_dia_outer,
                                    align=[0,0,0],
                                    orient=[1,0,0]
                                    );
                            cubea(
                                    size=[extrusion_size, mount_screw_dist-yaxis_idler_mount_tightscrew_dia*3, yaxis_idler_mount_thickness],
                                    align=[0,0,1],
                                    extrasize=[yaxis_idler_mount_thickness,0,0],
                                    extrasize_align=[1,0,0]
                                    );
                        }
                    }
                }

                translate([0,0,extrusion_size/2+yaxis_idler_mount_thickness])
                {
                    for(i=[-1,0,1])
                    {
                        translate([0, i*mount_screw_dist/2, 0])
                        {
                            screw_cut(extrusion_nut, head_embed=false, h=extrusion_size+yaxis_idler_mount_thickness, with_nut=false, orient=[0,0,-1], align=[0,0,-1]);
                        }
                    }
                }

                for(y=[-1,1])
                    translate([
                            -extrusion_size/2-yaxis_idler_mount_thickness,
                            y*yaxis_idler_tightscrew_dist,
                            extrusion_size/2+yaxis_belt_path_offset_z])
                        screw_cut(yaxis_idler_mount_tightscrew_hexnut, head_embed=true, h=extrusion_size+yaxis_idler_mount_thickness, with_nut=false, orient=[1,0,0], align=[1,0,0]);

                translate([0,0,extrusion_size/2])
                cubea(size=[extrusion_size+1, yidler_mount_width, tighten_screw_dia_outer/2],
                        extrasize=[yaxis_idler_mount_thickness,0,0],
                        extrasize_align=[1,0,0],
                        align=[-1,0,-1]);
            }

            translate([-extrusion_size/2,0,0])
            difference()
            {
                cubea([yaxis_idler_mount_thickness, yidler_mount_width, extrusion_size], align=[-1,0,0]);

                for(i=[-1,1])
                    translate([0, i*(yidler_w/2+yaxis_idler_mount_thread_dia*3), 0])
                        screw_cut(yaxis_idler_mount_tightscrew_hexnut, h=yaxis_idler_mount_thickness, with_nut=false, orient=[-1,0,0], align=[-1,0,0]);
            }
        }
    }
}

yaxis_idler_tightscrew_dist = 10*mm;
yaxis_idler_pulley_nut = MHexNutM5;
yaxis_idler_pulley_thread = ThreadM5;
yaxis_idler_pulley_thread_dia = lookup(ThreadSize, yaxis_idler_pulley_thread);
yaxis_idler_pulleyblock_supportsize = yaxis_idler_pulley_outer_d*1.2;
yaxis_idler_pulleyblock_wallthick = 5*mm;
yaxis_idler_pulleyblock_lenfrompulley = yaxis_idler_pulleyblock_supportsize/2 + yaxis_idler_pulley_tight_len;

module yaxis_idler_pulleyblock(show_pulley=false)
{
    if(show_pulley)
    {
        %pulley(pulley_2GT_20T_idler);
    }

    h = yaxis_idler_pulley_h + 3*mm*2;
    difference()
    {
        hull()
        {
            /*cylindera(d=yaxis_idler_pulley_inner_d*1.5, h=h, orient=[0,0,1], align=[0,0,0]);*/
            rcubea([yaxis_idler_pulleyblock_supportsize, 2*yaxis_idler_pulleyblock_supportsize, h],
                    align=[0,0,0],
                    extrasize=[yaxis_idler_pulley_tight_len,0,0],
                    extrasize_align=[-1,0,0]
                 );
            /*translate([-yaxis_idler_pulley_tight_len,0,0])*/
                /*cubea([yaxis_idler_pulley_inner_d, yaxis_idler_pulley_inner_d*1.5, h]);*/
        }

        // pulley cutout
        translate([-3*mm,0,0])
            cubea(
                    size=[yaxis_idler_pulley_outer_d, yaxis_idler_pulley_outer_d*3, yaxis_idler_pulley_h+0.5],
                    align=[0,0,0],
                    extrasize=[20*mm,0,0], extrasize_align=[1,0,0]
                 );

        // pulley screw
        translate([0,0,h/2])
        {
            screw_cut(yaxis_idler_pulley_nut, h=h+5*mm, orient=[0,0,-1], align=[0,0,-1]);
        }

        cylindera(d=yaxis_idler_pulley_thread_dia, h=h*2, orient=[0,0,1], align=[0,0,0]);

        for(y=[-1,1])
        {
            translate([
                    -yaxis_idler_pulleyblock_supportsize/2-yaxis_idler_pulley_tight_len,
                    y*yaxis_idler_tightscrew_dist,
                    0
            ])
            {
                screw_cut(yaxis_idler_mount_tightscrew_hexnut, head_embed=true, nut_offset=5*mm, h=yaxis_idler_pulley_tight_len, orient=[1,0,0], align=[1,0,0]);
            }
        }
    }

}

// the pulley block mounting point (mounting point in pulley block frame)
yaxis_idler_pulleyblock_conn = [[-yaxis_idler_pulleyblock_lenfrompulley, 0, 0], [-1,0,0]];

yaxis_idler_pulleyblock_conn_print = [[-yaxis_idler_pulleyblock_lenfrompulley, yaxis_idler_pulleyblock_supportsize/2, 0], [0,1,0]];

// the idler pulley block mounting point (mounting point in idler frame)
yaxis_idler_conn_pulleyblock = [[extrusion_size/2+yaxis_idler_mount_thickness, 0, extrusion_size/2+yaxis_belt_path_offset_z], [1,0,0]];

module print_yaxis_idler()
{
    attach([[0,0,0], [0,0,-1]], yaxis_idler_conn)
    {
        yaxis_idler();
    }
}

module print_yaxis_idler_pulleyblock()
{
    attach([[0,0,0], [0,0,-1]], yaxis_idler_pulleyblock_conn_print)
    {
        yaxis_idler_pulleyblock(show_pulley=false);
    }
}

/*yaxis_idler();*/
/*yaxis_idler_pulleyblock();*/

/*print_yaxis_idler();*/
/*print_yaxis_idler_pulleyblock();*/

/*attach([[0,0,0],[-1,0,0]], yaxis_idler_conn)*/
/*{*/
    /*yaxis_idler();*/
    /*attach(yaxis_idler_conn_pulleyblock, yaxis_idler_pulleyblock_conn)*/
    /*{*/
        /*yaxis_idler_pulleyblock(show_pulley=true);*/
    /*}*/
/*}*/


This is a move refactor.

This is a move refactor.


A color was added to the shape.

A color was added to the shape.

use <../../rounded-cube.scad>

boardLength = 150;
boardWidth = 100;
size = [boardLength, boardWidth, 1];

roundedCube(size=[boardLength, boardWidth, 1],
            sides=5,
            sides=20);

color("green")
translate([0, 130, 0])
roundedCube(cornerRadius = 5,
            sides=20,
            sidesOnly=true,
            size=size);

use <../../rounded-cube.scad>

boardLength = 150;
boardWidth = 100;
size = [boardLength, boardWidth, 1];

roundedCube(size=[boardLength, boardWidth, 1],
            sides=5,
            sides=20);

translate([0, 130, 0])
roundedCube(cornerRadius = 5,
            sides=20,
            sidesOnly=true,
            size=size);


not neede really...

not neede really...

use <leftWall.scad>
use <rightWall.scad>

leftWall();
translate([85, 0, 0])
  rightWall();


modified openscad

modified openscad

$fn=100;

out_x=64;
out_y=40;
all_z=36;
all_r=4;

all_y = out_y+2*all_r;
all_x = out_x+2*all_r;

hdmi_look_x = 12;
hdmi_look_y = 6;

usb_look_x = 6;
usb_look_y = 3;

side_look_x = 30;
side_look_y = 15;

hdmi_x_pos = 5;
hdmi_y_pos = 1;
hdmi_z_pos = 5;

usb_x_pos  = -15;
usb_z_pos  = 5;

uart_x=10;
uart_y=8;
uart_z=2;

uart_x_pos = 10;
uart_z_pos = 20;

lr_width=3;
f_width=3;
b_width=10;
bottom_h=3;

gb_x=out_x-2*all_r;
gb_sx=1;
gb_mw=2;
gb_sy=6;

top_z=bottom_h;

module round_cube(size_x, size_y, size_z, r) {
union() {
cube([size_x + 2*r, size_y, size_z], center=true);
cube([size_x , size_y + 2*r, size_z], center=true);
translate([-size_x/2, -size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([size_x/2, -size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([size_x/2, size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([-size_x/2, size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
}

}

module gong_bang(all_x, side_x, mid_w, side_y, h) {
    cube([all_x, mid_w, h], center=true);
    translate([(all_x-side_x)/2, 0,0]) cube([side_x, side_y, h], center=true);
    translate([-(all_x-side_x)/2, 0,0]) cube([side_x, side_y, h], center=true);
    translate([-(all_x-side_x)/2, side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
    translate([-(all_x-side_x)/2, -side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
    translate([(all_x-side_x)/2, -side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
    translate([(all_x-side_x)/2, side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
}

shrink=0.1;
module gong_bang_shrink(all_x, side_x, mid_w, side_y, h) {
    gong_bang(all_x-shrink, side_x-shrink, mid_w-shrink,
        side_y-shrink, h);
}

$fn=100;
module round_cube(size_x, size_y, size_z, r) {
union() {
cube([size_x + 2*r, size_y, size_z], center=true);
cube([size_x , size_y + 2*r, size_z], center=true);
translate([-size_x/2, -size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([size_x/2, -size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([size_x/2, size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([-size_x/2, size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
}

}

module gong_bang(all_x, side_x, mid_w, side_y, h) {
    cube([all_x, mid_w, h], center=true);
    translate([(all_x-side_x)/2, 0,0]) cube([side_x, side_y, h], center=true);
    translate([-(all_x-side_x)/2, 0,0]) cube([side_x, side_y, h], center=true);
    translate([-(all_x-side_x)/2, side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
    translate([-(all_x-side_x)/2, -side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
    translate([(all_x-side_x)/2, -side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
    translate([(all_x-side_x)/2, side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
}

shrink=0.1;
module gong_bang_shrink(all_x, side_x, mid_w, side_y, h) {
    gong_bang(all_x-shrink, side_x-shrink, mid_w-shrink,
        side_y-shrink, h);
}

//gong_bang(80, 2, 2, 10, 40);

out_x=46;
out_y=26;
all_z=20;
all_r=4;

lr_width=3;
f_width=3;
b_width=10;
bottom_h=3;

gb_x=out_x-2*all_r;
gb_sx=1;
gb_mw=2;
gb_sy=6;

top_z=bottom_h;

difference () {
round_cube(out_x,out_y,all_z,all_r);
translate([0,(f_width-b_width)/2,bottom_h]) round_cube(out_x-2*lr_width,out_y-f_width-b_width,all_z,all_r);
color([1,0,0])
translate([0, (out_y - b_width)/2 + all_r, 2])
gong_bang(gb_x, gb_sx, gb_mw, gb_sy, all_z);
translate([0, out_y/2, bottom_h])
    cube([gb_x-gb_sx-4, out_y, all_z], center=true);
}

//union() {
//round_cube(out_x,out_y,top_z,bottom_h);
translate([-100, 0,all_z])
union() {
round_cube(out_x,out_y,bottom_h,all_r);
    translate([0,0,bottom_h])
    difference() {
color([1,0,0])
translate([0,(f_width-b_width)/2,0]) round_cube(out_x-2*lr_width,out_y-f_width-b_width,bottom_h,all_r);
translate([0,(f_width-b_width)/2,1]) round_cube(out_x-4*lr_width,out_y-f_width-b_width-4,bottom_h,all_r);            }
color([0,0,1])
translate([0, (out_y - b_width)/2 + all_r, all_z/2-1])
gong_bang(gb_x, gb_sx, gb_mw, gb_sy, all_z);
//color([0,1,0])
//translate([0,(f_width-b_width)/2,-(top_z)]) round_cube(out_x-4*lr_width,out_y-f_width-b_width-10,bottom_h+1,all_r);
    }
//}


screws/screw_cut: fix screw preview/vit (respect head_embed)

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

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

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

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

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

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

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

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

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

module screw_cut(nut, thread, h=10, tolerance=1.05, head_embed=false, with_nut=true, nut_cut_h=1000, with_head=true, head_cut_h=1000, nut_offset=0, cut_access=true, orient=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;
    head_h = get_screw_head_h(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)
    {
        translate([0,0,head_embed?-head_h:0])
        {
            if(with_head)
            {
                translate([0,0,h/2+.01])
                screw_head_cut(thread=thread_, tolerance=tolerance, override_h=head_cut_h, align=Z);
            }

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

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

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

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

module screw_thread_cut(thread, h=10, tolerance=1.05, orient=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(thread, tolerance=1.00, override_h=U, orient=Z, align=N)
{
    assert(thread!=U, "screw_head: thread is undef");

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

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

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

module screw_nut(nut, 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);
    cylindera($fn=nut_facets, d=nut_dia, h=fallback(override_h, nut_thick), orient=orient, align=align);
}

module screw_nut_cut(nut, tolerance=1.05, h=1000, 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)
    {
        translate([0,0,nut_thick/2])
        {
            screw_nut(nut, tolerance, orient=Z, align=-Z);
            translate([0,0,-nut_thick+.01])
            {
                cylindera(d=nut_dia+2*mm, h=h, orient=Z, align=-Z);
            }
        }
    }
}

// distance from center to flat on a polygon (taking in the diagonal distance)
function apothem(radius, facets) = radius/cos(180/facets);

function nut_radius(nut) = apothem(get(NutWidthMax, nut)/2, get(NutFacets, nut));
function nut_dia(nut) = 2*nut_radius(nut);

module nut_trap_cut(nut, thread, 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(thread);
    nut_h = get(NutThickness, nut) +.5*mm;

    nut_width_min = get(NutWidthMin, nut);
    nut_facets = get(NutFacets, nut);
    nut_dia = nut_dia(nut);
    total_h = nut_h;
    size_align(size=[nut_dia, nut_dia, total_h], orient=orient, orient_ref=Z, align=align)
    {
        if(cut_screw)
        {
            translate(-nut_h/2*Z)
            translate(screw_offset*Z)
            screw_cut($show_vit=false, nut=nut, thread=thread_, with_nut=false, tolerance=1.1, h=screw_l, orient=-Z, align=Z);
        }
        else
        {
            translate([0,0,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)
        {
            translate(-nut_h/2*Z)
            translate(screw_offset*Z)
            %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);
    }
}

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, 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>

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

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

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

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

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

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

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

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

module screw_cut(nut, thread, h=10, tolerance=1.05, head_embed=false, with_nut=true, nut_cut_h=1000, with_head=true, head_cut_h=1000, nut_offset=0, cut_access=true, orient=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;
    head_h = get_screw_head_h(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)
    {
        translate([0,0,head_embed?-head_h:0])
        {
            if(with_head)
            {
                translate([0,0,h/2+.01])
                screw_head_cut(thread=thread_, tolerance=tolerance, override_h=head_cut_h, align=Z);
            }

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

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

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

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

module screw_thread_cut(thread, h=10, tolerance=1.05, orient=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(thread, tolerance=1.00, override_h=U, orient=Z, align=N)
{
    assert(thread!=U, "screw_head: thread is undef");

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

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

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

module screw_nut(nut, 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);
    cylindera($fn=nut_facets, d=nut_dia, h=fallback(override_h, nut_thick), orient=orient, align=align);
}

module screw_nut_cut(nut, tolerance=1.05, h=1000, 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)
    {
        translate([0,0,nut_thick/2])
        {
            screw_nut(nut, tolerance, orient=Z, align=-Z);
            translate([0,0,-nut_thick+.01])
            {
                cylindera(d=nut_dia+2*mm, h=h, orient=Z, align=-Z);
            }
        }
    }
}

// distance from center to flat on a polygon (taking in the diagonal distance)
function apothem(radius, facets) = radius/cos(180/facets);

function nut_radius(nut) = apothem(get(NutWidthMax, nut)/2, get(NutFacets, nut));
function nut_dia(nut) = 2*nut_radius(nut);

module nut_trap_cut(nut, thread, 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(thread);
    nut_h = get(NutThickness, nut) +.5*mm;

    nut_width_min = get(NutWidthMin, nut);
    nut_facets = get(NutFacets, nut);
    nut_dia = nut_dia(nut);
    total_h = nut_h;
    size_align(size=[nut_dia, nut_dia, total_h], orient=orient, orient_ref=Z, align=align)
    {
        if(cut_screw)
        {
            translate(-nut_h/2*Z)
            translate(screw_offset*Z)
            screw_cut($show_vit=false, nut=nut, thread=thread_, with_nut=false, tolerance=1.1, h=screw_l, orient=-Z, align=Z);
        }
        else
        {
            translate([0,0,nut_h/2+screw_offset])
            screw_thread_cut(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)
        {
            translate(-nut_h/2*Z)
            translate(screw_offset*Z)
            %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);
    }
}

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


top of the tower is bigger, to avoid issues with small layers w/o cooling


cross must be a bit bigger in order to print correctly...


holder is now simpler and a bit wider

holder is now simpler and a bit wider

/*
 * Brown Orla-B brush holder (wall-attached).
 */
$fn=30;

corrners = [ [-1,-1,0], [-1,+1,0], [+1,-1,0], [+1,+1,0] ];

// wall-mounted part
module wall(tr, size)
{
  translate(tr)
    hull()
      difference()
      {
        for(t = corrners)
        {
          assign( off = [size[0]/2*t[0], size[1]/2*t[1], 0*t[2]] )
            translate(off)
              sphere(size[2]);
        };
        translate([0,0,-size[2]]) cube(2*size, center=true);
      }
}

// water drops catching plane
module plane(tr, size)
{
  rotate([90,0,0])
    translate(tr)
      hull()
        for(t = corrners)
        {
          assign( off = [size[0]/2*t[0], size[1]/2*t[1], 0*t[2]] )
            translate(off)
              sphere(size[2]);
        };
}

// element for holding a single brush
module holder(tr, size)
{
  translate(tr)
  {
    cube([size[0], 7, size[2]]);
    translate([0, 7, size[2]-6])
      cube([size[0], size[1]-7, 6]);
  }
}

wall([0,0,0], [36,50,2]);
plane([0,16.5,50/2-2], [36-2*2,29,2]);
holder([20/2-1,-1,2], [4,25,18]);
holder([-20/2-1,-1,2], [4,25,18]);

/*
 * Brown Orla-B brush holder (wall-attached).
 */
$fn=30;

corrners = [ [-1,-1,0], [-1,+1,0], [+1,-1,0], [+1,+1,0] ];

// wall-mounted part
module wall(tr, size)
{
  translate(tr)
    hull()
      difference()
      {
        for(t = corrners)
        {
          assign( off = [size[0]/2*t[0], size[1]/2*t[1], 0*t[2]] )
            translate(off)
              sphere(size[2]);
        };
        translate([0,0,-size[2]]) cube(2*size, center=true);
      }
}

// water drops catching plane
module plane(tr, size)
{
  rotate([90,0,0])
    translate(tr)
      hull()
        for(t = corrners)
        {
          assign( off = [size[0]/2*t[0], size[1]/2*t[1], 0*t[2]] )
            translate(off)
              sphere(size[2]);
        };
}

// element for holding a single brush
module holder(tr, size)
{
  translate(tr)
  {
    difference()
    {
      cube(size);
      translate([0,7.5,0])
        cube([size[0],size[1]-7.5,size[2]-7.5]);
    }
    translate([size[0],0,size[2]-(7.5-3.5)])
      cube([3-2,size[1],7.5-3.5]);
  }
}

wall([0,0,0], [36,50,2]);
plane([0,16.5,50/2-2], [36-2*2,29,2]);
holder([20/2-1,-1,2], [2,19,23.5]);
holder([-20/2-1,-1,2], [2,19,23.5]);


Refine circle quadrants constants

Refine circle quadrants constants

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

/**
 * Part of the camelSCAD library.
 *
 * Global constants to include.
 *
 * @package core/constants
 * @author jsconan
 */

/**
 * The name of the development rendering mode.
 * @type String
 */
MODE_DEV = "dev";

/**
 * The name of the production rendering mode.
 * @type String
 */
MODE_PROD = "prod";

/**
 * The name of the dirty rendering mode.
 * @type String
 */
MODE_DIRTY = "dirty";

/**
 * The name of the default rendering mode.
 * @type String
 */
DEFAULT_MODE = MODE_DEV;

/**
 * Degrees in a circle.
 * @type Number
 */
DEGREES = 360;

/**
 * Degrees of a right angle.
 * @type Number
 */
RIGHT = 90;

/**
 * Degrees of a straight angle.
 * @type Number
 */
STRAIGHT = 180;

/**
 * The end angle of the first quadrant in a circle.
 * @type Number
 */
QUADRANT_1 = RIGHT;

/**
 * The end angle of the second quadrant in a circle.
 * @type Number
 */
QUADRANT_2 = STRAIGHT;

/**
 * The end angle of the third quadrant in a circle.
 * @type Number
 */
QUADRANT_3 = DEGREES - RIGHT;

/**
 * The end angle of the fourth quadrant in a circle.
 * @type Number
 */
QUADRANT_4 = DEGREES;

/**
 * Useful value for computations based on hexagons.
 * @type Number
 */
SQRT3 = sqrt(3);

/**
 * Minimum value for $fa and $fs.
 * @type Number
 */
MIN_ANGLE = 0.01;

/**
 * Minimum allowed size.
 * @type Number
 */
MIN_SIZE = 0.000001;

/**
 * A very very small value.
 * @type Number
 */
EPSILON = 0.0000001;

/**
 * The maximum number of decimals
 * @type Number
 */
MAX_DECIMALS = 7;

/**
 * A value utilized to align wall and ensure proper cuts on one side.
 * @type Number
 */
ALIGN = 0.005;

/**
 * A value utilized to align wall and ensure proper cuts on both sides.
 * @type Number
 */
ALIGN2 = 2 * ALIGN;

/**
 * The default size of the build plate.
 * @type Number
 */
DEFAULT_BUILD_PLATE_SIZE = 200;

/**
 * The default size of the build volume.
 * @type Number
 */
DEFAULT_BUILD_VOLUME_SIZE = DEFAULT_BUILD_PLATE_SIZE;

/**
 * The default size of a cell on the build plate.
 * @type Number
 */
DEFAULT_BUILD_PLATE_CELL = 10;

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

/**
 * Part of the camelSCAD library.
 *
 * Global constants to include.
 *
 * @package core/constants
 * @author jsconan
 */

/**
 * The name of the development rendering mode.
 * @type String
 */
MODE_DEV = "dev";

/**
 * The name of the production rendering mode.
 * @type String
 */
MODE_PROD = "prod";

/**
 * The name of the dirty rendering mode.
 * @type String
 */
MODE_DIRTY = "dirty";

/**
 * The name of the default rendering mode.
 * @type String
 */
DEFAULT_MODE = MODE_DEV;

/**
 * Degrees in a circle.
 * @type Number
 */
DEGREES = 360;

/**
 * Degrees of a right angle.
 * @type Number
 */
RIGHT = 90;

/**
 * Degrees of a straight angle.
 * @type Number
 */
STRAIGHT = 180;

/**
 * The end angle of the first quadrant in a circle.
 * @type Number
 */
QUADRANT_1 = 90;

/**
 * The end angle of the second quadrant in a circle.
 * @type Number
 */
QUADRANT_2 = 180;

/**
 * The end angle of the third quadrant in a circle.
 * @type Number
 */
QUADRANT_3 = 270;

/**
 * The end angle of the fourth quadrant in a circle.
 * @type Number
 */
QUADRANT_4 = 360;

/**
 * Useful value for computations based on hexagons.
 * @type Number
 */
SQRT3 = sqrt(3);

/**
 * Minimum value for $fa and $fs.
 * @type Number
 */
MIN_ANGLE = 0.01;

/**
 * Minimum allowed size.
 * @type Number
 */
MIN_SIZE = 0.000001;

/**
 * A very very small value.
 * @type Number
 */
EPSILON = 0.0000001;

/**
 * The maximum number of decimals
 * @type Number
 */
MAX_DECIMALS = 7;

/**
 * A value utilized to align wall and ensure proper cuts on one side.
 * @type Number
 */
ALIGN = 0.005;

/**
 * A value utilized to align wall and ensure proper cuts on both sides.
 * @type Number
 */
ALIGN2 = 2 * ALIGN;

/**
 * The default size of the build plate.
 * @type Number
 */
DEFAULT_BUILD_PLATE_SIZE = 200;

/**
 * The default size of the build volume.
 * @type Number
 */
DEFAULT_BUILD_VOLUME_SIZE = DEFAULT_BUILD_PLATE_SIZE;

/**
 * The default size of a cell on the build plate.
 * @type Number
 */
DEFAULT_BUILD_PLATE_CELL = 10;


removed deprecated function

removed deprecated function

/*
 * Brown Orla-B brush holder (wall-attached).
 */
$fn=30;

corrners = [ [-1,-1,0], [-1,+1,0], [+1,-1,0], [+1,+1,0] ];

// wall-mounted part
module wall(tr, size)
{
  translate(tr)
    hull()
      difference()
      {
        for(t = corrners)
          translate([size[0]/2*t[0], size[1]/2*t[1], 0*t[2]])
            sphere(size[2]);
        translate([0,0,-size[2]]) cube(2*size, center=true);
      }
}

// water drops catching plane
module plane(tr, size)
{
  rotate([90,0,0])
    translate(tr)
      hull()
        for(t = corrners)
          translate([size[0]/2*t[0], size[1]/2*t[1], 0*t[2]])
            sphere(size[2]);
}

// element for holding a single brush
module holder(tr, size)
{
  translate(tr)
  {
    cube([size[0], 7, size[2]]);
    translate([0, 7, size[2]-6])
      cube([size[0], size[1]-7, 6]);
  }
}

wall([0,0,0], [36,50,2]);
plane([0,16.5,50/2-2], [36-2*2,29,2]);
holder([20/2-1,-1,2], [3,25,18]);
holder([-20/2-1,-1,2], [3,25,18]);

/*
 * Brown Orla-B brush holder (wall-attached).
 */
$fn=30;

corrners = [ [-1,-1,0], [-1,+1,0], [+1,-1,0], [+1,+1,0] ];

// wall-mounted part
module wall(tr, size)
{
  translate(tr)
    hull()
      difference()
      {
        for(t = corrners)
        {
          assign( off = [size[0]/2*t[0], size[1]/2*t[1], 0*t[2]] )
            translate(off)
              sphere(size[2]);
        };
        translate([0,0,-size[2]]) cube(2*size, center=true);
      }
}

// water drops catching plane
module plane(tr, size)
{
  rotate([90,0,0])
    translate(tr)
      hull()
        for(t = corrners)
        {
          assign( off = [size[0]/2*t[0], size[1]/2*t[1], 0*t[2]] )
            translate(off)
              sphere(size[2]);
        };
}

// element for holding a single brush
module holder(tr, size)
{
  translate(tr)
  {
    cube([size[0], 7, size[2]]);
    translate([0, 7, size[2]-6])
      cube([size[0], size[1]-7, 6]);
  }
}

wall([0,0,0], [36,50,2]);
plane([0,16.5,50/2-2], [36-2*2,29,2]);
holder([20/2-1,-1,2], [3,25,18]);
holder([-20/2-1,-1,2], [3,25,18]);


main: render belts in preview_mode

main: render belts in preview_mode

use <thing_libutils/metric-screw.scad>
use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/transforms.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/linear-extrusion.scad>;
use <thing_libutils/timing-belts.scad>;
include <thing_libutils/timing-belts-data.scad>;

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

/*include <extruder-direct.scad>*/
include <x-axis-end.scad>
include <x-carriage.scad>
include <y-axis-motor-mount.scad>
include <y-axis-carriage-bearing-mount.scad>
include <y-axis-carriage-belt-clamp.scad>
include <y-axis-idler.scad>
include <z-axis-motor-mount.scad>
use <gantry-upper-connector.scad>
use <gantry-lower-connector.scad>
include <psu.scad>
use <rod-clamps.scad>
use <lcd2004.scad>
use <power-panel-iec320.scad>

/*use <scad-utils/trajectory.scad>*/
/*use <scad-utils/trajectory_path.scad>*/
/*use <scad-utils/transformations.scad>*/
/*use <scad-utils/shapes.scad>*/
/*use <list-comprehension-demos/skin.scad>*/

// x carriage
axis_range_x_ = main_width/2 + zmotor_mount_rod_offset_x - xaxis_end_width(true) - x_carriage_w/2;
axis_range_x = [-1* axis_range_x_,-1*axis_range_x_+x_carriage_w];
axis_printrange_x = [-1/2, 1/2] * printbed_size[0];
axis_x_parked = [true, false];

axis_range_y=[0*mm,200*mm];
axis_pos_y = axis_range_y[0];
axis_range_z=[90*mm,353*mm];
axis_pos_z = axis_range_z[0];

echo(str("Build area Z: " , axis_range_z[1]-axis_range_z[0] , " mm"));

module x_axis()
{
    // x axis
    translate([0,0,axis_pos_z])
    {
        zrod_offset = zmotor_mount_rod_offset_x;
        for(z=[-1,1])
        for(z=xaxis_beltpath_z_offsets)
        translate([-main_width/2-zrod_offset+xaxis_end_motor_offset[0], xaxis_zaxis_distance_y, z])
        rotate([90,0,0])
        belt_path(main_width+2*(zrod_offset)+xaxis_end_motor_offset[0], 6, xaxis_pulley_inner_d, orient=[1,0,0], align=[1,0,0]);

        for(x=[0:len(axis_range_x)-1])
        {
            /*#cubea(size=[x_carriage_w,10,100]);*/

            pos = axis_x_parked[x] ? axis_range_x[x] : -axis_printrange_x[x];

            translate([pos,0,0])
            mirror([x==0?0:1,0,0])
            attach(xaxis_carriage_conn, [[0,-xaxis_zaxis_distance_y,0],[0,0,0]])
            {
                x_carriage_withmounts(show_vitamins=true, beltpath_offset=x==0?-1:1);

                x_carriage_extruder(show_vitamins=true, with_sensormount=x==0);
            }
        }

        // x smooth rods
        color(color_rods)
        for(z=[-1,1])
            translate([xaxis_rod_offset_x,xaxis_zaxis_distance_y,z*(xaxis_rod_distance/2)])
                cylindera(h=xaxis_rod_l,d=xaxis_rod_d+.1, orient=[1,0,0]);

        for(x=[-1,1])
        {
            translate([x*(main_width/2), 0, 0])
            translate([0, xaxis_zaxis_distance_y, 0])
            translate([x*zmotor_mount_rod_offset_x, 0, 0])
            {
                mirror([max(0,x),0,0])
                xaxis_end(with_motor=true, beltpath_index=max(0,x), show_nut=true, show_motor=true, show_nut=true);
            }
        }
    }
}

module y_axis()
{
    // y axis
    color(color_part)
    attach([[yaxis_belt_path_offset_x,main_depth/2,yaxis_motor_offset_z], [0,-1,0]], yaxis_motor_mount_conn)
    {
        yaxis_motor_mount(show_motor=true);
    }

    extrusion_idler_conn = [[yaxis_belt_path_offset_x, -main_depth/2-extrusion_size, -extrusion_size+yaxis_idler_offset_z], [0,-1,0]];
    attach(extrusion_idler_conn, yaxis_idler_conn)
    {
        color(color_part)
        yaxis_idler();

        attach(yaxis_idler_conn_pulleyblock, yaxis_idler_pulleyblock_conn)
        {
            color(color_part)
            yaxis_idler_pulleyblock(show_pulley=true);
        }
    }

    translate([yaxis_belt_path_offset_x,0,yaxis_belt_path_offset_z])
    {
        translate([0,main_depth/2-yaxis_motor_offset_x,0])
        {
            belt_path(main_depth-yaxis_motor_offset_x-yaxis_idler_pulley_offset_y, 6, yaxis_pulley_inner_d, align=[0,-1,0], orient=[0,1,0]);
        }
    }

    color(color_part)
    translate([0,-axis_pos_y,yaxis_bearing[0]/2])
    attach(yaxis_carriage_bearing_mount_conn_bearing, yaxis_belt_mount_conn)
    {
        yaxis_belt_holder();
    }

    translate([0,0,yaxis_bearing[0]/2])
    {
        for(x=[-1,1])
        for(y=[-1,1])
        {
            attach([[x*(yaxis_rod_distance/2),y*(main_depth/2+extrusion_size/2),0],[0,0,1]],mount_rod_clamp_conn_rod)
            {
                mount_rod_clamp_full(rod_d=zaxis_rod_d, thick=4, width=extrusion_size, thread=zmotor_mount_clamp_thread, orient=[0,1,0]);
            }
        }

        // y smooth rods
        for(x=[-1,1])
        translate([x*(yaxis_rod_distance/2), 0, 0])
        {
            color(color_rods)
            cylindera(h=yaxis_rod_l,d=yaxis_rod_d, orient=[0,1,0]);

            for(y=[-1,1])
            {
                attach([[0,y*(yaxis_bearing_distance_y/2)-axis_pos_y,0],[0,0,-1]], yaxis_carriage_bearing_mount_conn_bearing)
                {
                    yaxis_carriage_bearing_mount(show_bearing=true);
                }
            }
        }

        attach(yaxis_carriage_bearing_mount_conn_bearing, [[0,axis_pos_y,0],[0,0,1]])
        {
            yaxis_carriage_size_inner = [32*mm,32*mm,0];

            // y axis plate "arms"
            for(x=[-1,1])
            for(y=[-1,1])
            hull()
            {
                translate([x*yaxis_carriage_size[0]/2, y*yaxis_carriage_size[1]/2, 0])
                {
                    cylindera(d=10*mm, h=yaxis_carriage_size[2], align=[-x,-y,1]);
                }
                translate([x*(yaxis_carriage_size[0]/2-yaxis_carriage_size_inner[0]/2), y*(yaxis_carriage_size[1]/2-yaxis_carriage_size_inner[1]/2*mm), 0])
                {
                    cylindera(d=10*mm, h=yaxis_carriage_size[2], align=[-x,-y,1]);
                }
            }

            // y axis plate
            cubea(yaxis_carriage_size - yaxis_carriage_size_inner, align=[0,0,1]);

            translate([0,0,10*mm])
                cubea(printbed_size, align=[0,0,1]);
        }
    }

}

module z_axis()
{
    // z axis
    for(x=[-1,1])
    {
        translate([x*(main_width/2),0,main_height])
        {
            mirror([x==-1?1:0,0,0])
            {
                color(color_part)
                translate([zmotor_mount_rod_offset_x, 0, extrusion_size/2])
                {
                    mount_rod_clamp_half(
                            rod_d=zaxis_rod_d,
                            screw_dist=zmotor_mount_clamp_dist,
                            thick=5,
                            base_thick=5,
                            width=zmotor_mount_thickness_h,
                            thread=zmotor_mount_clamp_thread);
                }
            }
        }

        translate([x*(main_width/2), 0, 0])
        {
            translate([0,0,zaxis_motor_offset_z])
                mirror([x==-1?1:0,0,0])
                {
                    color(color_part)
                    zaxis_motor_mount(show_motor=true);

                    color(color_part)
                    translate([zmotor_mount_rod_offset_x, 0, zmotor_mount_thickness_h/2])
                    {
                        mount_rod_clamp_half(
                                rod_d=zaxis_rod_d,
                                screw_dist=zmotor_mount_clamp_dist,
                                thick=5,
                                base_thick=5,
                                width=zmotor_mount_thickness_h,
                                thread=zmotor_mount_clamp_thread);
                    }
                }

            // z smooth rods
            translate([x*(zmotor_mount_rod_offset_x),0,0])
            {
                // z rods
                color(color_rods)
                translate([0,0,zaxis_motor_offset_z-80*mm])
                    cylindera(h=zaxis_rod_l,d=zaxis_rod_d, align=[0,0,1]);

                for(z=[-1,1])
                    translate([0,0,axis_pos_z-z*xaxis_rod_distance/2])
                        bearing(zaxis_bearing);

            }
        }
    }

}

module main()
{
    translate([0,0,-main_lower_dist_z/2])
    gantry_lower();

    translate(-zaxis_rod_offset)
    gantry_upper();

    x_axis();
    y_axis();
    z_axis();

    translate([-75*mm,0,0])
    translate([0,main_depth/2,0])
    translate([0,extrusion_size,0])
    translate([0,0,-main_lower_dist_z/2-extrusion_size/2])
    power_panel_iec320(orient=[0,-1,0], align=[0,1,0]);

    if(!$preview_mode)
    {
        translate([0,-main_depth/2,0])
        translate([0,-extrusion_size/2,0])
        translate([0,0,-main_lower_dist_z/2])
        mount_lcd2004(show_gantry=true);

        for(x=[-1,1])
        translate([x*(main_width/2-extrusion_size),main_depth/2,-main_lower_dist_z-extrusion_size])
        {
            translate([-x*psu_a_w/2, -psu_a_d/2, psu_a_h/2])
            {
                psu_a();

                mirror([x==-1?1:0,0,0])
                    translate([0, -psu_a_screw_dist_y/2, 0])
                    psu_a_extrusion_bracket_side();

                translate([0, psu_a_screw_dist_y/2, 0])
                    psu_a_extrusion_bracket_back();
            }
        }

        translate([0,-main_depth/2,-main_lower_dist_z-extrusion_size])
            translate([-100,100,0])
            rotate([0,0,270])
            import("stl/RAMPS1_4.STL");
    }
}

module gantry_upper()
{
    color(color_extrusion)
    for(y=[-1,1])
    translate([0,y*(main_upper_dist_y/2),0])
    {
        for(x=[-1,1])
        translate([x*(main_width/2), 0, 0])
        {
            if($preview_mode)
            {
                cubea(size=[extrusion_size, extrusion_size, main_height], align=[-x,0,1]);
            }
            else
            {
                linear_extrusion(h=main_height, align=[-x,0,1], orient=[0,0,1]);
            }
        }

        translate([0, 0, main_height])
        {
            if($preview_mode)
            {
                cubea(size=[main_upper_width, extrusion_size, extrusion_size], align=[0,0,1]);
            }
            else
            {
                linear_extrusion(h=main_upper_width, align=[0,0,1], orient=[1,0,0]);
            }
        }
    }

    // upper gantry connectors
    for(x=[-1,1])
    {
        translate([x*(main_width/2),0,main_height])
        {
            mirror([x==-1?1:0,0,0])
            {
                color(color_gantry_connectors)
                    gantry_upper_connector();
            }

        }
    }
}

module gantry_lower()
{
    color(color_extrusion)
    for(z=[-1,1])
    {
        translate([0,0,z*-main_lower_dist_z/2])
        {
            for(y=[-1,1])
            translate([0, y*(main_depth/2), 0])
            {
                if($preview_mode)
                {
                    cubea([main_width, extrusion_size, extrusion_size], align=[0,y,-1]);
                }
                else
                {
                    linear_extrusion(h=main_width, align=[0,y,-1], orient=[1,0,0]);
                }
            }

            for(x=[-1,1])
            translate([x*(main_width/2), 0, 0])
            {
                if($preview_mode)
                {
                    cubea([extrusion_size, main_depth, extrusion_size], align=[-x,0,-1]);
                }
                else
                {
                    linear_extrusion(h=main_depth, align=[-x,0,-1], orient=[0,1,0]);
                }
            }
        }

    }

    // lower gantry connectors
    for(x=[-1,1])
    for(y=[-1,1])
    {
        translate([x*(main_width/2),y*(main_depth/2),-extrusion_size/2])
        {
            mirror([x==1?0:-1,0,0])
            mirror([0,y==1?1:0,0])
            {
                color(color_gantry_connectors)
                    gantry_lower_connector();
            }

        }
    }
}

module enclosure()
{
    // inner
    w=56*cm;
    h=56*cm;
    d=58*cm;
    wallthick=2*cm;
    backthick=0.5*cm;

    translate([0, 0, h/2+wallthick])
    {
        // left/right walls
        for(x=[-1,1])
        translate([x*w/2,0,0])
        cubea([wallthick,d,h], align=[x, 0, 0]);

        // back plate
        translate([0,d/2,0])
        cubea([w,backthick,h], align=[0,-1, 0]);

        // top/bottom plate
        for(z=[-1,1])
        translate([0,0,z*h/2])
        cubea([w+wallthick*2,d,wallthick], align=[0,0, z]);
    }
}

feet_height = 8*mm;
translate([0, 0, main_lower_dist_z+extrusion_size*2+feet_height])
main();

/*psu();*/

/*%enclosure();*/

use <thing_libutils/metric-screw.scad>
use <thing_libutils/shapes.scad>;
use <thing_libutils/misc.scad>;
use <thing_libutils/transforms.scad>;
use <thing_libutils/attach.scad>;
use <thing_libutils/linear-extrusion.scad>;
use <thing_libutils/timing-belts.scad>;
include <thing_libutils/timing-belts-data.scad>;

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

/*include <extruder-direct.scad>*/
include <x-axis-end.scad>
include <x-carriage.scad>
include <y-axis-motor-mount.scad>
include <y-axis-carriage-bearing-mount.scad>
include <y-axis-carriage-belt-clamp.scad>
include <y-axis-idler.scad>
include <z-axis-motor-mount.scad>
use <gantry-upper-connector.scad>
use <gantry-lower-connector.scad>
include <psu.scad>
use <rod-clamps.scad>
use <lcd2004.scad>
use <power-panel-iec320.scad>

/*use <scad-utils/trajectory.scad>*/
/*use <scad-utils/trajectory_path.scad>*/
/*use <scad-utils/transformations.scad>*/
/*use <scad-utils/shapes.scad>*/
/*use <list-comprehension-demos/skin.scad>*/

// x carriage
axis_range_x_ = main_width/2 + zmotor_mount_rod_offset_x - xaxis_end_width(true) - x_carriage_w/2;
axis_range_x = [-1* axis_range_x_,-1*axis_range_x_+x_carriage_w];
axis_printrange_x = [-1/2, 1/2] * printbed_size[0];
axis_x_parked = [true, false];

axis_range_y=[0*mm,200*mm];
axis_pos_y = axis_range_y[0];
axis_range_z=[90*mm,353*mm];
axis_pos_z = axis_range_z[0];

echo(str("Build area Z: " , axis_range_z[1]-axis_range_z[0] , " mm"));

module x_axis()
{
    // x axis
    translate([0,0,axis_pos_z])
    {
        zrod_offset = zmotor_mount_rod_offset_x;
        for(z=[-1,1])
        for(z=xaxis_beltpath_z_offsets)
        translate([-main_width/2-zrod_offset+xaxis_end_motor_offset[0], xaxis_zaxis_distance_y, z])
        rotate([90,0,0])
        belt_path(main_width+2*(zrod_offset)+xaxis_end_motor_offset[0], 6, xaxis_pulley_inner_d, orient=[1,0,0], align=[1,0,0]);

        for(x=[0:len(axis_range_x)-1])
        {
            /*#cubea(size=[x_carriage_w,10,100]);*/

            pos = axis_x_parked[x] ? axis_range_x[x] : -axis_printrange_x[x];

            translate([pos,0,0])
            mirror([x==0?0:1,0,0])
            attach(xaxis_carriage_conn, [[0,-xaxis_zaxis_distance_y,0],[0,0,0]])
            {
                x_carriage_withmounts(show_vitamins=true, beltpath_offset=x==0?-1:1);

                x_carriage_extruder(show_vitamins=true, with_sensormount=x==0);
            }
        }

        // x smooth rods
        color(color_rods)
        for(z=[-1,1])
            translate([xaxis_rod_offset_x,xaxis_zaxis_distance_y,z*(xaxis_rod_distance/2)])
                cylindera(h=xaxis_rod_l,d=xaxis_rod_d+.1, orient=[1,0,0]);

        for(x=[-1,1])
        {
            translate([x*(main_width/2), 0, 0])
            translate([0, xaxis_zaxis_distance_y, 0])
            translate([x*zmotor_mount_rod_offset_x, 0, 0])
            {
                mirror([max(0,x),0,0])
                xaxis_end(with_motor=true, beltpath_index=max(0,x), show_nut=true, show_motor=true, show_nut=true);
            }
        }
    }
}

module y_axis()
{
    // y axis
    color(color_part)
    attach([[yaxis_belt_path_offset_x,main_depth/2,yaxis_motor_offset_z], [0,-1,0]], yaxis_motor_mount_conn)
    {
        yaxis_motor_mount(show_motor=true);
    }

    extrusion_idler_conn = [[yaxis_belt_path_offset_x, -main_depth/2-extrusion_size, -extrusion_size+yaxis_idler_offset_z], [0,-1,0]];
    attach(extrusion_idler_conn, yaxis_idler_conn)
    {
        color(color_part)
        yaxis_idler();

        attach(yaxis_idler_conn_pulleyblock, yaxis_idler_pulleyblock_conn)
        {
            color(color_part)
            yaxis_idler_pulleyblock(show_pulley=true);
        }
    }

    translate([yaxis_belt_path_offset_x,0,yaxis_belt_path_offset_z])
    {
        if(!$preview_mode)
        {
            translate([0,main_depth/2-yaxis_motor_offset_x,0])
            {
                /*cubea([10,main_depth-yaxis_motor_offset_x,10], align=[0,-1,0]);*/
                belt_path(main_depth-yaxis_motor_offset_x-yaxis_idler_pulley_offset_y, 6, yaxis_pulley_inner_d, align=[0,-1,0], orient=[0,1,0]);
            }
        }
    }

    color(color_part)
    translate([0,-axis_pos_y,yaxis_bearing[0]/2])
    attach(yaxis_carriage_bearing_mount_conn_bearing, yaxis_belt_mount_conn)
    {
        yaxis_belt_holder();
    }

    translate([0,0,yaxis_bearing[0]/2])
    {
        for(x=[-1,1])
        for(y=[-1,1])
        {
            attach([[x*(yaxis_rod_distance/2),y*(main_depth/2+extrusion_size/2),0],[0,0,1]],mount_rod_clamp_conn_rod)
            {
                mount_rod_clamp_full(rod_d=zaxis_rod_d, thick=4, width=extrusion_size, thread=zmotor_mount_clamp_thread, orient=[0,1,0]);
            }
        }

        // y smooth rods
        for(x=[-1,1])
        translate([x*(yaxis_rod_distance/2), 0, 0])
        {
            color(color_rods)
            cylindera(h=yaxis_rod_l,d=yaxis_rod_d, orient=[0,1,0]);

            for(y=[-1,1])
            {
                attach([[0,y*(yaxis_bearing_distance_y/2)-axis_pos_y,0],[0,0,-1]], yaxis_carriage_bearing_mount_conn_bearing)
                {
                    yaxis_carriage_bearing_mount(show_bearing=true);
                }
            }
        }

        attach(yaxis_carriage_bearing_mount_conn_bearing, [[0,axis_pos_y,0],[0,0,1]])
        {
            yaxis_carriage_size_inner = [32*mm,32*mm,0];

            // y axis plate "arms"
            for(x=[-1,1])
            for(y=[-1,1])
            hull()
            {
                translate([x*yaxis_carriage_size[0]/2, y*yaxis_carriage_size[1]/2, 0])
                {
                    cylindera(d=10*mm, h=yaxis_carriage_size[2], align=[-x,-y,1]);
                }
                translate([x*(yaxis_carriage_size[0]/2-yaxis_carriage_size_inner[0]/2), y*(yaxis_carriage_size[1]/2-yaxis_carriage_size_inner[1]/2*mm), 0])
                {
                    cylindera(d=10*mm, h=yaxis_carriage_size[2], align=[-x,-y,1]);
                }
            }

            // y axis plate
            cubea(yaxis_carriage_size - yaxis_carriage_size_inner, align=[0,0,1]);

            translate([0,0,10*mm])
                cubea(printbed_size, align=[0,0,1]);
        }
    }

}

module z_axis()
{
    // z axis
    for(x=[-1,1])
    {
        translate([x*(main_width/2),0,main_height])
        {
            mirror([x==-1?1:0,0,0])
            {
                color(color_part)
                translate([zmotor_mount_rod_offset_x, 0, extrusion_size/2])
                {
                    mount_rod_clamp_half(
                            rod_d=zaxis_rod_d,
                            screw_dist=zmotor_mount_clamp_dist,
                            thick=5,
                            base_thick=5,
                            width=zmotor_mount_thickness_h,
                            thread=zmotor_mount_clamp_thread);
                }
            }
        }

        translate([x*(main_width/2), 0, 0])
        {
            translate([0,0,zaxis_motor_offset_z])
                mirror([x==-1?1:0,0,0])
                {
                    color(color_part)
                    zaxis_motor_mount(show_motor=true);

                    color(color_part)
                    translate([zmotor_mount_rod_offset_x, 0, zmotor_mount_thickness_h/2])
                    {
                        mount_rod_clamp_half(
                                rod_d=zaxis_rod_d,
                                screw_dist=zmotor_mount_clamp_dist,
                                thick=5,
                                base_thick=5,
                                width=zmotor_mount_thickness_h,
                                thread=zmotor_mount_clamp_thread);
                    }
                }

            // z smooth rods
            translate([x*(zmotor_mount_rod_offset_x),0,0])
            {
                // z rods
                color(color_rods)
                translate([0,0,zaxis_motor_offset_z-80*mm])
                    cylindera(h=zaxis_rod_l,d=zaxis_rod_d, align=[0,0,1]);

                for(z=[-1,1])
                    translate([0,0,axis_pos_z-z*xaxis_rod_distance/2])
                        bearing(zaxis_bearing);

            }
        }
    }

}

module main()
{
    translate([0,0,-main_lower_dist_z/2])
    gantry_lower();

    translate(-zaxis_rod_offset)
    gantry_upper();

    x_axis();
    y_axis();
    z_axis();

    translate([-75*mm,0,0])
    translate([0,main_depth/2,0])
    translate([0,extrusion_size,0])
    translate([0,0,-main_lower_dist_z/2-extrusion_size/2])
    power_panel_iec320(orient=[0,-1,0], align=[0,1,0]);

    if(!$preview_mode)
    {
        translate([0,-main_depth/2,0])
        translate([0,-extrusion_size/2,0])
        translate([0,0,-main_lower_dist_z/2])
        mount_lcd2004(show_gantry=true);

        for(x=[-1,1])
        translate([x*(main_width/2-extrusion_size),main_depth/2,-main_lower_dist_z-extrusion_size])
        {
            translate([-x*psu_a_w/2, -psu_a_d/2, psu_a_h/2])
            {
                psu_a();

                mirror([x==-1?1:0,0,0])
                    translate([0, -psu_a_screw_dist_y/2, 0])
                    psu_a_extrusion_bracket_side();

                translate([0, psu_a_screw_dist_y/2, 0])
                    psu_a_extrusion_bracket_back();
            }
        }

        translate([0,-main_depth/2,-main_lower_dist_z-extrusion_size])
            translate([-100,100,0])
            rotate([0,0,270])
            import("stl/RAMPS1_4.STL");
    }
}

module gantry_upper()
{
    color(color_extrusion)
    for(y=[-1,1])
    translate([0,y*(main_upper_dist_y/2),0])
    {
        for(x=[-1,1])
        translate([x*(main_width/2), 0, 0])
        {
            if($preview_mode)
            {
                cubea(size=[extrusion_size, extrusion_size, main_height], align=[-x,0,1]);
            }
            else
            {
                linear_extrusion(h=main_height, align=[-x,0,1], orient=[0,0,1]);
            }
        }

        translate([0, 0, main_height])
        {
            if($preview_mode)
            {
                cubea(size=[main_upper_width, extrusion_size, extrusion_size], align=[0,0,1]);
            }
            else
            {
                linear_extrusion(h=main_upper_width, align=[0,0,1], orient=[1,0,0]);
            }
        }
    }

    // upper gantry connectors
    for(x=[-1,1])
    {
        translate([x*(main_width/2),0,main_height])
        {
            mirror([x==-1?1:0,0,0])
            {
                color(color_gantry_connectors)
                    gantry_upper_connector();
            }

        }
    }
}

module gantry_lower()
{
    color(color_extrusion)
    for(z=[-1,1])
    {
        translate([0,0,z*-main_lower_dist_z/2])
        {
            for(y=[-1,1])
            translate([0, y*(main_depth/2), 0])
            {
                if($preview_mode)
                {
                    cubea([main_width, extrusion_size, extrusion_size], align=[0,y,-1]);
                }
                else
                {
                    linear_extrusion(h=main_width, align=[0,y,-1], orient=[1,0,0]);
                }
            }

            for(x=[-1,1])
            translate([x*(main_width/2), 0, 0])
            {
                if($preview_mode)
                {
                    cubea([extrusion_size, main_depth, extrusion_size], align=[-x,0,-1]);
                }
                else
                {
                    linear_extrusion(h=main_depth, align=[-x,0,-1], orient=[0,1,0]);
                }
            }
        }

    }

    // lower gantry connectors
    for(x=[-1,1])
    for(y=[-1,1])
    {
        translate([x*(main_width/2),y*(main_depth/2),-extrusion_size/2])
        {
            mirror([x==1?0:-1,0,0])
            mirror([0,y==1?1:0,0])
            {
                color(color_gantry_connectors)
                    gantry_lower_connector();
            }

        }
    }
}

module enclosure()
{
    // inner
    w=56*cm;
    h=56*cm;
    d=58*cm;
    wallthick=2*cm;
    backthick=0.5*cm;

    translate([0, 0, h/2+wallthick])
    {
        // left/right walls
        for(x=[-1,1])
        translate([x*w/2,0,0])
        cubea([wallthick,d,h], align=[x, 0, 0]);

        // back plate
        translate([0,d/2,0])
        cubea([w,backthick,h], align=[0,-1, 0]);

        // top/bottom plate
        for(z=[-1,1])
        translate([0,0,z*h/2])
        cubea([w+wallthick*2,d,wallthick], align=[0,0, z]);
    }
}

feet_height = 8*mm;
translate([0, 0, main_lower_dist_z+extrusion_size*2+feet_height])
main();

/*psu();*/

/*%enclosure();*/


Disable debug chop

Disable debug chop

module MarbleCaster_STL () {
	od = connector_bore(MarbleCaster_Con_Default) - 0.5;  // include some tolerance!
	fod = od + 5;
	ballr = 16/2;

	plateThickness = connector_thickness(MarbleCaster_Con_Default);

	balltol = 0.5;

	$fn=64;

	printedPart("printedparts/MarbleCaster.scad", "Caster Housing", "MarbleCaster_STL()") {

	    view(t=[1.4, 0.8, -5.6], r=[63, 0, 114], d=172);

        color(Level2PlasticColor)
            if (UseSTL) {
                import(str(STLPath, "CasterHousing.stl"));
            } else {
                //render() // pre-render for speed
                difference() {
                    union()  {
                        // push fitting core
                        *cylinder(r=od/2, h=plateThickness+eta);

                        // push fitting upper taper
                        *translate([0, 0, plateThickness + 1])
                            cylinder(r1=od/2 + 0.5, r2=od/2 - 1, h= dw + 1);

                        // push fitting lower taper
                        *translate([0, 0, plateThickness])
                            cylinder(r1=od/2, r2=od/2 + 0.5, h=1 + eta);

                        //flange
                        translate([0, 0, -2])
                            cylinder(r=fod/2, h=2 + eta);

                        // tapered joint between ball casing and flange
                        translate([0, 0, -GroundClearance + ballr])
                            cylinder(r1=ballr + dw, r2=fod/2, h=GroundClearance - ballr + eta);

                        // ball casing
                        translate([0, 0, -GroundClearance + ballr])
                            sphere(r=ballr + dw);

                    }

                    // slit the push fitting
                    *for (i=[0,1])
                        rotate([0,0, i*90])
                        translate([-ballr, -1, eta])
                        cube([2*ballr, 2, 100]);

                    // chop the bottom off
                    translate([-50, -50, -100 - GroundClearance + ballr/2])
                        cube([100, 100, 100]);

                    // hollow the casing for the ball - allow some tolerance
                    translate([0,0, -GroundClearance + ballr])
                        sphere(ballr + balltol);

                    // taper the interior to allow for easier printing
                    *translate([0, 0, -GroundClearance + ballr])
                            cylinder(r1=ballr, r2=1, h= GroundClearance - ballr + plateThickness + dw + 2, $fn=32);

					// hollow for pin
					cylinder(r=7/2, h=100, center=true);
					translate([0,0,-10 - plateThickness])
						cylinder(r=7/2 + 1.5, h=10);

                    // cut a curve into the ball casing to allow flex for the marble to be inserted
                    // and so it looks pretty :)
                    translate([0, 0, -GroundClearance + ballr/2])
                        rotate([0, 90, 0])
                        scale([1, 0.7, 1])
                        cylinder(r=ballr, h=100, center=true, $fn=32);

                    // chop it in half for debugging
                    *translate([0, -50, -50])
                        cube([100,100,100]);
                }
            }
    }
}

module MarbleCaster_STL () {
	od = connector_bore(MarbleCaster_Con_Default) - 0.5;  // include some tolerance!
	fod = od + 5;
	ballr = 16/2;

	plateThickness = connector_thickness(MarbleCaster_Con_Default);

	balltol = 0.5;

	$fn=64;

	printedPart("printedparts/MarbleCaster.scad", "Caster Housing", "MarbleCaster_STL()") {

	    view(t=[1.4, 0.8, -5.6], r=[63, 0, 114], d=172);

        color(Level2PlasticColor)
            if (UseSTL) {
                import(str(STLPath, "CasterHousing.stl"));
            } else {
                //render() // pre-render for speed
                difference() {
                    union()  {
                        // push fitting core
                        *cylinder(r=od/2, h=plateThickness+eta);

                        // push fitting upper taper
                        *translate([0, 0, plateThickness + 1])
                            cylinder(r1=od/2 + 0.5, r2=od/2 - 1, h= dw + 1);

                        // push fitting lower taper
                        *translate([0, 0, plateThickness])
                            cylinder(r1=od/2, r2=od/2 + 0.5, h=1 + eta);

                        //flange
                        translate([0, 0, -2])
                            cylinder(r=fod/2, h=2 + eta);

                        // tapered joint between ball casing and flange
                        translate([0, 0, -GroundClearance + ballr])
                            cylinder(r1=ballr + dw, r2=fod/2, h=GroundClearance - ballr + eta);

                        // ball casing
                        translate([0, 0, -GroundClearance + ballr])
                            sphere(r=ballr + dw);

                    }

                    // slit the push fitting
                    *for (i=[0,1])
                        rotate([0,0, i*90])
                        translate([-ballr, -1, eta])
                        cube([2*ballr, 2, 100]);

                    // chop the bottom off
                    translate([-50, -50, -100 - GroundClearance + ballr/2])
                        cube([100, 100, 100]);

                    // hollow the casing for the ball - allow some tolerance
                    translate([0,0, -GroundClearance + ballr])
                        sphere(ballr + balltol);

                    // taper the interior to allow for easier printing
                    *translate([0, 0, -GroundClearance + ballr])
                            cylinder(r1=ballr, r2=1, h= GroundClearance - ballr + plateThickness + dw + 2, $fn=32);

					// hollow for pin
					cylinder(r=7/2, h=100, center=true);
					translate([0,0,-10 - plateThickness])
						cylinder(r=7/2 + 1.5, h=10);

                    // cut a curve into the ball casing to allow flex for the marble to be inserted
                    // and so it looks pretty :)
                    translate([0, 0, -GroundClearance + ballr/2])
                        rotate([0, 90, 0])
                        scale([1, 0.7, 1])
                        cylinder(r=ballr, h=100, center=true, $fn=32);

                    // chop it in half for debugging
                    translate([0, -50, -50])
                        cube([100,100,100]);
                }
            }
    }
}


widen the shade

widen the shade

bottomOuterRadius = 52;

intersection_xTranslate = -58;

outerRadius = 90;

squareLength = 59;

top_zTranslate = 1;

xScale = 0.2;

yScale = 0.7;

use <../christmas-story-lamp-shade.scad>

//translate([-120, 0, 0])
// translate([9, 18, 0])
// %import("/home/roberto/Versioning/world/betoland/household/lamps/christmas-story-leg-lamp/jetpuf/files/LegLamp_Shade130.stl");

legLampShade(intersection_xTranslate = intersection_xTranslate,
             bottomOuterRadius = bottomOuterRadius,
             outerRadius = outerRadius,
             squareLength = squareLength,
             top_zTranslate = top_zTranslate,
             xScale = xScale,
             yScale = yScale);

bottomOuterRadius = 52;

intersection_xTranslate = -51;

outerRadius = 90;
//outerRadius = 36;

squareLength = 59;  //28;

top_zTranslate = 5;

xScale = 0.2;       // 0.3;

yScale = 0.7;       // 0.7;

use <../christmas-story-lamp-shade.scad>

//translate([-120, 0, 0])
// translate([9, 18, 0])
// %import("/home/roberto/Versioning/world/betoland/household/lamps/christmas-story-leg-lamp/jetpuf/files/LegLamp_Shade130.stl");

legLampShade(intersection_xTranslate = intersection_xTranslate,
             bottomOuterRadius = bottomOuterRadius,
             outerRadius = outerRadius,
             squareLength = squareLength,
             top_zTranslate = top_zTranslate,
             xScale = xScale,
             yScale = yScale);


coding rules

coding rules