@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.