/[MITgcm]/MITgcm_contrib/darwinview/src/darwin.c
ViewVC logotype

Contents of /MITgcm_contrib/darwinview/src/darwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download)
Mon Jul 16 19:16:26 2007 UTC (18 years ago) by marissa
Branch: MAIN
Changes since 1.4: +112 -51 lines
File MIME type: text/plain
yz capability!

1 #include <GL/glut.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <math.h>
6 #define WINDOW "image"
7 #define UP 101
8 #define DOWN 103
9 #define RIGHT 102
10 #define LEFT 100
11 #define MAX 700
12
13 int NX, NY, NZ;
14
15 void do_byteswap_f32( float arr[], int nel ), global(), local( int, int, int );
16 void readnames( char[] ), readarray( float[], char[], int ), readjet(), readxz( float[], char[] );
17 void readyz( float[], char[] );
18 void TimerFunction( int ), bitmap( char[], int, int );
19
20 float data[MAX][MAX*MAX], mxval, mnval, jet[64][3];
21 float globalmx=0, globalmn=100;
22 int win[MAX], ilev=1, howmany, sets, count=0, glo=0, usr=0, anim=0, logscale=0, xz=0, nonegs=1, endian=0;
23 int xmax, ymax, yoffset=0, xoffset=0, yz=0;
24 char initfns[MAX][MAX], fns[MAX][MAX][MAX];
25
26 void menu(int value){ // called when menu is opened on right click
27
28 switch( value ){
29 case 1: usr=glo=0; // unset glo & usr, sets local max/min
30 glutPostRedisplay(); // recall display func with new values
31 break;
32 case 2: glo=1; // enables global max/min
33 usr=0; // unsets usr
34 mxval=globalmx; // sets max to globalmx
35 mnval=globalmn; // sets min to globalmn
36 glutPostRedisplay(); // recall display func with new values
37 break;
38 case 3: usr=1; // switch to user-set max/min
39 glo=0; // unset glo
40 printf( "Max=" ); scanf( "%f", &mxval ); // prompt user for new max
41 printf( "Min=" ); scanf( "%f", &mnval ); // prompt user for new min
42 glutPostRedisplay(); // recall display func with new values
43 break;
44 case 4: logscale=(logscale+1)%2; // switch log scale on/off
45 glutPostRedisplay();
46 break;
47 case 5: nonegs=(nonegs+1)%2; // switch allowance of negatives on/off
48 glutPostRedisplay();
49 break;
50 case 6: endian=(endian+1)%2; // switch between big/little endian
51 glutPostRedisplay();
52 break;
53 }
54 }
55 void display(){ // called on glutPostRedisplay
56 int i, j, ioff, q;
57 float r, g, b, k, y;
58 double num, logmx, logmn;
59 char str[MAX];
60
61 for( q=0; q<sets; q++ ){ // runs display func for each subwindow
62 glutSetWindow( win[q] ); // sets which subwindow to display to
63 glClear( GL_COLOR_BUFFER_BIT ); // background to black
64 if( xz ) { xmax=NX; ymax=NZ; }
65 else{
66 if( yz ){ xmax=NY; ymax=NZ; }
67 else { xmax=NX; ymax=NY; }
68 }
69
70 if( glo || usr ){ // if global or user-set max/min
71 if( xz )
72 readxz( data[q], fns[q][count] );
73 else{
74 if( yz )
75 readyz( data[q], fns[q][count] );
76 else
77 readarray( data[q], fns[q][count], ilev ); // read new array w/o calculating local max/min
78 }
79 }
80 else // if local max/min is set
81 local( q, count, ilev ); // read new array and calculate local max/min
82
83 if( logscale ){
84 if( usr ){
85 logmx=(double)mxval;
86 logmn=(double)mnval;
87 }
88 else{
89 logmx=log10( mxval );
90 logmn=log10( mnval );
91 }
92 }
93
94 ioff=0; // ioff will count both i&j b/c data is 1D
95 for( j=0; j<ymax; j++ ){ // cycles through y values
96 for( i=0; i<xmax; i++ ){ // cycles through x values
97 r=g=b=0; // set color values to black
98 if( data[q][ioff]==0 ); // if data=0, values stay black
99 else{
100 if( logscale ){
101 num=(double)data[q][ioff];
102 num=log10( num );
103 if( num<logmn ) num=0;
104 else{
105 if( num>logmx ) num=63;
106 else
107 num=63*( num-logmn )/( logmx-logmn );
108 }
109 }
110 else{
111 if( data[q][ioff]<mnval ) num=0; // if data is less than min, =min
112 else{
113 if( data[q][ioff]>mxval ) num=63; // if data is more than max, =max
114 else
115 num=63*( data[q][ioff]-mnval )/( mxval-mnval ); // scale num from 0-63 (not defined for 64)
116 }
117 }
118 r=jet[(int)num][0]; // set red val
119 g=jet[(int)num][1]; // set green val
120 b=jet[(int)num][2]; // set blue val
121 }
122
123 glColor3f( r, g, b ); // put r, g, b into effect
124 glRectf( i, j, i+1, j+1 ); // draws a square for data value
125 ioff++;
126 }
127 }
128 glColor3f( 1, 1, 1 ); // set color to white
129 glRectf( xmax, 0, xmax+1, ymax+1 ); // draws a border
130 glRectf( 0, ymax, xmax, ymax+1 ); // draws a border
131 for( i=0; i<64; i++ ){ // draws color bar
132 glColor3f( jet[i][0], jet[i][1], jet[i][2]); // sets color
133 k=(float)i; // turns i into a float
134 y=(float)ymax/64; // sets height of rectangles
135 glRectf( xmax+10, y*k, xmax+20, (k+1)*y ); // draws rectangle
136 }
137 glColor3f( 1, 1, 1 ); // color to white
138
139 if( logscale )
140 sprintf( str, "%.2f", logmx );
141 else
142 sprintf( str, "%.1e", mxval ); // labels color bar with max val
143 bitmap( str, xmax+2, ymax-1 );
144
145 if( logscale )
146 sprintf( str, "%.2f", logmn );
147 else
148 sprintf( str, "%.1e", mnval ); // labels color bar with min val
149 bitmap( str, xmax+2, 1 );
150
151 if( xz )
152 sprintf( str, "Y-coordinate=%d", yoffset+1);
153 else{
154 if( yz )
155 sprintf( str, "X-coordinate=%d", xoffset+1);
156 else
157 sprintf( str, "Level %d", ilev ); // labels current level
158 }
159 bitmap( str, 1, ymax+3 );
160
161 sprintf( str, "Time %d", count+1 ); // labels current time
162 bitmap( str, 80, ymax+3 );
163
164 if( glo ) // labels how max/min have been set
165 sprintf( str, "Global" ); // if glo is set, display Global
166 if( usr )
167 sprintf( str, "User-set" ); // if usr is set, display User-set
168 if( !usr && !glo )
169 sprintf( str, "Local" ); // else display Local
170 bitmap( str, xmax+12, ymax+3 );
171
172 if( anim ){ // tell user if autoplay is on
173 sprintf( str, "Autoplay" );
174 bitmap( str, xmax-25, ymax+3 );
175 }
176
177 if( logscale ){
178 sprintf( str, "Log Scale" ); // tell user if log scale is on
179 bitmap( str, xmax-25, ymax+10 );
180 }
181
182 bitmap( fns[q][count], 1, ymax+10 ); // labels current file
183
184 glutSwapBuffers(); // double buffering set to animate smoothly
185 glFlush();
186 }
187 }
188
189 void bitmap( char str[], int x, int y ){ // called to display text onscreen
190 int i;
191
192 glRasterPos2f( x, y ); // set position of text
193 for( i=0; i<strlen( str ); i++) // display each character of str
194 glutBitmapCharacter( GLUT_BITMAP_HELVETICA_12, str[i] );
195 }
196
197 void key( unsigned char key, int x, int y ){ // called on key press
198 int i, tmp;
199
200 switch(key){
201 case 'q': exit(0); // quits on 'q'
202 break;
203 case 'r': count=0; // resets back to first time
204 ilev=1; // and first level
205 glutPostRedisplay();
206 break;
207 case 'a': anim=(anim+1)%2; // turns anim on/off
208 glutPostRedisplay();
209 break;
210 case 'x': xz=(xz+1)%2;
211 yz=0;
212 glutPostRedisplay();
213 break;
214 case 'y': yz=(yz+1)%2;
215 xz=0;
216 glutPostRedisplay();
217 }
218 }
219
220 void TimerFunction( int value ){ // called when anim is set and arrow key is pressed
221 int i;
222
223 switch(value){ // increments in the correct direction
224 case DOWN : if( xz && yoffset>0 )
225 yoffset--;
226 else{
227 if( yz && xoffset<NX-1 )
228 xoffset++;
229 else
230 if( ilev<NZ && !xz && !yz )
231 ilev++; // if down arrow pressed, move down a level
232 }
233 break;
234 case UP : if( xz && yoffset<NY-1 )
235 yoffset++;
236 else{
237 if( yz && xoffset>0 )
238 xoffset--;
239 else
240 if( ilev>1 && !xz && !yz )
241 ilev--; // if up arrow is pressed, move up a level
242 }
243 break;
244 case LEFT : if( count>0 )
245 count--; // if left arrow is pressed, move back one time step
246 break;
247 case RIGHT: if( count<howmany-1 )
248 count++; // if right arrow is pressed, moves forward one time step
249 break;
250 }
251
252 glutPostRedisplay();
253
254 if ( anim )
255 switch( value ){
256 case DOWN : if( xz && yoffset==0 )
257 yoffset=NY-1;
258 else{
259 if( yz && xoffset==NX-1 )
260 xoffset=0;
261 else
262 if( ilev==NZ && !xz && !yz )
263 ilev=1; // if end reached, restart
264 }
265 glutTimerFunc( 100, TimerFunction, value ); // recalls itself
266 break;
267 case UP : if( xz && yoffset==NY-1 )
268 yoffset=0;
269 else{
270 if( yz && xoffset==0 )
271 xoffset=NX-1;
272 else
273 if( ilev==1 )
274 ilev=NZ; // if end reached, restart
275 }
276 glutTimerFunc( 100, TimerFunction, value ); // recalls itself
277 break;
278 case LEFT : if( count==0 ) count=howmany-1; // if end reached, restart
279 glutTimerFunc( 100, TimerFunction, value ); // recalls itself
280 break;
281 case RIGHT: if( count==howmany-1 ) count=0; // if end reached, restart
282 glutTimerFunc( 100, TimerFunction, value ); // recalls itself
283 break;
284 }
285 }
286
287 void specialkey( int key, int x, int y ){
288 int i;
289
290 if( anim ) // if animation is set, call the timer function
291 glutTimerFunc( 100, TimerFunction, key); // to scroll automatically
292
293 switch(key){
294 case DOWN : if( xz && yoffset>0 )
295 yoffset--;
296 else{
297 if( yz && xoffset<NY-1 )
298 xoffset++;
299 else
300 if( ilev<NZ && !xz && !yz ) // if you haven't reached the bottom
301 ilev++; // keep going down
302 }
303 break;
304 case UP : if( xz && yoffset<NY-1 )
305 yoffset++;
306 else{
307 if( yz && xoffset>0 )
308 xoffset--;
309 else
310 if( ilev>1 ) // if you haven't reached the top
311 ilev--; // keep going up
312 }
313 break;
314 case RIGHT : if( count<howmany-1 ) // if you haven't reached the last file
315 count++; // keep going right
316 break;
317 case LEFT : if( count>0 ) // if you haven't reached the first file
318 count--; // keep going left
319 break;
320 }
321 glutPostRedisplay();
322 }
323
324 void global(){ // calculates the max/min for the total data set
325 FILE* fp;
326 int h, i, j;
327 for( h=0; h<sets; h++) // cycles through each window
328 for( i=0; i<howmany; i++ ) // cycles through each time
329 for( j=0; j<NZ; j++ ){ // cycles through each level for each file
330 local( h, i, j ); // calculates local max/min for specific data set
331 if( mxval > globalmx ) globalmx = mxval; // sets highest value to globalmx
332 if( mnval < globalmn ) globalmn = mnval; // sets lowest value to globalmn
333 }
334 }
335
336 void local( int i, int time, int lev ){ // calculates local max/min
337 int j;
338
339 mxval=0;
340 mnval=100;
341 if( xz )
342 readxz( data[i], fns[i][time]);
343 else{
344 if( yz )
345 readyz( data[i], fns[i][time]);
346 else
347 readarray( data[i], fns[i][time], lev ); // read new array of data
348 }
349 for( j=0; j<xmax*ymax; j++ ){
350 if( data[i][j] > mxval )
351 mxval=data[i][j]; // set largest val to mxval
352 if( data[i][j] < mnval && data[i][j]!=0 )
353 mnval=data[i][j]; // set smallest positive val to mnval
354 }
355 }
356
357 void readnames( char filename[] ){ // reads in list of filenames
358 FILE* fp;
359 int i=0, j=0;
360
361 fp=fopen( filename, "r" ); // opens list of filenames
362 while( !feof(fp) ){ // reads until the end of the file
363 fscanf( fp, "%s", initfns[i] ); // places filename into an array of strings
364 i++; // counts how many filenames there are
365 }
366 fclose( fp ); // close file
367 sets=i-1; // saves number of initial filenames
368
369 for(i=0; i<sets; i++){ // goes through each read-in filename
370 fp=fopen( initfns[i], "r" ); // opens each filename
371 j=0;
372 while( !feof(fp) ){ // reads in filenames from each filename
373 fscanf( fp, "%s", fns[i][j]);
374 j++;
375 }
376 fclose(fp); // close file
377 }
378 howmany=j-1; // saves number of data filenames
379 }
380
381 void readjet(){ //reads in color scale values
382 FILE* fp;
383 int i, j;
384
385 fp=fopen( "jet.dat", "r" ); // opens file containing values
386 for( i=0; i<64; i++ ) // reads in 64 sets of r, g, b values
387 for( j=0; j<3; j++ )
388 fscanf( fp, "%f", &jet[i][j] );
389 fclose( fp ); // closes file
390 }
391
392 void readxz( float arr[], char filename[] ){
393 int i, j;
394 float tmp[MAX][MAX], tmp2[MAX*MAX];
395 FILE* fp;
396
397 fp=fopen( filename, "rb" );
398 for( i=0; i<NZ; i++){
399 fseek( fp, (NX*yoffset*4)+(i*NX*NY*4), SEEK_SET );
400 fread( &arr[NX*i], sizeof( arr[0] ), NX, fp ); // reads in data to fill one level
401 }
402 fclose( fp );
403
404 for( i=0; i<NZ; i++ )
405 for( j=0; j<NX; j++)
406 tmp[i][j]=arr[i*NX+j];
407
408 for( i=0; i<NZ; i++ )
409 for( j=0; j<NX; j++)
410 tmp2[i*NX+j]=tmp[NZ-i-1][j];
411
412 for( i=0; i<NX*NZ; i++)
413 arr[i]=tmp2[i];
414 }
415
416 void readyz( float arr[], char filename[] ){
417 int i, j;
418 float tmp[MAX][MAX], tmp2[MAX*MAX];
419 FILE* fp;
420
421 fp=fopen( filename, "rb" );
422 for( i=0; i<NY*NZ; i++ ){
423 fseek( fp, (xoffset*4)+(i*NX*4), SEEK_SET );
424 fread( &arr[i], sizeof( arr[0] ), 1, fp );
425 }
426 fclose(fp);
427
428 for( i=0; i<NZ; i++ )
429 for( j=0; j<NY; j++)
430 tmp[i][j]=arr[i*NY+j];
431
432 for( i=0; i<NZ; i++ )
433 for( j=0; j<NY; j++)
434 tmp2[i*NY+j]=tmp[NZ-i-1][j];
435
436 for( i=0; i<NY*NZ; i++)
437 arr[i]=tmp2[i];
438 }
439
440 void readarray( float arr[], char filename[], int il ){ // reads new data
441 FILE* fp;
442 int i;
443
444 fp=fopen( filename, "rb" ); // opens the file containing data
445 fseek( fp, (il-1)*NX*NY*4, SEEK_SET ); // seeks to the correct place using ilev
446 fread( arr, sizeof( arr[0] ), NX*NY, fp ); // reads in data to fill one level
447 fclose( fp ); // close file
448
449 if( nonegs )
450 for( i=0; i<NX*NY; i++ )
451 if( arr[i] < 0 )
452 arr[i] = pow(10, -20); // sets negative values to 10^-20
453
454 if( endian )
455 do_byteswap_f32( arr, NX*NY ); // switches endian
456 }
457
458 void do_byteswap_f32( float arr[], int nel ){ // switches endian
459
460 int i;
461 char src[4], trg[4];
462
463 for( i=0; i<nel; i++ ){
464 memcpy( src, &(arr[i]), 4 );
465 trg[0]=src[3];
466 trg[1]=src[2];
467 trg[2]=src[1];
468 trg[3]=src[0];
469 memcpy( &(arr[i]), trg, 4 );
470 }
471 }
472
473 void black(){
474 glClear( GL_COLOR_BUFFER_BIT );
475 glutSwapBuffers();
476 glFlush();
477 }
478
479 int main( int argc, char *argv[] ){
480 int i, setsx, setsy, tmpx, tmpy, winx, winy, parent;
481 char filename[MAX];
482
483 sscanf( argv[1], "%dx%d", &winx, &winy ); // reads screen resolution from command line
484 winy-=60; winx-=20; // adjusts resolution so edges won't get cut off
485
486 printf( "Please enter x, y and z dimensions.\n" );
487 scanf( "%d %d %d", &NX, &NY, &NZ ); // prompts user for NX, NY, NZ
488 printf( "Please enter filename.\n" );
489 scanf( "%s", filename ); // prompts user for initial filenames
490 printf( "Please enter dimensions of data sets.\n" );
491 scanf( "%dx%d", &setsx, &setsy ); // prompts user for dimensions of subwindows
492
493 xmax=NX; ymax=NY;
494
495 readjet(); // stores color values
496 readnames( filename ); // gets list of filenames to read from
497 global(); // calculates max and min for all data
498
499 glutInit( &argc, argv );
500 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); // sets rgb mode and double buffering
501 glutInitWindowSize( winx, winy ); // parent window will cover screen
502 glutInitWindowPosition( 10, 10 ); // location of parent window
503 parent=glutCreateWindow( WINDOW ); // creates parent window
504
505 glClearColor( 0, 0, 0, 0 ); // sets clear color to black
506 gluOrtho2D( 0, winx , winy, 0 ); // sets(0,0) as top left corner
507 glutDisplayFunc( display );
508 glutKeyboardFunc( key ); // called on key press
509 glutSpecialFunc( specialkey ); // called on special key press (arrow keys)
510
511
512 for( i=0; i<setsx*setsy; i++ ){
513 tmpx = (i%setsx)*(winx/setsx); // x coordinate of top left corner of subwindow
514 tmpy = (i/setsx)*(winy/setsy); // y coordinate of top left corner of subwindow
515
516 win[i]=glutCreateSubWindow( parent, tmpx, tmpy, winx/setsx, winy/setsy ); // creates subwindow
517 gluOrtho2D( 0, NX+35, 0, NY+15 ); // sets how data is mapped to subwindow
518 glutKeyboardFunc( key ); // called on key press
519 glutSpecialFunc( specialkey ); // called on special key press (arrow keys)
520 if( i >= sets ) //
521 glutDisplayFunc( black );
522 else
523 glutDisplayFunc( display ); // sets display func for subwindow
524
525
526 glutCreateMenu( menu ); // adds a menu
527 glutAddMenuEntry( "Local Color Scale", 1 ); // adds a menu entry
528 glutAddMenuEntry( "Global Color Scale", 2 ); // adds a menu entry
529 glutAddMenuEntry( "User-Set Color Scale", 3 ); // adds a menu entry
530 glutAddMenuEntry( "Log Scale (on/off)", 4 ); // adds a menu entry
531 glutAddMenuEntry( "Allow Negatives (on/off)", 5 ); // adds a menu entry
532 glutAddMenuEntry( "Switch Endian (big/little) ", 6); // adds a menu entry
533 glutAttachMenu( GLUT_RIGHT_BUTTON ); // menu called on right click
534 }
535
536 glutMainLoop(); // begin processing events
537 return 0;
538 }
539

  ViewVC Help
Powered by ViewVC 1.1.22