Airfoil has holes in it

I’m playing around with PixelFlow and the Wind Tunnel LIC example. I went to UUIC airfoil database and grabbed the coordinates for the Eppler 193 airfoil which is a good one for model airplanes. I wrote a little sketch to read the coordinates and draw them. I used the only method I know for drawing from point to point and to my amazement, it drew an airfoil.

I took that code and inserted it into the PixelFlow example and was again amazed. The problem is there are 60 coordinates and it doesn’t connect the dots exactly right. If I use a strokeWeight of 1, then the fluid finds ways to get inside the airfoil, so it doesn’t see it as solid. I upped the strokeWeight to 4 and it stopped but it just isn’t quite right.

First, heres the code for drawing the airfoil:


float y[] = new float[62];
float x[] = new float[62];

void setup()
{
   size( 650, 300,P3D );



}

void draw() {
 background(0,0,0);

translate(-620,-150,0);
 scale(2);
 // image(texmap,0,0);
 String[] coordinates = loadStrings("E193.csv");
println("Loaded " + coordinates.length + " coordinates:");


for (int i = 0; i < coordinates.length; i++) {
  
 String[] ordinate = splitTokens(coordinates[i], " ");
 float Xord = float(ordinate[0]);
 float Yord = float(ordinate[1]);

 x[i] = Xord;
 y[i] = Yord;

  println(i, ": ",String.format("%.5f %.5f",x[i],y[i]));

}

int j = 0;

 for (int i = 0; i < 61; i++){

  
      point(width/2 + x[j+1]*300,height/2 - y[j]*300);


      stroke(0,255,0);
      strokeWeight(1);
      beginShape();
 
      curveVertex(width/2 + x[j+1]*300,height/2 - y[j+1]*300);
      curveVertex(width/2 + x[j]*300,height/2 - y[j]*300);
      curveVertex(width/2 + x[j+1]*300,height/2 - y[j+1]*300);
      curveVertex(width/2 + x[j]*300,height/2 - y[j]*300);

      endShape();
 
      println(j, ": ",String.format("%.5f %.5f",x[j],y[j]));
     j++;
 }
noLoop(); 
}


Here’s a screenshot showing how the airfoil isn’t quite drawn right:

2 Likes

looks impressive,
can you tell me why you need to do 60 little shapes instead
one shape with the for …60 vertex inside?
and if you miss the last point ( = first point ) could do a
endShape(CLOSE);

and for the structure, see

can do a create shape in setup and a
draw shape ( width/2.height/2) in draw,
so no need to do that absolute in the create shape

I don’t know, really. I’m a code klutz and everything is a struggle for me. I’m all ears if you have a better way to draw a shape. I do know airfoils vary in subtle ways and small changes can make a big difference in lift and drag for a given condition.

very funny word! no way that you could find out my name
555 ( thai ) === LOL (en)

ok, show us the csv file and i try

Here are the coordinates:

1.00000 0.00000 
0.99661 0.00051 
0.98674 0.00220 
0.97108 0.00522 
0.95023 0.00932 
0.92452 0.01415 
0.89414 0.01957 
0.85945 0.02558 
0.82096 0.03215 
0.77923 0.03914 
0.73484 0.04643 
0.68839 0.05382 
0.64052 0.06112 
0.59187 0.06808 
0.54306 0.07437 
0.49458 0.07955 
0.44673 0.08333 
0.39979 0.08552 
0.35403 0.08604 
0.30968 0.08488 
0.26696 0.08214 
0.22620 0.07807 
0.18781 0.07285 
0.15218 0.06664 
0.11968 0.05958 
0.09061 0.05183 
0.06525 0.04354 
0.04383 0.03489 
0.02652 0.02610 
0.01344 0.01741 
0.00465 0.00917 
0.00026 0.00192 
0.00129 -0.00373 
0.00819 -0.00837 
0.02044 -0.01250 
0.03791 -0.01586 
0.06049 -0.01839 
0.08801 -0.02008 
0.12026 -0.02097 
0.15697 -0.02110 
0.19778 -0.02059 
0.24227 -0.01954 
0.28998 -0.01806 
0.34035 -0.01627 
0.39280 -0.01429 
0.44672 -0.01223 
0.50145 -0.01018 
0.55630 -0.00823 
0.61059 -0.00644 
0.66364 -0.00485 
0.71479 -0.00350 
0.76339 -0.00239 
0.80882 -0.00153 
0.85050 -0.00090 
0.88788 -0.00048 
0.92048 -0.00018 
0.94794 0.00010 
0.97003 0.00033 
0.98640 0.00034 
0.99655 0.00014 
1.00000 0.00000

try:


String csvfile="E193.csv";  // must be under /data/
String[] coordinates;
float y[] = new float[62];
float x[] = new float[62];

PShape s;

boolean dbug = false;
float zoomit =500;

void load_file() {
  coordinates = loadStrings(csvfile);  // also could use loadtable
  if (dbug) println("Loaded " + coordinates.length + " coordinates:");
  for (int i = 0; i < coordinates.length; i++) {

    String[] ordinate = splitTokens(coordinates[i], " ");
    x[i] = float(ordinate[0]);
    y[i] = float(ordinate[1]);
    if (dbug) println(i, ": ", String.format("%.5f %.5f", x[i], y[i]));
  }
}

void airfoiltest() {
  s = createShape();
  s.beginShape();
  for (int i = 0; i<coordinates.length; i++) s.vertex(zoomit*x[i], -zoomit*y[i]);
  s.endShape(CLOSE);
}

void setup()
{
  size( 650, 300, P2D); //P3D );
  load_file();
  airfoiltest();
  noLoop();
}

void draw() {
  background(200, 200, 0);
  translate(width/2-zoomit/2, height/2);
  shape(s, 0, 0);
}


Holey moley, that’s good. That’s a much better way, wow.

Aww shucks, except it wont work with the way PixelFlow draws obstacles. The klunky way I did it actually worked for some reason I don’t know. PixelFlow uses processing.opengl.PGraphics2D somehow to make the obstacles. I can draw a PShape but the fluid doesn’t see it.

Here’s an example of how a fluid-visible obstacle is made:

      pg_obstacles = (PGraphics2D) createGraphics(w, h, P2D);
      pg_obstacles.smooth(4);
      pg_obstacles.beginDraw();
      pg_obstacles.clear();
      pg_obstacles.fill(64);
      pg_obstacles.noStroke();
     // pg_obstacles.ellipse(w/2, 2*h/3f, 100, 100);
     
      pg_obstacles.ellipse(w/2, 2*h/3f, 50, 300);
      pg_obstacles.endDraw();

It looks to me like (PGraphics2D) is a cast? Yup it casts PGraphics to PGraphics2D. I tried casting PShape to PGraphics and PGraphics2D and it doesn’t allow that.

and you can show how you call your original code in the
pg_obstacles.
and how you try it now?

I got it working. I draw the PShape while within the PGraphics2D. I rewrote one of the functions in the Wind_Tunnel_LIC example, with a lot of help, thanks. Here it is:

   public void resetObstacles(){

    
    float dimxy = 2 * height/3f;

    float th = 20;
    
    load_file();
    for (int i = 0; i < coordinates.length; i++) { 
    pg_obstacles_drawing.beginDraw();
    pg_obstacles_drawing.beginDraw();
    pg_obstacles_drawing.clear();
    pg_obstacles_drawing.noStroke();
    pg_obstacles_drawing.fill(255);
    pg_obstacles_drawing.rectMode(CENTER);
          
      s = createShape();
      s.beginShape();
      s.fill(125);

      for ( i = 0; i<coordinates.length; i++) s.vertex(700*x[i]-500, -700*y[i]+50);

      s.rotate(radians(7));
      s.endShape(CLOSE);  
      shape(s,width/2,height/2);
          
    pg_obstacles_drawing.endDraw();

    pg_obstacles_drawing.endDraw();
        }   


  }

And finally, I went back to the noFill and green stroke:

One last note, even this PShape with noFill and a strokeWeight of 2 has Holes in it and the fluid will find a way inside. I find that ironic that the Holes were why I wanted to improve it and theyre still there. The airfoil is drawn more accurately, however, and that was needed.

very good show, but i not understand the code.

you do :


 60 loops {
  beginDraw
  beginDraw
  createShape
  shape()
  endDraw
  endDraw
}

so for what its worth:

  • the loadfile + createShape should be far outside ( like in setup )

  • for what draw 60 times that object

  • why need: begin begin end end

    • as i not understand that tool, what i actually expected was a one liner like:
pg_obstacles.shape(s,width/2-zoomit/2,height/2);
// ? or 
pg_obstacles_drawing.shape(s,width/2-zoomit/2,height/2);

but as the object is seen anyhow i might be wrong.

Yeah, the extra begin and end were a mistake. It was late. The extra for loop isn’t necessary either. I need to learn to clean up the code before I post it. Thanks for the help, @kll