3D printing NACA airfoil profiles
12 Jun 2020 - tsp
Last update 05 Jul 2020
4 mins
Note: This blog post is the product of a 3 AM idea. If you spot any errors
comments are welcome.
What are NACA profiles?

NACA profiles are well known airfoil shapes for wings. Theyβve been developed by
the National Advisory Committee for Aeronautics in the United States. All NACA
profiles are identified either by 4 or 5 digits - called 4 or 5 digit series.
The four digit series identifies:
- First digit is the maximum camber as percentage of the chord.
- Second digit is the distance of maximum camber from the airfoil leading
edge in tenths of the chord.
- The last two digits describe the maximum thickness of the airfoil as percent
of the chord.
An NACA 4318 profile would have a maximum camber of 4% located at 30% from the
leading edge with a maximum thickness of 18% of the chord.
Are 3D printed wings flyable?
Iβm going to do some experiments on this but currently it seems that they normally
require some additional post processing to get a smooth surface if one uses
FDM printing - for example sanding or painting. This seems to reduces vortexes
on the surface of the wings and produce much more laminar flow till the tail
edge (where vortexes of course occur and provide a major contribution to lift)
Basic symmetric profiles (00xx series)
The basic symmetric 00xx
airfoil is generated by
[
y_t = 5*t*(0.2969*\sqrt(x) - 0.1260*x - 0.3516*x^2 + 0.2843*x^3 - 0.1015*x^4) \\
x \in (0;1)
]
The variable $x$ is the position along the chord and runs from zero to
one, $y_t$ is the half thickness at the given center-line position - to
generate a symmetric airfoil this can simply be extended in both directions
of the $z$ axis. The $t$ value is the maximum thickness in relation to the
chord (i.e. the last two digits divided by hundred)
As one can see this has been derived as a polynomial fit.
To generate such a profile using OpenJSCAD we can simply use a polynomial and
extrude from that shape:
function naca00_YT(maxThickness, x) {
return 5 * (maxThickness/100.0) * (0.2969*Math.sqrt(x) - 0.1260*x - 0.3516*x*x + 0.2843*x*x*x - 0.1015*x*x*x*x);
}
function naca00_CAG(length, maxThickness, fn) {
let pnts = [];
let step = length / fn;
// Leading edge
pnts.push([0,0]);
// Upper half
for(let i = 1; i < fn; i++) {
pnts.push([i*step, naca00_YT(maxThickness, (i*step)/length)]);
}
// Trailing edge
pnts.push([length, 0]);
// Lower half
for(let i = fn-1; i > 0; i--) {
pnts.push([i*step, -1*naca00_YT(maxThickness, (i*step)/length)]);
}
return CAG.fromPoints(pnts);
}
function naca00(length, width, maxThickness, fn) {
return linear_extrude({ height : width }, naca00_CAG(length, maxThickness, fn));
}
function main() {
return naca00(5, 10, 60, 100);
}
These airfoils have their maximum thickness at about 30% of the airfoil.
Cambered airfoils
If one wants a cambered airfoil one has to modify the equation a little bit.
First one has to calculate the mean camber, then profile thickness as well as the
direction of thickness measurement due to bent camber line:
function nacaYC(x, maxCamber, maxPosition, maxThickness) {
let m = (maxCamber / 100.0);
let p = (maxPosition / 10.0);
let t = (maxThickness / 100.0);
if(x < p) {
return m / (p*p) * (2 * p * x - x * x);
} else {
return m / ((1-p)*(1-p)) * ((1-2*p) + 2*p*x - x*x);
}
}
function nacaYCDiff(x, maxCamber, maxPosition, maxThickness) {
let m = (maxCamber / 100.0);
let p = (maxPosition / 10.0);
let t = (maxThickness / 100.0);
if(x < p) {
return m / (p*p) * (2 * p - 2 * x);
} else {
return m / ((1-p)*(1-p)) * (2*p - 2 * x);
}
}
function nacaYT(x, maxThickness) {
let t = (maxThickness / 100.0);
return t / 0.2 * (0.2969 * Math.sqrt(x) - 0.1260 * x - 0.3516 * x * x + 0.2843 * x * x * x - 0.1015 * x * x * x * x);
}
function nacaCAG(length, maxCamber, maxPositon, maxThickness, fn) {
let pnts = [];
let step = length / fn;
for(let i = 0; i <= fn; i=i+1) {
let x = (i*step) / length;
let yt = nacaYT(x, maxThickness);
let theta = Math.atan(nacaYCDiff(x, maxCamber, maxPositon, maxThickness));
let xu = x - yt * Math.sin(theta);
let yu = nacaYC(x, maxCamber, maxPositon, maxThickness) + yt * Math.cos(theta);
pnts.push([xu*length, yu*length]);
}
for(let i = fn-1; i > 0; i--) {
let x = (i*step) / length;
let yt = nacaYT(x, maxThickness);
let theta = Math.atan(nacaYCDiff(x, maxCamber, maxPositon, maxThickness));
let xl = x + yt * Math.sin(theta);
let yl = nacaYC(x, maxCamber, maxPositon, maxThickness) - yt * Math.cos(theta);
pnts.push([xl*length, yl*length]);
}
return CAG.fromPoints(pnts);
}
function naca(length, width, maxCamber, maxPositon, maxThickness, fn) {
return linear_extrude({ height : width }, nacaCAG(length, maxCamber, maxPositon, maxThickness, fn));
}
function main() {
return naca(5, 10, 2, 4, 15, 100);
}
OpenJSCAD library
To make life way easier Iβve implemented (as usual) an OpenJSCAD library
thatβs available at GitHub.
This article is tagged: Airfoil, 3D printing, OpenJSCAD