#include <math.h>
#include "libsx.h"
#include "crosshair.h"
#include "geodata.h"
#include "globals.h"
#include "kraftwerk.h"
#include "graph.h"
#include "naca.h"
#include "circle.bm"
#include "ellips.bm"
#include "wing.bm"
#include "square.bm"
#include "poly.bm"
#include "move.bm"
#include "kill.bm"
#include "zoom.bm"
#include "unzoom.bm"
#define SYMMETRIC 0
#define NON_SYMMETRIC 1
#define TO_SCALE 0
#define STRECHED 1
typedef struct {
char *text;
Widget label;
Widget toggle;
} geoObjectUI;
typedef struct {
int n;
int type;
int drawmode;
float x[100];
float y[100];
} geoObject;
geoObject *thing;
Widget outBNDR, innBNDR, intBNDR;
Widget closeB;
geoObjectUI objectsUI[] = {
{"outer"},
{"inner"},
{"internal"},
{"Square"},
{"Circle"},
{"Ellips"},
{"NACA0012"},
{"Polygon"},
{"Move"},
{"Kill"},
{"Zoom"},
{"UnZoom"}};
int nObj = 12;
geoObject naca0012 = {18, SYMMETRIC, TO_SCALE,
{ 0.0,
.00351381,
.01346558,
.03066379,
.05517089,
.08673215,
.12514615,
.17041743,
.22262233,
.28171957,
.34769243,
.42050737,
.50013381,
.58655041,
.67974794,
.77972806,
.88648617,
1.0 },
{ 0.0,
.00919038,
.01914215,
.02881318,
.03721619,
.04423213,
.05026549,
.05524749,
.05855709,
.06009519,
.05966640,
.05719906,
.05277705,
.04655302,
.03855282,
.02845609,
.01568145,
0.0}
};
geoObject square = {4, NON_SYMMETRIC, STRECHED,
{0., 1., 1., 0.},
{0., 0., 1., 1.} };
geoObject circle;
geoObject ellips;
geoObject move;
geoObject kill;
int first = 0;
int xlead, ylead;
int xtrail, ytrail;
Widget geowindow;
void killBoundary();
void getBoundaryScale(Widget w, void *data);
int clickedOnBoundary(int x, int y, int *segment, int *offset, int *nseg, int *this);
GEO_NODE *new_clickedOnBoundary(int x, int y);
void setAction(int doThis);
void donefcn( Widget w, void *nulldata)
{
int hh=0, ww=0;
SetButtonUpCB(drawWindow, NULL);
SetButtonDownCB(drawWindow, NULL);
SetMouseMotionCB(drawWindow, NULL);
deleteCrossHair();
setAction(NORMAL);
SetCurrentWindow(geowindow);
CloseWindow();
redisplay(w, hh, ww, nulldata);
}
void togglefcn(Widget w, void *data)
{
int i, j, what[2];
int hh=0, ww=0;
j = 0;
for( i = 0; i < nObj; i++){
if( GetToggleState( objectsUI[i].toggle))
what[j++] = i;
}
SetButtonDownCB(drawWindow, nacaDown);
SetButtonUpCB(drawWindow, NULL);
SetMouseMotionCB(drawWindow, nacaMotion);
first = 0;
switch(what[0])
{
case 0:
boundaryType = OUTER;
break;
case 1:
boundaryType = INNER;
break;
case 2:
boundaryType = INTERNAL;
break;
}
switch(what[1])
{
case 3:
thing = □
setAction(DRAWING);
break;
case 4:
thing = &circle;
setAction(DRAWING);
break;
case 5:
thing = &ellips;
setAction(DRAWING);
break;
case 6:
thing = &naca0012;
setAction(DRAWING);
break;
case 7:
inputBoundary(w, data);
setAction(DRAWING);
break;
case 8:
moveBoundary( w, data);
setAction(MOVING);
break;
case 9:
killBoundary();
break;
case 10:
deleteCrossHair();
SetMouseMotionCB(drawWindow, NULL);
setAction(ZOOMING);
zoom(w, data);
break;
case 11:
deleteCrossHair();
SetMouseMotionCB(drawWindow, NULL);
SetButtonUpCB(drawWindow, NULL);
SetButtonDownCB(drawWindow, NULL);
unzoom(w, data);
setAction(NORMAL);
break;
}
redisplay(w, hh, ww, data);
}
void putUpGeoWindow()
{
int i;
geowindow = MakeWindow("Geometry", SAME_DISPLAY, NONEXCLUSIVE_WINDOW);
i = 0;
objectsUI[i++].toggle = MakeToggle(" Outer " , TRUE , NULL, togglefcn, NULL);
objectsUI[i++].toggle = MakeToggle(" Inner " , FALSE,objectsUI[0].toggle , togglefcn, NULL);
objectsUI[i++].toggle = MakeToggle(" Internal", FALSE, objectsUI[0].toggle, togglefcn, NULL);
for(i = 3; i < nObj; i++){
if(i == 3)
objectsUI[i].toggle = MakeToggle(NULL, TRUE, NULL, togglefcn, NULL);
else
objectsUI[i].toggle = MakeToggle(NULL, FALSE, objectsUI[3].toggle,
togglefcn, NULL);
}
closeB = MakeButton("Close", donefcn, NULL);
i = 3;
SetWidgetBitmap(objectsUI[i++].toggle, square_bits, square_width, square_height);
SetWidgetBitmap(objectsUI[i++].toggle, circle_bits, circle_width, circle_height);
SetWidgetBitmap(objectsUI[i++].toggle, ellips_bits, ellips_width, ellips_height);
SetWidgetBitmap(objectsUI[i++].toggle, wing_bits, wing_width, wing_height);
SetWidgetBitmap(objectsUI[i++].toggle, poly_bits, poly_width, poly_height);
SetWidgetBitmap(objectsUI[i++].toggle, move_bits, move_width, move_height);
SetWidgetBitmap(objectsUI[i++].toggle, kill_bits, kill_width, kill_height);
SetWidgetBitmap(objectsUI[i++].toggle, zoom_bits, zoom_width, zoom_height);
SetWidgetBitmap(objectsUI[i++].toggle, unzoom_bits, unzoom_width, unzoom_height);
for(i = 1; i < nObj; i++){
SetWidgetPos(objectsUI[i].toggle, PLACE_UNDER, objectsUI[i-1].toggle,
NO_CARE, NULL);
}
SetWidgetPos(closeB, PLACE_UNDER, objectsUI[nObj-1].toggle, NO_CARE, NULL);
togglefcn(drawWindow, NULL);
ShowDisplay();
}
void initCircle(geoObject *circle, int n, int id)
{
int i;
double fi;
for(i = 0; i < n ; i++){
fi = (double) 2 * 3.141592 * i / n;
circle->x[i] = (float) cos(fi);
circle->y[i] = (float) sin(fi);
}
circle->n = n ;
circle->type = NON_SYMMETRIC;
if(id == 0)
circle->drawmode = STRECHED;
else
circle->drawmode = TO_SCALE;
}
void naca(Widget w, void *data)
{
int hh=0, ww=0;
first = 0;
boundaryType = INNER;
initCircle(&circle, 30, 1);
initCircle(&ellips, 30, 0);
thing = □
thing = &naca0012;
putUpGeoWindow();
SetButtonDownCB(drawWindow, nacaDown);
SetMouseMotionCB(drawWindow, nacaMotion);
setAction(DRAWING);
state = HAVE_BOUNDARY;
redisplay(w, hh, ww, data);
}
void nacaMotion(Widget w, int xp, int yp, void *data)
{
crossHair(xp,yp);
if(state == HAVE_NOTHING){
getBoundaryScale(w, data);
}
state = HAVE_BOUNDARY;
if(first == 1){
SetDrawMode(SANE_XOR);
drawNaca(xlead, ylead, xtrail, ytrail);
drawNaca(xlead, ylead, xp, yp);
SetDrawMode(GXcopy);
xtrail = xp;
ytrail = yp;
}
}
double maxsize(int comp)
{
double max, cmp;
int i;
max = -1000;
for( i = 0; i < thing->n; i++){
if(comp == 0)
cmp = thing->x[i];
else
cmp = thing->y[i];
cmp = sqrt(cmp*cmp);
if( cmp > max)
max = cmp;
}
return max;
}
void nacaDown(Widget w, int button, int x, int y, void *data)
{
double l, lx, ly, ca, sa, xx, yy;
float x1, y1, x2, y2;
double lp, lpx, lpy;
int xp, yp;
int nb, i;
float xphys, yphys;
PTS_NODE *p0, *p1, *p2;
GEO_NODE *g;
if( first == 0){
first = 1;
xlead = x;
ylead = y;
xtrail = x;
ytrail = y;
}
else{
first = 0;
SetButtonDownCB(drawWindow, NULL);
SetMouseMotionCB(drawWindow, NULL);
deleteCrossHair();
g = new_bnd();
g->type = boundaryType;
pix2phys(xlead, ylead, &x1, &y1);
pix2phys(x, y, &x2, &y2);
if(thing->drawmode == TO_SCALE){
l = sqrt((double) (xlead-x)*(xlead-x) + (ylead-y)*(ylead-y));
l = l / maxsize(0);
if(l == 0.0)
l = .000001;
lx = l;
ly = l;
lp = sqrt((double) (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
lp = lp / maxsize(0);
lpx = lp;
lpy = lp;
ca = (double) (x-xlead) / l;
sa = (double) (y-ylead) / l;
}
else{
lx = (double) (x - xlead )/maxsize(0);
ly = (double) (y - ylead )/maxsize(1);
ca = 1.;
sa = 0.;
lpx = (x2 - x1) / (double) maxsize(0);
lpy = (y2 - y1) / (double) maxsize(1);
}
i = 0;
xx = lx * thing->x[i];
yy = ly * thing->y[i];
x2 = (float) lpx * thing->x[i];
y2 = -(float) lpy * thing->y[i];
xp = (int) (xx*ca - yy*sa + xlead);
yp = (int) (xx*sa + yy*ca + ylead);
xphys = (float) (x2*ca - y2*sa + x1);
yphys = (float) (-x2*sa - y2*ca + y1);
p0 = add_pnt(xphys, yphys);
p1 = p0;
for(i = 1; i < thing->n; i++){
xx = lx * thing->x[i];
yy = ly * thing->y[i];
x2 = (float) lpx * thing->x[i];
y2 = -(float) lpy * thing->y[i];
xp = (int) (xx*ca - yy*sa + xlead);
yp = (int) (xx*sa + yy*ca + ylead);
xphys = (float) (x2*ca - y2*sa + x1);
yphys = (float) (-x2*sa - y2*ca + y1);
p2 = add_pnt(xphys, yphys);
add_seg(p1, p2, g);
p1 = p2;
}
if(thing->type == SYMMETRIC){
for(i = thing->n - 2; i > 0; i--){
xx = lx * thing->x[i];
yy = - ly * thing->y[i];
x2 = (float) lpx * thing->x[i];
y2 = (float) lpy * thing->y[i];
xp = (int) (xx*ca - yy*sa + xlead);
yp = (int) (xx*sa + yy*ca + ylead);
xphys = (float) (x2*ca - y2*sa + x1);
yphys = (float) (-x2*sa - y2*ca + y1);
p2 = add_pnt(xphys, yphys);
add_seg(p1, p2, g);
p1 = p2;
}
}
add_seg(p1, p0, g);
state = HAVE_BOUNDARY;
redisplay(w, xx, yy, data);
SetButtonDownCB(drawWindow, nacaDown);
SetMouseMotionCB(drawWindow, nacaMotion);
}
}
void drawNaca(int x1, int y1, int x2, int y2)
{
double l, lx, ly, ca, sa;
int xx1, yy1, xx2, yy2;
int x, y;
int i;
x1++;
y1++;
x2--;
y2--;
if(thing->drawmode == TO_SCALE){
l = sqrt((double) (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
l = l / maxsize(0);
lx = l;
ly = l;
ca = (double) (x2-x1) / l;
sa = (double) (y2-y1) / l;
}
else{
ca = 1.;
sa = 0.;
lx = (double) (x2 -x1)/maxsize(0);
ly = (double) (y2 -y1)/maxsize(1);
}
x = (int) lx * thing->x[0] ;
y = (int) ly * thing->y[0] ;
xx1 = (int) (x*ca - y*sa + x1);
yy1 = (int) (x*sa + y*ca + y1);
for(i = 0; i < thing->n; i++){
x = (int) lx * thing->x[i];
y = (int) ly * thing->y[i];
xx2 = (int) (x*ca - y*sa + x1);
yy2 = (int) (x*sa + y*ca + y1);
myDrawLine(xx1, yy1, xx2, yy2);
xx1 = xx2;
yy1 = yy2;
}
if(thing->type == SYMMETRIC){
x = (int) lx * thing->x[0] ;
y = - (int) ly * thing->y[0] ;
xx1 = (int) (x*ca - y*sa + x1);
yy1 = (int) (x*sa + y*ca + y1);
for(i = 0; i < thing->n; i++){
x = (int) lx * thing->x[i];
y = - (int) ly * thing->y[i];
xx2 = (int) (x*ca - y*sa + x1);
yy2 = (int) (x*sa + y*ca + y1);
myDrawLine(xx1, yy1, xx2, yy2);
xx1 = xx2;
yy1 = yy2;
}
}
else{
x = (int) lx * thing->x[0];
y = (int) ly * thing->y[0];
xx2 = (int) (x*ca - y*sa + x1);
yy2 = (int) (x*sa + y*ca + y1);
myDrawLine(xx1, yy1, xx2, yy2);
}
}
void killMouseDown(Widget w, int button, int x, int y, void *data)
{
int n;
int ioff;
int segment, this;
GEO_NODE *g;
g = new_clickedOnBoundary(x, y);
if(g != NULL){
rm_bnd(g);
if(number_of_boundaries() == 0)
state = HAVE_SCALE;
redisplay(w, x, y, data);
}
}
void killBoundary()
{
first = 0;
setAction(DELETING);
SetButtonUpCB(drawWindow, NULL);
SetButtonDownCB(drawWindow, killMouseDown);
SetMouseMotionCB(drawWindow, nacaMotion);
}
syntax highlighted by Code2HTML, v. 0.9.1