// fourbar.scad // (c) Simon Brooke 2025; CC-BY-SA include include include include $fn=64; // Wherever you see unexplained numbers in this file, they are // fudge because I don't yet properly understand the coordinate // transforms and can't remember enough of the trigonometry I // learned 60 years ago. There REALLY should not be any unexplained // numbers. module fourbar_leg(length=1000, chord=100, lat_skew=35, long_skew=30) { h = length * cos(lat_skew) * cos( long_skew); w = length * sin( lat_skew); d = length * sin( long_skew); pivot_radius = 12; translate([0, 0-w, 0]) { // upper pivot needs a complex trig transformation! translate([d - (chord/2), w, h + chord]) rotate([0, 90+long_skew, 0]) color("black") cylinder(h=chord, r=12); // lower pivot: translate([0 - chord, 0, (chord/2 * sin(long_skew))]) rotate([0, 90+long_skew, 0]) color("black") difference() { cylinder(h=chord, r=12); // through hole for pivot axle translate([0, -1, 0]) cylinder(h=chord+2, r=pivot_radius/3); } // aerofoil section sskew([0, long_skew, 0, 0, 0, 0]) rotate([lat_skew, 0, 180]) color("black") airfoil(h=length, L=chord); } } module lower_bar_end_knuckle(chord=100, pivot_radius=12, rise=8,lat_skew=30) { l_body=chord * 1.5; w_body=pivot_radius * 2.5; h_axis=pivot_radius * 2.75; difference() { union () { translate([l_body/2, w_body/2, h_axis]) rotate([0, 90, 0]) cyl(h=l_body, r=w_body/2, rounding=5); // 'except=TOP' in phrase introduces the spurious hulls translate([l_body/2, w_body/2, h_axis*.75]) cuboid([l_body, w_body, h_axis * .75], rounding=5); // bulge for wheel axle; the fork insertion end of // a lefty axle is 25mm diameter translate([chord * 0.25, w_body/2, 0]) rotate([90, 0, 0]) cyl(h=w_body, r=25, rounding=5); // fairing for this translate([chord * 0.25, w_body/2, -3]) rotate([80, 0, 90]) prismoid([w_body, 45], [w_body, 10], rounding=5, h=l_body * .75); } translate([ chord*0.25, -1, pivot_radius * 3]) cube([chord, pivot_radius * 4, pivot_radius * 4]); // scoop for leg-bottom knuckle to rotate within translate([ chord*0.25, w_body/2, h_axis]) rotate([0, 90, 0]) cylinder(h=chord, r=pivot_radius * 1.3); // through hole for pivot axle translate([-1, w_body/2, h_axis]) rotate([0, 90, 0]) cylinder(h=l_body+2, r=pivot_radius/3); // through hole for wheel axle translate([ chord * 0.25, w_body +1, 0]) rotate([90, 0, 0]) cylinder(h=w_body-5, r=12.5); } // airfoil stub to be epoxied into the lower bar of // the linkage translate([chord*1.25, 1, 30]) rotate([90 + rise, 360 - lat_skew, 0]) airfoil(h=chord, L=2 - chord); // // brake disk // translate([(0 - (chord*1.25)), (l_hlb * cos(rise)), 1]) // rotate([90, 0, 0]) // color("silver") // cylinder( h=1.5, r=75); // // wheel (obviously) // translate([(0 - (chord*1.25)), (l_hlb * cos(rise)), -10]) // wheel(); } module fourbar_axle_half( length=1000, chord=100, lat_skew=35, long_skew=30, shoulder=650) { rise=8; // I've got something wrong in computing the half-lower-bar // length, and I don't know what. It scales with lat_skew, but // (unsurprisingly) not liniarly. Fudge of 23 works for lat_skew of 30; 34 works for lat_skew of 35 fudge=0; w = ((length * cos(lat_skew) )); l_hlb= w * (1/cos(rise)) + fudge; v_offset=(l_hlb * sin(rise)) + 38; translate([-15, 0, 0 - v_offset]) rotate([90-rise, 0, 180]) color("black") airfoil(h=l_hlb, L=chord); // lower knuckle rotate([0, long_skew, 0]) translate([(0 - (chord*1.25)), (l_hlb * cos(rise) + 72), -62]) lower_bar_end_knuckle(chord, 12, rise, lat_skew); } module fourbar(length=1000, chord=100, lat_skew=30, long_skew=30, shoulder=650) { translate([0, 0-(shoulder/2), 0]) fourbar_leg( length, chord, lat_skew, long_skew); translate([0, (shoulder/2), 0]) mirror([0, 1, 0]) fourbar_leg(length, chord, lat_skew, long_skew); fourbar_axle_half(length, chord, lat_skew, long_skew, shoulder); mirror([0, 1, 0]) fourbar_axle_half(length, chord, lat_skew, long_skew, shoulder); } translate([-125, 0, 0]) color("blue") lower_bar_end_knuckle(); translate([-100, 74, 0]) wheel(); translate([-100, 34, 0]) color("silver") rotate([90, 0, 0]) cylinder(h=1.5, r=75); // fourbar(length=1000, chord=100, long_skew=30, lat_skew=35, shoulder=650); // fourbar_axle_half(1000,100, 30);