PyFoil, disegna profili alari con il cellulare

PyFoil è un semplice programmino scritto da me in Python che permette di disegnare profili NACA a 4 e 5 cifre, direttamente dal cellulare.

Per poterlo utilizzare è necessario installare il software Python for S60 sul proprio cellulare, che è reperibile a questo indirizzo.

Ecco alcuni screenshot del programma:


Segue il codice dell’applicazione.

import e32
import graphics
import appuifw
from math import sqrt, sin, cos, tan, atan, log10, ceil

def draw(r=None):
    if buffer:
        c.blit(buffer)

appuifw.app.orientation = 'landscape'
appuifw.app.screen = 'full'
c = appuifw.Canvas(redraw_callback=draw)
buffer = graphics.Image.new(c.size)
appuifw.app.body = c
width, height = c.size
airfoil, digit, t, m, p = [None for i in range(5)]

def set_NACA():
    # Set NACA to operate
    global airfoil, digit, t, m, p
    airfoil = appuifw.query(u'Insert 4 digit NACA', 'number')
    digit = ceil(log10(airfoil))
    # Digit correction for 00XX and 000X
    if digit in [1, 2]: digit = 4
    t = (airfoil%100)/100. # Thickness
    if digit == 4:
        m = (airfoil/1000)/100. # Max camber
        p = (airfoil/100-airfoil/1000*10)/10. # Max camber position
        NACA_plot()
    elif digit == 5:
        mean_line_datas = {210:[0.0580, 361.4],
                           220:[0.1260, 51.64],
                           230:[0.2025, 15.957],
                           240:[0.2900, 6.643],
                           250:[0.3910, 3.230]}
        try:
            m = mean_line_datas[airfoil/100][0]
            p = mean_line_datas[airfoil/100][1]
            NACA_plot()
        except KeyError:
            appuifw.note(u'NACA not supported!', 'error')
    else:
        appuifw.note(u'NACA must be 4 or 5 digit!', 'error')

def derivative(func, x):
    # Derivates a function
    return (func(x) - func(x+0.01))/0.01

def mean_line(x):
    # Airfoil mean line function
    if digit == 4:
        if p == 0:
            return 0
        elif x <= p:
            return m/(p**2)*(2*p*x-x**2)
        elif x > p:
            return m*(1-2*p+2*p*x-x**2)/((1-p)**2)
    elif digit == 5:
        if x <= m:
            return p/6*(x**3-3*m*x**2+m**2*(3-m)*x)
        elif x > m:
            return p*m**3/6*(1-x)

def thickness(x):
    # Airfoil thickness function
    return t /0.2*(0.2969*sqrt(x)-0.126*x-0.3516*x**2+0.2843*x**3-0.1015*x**4)

def NACA_plot():
    # Plots a NACA
    if not airfoil: set_NACA()
    buffer.clear()
    font = (None, 30)
    color0 = (0, 0, 0) # Text color
    color1 = (0, 0, 255) # Airfoil color
    color2 = (255, 0, 0) # Meanline color
    color3 = (100, 100, 100) # Radius color
    # Draws the axes
    y0 = height/2 # Origin
    buffer.line((0, y0, width, y0), outline=color0)
    # Draws the scale
    for u in range(11):
        buffer.line((u*width/10, y0-2, u*width/10, y0+2), outline=color0)
    buffer.line((10, 2*y0-20, 10+width/10, 2*y0-20), outline=color0)
    buffer.text((20+width/10, 2*y0-15), u'10% of the chord', fill=color0)
    # Displays infos about the airfoil
    radius = 1.1019*t**2
    radius_pos = (0, y0 - radius*width, radius*width*2, y0 + radius*width)
    buffer.ellipse(radius_pos, outline=color3)
    buffer.text((10, 30), u'NACA %0#4d' % airfoil, font=font, fill=color0)
    buffer.text((10, 55), u'Leading Edge radius: %.4f' % radius, fill=color0)
    # Plot
    for x in range(width):
        x = float(x)/width
        # Meanline
        buffer.point((x*width, y0 - mean_line(x)*width), outline=color2)
        # Airfoil
        teta = atan(derivative(mean_line, x))
        xU = (x - thickness(x)*sin(teta)) * width
        yU = y0 - (mean_line(x) - thickness(x)*cos(teta)) * width
        xL = (x + thickness(x)*sin(teta)) * width
        yL = y0 - (mean_line(x) + thickness(x)*cos(teta)) * width
        buffer.point((xU, yU), outline=color1, width=2)
        buffer.point((xL, yL), outline=color1, width=2)
    draw()

def velocity_field():
    # Solve the velocity field
    appuifw.note(u'Coming soon!', 'info')

def quit():
    e32.Ao_lock().signal()

# Starting graphics
color = (0, 0, 0)
font1 = (u'Nokia Hindi TitleSmBd S6', 30)
font2 = (u'Nokia Hindi TitleSmBd S6', 15)
text1 = u'NACA PyFoil'
text2 = u'By Ale152'
box1 = buffer.measure_text(text1, font1)
box2 = buffer.measure_text(text2, font2)
position1 = ((width-box1[0][2])/2, 30)
position2 = ((width-box2[0][2])/2, 50)
buffer.text(position1, text1, font=font1, fill=color)
buffer.text(position2, text2, font=font2, fill=color)
for x in range(width):
    x = float(x)/width
    t = 0.12
    buffer.point((x*width, height/2-thickness(x)*width), outline=color)
    buffer.point((x*width, height/2+thickness(x)*width), outline=color)

draw()

appuifw.app.menu = [(u'Plot', NACA_plot),
                    (u'Velocity field', velocity_field),
                    (u'Set NACA', set_NACA),
                    (u'Quit', quit)]
app_lock = e32.Ao_lock()
app_lock.wait()