bearing/linear/mount: make mount_dir_align default U, assert != U

include <units.scad>
include <system.scad>

use <misc.scad>
use <transforms.scad>
use <shapes.scad>
use <screws.scad>
include <bearing-linear-data.scad>
include <thread-data.scad>

module linear_bearing(part, bearing, align=N, orient=Z, offset_flange=false)
{
    model = get(LinearBearingModel, bearing);
    width_x = fallback(get(LinearBearingFlangeCutDiameter, bearing),LinearBearingOuterDiameter);
    width_y = fallback(get(LinearBearingFlangeDiameter, bearing),LinearBearingOuterDiameter);

    clip_dist = get(LinearBearingClipsDistance, bearing);
    clip_groove = get(LinearBearingClipsGrooveDepth, bearing);
    clip_dia = get(LinearBearingClipsDiameter, bearing);

    flange_h = fallback(get(LinearBearingFlangeThickness, bearing),0);

    // for all kinds of flanges
    flange_d = get(LinearBearingFlangeDiameter,bearing);

    // only for square flange
    flange_side = get(LinearBearingFlangeSide,bearing);

    // only for cut flanges
    flange_d_cut = get(LinearBearingFlangeCutDiameter,bearing);

    flange_pcd = get(LinearBearingFlangePitchCircleDiameter,bearing);

    flange_screw_len=12*mm;

    flange_offset = offset_flange ? -flange_h : 0;
    h = get(LinearBearingLength,bearing);
    d = get(LinearBearingInnerDiameter, bearing);
    D = get(LinearBearingOuterDiameter, bearing);
    s = [width_x, width_y, h];
    if(part==U)
    {
        difference()
        {
            linear_bearing(part="pos", bearing=bearing, align=align, orient=orient, offset_flange=offset_flange);
            linear_bearing(part="neg", bearing=bearing, align=align, orient=orient, offset_flange=offset_flange);
        }
        %linear_bearing(part="vit", bearing=bearing, align=align, orient=orient, offset_flange=offset_flange);
    }
    else if(part=="pos")
    size_align(size=s, align=align, orient=orient)
    translate(Z*flange_offset)
    {
        cylindera(h=h, d=D, orient=Z);

        // flange
        translate(-Z*h/2)
        {
            if(flange_side != U)
            {
                // LMK
                intersection()
                {
                    rcubea(size=[flange_side, flange_side, flange_h], orient=Z, align=Z, round_r=1);

                    rcubea(size=[flange_d, flange_d, flange_h], orient=Z, align=Z, round_r=1);
                }
            }
            else if(flange_d != U)
            {
                // LMH
                if(flange_d_cut != U)
                {
                    intersection()
                    {
                        rcylindera(h=flange_h, d=flange_d, orient=Z, align=Z, round_r=1);
                        rcubea(size=[get(LinearBearingFlangeCutDiameter, bearing), flange_d, flange_h], align=Z, round_r=1);
                    }
                }
                // LMF
                else if(flange_d != U)
                {
                    rcylindera(h=flange_h, d=flange_d, orient=Z, align=Z, round_r=1);
                }
            }
        }
    }
    else if(part=="neg")
    size_align(size=s, align=align, orient=orient)
    translate(Z*flange_offset)
    {
        translate(-Z*h/2)
        {
            // inner bore cut
            cylindera(h=h, d=d, orient=Z, align=Z, extra_h=.2);

            // clips
            if(clip_dist != U)
            {
                translate(Z*h/2)
                for(z=[-1,1])
                translate(z*Z*clip_dist/2)
                hollow_cylinder(d=D-clip_groove/2+.01, thickness=clip_groove, h=clip_groove, taper=false, orient=Z, align=-z);
            }

            // flange
            if(flange_side != U)
            {
                // LMK
                // screw cut
                for(x=[-1,1])
                for(y=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d_cut != U)
            {
                // LMH
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*get(LinearBearingFlangeCutMountHoleDist, bearing)/2)
                translate(x*X*get(LinearBearingFlangeCutMountHoleDistSide, bearing)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d != U)
            {
                // LMF
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
        }
    }
}

module linear_bearing_mount(part=part, bearing, extra_h=0, override_h=U, ziptie_type=[2*mm, 3*mm], ziptie_bearing_distance=3*mm, tolerance=.1*mm, align=N, orient=Z, ziptie_dist=U, with_zips=true, offset_flange=false, mount_dir_align=U, mount_style="open")
{
    assert(mount_dir_align != U, "mount_dir_align == U");

    ziptie_thickness = ziptie_type[0];
    ziptie_width = ziptie_type[1]+0.6*mm;

    ziptie_dist_ = fallback(ziptie_dist, get(LinearBearingClipsDistance,bearing)/2);

    clip_dist = get(LinearBearingClipsDistance, bearing);

    h = fallback(override_h, get(LinearBearingLength,bearing)) + extra_h;
    d = get(LinearBearingInnerDiameter, bearing);
    D = get(LinearBearingOuterDiameter, bearing);

    flange_h = fallback(get(LinearBearingFlangeThickness, bearing),0);

    // for all kinds of flanges
    flange_d = get(LinearBearingFlangeDiameter,bearing);

    // only for square flange
    flange_side = get(LinearBearingFlangeSide,bearing);

    // only for cut flanges
    flange_d_cut = get(LinearBearingFlangeCutDiameter,bearing);

    flange_pcd = get(LinearBearingFlangePitchCircleDiameter,bearing);

    flange_screw_len=12*mm;
    flange_offset = offset_flange ? -flange_h : 0;

    support_wall_thickness = 2.5*mm;

    support_D=D+2*support_wall_thickness;
    support_h = h+flange_offset;
    if(part==U)
    {
        difference()
        {
            linear_bearing_mount(part="pos", bearing=bearing, extra_h=extra_h, override_h=override_h, ziptie_type=ziptie_type, ziptie_bearing_distance=ziptie_bearing_distance, tolerance=tolerance, align=align, orient=orient, ziptie_dist=ziptie_dist, with_zips=with_zips, offset_flange=offset_flange, mount_dir_align=mount_dir_align, mount_style=mount_style);
            linear_bearing_mount(part="neg", bearing=bearing, extra_h=extra_h, override_h=override_h, ziptie_type=ziptie_type, ziptie_bearing_distance=ziptie_bearing_distance, tolerance=tolerance, align=align, orient=orient, ziptie_dist=ziptie_dist, with_zips=with_zips, offset_flange=offset_flange, mount_dir_align=mount_dir_align, mount_style=mount_style);
        }
        %linear_bearing_mount(part="vit", bearing=bearing, extra_h=extra_h, override_h=override_h, ziptie_type=ziptie_type, ziptie_bearing_distance=ziptie_bearing_distance, tolerance=tolerance, align=align, orient=orient, ziptie_dist=ziptie_dist, with_zips=with_zips, offset_flange=offset_flange, mount_dir_align=mount_dir_align, mount_style=mount_style);
    }
    else if(part=="pos")
    size_align(size=[D,D,h], align=align, orient=orient)
    {
        translate(-Z*h/2)
        {
            // z axis bearing support
            if(mount_style=="open")
            {
                intersection()
                {
                    rcylindera(h=support_h, d=D, orient=Z, align=Z);
                    rcubea(size=[D,D,support_h], orient=Z, align=Z+mount_dir_align);
                }
            }
            else if(mount_style=="closed")
            {
                rcylindera(h=support_h, d=support_D, orient=Z, align=Z);
            }

            // support for clips
            if(clip_dist != U)
            {
                translate(Z*h/2)
                for(z=[-1,1])
                translate(z*Z*clip_dist/2)
                hollow_cylinder(d=D-clip_groove/2+.01, thickness=clip_groove, h=clip_groove, taper=false, orient=Z, align=-z);
            }

            // support for flange mount
            if(flange_side != U)
            {
                // LMK
                // screw cut
                for(x=[-1,1])
                for(y=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                rcylindera(d=1.5*get(LinearBearingFlangeMountingSize,bearing), h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d_cut != U)
            {
                // LMH
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*get(LinearBearingFlangeCutMountHoleDist, bearing)/2)
                translate(x*X*get(LinearBearingFlangeCutMountHoleDistSide, bearing)/2)
                rcylindera(d=1.5*get(LinearBearingFlangeMountingSize,bearing), h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d != U)
            {
                // LMF
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                rcylindera(d=1.5*get(LinearBearingFlangeMountingSize,bearing), h=flange_screw_len, orient=Z, align=Z);
            }
        }
    }
    else if(part=="neg")
    size_align(size=[D,D,h], align=align, orient=orient)
    translate(Z*flange_offset)
    translate(-Z*.001)
    {
        // Main bearing cut
        cylindera(h=h+tolerance, d=D+tolerance, orient=Z);

        if(mount_style=="open")
        {
            orient(-orient)
            rcubea(size=[1000,1000,D+.2*mm], align=mount_dir_align);

            if(with_zips)
            {
                for(z=[-1,1])
                translate([0,0,z*ziptie_dist_ - z*1/2])
                hollow_cylinder(
                    d=D+ziptie_bearing_distance+ziptie_thickness,
                    thickness = ziptie_thickness*2,
                    h = ziptie_width,
                    taper=false,
                    orient=Z,
                    align=N
                    );
            }
        }

        // for linear rod
        cylindera(d=d+2*mm, h=1000, orient=Z);

        // flange
        translate(-Z*h/2)
        {
            if(flange_side != U)
            {
                // LMK
                intersection()
                {
                    rcubea(size=[flange_side, flange_side, flange_h], orient=Z, align=Z, round_r=1);

                    rcubea(size=[flange_d, flange_d, flange_h], orient=Z, align=Z, round_r=1);
                }
            }
            else if(flange_d != U)
            {
                // LMH
                if(flange_d_cut != U)
                {
                    intersection()
                    {
                        rcylindera(h=flange_h, d=flange_d, orient=Z, align=Z, round_r=1);
                        rcubea(size=[get(LinearBearingFlangeCutDiameter, bearing), flange_d, flange_h], align=Z, round_r=1);
                    }
                }
                // LMF
                else if(flange_d != U)
                {
                    rcylindera(h=flange_h, d=flange_d, orient=Z, align=Z, round_r=1);
                }
            }
        }

        translate(-Z*h/2)
        {
            // inner bore cut
            cylindera(h=h, d=d, orient=Z, align=Z, extra_h=.2);

            // clips
            if(clip_dist != U)
            {
                translate(Z*h/2)
                for(z=[-1,1])
                translate(z*Z*clip_dist/2)
                hollow_cylinder(d=D-clip_groove/2+.01, thickness=clip_groove, h=clip_groove, taper=false, orient=Z, align=-z);
            }

            // flange
            if(flange_side != U)
            {
                // LMK
                // screw cut
                for(x=[-1,1])
                for(y=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d_cut != U)
            {
                // LMH
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*get(LinearBearingFlangeCutMountHoleDist, bearing)/2)
                translate(x*X*get(LinearBearingFlangeCutMountHoleDistSide, bearing)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d != U)
            {
                // LMF
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
        }

    }
    else if(part=="vit")
    size_align(size=[D,D,h], align=align, orient=orient)
    translate(Z*flange_offset)
    {
        if($show_vit)
        {
            linear_bearing(bearing=bearing);

            if(mount_style=="open")
            for(z=[-1,1])
            translate([0,0,z*ziptie_dist_])
            {
                hollow_cylinder(
                    d=D+ziptie_bearing_distance+ziptie_thickness,
                    thickness = ziptie_thickness,
                    h = ziptie_width,
                    taper=false,
                    orient=Z,
                    align=-z*Z
                    );
            }
        }
    }
}

// all
if(false)
{
    v_flangewidth = v_get(AllLinearBearing,LinearBearingFlangeDiameter);
    v_dia = v_get(AllLinearBearing,LinearBearingOuterDiameter);
    v_width = vv_fallback([v_flangewidth, v_dia]);
    dist_cumsum = v_cumsum(v_width, 0);
    for(i=[0:1:len(AllLinearBearing)-1])
    {
        bearing = AllLinearBearing[i];
        dist=dist_cumsum[i];
        translate(X*dist)
        {
            linear_bearing(bearing=bearing, align=Z);
            translate((v_width[i]/2 + 3*mm)*-Y)
            rotate(-90*Z)
            text(get(LinearBearingModel, bearing), size=v_width[i]*.8, valign="center", halign="left");

            translate((v_width[i] + 10*mm)*Y)
            linear_bearing_mount(bearing=bearing, align=Z);
        }
    }
}

if(false)
{
    stack(axis=X, dist=50*mm)
    {
        linear_bearing(bearing=LinearBearingLM6, align=Z);
        linear_bearing(bearing=LinearBearingLM6L, align=Z);
        linear_bearing(bearing=LinearBearingLMF8, align=Z);
        linear_bearing(bearing=LinearBearingLMF8L, align=Z);
        linear_bearing(bearing=LinearBearingLMK8, align=Z);
        linear_bearing(bearing=LinearBearingLMK8L, align=Z);
        linear_bearing(bearing=LinearBearingLMH12L, align=Z);
        linear_bearing(bearing=LinearBearingLMH16L, align=Z);
    }
}

include <units.scad>
include <system.scad>

use <misc.scad>
use <transforms.scad>
use <shapes.scad>
use <screws.scad>
include <bearing-linear-data.scad>
include <thread-data.scad>

module linear_bearing(part, bearing, align=N, orient=Z, offset_flange=false)
{
    model = get(LinearBearingModel, bearing);
    width_x = fallback(get(LinearBearingFlangeCutDiameter, bearing),LinearBearingOuterDiameter);
    width_y = fallback(get(LinearBearingFlangeDiameter, bearing),LinearBearingOuterDiameter);

    clip_dist = get(LinearBearingClipsDistance, bearing);
    clip_groove = get(LinearBearingClipsGrooveDepth, bearing);
    clip_dia = get(LinearBearingClipsDiameter, bearing);

    flange_h = fallback(get(LinearBearingFlangeThickness, bearing),0);

    // for all kinds of flanges
    flange_d = get(LinearBearingFlangeDiameter,bearing);

    // only for square flange
    flange_side = get(LinearBearingFlangeSide,bearing);

    // only for cut flanges
    flange_d_cut = get(LinearBearingFlangeCutDiameter,bearing);

    flange_pcd = get(LinearBearingFlangePitchCircleDiameter,bearing);

    flange_screw_len=12*mm;

    flange_offset = offset_flange ? -flange_h : 0;
    h = get(LinearBearingLength,bearing);
    d = get(LinearBearingInnerDiameter, bearing);
    D = get(LinearBearingOuterDiameter, bearing);
    s = [width_x, width_y, h];
    if(part==U)
    {
        difference()
        {
            linear_bearing(part="pos", bearing=bearing, align=align, orient=orient, offset_flange=offset_flange);
            linear_bearing(part="neg", bearing=bearing, align=align, orient=orient, offset_flange=offset_flange);
        }
        %linear_bearing(part="vit", bearing=bearing, align=align, orient=orient, offset_flange=offset_flange);
    }
    else if(part=="pos")
    size_align(size=s, align=align, orient=orient)
    translate(Z*flange_offset)
    {
        cylindera(h=h, d=D, orient=Z);

        // flange
        translate(-Z*h/2)
        {
            if(flange_side != U)
            {
                // LMK
                intersection()
                {
                    rcubea(size=[flange_side, flange_side, flange_h], orient=Z, align=Z, round_r=1);

                    rcubea(size=[flange_d, flange_d, flange_h], orient=Z, align=Z, round_r=1);
                }
            }
            else if(flange_d != U)
            {
                // LMH
                if(flange_d_cut != U)
                {
                    intersection()
                    {
                        rcylindera(h=flange_h, d=flange_d, orient=Z, align=Z, round_r=1);
                        rcubea(size=[get(LinearBearingFlangeCutDiameter, bearing), flange_d, flange_h], align=Z, round_r=1);
                    }
                }
                // LMF
                else if(flange_d != U)
                {
                    rcylindera(h=flange_h, d=flange_d, orient=Z, align=Z, round_r=1);
                }
            }
        }
    }
    else if(part=="neg")
    size_align(size=s, align=align, orient=orient)
    translate(Z*flange_offset)
    {
        translate(-Z*h/2)
        {
            // inner bore cut
            cylindera(h=h, d=d, orient=Z, align=Z, extra_h=.2);

            // clips
            if(clip_dist != U)
            {
                translate(Z*h/2)
                for(z=[-1,1])
                translate(z*Z*clip_dist/2)
                hollow_cylinder(d=D-clip_groove/2+.01, thickness=clip_groove, h=clip_groove, taper=false, orient=Z, align=-z);
            }

            // flange
            if(flange_side != U)
            {
                // LMK
                // screw cut
                for(x=[-1,1])
                for(y=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d_cut != U)
            {
                // LMH
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*get(LinearBearingFlangeCutMountHoleDist, bearing)/2)
                translate(x*X*get(LinearBearingFlangeCutMountHoleDistSide, bearing)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d != U)
            {
                // LMF
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
        }
    }
}

module linear_bearing_mount(part=part, bearing, extra_h=0, override_h=U, ziptie_type=[2*mm, 3*mm], ziptie_bearing_distance=3*mm, tolerance=.1*mm, align=N, orient=Z, ziptie_dist=U, with_zips=true, offset_flange=false, mount_dir_align=X, mount_style="open")
{
    ziptie_thickness = ziptie_type[0];
    ziptie_width = ziptie_type[1]+0.6*mm;

    ziptie_dist_ = fallback(ziptie_dist, get(LinearBearingClipsDistance,bearing)/2);

    clip_dist = get(LinearBearingClipsDistance, bearing);

    h = fallback(override_h, get(LinearBearingLength,bearing)) + extra_h;
    d = get(LinearBearingInnerDiameter, bearing);
    D = get(LinearBearingOuterDiameter, bearing);

    flange_h = fallback(get(LinearBearingFlangeThickness, bearing),0);

    // for all kinds of flanges
    flange_d = get(LinearBearingFlangeDiameter,bearing);

    // only for square flange
    flange_side = get(LinearBearingFlangeSide,bearing);

    // only for cut flanges
    flange_d_cut = get(LinearBearingFlangeCutDiameter,bearing);

    flange_pcd = get(LinearBearingFlangePitchCircleDiameter,bearing);

    flange_screw_len=12*mm;
    flange_offset = offset_flange ? -flange_h : 0;

    support_wall_thickness = 2.5*mm;

    support_D=D+2*support_wall_thickness;
    support_h = h+flange_offset;
    if(part==U)
    {
        difference()
        {
            linear_bearing_mount(part="pos", bearing=bearing, extra_h=extra_h, override_h=override_h, ziptie_type=ziptie_type, ziptie_bearing_distance=ziptie_bearing_distance, tolerance=tolerance, align=align, orient=orient, ziptie_dist=ziptie_dist, with_zips=with_zips, offset_flange=offset_flange, mount_dir_align=mount_dir_align, mount_style=mount_style);
            linear_bearing_mount(part="neg", bearing=bearing, extra_h=extra_h, override_h=override_h, ziptie_type=ziptie_type, ziptie_bearing_distance=ziptie_bearing_distance, tolerance=tolerance, align=align, orient=orient, ziptie_dist=ziptie_dist, with_zips=with_zips, offset_flange=offset_flange, mount_dir_align=mount_dir_align, mount_style=mount_style);
        }
        %linear_bearing_mount(part="vit", bearing=bearing, extra_h=extra_h, override_h=override_h, ziptie_type=ziptie_type, ziptie_bearing_distance=ziptie_bearing_distance, tolerance=tolerance, align=align, orient=orient, ziptie_dist=ziptie_dist, with_zips=with_zips, offset_flange=offset_flange, mount_dir_align=mount_dir_align, mount_style=mount_style);
    }
    else if(part=="pos")
    size_align(size=[D,D,h], align=align, orient=orient)
    {
        translate(-Z*h/2)
        {
            // z axis bearing support
            if(mount_style=="open")
            {
                intersection()
                {
                    rcylindera(h=support_h, d=D, orient=Z, align=Z);
                    rcubea(size=[D,D,support_h], orient=Z, align=Z+mount_dir_align);
                }
            }
            else if(mount_style=="closed")
            {
                rcylindera(h=support_h, d=support_D, orient=Z, align=Z);
            }

            // support for clips
            if(clip_dist != U)
            {
                translate(Z*h/2)
                for(z=[-1,1])
                translate(z*Z*clip_dist/2)
                hollow_cylinder(d=D-clip_groove/2+.01, thickness=clip_groove, h=clip_groove, taper=false, orient=Z, align=-z);
            }

            // support for flange mount
            if(flange_side != U)
            {
                // LMK
                // screw cut
                for(x=[-1,1])
                for(y=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                rcylindera(d=1.5*get(LinearBearingFlangeMountingSize,bearing), h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d_cut != U)
            {
                // LMH
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*get(LinearBearingFlangeCutMountHoleDist, bearing)/2)
                translate(x*X*get(LinearBearingFlangeCutMountHoleDistSide, bearing)/2)
                rcylindera(d=1.5*get(LinearBearingFlangeMountingSize,bearing), h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d != U)
            {
                // LMF
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                rcylindera(d=1.5*get(LinearBearingFlangeMountingSize,bearing), h=flange_screw_len, orient=Z, align=Z);
            }
        }
    }
    else if(part=="neg")
    size_align(size=[D,D,h], align=align, orient=orient)
    translate(Z*flange_offset)
    translate(-Z*.001)
    {
        // Main bearing cut
        cylindera(h=h+tolerance, d=D+tolerance, orient=Z);

        if(mount_style=="open")
        {
            orient(-orient)
            rcubea(size=[1000,1000,D+.2*mm], align=mount_dir_align);

            if(with_zips)
            {
                for(z=[-1,1])
                translate([0,0,z*ziptie_dist_ - z*1/2])
                hollow_cylinder(
                    d=D+ziptie_bearing_distance+ziptie_thickness,
                    thickness = ziptie_thickness*2,
                    h = ziptie_width,
                    taper=false,
                    orient=Z,
                    align=N
                    );
            }
        }

        // for linear rod
        cylindera(d=d+2*mm, h=1000, orient=Z);

        // flange
        translate(-Z*h/2)
        {
            if(flange_side != U)
            {
                // LMK
                intersection()
                {
                    rcubea(size=[flange_side, flange_side, flange_h], orient=Z, align=Z, round_r=1);

                    rcubea(size=[flange_d, flange_d, flange_h], orient=Z, align=Z, round_r=1);
                }
            }
            else if(flange_d != U)
            {
                // LMH
                if(flange_d_cut != U)
                {
                    intersection()
                    {
                        rcylindera(h=flange_h, d=flange_d, orient=Z, align=Z, round_r=1);
                        rcubea(size=[get(LinearBearingFlangeCutDiameter, bearing), flange_d, flange_h], align=Z, round_r=1);
                    }
                }
                // LMF
                else if(flange_d != U)
                {
                    rcylindera(h=flange_h, d=flange_d, orient=Z, align=Z, round_r=1);
                }
            }
        }

        translate(-Z*h/2)
        {
            // inner bore cut
            cylindera(h=h, d=d, orient=Z, align=Z, extra_h=.2);

            // clips
            if(clip_dist != U)
            {
                translate(Z*h/2)
                for(z=[-1,1])
                translate(z*Z*clip_dist/2)
                hollow_cylinder(d=D-clip_groove/2+.01, thickness=clip_groove, h=clip_groove, taper=false, orient=Z, align=-z);
            }

            // flange
            if(flange_side != U)
            {
                // LMK
                // screw cut
                for(x=[-1,1])
                for(y=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d_cut != U)
            {
                // LMH
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*get(LinearBearingFlangeCutMountHoleDist, bearing)/2)
                translate(x*X*get(LinearBearingFlangeCutMountHoleDistSide, bearing)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
            else if(flange_d != U)
            {
                // LMF
                // screw cut
                for(y=[-1,1])
                for(x=[-1,1])
                translate(y*Y*flange_pcd/2*sqrt(2)/2)
                translate(x*X*flange_pcd/2*sqrt(2)/2)
                screw_cut(thread=ThreadM4, h=flange_screw_len, orient=Z, align=Z);
            }
        }

    }
    else if(part=="vit")
    size_align(size=[D,D,h], align=align, orient=orient)
    translate(Z*flange_offset)
    {
        if($show_vit)
        {
            linear_bearing(bearing=bearing);

            if(mount_style=="open")
            for(z=[-1,1])
            translate([0,0,z*ziptie_dist_])
            {
                hollow_cylinder(
                    d=D+ziptie_bearing_distance+ziptie_thickness,
                    thickness = ziptie_thickness,
                    h = ziptie_width,
                    taper=false,
                    orient=Z,
                    align=-z*Z
                    );
            }
        }
    }
}

// all
if(false)
{
    v_flangewidth = v_get(AllLinearBearing,LinearBearingFlangeDiameter);
    v_dia = v_get(AllLinearBearing,LinearBearingOuterDiameter);
    v_width = vv_fallback([v_flangewidth, v_dia]);
    dist_cumsum = v_cumsum(v_width, 0);
    for(i=[0:1:len(AllLinearBearing)-1])
    {
        bearing = AllLinearBearing[i];
        dist=dist_cumsum[i];
        translate(X*dist)
        {
            linear_bearing(bearing=bearing, align=Z);
            translate((v_width[i]/2 + 3*mm)*-Y)
            rotate(-90*Z)
            text(get(LinearBearingModel, bearing), size=v_width[i]*.8, valign="center", halign="left");

            translate((v_width[i] + 10*mm)*Y)
            linear_bearing_mount(bearing=bearing, align=Z);
        }
    }
}

if(false)
{
    stack(axis=X, dist=50*mm)
    {
        linear_bearing(bearing=LinearBearingLM6, align=Z);
        linear_bearing(bearing=LinearBearingLM6L, align=Z);
        linear_bearing(bearing=LinearBearingLMF8, align=Z);
        linear_bearing(bearing=LinearBearingLMF8L, align=Z);
        linear_bearing(bearing=LinearBearingLMK8, align=Z);
        linear_bearing(bearing=LinearBearingLMK8L, align=Z);
        linear_bearing(bearing=LinearBearingLMH12L, align=Z);
        linear_bearing(bearing=LinearBearingLMH16L, align=Z);
    }
}


Add a barrel sample

Add a barrel sample

/**
 * Samples using the camelSCAD library.
 *
 * A parametric closed barrel.
 *
 * @author jsconan
 * @license CC0-1.0
 */

// As we need to use some shapes, use the right entry point of the library
use <../shapes.scad>
include <../core/constants.scad>

// We will render the object using the specifications of this mode
renderMode = MODE_PROD;

// Defines the dimensions of the object
diameter = 40;
height = 60;
fillet = ceil(min(diameter, height) / 20);

// Sets the minimum facet angle and size using the defined render mode.
applyMode(renderMode) {
    peg([diameter, diameter, height], r=fillet);
}

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


Row spacing was added.

Row spacing was added.

spurStl = "../lamp-shade-scallops/spur/spurs-a.stl";

littleSpurCount = 6;

littleSpurScale = 0.125;

rowSpacing = 30;

difference()
{
    // vase
    difference()
    {
        // outer vase
        translate([0,0,0])
        cylinder (h = 70, r=55, center = true, $fn=100);

        // remvoed inner vasecentered spur
        translate([0,0,5])
        cylinder (h = 70, r=50, center = true, $fn=100);
    }

    // outer spurs
    for ( i = [0 : 5] )
    {
        rotate([
                90,
                0,
                i * 360 / 6
        ])
        // normally x,y,z - but here y moves the little spurs up and down
        translate([15, 15+(z*rowSpacing), 30])
        scale([littleSpurScale, littleSpurScale, 20.2])
        import(spurStl);
    }
}

spurStl = "../lamp-shade-scallops/spur/spurs-a.stl";

littleSpurCount = 6;

littleSpurScale = 0.125;

difference()
{
    // vase
    difference()
    {
        // outer vase
        translate([0,0,0])
        cylinder (h = 70, r=55, center = true, $fn=100);

        // remvoed inner vasecentered spur
        translate([0,0,5])
        cylinder (h = 70, r=50, center = true, $fn=100);
    }

    // outer spurs
    for ( i = [0 : 5] )
    {
        rotate([
                90,
                0,
                i * 360 / 6
        ])
        // normally x,y,z - but here y moves the little spurs up and down
        translate([15, 0, 30])
        scale([littleSpurScale, littleSpurScale, 20.2])
        import(spurStl);
    }
}


Add a visual indicator when an assertion fails

/**
 * @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.
 *
 * Unit testing API.
 *
 * @package util/test
 * @author jsconan
 */

/**
 * Declares the target package of the test suite.
 *
 * @param String title
 * @param Number [expected]
 */
module testPackage(title, expected) {
    $testPackage = string(title);

    displayTestTitle(title, "package", true);
    children();
    displayExpectedAsserts($children, expected, "module");
}

/**
 * Declares the function or the feature that is tested.
 *
 * @param String title
 * @param Number [expected]
 */
module testModule(title, expected) {
    $testModule = string(title);

    displayTestTitle(title, "module");
    children();
    displayExpectedAsserts($children, expected, "test");
}

/**
 * Declares a unit test.
 *
 * @param String title
 * @param Number [expected]
 */
module testUnit(title, expected) {
    $testUnit = string(title);

    children();
    displayExpectedAsserts($children, expected, "assertion");
}

/**
 * Asserts the actual value is equal to the expected value.
 *
 * @param * actual
 * @param * expected
 * @param String [message]
 */
module assertEqual(actual, expected, message) {
    result = actual == expected;
    message = or(message, "Should be equal");
    details = [actual, expected];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the actual value is not equal to the expected value.
 *
 * @param * actual
 * @param * expected
 * @param String [message]
 */
module assertNotEqual(actual, expected, message) {
    result = actual != expected;
    message = or(message, "Should not be equal");
    details = [actual, expected];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the actual value is approximately equal to the expected value.
 *
 * @param * actual
 * @param * expected
 * @param String [message]
 */
module assertApproxEqual(actual, expected, message) {
    result = approx(actual, expected);
    message = or(message, "Should be approximately equal ");
    details = [actual, expected];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the actual value is not approximately equal to the expected value.
 *
 * @param * actual
 * @param * expected
 * @param String [message]
 */
module assertNotApproxEqual(actual, expected, message) {
    result = !approx(actual, expected);
    message = or(message, "Should not be approximately equal ");
    details = [actual, expected];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is equivalent to true.
 *
 * @param * value
 * @param String [message]
 */
module assertTrue(value, message) {
    result = !!value;
    message = or(message, "Should be true");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is falsy.
 *
 * @param * value
 * @param String [message]
 */
module assertFalse(value, message) {
    result = !value;
    message = or(message, "Should be false");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Failed assert.
 *
 * @param String [message]
 */
module failed(message) {
    message = or(message, "Failed!");

    displayAssertResult(false, message);
}

/**
 * Asserts the value is undefined.
 *
 * @param * value
 * @param String [message]
 */
module assertUndef(value, message) {
    result = isUndef(value);
    message = or(message, "Should be an undefined value");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is a number.
 *
 * @param * value
 * @param String [message]
 */
module assertNumber(value, message) {
    result = isNumber(value);
    message = or(message, "Should be a number");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is an integer.
 *
 * @param * value
 * @param String [message]
 */
module assertInteger(value, message) {
    result = isInteger(value);
    message = or(message, "Should be an integer");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is a boolean.
 *
 * @param * value
 * @param String [message]
 */
module assertBoolean(value, message) {
    result = isBoolean(value);
    message = or(message, "Should be a boolean");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is a vector.
 *
 * @param * value
 * @param String [message]
 */
module assertVector(value, message) {
    result = isVector(value);
    message = or(message, "Should be a vector");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is an array.
 *
 * @param * value
 * @param String [message]
 */
module assertArray(value, message) {
    result = isArray(value);
    message = or(message, "Should be an array");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is an empty array.
 *
 * @param * value
 * @param String [message]
 */
module assertEmptyArray(value, message) {
    result = value == [];
    message = or(message, "Should be an empty array");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is not an empty array.
 *
 * @param * value
 * @param String [message]
 */
module assertNotEmptyArray(value, message) {
    result = isArray(value) && value != [];
    message = or(message, "Should not be an empty array");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is a string.
 *
 * @param * value
 * @param String [message]
 */
module assertString(value, message) {
    result = isString(value);
    message = or(message, "Should be a string");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is an empty string.
 *
 * @param * value
 * @param String [message]
 */
module assertEmptyString(value, message) {
    result = value == "";
    message = or(message, "Should be an empty string");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is a not empty string.
 *
 * @param * value
 * @param String [message]
 */
module assertNotEmptyString(value, message) {
    result = isString(value) && value != "";
    message = or(message, "Should not be an empty string");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Displays a title.
 *
 * @private
 * @param String title
 * @param String type
 * @param Boolean [big]
 */
module displayTestTitle(title, type, big) {
    echo(formatTestTitle(title, type, big));
}

/**
 * Displays the number of expected asserts.
 *
 * @private
 * @param Number actual
 * @param Number [expected]
 * @param String [type]
 */
module displayExpectedAsserts(actual, expected, type) {
    echo(formatExpectedAsserts(actual, expected, type));
}

/**
 * Displays an assert result.
 *
 * @private
 * @param Boolean result
 * @param String message
 * @param Array [details]
 */
module displayAssertResult(result, message, details) {
    echo(formatAssertResult(result, message, details));
    if (!result) {
        color([1, 0, 0]) {
            sphere(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.
 *
 * Unit testing API.
 *
 * @package util/test
 * @author jsconan
 */

/**
 * Declares the target package of the test suite.
 *
 * @param String title
 * @param Number [expected]
 */
module testPackage(title, expected) {
    $testPackage = string(title);

    displayTestTitle(title, "package", true);
    children();
    displayExpectedAsserts($children, expected, "module");
}

/**
 * Declares the function or the feature that is tested.
 *
 * @param String title
 * @param Number [expected]
 */
module testModule(title, expected) {
    $testModule = string(title);

    displayTestTitle(title, "module");
    children();
    displayExpectedAsserts($children, expected, "test");
}

/**
 * Declares a unit test.
 *
 * @param String title
 * @param Number [expected]
 */
module testUnit(title, expected) {
    $testUnit = string(title);

    children();
    displayExpectedAsserts($children, expected, "assertion");
}

/**
 * Asserts the actual value is equal to the expected value.
 *
 * @param * actual
 * @param * expected
 * @param String [message]
 */
module assertEqual(actual, expected, message) {
    result = actual == expected;
    message = or(message, "Should be equal");
    details = [actual, expected];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the actual value is not equal to the expected value.
 *
 * @param * actual
 * @param * expected
 * @param String [message]
 */
module assertNotEqual(actual, expected, message) {
    result = actual != expected;
    message = or(message, "Should not be equal");
    details = [actual, expected];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the actual value is approximately equal to the expected value.
 *
 * @param * actual
 * @param * expected
 * @param String [message]
 */
module assertApproxEqual(actual, expected, message) {
    result = approx(actual, expected);
    message = or(message, "Should be approximately equal ");
    details = [actual, expected];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the actual value is not approximately equal to the expected value.
 *
 * @param * actual
 * @param * expected
 * @param String [message]
 */
module assertNotApproxEqual(actual, expected, message) {
    result = !approx(actual, expected);
    message = or(message, "Should not be approximately equal ");
    details = [actual, expected];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is equivalent to true.
 *
 * @param * value
 * @param String [message]
 */
module assertTrue(value, message) {
    result = !!value;
    message = or(message, "Should be true");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is falsy.
 *
 * @param * value
 * @param String [message]
 */
module assertFalse(value, message) {
    result = !value;
    message = or(message, "Should be false");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Failed assert.
 *
 * @param String [message]
 */
module failed(message) {
    message = or(message, "Failed!");

    displayAssertResult(false, message);
}

/**
 * Asserts the value is undefined.
 *
 * @param * value
 * @param String [message]
 */
module assertUndef(value, message) {
    result = isUndef(value);
    message = or(message, "Should be an undefined value");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is a number.
 *
 * @param * value
 * @param String [message]
 */
module assertNumber(value, message) {
    result = isNumber(value);
    message = or(message, "Should be a number");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is an integer.
 *
 * @param * value
 * @param String [message]
 */
module assertInteger(value, message) {
    result = isInteger(value);
    message = or(message, "Should be an integer");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is a boolean.
 *
 * @param * value
 * @param String [message]
 */
module assertBoolean(value, message) {
    result = isBoolean(value);
    message = or(message, "Should be a boolean");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is a vector.
 *
 * @param * value
 * @param String [message]
 */
module assertVector(value, message) {
    result = isVector(value);
    message = or(message, "Should be a vector");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is an array.
 *
 * @param * value
 * @param String [message]
 */
module assertArray(value, message) {
    result = isArray(value);
    message = or(message, "Should be an array");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is an empty array.
 *
 * @param * value
 * @param String [message]
 */
module assertEmptyArray(value, message) {
    result = value == [];
    message = or(message, "Should be an empty array");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is not an empty array.
 *
 * @param * value
 * @param String [message]
 */
module assertNotEmptyArray(value, message) {
    result = isArray(value) && value != [];
    message = or(message, "Should not be an empty array");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is a string.
 *
 * @param * value
 * @param String [message]
 */
module assertString(value, message) {
    result = isString(value);
    message = or(message, "Should be a string");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is an empty string.
 *
 * @param * value
 * @param String [message]
 */
module assertEmptyString(value, message) {
    result = value == "";
    message = or(message, "Should be an empty string");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Asserts the value is a not empty string.
 *
 * @param * value
 * @param String [message]
 */
module assertNotEmptyString(value, message) {
    result = isString(value) && value != "";
    message = or(message, "Should not be an empty string");
    details = [value];

    displayAssertResult(result, message, details);
}

/**
 * Displays a title.
 *
 * @private
 * @param String title
 * @param String type
 * @param Boolean [big]
 */
module displayTestTitle(title, type, big) {
    echo(formatTestTitle(title, type, big));
}

/**
 * Displays the number of expected asserts.
 *
 * @private
 * @param Number actual
 * @param Number [expected]
 * @param String [type]
 */
module displayExpectedAsserts(actual, expected, type) {
    echo(formatExpectedAsserts(actual, expected, type));
}

/**
 * Displays an assert result.
 *
 * @private
 * @param Boolean result
 * @param String message
 * @param Array [details]
 */
module displayAssertResult(result, message, details) {
    echo(formatAssertResult(result, message, details));
}


Creating top lid for case

Creating top lid for case

//$fn = 100;

//Need to fix servo tilt suport issue. The spheric part does not move with the arm when you change xPos parameter
include <rpi.scad>;
PIcameraDiam = 8;
PIcameraX = 25;
PIcameraY = 25;

mik = 2;
shellThickness = 3;
supportBaseHeight = 5;
//5.4 is the height of the
baseHeight = 31 + shellThickness - 5.4;
tolerance = 1.5;
gimballWidth = 45; //for 50 gives R = 86

R = sqrt(3 * gimballWidth * gimballWidth) / 2;
panSupport = sqrt(R * R - (gimballWidth * gimballWidth / 4));
gimballPivotR = R / 2;
supportY = 2 * sqrt(R * R - (gimballWidth / 2) * (gimballWidth / 2));
supportX = R - gimballWidth / 2;
supportZ = 1.1 * R;

servoHornThickness = 5.5;
servoHornWidth = 8;
servoHornLenght = 32;

screwDiam	= 3;
screwLenght = 10;
screwTolerance = 0.2;

Piwidth = 56;
Pilength = 85;
Piheight = 1.5;

boxLenght = Pilength + mik + 3;
boxDepth = 2 * R + 10;
boxHeight = 48;

function RatX(x) = sqrt(R * R - (x * x));

module box(Xdim, Ydim, Zdim, thickness, application)
//Creates a box, dimensions are internal
{
	difference() {
		//translate([10,0,-thickness])
		cube([Xdim + thickness, Ydim + thickness, Zdim], center = true);
		translate([0, 0, thickness / 2]) cube([Xdim, Ydim, Zdim], center = true);
		if (application == "servo") {
			translate([-Xdim / 2, 0, -0.5 * Zdim]) cube([5, Ydim + 2 * thickness, Zdim / 2 + thickness], center = true);
			translate([+Xdim / 2, 0, -0.5 * Zdim]) cube([5, Ydim + 2 * thickness, Zdim / 2 + thickness], center = true);
			translate([+Xdim / 2, 0, 0]) cube([thickness / 2, 0.3 * Ydim, Zdim], center = true);
			translate([-Xdim / 2, 0, 0]) cube([thickness / 2, 0.3 * Ydim, Zdim], center = true);
		}
	}
}

//Baseplate for pan mechanism
module base(servo) {
	difference(){

	 {
		minkowski() {
			cylinder(r = R + mik, h = supportBaseHeight);
			rotate([90, 0, 0]) cylinder(r = mik, h = 1);
		}

		//This to create a anchorign mechanism with the pan base
		//translate([0, 0,-mik])cylinder(r = R + mik+3, h = 2);
	}
		if(servo == true) translate([0, 0, -supportZ - servoHornThickness]) rotate([0, 90, 0]) servoHorn("cross");
	}
}
//-------------------------

module supportSection() {
	intersection() {
		difference() {
			sphere(R);
			cube([gimballWidth, 2 * gimballWidth, 2 * gimballWidth], center = true);

		}
		translate([R - supportX / 2, 0, 0]) cube([supportX, supportY, 10], center = true);
	}
}
//-------------------------

module tiltSupport()
//This creates the supporting pillar for the camera shell
 {
	union(){
difference() {
		sphere(R);
		cube([gimballWidth, 2 * gimballWidth, 2 * gimballWidth], center = true);
		translate([-gimballWidth,0,0])cube([2 * gimballWidth,2 * gimballWidth,2 * gimballWidth], center=true);

	}

	hull() {
		translate([0, 0, -5]) supportSection();
		translate([0, 0, -supportZ]) supportSection();
	}}

}

module servoTiltSupport(xPos) {
	//Need to center the servo shaft, the seconf figure is the distance form border
	supportPosition = xPos;
	eccentricity = 22.2 / 2 - 5;
	servoBodySupport = 20;
	//Need to adjust the clearance to account for the Xpos
	servoClerance = 31 - 16 - servoHornThickness;
	supportCurvature = 30;

	rotate([-0, 0, 0]) difference() {

		union() {

			difference() {
				translate([-shellThickness / 2 + supportPosition, 0, 15]) {
					cube([shellThickness, 20, 2 * RatX(gimballWidth / 2)], center = true);
				}
				difference() {
					translate([-shellThickness / 2 + supportPosition, 0, 15]) cube([shellThickness, 20, 2 * RatX(gimballWidth / 2)], center = true);

					//The size of the sphere governs where the servo support will be cut. Need to add tolerance if you wnat to print as one piece with the shell.
					sphere(RatX(gimballWidth / 2) + shellThickness + tolerance);

				}

			}

			translate([-servoBodySupport / 2 + supportPosition, 0, eccentricity]) {
				//This is the servo box
				difference() {
					cube([servoBodySupport, 12 + 1 + shellThickness, 22.2 + 1 + shellThickness], center = true);
					cube([servoBodySupport, 12 + 1, 22.2 + 1], center = true);

					//Servo cable slot
					translate([0, 0, -2 * eccentricity]) cube([100, 3, 3], center = true);

				}

			}
		}

	//This is the slot in the servo arm
		translate([servoClerance + 10, 0, eccentricity]) {

			cube([20+1, 12, 32.2+1], center = true);
			translate([-31 / 2, 0, 0]) cube([31+1, 12, 22.2+1], center = true);

		}
	}

translate([0, 0, 0])
			difference() {
		translate([3, 0,+ RatX(xPos)-10])
		difference() {
			cube([20, 20, 20], center = true);
			translate([-supportCurvature, 0, -supportCurvature]) sphere(r = supportCurvature + 20);
		}

		difference() {
			sphere(RatX(gimballWidth / 2) + 10 * shellThickness + tolerance);

			sphere(RatX(gimballWidth / 2) + shellThickness + tolerance);
		}
	}

}
//-------------------------
module cameraSupport() {
	difference() {
		difference() {
			sphere(R);
			sphere(R - shellThickness);
		}

		translate([R + gimballWidth / 2, 0, 0]) cube([2 * R, 2 * R, 2 * R], center = true);
		translate([-R - gimballWidth / 2, 0, 0]) cube([2 * R, 2 * R, 2 * R], center = true);
		//Creates camera support
		translate([0, R - 7, 0]) cube([PIcameraX + tolerance, 3, PIcameraY + tolerance], center = true);
		translate([0, R - 7, 0]) cube([2, 3, PIcameraY], center = true);
		//Slot for camera wires
		translate([0, R - 8, -PIcameraY / 2 - 2]) cube([PIcameraX - 5, 3, 3], center = true);

		//Hole for the camera
		translate([0, R, 0]) rotate([90, 0, 0]) cube([PIcameraDiam + tolerance, 10, PIcameraDiam + tolerance], center = true);
	}

	//Need to hardwire the servo dimensions

	{
		servoTiltSupport(gimballWidth / 2);

	}
	//pivot mechanism
	translate([-gimballWidth / 2, 0, 0]) {
		difference() {
			rotate([0, 90, 0]) cylinder(r = panSupport, h = shellThickness);
			gimballPivot(1);
			rotate([0, 90, 0]) cylinder(r = gimballPivotR - shellThickness, h = shellThickness);

		}
		gimballPivot(1);
	}
}
//-------------------------

module servoHorn(type) {
	cube([servoHornThickness, servoHornWidth, servoHornLenght], center = true);
	if (type == "cross") rotate([90, 0, 0]) cube([servoHornThickness, servoHornWidth, servoHornLenght], center = true);
}
//-------------------------

module gimballPivot(tolerance) {
	rotate([0, 90, 0])
	difference() {
		cylinder(r = gimballPivotR - tolerance / 2, h = gimballPivotR / 2, center = true);
		cylinder(r = gimballPivotR - 3 + tolerance / 2, h = gimballPivotR / 2, center = true);
	}
}
//-------------------------

module support() {
  scaleFactor = (R + tolerance)/R;

    difference() {
        tiltSupport();

        translate([gimballWidth / 2 + servoHornThickness / 2, 0, 0]) rotate([45, 0, 0]) servoHorn("line");
        SUB_servocableDuct();
    }

	//Need to cut holes in the base for servo and camera cables and the screws
	translate([0,0,-supportBaseHeight/2])
	difference(){

		{
			color("blue",0.5)translate([0, 0, -supportZ - supportBaseHeight])base(true);
			SUB_cameracableDuct();
			SUB_servocableDuct();
			translate([0,0,+supportBaseHeight/2])mirror([1, 0, 0])tiltSupport();
			SUB_mountedPillarScrewHoles();
		}

	}
}

module mountedPillar(){
    //Pillar for camera. This one needs to be mounted separately
	difference() {
        mirror([1, 0, 0]) tiltSupport();
        translate([-gimballWidth / 2, 0, 0]) gimballPivot(0);
        translate([-gimballWidth / 2, 0, 0]) gimballPivot(3); {
        SUB_cameracableDuct();
		SUB_mountedPillarScrewHoles();
        }

    }
}

module SUB_screw(tolerance)
{
	cylinder(r= screwDiam/2+tolerance, h = screwLenght);
	translate([0,0,-3])cylinder(r= 2*screwDiam/2+screwTolerance, h = 3);
}

module SUB_mountedPillarScrewHoles()
{
	color("blue",0.5)translate([-R+supportX/2+2,0,-supportZ-screwLenght/2])
	{
	translate([0, 0.5 * panSupport,0])SUB_screw(-screwTolerance);
	mirror([0,1,0])translate([0, 0.5 * panSupport,0])SUB_screw(-screwTolerance);
	}
}

module SUB_servocableDuct() {
    //Duct for servo cable
    translate([+gimballWidth / 2 + supportX / 4 + 2, -supportX/3, -3]) {
        translate([0, 0, -supportZ + supportX]) cylinder(r = supportX / 4, h = supportZ + supportX / 2, center = true);
        translate([-supportX, 0, 0]) rotate([0, 120, 0]) cylinder(r = supportX / 4, h = supportX, center = false);
        translate([0, 0, -supportZ - supportX / 3]) rotate([0, 90, 170]) cylinder(r = supportX / 4, h = 0.8 * R, center = false);
    }

}

module SUB_cameracableDuct()
 {
    //Duct for camera connetion
    translate([-gimballWidth / 2 - 0.5 * supportX, 0, 0]) rotate([0, 0, 90]) {
        translate([0, 0, 0]) rotate([90, 0, 0]) cylinder(r = 26 / 2, h = 0.6 * supportX);
        translate([0, 0, -supportZ / 2]) cube([20, 3, supportZ + 1.1 * supportBaseHeight], center = true);
        translate([0, -R * 0.5 + 13, -supportZ - supportBaseHeight]) rotate([90, 0, 0]) cube([20, 5, R * 0.5], center = true);

    }
}
//---------------------------

module connectionSocket ()
{

cylinder(r=3, h=5);
translate([-9,-3/2,0])cube([10,3,5]);

}

module mhole ()
	{
	cylinder (r=3/2-0.2, h=2*Piheight+8, $fs=0.1);
	}

module case(){
translate([0, 0, -boxHeight  / 2 - supportZ - 2 * supportBaseHeight]) {
	difference(){
	minkowski()
	{
		box(boxLength, boxDepth, boxHeight, shellThickness - mik, "PI");
		//sphere(r = mik);
		cylinder(r=mik, h=2);
	}
translate([R-10 , -Piwidth / 2,-boxHeight  / 2 - 5/2 ])connectionSocket ();
translate([-R+10 , -Piwidth / 2,-boxHeight  / 2 - 5/2 ])connectionSocket ();
translate([R-10 , Piwidth / 2,-boxHeight  / 2 - 5/2 ])connectionSocket ();
translate([-R+10 , Piwidth / 2,-boxHeight  / 2 - 5/2 ])connectionSocket ();
translate([0, 0,-boxHeight  / 2 - 5/2 ])cylinder(r=3,h=5);

	translate([-Pilength / 2, -Piwidth / 2, -boxHeight  / 2 + 5 + shellThickness]) {
		rpi();
	}
}
translate([-Pilength / 2, -Piwidth / 2, -boxHeight  / 2 + 5 + shellThickness])
{
 translate([25.5, 18, -(+5 + shellThickness)]) mhole();
 translate([length - 5, width - 12.5, -(+5 + shellThickness)]) mhole();

 }
}
}

//mountedPillar();
//mirror([1, 0, 0])tiltSupport();
//SUB_mountedPillarScrewHoles();
//servoTiltSupport(15);
//cameraSupport();

//translate([-10, 0, 0])
//support();

topCoverHeight = 15;
difference()
{
{
translate([0, 0, -supportZ-supportBaseHeight-topCoverHeight/2])	cube([boxLenght+mik,boxDepth,topCoverHeight], center=true);
translate([0, 0, -supportZ - supportBaseHeight]){
base("false");
scale([0.8,0.8,30])base("false");
}
}
}

//$fn = 100;

//Need to fix servo tilt suport issue. The spheric part does not move with the arm when you change xPos parameter
include <rpi.scad>;
PIcameraDiam = 8;
PIcameraX = 25;
PIcameraY = 25;

mik = 2;
shellThickness = 3;
supportBaseHeight = 5;
//5.4 is the height of the
baseHeight = 31 + shellThickness - 5.4;
tolerance = 1.5;
gimballWidth = 45; //for 50 gives R = 86

R = sqrt(3 * gimballWidth * gimballWidth) / 2;
panSupport = sqrt(R * R - (gimballWidth * gimballWidth / 4));
gimballPivotR = R / 2;
supportY = 2 * sqrt(R * R - (gimballWidth / 2) * (gimballWidth / 2));
supportX = R - gimballWidth / 2;
supportZ = 1.1 * R;

servoHornThickness = 5.5;
servoHornWidth = 8;
servoHornLenght = 32;

screwDiam	= 3;
screwLenght = 10;
screwTolerance = 0.2;

Piwidth = 56;
Pilength = 85;
Piheight = 1.5;

boxLenght = Pilength + mik + 3;
boxDepth = 2 * R + 10;
boxHeight = 48;

function RatX(x) = sqrt(R * R - (x * x));

module box(Xdim, Ydim, Zdim, thickness, application)
//Creates a box, dimensions are internal
{
	difference() {
		//translate([10,0,-thickness])
		cube([Xdim + thickness, Ydim + thickness, Zdim], center = true);
		translate([0, 0, thickness / 2]) cube([Xdim, Ydim, Zdim], center = true);
		if (application == "servo") {
			translate([-Xdim / 2, 0, -0.5 * Zdim]) cube([5, Ydim + 2 * thickness, Zdim / 2 + thickness], center = true);
			translate([+Xdim / 2, 0, -0.5 * Zdim]) cube([5, Ydim + 2 * thickness, Zdim / 2 + thickness], center = true);
			translate([+Xdim / 2, 0, 0]) cube([thickness / 2, 0.3 * Ydim, Zdim], center = true);
			translate([-Xdim / 2, 0, 0]) cube([thickness / 2, 0.3 * Ydim, Zdim], center = true);
		}
	}
}

module base(servo) {
	difference(){
		translate([0, 0, -supportZ - supportBaseHeight]) {
		minkowski() {
			cylinder(r = R + mik, h = supportBaseHeight);
			rotate([90, 0, 0]) cylinder(r = mik, h = 1);
		}

		//This to create a anchorign mechanism with the pan base
		//translate([0, 0,-mik])cylinder(r = R + mik+3, h = 2);
	}
		if(servo == true) translate([0, 0, -supportZ - servoHornThickness]) rotate([0, 90, 0]) servoHorn("cross");
	}
}
//-------------------------

module bottom()
//This creates a support for the pan mechanism if the gimball is to be used to be used standalone
 {
	translate([0, 0, -supportZ - supportBaseHeight - baseHeight]) {
		difference() {

			difference() {
				minkowski() {
					cylinder(r = R + 6, h = baseHeight);
					rotate([90, 0, 0]) cylinder(r = mik, h = 1);
				}

				translate([0, 0, 5]) cylinder(r = (R + mik) - 2 * shellThickness, h = 10 * baseHeight);
			}
			translate([0, 0, baseHeight - supportBaseHeight]) cylinder(r = R + mik + tolerance, h = 10 * supportBaseHeight);
			translate([0, 0, 0]) cylinder(r = 0.7 * R + mik + 2, h = 10 * supportBaseHeight);

		}

		translate([0, 0, 17 - 3]) box(24.5, 13, 17, 3, "servo");
	}
}
//-------------------------

module supportSection() {
	intersection() {
		difference() {
			sphere(R);
			cube([gimballWidth, 2 * gimballWidth, 2 * gimballWidth], center = true);

		}
		translate([R - supportX / 2, 0, 0]) cube([supportX, supportY, 10], center = true);
	}
}
//-------------------------

module tiltSupport()
//This creates the supporting pillar for the camera shell
 {
	union(){
difference() {
		sphere(R);
		cube([gimballWidth, 2 * gimballWidth, 2 * gimballWidth], center = true);
		translate([-gimballWidth,0,0])cube([2 * gimballWidth,2 * gimballWidth,2 * gimballWidth], center=true);

	}

	hull() {
		translate([0, 0, -5]) supportSection();
		translate([0, 0, -supportZ]) supportSection();
	}}

}

module servoTiltSupport(xPos) {
	//Need to center the servo shaft, the seconf figure is the distance form border
	supportPosition = xPos;
	eccentricity = 22.2 / 2 - 5;
	servoBodySupport = 20;
	//Need to adjust the clearance to account for the Xpos
	servoClerance = 31 - 16 - servoHornThickness;
	supportCurvature = 30;

	rotate([-0, 0, 0]) difference() {

		union() {

			difference() {
				translate([-shellThickness / 2 + supportPosition, 0, 15]) {
					cube([shellThickness, 20, 2 * RatX(gimballWidth / 2)], center = true);
				}
				difference() {
					translate([-shellThickness / 2 + supportPosition, 0, 15]) cube([shellThickness, 20, 2 * RatX(gimballWidth / 2)], center = true);

					//The size of the sphere governs where the servo support will be cut. Need to add tolerance if you wnat to print as one piece with the shell.
					sphere(RatX(gimballWidth / 2) + shellThickness + tolerance);

				}

			}

			translate([-servoBodySupport / 2 + supportPosition, 0, eccentricity]) {
				//This is the servo box
				difference() {
					cube([servoBodySupport, 12 + 1 + shellThickness, 22.2 + 1 + shellThickness], center = true);
					cube([servoBodySupport, 12 + 1, 22.2 + 1], center = true);

					//Servo cable slot
					translate([0, 0, -2 * eccentricity]) cube([100, 3, 3], center = true);

				}

			}
		}

	//This is the slot in the servo arm
		translate([servoClerance + 10, 0, eccentricity]) {

			cube([20+1, 12, 32.2+1], center = true);
			translate([-31 / 2, 0, 0]) cube([31+1, 12, 22.2+1], center = true);

		}
	}

translate([0, 0, 0])
			difference() {
		translate([3, 0,+ RatX(xPos)-10])
		difference() {
			cube([20, 20, 20], center = true);
			translate([-supportCurvature, 0, -supportCurvature]) sphere(r = supportCurvature + 20);
		}

		difference() {
			sphere(RatX(gimballWidth / 2) + 10 * shellThickness + tolerance);

			sphere(RatX(gimballWidth / 2) + shellThickness + tolerance);
		}
	}

}
//-------------------------
module cameraSupport() {
	difference() {
		difference() {
			sphere(R);
			sphere(R - shellThickness);
		}

		translate([R + gimballWidth / 2, 0, 0]) cube([2 * R, 2 * R, 2 * R], center = true);
		translate([-R - gimballWidth / 2, 0, 0]) cube([2 * R, 2 * R, 2 * R], center = true);
		//Creates camera support
		translate([0, R - 7, 0]) cube([PIcameraX + tolerance, 3, PIcameraY + tolerance], center = true);
		translate([0, R - 7, 0]) cube([2, 3, PIcameraY], center = true);
		//Slot for camera wires
		translate([0, R - 8, -PIcameraY / 2 - 2]) cube([PIcameraX - 5, 3, 3], center = true);

		//Hole for the camera
		translate([0, R, 0]) rotate([90, 0, 0]) cube([PIcameraDiam + tolerance, 10, PIcameraDiam + tolerance], center = true);
	}

	//Need to hardwire the servo dimensions

	{
		servoTiltSupport(gimballWidth / 2);

	}
	//pivot mechanism
	translate([-gimballWidth / 2, 0, 0]) {
		difference() {
			rotate([0, 90, 0]) cylinder(r = panSupport, h = shellThickness);
			gimballPivot(1);
			rotate([0, 90, 0]) cylinder(r = gimballPivotR - shellThickness, h = shellThickness);

		}
		gimballPivot(1);
	}
}
//-------------------------

module servoHorn(type) {
	cube([servoHornThickness, servoHornWidth, servoHornLenght], center = true);
	if (type == "cross") rotate([90, 0, 0]) cube([servoHornThickness, servoHornWidth, servoHornLenght], center = true);
}
//-------------------------

module gimballPivot(tolerance) {
	rotate([0, 90, 0])
	difference() {
		cylinder(r = gimballPivotR - tolerance / 2, h = gimballPivotR / 2, center = true);
		cylinder(r = gimballPivotR - 3 + tolerance / 2, h = gimballPivotR / 2, center = true);
	}
}
//-------------------------

module support() {
  scaleFactor = (R + tolerance)/R;

    difference() {
        tiltSupport();

        translate([gimballWidth / 2 + servoHornThickness / 2, 0, 0]) rotate([45, 0, 0]) servoHorn("line");
        SUB_servocableDuct();
    }

	//Need to cut holes in the base for servo and camera cables and the screws
	translate([0,0,-supportBaseHeight/2])
	difference(){

		{
			color("blue",0.5)base(true);
			SUB_cameracableDuct();
			SUB_servocableDuct();
			translate([0,0,+supportBaseHeight/2])mirror([1, 0, 0])tiltSupport();
			SUB_mountedPillarScrewHoles();
		}

	}
}

module mountedPillar(){
    //Pillar for camera. This one needs to be mounted separately
	difference() {
        mirror([1, 0, 0]) tiltSupport();
        translate([-gimballWidth / 2, 0, 0]) gimballPivot(0);
        translate([-gimballWidth / 2, 0, 0]) gimballPivot(3); {
        SUB_cameracableDuct();
		SUB_mountedPillarScrewHoles();
        }

    }
}

module SUB_screw(tolerance)
{
	cylinder(r= screwDiam/2+tolerance, h = screwLenght);
	translate([0,0,-3])cylinder(r= 2*screwDiam/2+screwTolerance, h = 3);
}

module SUB_mountedPillarScrewHoles()
{
	color("blue",0.5)translate([-R+supportX/2+2,0,-supportZ-screwLenght/2])
	{
	translate([0, 0.5 * panSupport,0])SUB_screw(-screwTolerance);
	mirror([0,1,0])translate([0, 0.5 * panSupport,0])SUB_screw(-screwTolerance);
	}
}

module SUB_servocableDuct() {
    //Duct for servo cable
    translate([+gimballWidth / 2 + supportX / 4 + 2, -supportX/3, -3]) {
        translate([0, 0, -supportZ + supportX]) cylinder(r = supportX / 4, h = supportZ + supportX / 2, center = true);
        translate([-supportX, 0, 0]) rotate([0, 120, 0]) cylinder(r = supportX / 4, h = supportX, center = false);
        translate([0, 0, -supportZ - supportX / 3]) rotate([0, 90, 170]) cylinder(r = supportX / 4, h = 0.8 * R, center = false);
    }

}

module SUB_cameracableDuct()
 {
    //Duct for camera connetion
    translate([-gimballWidth / 2 - 0.5 * supportX, 0, 0]) rotate([0, 0, 90]) {
        translate([0, 0, 0]) rotate([90, 0, 0]) cylinder(r = 26 / 2, h = 0.6 * supportX);
        translate([0, 0, -supportZ / 2]) cube([20, 3, supportZ + 1.1 * supportBaseHeight], center = true);
        translate([0, -R * 0.5 + 13, -supportZ - supportBaseHeight]) rotate([90, 0, 0]) cube([20, 5, R * 0.5], center = true);

    }
}
//---------------------------

module connectionSocket ()
{

cylinder(r=3, h=5);
translate([-9,-3/2,0])cube([10,3,5]);

}

module mhole ()
	{
	cylinder (r=3/2-0.2, h=2*Piheight+8, $fs=0.1);
	}

module case(){
translate([0, 0, -boxHeight  / 2 - supportZ - 2 * supportBaseHeight]) {
	difference(){
	minkowski()
	{
		box(boxLength, boxDepth, boxHeight, shellThickness - mik, "PI");
		//sphere(r = mik);
		cylinder(r=mik, h=2);
	}
translate([R-10 , -Piwidth / 2,-boxHeight  / 2 - 5/2 ])connectionSocket ();
translate([-R+10 , -Piwidth / 2,-boxHeight  / 2 - 5/2 ])connectionSocket ();
translate([R-10 , Piwidth / 2,-boxHeight  / 2 - 5/2 ])connectionSocket ();
translate([-R+10 , Piwidth / 2,-boxHeight  / 2 - 5/2 ])connectionSocket ();
translate([0, 0,-boxHeight  / 2 - 5/2 ])cylinder(r=3,h=5);

	translate([-Pilength / 2, -Piwidth / 2, -boxHeight  / 2 + 5 + shellThickness]) {
		rpi();
	}
}
translate([-Pilength / 2, -Piwidth / 2, -boxHeight  / 2 + 5 + shellThickness])
{
 translate([25.5, 18, -(+5 + shellThickness)]) mhole();
 translate([length - 5, width - 12.5, -(+5 + shellThickness)]) mhole();

 }
}
}

//mountedPillar();
//mirror([1, 0, 0])tiltSupport();
//SUB_mountedPillarScrewHoles();
//servoTiltSupport(15);
//cameraSupport();

//translate([-10, 0, 0])
//support();
topCoverHeight = 15;
difference()
{
{
translate([0, 0, -supportZ-supportBaseHeight-topCoverHeight/2])	cube([boxLenght+mik,boxDepth,topCoverHeight], center=true);

}
}


PrinterBotZStop.scad: create multiple to explore interior hole adjustments

// Various Z stop parts.

for (i = [0:5]) {
     translate([i * 25, 0, 0]) {
          BottomNutCapture(19, 14, 8, 13.2, 9 + i * 0.2, 3, 2 + i * 0.2);
     }
}

module BottomNutCapture(width, length, height, slotWidth, nutDiameter, nutHeight, screwDiameter) {
    // width = width in mm
    // length = length in mm
    // height = height in mm

    difference() {
        // body
        cube([width, length, height], center=true);

        // slot
        translate([0, -1, 10]) {
            cube([slotWidth, length + 3, 20], center=true);
        }

        // nut
        translate([0, 0, -nutHeight]) {
            cylinder(h = nutHeight + 1, d = nutDiameter, $fn=6, center=false);
        }

        // screw hole
        cylinder(h = height + 2, d = screwDiameter, $fn=30, center=true);
    }
}

// Various Z stop parts.

BottomNutCapture(19, 14, 8, 13, 7, 3, 2);

module BottomNutCapture(width, length, height, slotWidth, nutDiameter, nutHeight, screwDiameter) {
    // width = width in mm
    // length = length in mm
    // height = height in mm

    difference() {
        // body
        cube([width, length, height], center=true);

        // slot
        translate([0, -1, 10]) {
            cube([slotWidth, length + 3, 20], center=true);
        }

        // nut
        translate([0, 0, -nutHeight]) {
            cylinder(h = nutHeight + 1, d = nutDiameter, $fn=6, center=false);
        }

        // screw hole
        cylinder(h = height + 2, d = screwDiameter, $fn=30, center=true);
    }
}


Adding shedshed.scad

Adding shedshed.scad

shed_length = 5184;
shed_width = 1829+305/2;
shed_front_height = 2400;
shed_front_back = 2135;
base_timber = 47;

module cubeI(size,center=false)
{
    echo("Dim: ",size);
    cube(size, center=center);
}

module shedBaseSection(x,y,timber_width=75,timber_length=47, braces=0)
{
    echo("shedBaseSection: x,y,timber_width,timber_length, braces ", x,y,timber_width,timber_length, braces);
    echo("http://www.wickes.co.uk/Wickes-Sawn-Kiln-Dried-47X75-x-3000mm-Single/p/107186#tab-DynamicDeliveryWebTab_content");
    cubeI([x,timber_width,timber_length]);
    translate([0,y-timber_width,0]) cubeI([x,timber_width,timber_length]);
    translate([0,timber_width,0]) cubeI([timber_width,y-timber_width*2,timber_length]);
    translate([x-timber_width,timber_width,0]) cubeI([timber_width,y-timber_width*2,timber_length]);
    if(braces > 0)
    {
        middle_y = y - timber_width*2;
        part_y = middle_y/(braces+1);
        for(loop=[1 : braces ])
        {
                translate([timber_width,timber_width/(braces+1) + (loop*part_y),0]) cubeI([x-timber_width*2, timber_width,timber_length]);
        }
    }
}

module shedBase(x,y,number_x,number_y, braces=1)
{
    for(base_y = [0 : number_y-1])
    {
        for(base_x = [0 : number_x-1])
            {
                translate([base_x*(x/number_x),base_y*(y/number_y),0]) shedBaseSection(x/number_x,y/number_y, braces = braces);
            }
    }
}

module floorMembrane(x,y,thickness,color="Black", overlap=1)
{
    echo("x,y,thickness=1,color, overlap=1",x,y,thickness,color, overlap);
    echo("http://www.screwfix.com/p/dmp-damp-proof-membrane-black-1000ga-3-x-4m/50464#product_additional_details_container");
    translate([-overlap,-overlap,0]) color(color, 1) cube([x+overlap*2,y+overlap*2, thickness]);
}

module shedLowerFloor(x,y, panel_slf_w = 607, panel_slf_l =   1829, panel_slf_t =   5.5, panel_min_dimentions = 100)
{
    echo("http://www.wickes.co.uk/Wickes-Non-Structural-Hardwood-Plywood-5-5x607x1829mm/p/111196");
    x_panels = round(-0.5+x/panel_slf_w);
    y_panels = round(-0.5+y/panel_slf_l);
    for(base_y = [0 : y_panels-1]) //Truncate not round
    {
        for(base_x = [0 : x_panels-1])
        {
            translate([base_x*panel_slf_w,base_y*panel_slf_l,0]) cubeI([panel_slf_w, panel_slf_l,panel_slf_t]);
            if(y-(panel_slf_l*y_panels) > panel_min_dimentions)
            translate([base_x*panel_slf_w,y_panels*panel_slf_l,0]) cubeI([panel_slf_w, y-(panel_slf_l*y_panels),panel_slf_t]);
            }
        if(x-(panel_slf_w*x_panels) > panel_min_dimentions)
            translate([(x_panels)*panel_slf_w,(y_panels-1)*panel_slf_l,0]) cubeI([x-(panel_slf_w*x_panels), panel_slf_l,panel_slf_t]);
        if(y-(panel_slf_l*y_panels) > panel_min_dimentions)
            translate([(x_panels)*panel_slf_w,y_panels*panel_slf_l,0]) cubeI([x-(panel_slf_w*x_panels), y-(panel_slf_l*y_panels),panel_slf_t]);
    }

}

module verticalStruts(x,z,timber_width=47,timber_length=47, braces=0)
{
//    echo("shedBaseSection(x,z,timber_width,timber_length, braces",x,z,timber_width,timber_length, braces);
//    echo("Walls - http://www.wickes.co.uk/Wickes-Sawn-Kiln-Dried-47-x-47-x-2400mm-Pack-6/p/107114");
    cubeI([x,timber_width,timber_length]);
    translate([0,0,z-timber_width]) cubeI([x,timber_width,timber_length]);
    translate([0,0,timber_width]) cubeI([timber_width,timber_length,z-timber_width*2]);
    translate([x-timber_width,0,timber_width]) cubeI([timber_width,timber_length,z-timber_width*2]);
    if(braces > 0)
    {
        middle_z = z - timber_width*2;
        part_z = middle_z/(braces+1);
        for(loop=[1 : braces ])
        {
                translate([timber_width,0,timber_width/(braces+1) + (loop*part_z)]) cubeI([x-timber_width*2, timber_width,timber_length]);
        }
    }
}

module backWallStruts(x,z,number_x, braces=1)
{
    echo("backWallStruts(x,z,number_x, braces)",x,z,number_x, braces);
        for(base_x = [0 : number_x-1])
            {
                translate([base_x*(x/number_x),0,0]) verticalStruts(x/number_x,z, braces = braces);
            }
}

module frontWallStruts(x,z, space_to_window_w, space_to_window_h, window_w, window_h, door_w, door_h)
{
    echo("frontWallStruts(x,z,space_to_window_w, space_to_window_h, window_w, window_h, door_w)", x,z, space_to_window_w, space_to_window_h, window_w, window_h, door_w, door_h);
    translate([0,0,0]) verticalStruts(space_to_window_w,space_to_window_h+window_h, braces = braces);
    for(support_windows = [0 : 1])
    {
        translate([space_to_window_w+(support_windows*window_w/2),0,0]) verticalStruts(window_w/2,space_to_window_h, braces = braces);
    }
    translate([0,0,space_to_window_h+window_h]) verticalStruts(space_to_window_w/2,z-(space_to_window_h+window_h), braces = braces);
    translate([space_to_window_w/2,0,space_to_window_h+window_h]) verticalStruts(window_w+space_to_window_w,z-(space_to_window_h+window_h), braces = braces);
    translate([space_to_window_w+window_w,0,0]) verticalStruts(space_to_window_w,space_to_window_h+window_h, braces = braces);
    translate([space_to_window_w/2+window_w+space_to_window_w,0,space_to_window_h+window_h]) verticalStruts(space_to_window_w/2,door_h-(space_to_window_h+window_h), braces = braces);
    translate([space_to_window_w/2+window_w+space_to_window_w,0,door_h]) verticalStruts(x-(space_to_window_w/2+window_w+space_to_window_w),z-door_h, braces = braces);
    translate([space_to_window_w+window_w+space_to_window_w+door_w,0,0]) verticalStruts(x-(space_to_window_w+window_w+space_to_window_w+door_w),door_h, braces = braces);
}

shedBase(shed_length, shed_width, number_x=4,number_y=1, braces=1);
translate([0,0,base_timber]) floorMembrane(shed_length, shed_width, thickness = 1);
translate([0,0,base_timber+1]) shedLowerFloor(shed_length, shed_width);
translate([0,shed_width-base_timber,base_timber+1+5.5])  backWallStruts(shed_length, shed_front_back, 5);
translate([0,0,base_timber+1+5.5])  frontWallStruts(shed_length,shed_front_height, space_to_window_w=1830/2, space_to_window_h=shed_front_height-610-610, window_w=1830, window_h=610, door_w=870, , door_h=2030);

//shedBaseSection(shed_length/6,shed_width, braces = 1);

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


cube size increased, to avoid small-model issues, when printing

/*
 * small 3D cube for test prints
 */
cube([50, 30, 10]);

/*
 * small 3D cube for test prints
 */
cube([30, 20, 10]);


A 3d test piece designed to be pulled apart to measure part strength

// A strain test by pulling on each end
// Author: Joseph M. Joy
//
EPSILON = 0.001;
testDia = 6; // diameter of the thin, center cylinder
testHeight = 4; // height of thin cylinder
capDia = 12; // diameter of the thicker end-caps
capHeight = 8;
transitionHeight = 3; // Height of truncated transition cone from cap to test

pinHoleDia = 3; // diameter of hole in end-cap for pin
pinHoleCenterHeight = 3;
cordDia = 3; // Nominal diameter of cord (actually it is slightly larger than cord)

// The cord is attached to this end cap - looped over a pin inserted into
// the pin hole. There is one one each side of the test piece.
module endCap() {
    difference() {
        cylinder(d=capDia, capHeight);
        negativeCapSpace();
    }
}

// The composite holes for the pin and cord - designed to be
// subtracted from the end cap solid.
module negativeCapSpace() {
    pinLen = 2*capDia;
    cx = (cordDia + 0.6*pinHoleDia)/2;
    ch = pinHoleCenterHeight + pinHoleDia/2 + cordDia;
    union() {
        translate([0, pinLen/2, pinHoleCenterHeight]) rotate([90, 0, 0])
            cylinder(d=pinHoleDia, pinLen);
        translate([-cx, 0, -EPSILON]) cylinder(d=cordDia, ch);
        translate([cx, 0, -EPSILON]) cylinder(d=cordDia, ch);
        translate([-cx, -cordDia/2, -EPSILON]) cube([2*cx, cordDia, ch]);
    }
}

// Truncated cone transition from end cap to the thinner central test cylinder.
module transition() {
    cylinder(d1=capDia, d2=testDia, transitionHeight);
}

// The thin central cylinder - designed to be the piece that fails under
// the test load
module center() {
    cylinder(d=testDia, testHeight);
}

// The final test piece
module pullTestPiece() {
    endCap();
    z1 = capHeight;
    translate([0,0,capHeight]) transition();
    z2 = z1 + transitionHeight;
    translate([0,0, capHeight+transitionHeight]) center();
    z3 = z2 + testHeight;
    translate([0,0,z3 + transitionHeight]) rotate([180,0,0]) transition();
    z4 = z3 + transitionHeight;
    translate([0,0,z4 + capHeight]) rotate([180,0,0]) endCap();
}

$fn = 100;
//endCap();
//transition();
//center();
pullTestPiece();
//negativeCapSpace();

error: pathspec '3dprinting/openscad/test-models/pull-v1.scad' did not match any file(s) known to git


The whitepace was updated.

The whitepace was updated.

use <../../coin.scad>;

coin(innerIcon = "Spur",
    innerIconXyScale = 0.4,
    outerIcon = "Spur",
    outerIconCount = 10,
    outerIconXyScale = 0.125,
    radius = 55,
    height=5);


The icon paramters were organized.

The icon paramters were organized.

/* [Base] */

// This parameter is all about that base color.
baseColor = "black"; // [pink, red, black, white, yellow, blue, green]

baseThickness = 2; // [1 : 5]

// This determines how wide the name tag is.
baseWidth = 228;	// [228:600]

// This determines the height of the name tag.
baseHeight = 15; // [54:150]

/* [Border] */
borderColor = "yellow"; // [pink, red, black, white, yellow, blue, green]
showBorder = "No"; // [Yes, No]

/* [Bottom Text] */
bottomText = "Fun Enthusiast";
bottomTextFont = "Arial"; // "Wingdings";
bottomTextOffsetX = 0; // [-315 : 315]
bottomTextOffsetY = -15; // [-315 : 315]
bottomTextSize = 12; // [0 : 40]

/* [Chain Loop]*/
chainLoop = true;
chainLoopLengthZ = 6;
chainLoopType = "square"; // [rounded, square]
chainLoopPosition = "bottom"; // [bottom, top]

/* [General] */
letterThickness = 3; // [1 : 15]

/* [Icons] */
iconColor = "white"; // [pink, red, black, white, yellow, blue, green]

// This is the x off set of the icons
xIconOffset = -100; // [10:200]

// This is the y off set of the icons
yIconOffset = 3;  // [1:200]

/* [Left Icon] */
//TODO: Where is the heart icon, man?  "Put your heart into it."
leftIconType = "Moon";   // [Bass Clef, Creeper, Light Bulb, Moon, Rebel, Trooper, Aqua Dude, Cat, Fan, Spur, Mario, Luigi, Sun, Thundercat, Treble Clef]

// This is the X,Y scale of the icons.
leftIconXyScale = 0.99;  // [0.1 : 0.05 : 5]

leftIconHeight = 2.5; // [0.1: 0.1 :5]

/* [Right Icon] */
rightIconHeight = 4.0; // [0.1: 0.1 :5]

//TODO: Where is the heart icon, man?  "Put your heart into it."
rightIconType = "Sun";          // [Bass Clef, Creeper, Light Bulb, Moon, Rebel, Trooper, Aqua Dude, Cat, Fan, Spur, Mario, Luigi, Sun, Thundercat, Treble Clef]

rightIconXyScale = 1.3; // [0.1 : 0.05 : 5]

/* [Top Text] */
topText = "Firstnesto Lastquez";
topTextColor = "white"; // [pink, red, black, white, yellow, blue, green]
topTextFont = "Bauhaus 93";
topTextSize = 15; // [0 : 40]

/* [Hidden] */

use <../name-tag.scad>

nametag(baseColor = baseColor,
        baseThickness = baseThickness,
        borderColor = borderColor,
        chainLoop = chainLoop,
        chainLoopLengthZ = chainLoopLengthZ,
        chainLoopPosition = chainLoopPosition,
		chainLoopType = chainLoopType,
        iconColor = iconColor,
        letterThickness = letterThickness,
        roundedCorners = true,
        topText = topText,
		topTextOffsetY = 6,
        topTextSize = topTextSize,
        topTextColor = topTextColor,
        topTextFont = topTextFont,
        bottomText = bottomText,
        bottomTextFont = bottomTextFont,
        bottomTextOffsetX = bottomTextOffsetX,
        bottomTextOffsetY = bottomTextOffsetY,
		bottomTextSize = bottomTextSize,
		leftIconXyScale = leftIconXyScale,
        leftIconType = leftIconType,
        leftIconHeight = leftIconHeight,
        rightIconHeight = rightIconHeight,
		rightIconXyScale = rightIconXyScale,
        rightIconType = rightIconType,
        xIconOffset = xIconOffset,
        yIconOffset = yIconOffset,
        baseWidth = baseWidth,
        showBorder = showBorder);

/* [Base] */

// This parameter is all about that base color.
baseColor = "black"; // [pink, red, black, white, yellow, blue, green]

baseThickness = 2; // [1 : 5]

// This determines how wide the name tag is.
baseWidth = 228;	// [228:600]

// This determines the height of the name tag.
baseHeight = 15; // [54:150]

/* [Border] */
borderColor = "yellow"; // [pink, red, black, white, yellow, blue, green]
showBorder = "No"; // [Yes, No]

/* [Bottom Text] */
bottomText = "Fun Enthusiast";
bottomTextFont = "Arial"; // "Wingdings";
bottomTextOffsetX = 0; // [-315 : 315]
bottomTextOffsetY = -15; // [-315 : 315]
bottomTextSize = 12; // [0 : 40]

/* [Chain Loop]*/
chainLoop = true;
chainLoopLengthZ = 6;
chainLoopType = "square"; // [rounded, square]
chainLoopPosition = "bottom"; // [bottom, top]

/* [General] */
letterThickness = 3; // [1 : 15]

/* [Icons] */
iconColor = "white"; // [pink, red, black, white, yellow, blue, green]
//TODO: Where is the heart icon, man?  "Put your heart into it."
leftIconType = "Moon";   // [Bass Clef, Creeper, Light Bulb, Moon, Rebel, Trooper, Aqua Dude, Cat, Fan, Spur, Mario, Luigi, Sun, Thundercat, Treble Clef]
rightIconType = "Sun";          // [Bass Clef, Creeper, Light Bulb, Moon, Rebel, Trooper, Aqua Dude, Cat, Fan, Spur, Mario, Luigi, Sun, Thundercat, Treble Clef]

// This is the x off set of the icons
xIconOffset = -100; // [10:200]

// This is the y off set of the icons
yIconOffset = 3;  // [1:200]

// This is the X,Y scale of the icons.
leftIconXyScale = 0.99;  // [0.1 : 0.05 : 5]

rightIconXyScale = 1.3; // [0.1 : 0.05 : 5]

leftIconHeight = 2.5; // [0.1: 0.1 :5]
rightIconHeight = 4.0; // [0.1: 0.1 :5]

/* [Top Text] */
topText = "Firstnesto Lastquez";
topTextColor = "white"; // [pink, red, black, white, yellow, blue, green]
topTextFont = "Bauhaus 93";
topTextSize = 15; // [0 : 40]

/* [Hidden] */

use <../name-tag.scad>

nametag(baseColor = baseColor,
        baseThickness = baseThickness,
        borderColor = borderColor,
        chainLoop = chainLoop,
        chainLoopLengthZ = chainLoopLengthZ,
        chainLoopPosition = chainLoopPosition,
		chainLoopType = chainLoopType,
        iconColor = iconColor,
        letterThickness = letterThickness,
        roundedCorners = true,
        topText = topText,
		topTextOffsetY = 6,
        topTextSize = topTextSize,
        topTextColor = topTextColor,
        topTextFont = topTextFont,
        bottomText = bottomText,
        bottomTextFont = bottomTextFont,
        bottomTextOffsetX = bottomTextOffsetX,
        bottomTextOffsetY = bottomTextOffsetY,
		bottomTextSize = bottomTextSize,
		leftIconXyScale = leftIconXyScale,
        leftIconType = leftIconType,
        leftIconHeight = leftIconHeight,
        rightIconHeight = rightIconHeight,
		rightIconXyScale = rightIconXyScale,
        rightIconType = rightIconType,
        xIconOffset = xIconOffset,
        yIconOffset = yIconOffset,
        baseWidth = baseWidth,
        showBorder = showBorder);