Start made on the four-bar linkage. I need to remember trigonometry.

This commit is contained in:
Simon Brooke 2025-09-04 17:27:21 +01:00
parent f863799729
commit 3f22298df1
11 changed files with 210850 additions and 0 deletions

View file

@ -0,0 +1 @@
This thing was created by Thingiverse user Parkinbot, and is licensed under Creative Commons - Attribution - Non-Commercial

View file

@ -0,0 +1,4 @@
NACA Airfoils - 4 digit fully parametric OpenSCAD library by Parkinbot on Thingiverse: https://www.thingiverse.com/thing:898554
Summary:
Are you playing around with airfoils? Better have a fast airfoil data generator at hand. I found some code doing airfoils in this forum, but that wasn't flexible enough as it didn't take advantage of the new vector features of OpenSCAD 2015.So I coded my own little library to always have a fully customizable 4 digit NACA airfoil data generator at hand. What you geta fully parametric library a bunch of usage examples help functionality well documented code (but very tough in the core part) In my next post I'll show how to do objects that sweep smoothly between different airfoil types being freely shifted and rotated in 3D space. Stay tuned.

View file

@ -0,0 +1,60 @@
// Naca4.scad - library for parametric airfoils of 4 digit NACA series
// Code: Rudolf Huttary, Berlin
// June 2015
// commercial use prohibited
// general use: for more examples refer to sampler.scad
// naca = naca digits or 3el vector (default = 12 or [0, 0, .12])
// L = chord length [mm] (default= 100)
// N = # sample points (default= 81)
// h = height [mm] (default= 1)
// open = close at the thin end? (default = true)
// two equivalent example calls
// airfoil(naca = 2408, L = 60, N=1001, h = 30, open = false);
// airfoil(naca = [.2, .4, .32], L = 60, N=1001, h = 30, open = false);
module help_Naca4()
{
echo(str("\n\nList of signatures in lib:\n=================\n",
"module help() - displays this help\n",
"module help_Naca() - displays this help\n",
"module help_Naca4() - displays this help\n",
"module airfoil(naca=2412, L = 100, N = 81, h = 1, open = false) - renders airfoil object\n",
"module airfoil(naca=[.2, .4, .12], L = 100, N = 81, h = 1, open = false) - renders airfoil object using percentage for camber, camber distance and thicknes\n",
"function airfoil_data(naca=12, L = 100, N = 81, open = false)\n",
"=================\n"));
}
module help() help_Naca4();
// help();
// this is the object
module airfoil(naca=12, L = 100, N = 81, h = 1, open = false)
{
linear_extrude(height = h)
polygon(points = airfoil_data(naca, L, N, open));
}
// this is the main function providing the airfoil data
function airfoil_data(naca=12, L = 100, N = 81, open = false) =
let(Na = len(naca)!=3?NACA(naca):naca)
let(A = [.2969, -0.126, -.3516, .2843, open?-0.1015:-0.1036])
[for (b=[-180:360/(N):179.99])
let (x = (1-cos(b))/2)
let(yt = sign(b)*Na[2]/.2*(A*[sqrt(x), x, x*x, x*x*x, x*x*x*x]))
Na[0]==0?L*[x, yt]:L*camber(x, yt, Na[0], Na[1], sign(b))];
// helper functions
function NACA(naca) =
let (M = floor(naca/1000))
let (P = floor((naca-M*1000)/100))
[M/100, P/10, floor(naca-M*1000-P*100)/100];
function camber(x, y, M, P, upper) =
let(yc = (x<P)?M/P/P*(2*P*x-x*x): M/(1-P)/(1-P)*(1 - 2*P + 2*P*x -x*x))
let(dy = (x<P)?2*M/P/P*(P-x):2*M/(1-P)/(1-P)*(P-x))
let(th = atan(dy))
[upper ? x - y*sin(th):x + y*sin(th), upper ? yc + y*cos(th):yc - y*cos(th)];

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
// Sampler.scad - library for parametric airfoils of 4 digit NACA series
// Code: Rudolf Huttary, Berlin
// June 2015
// commercial use prohibited
use <ShortCuts.scad> // see: http://www.thingiverse.com/thing:644830
use <Naca4.scad>
place_in_rect(110, 70) // arange that stuff in a grid
{
// duct
T(50, 30, 0)
rotate_extrude($fn = 100)
translate([30, 100, 0])
R(0, -180, 90)
polygon(points = airfoil_data([-.1, .4, .1], L=100));
// drop
T(50, 30, 0)
scale([1, 2])
rotate_extrude()
Rz(90)
difference()
{
polygon(points = airfoil_data(30));
square(100, 100);
}
// some winding airfoils
linear_extrude(height = 100, twist = 30, scale = .5)
polygon(points = airfoil_data(30));
translate([50, 0, 0])
linear_extrude(height = 100, twist = 30, scale = .5)
translate([-50, 0, 0])
polygon(points = airfoil_data(30));
translate([100, 0, 0])
linear_extrude(height = 100, twist = 30, scale = .5)
translate([-100, 0, 0])
polygon(points = airfoil_data(30));
T(30)
airfoil(naca = 2432, L = 60, N=101, h = 30, open = false);
// some airfoil objects, Naca values defined with number or vector
airfoil (); // NACA12 object
airfoil (2417); // NACA2417 object
airfoil ([.2, .4, .17]); // NACA2417 object
airfoil ([-.10101, .52344, .17122]); // inverted precise curvature
help(); // show help in console
// end of sampler
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,251 @@
// ShortCuts.scad
// Autor: Rudolf Huttary, Berlin 2015
//
$fn = 100;
//show_examples();
module show_examples()
place_in_rect(30, 30)
{
Cy(h = 10);
CyH(h = 10);
CyH(h = 10, w = 30);
CyS(h = 10);
CyS(h = 10, w1 = 25, w2 = 75);
Cu(10);
Ri(h = 10);
RiH(h = 10);
RiS(h = 10, w1 = 10);
RiS(h = 10, w1 = 30, w2 = 300);
Sp();
SpH(10, 30, 30);
}
module help()
{
echo("===============");
echo("help(): shows this help");
echo("show_examples(): shows some examples");
echo("place_in_rect(): places children objects in grid");
echo("Transformations:");
echo(" transform : T(x=0, y=0, z=0), Tx(x=0) , Ty(y=0), Tz(z=0)");
echo(" rotate : R(x=0, y=0, z=0), Rx(x=0) , Ry(y=0), Rz(z=0)");
echo(" scale : S(x=1, y=1, z=1), Sx(x=1) , Sy(y=1), Sz(z=1)");
echo("Logical");
echo(" difference : D()");
echo(" union : U()");
echo(" intersection : *missing*");
echo("Primitives");
echo(" circle : Ci(r=10)");
echo(" circle_half : CiH(r=10, w=0)")
echo(" circle_segment : CiS(r=10, w1=0, w2=90)")
echo(" square : Sq(x=10, y=0, center=true))");
echo(" cylinder : Cy(r=10, h=1, center=true)");
echo(" cylinder_half : CyH(r=10, w=0)")
echo(" cylinder_segment: CyS(r=10, h=1, w1=0, w2=90,center=true)");
echo(" cylinder_segment: Pie(r=10, h=1, w1=0, w2=90,center=true)");
echo(" cube : Cu(x=10, y=0, z=10, center=true)");
echo(" ring : Ri(R=10, r=5, h=1, center=true)");
echo(" ring_half : RiH(R=10, r=5, h=1, w=0 center=true)");
echo(" ring_segment : RiS(R=10, r=5, h=1, w1=0, w2=90, center=true)");
echo(" sphere: Sp(r=10))");
echo(" sphere_half: SpH(r=10, w1 = 0, w2 = 0))");
echo("===============");
}
// Euclidean Transformations
module T(x=0, y=0, z=0){translate([x, y, z])children(); }
module Tx(x) { translate([x, 0, 0])children(); }
module Ty(y) { translate([0, y, 0])children(); }
module Tz(z) { translate([0, 0, z])children(); }
module R(x=0, y=0, z=0){rotate([x, y, z]) children();}
module Rx(x=90){rotate([x, 0, 0]) children();}
module Ry(y=90){rotate([0, y, 0]) children();}
module Rz(z=90){rotate([0, 0, z]) children();}
module S(x=1, y=1, z=1){scale([x, y, z]) children();}
module Sx(x=1){scale([x, 1, 1]) children();}
module Sy(y=1){scale([1, y, 1]) children();}
module Sz(z=1){scale([1, 1, z]) children();}
module D() difference(){children(0); children([1:$children-1]);}
module U() children([0:$children-1]);
// module I() intersection()children([0:$children-1]); // does not work for some reason
// primitives - 2D
module Sq(x =10, y = 0, center = true)
{
if(y==0)
square([x, x], center = center);
else
square([x, y], center = center);
}
module Ci(r = 10)
{
circle(r = r);
}
// derived primitives - 2d
module CiH(r = 10, w = 0)
circle_half(r, w);
module CiS(r = 10, w1 = 0, w2 = 90)
circle_segment(r, w1, w2);
// primitives - 3d
module Cy(r = 10, h = 1, center = true)
{
cylinder(r = r, h = h, center = center);
}
module Cu(x = 10, y = 0, z = 10, center = true)
{
if (y==0)
cube([x, x, x], center = center);
else
cube([x, y, z], center = center);
}
// derived primitives - 3d
module CyH(r = 10, h = 1, w = 0, center = true)
cylinder_half(r, h, w, center);
module CyS(r = 10, h = 1, w1 = 0, w2 = 90, center = true)
cylinder_segment(r, h, w1, w2, center);
module Ri(R = 10, r = 5, h = 1, center = true)
ring(R, r, h, center);
module RiS(R = 10, r = 5, h = 1, w1 = 0, w2 = 90, center = true)
ring_segment(R, r, h, w1, w2, center);
module RiH(r1 = 10, r2, h = 1, w = 0, center = true)
ring_half(r1, r2, h, w, center);
module Pie(r = 10, h = 1, w1 = 0, w2 = 90, center = true)
cylinder_segment(r, h, w1, w2, center);
module Sp(r = 10)
sphere(r);
module SpH(r = 10, w1 = 0, w2 = 0)
sphere_half(r, w1, w2);
module SpS(r = 10, w1 = 0, w2 = 90, w3 = 90)
sphere_segment(r, w1, w2);
// clear text definitions
module circle_half(r = 10, w = 0)
{
difference()
{
circle(r);
rotate([0, 0, w-90])
translate([0, -r])
square([r, 2*r], center = false);
}
}
module circle_segment(r = 10, w1 = 0, w2 = 90)
{
W2 = (w1>w2)?w2+360:w2;
if (W2-w1 < 180)
intersection()
{
circle_half(r, w1);
circle_half(r, W2-180);
}
else
union()
{
circle_half(r, w1);
circle_half(r, W2-180);
}
}
module cylinder_half(r = 10, h = 1, w = 0, center = true)
{
linear_extrude(height = h, center = center)
circle_half(r, w);
}
module cylinder_segment(r = 10, h = 1, w1 = 0, w2 = 90, center = true)
{
linear_extrude(height = h, center = center)
circle_segment(r, w1, w2);
}
module ring(R = 10, r = 5, h = 1, center = true)
{
difference()
{
cylinder(r = R, h = h, center = center);
translate([0, 0, -2*h])
cylinder(r = r, h = 4*h, center = false);
}
}
module ring_half(R = 10, r = 5, h = 1, w = 0, center = true)
{
difference()
{
ring(R, r, h, center);
rotate([0, 0, w])
translate([0, -R/2, 0])
cube([2*R, R, 3*h], center = true);
}
}
module ring_segment(R = 10, r = 5, h = 1, w1 = 0, w2 = 90, center = true)
{
W2 = (w1>w2)?w2+360:w2;
if (W2-w1 < 180)
intersection()
{
ring_half(R, r, h, w1, center);
ring_half(R, r, h, W2-180, center);
}
else
union()
{
ring_half(R, r, h, w1, center);
ring_half(R, r, h, W2-180, center);
}
}
module sphere_half(r = 10, w1 = 0, w2 = 0)
{
difference()
{
sphere(r);
rotate([-w1, -w2, 0])
translate([0, 0, r])
cube(2*r, 2*r, r, center = true);
}
}
// additional code
module place_in_rect(dx =20, dy=20)
{
cols = ceil(sqrt($children));
rows = floor(sqrt($children));
for(i = [0:$children-1])
{
T(dx*(-cols/2+(i%cols)+.5), dy*(rows/2-floor(i/cols)-.5))
children(i);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

43
model/Library/skew.scad Normal file
View file

@ -0,0 +1,43 @@
/* Taken from https://gist.github.com/boredzo/fde487c724a40a26fa9c?permalink_comment_id=4258747 */
/* skew takes an array of six angles:
* x along y
* x along z
* y along x
* y along z
* z along x
* z along y
*/
module skew(dims) {
matrix = [
[ 1, dims[0]/45, dims[1]/45, 0 ],
[ dims[2]/45, 1, dims[4]/45, 0 ],
[ dims[5]/45, dims[3]/45, 1, 0 ],
[ 0, 0, 0, 1 ]
];
multmatrix(matrix)
children();
}
/* example:
* skew([45, 0, 0, 0, 0, 0])
* cube([10,10,10]);
*/
// Skews the child geometry.
// xy: Angle towards X along Y axis.
// xz: Angle towards X along Z axis.
// yx: Angle towards Y along X axis.
// yz: Angle towards Y along Z axis.
// zx: Angle towards Z along X axis.
// zy: Angle towards Z along Y axis.
module skew2(xy = 0, xz = 0, yx = 0, yz = 0, zx = 0, zy = 0) {
matrix = [
[ 1, tan(xy), tan(xz), 0 ],
[ tan(yx), 1, tan(yz), 0 ],
[ tan(zx), tan(zy), 1, 0 ],
[ 0, 0, 0, 1 ]
];
multmatrix(matrix)
children();
}

35
model/fourbar.scad Normal file
View file

@ -0,0 +1,35 @@
// fourbar.scad
include <Library/BentSim/Bike_accessories.scad>
include <Library/NACAAirfoils/files/Naca4.scad>
include <Library/skew.scad>
module fourbar_leg(length=1000, chord=100, long_skew=30, lat_skew=30) {
// upper pivot needs a complex trig transformation!
translate([(length * cos(long_skew) * cos(lat_skew)) - (2 * chord),
length * cos(long_skew) * sin(lat_skew), 0])
rotate([0, 90+long_skew, 0])
cylinder(h=chord, r=12);
// lower pivot:
translate([0-chord, -12, (chord/2) * sin(long_skew) * sin(lat_skew)])
rotate([0, 90+long_skew, 0])
cylinder(h=chord, r=12);
// aerofoil section
skew([0, long_skew, 0, 0, 0, 0])
rotate([lat_skew, 0, 180])
airfoil(h=length, L=chord);
}
module fourbar(length=1000, chord=100, long_skew=30, lat_skew=30, shoulder=650) {
translate([0, 0-(shoulder/2), 0])
fourbar_leg( length, chord, long_skew, lat_skew);
translate([0, shoulder/2, 0])
mirror([0, 1, 0])
fourbar_leg(length, chord, long_skew, lat_skew);
}
fourbar(600, 100, 30, 30, 650);