rod-clamps: don't include rod as vitamin

include <rod-clamps.h>

include <thing_libutils/materials.scad>
use <thing_libutils/attach.scad>
use <thing_libutils/shapes.scad>
use <thing_libutils/screws.scad>
use <thing_libutils/transforms.scad>

module mount_rod_clamp_half(part, rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4, align, orient, align_obj = "rod")
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?outer_d+thread_dia+thick_:screw_dist;
    base_thick_=base_thick==undef?thick_*1.2:base_thick;
    clamp_tolerance = 0.5*mm;

    pos_offset = align_obj == "mount" ? N : N;

    if(part==undef)
    {
        difference()
        {
            mount_rod_clamp_half(part="pos", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
            mount_rod_clamp_half(part="neg", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
        }
        if($show_vit)
        {
            %mount_rod_clamp_half(part="vit", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
        }
    }
    else if(part=="pos")
    {
        s=[outer_d, base_thick_, width];
        material(Mat_Plastic)
        size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        {
            /*hull()*/
            {
                // cylinder around rod
                rcylindera(d=outer_d, h=width, orient=Z, align=N);

                // base
                rcubea([base_thick_, screw_dist_+thread_dia*2.5, width], align=X);
            }
        }
    }
    else if(part=="neg")
    {
        s=[outer_d, base_thick_, width];
        size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        {
            // cut bottom of cylinder
            cubea([outer_d/2+.1, screw_dist_+thread_dia*2.5+.1, width+1], align=[-1,0,0]);

            // cut clamp screw holes
            for(i=[-1,1])
            translate([0, i*screw_dist_/2, 0])
            {
                screw_cut(thread=thread, orient=-X);
            }

            // cut rod
            translate(-clamp_tolerance*X)
            cylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=Z);
        }
    }
    else if(part=="vit")
    {
        s=[outer_d, base_thick_, width];
        size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        {
            translate(-clamp_tolerance*X)
            cylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=Z);
        }
    }
}

module mount_rod_clamp_full(part, rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4, align, orient, align_obj = "rod")
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?outer_d+thread_dia*2+thick_:screw_dist;
    base_thick_=base_thick==undef?thick_*1.2:base_thick;
    clamp_tolerance = 0.5*mm;

    pos_offset = align_obj == "mount" ? N : [-rod_d/2,0,0];

    s=[base_thick_, screw_dist_+thread_dia*2.5, width];
    if(part==undef)
    {
        difference()
        {
            mount_rod_clamp_full(part="pos", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
            mount_rod_clamp_full(part="neg", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
        }
        if($show_vit)
        {
            %mount_rod_clamp_full(part="vit", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
        }
    }
    else if(part=="pos")
    {
        material(Mat_Plastic)
        size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        {
            /*hull()*/
            {
                // cylinder around rod
                translate([rod_d/2,0,0])
                rcylindera(d=outer_d, h=width, orient=Z, align=N);

                // base
                /*translate([-rod_d/2,0,0])*/
                rcubea([base_thick_, screw_dist_+thread_dia*2.5, width], align=X);
            }
        }
    }
    else if(part=="neg")
    {
        size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        {
            // cut bottom of cylinder
            /*translate(-rod_d/2*X)*/
            cubea([outer_d/2, screw_dist_+thread_dia*2.5+.1, width+1], align=[-1,0,0]);

            // cut clamp screw holes
            for(i=[-1,1])
            translate([0, i*screw_dist_/2, 0])
            {
                screw_cut(thread=thread, orient=-X);
            }

            // cut rod
            translate([rod_d/2,0,0])
            translate(-clamp_tolerance*X)
            hull()
            {
                stack(axis=-X, dist=100)
                {
                    cylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=Z);
                    cylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=Z);
                }
            }
        }
    }
    else if(part=="vit")
    {
        /*%size_align(size=s, align=align, orient=orient, orient_ref=Z)*/
        /*translate(pos_offset)*/
        /*translate([rod_d/2,0,0])*/
        /*translate(-clamp_tolerance*X)*/
        /*cylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=Z);*/
    }
}

if(false)
{
    /*$show_vit=false;*/
    /*$preview_mode=false;*/
    stack(axis=Z, dist=50)
    {
        mount_rod_clamp_half(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5, align_obj="mount");
        mount_rod_clamp_full(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5, align_obj="mount");

        mount_rod_clamp_half(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5, align_obj="rod");
        mount_rod_clamp_full(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5, align_obj="rod");
    }
}

include <rod-clamps.h>

include <thing_libutils/materials.scad>
use <thing_libutils/attach.scad>
use <thing_libutils/shapes.scad>
use <thing_libutils/screws.scad>
use <thing_libutils/transforms.scad>

module mount_rod_clamp_half(part, rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4, align, orient, align_obj = "rod")
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?outer_d+thread_dia+thick_:screw_dist;
    base_thick_=base_thick==undef?thick_*1.2:base_thick;
    clamp_tolerance = 0.5*mm;

    pos_offset = align_obj == "mount" ? N : N;

    if(part==undef)
    {
        difference()
        {
            mount_rod_clamp_half(part="pos", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
            mount_rod_clamp_half(part="neg", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
        }
        if($show_vit)
        {
            %mount_rod_clamp_half(part="vit", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
        }
    }
    else if(part=="pos")
    {
        s=[outer_d, base_thick_, width];
        material(Mat_Plastic)
        size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        {
            /*hull()*/
            {
                // cylinder around rod
                rcylindera(d=outer_d, h=width, orient=Z, align=N);

                // base
                rcubea([base_thick_, screw_dist_+thread_dia*2.5, width], align=X);
            }
        }
    }
    else if(part=="neg")
    {
        s=[outer_d, base_thick_, width];
        size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        {
            // cut bottom of cylinder
            cubea([outer_d/2+.1, screw_dist_+thread_dia*2.5+.1, width+1], align=[-1,0,0]);

            // cut clamp screw holes
            for(i=[-1,1])
            translate([0, i*screw_dist_/2, 0])
            {
                screw_cut(thread=thread, orient=-X);
            }

            // cut rod
            translate(-clamp_tolerance*X)
            cylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=Z);
        }
    }
    else if(part=="vit")
    {
        s=[outer_d, base_thick_, width];
        size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        {
            translate(-clamp_tolerance*X)
            cylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=Z);
        }
    }
}

module mount_rod_clamp_full(part, rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4, align, orient, align_obj = "rod")
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?outer_d+thread_dia*2+thick_:screw_dist;
    base_thick_=base_thick==undef?thick_*1.2:base_thick;
    clamp_tolerance = 0.5*mm;

    pos_offset = align_obj == "mount" ? N : [-rod_d/2,0,0];

    s=[base_thick_, screw_dist_+thread_dia*2.5, width];
    if(part==undef)
    {
        difference()
        {
            mount_rod_clamp_full(part="pos", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
            mount_rod_clamp_full(part="neg", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
        }
        if($show_vit)
        {
            %mount_rod_clamp_full(part="vit", rod_d=rod_d, screw_dist=screw_dist, width=width, thick=thick, base_thick=base_thick, thread=thread, align=align, orient=orient, align_obj=align_obj);
        }
    }
    else if(part=="pos")
    {
        material(Mat_Plastic)
        size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        {
            /*hull()*/
            {
                // cylinder around rod
                translate([rod_d/2,0,0])
                rcylindera(d=outer_d, h=width, orient=Z, align=N);

                // base
                /*translate([-rod_d/2,0,0])*/
                rcubea([base_thick_, screw_dist_+thread_dia*2.5, width], align=X);
            }
        }
    }
    else if(part=="neg")
    {
        size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        {
            // cut bottom of cylinder
            /*translate(-rod_d/2*X)*/
            cubea([outer_d/2, screw_dist_+thread_dia*2.5+.1, width+1], align=[-1,0,0]);

            // cut clamp screw holes
            for(i=[-1,1])
            translate([0, i*screw_dist_/2, 0])
            {
                screw_cut(thread=thread, orient=-X);
            }

            // cut rod
            translate([rod_d/2,0,0])
            translate(-clamp_tolerance*X)
            hull()
            {
                stack(axis=-X, dist=100)
                {
                    cylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=Z);
                    cylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=Z);
                }
            }
        }
    }
    else if(part=="vit")
    {
        %size_align(size=s, align=align, orient=orient, orient_ref=Z)
        translate(pos_offset)
        translate([rod_d/2,0,0])
        translate(-clamp_tolerance*X)
        cylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=Z);
    }
}

if(false)
{
    /*$show_vit=false;*/
    /*$preview_mode=false;*/
    stack(axis=Z, dist=50)
    {
        mount_rod_clamp_half(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5, align_obj="mount");
        mount_rod_clamp_full(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5, align_obj="mount");

        mount_rod_clamp_half(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5, align_obj="rod");
        mount_rod_clamp_full(rod_d=yaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5, align_obj="rod");
    }
}


rod-clamps: Tweaks

rod-clamps: Tweaks

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

mount_rod_clamp_conn_rod = [[0,0,0],[1,0,0]];

module mount_rod_clamp_half(rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4, orient=[0,0,1])
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?rod_d+thread_dia*2+thick_+thread_dia/2:screw_dist;
    base_thick_=base_thick==undef?thick_*1.5:base_thick;

    orient(orient)
    difference()
    {
        union()
        {
            difference()
            {
                fncylindera(d=outer_d, h=width, orient=[0,0,1], align=[0,0,0]);
                cubea([outer_d/2+.1, outer_d+.1, width+1], align=[-1,0,0]);
            }
            cubea([base_thick_, screw_dist_+thread_dia*2.5, width], align=[1,0,0]);
        }

        // cut clamp screw holes
        for(i=[-1,1])
        translate([0, i*screw_dist_/2, 0])
        {
            fncylindera(d=thread_dia, h=base_thick_*3, orient=[1,0,0]);
        }

        // cut zrod
        fncylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=[0,0,1]);
    }
}

module mount_rod_clamp_full(rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4, orient=[0,0,1])
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?rod_d+thread_dia*2+thick_+thread_dia/2:screw_dist;
    base_thick_=base_thick==undef?thick_*1.5:base_thick;

    orient(orient)
    difference()
    {
        union()
        {
            difference()
            {
                fncylindera(d=outer_d, h=width, orient=[0,0,1], align=[0,0,0]);
                translate([-rod_d/2,0,0])
                    cubea([outer_d/2+.1, outer_d+.1, width+1], align=[-1,0,0]);
            }
            translate([-rod_d/2,0,0])
            cubea([base_thick_, screw_dist_+thread_dia*2.5, width], align=[1,0,0]);
        }

        // cut clamp screw holes
        for(i=[-1,1])
        translate([0, i*screw_dist_/2, 0])
        {
            fncylindera(d=thread_dia, h=base_thick_*3, orient=[1,0,0]);
        }

        // cut zrod
        fncylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=[0,0,1]);
    }
}

/*translate([20,0,0])*/
/*mount_rod_clamp_half(rod_d=xaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5);*/

/*mount_rod_clamp_full(rod_d=xaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5);*/

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

module mount_rod_clamp_half(rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4)
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?rod_d+thread_dia*2+thick_+thread_dia/2:screw_dist;
    base_thick=thick_*1.5;
    difference()
    {
        union()
        {
            difference()
            {
                fncylindera(d=outer_d, h=width, orient=[0,0,1], align=[0,0,0]);
                cubea([outer_d/2+.1, outer_d+.1, width+1], align=[-1,0,0]);
            }
            cubea([base_thick, screw_dist_+thread_dia*2, width], align=[1,0,0]);
        }

        // cut clamp screw holes
        for(i=[-1,1])
        translate([0, i*screw_dist_/2, 0])
        {
            fncylindera(d=thread_dia, h=base_thick*3, orient=[1,0,0]);
        }

        // cut zrod
        fncylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=[0,0,1]);
    }
}

module mount_rod_clamp_full(rod_d=10, screw_dist=undef, width=4, thick=undef, base_thick=undef, thread=ThreadM4)
{
    thick_=thick==undef?rod_d:thick;
    outer_d= rod_d+thick_*2;
    thread_dia=lookup(ThreadSize, thread);
    screw_dist_=screw_dist==undef?rod_d+thread_dia*2+thick_+thread_dia/2:screw_dist;
    base_thick=thick_*1.5;
    difference()
    {
        union()
        {
            difference()
            {
                fncylindera(d=outer_d, h=width, orient=[0,0,1], align=[0,0,0]);
                translate([-rod_d/2,0,0])
                    cubea([outer_d/2+.1, outer_d+.1, width+1], align=[-1,0,0]);
            }
            translate([-rod_d/2,0,0])
            cubea([base_thick, screw_dist_+thread_dia*2, width], align=[1,0,0]);
        }

        // cut clamp screw holes
        for(i=[-1,1])
        translate([0, i*screw_dist_/2, 0])
        {
            fncylindera(d=thread_dia, h=base_thick*3, orient=[1,0,0]);
        }

        // cut zrod
        fncylindera(d=rod_d*rod_fit_tolerance, h=width*2, orient=[0,0,1]);
    }
}

/*translate([20,0,0])*/
/*mount_rod_clamp_half(rod_d=xaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5);*/

/*mount_rod_clamp_full(rod_d=xaxis_rod_d,  width=extrusion_size, thick=4, thread=ThreadM5);*/


proper drawings for 25x37x7 bearings on B-axle

// try to draw Jansen linkage leg assembly as it might appear in steel

// these are for configuration "E" as referenced in other drawings
AC=17.5;
Ay =  3.318; Bx = 53.833;
BD = 48.020; BE = 46.977; BH = 40.359;
CD = 59.635; CH = 71.441; DE = 66.437;
EF = 47.467; FG = 75.792;
FH = 40.843; GH = 55.790;

DEleft = (DE*DE + BD*BD - BE*BE)/(2*DE);
FGleft = (FG*FG + FH*FH - GH*GH)/(2*FG);
DEperp = sqrt(BD*BD - DEleft*DEleft);
FGperp = sqrt(FH*FH - FGleft*FGleft);

echo(str("DEleft=",DEleft,"   DEperp=",DEperp));
echo(str("FGleft=",FGleft,"   FGperp=",FGperp));

//r38 = (3/8)*2.54/2;  // radius of 3/8" bolt

a=360*$t;
legAssembly(a,0);
mirror([1,0,0]) legAssembly(180-a,1.3);

//  -------------------------- crank-arm circle reference
%color([1,.5,.3,.4]) translate([0,Ay,-2]) difference() {
  cylinder(r=AC,h=1,$fn=48,center=true);
  cylinder(r=2,h=2,center=true);
}
color([0.3,.3,1,.7]) // axles
for(x=[-1,1]) translate([x*Bx,0,0]) difference() {
   cylinder(r=2.54/2,h=20,$fn=24,center=true);
   cylinder(r=2.54/2-.4,h=22,$fn=19,center=true);
}

%translate([0,-93,0]) cube([200,2,2],center=true); // ground

// -----------------------------------------------------------------

// plot a link shadow, a different way, to check kinematic correctness
module checkLink(xa,ya,xb,yb,ab) {
  *translate([(xa+xb)/2,(ya+yb)/2,-9])
    rotate([0,0,atan2(yb-ya,xb-xa)]) cube([ab,1,1],center=true);
}

function triK1(ax,ay,ca,bx,by,cb) = (cb*cb - ca*ca + ax*ax -bx*bx +ay*ay -by*by)/(2*(ax-bx));

// ===================================================================

module legAssembly(ang=0,linkOffset=0) {

// solve kinematics for given crank angle
xC = AC*cos(ang);
yC = AC*sin(ang)+Ay;
echo("C",xC,yC);

k1=(yC*yC - Bx*Bx + BD*BD - CD*CD + xC*xC)/(2*yC);
k2=(xC+Bx)/yC;
c=k1*k1-BD*BD+Bx*Bx;
b=2*(Bx-k1*k2);
a=k2*k2+1;
sgnD=(yC<0)?1:-1;
xD=(-b+sgnD*sqrt(b*b-4*a*c))/(2*a);
yD=sqrt(BD*BD - pow(xD+Bx,2));
echo("D",xD,yD,"CD err",sqrt(pow(xC-xD,2)+pow(yC-yD,2))-CD);

hipRot = atan2(yD,Bx+xD)-atan2(DEperp,DEleft);
echo("hipRot",hipRot);
xE = cos(hipRot) * (DEleft-DE) - sin(hipRot) * DEperp - Bx;
yE = sin(hipRot) * (DEleft-DE) + cos(hipRot) * DEperp;
/*
ke1=(yD*yD + xD*xD + DE*DE + BE*BE)/(2*yD);
ke2=(xD+Bx)/yD;
ae=2+ke2*ke2;
be=2*(Bx-ke1*ke2);
ce=ke1*ke1 - BE*BE +Bx*Bx;
echo("E abc:",ae,be,ce);
xE=(-be+sqrt(be*be-4*ae*ce))/(2*ae);
yE=sqrt(BE*BE - pow(xE+Bx,2));
*/
echo("E",xE,yE);

k1h=(xC*xC + yC*yC + BH*BH - CH*CH - Bx*Bx)/(2*yC);
k2h=-(xC+Bx)/yC;
ah=k2h*k2h+1;
bh=2*(k1h*k2h + Bx);
ch=k1h*k1h + Bx*Bx - BH*BH;
sgnH=(yC>0)?1:-1;
xH=(-bh+sgnH*sqrt(bh*bh-4*ah*ch))/(2*ah);
yH=-sqrt(BH*BH - pow(xH+Bx,2));
bhRot=atan2(yH,xH+Bx);
echo("H",xH,yH,"rot",bhRot,"CH err",sqrt(pow(xH-xC,2)+pow(yH-yC,2))-CH);

/*
k1f=(FH*FH - EF*EF - yE*yE - yH*yH + xE*xE - xH*xH) / (2*(yE-yH));
k2f=(xH-xE)/(yE-yH);
af=k2f*k2f+1;
bf=2*(k1f*k2f - xH - k2f*yH);
cf=xH*xH + yH*yH - 2*k1f*yH + k1f*k1f - FH*FH;
xF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
yF=k1f+k2f*xF;
*/
k2f = (yE-yH)/(xE-xH);
k1f = triK1(xE,yE,EF,xH,yH,FH);
af=k2f*k2f+1;
bf=2*(k2f*xE - k1f*k2f -yE);
cf=k1f*k1f - 2*k1f*xE + xE*xE + yE*yE - EF*EF;
yF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
xF=k1f-k2f*yF;
echo("F",xF,yF,"EF err",sqrt(pow(xF-xE,2)+pow(yF-yE,2))-EF);
echo("FH err",sqrt(pow(xF-xH,2)+pow(yF-yH,2))-FH);

// draw the hip so that the main "plane", the ED centerline plane, is at z=0
translate([-Bx,0,0]) rotate([0,0,hipRot])
    translate([DEleft-DE,DEperp,0]) hip();
//translate([-Bx,0,2.5]) rotate([0,0,12.5]) translate([-DEleft,DEperp,0]) hip();
//translate([ Bx,0,0]) rotate([0,0,-20]) translate([DE-DEleft,DEperp,0]) mirror([1,0,0])
//  hip();
checkLink(-Bx,0,xD,yD,BD);
checkLink(-Bx,0,xE,yE,BE);
checkLink(xD,yD,xE,yE,DE);

translate([-Bx,0,0]) rotate([0,0,bhRot])
   BHlinks();
checkLink(-Bx,0,xH,yH,BH);

//------------------------------------------------------- CrankLinks
translate([xC,yC,linkOffset-.6]) rotate([0,0,atan2(yD-yC,xD-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CD);
checkLink(xC,yC,xD,yD,CD);

translate([xC,yC,linkOffset+2]) rotate([0,0,atan2(yH-yC,xH-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CH);
checkLink(xC,yC,xH,yH,CH);

translate([xF,yF,0]) rotate([0,0,atan2(yE-yF,xE-xF)]) EFlink();
checkLink(xE,yE,xF,yF,EF);

footRot = atan2(yH-yF,xH-xF)-atan2(FGperp,FGleft);
translate([xF,yF,0]) rotate([0,0,footRot])
   foot();
checkLink(xF,yF,xH,yH,FH);

} // end module legAssembly()

// include includes whole text.
// use just imports modules
use <util.scad>

// -----------------------------------------------------------------

module foot() {
  hull() {  // FG
    translate([4,0,.2]) cube([4,2.5,2.5],center=true);
    translate([FG-1.3,0,.2]) cylinder(r=1.3,h=2.6,$fn=24,center=true);
  }

  // knee braces/fork
  for (z=[-1.3,7]) rotate([0,0,(z>0)?25*0:0]) difference() {
    hull() {
      // This was elongated as a brace for knee
      //translate([-5,2,1.5*z])scale([3,5,1])cylinder(r=1,h=.4,$fn=64,center=true);
      // wider knee shouldn't need brace
      translate([0,0,z]) cylinder(r=2.5,h=.4,$fn=24,center=true);
      translate([9,0,z])cylinder(r=1,h=.4,center=true);
    }
    cylinder(r=.4,h=22,$fn=17,center=true);
  }

  // hinge holders at H
  %color([0,0,.6,.4])
  translate([FGleft,FGperp,-1]) difference() {
    cylinder(r=2.54/2,h=7,$fn=36);

    cylinder(r=1.9/2,h=22,center=true,$fn=24);
    translate([0,0,3.6])cube([3,3,2.8],center=true);
  }
  translate([FGleft,FGperp,-.87]) {
    rotate([180,0,0]) F698();
    translate([0,0,5.0]) rotate([180,0,0]) F698();
    translate([0,0,1.95]) F698();
    translate([0,0,6.75]) F698();
  }

  // vertical brace extension at knee
  translate([3.5,0,4.1]) cube([2.6,2.6,5.3],center=true);
  hull() {  // gusset
    translate([ 5.5,-1,1]) cylinder(r=.2,h=5.8,$fn=8);
    translate([18, 1,0]) cylinder(r=.3,h=1  ,$fn=8);
  }

  // FH segment bracing
  for (z=[-.3,5.1]) hull() {
    translate([   3    ,   1    ,z]) barEnd1();
    translate([FGleft-1,FGperp-1,z]) barEnd1();
  }
  hull() {  // dig brace.  Could be gusset?
      translate([3,1,5.7]) barEnd1();
      translate([12,11,-.3]) barEnd1();
  }
  translate([FGleft-2,FGperp-2,.3]) cylinder(r=.8,h=5,$fn=11);
  hull() {
      translate([FGleft-7.2,FGperp-8,5.3]) barEnd1();
      translate([14,13.5,-.3]) barEnd1();
  }

  // GH braces
  hull() {
      translate([FG-8,0,-.3]) barEnd1();
      translate([FGleft+1,FGperp-1,-.3]) barEnd1();
  }
  hull() {
      translate([FG-10,0,0]) barEnd1();
      translate([FGleft+1,FGperp-1,5.2]) barEnd1();
  }

  hull() {    // perp brace
      translate([FGleft,FGperp-1,5.2]) barEnd1();
      translate([FGleft,0,0]) barEnd1();
  }
  hull() {    // perp brace
      translate([FGleft,FGperp-1,-.3]) barEnd1();
      translate([FGleft,0,-.3]) barEnd1();
  }

  // extra truss braces
  hull() {
      translate([46,15,3]) barEnd1();
      translate([35, 0,0]) barEnd1();
  }
  translate([FGleft+2,FGperp-2,.3]) cylinder(r=.6,h=5);
  translate([FGleft,FGperp-2,.3]) cylinder(r=.6,h=5);
}

$fn=12;
module hip() {
  translate([DE/2,0,-.2]) rotate([0,90,0])      // top tube
    cylinder(r=.9,h=DE-4,$fn=17,center=true);

  translate([DE-DEleft,-DEperp,-1.2]) difference() {
     union() {
       cylinder(r=2.54*1.75/2,h=7.2,$fn=36);                // axle

       hull() {  // diag tubes
         translate([-1.6,1.4,1.2]) barEnd1();
         translate([DEleft-DE+2,DEperp,1.2]) barEnd1();
       }
       hull() {
         translate([0,0,1.2]) barEnd1();
         translate([DE-DEleft-1,DEperp,1.2]) barEnd1();
       }

       // extra brace
       translate([0,0,6.2]) rotate([-105,0,0]) cylinder(r=.8,h=20);
     }

     // bore out for 6805 bearing
     cylinder(r=3.7/2+.1,h=22,$fn=18,center=true);
  }

  // use cut-out square tube (or channel) for forks, instead of all welded.
  // easier to drill and maintain aligned holes
  // 14ga roughly 2mm thick
  translate([DE,0,0]) rotate([0,0,180]) channelFork();
  channelFork();

  // extra bracing
  translate([DE/2,-15,0]) rotate([0,90,0]) cylinder(r=.8,h=35,center=true);
}

// cut-out square tube (or channel) for forks
//     easier to drill and maintain aligned holes
module channelFork(od=2.54*1.24,gu=.2,len=3,hd=.82,co=.5)
translate([co,0,0]) difference() {
  cube([od     ,len  ,od     ],center=true);
  cube([od-2*gu,len+1,od-2*gu],center=true);

  // open one side of square tube to make a channel
  translate([-od/2,0,0]) cube([2.1*gu,len+1,od-2*gu-.05],center=true);

  // put hole at x=0,y=0 in part space.
  translate([-co,0,0]) cylinder(r=hd/2,h=od+1,$fn=17,center=true);
}

/*
module eFork() for(z=[-1,1]) difference() {
  hull() {
    translate([0,0,1.4*z]) cylinder(r=2,h=.3,$fn=24,center=true);
    translate([6,0,1.4*z]) cube([1,2,.3],center=true);
  }
  cylinder(r=.4,h=11,$fn=17,center=true);
}
*/

module crankLink(dx=CD) {
  %color([0,0,.6,.4]) difference() {
    cylinder(r=2.54/2,h=.9,$fn=36,center=true);
    cylinder(r=2.54/2-.17,h=2,$fn=24,center=true);
  }
  translate([0,0, .31]) F698(); //cylinder(r=1.4,h=.7,$fn=24,center=true);
  translate([0,0,-.31]) rotate([180,0,0]) F698();

  //translate([dx/2-1,0,0]) cube([dx-3,1.3,1.3],center=true);
  %color([0,.8,0,.6])
  translate([dx/2-1,0,0]) rotate([0,90,0])
     cylinder(r=.6,h=dx-3,$fn=11,center=true);

  translate([dx,0,0]) SA8();
}

module EFlink() {
  translate([EF,0,0]) SA8();
  translate([EF/2-.4,0,0]) rotate([0,90,0])
      cylinder(r=.8,h=EF-3,$fn=13,center=true);

    // ------ tube and knee bearings
    %color([0,0,.6,.4])
    translate([0,0,-.84]) difference() {
       cylinder(r=2.54/2,h=2.54*3-.25,$fn=36);
       cylinder(r=2.54/2-.3,h=22,$fn=36,center=true);
    }
    translate([0,0,6.41]) F698();
    translate([0,0,-.7]) rotate([180,0,0]) F698();

    hull() {  // gusset
      translate([1.3,0,2*2.54/2]) cylinder(r=.2,h=2.54*3,$fn=12,center=true);
      translate([9,0,   0    ]) cylinder(r=.2,h=1,$fn=12);
    }

  //translate([EF,0,0]) cylinder(r=r38,h=5,center=true);
    //                //cylinder(r=r38,h=55,center=true);
  //cylinder(r=1.2,h=22,$fn=36,center=true);
}

// this link drawn with B axle at origin, always.
module BHlinks() {
  difference() {  // main axle rings
    union() {
      // main axle tube
      translate([0,0,2.4]) cylinder(r=2.54*1.75/2,h=13.5,$fn=36,center=true);

      for(z=[-2.4,7.2]) {  // main side rails
        hull() {
          translate([BH-6,0,z]) barEnd1();
          translate([   0,0,z]) barEnd1();
        }
      }

    }

    translate([0,0,2.4]) cube([5,5,7.9],center=true);
    cylinder(r=3.7/2+.1,h=22,$fn=19,center=true);
  }

  // brace near axle
  translate([3.3,0,2.2]) cylinder(r=.8,h=10,$fn=19,center=true);

/* get rid of fork brace.  Comes close to hitting CH cranklink.
   let cross members hold forks apart
  //    fork brace
  translate([BH-7,0,2.43]) cube([2.5,2.5,7.6],center=true);

  hull() {
    translate([   4,.7,-1.6]) barEnd1();
    translate([BH-9,.7, 6.2]) barEnd1();
  }
  hull() {
    translate([   4,-.7, 6.2]) barEnd1();
    translate([BH-9,-.7,-1.6]) barEnd1();
  }
*/

  BHcrosses();

  // H forks
  for(z=[-1.7,6.2]) translate([BH,0,z]) difference() {
     hull() {
       cylinder(r=3,h=.33,$fn=36);
       translate([-8,0,0]) cylinder(r=1,h=.33);
     }
     cylinder(r=.7,h=2,center=true);
  }

  // to check dimensions
  //%translate([BH/2,0,2.4]) cube([BH,1,7.8],center=true);
}
module barEnd1() sphere(.8,$fn=12);
// diag braces.  Try to leave fork area open to allow clearance for CH link
module BHcrosses() {
h1=BH-4;  // node closest to H
h2=h1-19;
b2=h2-4;
b1=4;
spread=.7;
lo=-1.6;
hi=6.5;
rBar=.8;
  hull() {
    translate([h2, spread,lo]) barEnd1();
    translate([h1, spread,hi]) barEnd1();
  }
  hull() {
    translate([h2,-spread,hi]) barEnd1();
    translate([h1,-spread,lo]) barEnd1();
  }
  hull() {
    translate([b1,-spread,lo]) barEnd1();
    translate([b2,-spread,hi]) barEnd1();
  }
  hull() {
    translate([b2,spread,lo]) barEnd1();
    translate([b1,spread,hi]) barEnd1();
  }
}

// try to draw Jansen linkage leg assembly as it might appear in steel

// these are for configuration "E" as referenced in other drawings
AC=17.5;
Ay =  3.318; Bx = 53.833;
BD = 48.020; BE = 46.977; BH = 40.359;
CD = 59.635; CH = 71.441; DE = 66.437;
EF = 47.467; FG = 75.792;
FH = 40.843; GH = 55.790;

DEleft = (DE*DE + BD*BD - BE*BE)/(2*DE);
FGleft = (FG*FG + FH*FH - GH*GH)/(2*FG);
DEperp = sqrt(BD*BD - DEleft*DEleft);
FGperp = sqrt(FH*FH - FGleft*FGleft);

echo(str("DEleft=",DEleft,"   DEperp=",DEperp));
echo(str("FGleft=",FGleft,"   FGperp=",FGperp));

//r38 = (3/8)*2.54/2;  // radius of 3/8" bolt

a=360*$t;
legAssembly(a,0);
mirror([1,0,0]) legAssembly(180-a,1.3);

//  -------------------------- crank-arm circle reference
%color([1,.5,.3,.4]) translate([0,Ay,-2]) difference() {
  cylinder(r=AC,h=1,$fn=48,center=true);
  cylinder(r=2,h=2,center=true);
}
color([0.3,.3,1,.7]) // axles
for(x=[-1,1]) translate([x*Bx,0,0]) difference() {
   cylinder(r=2.54/2,h=20,$fn=24,center=true);
   cylinder(r=2.54/2-.4,h=22,$fn=19,center=true);
}

%translate([0,-93,0]) cube([200,2,2],center=true); // ground

// -----------------------------------------------------------------

// plot a link shadow, a different way, to check kinematic correctness
module checkLink(xa,ya,xb,yb,ab) {
  *translate([(xa+xb)/2,(ya+yb)/2,-9])
    rotate([0,0,atan2(yb-ya,xb-xa)]) cube([ab,1,1],center=true);
}

function triK1(ax,ay,ca,bx,by,cb) = (cb*cb - ca*ca + ax*ax -bx*bx +ay*ay -by*by)/(2*(ax-bx));

// ===================================================================

module legAssembly(ang=0,linkOffset=0) {

// solve kinematics for given crank angle
xC = AC*cos(ang);
yC = AC*sin(ang)+Ay;
echo("C",xC,yC);

k1=(yC*yC - Bx*Bx + BD*BD - CD*CD + xC*xC)/(2*yC);
k2=(xC+Bx)/yC;
c=k1*k1-BD*BD+Bx*Bx;
b=2*(Bx-k1*k2);
a=k2*k2+1;
sgnD=(yC<0)?1:-1;
xD=(-b+sgnD*sqrt(b*b-4*a*c))/(2*a);
yD=sqrt(BD*BD - pow(xD+Bx,2));
echo("D",xD,yD,"CD err",sqrt(pow(xC-xD,2)+pow(yC-yD,2))-CD);

hipRot = atan2(yD,Bx+xD)-atan2(DEperp,DEleft);
echo("hipRot",hipRot);
xE = cos(hipRot) * (DEleft-DE) - sin(hipRot) * DEperp - Bx;
yE = sin(hipRot) * (DEleft-DE) + cos(hipRot) * DEperp;
/*
ke1=(yD*yD + xD*xD + DE*DE + BE*BE)/(2*yD);
ke2=(xD+Bx)/yD;
ae=2+ke2*ke2;
be=2*(Bx-ke1*ke2);
ce=ke1*ke1 - BE*BE +Bx*Bx;
echo("E abc:",ae,be,ce);
xE=(-be+sqrt(be*be-4*ae*ce))/(2*ae);
yE=sqrt(BE*BE - pow(xE+Bx,2));
*/
echo("E",xE,yE);

k1h=(xC*xC + yC*yC + BH*BH - CH*CH - Bx*Bx)/(2*yC);
k2h=-(xC+Bx)/yC;
ah=k2h*k2h+1;
bh=2*(k1h*k2h + Bx);
ch=k1h*k1h + Bx*Bx - BH*BH;
sgnH=(yC>0)?1:-1;
xH=(-bh+sgnH*sqrt(bh*bh-4*ah*ch))/(2*ah);
yH=-sqrt(BH*BH - pow(xH+Bx,2));
bhRot=atan2(yH,xH+Bx);
echo("H",xH,yH,"rot",bhRot,"CH err",sqrt(pow(xH-xC,2)+pow(yH-yC,2))-CH);

/*
k1f=(FH*FH - EF*EF - yE*yE - yH*yH + xE*xE - xH*xH) / (2*(yE-yH));
k2f=(xH-xE)/(yE-yH);
af=k2f*k2f+1;
bf=2*(k1f*k2f - xH - k2f*yH);
cf=xH*xH + yH*yH - 2*k1f*yH + k1f*k1f - FH*FH;
xF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
yF=k1f+k2f*xF;
*/
k2f = (yE-yH)/(xE-xH);
k1f = triK1(xE,yE,EF,xH,yH,FH);
af=k2f*k2f+1;
bf=2*(k2f*xE - k1f*k2f -yE);
cf=k1f*k1f - 2*k1f*xE + xE*xE + yE*yE - EF*EF;
yF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
xF=k1f-k2f*yF;
echo("F",xF,yF,"EF err",sqrt(pow(xF-xE,2)+pow(yF-yE,2))-EF);
echo("FH err",sqrt(pow(xF-xH,2)+pow(yF-yH,2))-FH);

// draw the hip so that the main "plane", the ED centerline plane, is at z=0
translate([-Bx,0,0]) rotate([0,0,hipRot])
    translate([DEleft-DE,DEperp,0]) hip();
//translate([-Bx,0,2.5]) rotate([0,0,12.5]) translate([-DEleft,DEperp,0]) hip();
//translate([ Bx,0,0]) rotate([0,0,-20]) translate([DE-DEleft,DEperp,0]) mirror([1,0,0])
//  hip();
checkLink(-Bx,0,xD,yD,BD);
checkLink(-Bx,0,xE,yE,BE);
checkLink(xD,yD,xE,yE,DE);

translate([-Bx,0,0]) rotate([0,0,bhRot])
   BHlinks();
checkLink(-Bx,0,xH,yH,BH);

//------------------------------------------------------- CrankLinks
translate([xC,yC,linkOffset-.6]) rotate([0,0,atan2(yD-yC,xD-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CD);
checkLink(xC,yC,xD,yD,CD);

translate([xC,yC,linkOffset+2]) rotate([0,0,atan2(yH-yC,xH-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CH);
checkLink(xC,yC,xH,yH,CH);

translate([xF,yF,0]) rotate([0,0,atan2(yE-yF,xE-xF)]) EFlink();
checkLink(xE,yE,xF,yF,EF);

footRot = atan2(yH-yF,xH-xF)-atan2(FGperp,FGleft);
translate([xF,yF,0]) rotate([0,0,footRot])
   foot();
checkLink(xF,yF,xH,yH,FH);

} // end module legAssembly()

// include includes whole text.
// use just imports modules
use <util.scad>

// -----------------------------------------------------------------

module foot() {
  hull() {  // FG
    translate([4,0,.2]) cube([4,2.5,2.5],center=true);
    translate([FG-1.3,0,.2]) cylinder(r=1.3,h=2.6,$fn=24,center=true);
  }

  // knee braces/fork
  for (z=[-1.3,7]) rotate([0,0,(z>0)?25*0:0]) difference() {
    hull() {
      // This was elongated as a brace for knee
      //translate([-5,2,1.5*z])scale([3,5,1])cylinder(r=1,h=.4,$fn=64,center=true);
      // wider knee shouldn't need brace
      translate([0,0,z]) cylinder(r=2.5,h=.4,$fn=24,center=true);
      translate([9,0,z])cylinder(r=1,h=.4,center=true);
    }
    cylinder(r=.4,h=22,$fn=17,center=true);
  }

  // hinge holders at H
  %color([0,0,.6,.4])
  translate([FGleft,FGperp,-1]) difference() {
    cylinder(r=2.54/2,h=7,$fn=36);

    cylinder(r=1.9/2,h=22,center=true,$fn=24);
    translate([0,0,3.6])cube([3,3,2.8],center=true);
  }
  translate([FGleft,FGperp,-.87]) {
    rotate([180,0,0]) F698();
    translate([0,0,5.0]) rotate([180,0,0]) F698();
    translate([0,0,1.95]) F698();
    translate([0,0,6.75]) F698();
  }

  // vertical brace extension at knee
  translate([3.5,0,4.1]) cube([2.6,2.6,5.3],center=true);
  hull() {  // gusset
    translate([ 5.5,-1,1]) cylinder(r=.2,h=5.8,$fn=8);
    translate([18, 1,0]) cylinder(r=.3,h=1  ,$fn=8);
  }

  // FH segment bracing
  for (z=[-.3,5.1]) hull() {
    translate([   3    ,   1    ,z]) barEnd1();
    translate([FGleft-1,FGperp-1,z]) barEnd1();
  }
  hull() {  // dig brace.  Could be gusset?
      translate([3,1,5.7]) barEnd1();
      translate([12,11,-.3]) barEnd1();
  }
  translate([FGleft-2,FGperp-2,.3]) cylinder(r=.8,h=5,$fn=11);
  hull() {
      translate([FGleft-7.2,FGperp-8,5.3]) barEnd1();
      translate([14,13.5,-.3]) barEnd1();
  }

  // GH braces
  hull() {
      translate([FG-8,0,-.3]) barEnd1();
      translate([FGleft+1,FGperp-1,-.3]) barEnd1();
  }
  hull() {
      translate([FG-10,0,0]) barEnd1();
      translate([FGleft+1,FGperp-1,5.2]) barEnd1();
  }

  hull() {    // perp brace
      translate([FGleft,FGperp-1,5.2]) barEnd1();
      translate([FGleft,0,0]) barEnd1();
  }
  hull() {    // perp brace
      translate([FGleft,FGperp-1,-.3]) barEnd1();
      translate([FGleft,0,-.3]) barEnd1();
  }

  // extra truss braces
  hull() {
      translate([46,15,3]) barEnd1();
      translate([35, 0,0]) barEnd1();
  }
  translate([FGleft+2,FGperp-2,.3]) cylinder(r=.6,h=5);
  translate([FGleft,FGperp-2,.3]) cylinder(r=.6,h=5);
}

$fn=12;
module hip() {
  translate([DE/2,0,-.2]) rotate([0,90,0])      // top tube
    cylinder(r=.9,h=DE-4,$fn=17,center=true);

  translate([DE-DEleft,-DEperp,-1.2]) difference() {
     cylinder(r=2.54*1.5/2,h=7.2,$fn=36);                // axle
     cylinder(r=2.54*1.5/2-.3,h=22,$fn=18,center=true);
  }

  // use cut-out square tube (or channel) for forks, instead of all welded.
  // easier to drill and maintain aligned holes
  // 14ga roughly 2mm thick
  translate([DE,0,0]) rotate([0,0,180]) channelFork();
  channelFork();

  hull() {  // diag tubes
    translate([DE-DEleft,-DEperp,0]) barEnd1();
    translate([2,0,0]) barEnd1();
  }
  hull() {
    translate([DE-DEleft,-DEperp,0]) barEnd1();
    translate([DE-2,0,0]) barEnd1();
  }

  // extra bracing
  translate([DE/2,-15,0]) rotate([0,90,0]) cylinder(r=.8,h=35,center=true);
  translate([DE-DEleft,-DEperp,5]) rotate([-105,0,0]) cylinder(r=.8,h=20);
}

// cut-out square tube (or channel) for forks
//     easier to drill and maintain aligned holes
module channelFork(od=2.54*1.24,gu=.2,len=3,hd=.82,co=.5)
translate([co,0,0]) difference() {
  cube([od     ,len  ,od     ],center=true);
  cube([od-2*gu,len+1,od-2*gu],center=true);

  // open one side of square tube to make a channel
  translate([-od/2,0,0]) cube([2.1*gu,len+1,od-2*gu-.05],center=true);

  // put hole at x=0,y=0 in part space.
  translate([-co,0,0]) cylinder(r=hd/2,h=od+1,$fn=17,center=true);
}

/*
module eFork() for(z=[-1,1]) difference() {
  hull() {
    translate([0,0,1.4*z]) cylinder(r=2,h=.3,$fn=24,center=true);
    translate([6,0,1.4*z]) cube([1,2,.3],center=true);
  }
  cylinder(r=.4,h=11,$fn=17,center=true);
}
*/

module crankLink(dx=CD) {
  %color([0,0,.6,.4]) difference() {
    cylinder(r=2.54/2,h=.9,$fn=36,center=true);
    cylinder(r=2.54/2-.17,h=2,$fn=24,center=true);
  }
  translate([0,0, .31]) F698(); //cylinder(r=1.4,h=.7,$fn=24,center=true);
  translate([0,0,-.31]) rotate([180,0,0]) F698();

  //translate([dx/2-1,0,0]) cube([dx-3,1.3,1.3],center=true);
  %color([0,.8,0,.6])
  translate([dx/2-1,0,0]) rotate([0,90,0])
     cylinder(r=.6,h=dx-3,$fn=11,center=true);

  translate([dx,0,0]) SA8();
}

module EFlink() {
  translate([EF,0,0]) SA8();
  translate([EF/2-.4,0,0]) rotate([0,90,0])
      cylinder(r=.8,h=EF-3,$fn=13,center=true);

    // ------ tube and knee bearings
    %color([0,0,.6,.4])
    translate([0,0,-.84]) difference() {
       cylinder(r=2.54/2,h=2.54*3-.25,$fn=36);
       cylinder(r=2.54/2-.3,h=22,$fn=36,center=true);
    }
    translate([0,0,6.41]) F698();
    translate([0,0,-.7]) rotate([180,0,0]) F698();

    hull() {  // gusset
      translate([1.3,0,2*2.54/2]) cylinder(r=.2,h=2.54*3,$fn=12,center=true);
      translate([9,0,   0    ]) cylinder(r=.2,h=1,$fn=12);
    }

  //translate([EF,0,0]) cylinder(r=r38,h=5,center=true);
    //                //cylinder(r=r38,h=55,center=true);
  //cylinder(r=1.2,h=22,$fn=36,center=true);
}

// this link drawn with B axle at origin, always.
module BHlinks() {
  difference() {  // main axle rings
    translate([0,0,2.4]) cylinder(r=2.54*1.5/2,h=13.5,$fn=36,center=true);
    translate([0,0,2.4]) cube([5,5,7.9],center=true);
    cylinder(r=2.54*1.5/2-.3,h=22,$fn=19,center=true);
  }

  for(z=[-2.4,7.2]) {  // main side rails
     hull() {
       translate([BH-6,0,z]) barEnd1();
       translate([   0,0,z]) barEnd1();
     }
  }

  // brace near axle
  translate([3,0,2.2]) cylinder(r=.8,h=10,$fn=19,center=true);

/* get rid of fork brace.  Comes close to hitting CH cranklink.
   let cross members hold forks apart
  //    fork brace
  translate([BH-7,0,2.43]) cube([2.5,2.5,7.6],center=true);

  hull() {
    translate([   4,.7,-1.6]) barEnd1();
    translate([BH-9,.7, 6.2]) barEnd1();
  }
  hull() {
    translate([   4,-.7, 6.2]) barEnd1();
    translate([BH-9,-.7,-1.6]) barEnd1();
  }
*/

  BHcrosses();

  // H forks
  for(z=[-1.7,6.2]) translate([BH,0,z]) difference() {
     hull() {
       cylinder(r=3,h=.33,$fn=36);
       translate([-8,0,0]) cylinder(r=1,h=.33);
     }
     cylinder(r=.7,h=2,center=true);
  }

  // to check dimensions
  //%translate([BH/2,0,2.4]) cube([BH,1,7.8],center=true);
}
module barEnd1() sphere(.8,$fn=12);
// diag braces.  Try to leave fork area open to allow clearance for CH link
module BHcrosses() {
h1=BH-4;  // node closest to H
h2=h1-19;
b2=h2-4;
b1=4;
spread=.7;
lo=-1.6;
hi=6.5;
rBar=.8;
  hull() {
    translate([h2, spread,lo]) barEnd1();
    translate([h1, spread,hi]) barEnd1();
  }
  hull() {
    translate([h2,-spread,hi]) barEnd1();
    translate([h1,-spread,lo]) barEnd1();
  }
  hull() {
    translate([b1,-spread,lo]) barEnd1();
    translate([b2,-spread,hi]) barEnd1();
  }
  hull() {
    translate([b2,spread,lo]) barEnd1();
    translate([b1,spread,hi]) barEnd1();
  }
}


move to channelFork on hip

move to channelFork on hip

// try to draw Jansen linkage leg assembly as it might appear in steel

// these are for configuration "E" as referenced in other drawings
AC=17.5;
Ay =  3.318; Bx = 53.833;
BD = 48.020; BE = 46.977; BH = 40.359;
CD = 59.635; CH = 71.441; DE = 66.437;
EF = 47.467; FG = 75.792;
FH = 40.843; GH = 55.790;

DEleft = (DE*DE + BD*BD - BE*BE)/(2*DE);
FGleft = (FG*FG + FH*FH - GH*GH)/(2*FG);
DEperp = sqrt(BD*BD - DEleft*DEleft);
FGperp = sqrt(FH*FH - FGleft*FGleft);

echo(str("DEleft=",DEleft,"   DEperp=",DEperp));
echo(str("FGleft=",FGleft,"   FGperp=",FGperp));

//r38 = (3/8)*2.54/2;  // radius of 3/8" bolt

a=360*$t;
legAssembly(a,0);
mirror([1,0,0]) legAssembly(180-a,1.3);

//  -------------------------- crank-arm circle reference
%color([1,.5,.3,.4]) translate([0,Ay,-2]) difference() {
  cylinder(r=AC,h=1,$fn=48,center=true);
  cylinder(r=2,h=2,center=true);
}
color([0.3,.3,1,.7]) // axles
for(x=[-1,1]) translate([x*Bx,0,0]) difference() {
   cylinder(r=2.54/2,h=20,$fn=24,center=true);
   cylinder(r=2.54/2-.4,h=22,$fn=19,center=true);
}

%translate([0,-93,0]) cube([200,2,2],center=true); // ground

// -----------------------------------------------------------------

// plot a link shadow, a different way, to check kinematic correctness
module checkLink(xa,ya,xb,yb,ab) {
  *translate([(xa+xb)/2,(ya+yb)/2,-9])
    rotate([0,0,atan2(yb-ya,xb-xa)]) cube([ab,1,1],center=true);
}

function triK1(ax,ay,ca,bx,by,cb) = (cb*cb - ca*ca + ax*ax -bx*bx +ay*ay -by*by)/(2*(ax-bx));

// ===================================================================

module legAssembly(ang=0,linkOffset=0) {

// solve kinematics for given crank angle
xC = AC*cos(ang);
yC = AC*sin(ang)+Ay;
echo("C",xC,yC);

k1=(yC*yC - Bx*Bx + BD*BD - CD*CD + xC*xC)/(2*yC);
k2=(xC+Bx)/yC;
c=k1*k1-BD*BD+Bx*Bx;
b=2*(Bx-k1*k2);
a=k2*k2+1;
sgnD=(yC<0)?1:-1;
xD=(-b+sgnD*sqrt(b*b-4*a*c))/(2*a);
yD=sqrt(BD*BD - pow(xD+Bx,2));
echo("D",xD,yD,"CD err",sqrt(pow(xC-xD,2)+pow(yC-yD,2))-CD);

hipRot = atan2(yD,Bx+xD)-atan2(DEperp,DEleft);
echo("hipRot",hipRot);
xE = cos(hipRot) * (DEleft-DE) - sin(hipRot) * DEperp - Bx;
yE = sin(hipRot) * (DEleft-DE) + cos(hipRot) * DEperp;
/*
ke1=(yD*yD + xD*xD + DE*DE + BE*BE)/(2*yD);
ke2=(xD+Bx)/yD;
ae=2+ke2*ke2;
be=2*(Bx-ke1*ke2);
ce=ke1*ke1 - BE*BE +Bx*Bx;
echo("E abc:",ae,be,ce);
xE=(-be+sqrt(be*be-4*ae*ce))/(2*ae);
yE=sqrt(BE*BE - pow(xE+Bx,2));
*/
echo("E",xE,yE);

k1h=(xC*xC + yC*yC + BH*BH - CH*CH - Bx*Bx)/(2*yC);
k2h=-(xC+Bx)/yC;
ah=k2h*k2h+1;
bh=2*(k1h*k2h + Bx);
ch=k1h*k1h + Bx*Bx - BH*BH;
sgnH=(yC>0)?1:-1;
xH=(-bh+sgnH*sqrt(bh*bh-4*ah*ch))/(2*ah);
yH=-sqrt(BH*BH - pow(xH+Bx,2));
bhRot=atan2(yH,xH+Bx);
echo("H",xH,yH,"rot",bhRot,"CH err",sqrt(pow(xH-xC,2)+pow(yH-yC,2))-CH);

/*
k1f=(FH*FH - EF*EF - yE*yE - yH*yH + xE*xE - xH*xH) / (2*(yE-yH));
k2f=(xH-xE)/(yE-yH);
af=k2f*k2f+1;
bf=2*(k1f*k2f - xH - k2f*yH);
cf=xH*xH + yH*yH - 2*k1f*yH + k1f*k1f - FH*FH;
xF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
yF=k1f+k2f*xF;
*/
k2f = (yE-yH)/(xE-xH);
k1f = triK1(xE,yE,EF,xH,yH,FH);
af=k2f*k2f+1;
bf=2*(k2f*xE - k1f*k2f -yE);
cf=k1f*k1f - 2*k1f*xE + xE*xE + yE*yE - EF*EF;
yF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
xF=k1f-k2f*yF;
echo("F",xF,yF,"EF err",sqrt(pow(xF-xE,2)+pow(yF-yE,2))-EF);
echo("FH err",sqrt(pow(xF-xH,2)+pow(yF-yH,2))-FH);

// draw the hip so that the main "plane", the ED centerline plane, is at z=0
translate([-Bx,0,0]) rotate([0,0,hipRot])
    translate([DEleft-DE,DEperp,0]) hip();
//translate([-Bx,0,2.5]) rotate([0,0,12.5]) translate([-DEleft,DEperp,0]) hip();
//translate([ Bx,0,0]) rotate([0,0,-20]) translate([DE-DEleft,DEperp,0]) mirror([1,0,0])
//  hip();
checkLink(-Bx,0,xD,yD,BD);
checkLink(-Bx,0,xE,yE,BE);
checkLink(xD,yD,xE,yE,DE);

translate([-Bx,0,0]) rotate([0,0,bhRot])
   BHlinks();
checkLink(-Bx,0,xH,yH,BH);

//------------------------------------------------------- CrankLinks
translate([xC,yC,linkOffset-.6]) rotate([0,0,atan2(yD-yC,xD-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CD);
checkLink(xC,yC,xD,yD,CD);

translate([xC,yC,linkOffset+2]) rotate([0,0,atan2(yH-yC,xH-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CH);
checkLink(xC,yC,xH,yH,CH);

translate([xF,yF,0]) rotate([0,0,atan2(yE-yF,xE-xF)]) EFlink();
checkLink(xE,yE,xF,yF,EF);

footRot = atan2(yH-yF,xH-xF)-atan2(FGperp,FGleft);
translate([xF,yF,0]) rotate([0,0,footRot])
   foot();
checkLink(xF,yF,xH,yH,FH);

} // end module legAssembly()

// include includes whole text.
// use just imports modules
use <util.scad>

// -----------------------------------------------------------------

module foot() {
  hull() {  // FG
    translate([4,0,.2]) cube([4,2.5,2.5],center=true);
    translate([FG-1.3,0,.2]) cylinder(r=1.3,h=2.6,$fn=24,center=true);
  }

  // knee braces/fork
  for (z=[-1.3,7]) rotate([0,0,(z>0)?25*0:0]) difference() {
    hull() {
      // This was elongated as a brace for knee
      //translate([-5,2,1.5*z])scale([3,5,1])cylinder(r=1,h=.4,$fn=64,center=true);
      // wider knee shouldn't need brace
      translate([0,0,z]) cylinder(r=2.5,h=.4,$fn=24,center=true);
      translate([9,0,z])cylinder(r=1,h=.4,center=true);
    }
    cylinder(r=.4,h=22,$fn=17,center=true);
  }

  // hinge holders at H
  %color([0,0,.6,.4])
  translate([FGleft,FGperp,-1]) difference() {
    cylinder(r=2.54/2,h=7,$fn=36);

    cylinder(r=1.9/2,h=22,center=true,$fn=24);
    translate([0,0,3.6])cube([3,3,2.8],center=true);
  }
  translate([FGleft,FGperp,-.87]) {
    rotate([180,0,0]) F698();
    translate([0,0,5.0]) rotate([180,0,0]) F698();
    translate([0,0,1.95]) F698();
    translate([0,0,6.75]) F698();
  }

  // vertical brace extension at knee
  translate([3.5,0,4.1]) cube([2.6,2.6,5.3],center=true);
  hull() {  // gusset
    translate([ 5.5,-1,1]) cylinder(r=.2,h=5.8,$fn=8);
    translate([18, 1,0]) cylinder(r=.3,h=1  ,$fn=8);
  }

  // FH segment bracing
  for (z=[-.3,5.1]) hull() {
    translate([   3    ,   1    ,z]) barEnd1();
    translate([FGleft-1,FGperp-1,z]) barEnd1();
  }
  hull() {  // dig brace.  Could be gusset?
      translate([3,1,5.7]) barEnd1();
      translate([12,11,-.3]) barEnd1();
  }
  translate([FGleft-2,FGperp-2,.3]) cylinder(r=.8,h=5,$fn=11);
  hull() {
      translate([FGleft-7.2,FGperp-8,5.3]) barEnd1();
      translate([14,13.5,-.3]) barEnd1();
  }

  // GH braces
  hull() {
      translate([FG-8,0,-.3]) barEnd1();
      translate([FGleft+1,FGperp-1,-.3]) barEnd1();
  }
  hull() {
      translate([FG-10,0,0]) barEnd1();
      translate([FGleft+1,FGperp-1,5.2]) barEnd1();
  }

  hull() {    // perp brace
      translate([FGleft,FGperp-1,5.2]) barEnd1();
      translate([FGleft,0,0]) barEnd1();
  }
  hull() {    // perp brace
      translate([FGleft,FGperp-1,-.3]) barEnd1();
      translate([FGleft,0,-.3]) barEnd1();
  }

  // extra truss braces
  hull() {
      translate([46,15,3]) barEnd1();
      translate([35, 0,0]) barEnd1();
  }
  translate([FGleft+2,FGperp-2,.3]) cylinder(r=.6,h=5);
  translate([FGleft,FGperp-2,.3]) cylinder(r=.6,h=5);
}

$fn=12;
module hip() {
  translate([DE/2,0,-.2]) rotate([0,90,0])      // top tube
    cylinder(r=.9,h=DE-4,$fn=17,center=true);

  translate([DE-DEleft,-DEperp,-1.2]) difference() {
     cylinder(r=2.54*1.5/2,h=7.2,$fn=36);                // axle
     cylinder(r=2.54*1.5/2-.3,h=22,$fn=18,center=true);
  }

  // use cut-out square tube (or channel) for forks, instead of all welded.
  // easier to drill and maintain aligned holes
  // 14ga roughly 2mm thick
  translate([DE,0,0]) rotate([0,0,180]) channelFork();
  channelFork();

  hull() {  // diag tubes
    translate([DE-DEleft,-DEperp,0]) barEnd1();
    translate([2,0,0]) barEnd1();
  }
  hull() {
    translate([DE-DEleft,-DEperp,0]) barEnd1();
    translate([DE-2,0,0]) barEnd1();
  }

  // extra bracing
  translate([DE/2,-15,0]) rotate([0,90,0]) cylinder(r=.8,h=35,center=true);
  translate([DE-DEleft,-DEperp,5]) rotate([-105,0,0]) cylinder(r=.8,h=20);
}

// cut-out square tube (or channel) for forks
//     easier to drill and maintain aligned holes
module channelFork(od=2.54*1.24,gu=.2,len=3,hd=.82,co=.5)
translate([co,0,0]) difference() {
  cube([od     ,len  ,od     ],center=true);
  cube([od-2*gu,len+1,od-2*gu],center=true);

  // open one side of square tube to make a channel
  translate([-od/2,0,0]) cube([2.1*gu,len+1,od-2*gu-.05],center=true);

  // put hole at x=0,y=0 in part space.
  translate([-co,0,0]) cylinder(r=hd/2,h=od+1,$fn=17,center=true);
}

/*
module eFork() for(z=[-1,1]) difference() {
  hull() {
    translate([0,0,1.4*z]) cylinder(r=2,h=.3,$fn=24,center=true);
    translate([6,0,1.4*z]) cube([1,2,.3],center=true);
  }
  cylinder(r=.4,h=11,$fn=17,center=true);
}
*/

module crankLink(dx=CD) {
  %color([0,0,.6,.4]) difference() {
    cylinder(r=2.54/2,h=.9,$fn=36,center=true);
    cylinder(r=2.54/2-.17,h=2,$fn=24,center=true);
  }
  translate([0,0, .31]) F698(); //cylinder(r=1.4,h=.7,$fn=24,center=true);
  translate([0,0,-.31]) rotate([180,0,0]) F698();

  //translate([dx/2-1,0,0]) cube([dx-3,1.3,1.3],center=true);
  %color([0,.8,0,.6])
  translate([dx/2-1,0,0]) rotate([0,90,0])
     cylinder(r=.6,h=dx-3,$fn=11,center=true);

  translate([dx,0,0]) SA8();
}

module EFlink() {
  translate([EF,0,0]) SA8();
  translate([EF/2-.4,0,0]) rotate([0,90,0])
      cylinder(r=.8,h=EF-3,$fn=13,center=true);

    // ------ tube and knee bearings
    %color([0,0,.6,.4])
    translate([0,0,-.84]) difference() {
       cylinder(r=2.54/2,h=2.54*3-.25,$fn=36);
       cylinder(r=2.54/2-.3,h=22,$fn=36,center=true);
    }
    translate([0,0,6.41]) F698();
    translate([0,0,-.7]) rotate([180,0,0]) F698();

    hull() {  // gusset
      translate([1.3,0,2*2.54/2]) cylinder(r=.2,h=2.54*3,$fn=12,center=true);
      translate([9,0,   0    ]) cylinder(r=.2,h=1,$fn=12);
    }

  //translate([EF,0,0]) cylinder(r=r38,h=5,center=true);
    //                //cylinder(r=r38,h=55,center=true);
  //cylinder(r=1.2,h=22,$fn=36,center=true);
}

// this link drawn with B axle at origin, always.
module BHlinks() {
  difference() {  // main axle rings
    translate([0,0,2.4]) cylinder(r=2.54*1.5/2,h=13.5,$fn=36,center=true);
    translate([0,0,2.4]) cube([5,5,7.9],center=true);
    cylinder(r=2.54*1.5/2-.3,h=22,$fn=19,center=true);
  }

  for(z=[-2.4,7.2]) {  // main side rails
     hull() {
       translate([BH-6,0,z]) barEnd1();
       translate([   0,0,z]) barEnd1();
     }
  }

  // brace near axle
  translate([3,0,2.2]) cylinder(r=.8,h=10,$fn=19,center=true);

/* get rid of fork brace.  Comes close to hitting CH cranklink.
   let cross members hold forks apart
  //    fork brace
  translate([BH-7,0,2.43]) cube([2.5,2.5,7.6],center=true);

  hull() {
    translate([   4,.7,-1.6]) barEnd1();
    translate([BH-9,.7, 6.2]) barEnd1();
  }
  hull() {
    translate([   4,-.7, 6.2]) barEnd1();
    translate([BH-9,-.7,-1.6]) barEnd1();
  }
*/

  BHcrosses();

  // H forks
  for(z=[-1.7,6.2]) translate([BH,0,z]) difference() {
     hull() {
       cylinder(r=3,h=.33,$fn=36);
       translate([-8,0,0]) cylinder(r=1,h=.33);
     }
     cylinder(r=.7,h=2,center=true);
  }

  // to check dimensions
  //%translate([BH/2,0,2.4]) cube([BH,1,7.8],center=true);
}
module barEnd1() sphere(.8,$fn=12);
// diag braces.  Try to leave fork area open to allow clearance for CH link
module BHcrosses() {
h1=BH-4;  // node closest to H
h2=h1-19;
b2=h2-4;
b1=4;
spread=.7;
lo=-1.6;
hi=6.5;
rBar=.8;
  hull() {
    translate([h2, spread,lo]) barEnd1();
    translate([h1, spread,hi]) barEnd1();
  }
  hull() {
    translate([h2,-spread,hi]) barEnd1();
    translate([h1,-spread,lo]) barEnd1();
  }
  hull() {
    translate([b1,-spread,lo]) barEnd1();
    translate([b2,-spread,hi]) barEnd1();
  }
  hull() {
    translate([b2,spread,lo]) barEnd1();
    translate([b1,spread,hi]) barEnd1();
  }
}

// try to draw Jansen linkage leg assembly as it might appear in steel

// these are for configuration "E" as referenced in other drawings
AC=17.5;
Ay =  3.318; Bx = 53.833;
BD = 48.020; BE = 46.977; BH = 40.359;
CD = 59.635; CH = 71.441; DE = 66.437;
EF = 47.467; FG = 75.792;
FH = 40.843; GH = 55.790;

DEleft = (DE*DE + BD*BD - BE*BE)/(2*DE);
FGleft = (FG*FG + FH*FH - GH*GH)/(2*FG);
DEperp = sqrt(BD*BD - DEleft*DEleft);
FGperp = sqrt(FH*FH - FGleft*FGleft);

echo(str("DEleft=",DEleft,"   DEperp=",DEperp));
echo(str("FGleft=",FGleft,"   FGperp=",FGperp));

//r38 = (3/8)*2.54/2;  // radius of 3/8" bolt

a=360*$t;
legAssembly(a,0);
mirror([1,0,0]) legAssembly(180-a,1.3);

//  -------------------------- crank-arm circle reference
%color([1,.5,.3,.4]) translate([0,Ay,-2]) difference() {
  cylinder(r=AC,h=1,$fn=48,center=true);
  cylinder(r=2,h=2,center=true);
}
color([0.3,.3,1,.7]) // axles
for(x=[-1,1]) translate([x*Bx,0,0]) difference() {
   cylinder(r=2.54/2,h=20,$fn=24,center=true);
   cylinder(r=2.54/2-.4,h=22,$fn=19,center=true);
}

%translate([0,-93,0]) cube([200,2,2],center=true); // ground

// -----------------------------------------------------------------

// plot a link shadow, a different way, to check kinematic correctness
module checkLink(xa,ya,xb,yb,ab) {
  *translate([(xa+xb)/2,(ya+yb)/2,-9])
    rotate([0,0,atan2(yb-ya,xb-xa)]) cube([ab,1,1],center=true);
}

function triK1(ax,ay,ca,bx,by,cb) = (cb*cb - ca*ca + ax*ax -bx*bx +ay*ay -by*by)/(2*(ax-bx));

// ===================================================================

module legAssembly(ang=0,linkOffset=0) {

// solve kinematics for given crank angle
xC = AC*cos(ang);
yC = AC*sin(ang)+Ay;
echo("C",xC,yC);

k1=(yC*yC - Bx*Bx + BD*BD - CD*CD + xC*xC)/(2*yC);
k2=(xC+Bx)/yC;
c=k1*k1-BD*BD+Bx*Bx;
b=2*(Bx-k1*k2);
a=k2*k2+1;
sgnD=(yC<0)?1:-1;
xD=(-b+sgnD*sqrt(b*b-4*a*c))/(2*a);
yD=sqrt(BD*BD - pow(xD+Bx,2));
echo("D",xD,yD,"CD err",sqrt(pow(xC-xD,2)+pow(yC-yD,2))-CD);

hipRot = atan2(yD,Bx+xD)-atan2(DEperp,DEleft);
echo("hipRot",hipRot);
xE = cos(hipRot) * (DEleft-DE) - sin(hipRot) * DEperp - Bx;
yE = sin(hipRot) * (DEleft-DE) + cos(hipRot) * DEperp;
/*
ke1=(yD*yD + xD*xD + DE*DE + BE*BE)/(2*yD);
ke2=(xD+Bx)/yD;
ae=2+ke2*ke2;
be=2*(Bx-ke1*ke2);
ce=ke1*ke1 - BE*BE +Bx*Bx;
echo("E abc:",ae,be,ce);
xE=(-be+sqrt(be*be-4*ae*ce))/(2*ae);
yE=sqrt(BE*BE - pow(xE+Bx,2));
*/
echo("E",xE,yE);

k1h=(xC*xC + yC*yC + BH*BH - CH*CH - Bx*Bx)/(2*yC);
k2h=-(xC+Bx)/yC;
ah=k2h*k2h+1;
bh=2*(k1h*k2h + Bx);
ch=k1h*k1h + Bx*Bx - BH*BH;
sgnH=(yC>0)?1:-1;
xH=(-bh+sgnH*sqrt(bh*bh-4*ah*ch))/(2*ah);
yH=-sqrt(BH*BH - pow(xH+Bx,2));
bhRot=atan2(yH,xH+Bx);
echo("H",xH,yH,"rot",bhRot,"CH err",sqrt(pow(xH-xC,2)+pow(yH-yC,2))-CH);

/*
k1f=(FH*FH - EF*EF - yE*yE - yH*yH + xE*xE - xH*xH) / (2*(yE-yH));
k2f=(xH-xE)/(yE-yH);
af=k2f*k2f+1;
bf=2*(k1f*k2f - xH - k2f*yH);
cf=xH*xH + yH*yH - 2*k1f*yH + k1f*k1f - FH*FH;
xF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
yF=k1f+k2f*xF;
*/
k2f = (yE-yH)/(xE-xH);
k1f = triK1(xE,yE,EF,xH,yH,FH);
af=k2f*k2f+1;
bf=2*(k2f*xE - k1f*k2f -yE);
cf=k1f*k1f - 2*k1f*xE + xE*xE + yE*yE - EF*EF;
yF=(-bf-sqrt(bf*bf - 4*af*cf))/(2*af);
xF=k1f-k2f*yF;
echo("F",xF,yF,"EF err",sqrt(pow(xF-xE,2)+pow(yF-yE,2))-EF);
echo("FH err",sqrt(pow(xF-xH,2)+pow(yF-yH,2))-FH);

// draw the hip so that the main "plane", the ED centerline plane, is at z=0
translate([-Bx,0,0]) rotate([0,0,hipRot])
    translate([DEleft-DE,DEperp,0]) hip();
//translate([-Bx,0,2.5]) rotate([0,0,12.5]) translate([-DEleft,DEperp,0]) hip();
//translate([ Bx,0,0]) rotate([0,0,-20]) translate([DE-DEleft,DEperp,0]) mirror([1,0,0])
//  hip();
checkLink(-Bx,0,xD,yD,BD);
checkLink(-Bx,0,xE,yE,BE);
checkLink(xD,yD,xE,yE,DE);

translate([-Bx,0,0]) rotate([0,0,bhRot])
   BHlinks();
checkLink(-Bx,0,xH,yH,BH);

//------------------------------------------------------- CrankLinks
translate([xC,yC,linkOffset-.6]) rotate([0,0,atan2(yD-yC,xD-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CD);
checkLink(xC,yC,xD,yD,CD);

translate([xC,yC,linkOffset+2]) rotate([0,0,atan2(yH-yC,xH-xC)])
  mirror([0,0,(linkOffset>0)?1:0]) crankLink(CH);
checkLink(xC,yC,xH,yH,CH);

translate([xF,yF,0]) rotate([0,0,atan2(yE-yF,xE-xF)]) EFlink();
checkLink(xE,yE,xF,yF,EF);

footRot = atan2(yH-yF,xH-xF)-atan2(FGperp,FGleft);
translate([xF,yF,0]) rotate([0,0,footRot])
   foot();
checkLink(xF,yF,xH,yH,FH);

} // end module legAssembly()

// include includes whole text.
// use just imports modules
use <util.scad>

// -----------------------------------------------------------------

module foot() {
  hull() {  // FG
    translate([4,0,.2]) cube([4,2.5,2.5],center=true);
    translate([FG-1.3,0,.2]) cylinder(r=1.3,h=2.6,$fn=24,center=true);
  }

  // knee braces/fork
  for (z=[-1.3,7]) rotate([0,0,(z>0)?25*0:0]) difference() {
    hull() {
      // This was elongated as a brace for knee
      //translate([-5,2,1.5*z])scale([3,5,1])cylinder(r=1,h=.4,$fn=64,center=true);
      // wider knee shouldn't need brace
      translate([0,0,z]) cylinder(r=2.5,h=.4,$fn=24,center=true);
      translate([9,0,z])cylinder(r=1,h=.4,center=true);
    }
    cylinder(r=.4,h=22,$fn=17,center=true);
  }

  // hinge holders at H
  %color([0,0,.6,.4])
  translate([FGleft,FGperp,-1]) difference() {
    cylinder(r=2.54/2,h=7,$fn=36);

    cylinder(r=1.9/2,h=22,center=true,$fn=24);
    translate([0,0,3.6])cube([3,3,2.8],center=true);
  }
  translate([FGleft,FGperp,-.87]) {
    rotate([180,0,0]) F698();
    translate([0,0,5.0]) rotate([180,0,0]) F698();
    translate([0,0,1.95]) F698();
    translate([0,0,6.75]) F698();
  }

  // vertical brace extension at knee
  translate([3.5,0,4.1]) cube([2.6,2.6,5.3],center=true);
  hull() {  // gusset
    translate([ 5.5,-1,1]) cylinder(r=.2,h=5.8,$fn=8);
    translate([18, 1,0]) cylinder(r=.3,h=1  ,$fn=8);
  }

  // FH segment bracing
  for (z=[-.3,5.1]) hull() {
    translate([   3    ,   1    ,z]) barEnd1();
    translate([FGleft-1,FGperp-1,z]) barEnd1();
  }
  hull() {  // dig brace.  Could be gusset?
      translate([3,1,5.7]) barEnd1();
      translate([12,11,-.3]) barEnd1();
  }
  translate([FGleft-2,FGperp-2,.3]) cylinder(r=.8,h=5,$fn=11);
  hull() {
      translate([FGleft-7.2,FGperp-8,5.3]) barEnd1();
      translate([14,13.5,-.3]) barEnd1();
  }

  // GH braces
  hull() {
      translate([FG-8,0,-.3]) barEnd1();
      translate([FGleft+1,FGperp-1,-.3]) barEnd1();
  }
  hull() {
      translate([FG-10,0,0]) barEnd1();
      translate([FGleft+1,FGperp-1,5.2]) barEnd1();
  }

  hull() {    // perp brace
      translate([FGleft,FGperp-1,5.2]) barEnd1();
      translate([FGleft,0,0]) barEnd1();
  }
  hull() {    // perp brace
      translate([FGleft,FGperp-1,-.3]) barEnd1();
      translate([FGleft,0,-.3]) barEnd1();
  }

  // extra truss braces
  hull() {
      translate([46,15,3]) barEnd1();
      translate([35, 0,0]) barEnd1();
  }
  translate([FGleft+2,FGperp-2,.3]) cylinder(r=.6,h=5);
  translate([FGleft,FGperp-2,.3]) cylinder(r=.6,h=5);
}

$fn=12;
module hip() {
  translate([DE/2,0,-.2]) cube([DE-5,2.5,2.5],center=true); // top tube
  translate([DE-DEleft,-DEperp,-1.2]) difference() {
     cylinder(r=2.54*1.5/2,h=7.2,$fn=36); // axle
     cylinder(r=2.54*1.5/2-.3,h=22,$fn=18,center=true);
  }

  // top tube fork plates
  translate([DE,0,0]) mirror([1,0,0]) eFork();
                                      eFork();

  hull() {  // diag tubes
    translate([DE-DEleft,-DEperp,0]) barEnd1();
    translate([8,0,0]) barEnd1();
  }
  hull() {
    translate([DE-DEleft,-DEperp,0]) barEnd1();
    translate([DE-8,0,0]) barEnd1();
  }

  // extra bracing
  translate([DE/2,-20,0]) rotate([0,90,0]) cylinder(r=.8,h=20,center=true);
  translate([DE-DEleft,-DEperp,5]) rotate([-110,0,0]) cylinder(r=.8,h=14.4);
}

module eFork() for(z=[-1,1]) difference() {
  hull() {
    translate([0,0,1.4*z]) cylinder(r=2,h=.3,$fn=24,center=true);
    translate([6,0,1.4*z]) cube([1,2,.3],center=true);
  }
  cylinder(r=.4,h=11,$fn=17,center=true);
}

module crankLink(dx=CD) {
  %color([0,0,.6,.4]) difference() {
    cylinder(r=2.54/2,h=.9,$fn=36,center=true);
    cylinder(r=2.54/2-.17,h=2,$fn=24,center=true);
  }
  translate([0,0, .31]) F698(); //cylinder(r=1.4,h=.7,$fn=24,center=true);
  translate([0,0,-.31]) rotate([180,0,0]) F698();

  //translate([dx/2-1,0,0]) cube([dx-3,1.3,1.3],center=true);
  %color([0,.8,0,.6])
  translate([dx/2-1,0,0]) rotate([0,90,0])
     cylinder(r=.6,h=dx-3,$fn=11,center=true);

  translate([dx,0,0]) SA8();
}

module EFlink() {
  translate([EF,0,0]) SA8();
  translate([EF/2-.4,0,0]) rotate([0,90,0])
      cylinder(r=.8,h=EF-3,$fn=13,center=true);

    // ------ tube and knee bearings
    %color([0,0,.6,.4])
    translate([0,0,-.84]) difference() {
       cylinder(r=2.54/2,h=2.54*3-.25,$fn=36);
       cylinder(r=2.54/2-.3,h=22,$fn=36,center=true);
    }
    translate([0,0,6.41]) F698();
    translate([0,0,-.7]) rotate([180,0,0]) F698();

    hull() {  // gusset
      translate([1.3,0,2*2.54/2]) cylinder(r=.2,h=2.54*3,$fn=12,center=true);
      translate([9,0,   0    ]) cylinder(r=.2,h=1,$fn=12);
    }

  //translate([EF,0,0]) cylinder(r=r38,h=5,center=true);
    //                //cylinder(r=r38,h=55,center=true);
  //cylinder(r=1.2,h=22,$fn=36,center=true);
}

// this link drawn with B axle at origin, always.
module BHlinks() {
  difference() {  // main axle rings
    translate([0,0,2.4]) cylinder(r=2.54*1.5/2,h=13.5,$fn=36,center=true);
    translate([0,0,2.4]) cube([5,5,7.9],center=true);
    cylinder(r=2.54*1.5/2-.3,h=22,$fn=19,center=true);
  }

  for(z=[-2.4,7.2]) {  // main side rails
     hull() {
       translate([BH-6,0,z]) barEnd1();
       translate([   0,0,z]) barEnd1();
     }
  }

  // brace near axle
  translate([3,0,2.2]) cylinder(r=.8,h=10,$fn=19,center=true);

/* get rid of fork brace.  Comes close to hitting CH cranklink.
   let cross members hold forks apart
  //    fork brace
  translate([BH-7,0,2.43]) cube([2.5,2.5,7.6],center=true);

  hull() {
    translate([   4,.7,-1.6]) barEnd1();
    translate([BH-9,.7, 6.2]) barEnd1();
  }
  hull() {
    translate([   4,-.7, 6.2]) barEnd1();
    translate([BH-9,-.7,-1.6]) barEnd1();
  }
*/

  BHcrosses();

  // H forks
  for(z=[-1.7,6.2]) translate([BH,0,z]) difference() {
     hull() {
       cylinder(r=3,h=.33,$fn=36);
       translate([-8,0,0]) cylinder(r=1,h=.33);
     }
     cylinder(r=.7,h=2,center=true);
  }

  // to check dimensions
  //%translate([BH/2,0,2.4]) cube([BH,1,7.8],center=true);
}
module barEnd1() sphere(.8,$fn=12);
// diag braces.  Try to leave fork area open to allow clearance for CH link
module BHcrosses() {
h1=BH-4;  // node closest to H
h2=h1-19;
b2=h2-4;
b1=4;
spread=.7;
lo=-1.6;
hi=6.5;
rBar=.8;
  hull() {
    translate([h2, spread,lo]) barEnd1();
    translate([h1, spread,hi]) barEnd1();
  }
  hull() {
    translate([h2,-spread,hi]) barEnd1();
    translate([h1,-spread,lo]) barEnd1();
  }
  hull() {
    translate([b1,-spread,lo]) barEnd1();
    translate([b2,-spread,hi]) barEnd1();
  }
  hull() {
    translate([b2,spread,lo]) barEnd1();
    translate([b1,spread,hi]) barEnd1();
  }
}


[scad] use support + ring for fixing the magnet

/*
	kube.scad - OpenSCAD code generating the Fluksokube enclosure

	Copyright (C) 2014 Bart Van Der Meerssche <bart@flukso.net>

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*$fn = 100; /* number of facets per circle */

/*
	_h = height
	_w = width
	_r = radius
	_t = tolerance
	_s = scaling factor (printer specific)
*/

dim_s = 1;
dim_s = 1.04; /* makerbot */
kube_s = [dim_s, dim_s, dim_s];

magnet_h = 5;
magnet_t = 0.2;
magnet_r = 8 - magnet_t; /* inner diameter now! */

flk_h = 23.5;
flk_t = 0.2;
flk_w = 30.5 + 2*flk_t;

wall_w = 2;
outer_w = flk_w + 2*wall_w;

support_h = outer_w - wall_w - flk_h;
support_r = magnet_r;

ring_h = support_h - magnet_h;
ring_t = 0.1;
ring_inner_r = support_r + ring_t;
ring_outer_r = ring_inner_r + 2;

echo("scaling vector", kube_s);
echo("magnet diameter", magnet_r*2);
echo("flk width", flk_w);
echo("kube width", outer_w);
echo("support diameter", support_r*2);
echo("support height", support_h);
echo("ring height", ring_h);
echo("ring inner diameter", ring_inner_r*2);
echo("ring outer diameter", ring_outer_r*2);

module kube()
{
	difference() {
		cube(outer_w);
		translate([wall_w, wall_w, wall_w + magnet_h]) {
			cube(flk_w, flk_w, outer_w - (wall_w + magnet_h));
		}
	}

	translate([outer_w/2, outer_w/2, wall_w]) {
		cylinder(r=support_r, h=support_h);
	}
}

module ring()
{
	difference() {
		cylinder(r=ring_outer_r, h=ring_h);
		cylinder(r=ring_inner_r, h=ring_h);
	}
}

scale(kube_s) {
	kube();
	translate([1.5*outer_w, outer_w/2, 0]) ring();
}

$fn = 100; /* number of facets per circle */

/*
	_h = height
	_w = width
	_r = radius
	_t = tolerance
	_s = scaling factor (printer specific)
*/

dim_s = 1.04;
kube_s = [dim_s, dim_s, dim_s];

magnet_h = 5;
magnet_t = 0.2;
magnet_r = 13.5 + magnet_t;

flk_h = 23.5;
flk_t = 0.2;
flk_w = 30.5 + 2*flk_t;

wall_w = 2;
outer_w = flk_w + 2*wall_w;

support_r = 5;
support_h = outer_w - wall_w - flk_h;

echo("scaling vector", kube_s);
echo("magnet diameter", magnet_r*2);
echo("flk width", flk_w);
echo("kube width", outer_w);
echo("support height", support_h);

module kube()
{
	difference() {
		cube(outer_w);
		translate([wall_w, wall_w, wall_w + magnet_h]) {
			cube(flk_w, flk_w, outer_w - (wall_w + magnet_h));
		}
		translate([outer_w/2, outer_w/2, wall_w]) {
			cylinder(r=magnet_r, h=magnet_h);
		}
	}

	translate([outer_w/2, outer_w/2, wall_w]) {
		cylinder(r=support_r, h=support_h);
	}
}

scale(kube_s) kube();


transforms: add all_axes

transforms: add all_axes

include <system.scad>
use <misc.scad>

// translate children
module linup(arr=U)
{
    if($children>0)
    {
        for (i = [0 : $children-1])
        translate(arr[i]) children(i);
    }
}

module stack(dist=10, distances=U, axis=Z)
{
    if($children>0)
    {
        if(dist == U && distances != U)
        {
            for (i = [0:len(distances)-1])
            {
                offset = v_sum(distances,i);
                translate(axis*offset)
                    child(i);
            }
        }
        else if(dist != U && distances == U)
        {
            for (i = [0 : $children-1])
                translate(axis*(dist*i))
                    children(i);
        }
    }
}

module orient(axis=U, axis_ref=U, roll=0, extra_roll, extra_roll_orient)
{
    rotate(extra_roll_orient==U||extra_roll==U?0:extra_roll*extra_roll_orient)

    // orient to reference axis
    multmatrix(axis_ref==U?0:v_rotate(90, axis_ref))

    // roll around orient axis
    rotate(axis==U?0:roll*axis)

    // orient to axis
    multmatrix(axis==U?0:v_rotate(90, axis))
    children();
}

function _orient_bounds(orient, size) =
    (_rotate_matrix(_orient_angles(orient)) * [size.x,size.y,size.z,1]);

function _orient_t(orient, align, size) =
    let(bounds = _orient_bounds(orient, size))
    (hadamard(align, [abs(bounds.x/2),abs(bounds.y/2),abs(bounds.z/2)]));

module size_align(size=[10,10,10], extra_size=N, align=N, extra_align=N, orient=Z, orient_ref=Z, roll=0, extra_roll, extra_roll_orient)
{
    t = orient==U?N:_orient_t(orient, align, size);
    /*t_ = orient_ref==U?N:_orient_t(orient_ref, align, size);*/
    extra_t = (orient==U||extra_size==U)?N:_orient_t(orient, extra_align, extra_size);
    translate(t+extra_t)
    {
        orient(axis=orient, axis_ref=orient_ref, roll=roll, extra_roll=extra_roll, extra_roll_orient=extra_roll_orient)
        {
            children();
        }
    }
}

module hull_pairwise()
{
    for (i= [1:1:$children-1])
    {
        hull()
        {
            children(i-1);
            children(i);
        }
    }
}

module proj_extrude_axis(axis=Z, h=1, offset=0, cut=false)
{
    translate(-offset*axis)
    hull()
    {
        orient(axis, axis_ref=Z)
        {
            linear_extrude(h, center=false)
            projection(cut=cut)
            orient(Z, axis_ref=axis)
            translate(offset*axis)
            children();

            orient(Z, axis_ref=axis)
            translate(offset*axis)
            children();
        }
    }
}

module all_axes()
{
    for($axis=concat(AXES,-AXES))
    {
        $color = v_abs($axis*.3 + v_clamp(v_sign($axis),0,1)*.7);
        children();
    }
}

if(false)
{
    for(a=concat(AXES,-AXES))
    translate(5*a)
    {
        c= v_abs(a*.3 + v_clamp(v_sign(a),0,1)*.7);
        color(c)
        proj_extrude_axis(axis=a)
        {
            translate(20*a)
            sphere(d=10);
        }
    }
}

if(false)
{
    translate(Y*10)
    proj_extrude_axis(axis=Y, offset=10)
    {
        sphere(d=10);
    }
}

include <system.scad>
use <misc.scad>

// translate children
module linup(arr=U)
{
    if($children>0)
    {
        for (i = [0 : $children-1])
        translate(arr[i]) children(i);
    }
}

module stack(dist=10, distances=U, axis=Z)
{
    if($children>0)
    {
        if(dist == U && distances != U)
        {
            for (i = [0:len(distances)-1])
            {
                offset = v_sum(distances,i);
                translate(axis*offset)
                    child(i);
            }
        }
        else if(dist != U && distances == U)
        {
            for (i = [0 : $children-1])
                translate(axis*(dist*i))
                    children(i);
        }
    }
}

module orient(axis=U, axis_ref=U, roll=0, extra_roll, extra_roll_orient)
{
    rotate(extra_roll_orient==U||extra_roll==U?0:extra_roll*extra_roll_orient)

    // orient to reference axis
    multmatrix(axis_ref==U?0:v_rotate(90, axis_ref))

    // roll around orient axis
    rotate(axis==U?0:roll*axis)

    // orient to axis
    multmatrix(axis==U?0:v_rotate(90, axis))
    children();
}

function _orient_bounds(orient, size) =
    (_rotate_matrix(_orient_angles(orient)) * [size.x,size.y,size.z,1]);

function _orient_t(orient, align, size) =
    let(bounds = _orient_bounds(orient, size))
    (hadamard(align, [abs(bounds.x/2),abs(bounds.y/2),abs(bounds.z/2)]));

module size_align(size=[10,10,10], extra_size=N, align=N, extra_align=N, orient=Z, orient_ref=Z, roll=0, extra_roll, extra_roll_orient)
{
    t = orient==U?N:_orient_t(orient, align, size);
    /*t_ = orient_ref==U?N:_orient_t(orient_ref, align, size);*/
    extra_t = (orient==U||extra_size==U)?N:_orient_t(orient, extra_align, extra_size);
    translate(t+extra_t)
    {
        orient(axis=orient, axis_ref=orient_ref, roll=roll, extra_roll=extra_roll, extra_roll_orient=extra_roll_orient)
        {
            children();
        }
    }
}

module hull_pairwise()
{
    for (i= [1:1:$children-1])
    {
        hull()
        {
            children(i-1);
            children(i);
        }
    }
}

module proj_extrude_axis(axis=Z, h=1, offset=0, cut=false)
{
    translate(-offset*axis)
    hull()
    {
        orient(axis, axis_ref=Z)
        {
            linear_extrude(h, center=false)
            projection(cut=cut)
            orient(Z, axis_ref=axis)
            translate(offset*axis)
            children();

            orient(Z, axis_ref=axis)
            translate(offset*axis)
            children();
        }
    }
}

if(false)
{
    for(a=concat(AXES,-AXES))
    translate(5*a)
    {
        c= v_abs(a*.3 + v_clamp(v_sign(a),0,1)*.7);
        color(c)
        proj_extrude_axis(axis=a)
        {
            translate(20*a)
            sphere(d=10);
        }
    }
}

if(false)
{
    translate(Y*10)
    proj_extrude_axis(axis=Y, offset=10)
    {
        sphere(d=10);
    }
}


config: Add some belt variables

config: Add some belt variables

include <bearings.scad>
include <screws.scad>
include <thing_libutils/metric-thread.scad>

e=0.01;

// resolution of any round object (segment length)
fnr                         = 0.4;

extrusion_height            = 0.4*mm;

// width of a single wall, should match your slicer settings
extrusion_width             = 0.4*mm;

// how many lines should a normal wall have (i.e. 0.6(extrusion_width)*6(normal_wall_factor)= 3.6mm wall width)
normal_wall_factor          = 3;

thick_wall_factor           = 4;

// diameter of your filament.
filament_d                  = 1.75*mm;
filament_r                  = filament_d/2;

main_width = 340*mm;
main_depth = 420*mm;
main_height = 400*mm;
main_upper_width = 420*mm;

extrusion_color = [0.5,0.5,0.5];
extrusion_size = 20*mm;
extrusion_thread = ThreadM5;

main_lower_dist_z= 80*mm;
main_upper_dist_y= 160*mm;

xaxis_rod_distance = 60*mm;
xaxis_rod_d = 9.975*mm;
xaxis_rod_l = 500*mm;
xaxis_bearing=bearing_igus_rj4jp_01_10;

yaxis_rod_distance = 170*mm;
yaxis_rod_d = 11.975*mm;
yaxis_rod_l = 500*mm;
yaxis_bearing=bearing_igus_rj4jp_01_12;
ycarriage_size=[220*mm,220*mm,5*mm];

zaxis_rod_d = 11.975*mm;
zaxis_rod_l = 500*mm;
zaxis_bearing=bearing_igus_rj4jp_01_12;

// NEMA17 motor w/340mm leadscrew
zaxis_motor = [
                [NemaModel, 17],
                [NemaLengthShort, 33*mm],
                [NemaLengthMedium, 39*mm],
                [NemaLengthLong, 47*mm],
                [NemaSideSize, 42.20*mm],
                [NemaDistanceBetweenMountingHoles, 31.04*mm],
                [NemaMountingHoleDiameter, 4*mm],
                [NemaMountingHoleDepth, 4.5*mm],
                [NemaMountingHoleLip, -1*mm],
                [NemaMountingHoleCutoutRadius, 0*mm],
                [NemaEdgeRoundingRadius, 7*mm],
                [NemaRoundExtrusionDiameter, 22*mm],
                [NemaRoundExtrusionHeight, 1.9*mm],
                [NemaAxleDiameter, 8*mm],
                // custom front axle length
                [NemaFrontAxleLength, 340*mm],
                [NemaBackAxleLength, 15*mm],
                [NemaAxleFlatDepth, 0.5*mm],
                [NemaAxleFlatLengthFront, 15*mm],
                [NemaAxleFlatLengthBack, 14*mm]
         ];

zaxis_motor_offset_z = 10*mm;

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

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

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

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

// GT2
// there is bunch of GT2 belts with different tooth-to-tooth distance
// this one is most common in reprap world
// adjust to your needs.
belt_width = 6.5;
belt_tooth_distance = 2;
belt_tooth_ratio = 0.5;
belt_thickness = 0.8;

//T2.5
//belt_tooth_distance = 2.5;
//belt_tooth_ratio = 0.5;

//T5 (strongly discouraged)
//belt_tooth_distance = 5;
//belt_tooth_ratio = 0.75;

//HTD3
//belt_tooth_distance = 3;
//belt_tooth_ratio = 0.75;

//MXL
//belt_tooth_distance = 2.032;
//belt_tooth_ratio = 0.64;