Trying to use modelX() but built a spiral galaxy of points

@kll, thanks again, your example helped me get it. I had to do some weird gymnastics, but I got it. There’s probably an easier way than how I did it.


int N = 81;  //number of points
float M = 04.00000f; //2/100.0;
float[] dydx = new float[81];
float T = 12/100.000000f;
float[] dT;
float x[] = new float[81];  //divide up unit chord length by N
float y[] = new float[81];  //divide up unit chord length by N
float xU[] = new float[81];
float yU[] = new float[81];
float xL[] = new float[81];
float yL[] = new float[81];
float P = 0.4; //0.4; //40/100.0;
PShape s,s2,s3;
float a0 = 0.2969;
float a1 = -0.126;
float a2 = -0.3516;
float a3 = 0.2843;
float a4 = -0.1036;
float[] theta = new float[81];
float[] yt = new float[81];
float angle;
float[] beta = new float[81];

Controls controls;
Controls controls2;
HorizontalControl controlX;
int showControls;
boolean draggingZoomSlider = false;
boolean released = true;
float zoom = -200f;
float tzoom = 183.56482f;

PFont font;
PVector[] Xordinates;
PVector[] Yordinates;
float[] XUoord; // = new float[81];
float[] YUoord; // = new float[81];
float[] XLoord; // = new float[81];
float[] YLoord; // = new float[81];
float[] Xvalues; // = new float[162];
float[] Yvalues; // = new float[162];

Table table;
TableRow row;

void setup() {
  
  size( 650, 300, P3D); 
            String[] coordinates = loadStrings("new.csv");
  font = loadFont("CourierNew36.vlw");   
  Xordinates = new PVector[coordinates.length];
  Yordinates = new PVector[coordinates.length]; 
  controls = new Controls();
  controlX = new HorizontalControl();
  showControls = 1;
  Table table = new Table(); 
  table.addColumn("X/C");
  table.addColumn("Y/C");
 
}

void draw() {
  
  background(0, 0, 0);
  
  getOrdinates();               
  Xvalues = concat(xU,xL);
  Yvalues = concat(yU,yL);
  XLoord = subset(Xvalues,81,80);
  YLoord = subset(Yvalues,81,80);
  XUoord = subset(Xvalues,0,80);
  YUoord = subset(Yvalues,0,80);
  
    if (mousePressed) {
     if( (showControls == 1) && (controls.isZoomSliderEvent(mouseX, mouseY)) || ( showControls == 1 && controlX.isZoomSliderEvent(mouseX,mouseY))) {
        draggingZoomSlider = true;      
        zoom = controls.getZoomValue(mouseY);
        tzoom = controlX.getZoomValue(mouseX,mouseY);      
     }    
           // MousePress - Rotation Adjustment
     else if (!draggingZoomSlider) {
        if (released == true){   
        }      
     }
  }  
  stroke(182,185,188);

  strokeWeight(1);
  line( width-width, height/2,width, height/2); 
  textFont(font, 15);
  textAlign(LEFT, BOTTOM);
  text("Airfoil:\nCamber  : "+M * 100.0f + "\nThickness: "  +T * 100.0f , width/2+150, height/2+120);
   
  if (showControls == 1) {
     controls.render(); 
     controlX.render();

  }
  angle = sqrt( ((300 - Xvalues[0]) * (300 - Xvalues[0])) + ((300*Yvalues[80]) * (300*Yvalues[80])) );
  angle = asin(300*Yvalues[80]/angle);

  controls.updateZoomSlider(zoom);
  controlX.updateZoomSlider(tzoom);
  stroke(0,255,0);
  strokeWeight(3);
  translate(width/2-450/2, height/2);
  stroke(255,0,0);
  shearY(-angle);
  
        for (int i = 0; i < Xordinates.length-1; i++){

          if (i < 80){
            
          point(300*XUoord[i],-300*YUoord[i]);   
          Xordinates[i] = new PVector(modelX(XUoord[i],YUoord[i],0), modelY(0,0,0)); 
          Yordinates[i] = new PVector(modelX(0,0,0), modelY(XUoord[i],YUoord[i],0));
          Xvalues[i] = Xordinates[i].x;
          Yvalues[i] = Yordinates[i].y; 
          
         }
}

  shearY(angle);
  shearY(angle);
        for (int i = 0; i < Xordinates.length-1; i++){

          if (i < 80){
            
          point(300*XLoord[i],-300*YLoord[i]);    
          Xordinates[80+i] = new PVector(modelX(XLoord[i],YLoord[i],0), modelY(0,0,0));   
          Yordinates[80+i] = new PVector(modelX(0,0,0), modelY(XLoord[i],YLoord[i],0)); 
          Xvalues[80+i] = Xordinates[80+i].x;
          Yvalues[80+i] = Yordinates[80+i].y;
           
         }

 
}

   printArray(Yvalues);
   Table table = new Table(); 
   table.addColumn("X/C");
   table.addColumn("Y/C");
   stroke(0,255,0);
   shearY(-angle);

   for(int i = 0; i < Xordinates.length-1; i++){
     
      TableRow newRow = table.addRow();
      newRow.setFloat("X/C",Xvalues[i] );
      newRow.setFloat("Y/C",Yvalues[i] );
      point(300*(Xvalues[i]-100),-300*(Yvalues[i]-150)); 
   }  
  
      saveTable(table, "data/new.csv"); 
  
  
}

        
        
        
        
        

void getOrdinates(){
   
  for (int i = 0; i < N; i++){
  
    M = zoom/1000f;
    T = tzoom/1000f;

    if(i >= 0){
       beta[i] = (radians(180)/81.0) * i;
       x[i] = (1 - cos(beta[i]))/2;
     }
    if(i < 40){
     if (x[i] >= 0){
     y[i] = ((M/(P*P) * (2*P*x[i] - x[i]*x[i])));
     dydx[i] = (2*M)/(P*P) * (P - x[i]);
     }    
   }  
    if(i >=40){  
    if (x[i] <= 1.00000f){     
    y[i] = (M/(1-P)*(1-P) * (1 - 2*P + 2*P*x[i] - x[i]*x[i]))*2.75; //* 2.75; //*2.686; 
    dydx[i] = (2*M/((1-P)*(1-P)) * (P - x[i])); 
     } 
   }    
}  //end for loop

   for (int i = 0; i < 81; i++){
   
       yt[i] = (T/0.2* (sqrt(a0*x[i])+ a1*x[i] + a2*(x[i]*x[i]) + a3*(x[i]*x[i]*x[i]) + a4*(x[i]*x[i]*x[i]*x[i])));
       theta[i] = (atan((dydx[i])));
       xU[i] = x[i] - yt[i] * (sin(radians(theta[i]))); 
       yU[i] = ( (y[i] + yt[i]  * (cos(radians(theta[i]))) ) );
       xL[i] = x[i] + yt[i] * sin(radians(theta[i]));        
       yL[i] = (y[i] - yt[i] * cos(radians(theta[i]))); 
      
  /*   upperX[i] = nfs(xU[i], 1, 8);
       upperY[i] = nfs(yU[i], 1, 8);
       lowerX[i] = nfs(xL[i], 1, 8);
       lowerY[i] = nfs(yL[i], 1, 8);  */

   
    }
    

    
    for(int i = 0; i < Xordinates.length; i++){
      
      
      
    }


}
/*

 Kepler Visualization - Controls
 
 GUI controls added by Lon Riesberg, Laboratory for Atmospheric and Space Physics
 lon@ieee.org
 
 April, 2012
 
 Current release consists of a vertical slider for zoom control.  The slider can be toggled
 on/off by pressing the 'c' key.
 
 Slide out controls that map to the other key bindings is currently being implemented and
 will be released soon.
 
*/

class Controls {
   
   int barWidth;   
   int barX;                          // x-coordinate of zoom control
   int minY, maxY;                    // y-coordinate range of zoom control
   float minZoomValue, maxZoomValue;  // values that map onto zoom control
   float valuePerY;                   // zoom value of each y-pixel 
   int sliderY;                       // y-coordinate of current slider position
   float sliderValue;                 // value that corresponds to y-coordinate of slider
   int sliderWidth, sliderHeight;
   int sliderX;  // x-coordinate of left-side slider edge

                       
   
   Controls () {
      
      barX = 40;
      barWidth = 15;
 
      minY = 40;
      maxY = minY + height/3 - sliderHeight/2;
           
      minZoomValue = height - height;
      maxZoomValue = height;   // 300 percent
      valuePerY = (maxZoomValue - minZoomValue) / (maxY - minY);
      
      sliderWidth = 25;
      sliderHeight = 10;
      sliderX = ((barX + (barWidth/2)) - (sliderWidth/2));      
      sliderValue = minZoomValue; 
      sliderY = minY;     
   }
   
   
   void render() {
pushMatrix();
     // strokeWeight(1.5); 
        strokeWeight(1); 
    //  stroke(105, 105, 105);  // fill(0xff33ff99);
   //   stroke(0xff33ff99);  // fill(0xff33ff99);  0xffff0000
       stroke(0xffff0000);
      
      // zoom control bar
      fill(0, 0, 0, 0);
        
      rect(barX, minY, barWidth, maxY-minY);
      
      // slider
     // fill(105, 105, 105); //0x3300FF00
       fill(0xffff0000); // 0xff33ff99//0x3300FF00
      rect(sliderX, sliderY, sliderWidth, sliderHeight);
popMatrix();
   }
   
   
   float getZoomValue(int y) {
      if ((y >= minY) && (y <= (maxY - sliderHeight/2))) {
         sliderY = (int) (y - (sliderHeight/2));     
         if (sliderY < minY) { 
            sliderY = minY; 
         } 
         sliderValue = (y - minY) * valuePerY + minZoomValue;
      }     
      return sliderValue;
   }
   
   
   void updateZoomSlider(float value) {
      int tempY = (int) (value / valuePerY) + minY;
      if ((tempY >= minY) && (tempY <= (maxY-sliderHeight))) {
         sliderValue = value;
         sliderY = tempY;
      }
   }
   
   
   boolean isZoomSliderEvent(int x, int y) {
      int slop = 50;  // number of pixels above or below slider that's acceptable.  provided for ease of use.
      int sliderTop = (int) (sliderY - (sliderHeight/2)) - slop;
      int sliderBottom = sliderY + sliderHeight + slop;
      return ((x >= sliderX) && (x <= (sliderX    + sliderWidth)) && (y >= sliderTop)  && (y <= sliderBottom) || draggingZoomSlider );
   } 
}
 
/*
I modified this so the slider is horizontal.  That gives me a vertical for
tweaking altitude and horizontal for right ascension/longitude
*/

/*

 Kepler Visualization - Controls
 
 GUI controls added by Lon Riesberg, Laboratory for Atmospheric and Space Physics
 lon@ieee.org
 
 April, 2012
 
 Current release consists of a vertical slider for zoom control.  The slider can be toggled
 on/off by pressing the 'c' key.
 
 Slide out controls that map to the other key bindings is currently being implemented and
 will be released soon.
 
*/

class HorizontalControl {
   
   int barHeight;   
   int barY;                          // y-coordinate of zoom control
   int minX, maxX;                    // x-coordinate range of zoom control
   float minZoomValue, maxZoomValue;  // values that map onto zoom control
   float valuePerX;                   // zoom value of each y-pixel 
   int sliderY;                       // y-coordinate of current slider position
   float sliderValue;                 // value that corresponds to y-coordinate of slider
   int sliderWidth, sliderHeight;
   int sliderX;                       // x-coordinate of left-side slider edge                     
   
   HorizontalControl () {
      
      barY = 15; //40;
      barHeight = 40; //15;
 
      minX = 40;
      maxX = minX + width/3 - sliderWidth/2;
           
      minZoomValue = width - width;
      maxZoomValue = width;   // 300 percent
      valuePerX = (maxZoomValue - minZoomValue) / (maxX - minX);
      
      sliderWidth = 10; //25;
      sliderHeight = 25; //10;
     // sliderY = (barY + (barHeight/2)) - (sliderHeight/2);
      sliderY = (barY - (sliderHeight/2)) + (barHeight/2);
      sliderValue = minZoomValue; 
      sliderX = minX;     
   }
   
   
   void render() {
    pushMatrix();


     // strokeWeight(1.5); 
        strokeWeight(1); 
    //  stroke(105, 105, 105);  // fill(0xff33ff99);
   //   stroke(0xff33ff99);  // fill(0xff33ff99);  0xffff0000
       stroke(0xffff0000);
      
      // zoom control bar
      fill(0, 0, 0, 0);
        
      rect(minX,barHeight + height - height/4,maxX-minX, barY );
     // rect(maxX-minX, barHeight/2,minX,barY + height - height/4 );
      
      // slider
     // fill(105, 105, 105); //0x3300FF00
       fill(0xffff0000); // 0xff33ff99//0x3300FF00

      rect(sliderX, sliderY + height - height/4 + sliderHeight/2 , sliderWidth, sliderHeight);

popMatrix();

   }
   
   
   float getZoomValue(int x, int y) {
      if ((x >= minX) && (x <= (maxX - sliderWidth/2)) && (y > (height - height/3))) {
         sliderX = (int) (x - (sliderWidth/2));     
         if (sliderX < minX) { 
            sliderX = minX; 
         } 
         sliderValue = (x - minX) * valuePerX + minZoomValue;
      }     
      return sliderValue;
   }
   
   
   void updateZoomSlider(float value) {
      int tempX = (int) (value / valuePerX) + minX;
      
      if ( (tempX >= minX) && (tempX <= (maxX+sliderWidth))  ) {
         sliderValue = value;
         sliderX = tempX;
      }
   }
   
   
/*   boolean isZoomSliderEvent(int x, int y) {
      int slop = 50;  // number of pixels above or below slider that's acceptable.  provided for ease of use.
      int sliderTop = (int) (sliderY - (sliderHeight/2)) - slop;
      int sliderBottom = sliderY + sliderHeight + slop;
      return ((x >= sliderX) && (x <= (sliderX    + sliderWidth)) && (y >= sliderTop)  && (y <= sliderBottom) || draggingZoomSlider );
   } */
   
      boolean isZoomSliderEvent(int x, int y) {
      int slop = 50;  // number of pixels above or below slider that's acceptable.  provided for ease of use.
      int sliderLeft = (int) (sliderX - (sliderWidth/2)) - slop;
      int sliderRight = sliderX + sliderWidth + slop;
    //  return ((y >= sliderY + height - height/4) && (y <= (sliderY + height - height/4    + sliderHeight)) && (x >= sliderLeft)  && (x <= sliderRight) || draggingZoomSlider );
           return ((y >= sliderY + height - height/4 - sliderHeight/2) && (y <= (sliderY + height - height/4 + sliderHeight*2 )) && (x >= sliderLeft )  && (x <= sliderRight ) || draggingZoomSlider );
   } 
}

The red points are how it must look to capture the final coordinates correctly, otherwise they get written wrong. Draw wrong, write correctly? Like I said, some weird gymnastics.

Edit: I just realized if you try it, you need a new.csv file in /data and it needs to have at least 160 entries or all you;ll get is a blank screen.

PFoil