/* $Log: graph.c,v $ * Revision 1.4 1995/03/20 14:54:55 martenl * *** empty log message *** * * Revision 1.3 1995/03/10 12:41:16 martenl * *** empty log message *** * * Revision 1.2 1995/02/23 09:45:18 martenl * getDrawBox: * Changed criteriom for when xmin,xmax etc is recomputed * to allow calling even if no mesh is present. * * */ #include #include #include #include #include "libsx.h" /* gets us in the door with libsx */ #include "globals.h" #include "graph.h" #include "grid.h" #include "kraftwerk.h" #include "util.h" #include "naca.h" #include "geodata.h" #define min(x, y) (((x) < (y)) ? (x) : (y)) #define max(x, y) (((x) > (y)) ? (x) : (y)) #define PAPER_WIDTH 200 /* Paper size in mm */ #define PAPER_HEIGTH 300 #define PAPER_SIDE_MARGIN 0 #define PAPER_TOP_MARGIN 0 #define MM 2.8346 #define X11 0 #define PS 1 float xmin_orig; float xmax_orig; float ymin_orig; float ymax_orig; int device = X11; float psPixScale; float psPixXoff; float psPixYoff; float psPhysScale; float psPhysXoff; float psPhysYoff; int cells[256]; int ncells = 0; unsigned char red[255]; unsigned char green[255]; unsigned char blue[255]; FILE *psfile; GC drawgc; void psDrawFilledPolygon(XPoint *p, int n); void rainbow(double *hh, double *ss, double *vv, double *r, double *g, double *b); void dhsv2rgb(double h,double s, double v,double *r,double *g,double *b) ; void myDrawLine(int x1, int y1, int x2, int y2) { if(device == X11) DrawLine(x1, y1, x2, y2); else psDrawLine(x1, y1, x2, y2); } void myDrawCross(int x1, int y1, int h) { if(device == X11){ DrawLine(x1, y1-h, x1, y1+h); DrawLine(x1-h, y1, x1+h, y1); } else{ psDrawLine(x1, y1-h, x1, y1+h); psDrawLine(x1-h, y1, x1+h, y1); } } void myDrawFilledBox(int x, int y, int w, int h) { if(device == X11) DrawFilledBox(x, y, w, h); else psDrawFilledBox(x, y, w, h); } void myDrawFilledPolygon(XPoint *p, int n) { if(device == X11) DrawFilledPolygon(p, n); else psDrawFilledPolygon(p, n); } void myDrawText(char *text, int x, int y) { if(device == X11) DrawText(text, x, y); else psDrawText(text, x, y); } void drawText(char *text, float xp, float yp) { int x, y; phys2pix(&x, &y, xp, yp); if(device == X11) DrawText(text, x, y); else psDrawText(text, x, y); } void line(float *x, float *y, int n) { if(device == X11) xline(x, y, n); else psline(x, y, n); } void drawTitle(char *text) { int x1, x2, y; int l; l = TextWidth(GetWidgetFont(drawWindow), text); phys2pix(&x1, &y, 0, ymax); phys2pix(&x2, &y, xmax, ymax); myDrawText(text, x1+(x2-x1-l)/2, y - 8); } /* * Coordinate transformation functions * */ void pix2phys(int xx,int xy,float *px, float *py) { float x, y; x= (float) (xx - Xxoff)/(float)Xscl; y= (float) (ymax+ymin) - (float) (xy - Xyoff)/(float)Xscl; *px = x; *py = y; } void phys2pix(int *x, int *y, float xx, float yy) { *x = (int) ( xx * Xscl + Xxoff); *y = (int) ( (ymax+ymin-yy) * Xscl + Xyoff); } void pix2ps(int x, int y, float *xps, float *yps) { *xps = (float) x * psPixScale + psPixXoff; *yps = PAPER_HEIGTH - PAPER_TOP_MARGIN - ((float) y * psPixScale + psPixYoff); *xps = *xps * MM; *yps = *yps * MM; } void phys2ps(float x, float y, float *xps, float *yps) { int xpix, ypix; phys2pix(&xpix, &ypix, x, y); pix2ps(xpix, ypix, xps, yps); } void psPrint(char *printer, int where) { char cmd[100]; if(where == TO_PRINTER) psfile = fopen("plotBuf.ps", "w"); else psfile = fopen(printer, "w"); if(psfile != NULL){ psInit(); device = PS; doPlotting(); psDone(); fclose(psfile); if(where == TO_PRINTER){ sprintf(cmd, "lpr -P%s plotBuf.ps", printer); system(cmd); } device = X11; doPlotting(); } else errorHandler("Unable to open plotfile"); } void psInit() { psGetScale(); fprintf(psfile, "%s\n", "%!ps-adobe-2.0"); fprintf(psfile, "%s\n", "%%Creator: FEMLAB"); fprintf(psfile, "%s\n", "%%Title: FEMLAB plot"); fprintf(psfile, "%s\n", "%%Pages: 1"); fprintf(psfile, "%s\n", "%%EndComments: 1"); fprintf(psfile, "%s\n", "/mm { 2.8346 mul } def"); fprintf(psfile, "%s\n", "/l { lineto } def"); fprintf(psfile, "%s\n", "/m { moveto } def"); fprintf(psfile, "%s\n", "/c { closepath } def"); fprintf(psfile, "%s\n", "/n { newpath } def"); fprintf(psfile, "%s\n", "/s { setgray } def"); fprintf(psfile, "%s\n", "/r { setrgbcolor } def"); fprintf(psfile, "%s\n", "/k { stroke } def"); fprintf(psfile, "%s\n", "0.05 mm setlinewidth"); fprintf(psfile, "%s\n", "/Helvetica-Bold findfont"); fprintf(psfile, "%s\n", "30 scalefont"); fprintf(psfile, "%s\n", "setfont"); fprintf(psfile, "%s\n", ""); fprintf(psfile, "%s\n", "0. setgray"); fprintf(psfile, "%s\n", "76.5 mm 16.452 mm moveto"); fprintf(psfile, "%s\n", "(F E M L A B) show"); fprintf(psfile, "%s\n", "5 mm 30 mm m"); fprintf(psfile, "%s\n", "5 mm 295 mm l"); fprintf(psfile, "%s\n", "200 mm 295 mm l"); fprintf(psfile, "%s\n", "200 mm 30 mm l"); fprintf(psfile, "%s\n", "5 mm 30 mm c"); fprintf(psfile, "%s\n", "clip"); /* fprintf(psfile, "%s\n", "/Helvetica-Bold findfont"); fprintf(psfile, "%s\n", "4.56 scalefont"); fprintf(psfile, "%s\n", "setfont"); fprintf(psfile, "%s\n", "77.6 mm 14 mm moveto"); fprintf(psfile, "%s\n", "(T H E C H O I C E O F A N E W G E N E R A T I O N) show"); */ fprintf(psfile, "%s\n", "newpath"); fprintf(psfile, "%s\n", "/Courier findfont"); fprintf(psfile, "%s\n", "10 scalefont"); fprintf(psfile, "%s\n", "setfont"); } void psDone() { fprintf(psfile, "%s\n", "showpage"); } void psGetScale() { float scl; int width, height; float xoff, yoff; float ww; int nx, ny, id; if(state >= HAVE_SOLUTION){ nx = nwinx; ny = nwiny; id = winid; } else{ nx = ny = 1; id = 0; } /* First fix the pixel -> paper scale */ GetDrawAreaSize(&width, &height); width = width / nx; height = height / ny; scl = (float) 1./max(width, height); ww = min((PAPER_WIDTH - 2*PAPER_SIDE_MARGIN)/nx, (PAPER_HEIGTH-2*PAPER_TOP_MARGIN)/ny); psPixScale = ww * scl; psPixXoff = 0*PAPER_SIDE_MARGIN; psPixYoff = 0*PAPER_TOP_MARGIN; psPixXoff += (PAPER_WIDTH/nx - ( psPixScale*(width) + psPixXoff))/2 + (id+nx-1)%nx *PAPER_WIDTH/nx*scl; psPixYoff += (PAPER_HEIGTH/ny - ( psPixScale*(height) + psPixYoff))/2 + (int)(id/(nx+.5)) *PAPER_HEIGTH/ny*scl; /* */ /* Now fix the physical -> paper scale */ /* */ scl = 1./max(xmax-xmin,ymax-ymin); xoff = - xmin*scl; yoff = - ymin*scl; psPhysScale = ww * scl; psPhysXoff = ww * xoff; psPhysYoff = ww * yoff; psPhysXoff += (PAPER_WIDTH/nx - ( psPhysScale*xmax +psPhysXoff))/2 + (id+nx-1)%nx *PAPER_WIDTH/nx; psPhysYoff += (PAPER_HEIGTH/ny - ( psPhysScale*ymax +psPhysYoff))/2 + (int)(id/(nx+.5)) *PAPER_HEIGTH/ny; } /* * Color stuff * * */ mySetColor(int color) { if(have_colors == TRUE){ SetColor(color); if(color == WHITE){ psred = 0.0; psgreen = 0.0; psblue = 0.0; } else if(color == BLACK){ psred = 1.0; psgreen = 1.0; psblue = 1.0; } else if(color == RED){ psred = 1.0; psgreen = 0.0; psblue = 0.0; } else if(color == GREEN){ psred = 0.0; psgreen = 1.0; psblue = 0.0; } else if(color == BLUE){ psred = 0.0; psgreen = 0.0; psblue = 1.0; } else if(color == YELLOW){ psred = 0.0; psgreen = 1.0; psblue = 1.0; } else if(color == GREY){ psred = .8; psgreen = .8; psblue = .8; } } } void mySetMyColor(float value) { if(have_colors == TRUE){ psred = (float)red[(int) ((float)(value*ncells))]/255.; psgreen = (float)green[(int) ((float)(value*ncells))]/255.; psblue = (float)blue[(int) ((float)(value*ncells))]/255.; SetColor(cells[(int) ((float)ncells * value)]); } } /* * Postscript counterparts of plotting functions * */ void psDrawFilledBox(int x, int y, int w, int h) { float xx, yy; fprintf(psfile,"%s","n\n"); fprintf(psfile,"%s","0. s\n"); pix2ps(x, y, &xx, &yy); fprintf(psfile,"%f %f m\n", xx, yy); pix2ps(x + h, y, &xx, &yy); fprintf(psfile,"%f %f l\n", xx, yy); pix2ps(x + h, y + h, &xx, &yy); fprintf(psfile,"%f %f l\n", xx, yy); pix2ps(x, y + h, &xx, &yy); fprintf(psfile,"%f %f l\n", xx, yy); pix2ps(x, y, &xx, &yy); fprintf(psfile,"%f %f l\n", xx, yy); fprintf(psfile,"%s","c\n"); fprintf(psfile,"%s",".0 s fill\n"); } void psDrawFilledPolygon(XPoint *p, int n) { float x, y; int i; fprintf(psfile,"%s","n\n"); if(color_ps == TRUE) fprintf(psfile,"%f %f %f r\n", psred, psgreen, psblue); else fprintf(psfile,"%s","0. s\n"); pix2ps(p[0].x, p[0].y, &x, &y); fprintf(psfile,"%f %f m\n", x, y); for(i=1; i < n; i++){ pix2ps(p[i].x, p[i].y, &x, &y); fprintf(psfile,"%f %f l\n", x, y); } fprintf(psfile,"c\n"); fprintf(psfile,"fill\n"); } void psDrawText(char *text, int x, int y) { float xx, yy; fprintf(psfile,"%s","0. s\n"); pix2ps(x, y, &xx, &yy); fprintf(psfile, "%f %f m\n", xx, yy); fprintf(psfile, "(%s) show \n", text); } void psDrawLine(int x1, int y1, int x2, int y2) { float xx, yy; fprintf(psfile,"%s","n\n"); fprintf(psfile,"%s","0. s\n"); pix2ps(x1, y1, &xx, &yy); fprintf(psfile,"%.1f %.1f m\n", xx, yy); pix2ps(x2, y2, &xx, &yy); fprintf(psfile,"%.1f %.1f l\n", xx, yy); fprintf(psfile,"%s","k\n"); } void psline(float *x, float *y,int np) { float xx, yy; int i; fprintf(psfile,"%s","n\n"); if(color_ps == TRUE) fprintf(psfile,"%f %f %f r\n", psred, psgreen, psblue); else fprintf(psfile,"%s","0. s\n"); phys2ps(*x++, *y++, &xx, &yy); fprintf(psfile,"%.1f %.1f m\n", xx, yy); for(i = 1; i < np; i++){ phys2ps(*x++, *y++, &xx, &yy); fprintf(psfile,"%.1f %.1f l\n", xx, yy); } fprintf(psfile,"%s","k\n"); } void getDrawBox() { int i, j, n, nb; PTS_NODE *p; if(zoomActive == FALSE && state <= HAVE_BOUNDARY){ xmin = xmin_orig; xmax = xmax_orig; ymin = ymin_orig; ymax = ymax_orig; } if(zoomActive == FALSE && state >= HAVE_MESH){ xmin = 10000; ymin = 10000; xmax = -10000; ymax = -10000; FOR_ALL_POINTS(p){ xmin = min(xmin, p->physicalX); ymin = min(ymin, p->physicalY); xmax = max(xmax, p->physicalX); ymax = max(ymax, p->physicalY); } if(zoomActive == FALSE && state >= HAVE_SOLUTION){ xmin = 10000; ymin = 10000; xmax = -10000; ymax = -10000; for(i=0; i < mySol[currentSolution].nnode; i++){ xmin = min(xmin, mySol[currentSolution].coord[i][0]); ymin = min(ymin, mySol[currentSolution].coord[i][1]); xmax = max(xmax, mySol[currentSolution].coord[i][0]); ymax = max(ymax, mySol[currentSolution].coord[i][1]); } } } } void xline(float *x,float *y, int np) { int i; XPoint *pp, *pts; pts = (XPoint *) malloc( np * sizeof(XPoint) ); pp = pts; for(i = 0; i < np; i++) { pp[i].x = (int) ( *x++ * Xscl + Xxoff); pp[i].y = (int) ( (ymax+ymin-*y++) * Xscl + Xyoff); } DrawPolyline(pp, np); free(pts); } void fill(float *x,float *y, int np) { int i; XPoint *pp, *pts; pts = (XPoint *) malloc( np * sizeof(XPoint) ); pp = pts; for(i = 0; i < np; i++) { pp[i].x = (int) ( *x++ * Xscl + Xxoff); pp[i].y = (int) ( (ymax+ymin-*y++) * Xscl + Xyoff); } DrawFilledPolygon(pp, np); free(pts); } void arrow(float xr1, float yr1, float xr2, float yr2) { float x[5], y[5]; double dx, dy, d1, d; x[0]=xr2; x[1]=xr1; y[0]=yr2; y[1]=yr1; line(x,y,2); dx=xr2-xr1; dy=yr2-yr1; d1=sqrt(dx*dx+dy*dy); d = .1 * d1; if(d1 != 0.){ dx=dx/d1; dy=dy/d1; x[1]=xr2+(-dy-dx)*d; y[1]=yr2+(dx-dy)*d; x[2]=xr2; y[2]=yr2; x[3]=xr2+(dy-dx)*d; y[3]=yr2+(-dx-dy)*d; x[4]=xr2; y[4]=yr2; line(x,y,5); } } void setClipRect(int x1, int y1, int x2, int y2) { XRectangle box[1]; Display *dpy; int fore_g,back_g; /* Fore and back ground pixels */ GC drawgc; dpy = (Display *) XtDisplay(drawWindow); back_g = WhitePixel(XtDisplay(drawWindow),DefaultScreen(XtDisplay(drawWindow))); fore_g = BlackPixel(XtDisplay(drawWindow),DefaultScreen(XtDisplay(drawWindow))); /* Create drawing GC */ drawgc = XCreateGC(XtDisplay(drawWindow), DefaultRootWindow(XtDisplay(drawWindow)), 0, 0); box[0].x = x1; box[0].y = y1; box[0].width = x2 - x1; box[0].height = y2 - y1; printf("%i %i %i %i\n", x1, y1, x2, y2); XSetClipRectangles(dpy, drawgc, 0, 0, box, 1, Unsorted); } void getDrawingScale() { float xoff, yoff; float scl; int width, height; int ww; int nx, ny, id; if(state >= HAVE_MESH) getDrawBox(); if(state >= HAVE_SOLUTION){ nx = nwinx; ny = nwiny; id = winid; } else{ nx = ny = 1; id = 0; } GetDrawAreaSize(&width, &height); width = width / nx; height = height / ny; if(state > HAVE_NOTHING){ scl = 1./max(xmax-xmin,ymax-ymin); xoff = -scl*(xmin+.5*(xmax-xmin)-.5/scl); yoff = -scl*(ymin+.5*(ymax-ymin)-.5/scl); xoff = - xmin*scl*.85; yoff = - ymin*scl*.85; ww = min(width, height); Xscl = (int) ((float)ww * 0.85 * scl); Xxoff = (int) ww * xoff ; Xyoff = (int) ww * yoff; Xxoff += (int) (width - ( Xscl*xmax +Xxoff))/2 + (id+nx-1)%nx *width; Xyoff += (int) (height - ( Xscl*ymax +Xyoff))/2 + (int)(id/(nx+.5)) *height; } SetDrawArea(drawWindow); if(device == PS) psGetScale(); } void getBoundaryScale(Widget w, void *data) { int ww=0, hh=0; TagList tags[] = { {TAG_WINDOW_LABEL, "Define the size of your domain ", NULL , TAG_INIT}, {TAG_LABEL, "Before the boundary can be defined", NULL, TAG_NOINIT}, {TAG_LABEL, "You must specify the size of your domain", NULL, TAG_NOINIT}, {TAG_FLOAT, "min X: ", &xmin, TAG_INIT}, {TAG_FLOAT, "max X: ", &xmax, TAG_INIT}, {TAG_FLOAT, "min Y: ", &ymin, TAG_INIT}, {TAG_FLOAT, "max Y: ", &ymax, TAG_INIT}, {TAG_DONE, NULL , NULL, TAG_NOINIT} }; xmax = 1.; ymax = 1.; xmin = 0.; ymin = 0.; if(GetValues(tags)) printf("Cancelled\n"); getDrawingScale(); if(state == HAVE_NOTHING) state = HAVE_SCALE; xmin_orig = xmin; xmax_orig = xmax; ymin_orig = ymin; ymax_orig = ymax; redisplay(w, ww, hh, data); naca(w, data); } void freeMyColorMap(int n) { int i; for(i = 0; i < n ; i++) FreePrivateColor(cells[i]); } int setUpMycolorMap(int ncolor) { double h, s, v, r, g, b; int i, n; n = ncolor; freeMyColorMap(ncells); /* Get all available colors */ i = 0; while( (cells[i++] = GetPrivateColor()) != -1 ); n = i - 1; ncells = n; h=1.; s=1.; v=1.; for(i = 0; i < n ; i++){ h = 1.0 - 1.0* (float)i /( n ); /* h = .5 + .5*h;*/ rainbow(&h,&s,&v,&r,&g,&b); red[i] = 255*r; green[i] = 255*g; blue[i] = 255*b; } for(i = 0; i < n ; i++) SetPrivateColor(cells[i], red[i], green[i], blue[i]); return n; } /* rainbow(h, s, v, r, g, b) double h, s, v, *r, *g, *b; This routine computes colors suitable for use in color level plots. Typically s=v=1 and h varies from 0 (red) to 1 (blue) in equally spaced steps. (h=.5 gives green; 1