/[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.4 - (show annotations) (download)
Mon Jul 16 15:40:16 2007 UTC (18 years ago) by marissa
Branch: MAIN
Changes since 1.3: +107 -37 lines
File MIME type: text/plain
xz version

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

  ViewVC Help
Powered by ViewVC 1.1.22