airfoil.frink

Download or view airfoil.frink in plain text format


/** This library allows you to load and format various airfoils.  It uses the
    data available at the UIUC Airfoil Data site:

    https://m-selig.ae.illinois.edu/ads.html

    and the extensive UIUC Airfoil Coordinates Database:

    https://m-selig.ae.illinois.edu/ads/coord_database.html

    All of the airfoils can be downloaded from:
    https://m-selig.ae.illinois.edu/ads/archives/coord_seligFmt.zip

    You can plot airfoil shapes at:
    http://airfoiltools.com/plotter/index

    Airfoils in these databases are mostly listed in the "Selig" format named
    for Michael S. Selig.  The coordinates are in an x,y format starting from
    trailing edge, along the upper surface to the leading edge and back around
    the lower surface to trailing edge
    For example, see E205 at
       https://m-selig.ae.illinois.edu/ads/coord/e205.dat

    Other airfols are in the "Lednicer" format which are upper surface points
    leading edge to trailing edge and then lower surface leading edge to
    trailing edge, separated by an intervening blank line.
    For example, see Clark Y at
       https://m-selig.ae.illinois.edu/ads/coord/clarky.dat

    Some of the airfoils listed do not close at the trailing edge, i.e. the
    trailing edge has a finite thickness as designed.
*/


class Airfoil
{
   /** The name of the airfoil */
   var name

   /** An array of dimensionless [x,y] points in the "Selig" format.  The
    coordinates are in an x,y format starting from trailing edge, along the
    upper surface to the leading edge and back around the lower surface to
    trailing edge For example, see E205 at
    https://m-selig.ae.illinois.edu/ads/coord/e205.dat
    It is expected that the leading edge is at x=0 and the trailing edge is at
    x=1 but this may not be guaranteed.
   */

   var points

   /** The upward rotation of the airfoil as an angle.  This can be populated
   when using the rotate method to create a new Airfoil. */

   var rotation = 0 deg

   /** Constructor.  Creates a new airfoil. */
   new[name, points] :=
   {
      this.name = name
      this.points = points
   }

   /** This loads an airfoil definition from a Selig-formatted URL and returns
       a new Airfoil object. */

   class loadSelig[url] :=
   {
      lines = array[lines[url]]
      name = trim[lines@0]
      points = new array

      LINE:
      for i=1 to length[lines]-1
      {
         // For FrinkTNG this needs to be \p{Space}
         if lines@i =~ %r/[^0-9eE\.[:space:]-]/
         {
            println["Rejecting line $i in $url: " + lines@i]
            next LINE
         }
            
         [x,y] = eval[split[%r/\s+/, trim[lines@i]]]
         if ! (isUnit[x] and isUnit[y])
            next LINE
         
         if y != undef
            points.push[[x,y]]
      }
      return new Airfoil[name, points]
   }

   /** Creates a new (unclosed) polyline object from this airfoil. */
   toPolyline[scaleX=1, scaleY=1] :=
   {
      return new polyline[getPoly[scaleX, scaleY]]
   }

   /** Creates a new (closed) polygon object from this airfoil. */
   toPolygon[scaleX=1, scaleY=1] :=
   {
      return getPoly[scaleX, scaleY]
   }

   /** Creates a new (closed, filled) polygon object from this airfoil. */
   toFilledPolygon[scaleX=1, scaleY=1] :=
   {
      return new filledPolygon[getPoly[scaleX, scaleY]]
   }

   /** Rotate the airfoil upward by the specified angle.  The airfoil is
       rotated around the specified x and y coordinates.  If either coordinate
       is undef, it is replaced by the geometric centroid of the wing.

       It returns a new Airfoil object.
   */

   rotate[angle, cx=undef, cy=undef] :=
   {
      if cx == undef || cy == undef
      {
         [cx1, cy1] = getPoly[].getCentroid[]
         if cx == undef
            cx = cx1
         if cy == undef
            cy = cy1
      }

      p1 = new array
      for [x,y] = points
      {
         x1 = (x - cx) cos[-angle] - (y - cy) sin[-angle] + cx
         y1 = (x - cx) sin[-angle] + (y - cy) cos[-angle] + cy
         p1.push[[x1,y1]]
      }

      a  = new Airfoil[name, p1]
      a.rotation = this.rotation + angle
      return a
   }

   /** Turns the array of points into a polygon object and returns it. */
   getPoly[scaleX=1, scaleY=1] :=
   {
      poly = new polygon
      for [x,y] = points
         poly.addPoint[x scaleX, -y scaleY]

      return poly
   }
}


Download or view airfoil.frink in plain text format


This is a program written in the programming language Frink.
For more information, view the Frink Documentation or see More Sample Frink Programs.

Alan Eliasen was born 20136 days, 3 hours, 36 minutes ago.