naca 4-digit airfoil plotter

I didn’t have one, so I made one myself.
wil try to add other naca series, but that could take some time

To see the effect of the upper 3 sliders, you have to go into edit mode.


######################################################################
#
# NACA 4-digit airfoil plotter
# 
# (C) march 2003 Wim Van Hoydonck
#
#######################################################################

import Blender
from Blender import *
from Blender.Draw import *
from Blender.BGL import *
from math import *

###############################################################

# parameter section

p = Create(0.05)		# max camber (in percent of chord)
m = Create(0.5)			# chordwise location of max camber (0 <= m < 1)
xx = Create(0.1)		# airfoil thickness in percent of chord
nv = Create(100)	 	# (half) number of (total) vertices
nvbl = Create(50)		# number of vertices before le
le = Create(0.02)		# point on chord

############################################################### 

def PlotNACA4():
	
	p1 = p.val
	m1 = m.val
	xx1 = xx.val
	nv1 = nv.val
	nvbl1 = nvbl.val
	le1 = le.val

# constants in thickness equation of NACA 4-series (from NASA TM 4741) 

	a0 = 0.2969
	a1 = -0.1260
	a2 = -0.3516
	a3 = 0.2843
	a4 = -0.1015

	me = NMesh.GetRaw()
	
	# calculate position of verts
	i = 0.0
	for i in range(2*nv1):
		if i <= nv1:		# upper surface calculations
			if i < nvbl1:		# x distribution before le
				x = i*le1/(nvbl1-1.0)
			else:				# x distribution after le
				x = le1 + (1.0-le1)*(i-nvbl1+1.0)/(nv1-nvbl1+1.0)
			if x <= m1:			# camber line equation before max camber
				yc = (p1/m1**2.0) * ((2.0*m1*x)-(x*x))
			else:				# after maxcamber
				yc = (p1/((1-m1)**2.0))*((1.0-2.0*m1) + 2.0*m1*x - x**2.0)
			yt = (xx1/0.2)*(a0*x**(0.5) + a1*x + a2*x**2.0 + a3*x**3.0 + a4*x**4.0)	# thickness equation
			y = yc + yt			# add thickness to camber for upper surface
			z = 0
		else:				# lower surface
			if i < 2.0*nv1 - nvbl1+1.0:
				x = 1.0 - (i-nv1)*(1.0-le1)/(nv1-nvbl1+1.0)
			else:
				x = le1*(1.0-(i-2.0*nv1+nvbl1)/(nvbl1-1.0))
			if x <= m1:
				yc = (p1/m1**2.0) * ((2.0*m1*x)-(x)**2.0)
			else:
				yc = (p1/((1-m1)**2.0))*((1.0-2.0*m1) + 2.0*m1*x - x**2.0)
			yt = (xx1/0.2)*(a0*x**(0.5) + a1*x + a2*x**2.0 + a3*x**3.0 + a4*x**4.0)
			y = yc - yt
			z = 0
		v = NMesh.Vert(x,y,z)
		me.verts.append(v)

	# connect verts by lines
	for i in range(2*nv1):
		f = NMesh.Face()
		f.v.append(me.verts[i-1])
		f.v.append(me.verts[i])
		me.faces.append(f)
	
	NMesh.PutRaw(me, "naca4")
	Redraw()

############################################################################
# gui

def draw():
	global p, m, xx, nv, nvbl, le
	glClearColor(0.5, 0.5, 0.5, 1)
	glClear(GL_COLOR_BUFFER_BIT)
	glColor3f(1.0, 1.0, 1.0)
	glRasterPos2i(50, 230) 
	Text("NACA 4-digit airfoil plotter")
	glRasterPos2i(50, 200)
	Text("(C) March 2003 Wim Van Hoydonck")

	p = Slider(" max_camber = ", 2, 10, 10, 350, 20, p.val, -2.0, 2.0)
	m = Slider(" Loc of max_camber = ", 2, 10, 40, 350, 20, m.val, 0.01, 1.0)
	xx = Slider(" thickness = ", 2, 10, 70, 350, 20, xx.val, 0.0, 1.0)
	nv = Slider(" # of verts = ", 2, 10, 100, 350, 20, nv.val, 10, 500)
	nvbl = Slider(" # of verts before le = ", 2, 10, 130, 350, 20, nvbl.val, 2, nv.val)
	le = Slider (" point on chord (=le) = ", 2, 10, 160, 350, 20, le.val, 0.001, 0.1)
	Button("Exit", 1, 310, 200, 50, 30)

def event(evt, val):
	if (evt == QKEY and not val): Exit()
		
def bevent(evt):
	if (evt==1):
		Exit()
	elif (evt==2):
		PlotNACA4()
		Draw()
	elif (evt==3):
		PlotNACA4()
		Redraw()

PlotNACA4()
Register(draw, event, bevent)

greets

wim

This is wonderful, thank you.

I have a plotter for the 16-series aerofoil that I will post one day. I was not brave enough to take on the 6XXXX series. I hope one day to model a sailboat using these.

Cheers

Thanks for the comments daddy. :slight_smile:

I finished an importscript for files with airfoil coordinates in ‘selig’-format.
A database with files can be found overhere: http://www.aae.uiuc.edu/m-selig/ads/coord_database.html

#######################################################################
#
# import script for external airfoil coordinate-files
# 
# (C) march 2003 Wim Van Hoydonck
#
#######################################################################
#
# site with selig-data this script can import:
# http://www.aae.uiuc.edu/m-selg/ads/coord_database.html
#
#######################################################################

import Blender, string
from Blender import *
from Blender.Draw import *

from math import *

# specify file + path
filename = 'C:\	emp\\coord_seligFmt\\p51dtip.dat'
# open file to read ('r')
file = open(filename, 'r')

# read first line, replace whitespaces by underscores
# this will be the name of the mesh
airfoil = string.replace(file.readlines()[0], ' ','_')

# create vectors to store coordinates in
x_coord = []
y_coord = []	

# reopen file
file2 = open(filename, 'r')
# and read from second line
for line in file2.readlines()[1:]:
	# if to many whitespaces
	line = string.strip(line) 
	# split the line in two
	x1, y1 = string.split(line)
	# convert strings to numbers
	x1, y1 = float(x1), float(y1) 
	# append them to vector
	x_coord.append(x1)
	y_coord.append(y1)

# get the length of the vector
length=len(x_coord)

# create new mesh
m = NMesh.GetRaw()

i = 0

# plot verts
for i in range(0,length):	
	x = x_coord[i]
	y = y_coord[i]
	z = 0.0
	v = NMesh.Vert(x,y,z)
	m.verts.append(v)

# connect verts by lines
for i in range(0, length):
	f = NMesh.Face()
	f.v.append(m.verts[i-1])
	f.v.append(m.verts[i])
	m.faces.append(f)
# replace name of mesh (m) by airfoil name
NMesh.PutRaw(m, airfoil)

The only thing that has to be changed is the line that starts with “filename” to point to the place where you saved the files.

Almost forgotten, you need a full python installation to get it working.

greets

wim