PUMA
219
Portable University Model of the Atmosphere
|
00001 /* 00002 pumax - a GUI for PUMA & PLASIM 00003 (c) 2007 Edilbert Kirk (E.Kirk@gmx.de) 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 */ 00019 00020 int Debug = 0; // set in initgui 00021 00022 #include <ctype.h> 00023 #include <stdio.h> 00024 #include <string.h> 00025 #include <stdlib.h> 00026 #include <math.h> 00027 #include <sys/time.h> 00028 #include <sys/resource.h> 00029 #include <X11/Xlib.h> 00030 #include <X11/Xutil.h> 00031 #include <X11/Xos.h> 00032 #include <X11/Xatom.h> 00033 #include <X11/keysym.h> 00034 00035 #define INT int 00036 #define REAL float 00037 #define INTXU unsigned int 00038 #define INTXS int 00039 00040 #ifndef MIN 00041 #define MIN(a,b) ((a) < (b) ? (a) : (b)) 00042 #endif 00043 00044 #ifndef MAX 00045 #define MAX(a,b) ((a) > (b) ? (a) : (b)) 00046 #endif 00047 00048 #define ROTATE_LEFT (XK_Left) 00049 #define ROTATE_RIGHT (XK_Right) 00050 00051 #define TOLELO 0x0001 00052 #define TOLEHI 0x0002 00053 #define TORILO 0x0004 00054 #define TORIHI 0x0008 00055 #define BOLELO 0x0010 00056 #define BOLEHI 0x0020 00057 #define BORILO 0x0040 00058 #define BORIHI 0x0080 00059 #define TOLEIN 0x0100 00060 #define TOREIN 0x0200 00061 #define BOLEIN 0x0400 00062 #define BOREIN 0x0800 00063 00064 #define IPX(l,m,h) (VGAX * (x + (l-m) / (l-h))) 00065 #define IPY(l,m,h) (VGAY * (y + (l-m) / (l-h))) 00066 00067 #define NUMWIN 9 00068 #define NUMPAL 13 00069 00070 /* Picture types */ 00071 00072 #define ISOHOR 0 00073 #define ISOCS 1 00074 #define ISOHOV 2 00075 #define ISOTS 3 00076 #define ISOTAB 4 00077 #define ISOSH 5 00078 #define ISOLON 6 00079 #define ISOTRA 7 00080 #define ISOCOL 8 00081 #define ISOROT 9 00082 #define MAPHOR 10 00083 #define MAPTRA 11 00084 00085 /* Models */ 00086 00087 #define PUMA 0 00088 00089 char *IsoNames[] = 00090 { 00091 "ISOHOR", 00092 "ISOCS", 00093 "ISOHOV", 00094 "ISOTS", 00095 "ISOTAB", 00096 "ISOSH", 00097 "ISOLON", 00098 "ISOTRA", 00099 "ISOCOL", 00100 "ISOROT", 00101 "MAPHOR", 00102 "MAPTRA" 00103 }; 00104 00105 int IsoTypes = sizeof(IsoNames) / sizeof(char *); 00106 00107 char *PalNames[] = 00108 { 00109 "AUTO", 00110 "U", 00111 "V", 00112 "T", 00113 "P", 00114 "Q", 00115 "MARST", 00116 "AMPLI", 00117 "VEG", 00118 "OCET", 00119 "OCES", 00120 "DCC", 00121 "DTDT" 00122 }; 00123 00124 int PalTypes = sizeof(PalNames) / sizeof(char *); 00125 00126 /* Map projections */ 00127 00128 #define CYLINDRICAL 0 00129 #define POLAR 1 00130 #define AZIMUTHAL 2 00131 00132 #define MAXMAPS 3 00133 00134 char *ProNames[] = 00135 { 00136 "CYLINDRICAL", 00137 "POLAR", 00138 "AZIMUTHAL" 00139 }; 00140 00141 00142 /* Coordinates of button areas */ 00143 00144 int ShowQueue = 0; 00145 int ShowOnce = 1; 00146 int OffsetY = 20; 00147 00148 int Stop_XL; 00149 int Stop_XH; 00150 int Stop_YL; 00151 int Stop_YH; 00152 00153 int Start_XL; 00154 int Start_XH; 00155 int Start_YL; 00156 int Start_YH; 00157 00158 int Pause_XL; 00159 int Pause_XH; 00160 int Pause_YL; 00161 int Pause_YH; 00162 00163 int Help_XL; 00164 int Help_XH; 00165 int Help_YL; 00166 int Help_YH; 00167 00168 int Minus_XL; 00169 int Minus_XH; 00170 int Minus_YL; 00171 int Minus_YH; 00172 00173 int FBWD_XL; 00174 int FBWD_XH; 00175 int FBWD_YL; 00176 int FBWD_YH; 00177 00178 int Plus_XL; 00179 int Plus_XH; 00180 int Plus_YL; 00181 int Plus_YH; 00182 00183 int FFWD_XL; 00184 int FFWD_XH; 00185 int FFWD_YL; 00186 int FFWD_YH; 00187 00188 int Parc_XL; 00189 int Parc_XH; 00190 int Parc_XD; 00191 int Parc_YL; 00192 int Parc_YH; 00193 int Parc_YD; 00194 00195 int Wbox_XL; 00196 int Wbox_XH; 00197 int Wbox_YL; 00198 int Wbox_YH; 00199 00200 int Grid_XL; 00201 int Grid_XH; 00202 int Grid_YL; 00203 int Grid_YH; 00204 00205 XPoint StopButton[4] = {{10,10},{40,10},{40,40},{10,40}}; 00206 XPoint StartButton[3] = {{50,10},{80,25},{50,40}}; 00207 XPoint PauseButton1[4] = {{95,10},{102,10},{102,40},{95,40}}; 00208 XPoint PauseButton2[4] = {{108,10},{115,10},{115,40},{108,40}}; 00209 00210 #define PARCS 100 00211 00212 struct ParcStruct 00213 { 00214 char Name[8]; 00215 float Inc; 00216 float Min; 00217 float Max; 00218 float Val; 00219 }; 00220 00221 int Parcs; 00222 int cpi = 1; 00223 00224 struct ParcStruct Parc[PARCS]; 00225 00226 int screen_num; 00227 00228 Display *display; 00229 unsigned int ScreenW,ScreenH,ScreenBot; 00230 int SmallScreen; 00231 00232 static char *progname = "PUMA"; 00233 00234 int BigEndian; 00235 int ScreenOffset; 00236 int Model; 00237 int CowX = -1; 00238 int CowY = -1; 00239 int CowW; 00240 int CowH; 00241 int NumWin = NUMWIN; 00242 int WinCols = 3; 00243 int WinRows = 3; 00244 int DimT = 100; // Default length of time axis 00245 int DimX; 00246 int DimY; 00247 int DimZ; 00248 int DimXY; 00249 int Uindex = -1; 00250 int Vindex = -1; 00251 int ScreenD; 00252 int OffX; 00253 int OffY = 0; 00254 INTXU WinXSize; 00255 INTXU WinYSize; 00256 int InXSize; 00257 int InYSize; 00258 int Latitudes; 00259 int Lines; 00260 int SizeChanged; 00261 int Shutdown; 00262 int Grid = 1; 00263 int GridLabel = 1; 00264 int WhitePix; 00265 int BlackPix; 00266 int *Flag; 00267 int FlagSize; 00268 int nstep; 00269 int MRpid; 00270 int MRnum; 00271 int wto; 00272 int FirstKey; 00273 int LastKey; 00274 int SymsPerKey; 00275 00276 KeySym *KeyMap; 00277 00278 char wtrun[8]; 00279 00280 unsigned Seed; 00281 00282 float RotInc = 0.2; 00283 int LineCo[NUMPAL]; 00284 int MapPro[NUMWIN]; 00285 int HovInx[NUMWIN]; 00286 int Indez[NUMWIN]; 00287 int MaxZ[NUMWIN]; 00288 int RedrawFlag[NUMWIN]; 00289 int LevelChanged[NUMWIN]; 00290 int RotLon[NUMWIN]; 00291 double AutoDelta[NUMWIN]; 00292 double AutoXdelt[NUMWIN]; 00293 double AutoLo[NUMWIN]; 00294 REAL *TSdata[NUMWIN]; 00295 REAL *Dmin[NUMWIN]; 00296 REAL *Dmax[NUMWIN]; 00297 REAL *SpeedScale; 00298 XPoint *TSxp[NUMWIN]; 00299 00300 00301 #define MAXPAR 16384 00302 float pax[MAXPAR]; 00303 float pay[MAXPAR]; 00304 long pal[MAXPAR]; 00305 00306 int Delpar = 8; /* Interval for particle injection */ 00307 int ParInd = 0; 00308 int ColInd = 0; 00309 long TracerColor; 00310 00311 #define NUMSCALARS 9 00312 00313 char TSName[NUMSCALARS][80]; 00314 char TSubsc[NUMSCALARS][80]; 00315 char TSUnit[NUMSCALARS][80]; 00316 char TScale[NUMSCALARS][80]; 00317 00318 struct PixStruct 00319 { 00320 int DimX; 00321 int DimY; 00322 Pixmap Pix; 00323 } WinPixMap[NUMWIN]; 00324 00325 Pixmap pix; 00326 00327 #define NUMARRAYS 100 00328 00329 struct ArrayStruct 00330 { 00331 char Name[80]; 00332 float *Data; 00333 int DimX; 00334 int DimY; 00335 int DimZ; 00336 int Flag; 00337 } Array[NUMARRAYS]; 00338 00339 int NumArrays; 00340 00341 struct WinAttStruct 00342 { 00343 unsigned int x; 00344 unsigned int y; 00345 unsigned int w; 00346 unsigned int h; 00347 int active; 00348 char array_name[80]; 00349 int Plot; 00350 int Palette; 00351 } WinAtt[NUMWIN]; 00352 00353 int BorderWidth = 0; 00354 int WM_top_area = 0; // Window manager top area 00355 int WinLM = 0; 00356 int WinRM = 0; 00357 int WinTM = 24; 00358 int WinBM = 0; 00359 00360 struct ColorStrip 00361 { 00362 double Lo; 00363 double Hi; 00364 char *Name; 00365 unsigned long pixel; 00366 }; 00367 00368 #define AUTOCOLORS 14 00369 struct ColorStrip Autostrip[AUTOCOLORS+1] = 00370 { 00371 {0.0,0.0,"red"}, 00372 {0.0,0.0,"OrangeRed"}, 00373 {0.0,0.0,"Orange"}, 00374 {0.0,0.0,"yellow"}, 00375 {0.0,0.0,"GreenYellow"}, 00376 {0.0,0.0,"green"}, 00377 {0.0,0.0,"aquamarine"}, 00378 {0.0,0.0,"cyan"}, 00379 {0.0,0.0,"SkyBlue"}, 00380 {0.0,0.0,"blue"}, 00381 {0.0,0.0,"orchid"}, 00382 {0.0,0.0,"magenta"}, 00383 {0.0,0.0,"violet"}, 00384 {0.0,0.0,"DarkViolet"}, 00385 {0.0,0.0,NULL} 00386 }; 00387 00388 struct ColorStrip Ustrip[] = 00389 { 00390 {-99.0,-10.0,"red"}, 00391 {-10.0, -5.0,"OrangeRed"}, 00392 { -5.0, 0.0,"Orange"}, 00393 { 0.0, 5.0,"yellow"}, 00394 { 5.0, 10.0,"GreenYellow"}, 00395 { 10.0, 15.0,"green"}, 00396 { 15.0, 20.0,"aquamarine"}, 00397 { 20.0, 25.0,"cyan"}, 00398 { 25.0, 30.0,"SkyBlue"}, 00399 { 30.0, 35.0,"blue"}, 00400 { 35.0, 40.0,"orchid"}, 00401 { 40.0, 45.0,"magenta"}, 00402 { 45.0, 50.0,"violet"}, 00403 { 50.0, 99.0,"DarkViolet"}, 00404 { 0.0, 0.0,NULL} 00405 }; 00406 00407 struct ColorStrip Qstrip[] = 00408 { 00409 {-99.0, 0.0,"black"}, 00410 { 0.0, 5.0,"OrangeRed"}, 00411 { 5.0, 10.0,"Orange"}, 00412 { 10.0, 15.0,"yellow"}, 00413 { 15.0, 20.0,"GreenYellow"}, 00414 { 20.0, 25.0,"green"}, 00415 { 25.0, 30.0,"aquamarine"}, 00416 { 30.0, 35.0,"cyan"}, 00417 { 35.0, 40.0,"SkyBlue"}, 00418 { 40.0, 45.0,"blue"}, 00419 { 45.0, 50.0,"orchid"}, 00420 { 50.0, 55.0,"magenta"}, 00421 { 55.0, 60.0,"violet"}, 00422 { 60.0, 99.0,"DarkViolet"}, 00423 { 0.0, 0.0,NULL} 00424 }; 00425 00426 struct ColorStrip Vstrip[] = 00427 { 00428 {-99.0,-10.0,"brown"}, 00429 {-10.0, -8.0,"gold"}, 00430 { -8.0, -6.0,"purple"}, 00431 { -6.0, -4.0,"red"}, 00432 { -4.0, -2.0,"OrangeRed"}, 00433 { -2.0, 0.0,"Orange"}, 00434 { 0.0, 2.0,"yellow"}, 00435 { 2.0, 4.0,"GreenYellow"}, 00436 { 4.0, 6.0,"green"}, 00437 { 6.0, 8.0,"aquamarine"}, 00438 { 8.0, 10.0,"cyan"}, 00439 { 10.0, 99.0,"blue"}, 00440 { 0.0, 0.0,NULL} 00441 }; 00442 00443 struct ColorStrip Tstrip[] = 00444 { 00445 {-99.0,-50.0,"MidnightBlue"}, 00446 {-50.0,-40.0,"RoyalBlue4"}, 00447 {-40.0,-30.0,"RoyalBlue3"}, 00448 {-30.0,-20.0,"RoyalBlue2"}, 00449 {-20.0,-10.0,"RoyalBlue1"}, 00450 {-10.0, 0.0,"violet"}, 00451 { 0.0, 10.0,"IndianRed1"}, 00452 { 10.0, 20.0,"IndianRed2"}, 00453 { 20.0, 30.0,"IndianRed3"}, 00454 { 30.0, 40.0,"IndianRed4"}, 00455 { 40.0, 50.0,"red"}, 00456 { 0.0, 0.0,NULL} 00457 }; 00458 00459 struct ColorStrip Kstrip[] = 00460 { 00461 {100.0,210.0,"RoyalBlue4"}, 00462 {210.0,220.0,"RoyalBlue3"}, 00463 {220.0,230.0,"RoyalBlue2"}, 00464 {230.0,240.0,"RoyalBlue1"}, 00465 {240.0,250.0,"violet"}, 00466 {250.0,260.0,"IndianRed1"}, 00467 {260.0,270.0,"IndianRed2"}, 00468 {270.0,280.0,"IndianRed3"}, 00469 {280.0,290.0,"IndianRed4"}, 00470 {290.0,400.0,"red"}, 00471 { 0.0, 0.0,NULL} 00472 }; 00473 00474 struct ColorStrip Pstrip[] = 00475 { 00476 { 00.0, 985.0,"RoyalBlue4"}, 00477 { 985.0, 990.0,"RoyalBlue3"}, 00478 { 990.0, 995.0,"RoyalBlue2"}, 00479 { 995.0,1000.0,"RoyalBlue1"}, 00480 {1000.0,1005.0,"violet"}, 00481 {1005.0,1010.0,"IndianRed1"}, 00482 {1010.0,1015.0,"IndianRed2"}, 00483 {1015.0,1020.0,"IndianRed3"}, 00484 {1020.0,1025.0,"IndianRed4"}, 00485 {1025.0,9990.0,"red"}, 00486 { 0.0, 0.0,NULL} 00487 }; 00488 00489 struct ColorStrip MarsTStrip[] = 00490 { 00491 {-200.0,-90.0,"RoyalBlue4"}, 00492 { -90.0,-80.0,"RoyalBlue3"}, 00493 { -80.0,-70.0,"RoyalBlue2"}, 00494 { -70.0,-60.0,"RoyalBlue1"}, 00495 { -60.0,-50.0,"violet"}, 00496 { -50.0,-40.0,"IndianRed1"}, 00497 { -40.0,-30.0,"IndianRed2"}, 00498 { -30.0,-20.0,"IndianRed3"}, 00499 { -20.0, 0.0,"IndianRed4"}, 00500 { 0.0,100.0,"red"}, 00501 { 0.0, 0.0,NULL} 00502 }; 00503 00504 struct ColorStrip AmpliStrip[] = 00505 { 00506 { 0.0, 1.0,"DarkBlue"}, 00507 { 8.0, 9.0,"blue"}, 00508 { 8.0, 9.0,"DarkGreen"}, 00509 { 8.0, 9.0,"green"}, 00510 { 8.0, 9.0,"yellow"}, 00511 { 9.0, 10.0,"Orange"}, 00512 { 10.0, 11.0,"OrangeRed"}, 00513 { 11.0, 12.0,"red"}, 00514 { 0.0, 0.0,NULL} 00515 }; 00516 00517 struct ColorStrip Vegstrip[] = 00518 { 00519 {-999.9,0.001,"DarkBlue"}, 00520 { 0.001, 10.0,"brown"}, 00521 { 10.0, 20.0,"SeaGreen4"}, 00522 { 20.0, 30.0,"SeaGreen3"}, 00523 { 30.0, 40.0,"SeaGreen2"}, 00524 { 40.0, 50.0,"SeaGreen1"}, 00525 { 50.0, 60.0,"YellowGreen"}, 00526 { 60.0, 70.0,"green4"}, 00527 { 70.0, 80.0,"green3"}, 00528 { 80.0, 90.0,"green2"}, 00529 { 90.0,999.0,"green1"}, 00530 { 0.0, 0.0,NULL} 00531 }; 00532 00533 struct ColorStrip Tstripoce[] = 00534 { 00535 {-99.0, 0.00001,"Black"}, 00536 { 0.00001, 4.0 ,"RoyalBlue4"}, 00537 { 4.0 ,8.0,"RoyalBlue3"}, 00538 { 8.0, 12.0,"RoyalBlue2"}, 00539 { 12.0, 16.0,"RoyalBlue1"}, 00540 { 16.0, 20.0,"violet"}, 00541 { 20.0, 24.0,"IndianRed1"}, 00542 { 24.0, 28.0,"IndianRed2"}, 00543 { 28.0, 32.0,"IndianRed3"}, 00544 { 32.0, 36.0,"IndianRed4"}, 00545 { 36.0, 40.0,"red"}, 00546 { 0.0, 0.0,NULL} 00547 }; 00548 00549 struct ColorStrip Sstripoce[] = 00550 { 00551 {-99.0, 30.0,"Black"}, 00552 { 30.0, 32.0 ,"RoyalBlue4"}, 00553 { 32.0 ,32.5,"RoyalBlue3"}, 00554 { 32.5, 33.0,"RoyalBlue2"}, 00555 { 33.0, 34.0,"SeaGreen"}, 00556 { 34.0, 34.5,"YellowGreen"}, 00557 { 34.5, 35.0,"LightGreen"}, 00558 { 35.0, 35.5,"Orange"}, 00559 { 35.5, 36.0,"DarkOrange"}, 00560 { 36.0, 36.5,"OrangeRed"}, 00561 { 36.5, 40.0,"red"}, 00562 { 0.0, 0.0,NULL} 00563 }; 00564 00565 struct ColorStrip DCCstrip[] = 00566 { 00567 {-99.0, 0.0, "Black"}, 00568 { 0.0, 10.0,"Yellow"}, 00569 { 10.0, 20.0,"YellowGreen"}, 00570 { 20.0, 30.0,"Green"}, 00571 { 30.0, 40.0,"Aquamarine"}, 00572 { 40.0, 50.0,"Cyan"}, 00573 { 50.0, 60.0,"SkyBlue"}, 00574 { 60.0, 70.0,"Blue"}, 00575 { 70.0, 80.0,"Orchid"}, 00576 { 80.0, 90.0,"Magenta"}, 00577 { 90.0,100.0,"DarkViolet"}, 00578 { 0.0, 0.0,NULL} 00579 }; 00580 00581 struct ColorStrip DTDTstrip[] = 00582 { 00583 {-99.0, -5.0,"brown"}, 00584 {- 5.0, -3.0,"gold"}, 00585 { -3.0, -1.5,"purple"}, 00586 { -1.5, -0.5,"red"}, 00587 { -0.5, -0.25,"OrangeRed"}, 00588 { -0.25, 0.0,"Orange"}, 00589 { 0.0, 0.25,"yellow"}, 00590 { 0.25, 0.5,"GreenYellow"}, 00591 { 0.5, 1.5,"green"}, 00592 { 1.5, 3.0,"aquamarine"}, 00593 { 3.0, 5.0,"cyan"}, 00594 { 5.0, 99.0,"blue"}, 00595 { 0.0, 0.0,NULL} 00596 }; 00597 00598 #define AMPLI_COLS 8 00599 00600 struct ColorStrip *Cstrip; 00601 struct ColorStrip *Pallet[NUMPAL] = 00602 { Autostrip, Ustrip, Vstrip, Tstrip, Pstrip, Qstrip,MarsTStrip,AmpliStrip, 00603 Vegstrip, Tstripoce, Sstripoce, DCCstrip, DTDTstrip}; 00604 00605 REAL VGAX; 00606 REAL VGAY; 00607 REAL CurVal; 00608 00609 REAL *Field; // Pointer for ISO data 00610 REAL *Ampli; // Amplitudes of spherical harmonics 00611 XColor *Acol; // Amplitude colors 00612 00613 Colormap colormap; 00614 00615 XColor xcolor1,xcolor2; 00616 XColor Red,Green,Blue,Yellow,Grey,LightRed,DarkRed,LightBlue,DarkBlue; 00617 XColor LightGreen,DarkGreen,Dummy; 00618 00619 unsigned long TSColor[10]; 00620 00621 Window Win[NUMWIN]; 00622 int win; // Current window 00623 Window Cow; // Control bar 00624 Window HelpWindow; 00625 00626 XTextProperty WinconName1; 00627 XTextProperty WinconName3; 00628 XTextProperty WinconPause; 00629 XTextProperty WinconReady; 00630 char *PauseTitle = "Run Paused"; 00631 char *ReadyTitle = "Press Start Button"; 00632 00633 XEvent CowEvent; 00634 00635 XSizeHints WinSizeHints; 00636 XSizeHints CowSizeHints; 00637 int OutXSize,OutYSize; 00638 int count; 00639 XEvent report; 00640 GC gc; 00641 00642 /* 00643 char BigFontName[80] = "10x20"; 00644 char FixFontName[80] = "9x15bold"; 00645 char SubFontName[80] = "6x10"; 00646 */ 00647 char BigFontName[80] = "9x15bold"; 00648 char FixFontName[80] = "8x13"; 00649 char SubFontName[80] = "6x10"; 00650 00651 XFontStruct *FixFont; 00652 XFontStruct *SubFont; 00653 XFontStruct *BigFont; 00654 int FixFontHeight; 00655 int SubFontHeight; 00656 int BigFontHeight; 00657 int FixFontWidth; 00658 int SubFontWidth; 00659 int BigFontWidth; 00660 int Paused = 0; 00661 00662 char *display_name = NULL; 00663 XWMHints wm_hints; 00664 XClassHint class_hints; 00665 Atom Delwin; 00666 00667 char *WindowTitle[NUMWIN]; 00668 XTextProperty WindowName[NUMWIN]; 00669 XTextProperty HelpName; 00670 00671 char *mona[12] = 00672 { 00673 "Jan","Feb","Mar", 00674 "Apr","May","Jun", 00675 "Jul","Aug","Sep", 00676 "Oct","Nov","Dec" 00677 }; 00678 00679 char *wena[7] = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"}; 00680 00681 char datch[64]; 00682 char PlanetName[32] = "Earth"; 00683 00684 char GUI_default[80] = "GUI.cfg"; 00685 char GUI_config[80] = "GUI_last_used.cfg"; 00686 00687 00688 #define PSDIM 30 00689 char *pixelstar[PSDIM] = { 00690 "..............................", 00691 "..............................", 00692 "..............................", 00693 "...**....**....**....**.......", 00694 "...**....**....**....**.......", 00695 "...**....**....**....**.......", 00696 "...**....**....**....**.......", 00697 "...**....**************.......", 00698 "...**....**************.......", 00699 "...**....**....**....**.......", 00700 "...***...**....**....**.......", 00701 "....******.....**....**.......", 00702 ".....****......**....**.......", 00703 "..............................", 00704 "..............................", 00705 "..............................", 00706 "..............................", 00707 "..............................", 00708 "..............................", 00709 "..............................", 00710 "..............................", 00711 "..............................", 00712 ".......................*......", 00713 "......................***.....", 00714 "...................**.***.**..", 00715 "...................**.***.**..", 00716 "...................**.***.**..", 00717 "...................****.****..", 00718 "...................***...***..", 00719 "...................***...***.."}; 00720 00721 // Variables used for calculating "frames per second" 00722 00723 int fps; 00724 int rmuf = 20; // Rotating map update frequency [1/sec] 00725 int rmui = 1; // Rotating map update interval [steps] 00726 int SkipFreq; 00727 int ThisSecond; 00728 int LastSecond; 00729 int LastStep; 00730 int SecEvent; 00731 00732 int ndatim[6]; /* year, month, day, hour, minute, weekday */ 00733 int LastMinute; /* Last value of ndatim(4) */ 00734 int DeltaTime ; /* Computed timestep interval [min] */ 00735 00736 struct BMIstruct 00737 { 00738 int Size; 00739 int Width; 00740 int Height; 00741 short Planes; 00742 short Count; 00743 int Compression; 00744 int SizeImage; 00745 int XPelsPerMeter; 00746 int YPelsPerMeter; 00747 int ClrUsed; 00748 int ClrImportant; 00749 }; 00750 00751 struct BMIstruct ImageBMI; 00752 00753 struct MapImageStruct 00754 { 00755 char *d; // Bitmap data 00756 int w; // Image width 00757 int h; // Image height 00758 int f; // Rotation factor 00759 float l; // Reference longitude 00760 float r; // Rotation speed [deg/step] 00761 XImage *X; // XImage structure 00762 }; 00763 00764 // Convert an RGB value to an X11 Pixel 00765 00766 unsigned long create_pixel(long red, long green, long blue) 00767 { 00768 if (ScreenD == 24) // 24 bit true color 00769 { 00770 return red | green << 8 | blue << 16; 00771 } 00772 else if (ScreenD == 16) // 16 bit RGB 565 00773 { 00774 return red >> 3 | (green >> 2) << 5 | (blue >> 3) << 11; 00775 } 00776 else return 0; 00777 } 00778 00779 struct MapImageStruct MapHR; // Hires (2560x1280) Earth image 00780 struct MapImageStruct MapLR[NUMWIN]; 00781 00782 void ScaleImage(struct MapImageStruct *s, struct MapImageStruct *d) 00783 { 00784 int a,b,x,y; 00785 unsigned long px; 00786 unsigned long h,w; 00787 double f,g; 00788 00789 if (d->X) XDestroyImage(d->X); 00790 w = (d->w + 7) & 0xFFF8; 00791 h = d->h; 00792 d->d = malloc(4 * w * h); 00793 d->X = XCreateImage(display,CopyFromParent,ScreenD,ZPixmap,0, 00794 d->d,w,h,8,0); 00795 00796 f = (double)s->w / (double)d->w; 00797 g = (double)s->h / (double)d->h; 00798 00799 for (y = 0 ; y < d->h ; ++y) 00800 for (x = 0 ; x < d->w ; ++x) 00801 { 00802 a = x * f; 00803 b = y * g; 00804 XPutPixel(d->X,x,y,XGetPixel(s->X,a,b)); 00805 } 00806 } 00807 00808 00809 void PolarImage(struct MapImageStruct *s, struct MapImageStruct *d) 00810 { 00811 int a,b,x,y; 00812 unsigned long h,w; 00813 double f,lfa,xnp,ynp,xsp,ysp,dx,dy; 00814 00815 if (d->X) XDestroyImage(d->X); 00816 w = (d->w + 7) & 0xFFF8; 00817 h = d->h; 00818 d->d = malloc(4 * w * h); 00819 d->X = XCreateImage(display,CopyFromParent,ScreenD,ZPixmap,0, 00820 d->d,w,h,8,0); 00821 00822 f = (double)s->h / (double)d->h; 00823 lfa = (s->w-1) / (2.0 * M_PI); 00824 xnp = (d->w) * 0.25; 00825 ynp = (d->h) * 0.50; 00826 xsp = (d->w) * 0.75; 00827 ysp = ynp; 00828 00829 for (y = 0 ; y < d->h ; ++y) 00830 { 00831 dy = ynp - y; 00832 for (x = 0 ; x < d->w/2 ; ++x) /* Northern hemisphere */ 00833 { 00834 dx = xnp - x; 00835 a = atan2(dx,dy) * lfa; 00836 b = sqrt(dx * dx + dy * dy) * f; 00837 if (a < 0.0) a += (s->w); 00838 if (a >= 0 && a < s->w && b >= 0 && b <= s->h/2) 00839 XPutPixel(d->X,x,y,XGetPixel(s->X,a,b)); 00840 else XPutPixel(d->X,x,y,BlackPix); 00841 } 00842 dy = ysp - y; 00843 for (x = d->w/2 ; x < d->w ; ++x) /* Southern hemisphere */ 00844 { 00845 dx = x - xsp; 00846 a = atan2(dx,dy) * lfa; 00847 b = s->h - f * sqrt(dx * dx + dy * dy); 00848 if (a < 0.0) a += (s->w); 00849 if (a >= 0 && a < s->w && b >= 0 && b >= s->h/2 && b <= s->h) 00850 XPutPixel(d->X,x,y,XGetPixel(s->X,a,b)); 00851 else XPutPixel(d->X,x,y,BlackPix); 00852 } 00853 } 00854 } 00855 00856 00857 void RevOrtho(double R, double lam0, double phi0, int xx, int yy, double *lam, double *phi) 00858 { 00859 double rho,c,rhoq,x,y; 00860 00861 x = xx; 00862 y = yy; 00863 00864 rhoq = x*x + y*y; 00865 rho = sqrt(rhoq); 00866 if (rho > R) 00867 { 00868 *phi = 999.9; 00869 *lam = 999.9; 00870 } 00871 else if (rho > R / 100000.0) 00872 { 00873 c = asin(rho / R); 00874 *phi = asin(cos(c) * sin(phi0) + y * sin(c) * cos(phi0) / rho); 00875 *lam = lam0 + atan2(x * sin(c) , rho * cos(phi0) * cos(c) - y * sin(phi0) * sin(c)); 00876 } 00877 else 00878 { 00879 *phi = phi0; 00880 *lam = lam0; 00881 } 00882 // printf("[%6.1lf / %6.1lf] --> (%6.1lf / %6.1lf)\n",x,y,*lam,*phi); 00883 } 00884 00885 /* ==================================================== */ 00886 /* AzimuthalImage - Display map in azimuthal projection */ 00887 /* ==================================================== */ 00888 00889 void AzimuthalImage(struct MapImageStruct *s, struct MapImageStruct *d) 00890 { 00891 int lam; // lambda pixel coordinate in source image 00892 int phi; // phi pixel coordinate in source image 00893 int x ; // x pixel coordinate in destination image 00894 int y ; // y pixel coordinate in destination image 00895 int dxc; // pixel coordinate of centre position 00896 int dxl; // pixel coordinate of left most position 00897 int dxr; // pixel coordinate of right most position 00898 int dx ; // centre relative x position 00899 int dy ; // centre relative y position 00900 int p00; // euqator 00901 int l00; // reference longitude 00902 00903 unsigned int dih; // destination image height 00904 unsigned int diw; // destination image width 00905 unsigned int dpw; // destination image padded width 00906 00907 double rad; // pixel radius of new image 00908 double ysc; // yscale = source height / destination height 00909 double rho; // distance from centre 00910 double xpi; // x scale factor = 2 * PI / width 00911 double ypi; // y scale factor = PI / height 00912 double xrf; 00913 double yrf; 00914 00915 XImage *sX; // source image 00916 XImage *dX; // destination image 00917 00918 00919 // Destroy old image structure inclusive data storage 00920 00921 if (d->X) XDestroyImage(d->X); 00922 00923 // Set width of new image 00924 00925 diw = d->w; 00926 00927 // Pad width of new image to a multiple of 8 00928 00929 dpw = (diw + 7) & 0xFFF8; 00930 00931 // Set height of new image 00932 00933 dih = d->h; 00934 00935 // Allocate space for image data 00936 00937 d->d = calloc(dpw * dih,4); 00938 00939 // Create image structure 00940 00941 dX = d->X = XCreateImage(display,CopyFromParent,ScreenD,ZPixmap,0,d->d,dpw,dih,8,0); 00942 sX = s->X; 00943 00944 p00 = s->h >> 1; 00945 rad = dih >> 1; 00946 dxc = diw >> 1; 00947 dxl = MAX(dxc - rad, 0); 00948 dxr = MIN(dxc + rad, diw); 00949 xpi = s->w / M_PI * 0.5; 00950 ypi = s->h / M_PI; 00951 ysc = (double)s->h / (double)dih; 00952 l00 = (int)((d->l * s->w) / 360 + s->w/2) % s->w; 00953 xrf = (double)diw / pow(2.0,31), 00954 yrf = (double)dih / pow(2.0,31); 00955 00956 // Paint some stars on the sky 00957 00958 srandom(Seed); 00959 for (y = 0 ; y < (diw * dih) >> 8 ; ++y) 00960 XPutPixel(dX,xrf*random(),yrf*random(),WhitePix); 00961 00962 for (y = 0 ; y < dih ; ++y) 00963 { 00964 dy = y - rad; 00965 phi = y * ysc; 00966 for (x = dxl ; x < dxr ; ++x) 00967 { 00968 dx = x - dxc; 00969 rho = sqrt(dx * dx + dy * dy); 00970 if (rho < rad) 00971 { 00972 lam = l00 + xpi * atan2(dx / rad, cos(asin(rho / rad))); 00973 phi = p00 + ypi * asin(dy / rad); 00974 XPutPixel(dX,x,y,XGetPixel(sX,lam,phi)); 00975 } 00976 } 00977 } 00978 } 00979 00980 00981 void SwapIEEE16(char W[2]) 00982 { 00983 char B; 00984 00985 B = W[0]; W[0] = W[1]; W[1] = B; 00986 } 00987 00988 void SwapIEEE32(char W[4]) 00989 { 00990 char B; 00991 00992 B = W[0]; W[0] = W[3]; W[3] = B; 00993 B = W[1]; W[1] = W[2]; W[2] = B; 00994 } 00995 00996 int ReadINT(FILE *fpi) 00997 { 00998 int k; 00999 fread(&k,sizeof(k),1,fpi); 01000 if (BigEndian) SwapIEEE32((char *)&k); 01001 return k; 01002 } 01003 01004 short ReadSHORT(FILE *fpi) 01005 { 01006 short k; 01007 fread(&k,sizeof(k),1,fpi); 01008 if (BigEndian) SwapIEEE16((char *)&k); 01009 return k; 01010 } 01011 01012 void ReadImage(struct MapImageStruct *ei, char *filename) 01013 { 01014 char ch; 01015 int i,n,x,y,z; 01016 long r,g,b; 01017 int FileSize; 01018 int Reserved; 01019 int OffBits; 01020 int PicBytes; 01021 int ImgBytes; 01022 int PadWidth; 01023 int PadBytes; 01024 int bpp; 01025 int byr; 01026 FILE *fp; 01027 unsigned char *BuffImageData; 01028 01029 if (!(fp = fopen(filename,"r"))) return; 01030 ch = fgetc(fp); 01031 if (ch != 'B') return; 01032 ch = fgetc(fp); 01033 if (ch != 'M') return; 01034 FileSize = ReadINT(fp); 01035 Reserved = ReadINT(fp); 01036 OffBits = ReadINT(fp); 01037 01038 if (Debug) 01039 { 01040 printf("Properties of %s:\n",filename); 01041 printf("FileSize = %d\n",FileSize); 01042 printf("FileOffset = %d\n",OffBits); 01043 } 01044 01045 ImageBMI.Size = ReadINT(fp); 01046 ImageBMI.Width = ReadINT(fp); 01047 ImageBMI.Height = ReadINT(fp); 01048 ImageBMI.Planes = ReadSHORT(fp); 01049 ImageBMI.Count = ReadSHORT(fp); 01050 ImageBMI.Compression = ReadINT(fp); 01051 ImageBMI.SizeImage = ReadINT(fp); 01052 ImageBMI.XPelsPerMeter = ReadINT(fp); 01053 ImageBMI.YPelsPerMeter = ReadINT(fp); 01054 ImageBMI.ClrUsed = ReadINT(fp); 01055 ImageBMI.ClrImportant = ReadINT(fp); 01056 01057 PadWidth = (ImageBMI.Width + 7) & 0xFFF8; 01058 bpp = ImageBMI.Count >> 3; 01059 PadBytes = (4 - ((ImageBMI.Width * bpp) % 4)) % 4 ; 01060 01061 if (Debug) 01062 { 01063 printf("BMI Size = %d\n",ImageBMI.Size); 01064 printf("BMI Width = %d\n",ImageBMI.Width); 01065 printf("BMI Height = %d\n",ImageBMI.Height); 01066 printf("BMI Planes = %d\n",ImageBMI.Planes); 01067 printf("BMI Count = %d\n",ImageBMI.Count); 01068 printf("BMI ClrUsed = %d\n",ImageBMI.ClrUsed); 01069 printf("Pad Bytes = %d\n",PadBytes); 01070 printf("ScreenD= %d\n",ScreenD); 01071 } 01072 01073 PicBytes = (bpp * ImageBMI.Width + PadBytes) * ImageBMI.Height; 01074 ImgBytes = 4 * PadWidth * ImageBMI.Height; 01075 ei->d = calloc(ImgBytes,1); 01076 BuffImageData = malloc(PicBytes); 01077 n = fread(BuffImageData,PicBytes,1,fp); 01078 fclose(fp); 01079 01080 ei->X = XCreateImage(display,CopyFromParent,ScreenD,ZPixmap,0, 01081 ei->d,PadWidth,ImageBMI.Height,8,0); 01082 01083 for (y = 0 ; y < ImageBMI.Height ; ++y) 01084 for (x = 0 ; x < ImageBMI.Width ; ++x) 01085 { 01086 i = bpp * x + (ImageBMI.Height - 1 - y) * (ImageBMI.Width*bpp+PadBytes); 01087 r = BuffImageData[i ]; 01088 g = BuffImageData[i+1]; 01089 b = BuffImageData[i+2]; 01090 XPutPixel(ei->X, x, y, create_pixel(r,g,b)); 01091 } 01092 free(BuffImageData); 01093 ei->w = ImageBMI.Width; 01094 ei->h = ImageBMI.Height; 01095 } 01096 01097 01098 void ntocdat(void) 01099 { 01100 if (ndatim[1] > 0) 01101 { 01102 if (ndatim[5] >= 0) 01103 sprintf(datch,"%s %2d-%s-%04d %2d:%02d",wena[ndatim[5]],ndatim[2],mona[ndatim[1]-1], 01104 ndatim[0],ndatim[3],ndatim[4]); 01105 else 01106 sprintf(datch,"%2d-%s-%04d %2d:%02d",ndatim[2],mona[ndatim[1]-1], 01107 ndatim[0],ndatim[3],ndatim[4]); 01108 } 01109 } 01110 01111 /* ============================================== */ 01112 /* CharAlloc - Allocate space for character array */ 01113 /* ============================================== */ 01114 01115 char *CharAlloc(int bytes,char *array_name) 01116 { 01117 char *result = NULL; 01118 if (bytes > 0) 01119 { 01120 result = (char *)calloc(bytes, sizeof(char)); 01121 if (!result || Debug) 01122 { 01123 if (!result) printf("*** Out of Memory *** on "); 01124 printf("CharAlloc: at%10p %6d char for %-30.30s\n", 01125 result,bytes,array_name); 01126 } 01127 } 01128 return(result); 01129 } 01130 01131 /* ======================================= */ 01132 /* IntAlloc - Allocate space for int array */ 01133 /* ======================================= */ 01134 01135 int *IntAlloc(int words,char *array_name) 01136 { 01137 int *result = NULL; 01138 if (words > 0) 01139 { 01140 result = (int *) calloc(words, sizeof(int)); 01141 if (!result || Debug) 01142 { 01143 if (!result) printf("*** Out of Memory *** on "); 01144 printf("IntAlloc: at%10p %6d int for %s\n", 01145 result,words,array_name); 01146 } 01147 } 01148 return(result); 01149 } 01150 01151 /* =========================================== */ 01152 /* FloatAlloc - Allocate space for float array */ 01153 /* =========================================== */ 01154 01155 float *FloatAlloc(int words, char *array_name) 01156 { 01157 float *result = NULL; 01158 if (words > 0) 01159 { 01160 result = (float *) calloc(words, sizeof(float)); 01161 if (!result || Debug) 01162 { 01163 if (!result) printf("*** Out of Memory *** on "); 01164 printf("FloatAlloc: at%10p %6d float for %s\n", 01165 result,words,array_name); 01166 } 01167 } 01168 return(result); 01169 } 01170 01171 /* ========================================== */ 01172 /* SizeAlloc - Allocate space for sized array */ 01173 /* ========================================== */ 01174 01175 void *SizeAlloc(int words, int Size, char *array_name) 01176 { 01177 void *result = NULL; 01178 if (words > 0) 01179 { 01180 result = (void *) calloc(words, Size); 01181 if (!result || Debug) 01182 { 01183 if (!result) printf("*** Out of Memory *** on "); 01184 printf("SizeAlloc: at%10p %6d void for %s\n", 01185 result,words,array_name); 01186 } 01187 } 01188 return(result); 01189 } 01190 01191 void LoadFonts(void) 01192 { 01193 if ((FixFont = XLoadQueryFont(display,FixFontName)) == NULL) 01194 { 01195 printf("%s: Cannot open %s font\n",progname,FixFontName); 01196 exit(-1); 01197 } 01198 if ((SubFont = XLoadQueryFont(display,SubFontName)) == NULL) 01199 { 01200 SubFont = FixFont; 01201 } 01202 if ((BigFont = XLoadQueryFont(display,BigFontName)) == NULL) 01203 { 01204 if ((BigFont = XLoadQueryFont(display,"10x20")) == NULL) 01205 { 01206 printf("%s: Cannot open %s font\n",progname,BigFontName); 01207 exit(-1); 01208 } 01209 } 01210 FixFontWidth = XTextWidth(FixFont,"X",1); 01211 SubFontWidth = XTextWidth(SubFont,"X",1); 01212 BigFontWidth = XTextWidth(BigFont,"X",1); 01213 FixFontHeight = FixFont->ascent + FixFont->descent; 01214 SubFontHeight = SubFont->ascent + SubFont->descent; 01215 BigFontHeight = BigFont->ascent + BigFont->descent; 01216 } 01217 01218 int AllocateColorCells(struct ColorStrip cs[]) 01219 { 01220 int i = 0; 01221 XColor xcolor1,xcolor2; 01222 01223 while (cs[i].Name) 01224 { 01225 XAllocNamedColor(display,colormap,cs[i].Name,&xcolor1,&xcolor2); 01226 cs[i].pixel = xcolor1.pixel; 01227 ++i; 01228 } 01229 return i; 01230 } 01231 01232 void CalcButtonAreas(void) 01233 { 01234 int of,ds,bh,fh,fw,j; 01235 01236 of = OffsetY; 01237 ds = 10; 01238 bh = 30; 01239 fh = BigFontHeight; 01240 fw = BigFontWidth; 01241 01242 /* 1. Stop Button */ 01243 01244 StopButton[0].y += OffsetY; 01245 StopButton[1].y += OffsetY; 01246 StopButton[2].y += OffsetY; 01247 StopButton[3].y += OffsetY; 01248 01249 Stop_XL = ds; 01250 Stop_XH = Stop_XL + bh; 01251 Stop_YL = of + ds; 01252 Stop_YH = Stop_YL + bh; 01253 01254 /* 2. Start Button */ 01255 01256 Start_XL = Stop_XH + ds; 01257 Start_XH = Start_XL + bh; 01258 Start_YL = Stop_YL; 01259 Start_YH = Stop_YH; 01260 01261 StartButton[0].y += OffsetY; 01262 StartButton[1].y += OffsetY; 01263 StartButton[2].y += OffsetY; 01264 01265 /* 3. Pause Button */ 01266 01267 Pause_XL = Start_XH + 15; 01268 Pause_XH = Start_XH + 35; 01269 Pause_YL = Start_YL; 01270 Pause_YH = Start_YH; 01271 01272 PauseButton1[0].y += OffsetY; 01273 PauseButton1[1].y += OffsetY; 01274 PauseButton1[2].y += OffsetY; 01275 PauseButton1[3].y += OffsetY; 01276 01277 PauseButton2[0].y += OffsetY; 01278 PauseButton2[1].y += OffsetY; 01279 PauseButton2[2].y += OffsetY; 01280 PauseButton2[3].y += OffsetY; 01281 01282 /* 4. Help Button */ 01283 01284 Help_XL = 200; 01285 Help_XH = Help_XL + 5 * fw; 01286 Help_YL = Pause_YL; 01287 Help_YH = Pause_YH; 01288 01289 /* 5. Minus & FBWD Button */ 01290 01291 Minus_XL = 300; 01292 Minus_XH = Minus_XL + fh; 01293 Minus_YL = Pause_YL + (bh - fh) / 2; 01294 Minus_YH = Minus_YL + fh; 01295 01296 FBWD_XH = Minus_XL - ds/2; 01297 FBWD_XL = FBWD_XH - fh; 01298 FBWD_YL = Minus_YL; 01299 FBWD_YH = Minus_YH; 01300 01301 /* 6. Parameter Change Area */ 01302 01303 Parc_XL = Minus_XH + ds; 01304 Parc_XH = Parc_XL + fw * 14; 01305 Parc_YL = Minus_YL; 01306 Parc_YH = Minus_YH; 01307 Parc_XD = Parc_XH - Parc_XL; 01308 Parc_YD = Parc_YH - Parc_YL; 01309 01310 /* 7. Plus & FFWD Button */ 01311 01312 Plus_XL = Parc_XH + ds; 01313 Plus_XH = Plus_XL + fh; 01314 Plus_YL = Minus_YL; 01315 Plus_YH = Minus_YH; 01316 01317 FFWD_XL = Plus_XH + ds/2; 01318 FFWD_XH = FFWD_XL + fh; 01319 FFWD_YL = Plus_YL; 01320 FFWD_YH = Plus_YH; 01321 01322 /* 8. Grid on/off box */ 01323 01324 Grid_XL = Stop_XL; 01325 Grid_XH = Grid_XL + FixFontHeight; 01326 Grid_YL = Stop_YH + 3 * BigFontHeight / 2; 01327 Grid_YH = Grid_YL + FixFontHeight; 01328 01329 /* Window status and select boxes */ 01330 01331 Wbox_XL = 580; 01332 Wbox_XH = Wbox_XL + FixFontHeight; 01333 Wbox_YL = 0; 01334 Wbox_YH = NumWin * FixFontHeight; 01335 } 01336 01337 01338 /* Hack for getting information of window decoration */ 01339 /* especially borderwidth and titleheight */ 01340 /* These are properties of the window manager and are */ 01341 /* usually adjustable by the user */ 01342 01343 void TestWindow(int xx, int yy, int wi, int he, int *x, int *y, 01344 int *X, int *Y, unsigned int *W, unsigned int *H) 01345 { 01346 unsigned int DepthReturn = 0; 01347 unsigned int BorderReturn = 0; 01348 Window TW,Parent,Child; 01349 01350 TW = XCreateWindow(display,RootWindow(display,screen_num), 01351 xx,yy,wi,he, // x,y,w,h 01352 0,CopyFromParent,InputOutput, // border, depth, class 01353 CopyFromParent,0,NULL); // visual, valuemask, attributes 01354 XSelectInput(display,TW,ExposureMask); 01355 XMapWindow(display,TW); 01356 XMoveWindow(display,TW,xx,yy); 01357 XNextEvent(display,&CowEvent); // Wait until WM mapped it 01358 XGetGeometry(display,TW,&Parent,x,y,W,H,&BorderReturn,&DepthReturn); 01359 XTranslateCoordinates(display,TW,Parent,0,0,X,Y,&Child); 01360 XDestroyWindow(display,TW); 01361 01362 if (Debug) 01363 { 01364 printf("TW[%x][%x]: %4d / %4d %4d x %4d x %2d [%2d:%2d]\n", 01365 (int)TW,(int)Parent,*x,*y,*W,*H,DepthReturn,*X,*Y); 01366 } 01367 } 01368 01369 01370 void CreateTestWindow(void) 01371 { 01372 int X,Y,xp,yp; 01373 unsigned int W,H; 01374 01375 // Open a test window with displacement x = 100 and y = 100 01376 // Test the returned coordinates for upper left corner 01377 // and compute left margin (border) and top margin (title bar) 01378 01379 TestWindow(100,100,100,100,&xp,&yp,&X,&Y,&W,&H); 01380 01381 // Left margin 01382 01383 if (X >= 100 && X < 110) WinLM = X - 100; 01384 01385 // Right margin 01386 01387 WinRM = WinLM; 01388 01389 // Top margin 01390 01391 if (Y >= 100 && Y < 150) WinTM = Y - 100; 01392 else if (Y > 0 && Y < 50) WinTM = Y; 01393 01394 // Bottom margin 01395 01396 WinBM = WinLM; 01397 01398 // Open a full screen test window 01399 // Test the returned coordinates for upper left corner 01400 // the y displacement should be WinTM plus Windowmanager menu bar 01401 01402 TestWindow(0,0,ScreenW,ScreenH,&xp,&yp,&X,&Y,&W,&H); 01403 01404 // Window manager menu bar on top 01405 01406 if (yp > WinTM) WM_top_area = yp - WinTM; 01407 01408 01409 // Last usable scan line 01410 01411 ScreenBot = WM_top_area + WinTM + H; 01412 if (ScreenBot > ScreenH) ScreenBot = ScreenH; 01413 01414 // Are we running on a 27" iMac :-) 01415 01416 if (ScreenW == 2560 && ScreenH > 1400) ScreenBot -= 100; 01417 01418 if (Debug) 01419 { 01420 printf("Screen = %4d x %4d x %2d\n",ScreenW,ScreenH,ScreenD); 01421 printf("ScreenBot = %4d\n",ScreenBot); 01422 printf("Top reserved = %4d\n",WM_top_area); 01423 printf("Bot reserved = %4d\n",ScreenH-ScreenBot); 01424 printf("Left margin = %4d\n",WinLM); 01425 printf("Right margin = %4d\n",WinRM); 01426 printf("Top margin = %4d\n",WinTM); 01427 printf("Bot margin = %4d\n",WinBM); 01428 } 01429 } 01430 01431 01432 void TrimCopy(char *Trim, char *Line, int n) 01433 { 01434 int l; 01435 char *s; 01436 01437 l = strlen(Line); 01438 Line[--l] = 0; // Remove linefeed 01439 while (Line[l-1] == ' ') Line[--l] = 0; // Remove trailing blanks 01440 s = Line; 01441 while (*s == ' ') ++s; // Remove leading blanks 01442 strncpy(Trim,s,n); 01443 } 01444 01445 01446 int ReadConfig(char *filename) 01447 { 01448 FILE *fp; 01449 int i,w,l,s,p; 01450 char Line[256]; 01451 char Plot[80]; 01452 char Palette[80]; 01453 char Projection[80]; 01454 char Rotation[80]; 01455 char *t; 01456 01457 fp = fopen(filename,"r"); 01458 if (!fp) return 1; 01459 01460 w = -2; 01461 s = -1; 01462 p = -1; 01463 while (!feof(fp)) 01464 { 01465 t = fgets(Line,256,fp); 01466 if (Line[0] == '#') continue; 01467 if (strncmp(Line,"[Window " , 8) == 0) w = atoi(Line+8); 01468 if (strncmp(Line,"[Control" , 8) == 0) w = -1; 01469 if (strncmp(Line,"[Scalar " , 8) == 0) s = atoi(Line+8); 01470 if (strncmp(Line,"WinRows =" , 9) == 0) 01471 { 01472 WinRows = atoi(Line+9); 01473 if (WinRows < 1) WinRows = 1; 01474 if (WinRows > 3) WinRows = 3; 01475 NumWin = WinCols * WinRows; 01476 } 01477 if (strncmp(Line,"WinCols =" , 9) == 0) 01478 { 01479 WinCols = atoi(Line+9); 01480 if (WinCols < 1) WinCols = 1; 01481 if (WinCols > 3) WinCols = 3; 01482 NumWin = WinCols * WinRows; 01483 } 01484 if (strncmp(Line,"[Parameter " ,11) == 0) 01485 { 01486 p = atoi(Line+11); 01487 if (p >= Parcs) Parcs = p+1; 01488 } 01489 if (strncmp(Line,"Geometry:",9) == 0 && w >= 0 && w < NUMWIN) 01490 { 01491 sscanf(Line+9,"%d %d %d %d",&WinAtt[w].w,&WinAtt[w].h, 01492 &WinAtt[w].x,&WinAtt[w].y); 01493 WinAtt[w].active = 1; 01494 } 01495 if (strncmp(Line,"Inactive:",9) == 0 && w >= 0 && w < NUMWIN) 01496 { 01497 sscanf(Line+9,"%d %d %d %d",&WinAtt[w].w,&WinAtt[w].h, 01498 &WinAtt[w].x,&WinAtt[w].y); 01499 WinAtt[w].active = 0; 01500 } 01501 if (strncmp(Line,"Geometry:",9) == 0 && w == -1) 01502 { 01503 sscanf(Line+9,"%d %d %d %d",&CowW,&CowH,&CowX,&CowY); 01504 } 01505 if (strncmp(Line,"Title:",6) == 0 && w >= -1 && w < NUMWIN) 01506 { 01507 if (w == -1) TrimCopy(PlanetName,Line+6,sizeof(PlanetName)-1); 01508 else TrimCopy(WindowTitle[w]+wto,Line+6,79-wto); 01509 } 01510 if (strncmp(Line,"Array:",6) == 0 && w >= 0 && w < NUMWIN) 01511 TrimCopy(WinAtt[w].array_name,Line+6,79); 01512 if (strncmp(Line,"Plot:",5) == 0 && w >= 0 && w < NUMWIN) 01513 { 01514 TrimCopy(Plot,Line+5,79); 01515 for (i=0 ; i < IsoTypes ; ++i) 01516 if (!strcmp(Plot,IsoNames[i])) WinAtt[w].Plot = i; 01517 } 01518 if (strncmp(Line,"Projection:",11) == 0 && w >= 0 && w < NUMWIN) 01519 { 01520 TrimCopy(Projection,Line+11,79); 01521 for (i=0 ; i < MAXMAPS ; ++i) 01522 if (!strcmp(Projection,ProNames[i])) MapPro[w] = i; 01523 } 01524 if (strncmp(Line,"Rotation factor:",15) == 0 && w >= 0 && w < NUMWIN) 01525 { 01526 TrimCopy(Rotation,Line+15,79); 01527 MapLR[w].f = atoi(Rotation); 01528 } 01529 if (strncmp(Line,"Palette:",8) == 0 && w >= 0 && w < NUMWIN) 01530 { 01531 TrimCopy(Palette,Line+8,79); 01532 for (i=0 ; i < PalTypes ; ++i) 01533 if (!strcmp(Palette,PalNames[i])) WinAtt[w].Palette = i; 01534 } 01535 01536 // Dimension for time axis 01537 01538 if (strncmp(Line,"DimT:" ,5) == 0) DimT = atoi(Line+5); 01539 01540 // Attributes of scalars for timeseries windows 01541 01542 if (strncmp(Line,"Name:" ,5) == 0 && s >= 0 && s < NUMSCALARS) 01543 TrimCopy(TSName[s],Line+5,79); 01544 if (strncmp(Line,"Sub:" ,4) == 0 && s >= 0 && s < NUMSCALARS) 01545 TrimCopy(TSubsc[s],Line+4,79); 01546 if (strncmp(Line,"Unit:" ,5) == 0 && s >= 0 && s < NUMSCALARS) 01547 TrimCopy(TSUnit[s],Line+5,79); 01548 if (strncmp(Line,"Scale:",6) == 0 && s >= 0 && s < NUMSCALARS) 01549 TrimCopy(TScale[s],Line+6,79); 01550 01551 // Attributes of parameter in change menu 01552 01553 if (strncmp(Line,"ParName:",8) == 0 && p >= 0 && p < PARCS) 01554 TrimCopy(Parc[p].Name,Line+8,6); 01555 if (strncmp(Line,"ParInc:" ,7) == 0 && p >= 0 && p < PARCS) 01556 Parc[p].Inc = atof(Line+7); 01557 if (strncmp(Line,"ParMin:" ,7) == 0 && p >= 0 && p < PARCS) 01558 Parc[p].Min = atof(Line+7); 01559 if (strncmp(Line,"ParMax:" ,7) == 0 && p >= 0 && p < PARCS) 01560 Parc[p].Max = atof(Line+7); 01561 if (strcmp(Parc[p].Name,"SELLON") == 0) Parc[p].Inc = 360.0 / (2.0 * Latitudes); 01562 } 01563 fclose(fp); 01564 return 0; 01565 } 01566 01567 01568 void CreateControlWindow(void) 01569 { 01570 int X,Y,W,H,B,D,x,y; 01571 char Title1[256]; 01572 char *WinconTitle1; 01573 char *WinconTitle3 = {"RUN finished - click on red stop button"}; 01574 Window Rootwin; 01575 Window Child; 01576 01577 strcpy(Title1,"Unknown model"); 01578 if (Model == 0) // PUMA 01579 { 01580 if (MRpid < 0) 01581 strcpy(Title1,"PUMA - KlimaCampus Hamburg"); 01582 else 01583 sprintf(Title1,"Run %d: PUMA - KlimaCampus Hamburg",MRpid); 01584 } 01585 else if (Model == 1) sprintf(Title1,"SAM - KlimaCampus"); 01586 else if (Model == 2) 01587 { 01588 if (MRpid < 0) 01589 sprintf(Title1,"Planet Simulator (%s) - KlimaCampus",PlanetName); 01590 else 01591 sprintf(Title1,"Run %d: Planet Simulator (%s) - KlimaCampus",MRpid,PlanetName); 01592 } 01593 else if (Model == 3) sprintf(Title1,"Planet Simulator / LSG - KlimaCampus"); 01594 else printf("*** unknown model number %d in pumax ***\n",Model); 01595 WinconTitle1 = Title1; 01596 if (CowW < 920 || CowW > ScreenW) CowW = 920; 01597 if (NumWin < 5) CowH = 6 * FixFontHeight + 5; 01598 else CowH = NumWin * FixFontHeight + 5; 01599 if (CowX < 0 || CowX > ScreenW - CowW) CowX = (ScreenW - CowW) / 2; 01600 if (CowY < 0 || CowY > ScreenBot - CowH - WinTM - WinBM) CowY = ScreenBot - CowH - WinTM - WinBM; 01601 CowSizeHints.flags = PPosition | PSize | PMinSize | PMaxSize; 01602 CowSizeHints.min_width = CowW; 01603 CowSizeHints.min_height = CowH; 01604 CowSizeHints.max_width = ScreenW - WinLM - WinRM; 01605 CowSizeHints.max_height = CowH; 01606 if (MRnum == 2 && MRpid == 1) CowX += ScreenW; 01607 if (Debug) printf("Control Window %d/%d %dx%d\n",CowX,CowY,CowW,CowH); 01608 Cow = XCreateWindow(display,RootWindow(display,screen_num), // display, parent 01609 CowX,CowY,CowW,CowH, 01610 BorderWidth,CopyFromParent,InputOutput, // border, depth, class 01611 CopyFromParent,0,NULL); // visual, valuemask, attributes 01612 XStringListToTextProperty(&WinconTitle1,1,&WinconName1); 01613 XStringListToTextProperty(&WinconTitle3,1,&WinconName3); 01614 XStringListToTextProperty(&PauseTitle,1,&WinconPause); 01615 XStringListToTextProperty(&ReadyTitle,1,&WinconReady); 01616 XSetWMProtocols(display,Cow,&Delwin,1); 01617 XSetWMProperties(display,Cow,&WinconName1,NULL, 01618 NULL,0,&CowSizeHints,&wm_hints,&class_hints); 01619 XSelectInput(display,Cow,ButtonPressMask | KeyPressMask | ExposureMask); 01620 XMapWindow(display,Cow); 01621 } 01622 01623 01624 void ShowStep(void) 01625 { 01626 char Text[80]; 01627 XSetFont(display, gc, BigFont->fid); 01628 XSetForeground(display,gc,BlackPix); 01629 XSetBackground(display,gc,Grey.pixel); 01630 ntocdat(); 01631 if (ndatim[5] == 6) XSetForeground(display,gc,Red.pixel); // sunday 01632 XDrawImageString(display,Cow,gc,10,BigFontHeight,datch,strlen(datch)); 01633 XSetForeground(display,gc,BlackPix); 01634 if (ShowQueue) 01635 { 01636 sprintf(Text,"%8d Events ",XPending(display)); 01637 XDrawImageString(display,Cow,gc,10,60 + BigFontHeight,Text,strlen(Text)); 01638 } 01639 else if (fps > 1) 01640 { 01641 if (SkipFreq < 2) sprintf(Text,"%5d fps",fps); 01642 else sprintf(Text,"%5d fps [%d]",fps,SkipFreq); 01643 XDrawImageString(display,Cow,gc,10,60 + BigFontHeight,Text,strlen(Text)); 01644 } 01645 } 01646 01647 01648 int FormatVal(char *Name, float V, char *Text) 01649 { 01650 char Format[80]; 01651 01652 if (V > 9999.9 || V < -999.9) 01653 { 01654 sprintf(Text,"%6.6s = *****",Name); 01655 return strlen(Text); 01656 } 01657 else if (V > 999.99 ) strcpy(Format,"%6.6s =%6.1f"); 01658 else if (V > 99.999 ) strcpy(Format,"%6.6s =%6.2f"); 01659 else if (V > 9.9999) strcpy(Format,"%6.6s =%6.3f"); 01660 else if (V > 0.0 ) strcpy(Format,"%6.6s =%6.4f"); 01661 else if (V > -9.9 ) strcpy(Format,"%6.6s =%6.3f"); 01662 else if (V > -99.9 ) strcpy(Format,"%6.6s =%6.2f"); 01663 else strcpy(Format,"%6.6s =%6.1f"); 01664 01665 sprintf(Text,Format,Name,V); 01666 return strlen(Text); 01667 } 01668 01669 01670 void ShowParcs(void) 01671 { 01672 char Text[80]; 01673 int len; 01674 float V; 01675 01676 XSetFont(display, gc, BigFont->fid); 01677 len = FormatVal(Parc[cpi].Name,Parc[cpi].Val,Text); 01678 01679 XSetBackground(display,gc,WhitePix); 01680 XSetForeground(display,gc,Red.pixel); 01681 XFillRectangle(display,Cow,gc,Minus_XL,Minus_YL,Minus_XH-Minus_XL,Minus_YH-Minus_YL); 01682 XFillRectangle(display,Cow,gc,FBWD_XL,FBWD_YL,FBWD_XH-FBWD_XL,FBWD_YH-FBWD_YL); 01683 XSetForeground(display,gc,WhitePix); 01684 XFillRectangle(display,Cow,gc,Minus_XL+3,(Minus_YH+Minus_YL)/2-1,Minus_XH-Minus_XL-5,3); 01685 XFillRectangle(display,Cow,gc,FBWD_XL+3,(FBWD_YH+FBWD_YL)/2-1,FBWD_XH-FBWD_XL-5,3); 01686 XSetForeground(display,gc,BlackPix); 01687 XDrawImageString(display,Cow,gc,Parc_XL,Parc_YH-3,Text,len); 01688 XSetForeground(display,gc,Green.pixel); 01689 XFillRectangle(display,Cow,gc,Plus_XL,Plus_YL,Plus_XH-Plus_XL,Plus_YH-Plus_YL); 01690 XFillRectangle(display,Cow,gc,FFWD_XL,FFWD_YL,FFWD_XH-FFWD_XL,FFWD_YH-FFWD_YL); 01691 XSetForeground(display,gc,WhitePix); 01692 XFillRectangle(display,Cow,gc,Plus_XL+3,(Plus_YH+Plus_YL)/2-1,Plus_XH-Plus_XL-5,3); 01693 XFillRectangle(display,Cow,gc,FFWD_XL+3,(FFWD_YH+FFWD_YL)/2-1,FFWD_XH-FFWD_XL-5,3); 01694 XFillRectangle(display,Cow,gc,(Plus_XH+Plus_XL)/2-1,Plus_YL+3,3,Plus_YH-Plus_YL-5); 01695 XFillRectangle(display,Cow,gc,(FFWD_XH+FFWD_XL)/2-1,FFWD_YL+3,3,FFWD_YH-FFWD_YL-5); 01696 XSetForeground(display,gc,BlackPix); 01697 XDrawRectangle(display,Cow,gc,Minus_XL,Minus_YL,Minus_XH-Minus_XL,Minus_YH-Minus_YL); 01698 XDrawRectangle(display,Cow,gc,FBWD_XL,FBWD_YL,FBWD_XH-FBWD_XL,FBWD_YH-FBWD_YL); 01699 XDrawRectangle(display,Cow,gc,Parc_XL-1,Parc_YL-1,Parc_XH-Parc_XL+1,Parc_YH-Parc_YL); 01700 XDrawRectangle(display,Cow,gc,Plus_XL,Plus_YL,Plus_XH-Plus_XL,Plus_YH-Plus_YL); 01701 XDrawRectangle(display,Cow,gc,FFWD_XL,FFWD_YL,FFWD_XH-FFWD_XL,FFWD_YH-FFWD_YL); 01702 01703 /* Show next parameter */ 01704 01705 strcpy(Text," "); 01706 if (cpi < Parcs-1) FormatVal(Parc[cpi+1].Name,Parc[cpi+1].Val,Text); 01707 len = strlen(Text); 01708 01709 XSetBackground(display,gc,WhitePix); 01710 XSetForeground(display,gc,BlackPix); 01711 XDrawImageString(display,Cow,gc,Parc_XL,2*Parc_YH-Parc_YL-3,Text,len); 01712 XDrawRectangle(display,Cow,gc,Parc_XL-1,Parc_YH-1,Parc_XH-Parc_XL+1,Parc_YH-Parc_YL); 01713 01714 /* Show previous parameter */ 01715 01716 strcpy(Text," "); 01717 if (cpi > 0) FormatVal(Parc[cpi-1].Name,Parc[cpi-1].Val,Text); 01718 len = strlen(Text); 01719 01720 XSetBackground(display,gc,WhitePix); 01721 XSetForeground(display,gc,BlackPix); 01722 XDrawImageString(display,Cow,gc,Parc_XL,Parc_YL-3,Text,len); 01723 XDrawRectangle(display,Cow,gc,Parc_XL-1,2*Parc_YL-Parc_YH-1,Parc_XH-Parc_XL+1,Parc_YH-Parc_YL); 01724 XSetFont(display, gc, FixFont->fid); 01725 01726 } 01727 01728 01729 void CheckMark(int x, int y, int d) 01730 { 01731 XDrawLine(display,Cow,gc,x+2,y+2,x+d-1,y+d-1); 01732 XDrawLine(display,Cow,gc,x+3,y+2,x+d-1,y+d-2); 01733 XDrawLine(display,Cow,gc,x+2,y+3,x+d-2,y+d-1); 01734 01735 XDrawLine(display,Cow,gc,x+d-1,y+1,x+2,y+d-2); 01736 XDrawLine(display,Cow,gc,x+d-2,y+1,x+2,y+d-3); 01737 XDrawLine(display,Cow,gc,x+d-1,y+2,x+3,y+d-2); 01738 } 01739 01740 01741 void ShowWindowStatus(void) 01742 { 01743 char *cp; 01744 char Text[80]; 01745 int len,w,x,d; 01746 01747 XSetFont(display, gc, FixFont->fid); 01748 XSetForeground(display,gc,BlackPix); 01749 XSetBackground(display,gc,Grey.pixel); 01750 x = Wbox_XL; 01751 d = FixFontHeight; 01752 for (w=0 ; w < NumWin ; ++w) 01753 { 01754 strncpy(Text,WindowTitle[w]+wto,40); 01755 Text[40] = 0; 01756 cp = strstr(Text,"Level"); 01757 if (cp) *cp = 0; 01758 cp = strstr(Text,"Latitude"); 01759 if (cp) *cp = 0; 01760 len = strlen(Text); 01761 XDrawImageString(display,Cow,gc,x+20,(w+1) * d,Text,len); 01762 } 01763 XSetForeground(display,gc,WhitePix); 01764 for (w=0 ; w < NumWin ; ++w) 01765 { 01766 XFillRectangle(display,Cow,gc,x,w*d,d,d); 01767 } 01768 XSetForeground(display,gc,BlackPix); 01769 for (w=0 ; w < NumWin ; ++w) 01770 { 01771 XDrawRectangle(display,Cow,gc,x,w*d,d,d); 01772 } 01773 for (w=0 ; w < NumWin ; ++w) 01774 if (Win[w]) CheckMark(x,w*d,d); 01775 } 01776 01777 01778 void ShowGridStatus(void) 01779 { 01780 int x,y,d; 01781 01782 d = FixFontHeight; 01783 x = Grid_XL; 01784 y = Grid_YL; 01785 XSetFont(display, gc, FixFont->fid); 01786 XSetForeground(display,gc,BlackPix); 01787 XSetBackground(display,gc,Grey.pixel); 01788 XDrawImageString(display,Cow,gc,Grid_XH+FixFontWidth,Grid_YH,"Grid",4); 01789 XSetForeground(display,gc,WhitePix); 01790 XFillRectangle(display,Cow,gc,x,Grid_YL,d,d); 01791 XSetForeground(display,gc,BlackPix); 01792 XDrawRectangle(display,Cow,gc,x,Grid_YL,d,d); 01793 01794 if (Grid) CheckMark(x,y,d); 01795 } 01796 01797 01798 int RedrawControlWindow(void) 01799 { 01800 char Text[80]; 01801 int status,WinXSize,WinYSize,font_height,width,len; 01802 int i,j,x1,x2,y1,y2,y3; 01803 XWindowAttributes CurAtt; 01804 01805 status = XGetWindowAttributes(display,Cow,&CurAtt); 01806 WinXSize = CurAtt.width; 01807 WinYSize = CurAtt.height; 01808 01809 XSetForeground(display,gc,BlackPix); 01810 XSetBackground(display,gc,WhitePix); 01811 01812 XSetWindowBackground(display,Cow,Grey.pixel); 01813 XClearWindow(display,Cow); 01814 01815 /* Red stop button */ 01816 01817 XSetForeground(display,gc,Red.pixel); 01818 XFillPolygon(display,Cow,gc,StopButton,4,Convex,CoordModeOrigin); 01819 XSetForeground(display,gc,WhitePix); 01820 x1 = StopButton[0].x ; 01821 y1 = StopButton[0].y ; 01822 for (j=0 ; j < PSDIM ; ++j) 01823 for (i=0 ; i < PSDIM ; ++i) 01824 if (pixelstar[j][i] == '*') 01825 XDrawPoint(display,Cow,gc,i+x1,j+y1); 01826 01827 XSetForeground(display,gc,LightRed.pixel); 01828 x1 = 10; x2 = 40 ; y1 = OffsetY + 10 ; y2 = OffsetY + 40; 01829 XDrawLine(display,Cow,gc,x2 ,y1-1,x2 ,y2 ); 01830 XDrawLine(display,Cow,gc,x2+1,y1-2,x2+1,y2+1); 01831 XDrawLine(display,Cow,gc,x1-1,y1-1,x2 ,y1-1); 01832 XDrawLine(display,Cow,gc,x2+1,y2-2,x2+1,y1-2); 01833 XSetForeground(display,gc,DarkRed.pixel); 01834 XDrawLine(display,Cow,gc,x1-1,y1-1,x1-1,y2 ); 01835 XDrawLine(display,Cow,gc,x1-2,y1-2,x1-2,y2+1); 01836 XDrawLine(display,Cow,gc,x1-1,y2 ,x2 ,y2 ); 01837 XDrawLine(display,Cow,gc,x1-2,y2+1,x2+1,y2+1); 01838 01839 // Green <play> button 01840 01841 XSetForeground(display,gc,Green.pixel); 01842 XFillPolygon(display,Cow,gc,StartButton,3,Convex,CoordModeOrigin); 01843 x1 = 50; x2 = 80 ; y1 = OffsetY + 10 ; y2 = OffsetY + 25; y3 = OffsetY + 40; 01844 XSetForeground(display,gc,LightGreen.pixel); 01845 XDrawLine(display,Cow,gc,x1 ,y1-1,x2 ,y2 ); 01846 XDrawLine(display,Cow,gc,x1 ,y1-2,x2+1,y2 ); 01847 XSetForeground(display,gc,DarkGreen.pixel); 01848 XDrawLine(display,Cow,gc,x1-1,y1-1,x1-1,y3+1); 01849 XDrawLine(display,Cow,gc,x1-2,y1-2,x1-2,y3+2); 01850 01851 // Blue <pause> button 01852 01853 XSetForeground(display,gc,Blue.pixel); 01854 XFillPolygon(display,Cow,gc,PauseButton1,4,Convex,CoordModeOrigin); 01855 XFillPolygon(display,Cow,gc,PauseButton2,4,Convex,CoordModeOrigin); 01856 01857 x1 = 95; x2 = 102; y1 = OffsetY + 10; y2 = OffsetY + 40; 01858 XSetForeground(display,gc,DarkBlue.pixel); 01859 XDrawLine(display,Cow,gc,x1-1,y1-1,x1-1,y2 ); 01860 XDrawLine(display,Cow,gc,x1-2,y1-2,x1-2,y2+1); 01861 XDrawLine(display,Cow,gc,x1-1,y2 ,x2 ,y2 ); 01862 XDrawLine(display,Cow,gc,x1-2,y2+1,x2+1,y2+1); 01863 XSetForeground(display,gc,LightBlue.pixel); 01864 XDrawLine(display,Cow,gc,x2 ,y1-1,x2 ,y2 ); 01865 XDrawLine(display,Cow,gc,x2+1,y1-2,x2+1,y2+1); 01866 XDrawLine(display,Cow,gc,x1-1,y1-1,x2 ,y1-1); 01867 XDrawLine(display,Cow,gc,x2+1,y2-2,x2+1,y1-2); 01868 01869 x1 = 108; x2 = 115; y1 = OffsetY + 10; y2 = OffsetY + 40; 01870 XSetForeground(display,gc,DarkBlue.pixel); 01871 XDrawLine(display,Cow,gc,x1-1,y1-1,x1-1,y2 ); 01872 XDrawLine(display,Cow,gc,x1-2,y1-2,x1-2,y2+1); 01873 XDrawLine(display,Cow,gc,x1-1,y2 ,x2 ,y2 ); 01874 XDrawLine(display,Cow,gc,x1-2,y2+1,x2+1,y2+1); 01875 XSetForeground(display,gc,LightBlue.pixel); 01876 XDrawLine(display,Cow,gc,x2 ,y1-1,x2 ,y2 ); 01877 XDrawLine(display,Cow,gc,x2+1,y1-2,x2+1,y2+1); 01878 XDrawLine(display,Cow,gc,x1-1,y1-1,x2 ,y1-1); 01879 XDrawLine(display,Cow,gc,x2+1,y2-2,x2+1,y1-2); 01880 01881 // Help button 01882 01883 x1 = 200; x2 = x1 + 5 * BigFontWidth; y1 = OffsetY + 10; y2 = y1 + 30; 01884 XSetForeground(display,gc,Red.pixel); 01885 XFillRectangle(display,Cow,gc,x1,y1,x2-x1,y2-y1); 01886 XSetForeground(display,gc,BlackPix); 01887 XDrawRectangle(display,Cow,gc,x1-1,y1-1,x2-x1+1,y2-y1+1); 01888 XSetFont(display,gc,BigFont->fid); 01889 XSetForeground(display,gc,Yellow.pixel); 01890 XSetBackground(display,gc,Red.pixel); 01891 XDrawImageString(display,Cow,gc,x1+BigFontWidth/2,(y1+y2)/2+BigFont->ascent/2,"HELP",4); 01892 01893 ShowStep(); 01894 ShowParcs(); 01895 ShowWindowStatus(); 01896 ShowGridStatus(); 01897 return 0; 01898 } 01899 01900 01901 void ClearTracer(void) 01902 { 01903 int j; 01904 for (j=0 ; j < MAXPAR ; ++j) 01905 { 01906 pax[j] = -1.0; 01907 pay[j] = -1.0; 01908 } 01909 } 01910 01911 01912 int CheckEndianess(void) 01913 { 01914 union EndianCheck 01915 { 01916 char b[sizeof(int)]; 01917 int i; 01918 } ec; 01919 01920 ec.i = 8; 01921 return (ec.b[0] == 0); 01922 } 01923 01924 01925 void initgui_(int *model, int *debug, int *lats, int *mrpid, int *mrnum) 01926 { 01927 int x,y,w,h; 01928 int argc = 1; 01929 int i,j; 01930 unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */ 01931 XGCValues values; 01932 XEvent Event; 01933 struct timeval TimeVal; 01934 01935 // Check for big endian computer 01936 // The bitmap format ".bmp" ist little endian 01937 01938 BigEndian = CheckEndianess(); 01939 01940 // Set seed for random number generator from clock 01941 01942 gettimeofday(&TimeVal,NULL); 01943 Seed = TimeVal.tv_sec; 01944 01945 Model = *model; 01946 Debug = *debug; 01947 Latitudes = *lats; 01948 MRpid = *mrpid; 01949 MRnum = *mrnum; 01950 01951 if (MRpid >= 0) 01952 { 01953 sprintf(wtrun,"[%d] ",MRpid); 01954 wto = strlen(wtrun); 01955 } 01956 01957 if (Debug) printf("initgui(%d,%d)\n",Model,Debug); 01958 if ((display=XOpenDisplay(display_name)) == NULL) 01959 { 01960 fprintf(stderr,"%s: cannot connect to X server %s\n", 01961 progname, XDisplayName(display_name)); 01962 exit(1); 01963 } 01964 screen_num = DefaultScreen(display); 01965 ScreenD = XDefaultDepth(display,screen_num); 01966 ScreenW = DisplayWidth (display,screen_num); 01967 ScreenH = DisplayHeight(display,screen_num); 01968 BlackPix = BlackPixel(display,screen_num); 01969 WhitePix = WhitePixel(display,screen_num); 01970 SmallScreen = ScreenH <= 768; 01971 if (SmallScreen) 01972 { 01973 WinRows = 2; 01974 NumWin = WinCols * WinRows; 01975 Grid = 0; 01976 } 01977 01978 if (MRnum == 2) ScreenW /= 2; /* Run with two GUI's */ 01979 01980 /* Fix defaults for multihead displays */ 01981 01982 if (ScreenH > ScreenW && ScreenH > 1200) ScreenH = 1200; 01983 if (ScreenW > 2 * ScreenH && ScreenW >= 2048) ScreenW /= 2; 01984 01985 for (i = 0 ; i < NUMWIN ; ++i) 01986 { 01987 WindowTitle[i] = CharAlloc(256,"WindowTitle"); 01988 if (wto == 0) sprintf(WindowTitle[i],"Window %d",i+1); 01989 else sprintf(WindowTitle[i],"%sWindow %d",wtrun,i+1); 01990 WinAtt[i].x = -1; 01991 WinAtt[i].y = -1; 01992 WinAtt[i].w = -1; 01993 WinAtt[i].h = -1; 01994 WinAtt[i].active = 1; 01995 } 01996 01997 CreateTestWindow(); 01998 01999 if (MRpid >= 0) sprintf(GUI_default,"GUI_%2.2d.cfg",MRpid); 02000 ReadConfig(GUI_default); 02001 if (MRpid >= 0) sprintf(GUI_config,"GUI_last_used_%2.2d.cfg",MRpid); 02002 ReadConfig(GUI_config); 02003 02004 LoadFonts(); 02005 CreateControlWindow(); 02006 02007 OutXSize = (ScreenW-ScreenOffset) / WinCols; 02008 OutYSize = (CowY-ScreenOffset-1-WM_top_area) / WinRows; 02009 WinXSize = OutXSize - WinLM - WinRM; 02010 WinYSize = OutYSize - WinTM - WinBM; 02011 WinSizeHints.flags = PPosition | PSize | PMinSize; 02012 WinSizeHints.min_width = 200; 02013 WinSizeHints.min_height = 100; 02014 if (Debug) 02015 { 02016 printf("Outer windowsize = %dx%d\n",OutXSize,OutYSize); 02017 printf("Inner windowsize = %dx%d\n",WinXSize,WinYSize); 02018 } 02019 02020 wm_hints.initial_state = NormalState; 02021 wm_hints.input = True; 02022 wm_hints.flags = StateHint | InputHint; 02023 02024 class_hints.res_name = progname; 02025 class_hints.res_class = "PUMA"; 02026 02027 Delwin = XInternAtom(display,"WM_DELETE_WINDOW",0); 02028 02029 ReadImage(&MapHR,"map.bmp"); 02030 02031 for (i = 0 ; i < NumWin ; ++i) 02032 { 02033 x = WinAtt[i].x; 02034 y = WinAtt[i].y; 02035 w = WinAtt[i].w; 02036 h = WinAtt[i].h; 02037 02038 if (x < ScreenOffset || x >= ScreenW) x = ScreenOffset+(i%WinCols)*OutXSize; 02039 if (y < ScreenOffset || y >= ScreenH) y = ScreenOffset+(i/WinCols)*OutYSize+WM_top_area; 02040 if (w < WinSizeHints.min_width ) w = WinXSize; 02041 if (h < WinSizeHints.min_height) h = WinYSize; 02042 XStringListToTextProperty(&WindowTitle[i],1,WindowName+i); 02043 if (WinAtt[i].active) 02044 { 02045 if (MRnum == 2 && MRpid == 1) x += ScreenW; 02046 Win[i] = XCreateWindow(display,RootWindow(display,screen_num), // display, parent 02047 x,y,w,h, 02048 BorderWidth,CopyFromParent,InputOutput, // border, depth, class 02049 CopyFromParent,0,NULL); // visual, valuemask, attributes 02050 XSetWMProtocols(display,Win[i],&Delwin,1); 02051 XSetWMProperties(display,Win[i],WindowName+i,NULL, 02052 NULL,0,&WinSizeHints,&wm_hints,&class_hints); 02053 XSelectInput(display,Win[i],ButtonPressMask | KeyPressMask | ExposureMask); 02054 XMapWindow(display,Win[i]); 02055 } 02056 } 02057 02058 /* Prepare GC */ 02059 02060 gc = XCreateGC(display, Cow, valuemask, &values); 02061 XSetFont(display, gc, FixFont->fid); 02062 colormap = XDefaultColormap(display,screen_num); 02063 XSetForeground(display,gc,BlackPix); 02064 XSetBackground(display,gc,WhitePix); 02065 02066 /* Get keyboard information */ 02067 02068 XDisplayKeycodes(display,&FirstKey,&LastKey); 02069 KeyMap = XGetKeyboardMapping(display,FirstKey,LastKey-FirstKey+1,&SymsPerKey); 02070 02071 /* Allocate color cells */ 02072 02073 for (i=0 ; i < NUMPAL ; ++i) 02074 LineCo[i] = AllocateColorCells(Pallet[i]); 02075 02076 /* Color cells for control window */ 02077 02078 XAllocNamedColor(display,colormap,"red" ,&Red ,&Dummy); 02079 XAllocNamedColor(display,colormap,"green" ,&Green ,&Dummy); 02080 XAllocNamedColor(display,colormap,"blue" ,&Blue ,&Dummy); 02081 XAllocNamedColor(display,colormap,"grey" ,&Grey ,&Dummy); 02082 XAllocNamedColor(display,colormap,"yellow" ,&Yellow ,&Dummy); 02083 XAllocNamedColor(display,colormap,"hot pink" ,&LightRed ,&Dummy); 02084 XAllocNamedColor(display,colormap,"dark red" ,&DarkRed ,&Dummy); 02085 XAllocNamedColor(display,colormap,"light blue" ,&LightBlue ,&Dummy); 02086 XAllocNamedColor(display,colormap,"dark blue" ,&DarkBlue ,&Dummy); 02087 XAllocNamedColor(display,colormap,"light green",&LightGreen,&Dummy); 02088 XAllocNamedColor(display,colormap,"dark green" ,&DarkGreen ,&Dummy); 02089 02090 TSColor[0] = Red.pixel; 02091 TSColor[1] = Green.pixel; 02092 TSColor[2] = Blue.pixel; 02093 TSColor[3] = WhitePix; 02094 TSColor[4] = LightRed.pixel; 02095 TSColor[5] = Grey.pixel; 02096 TSColor[6] = Yellow.pixel; 02097 TSColor[7] = LightBlue.pixel; 02098 TSColor[8] = LightGreen.pixel; 02099 02100 ClearTracer(); 02101 CalcButtonAreas(); 02102 RedrawControlWindow(); 02103 XSync(display,0); 02104 } 02105 02106 void FillPoly(int n, REAL Poly[]) 02107 { 02108 int i; 02109 XPoint xpol[8]; 02110 for (i=0; i < n ; ++i) 02111 { 02112 xpol[i].x = OffX + Poly[i+i ] + 0.5; 02113 xpol[i].y = OffY + Poly[i+i+1] + 0.5; 02114 } 02115 XFillPolygon(display,pix,gc,xpol,n,Convex,CoordModeOrigin); 02116 } 02117 02118 /* ======= */ 02119 /* IsoArea */ 02120 /* ======= */ 02121 02122 void IsoArea(INT y, REAL vl, REAL vh, REAL Top[], REAL Bot[], INT Dim) 02123 { 02124 INT f,x,p; 02125 REAL xl,xr,yt,yb; 02126 REAL Poly[16]; 02127 02128 // if (Debug) printf("IsoArea %d %10.2f %10.2f %10.2f %10.2f %d\n",y,vl,vh,Top[0],Bot[0],Dim); 02129 for (x=0 ; x < Dim-1 ; x++) 02130 { 02131 Flag[x] = 0; 02132 if (Top[x ] < vl) Flag[x] |= TOLELO; 02133 if (Top[x ] >= vh) Flag[x] |= TOLEHI; 02134 if (Top[x+1] < vl) Flag[x] |= TORILO; 02135 if (Top[x+1] >= vh) Flag[x] |= TORIHI; 02136 if (Bot[x ] < vl) Flag[x] |= BOLELO; 02137 if (Bot[x ] >= vh) Flag[x] |= BOLEHI; 02138 if (Bot[x+1] < vl) Flag[x] |= BORILO; 02139 if (Bot[x+1] >= vh) Flag[x] |= BORIHI; 02140 } 02141 02142 x = 0; 02143 02144 while (x < Dim-1) 02145 { 02146 xl = VGAX * x ; 02147 xr = VGAX * (x+1); 02148 yt = VGAY * y ; 02149 yb = VGAY * (y+1); 02150 f = Flag[x]; 02151 02152 if (f == 0) 02153 { 02154 x++; 02155 while (x < Dim-1 && Flag[x] == 0) 02156 { 02157 x++; 02158 xr = VGAX * x; 02159 } 02160 Poly[0] = Poly[6] = xl; 02161 Poly[1] = Poly[3] = yt; 02162 Poly[2] = Poly[4] = xr; 02163 Poly[5] = Poly[7] = yb; 02164 02165 FillPoly(4,Poly); 02166 02167 } 02168 else if (f == (TOLELO | TORILO | BOLELO | BORILO) || 02169 f == (TOLEHI | TORIHI | BOLEHI | BORIHI)) x++; 02170 else if (Top[x] < vl && Top[x+1] >= vl && Bot[x] >= vl && Bot[x+1] < vl) 02171 { 02172 Poly[1] = Poly[3] = yt; 02173 Poly[2] = Poly[4] = xr; 02174 Poly[0] = IPX(Top[x ],vl,Top[x+1]); 02175 Poly[5] = IPY(Top[x+1],vl,Bot[x+1]); 02176 FillPoly(3,Poly); 02177 Poly[1] = Poly[3] = yb; 02178 Poly[2] = Poly[4] = xl; 02179 Poly[0] = IPX(Bot[x ],vl,Bot[x+1]); 02180 Poly[5] = IPY(Top[x ],vl,Bot[x ]); 02181 FillPoly(3,Poly); 02182 ++x; 02183 } 02184 else if (Top[x] >= vl && Top[x+1] < vl && Bot[x] < vl && Bot[x+1] >= vl) 02185 { 02186 Poly[0] = Poly[4] = xl; 02187 Poly[1] = Poly[3] = yt; 02188 Poly[2] = IPX(Top[x ],vl,Top[x+1]); 02189 Poly[5] = IPY(Top[x ],vl,Bot[x ]); 02190 FillPoly(3,Poly); 02191 Poly[0] = Poly[2] = xr; 02192 Poly[3] = Poly[5] = yb; 02193 Poly[1] = IPY(Top[x+1],vl,Bot[x+1]); 02194 Poly[4] = IPX(Bot[x ],vl,Bot[x+1]); 02195 FillPoly(3,Poly); 02196 ++x; 02197 } 02198 else 02199 { 02200 p = 0; 02201 02202 if (Top[x] < vl) 02203 { 02204 if (Top[x+1] >= vl) 02205 { 02206 Poly[p++] = IPX(Top[x],vl,Top[x+1]); 02207 Poly[p++] = yt; 02208 } 02209 02210 if (Top[x+1] >= vh) 02211 { 02212 Poly[p++] = IPX(Top[x],vh,Top[x+1]); 02213 Poly[p++] = yt; 02214 } 02215 } 02216 else if (Top[x] >= vh) 02217 { 02218 if (Top[x+1] < vh) 02219 { 02220 Poly[p++] = IPX(Top[x],vh,Top[x+1]); 02221 Poly[p++] = yt; 02222 } 02223 if (Top[x+1] < vl) 02224 { 02225 Poly[p++] = IPX(Top[x],vl,Top[x+1]); 02226 Poly[p++] = yt; 02227 } 02228 } 02229 else 02230 { 02231 Poly[p++] = xl; 02232 Poly[p++] = yt; 02233 if (Top[x+1] < vl) 02234 { 02235 Poly[p++] = IPX(Top[x],vl,Top[x+1]); 02236 Poly[p++] = yt; 02237 } 02238 if (Top[x+1] >= vh) 02239 { 02240 Poly[p++] = IPX(Top[x],vh,Top[x+1]); 02241 Poly[p++] = yt; 02242 } 02243 } 02244 02245 if (Top[x+1] < vl) 02246 { 02247 if (Bot[x+1] >= vl) 02248 { 02249 Poly[p++] = xr; 02250 Poly[p++] = IPY(Top[x+1],vl,Bot[x+1]); 02251 } 02252 02253 if (Bot[x+1] >= vh) 02254 { 02255 Poly[p++] = xr; 02256 Poly[p++] = IPY(Top[x+1],vh,Bot[x+1]); 02257 } 02258 } 02259 else if (Top[x+1] >= vh) 02260 { 02261 if (Bot[x+1] < vh) 02262 { 02263 Poly[p++] = xr; 02264 Poly[p++] = IPY(Top[x+1],vh,Bot[x+1]); 02265 } 02266 if (Bot[x+1] < vl) 02267 { 02268 Poly[p++] = xr; 02269 Poly[p++] = IPY(Top[x+1],vl,Bot[x+1]); 02270 } 02271 } 02272 else 02273 { 02274 Poly[p++] = xr; 02275 Poly[p++] = yt; 02276 if (Bot[x+1] < vl) 02277 { 02278 Poly[p++] = xr; 02279 Poly[p++] = IPY(Top[x+1],vl,Bot[x+1]); 02280 } 02281 if (Bot[x+1] >= vh) 02282 { 02283 Poly[p++] = xr; 02284 Poly[p++] = IPY(Top[x+1],vh,Bot[x+1]); 02285 } 02286 } 02287 02288 if (Bot[x+1] < vl) 02289 { 02290 if (Bot[x] >= vl) 02291 { 02292 Poly[p++] = IPX(Bot[x],vl,Bot[x+1]); 02293 Poly[p++] = yb; 02294 } 02295 if (Bot[x] >= vh) 02296 { 02297 Poly[p++] = IPX(Bot[x],vh,Bot[x+1]); 02298 Poly[p++] = yb; 02299 } 02300 } 02301 else if (Bot[x+1] >= vh) 02302 { 02303 if (Bot[x] < vh) 02304 { 02305 Poly[p++] = IPX(Bot[x],vh,Bot[x+1]); 02306 Poly[p++] = yb; 02307 } 02308 if (Bot[x] < vl) 02309 { 02310 Poly[p++] = IPX(Bot[x],vl,Bot[x+1]); 02311 Poly[p++] = yb; 02312 } 02313 } 02314 else 02315 { 02316 Poly[p++] = xr; 02317 Poly[p++] = yb; 02318 if (Bot[x] < vl) 02319 { 02320 Poly[p++] = IPX(Bot[x],vl,Bot[x+1]); 02321 Poly[p++] = yb; 02322 } 02323 if (Bot[x] >= vh) 02324 { 02325 Poly[p++] = IPX(Bot[x],vh,Bot[x+1]); 02326 Poly[p++] = yb; 02327 } 02328 } 02329 02330 if (Bot[x] < vl) 02331 { 02332 if (Top[x] >= vl) 02333 { 02334 Poly[p++] = xl; 02335 Poly[p++] = IPY(Top[x],vl,Bot[x]); 02336 } 02337 02338 if (Top[x] >= vh) 02339 { 02340 Poly[p++] = xl; 02341 Poly[p++] = IPY(Top[x],vh,Bot[x]); 02342 } 02343 } 02344 else if (Bot[x] >= vh) 02345 { 02346 if (Top[x] < vh) 02347 { 02348 Poly[p++] = xl; 02349 Poly[p++] = IPY(Top[x],vh,Bot[x]); 02350 } 02351 if (Top[x] < vl) 02352 { 02353 Poly[p++] = xl; 02354 Poly[p++] = IPY(Top[x],vl,Bot[x]); 02355 } 02356 } 02357 else 02358 { 02359 Poly[p++] = xl; 02360 Poly[p++] = yb; 02361 if (Top[x] < vl) 02362 { 02363 Poly[p++] = xl; 02364 Poly[p++] = IPY(Top[x],vl,Bot[x]); 02365 } 02366 if (Top[x] >= vh) 02367 { 02368 Poly[p++] = xl; 02369 Poly[p++] = IPY(Top[x],vh,Bot[x]); 02370 } 02371 } 02372 FillPoly(p>>1,Poly); 02373 x++; 02374 } 02375 } 02376 } 02377 02378 02379 /* ======= */ 02380 /* isoarea */ 02381 /* ======= */ 02382 02383 void IsoAreas(struct ColorStrip Strip[]) 02384 { 02385 INT i; 02386 INT y; 02387 REAL *Top; 02388 REAL *Bot; 02389 02390 i = 0; 02391 while (Strip[i].Name) 02392 { 02393 Top = Field; 02394 Bot = Field + DimX; 02395 XSetForeground(display,gc,Strip[i].pixel); 02396 for (y = 0 ; y < DimY-1 ; y++) 02397 { 02398 IsoArea(y,Strip[i].Lo,Strip[i].Hi,Top,Bot,DimX); 02399 Top += DimX; 02400 Bot += DimX; 02401 } 02402 ++i; 02403 } 02404 } 02405 02406 /* ======= */ 02407 /* IsoLine */ 02408 /* ======= */ 02409 02410 void IsoLine(INT y, REAL v, REAL Top[], REAL Bot[], INT Dim) 02411 { 02412 INT f,x; 02413 REAL xl,xr,yt,yb; 02414 REAL x1,yo,x2,y2,x3,y3,x4,y4; 02415 02416 for (x=0 ; x < Dim-1 ; x++) 02417 { 02418 Flag[x] = 0; 02419 if (Top[x ] < v) Flag[x] |= TOLELO; 02420 else Flag[x] |= TOLEHI; 02421 if (Top[x+1] < v) Flag[x] |= TORILO; 02422 else Flag[x] |= TORIHI; 02423 if (Bot[x ] < v) Flag[x] |= BOLELO; 02424 else Flag[x] |= BOLEHI; 02425 if (Bot[x+1] < v) Flag[x] |= BORILO; 02426 else Flag[x] |= BORIHI; 02427 } 02428 02429 x = 0; 02430 02431 while (x < Dim-1) 02432 { 02433 xl = VGAX * x ; 02434 xr = VGAX * (x+1); 02435 yt = VGAY * y ; 02436 yb = VGAY * (y+1); 02437 f = Flag[x]; 02438 02439 if (f == 0 || f == (TOLELO | TORILO | BOLELO | BORILO) || 02440 f == (TOLEHI | TORIHI | BOLEHI | BORIHI)) x++; 02441 else if (f == (TOLELO | BORILO | TORIHI | BOLEHI)) 02442 { 02443 x1 = IPX(Top[x ],v,Top[x+1]); 02444 yo = yt; 02445 x2 = xr; 02446 y2 = IPY(Top[x+1],v,Bot[x+1]); 02447 x3 = IPX(Bot[x ],v,Bot[x+1]); 02448 y3 = yb; 02449 x4 = xl; 02450 y4 = IPY(Top[x ],v,Bot[x ]); 02451 XDrawLine(display,pix,gc,x1,OffY+yo,x2,OffY+y2); 02452 XDrawLine(display,pix,gc,x3,OffY+y3,x4,OffY+y4); 02453 ++x; 02454 } 02455 else if (f == (TORILO | BOLELO | TOLEHI | BORIHI)) 02456 { 02457 x1 = xl; 02458 yo = IPY(Top[x ],v,Bot[x ]); 02459 x2 = IPX(Top[x ],v,Top[x+1]); 02460 y2 = yt; 02461 x3 = xr; 02462 y3 = IPY(Top[x+1],v,Bot[x+1]); 02463 x4 = IPX(Bot[x ],v,Bot[x+1]); 02464 y4 = yb; 02465 XDrawLine(display,pix,gc,x1,OffY+yo,x2,OffY+y2); 02466 XDrawLine(display,pix,gc,x3,OffY+y3,x4,OffY+y4); 02467 ++x; 02468 } 02469 else 02470 { 02471 x1 = x2 = x3 = x4 = -1; 02472 02473 if (Top[x ] < v && Top[x+1] >= v || Top[x ] >= v && Top[x+1] < v) 02474 { 02475 x1 = IPX(Top[x ],v,Top[x+1]); 02476 yo = yt; 02477 } 02478 if (Top[x+1] < v && Bot[x+1] >= v || Top[x+1] >= v && Bot[x+1] < v) 02479 { 02480 x2 = xr; 02481 y2 = IPY(Top[x+1],v,Bot[x+1]); 02482 } 02483 if (Bot[x+1] < v && Bot[x ] >= v || Bot[x+1] >= v && Bot[x ] < v) 02484 { 02485 x3 = IPX(Bot[x ],v,Bot[x+1]); 02486 y3 = yb; 02487 } 02488 if (Bot[x ] < v && Top[x ] >= v || Bot[x ] >= v && Top[x ] < v) 02489 { 02490 x4 = xl; 02491 y4 = IPY(Top[x ],v,Bot[x ]); 02492 } 02493 02494 if (x1 >= 0 && x2 >= 0 && x3 >= 0 && x4 >= 0) 02495 { 02496 XDrawLine(display,pix,gc,x1,OffY+yo,x2,OffY+y2); 02497 XDrawLine(display,pix,gc,x3,OffY+y3,x4,OffY+y4); 02498 } 02499 else if (x1 >= 0) 02500 { 02501 if (x2 >= 0) XDrawLine(display,pix,gc,x1,OffY+yo,x2,OffY+y2); 02502 else if (x3 >= 0) XDrawLine(display,pix,gc,x1,OffY+yo,x3,OffY+y3); 02503 else XDrawLine(display,pix,gc,x1,OffY+yo,x4,OffY+y4); 02504 } 02505 else if (x2 >= 0) 02506 { 02507 if (x3 >= 0) XDrawLine(display,pix,gc,x2,OffY+y2,x3,OffY+y3); 02508 else XDrawLine(display,pix,gc,x2,OffY+y2,x4,OffY+y4); 02509 } 02510 else XDrawLine(display,pix,gc,x3,OffY+y3,x4,OffY+y4); 02511 02512 x++; 02513 } 02514 } 02515 } 02516 02517 02518 /* ======== */ 02519 /* IsoLines */ 02520 /* ======== */ 02521 02522 void IsoLines(struct ColorStrip Strip[],int Colored) 02523 { 02524 INT i; 02525 INT y; 02526 REAL *Top; 02527 REAL *Bot; 02528 02529 XSetForeground(display,gc,BlackPix); 02530 i = 0; 02531 while (Strip[i].Name) 02532 { 02533 Top = Field; 02534 Bot = Field + DimX; 02535 if (Colored) XSetForeground(display,gc,Strip[i].pixel); 02536 for (y = 0 ; y < DimY-1 ; y++) 02537 { 02538 IsoLine(y,Strip[i].Lo,Top,Bot,DimX); 02539 Top += DimX; 02540 Bot += DimX; 02541 } 02542 ++i; 02543 } 02544 } 02545 02546 int AziPoint(int fpx, int fpy, int *x2, int *y2) 02547 { 02548 int xc,yc; 02549 double flam,fsin,fcos,roa,pil,piy; 02550 02551 xc = InXSize >> 1; 02552 yc = InYSize >> 1; 02553 roa = MapLR[win].l * InXSize / 360.0; 02554 pil = 2.0 * M_PI / InXSize; 02555 piy = M_PI / InYSize; 02556 02557 flam = (fpx - xc - roa) * pil; 02558 if (flam < -M_PI) flam += 2.0 * M_PI; 02559 if (flam > M_PI) flam -= 2.0 * M_PI; 02560 if (flam < -M_PI_2 || flam > M_PI_2) return 1; 02561 fsin = sin(flam); 02562 fcos = cos((fpy-yc) * piy); 02563 *x2 = xc + InYSize/2 * fcos * fsin; 02564 *y2 = yc + InYSize/2 * sin((fpy-yc) * piy); 02565 return 0; 02566 } 02567 02568 void AziLine(int x1, int y1, int x2, int y2) 02569 { 02570 int a1,b1,a2,b2; 02571 02572 if (AziPoint(x1,y1,&a1,&b1)) return; 02573 if (AziPoint(x2,y2,&a2,&b2)) return; 02574 XDrawLine(display,pix,gc,a1,b1,a2,b2); 02575 } 02576 02577 02578 /* ======= */ 02579 /* MapLine */ 02580 /* ======= */ 02581 02582 void MapLine(INT y, REAL v, REAL Top[], REAL Bot[], INT Dim) 02583 { 02584 INT f,x; 02585 REAL xl,xr,yt,yb; 02586 REAL x1,yo,x2,y2,x3,y3,x4,y4; 02587 02588 for (x=0 ; x < Dim-1 ; x++) 02589 { 02590 Flag[x] = 0; 02591 if (Top[x ] < v) Flag[x] |= TOLELO; 02592 else Flag[x] |= TOLEHI; 02593 if (Top[x+1] < v) Flag[x] |= TORILO; 02594 else Flag[x] |= TORIHI; 02595 if (Bot[x ] < v) Flag[x] |= BOLELO; 02596 else Flag[x] |= BOLEHI; 02597 if (Bot[x+1] < v) Flag[x] |= BORILO; 02598 else Flag[x] |= BORIHI; 02599 } 02600 02601 x = 0; 02602 02603 while (x < Dim-1) 02604 { 02605 xl = VGAX * x ; 02606 xr = VGAX * (x+1); 02607 yt = VGAY * y ; 02608 yb = VGAY * (y+1); 02609 f = Flag[x]; 02610 02611 if (f == 0 || f == (TOLELO | TORILO | BOLELO | BORILO) || 02612 f == (TOLEHI | TORIHI | BOLEHI | BORIHI)) x++; 02613 else if (f == (TOLELO | BORILO | TORIHI | BOLEHI)) 02614 { 02615 x1 = IPX(Top[x ],v,Top[x+1]); 02616 yo = yt; 02617 x2 = xr; 02618 y2 = IPY(Top[x+1],v,Bot[x+1]); 02619 x3 = IPX(Bot[x ],v,Bot[x+1]); 02620 y3 = yb; 02621 x4 = xl; 02622 y4 = IPY(Top[x ],v,Bot[x ]); 02623 AziLine(x1,OffY+yo,x2,OffY+y2); 02624 AziLine(x3,OffY+y3,x4,OffY+y4); 02625 ++x; 02626 } 02627 else if (f == (TORILO | BOLELO | TOLEHI | BORIHI)) 02628 { 02629 x1 = xl; 02630 yo = IPY(Top[x ],v,Bot[x ]); 02631 x2 = IPX(Top[x ],v,Top[x+1]); 02632 y2 = yt; 02633 x3 = xr; 02634 y3 = IPY(Top[x+1],v,Bot[x+1]); 02635 x4 = IPX(Bot[x ],v,Bot[x+1]); 02636 y4 = yb; 02637 AziLine(x1,OffY+yo,x2,OffY+y2); 02638 AziLine(x3,OffY+y3,x4,OffY+y4); 02639 ++x; 02640 } 02641 else 02642 { 02643 x1 = x2 = x3 = x4 = -1; 02644 02645 if (Top[x ] < v && Top[x+1] >= v || Top[x ] >= v && Top[x+1] < v) 02646 { 02647 x1 = IPX(Top[x ],v,Top[x+1]); 02648 yo = yt; 02649 } 02650 if (Top[x+1] < v && Bot[x+1] >= v || Top[x+1] >= v && Bot[x+1] < v) 02651 { 02652 x2 = xr; 02653 y2 = IPY(Top[x+1],v,Bot[x+1]); 02654 } 02655 if (Bot[x+1] < v && Bot[x ] >= v || Bot[x+1] >= v && Bot[x ] < v) 02656 { 02657 x3 = IPX(Bot[x ],v,Bot[x+1]); 02658 y3 = yb; 02659 } 02660 if (Bot[x ] < v && Top[x ] >= v || Bot[x ] >= v && Top[x ] < v) 02661 { 02662 x4 = xl; 02663 y4 = IPY(Top[x ],v,Bot[x ]); 02664 } 02665 02666 if (x1 >= 0 && x2 >= 0 && x3 >= 0 && x4 >= 0) 02667 { 02668 AziLine(x1,OffY+yo,x2,OffY+y2); 02669 AziLine(x3,OffY+y3,x4,OffY+y4); 02670 } 02671 else if (x1 >= 0) 02672 { 02673 if (x2 >= 0) AziLine(x1,OffY+yo,x2,OffY+y2); 02674 else if (x3 >= 0) AziLine(x1,OffY+yo,x3,OffY+y3); 02675 else AziLine(x1,OffY+yo,x4,OffY+y4); 02676 } 02677 else if (x2 >= 0) 02678 { 02679 if (x3 >= 0) AziLine(x2,OffY+y2,x3,OffY+y3); 02680 else AziLine(x2,OffY+y2,x4,OffY+y4); 02681 } 02682 else AziLine(x3,OffY+y3,x4,OffY+y4); 02683 02684 x++; 02685 } 02686 } 02687 } 02688 02689 02690 /* ======== */ 02691 /* MapLines */ 02692 /* ======== */ 02693 02694 void MapLines(struct ColorStrip Strip[],int Colored) 02695 { 02696 INT i; 02697 INT y; 02698 REAL *Top; 02699 REAL *Bot; 02700 02701 XSetForeground(display,gc,BlackPix); 02702 i = 0; 02703 while (Strip[i].Name) 02704 { 02705 Top = Field; 02706 Bot = Field + DimX; 02707 if (Colored) XSetForeground(display,gc,Strip[i].pixel); 02708 for (y = 0 ; y < DimY-1 ; y++) 02709 { 02710 MapLine(y,Strip[i].Lo,Top,Bot,DimX); 02711 Top += DimX; 02712 Bot += DimX; 02713 } 02714 ++i; 02715 } 02716 } 02717 02718 int polco = 0; 02719 02720 void poltra(float lam, float phi, float *x, float *y) 02721 { 02722 REAL xnp,ynp,xsp,ysp,lfa; 02723 02724 lfa = (2.0 * M_PI) / (InXSize-1) ; 02725 xnp = (InXSize-1) * 0.25; 02726 ynp = (InYSize-1) * 0.50; 02727 xsp = (InXSize-1) * 0.75; 02728 ysp = ynp; 02729 02730 /* Northern hemisphere */ 02731 02732 if (phi < ynp) 02733 { 02734 *x = xnp + sin(lam * lfa) * phi; 02735 *y = ynp + cos(lam * lfa) * phi; 02736 } 02737 02738 /* Souhern hemisphere */ 02739 02740 else 02741 { 02742 *x = xsp - sin(lam * lfa) * (phi-ysp); 02743 *y = ysp + cos(lam * lfa) * (phi-ysp); 02744 } 02745 } 02746 02747 02748 /* ========== */ 02749 /* TracerPlot */ 02750 /* ========== */ 02751 02752 void TracerPlot(int w) 02753 { 02754 int j,ipx,ipy,lpy,lpx,jx,jy,ic,ix,iy,ipr; 02755 int xnp,ynp,xsp,ysp,xc,yc; 02756 float *u; 02757 float *v; 02758 float fpx,fpy,du,dv,ppx,ppy,rx,ry,spfac; 02759 float lfa,lam,phi,hpy,fcos,fsin; 02760 float pil,piy; 02761 float roa; 02762 float flam; 02763 float dpx,dpy; 02764 02765 if (Uindex < 0 || Vindex < 0) return; // Data missing 02766 02767 Delpar = (8 * 60) / DeltaTime; // Injection interval 02768 if (LevelChanged[w]) ClearTracer(); 02769 LevelChanged[w] = 0; 02770 if (!SpeedScale) SpeedScale = FloatAlloc(DimY,"SpeedScale"); 02771 u = Array[Uindex].Data + Indez[w] * DimXY; 02772 v = Array[Vindex].Data + Indez[w] * DimXY; 02773 02774 TracerColor = Yellow.pixel; 02775 if (nstep % (8*Delpar) == 0) ColInd++; 02776 if (ColInd >= AUTOCOLORS) ColInd = 0; 02777 TracerColor = Autostrip[ColInd].pixel; 02778 02779 dpx = (float)(InXSize-1) / (float)(DimX-1); 02780 dpy = (float)(InYSize-1) / (float)(DimY-1); 02781 lpx = InXSize; 02782 lpy = InYSize; 02783 hpy = 0.5 * dpy; 02784 xc = lpx / 2; 02785 yc = lpy / 2; 02786 ipr = InXSize / 400; 02787 pil = 2.0 * M_PI / lpx; 02788 piy = M_PI / lpy; 02789 roa = MapLR[w].l * lpx / 360.0; 02790 02791 // Compute scale factors 02792 02793 if (SizeChanged || nstep < 10) 02794 { 02795 for (j=0 ; j < DimY; ++j) 02796 { 02797 SpeedScale[j] = InXSize * DeltaTime * 60.0 / 40000000.0 02798 / cos((j-0.5*(DimY-1)) * (M_PI/DimY)); 02799 } 02800 SpeedScale[DimY-1] = SpeedScale[0] = SpeedScale[1]; 02801 } 02802 02803 // Insert new particles 02804 02805 if (nstep % Delpar == 0) 02806 { 02807 fpx = dpx * (DimX-1) / 2.0; 02808 for (ipy = 0 ; ipy < lpy ; ipy += dpy) 02809 { 02810 ParInd = (ParInd+1) & (MAXPAR-1); 02811 pax[ParInd] = fpx; 02812 pay[ParInd] = ipy + hpy; 02813 pal[ParInd] = TracerColor; 02814 } 02815 } 02816 02817 // Move particles 02818 02819 for (j=0 ; j < MAXPAR ; ++j) 02820 if (pax[j] >= 0.0 && pay[j] >= 0.0) 02821 { 02822 jx = rx = pax[j] / dpx; 02823 jy = ry = pay[j] / dpy; 02824 ic = jx + DimX * jy; 02825 ix = ic + 1; 02826 if (jx >= DimX-1) ix -= DimX; 02827 iy = ic + DimX; 02828 if (iy >= DimX * DimY) iy -= DimX; 02829 rx -= jx; 02830 ry -= jy; 02831 02832 du = u[ic]+(u[ix]-u[ic])*rx+(u[iy]-u[ic])*ry; 02833 dv = v[ic]+(v[ix]-v[ic])*rx+(v[iy]-v[ic])*ry; 02834 spfac = SpeedScale[jy] + (SpeedScale[jy+1]-SpeedScale[jy]) * ry; 02835 du *= spfac; 02836 dv *= spfac; 02837 fpx = pax[j] + du; 02838 fpy = pay[j] + dv; 02839 if (fpx < 0.0) fpx += lpx; 02840 if (fpx >= lpx) fpx -= lpx; 02841 if (fpy < 0.0 || fpy > lpy-1) 02842 { 02843 pay[j] = -1.0; 02844 continue; 02845 } 02846 pax[j] = fpx; 02847 pay[j] = fpy; 02848 ipx = -1; 02849 if (MapPro[w] == POLAR) 02850 { 02851 lfa = (2.0 * M_PI) / lpx; 02852 xnp = (InXSize-1) * 0.25; 02853 ynp = (InYSize-1) * 0.50; 02854 xsp = (InXSize-1) * 0.75; 02855 ysp = ynp; 02856 lam = fpx; 02857 phi = fpy; 02858 if (phi < 0.5 * lpy) /* Northern hemisphere */ 02859 { 02860 fpx = xnp - sin(lam * lfa) * (phi + hpy); 02861 fpy = ynp - cos(lam * lfa) * (phi + hpy); 02862 } 02863 else /* Souhern hemisphere */ 02864 { 02865 fpx = xsp + sin(lam * lfa) * (lpy - phi + hpy); 02866 fpy = ysp - cos(lam * lfa) * (lpy - phi + hpy); 02867 } 02868 ipx = rintf(fpx); 02869 ipy = rintf(fpy); 02870 } 02871 else if (MapPro[w] == AZIMUTHAL) 02872 { 02873 flam = (fpx - xc - roa) * pil; 02874 if (flam < -M_PI) flam += 2.0 * M_PI; 02875 if (flam > M_PI) flam -= 2.0 * M_PI; 02876 if (flam < -M_PI_2 || flam > M_PI_2) continue; 02877 fsin = sin(flam); 02878 fcos = cos((fpy-yc) * piy); 02879 fpx = xc + lpy/2 * fcos * fsin; 02880 fpy = yc + lpy/2 * sin((fpy-yc) * piy); 02881 ipx = rintf(fpx); 02882 ipy = rintf(fpy); 02883 } 02884 else 02885 { 02886 ipx = rintf(fpx); 02887 ipy = rintf(fpy); 02888 } 02889 if (ipx >= 0) 02890 { 02891 XSetForeground(display,gc,pal[j]); 02892 if (ipr < 2) XDrawPoint(display,pix,gc,ipx,ipy); 02893 else if (ipr == 2) XFillRectangle(display,pix,gc,ipx,ipy,2,2); 02894 else XFillArc(display,pix,gc,ipx,ipy,ipr,ipr,0,360*64); 02895 } 02896 } 02897 } 02898 02899 02900 /* ============= */ 02901 /* AmplitudePlot */ 02902 /* ============= */ 02903 02904 void AmplitudePlot(void) 02905 { 02906 int i,j,m,n; 02907 int x,y; 02908 int r,dx,dy; 02909 int mmax; 02910 int imax; 02911 REAL Amax,Fac; 02912 02913 if (!Ampli) Ampli = FloatAlloc(DimX,"Ampli"); 02914 if (!Acol ) Acol = SizeAlloc(DimX,sizeof(XColor),"Acol"); 02915 02916 Amax = 0.0; 02917 imax = 0; 02918 for (i=0 ; i < DimX ; ++i) 02919 { 02920 Ampli[i] = log (1.0 + sqrt(Field[2*i]*Field[2*i]+Field[2*i+1]*Field[2*i+1])); 02921 Acol[i].pixel = WhitePix; 02922 if (Ampli[i] > Amax && i > DimY) 02923 { 02924 Amax = Ampli[i]; 02925 imax = i; 02926 } 02927 } 02928 02929 Fac = 0.0; 02930 if (Amax > 1.e-20) Fac = 1.0 / Amax; 02931 for (i=0 ; i < DimX ; ++i) 02932 { 02933 j = AMPLI_COLS * Ampli[i] * Fac; 02934 if (j >= AMPLI_COLS) j = AMPLI_COLS-1; 02935 Acol[i].pixel = AmpliStrip[j].pixel; 02936 } 02937 02938 dx = WinXSize / 23; 02939 r = (dx+dx) / 3; 02940 mmax = (InYSize / dx) - 1; 02941 XSetForeground(display,gc,BlackPix); 02942 for (m=0,i=0 ; m < mmax ; ++m) 02943 { 02944 y = FixFontHeight + 4 + m * dx; 02945 for (n=m ; n < DimY ; ++n,++i) 02946 if (n < 22) 02947 { 02948 x = dx/2 + n * dx; 02949 XSetForeground(display,gc,Acol[i].pixel); 02950 XFillArc(display,pix,gc,x,y,r,r,0,360*64); 02951 } 02952 } 02953 } 02954 02955 02956 void RedrawIsoWindow(int w) 02957 { 02958 if (WinPixMap[w].Pix) 02959 XCopyArea(display,WinPixMap[w].Pix,Win[w],gc,0,0,WinPixMap[w].DimX,WinPixMap[w].DimY,0,0); 02960 } 02961 02962 02963 void CloseWindow(int i) 02964 { 02965 INTXS X,Y,xp,yp; 02966 unsigned int border,depth; 02967 Window Rootwin,Child; 02968 02969 if (Win[i]) 02970 { 02971 XGetGeometry(display,Win[i],&Rootwin,&xp,&yp,&WinAtt[i].w,&WinAtt[i].h,&border,&depth); 02972 XTranslateCoordinates(display,Win[i],Rootwin,0,0,&X,&Y,&Child); 02973 WinAtt[i].x = X - WinLM; 02974 WinAtt[i].y = Y - WinTM; 02975 XDestroyWindow(display,Win[i]); 02976 Win[i] = 0; 02977 ShowWindowStatus(); 02978 } 02979 } 02980 02981 void ReopenWindow(int i) 02982 { 02983 if (Win[i] == 0) 02984 { 02985 if (WinAtt[i].x < ScreenOffset) WinAtt[i].x = ScreenOffset + OutXSize * (i % WinCols); 02986 if (WinAtt[i].y < ScreenOffset) WinAtt[i].y = ScreenOffset + OutYSize * (i / WinCols); 02987 Win[i] = XCreateSimpleWindow(display,RootWindow(display,screen_num), 02988 WinAtt[i].x,WinAtt[i].y,WinAtt[i].w,WinAtt[i].h, 02989 BorderWidth,BlackPix,WhitePix); 02990 XSetWMProtocols(display,Win[i],&Delwin,1); 02991 XSetWMProperties(display,Win[i],WindowName+i,NULL, 02992 NULL,0,&WinSizeHints,&wm_hints,&class_hints); 02993 XSelectInput(display,Win[i],ButtonPressMask | KeyPressMask | ExposureMask); 02994 XMapWindow(display,Win[i]); 02995 ShowWindowStatus(); 02996 } 02997 } 02998 02999 char *HelpText[] = 03000 { 03001 "Key assignment for azimuthal projection ", 03002 "--------------------------------------------", 03003 "<- cursor left : increase westward rotation", 03004 "-> cursor right : increase eastward rotation", 03005 "============================================", 03006 "Key assignment for 3D variables ", 03007 "--------------------------------------------", 03008 "^ cursor up : display next upper level ", 03009 "v cursor down : display next lower level ", 03010 "============================================", 03011 "Key assignment for Lon/Lev or Hovmoeller ", 03012 "--------------------------------------------", 03013 "^ cursor up : switch latitude northwards", 03014 "v cursor down : switch latitude southwards", 03015 "============================================", 03016 "Mouse button assignment ", 03017 "--------------------------------------------", 03018 "Left button : decrease level or latitude", 03019 "Right button : increase level or latitude", 03020 "Middle button : cycle through projections " 03021 }; 03022 03023 int HelpLines = sizeof(HelpText) / sizeof(char *); 03024 03025 void DrawHelpWindow(void) 03026 { 03027 int x,y,j,l; 03028 03029 XSetForeground(display,gc,Yellow.pixel); 03030 XSetBackground(display,gc,DarkBlue.pixel); 03031 XSetFont(display,gc,BigFont->fid); 03032 03033 x = BigFontWidth / 2; 03034 for (j=0 ; j < HelpLines ; ++j) 03035 { 03036 y = BigFontHeight / 2 + BigFont->ascent + j * BigFontHeight; 03037 l = strlen(HelpText[j]); 03038 XDrawImageString(display,HelpWindow,gc,x,y,HelpText[j],l); 03039 } 03040 } 03041 03042 void DisplayHelpWindow(void) 03043 { 03044 int x,y,w,h; 03045 char *HelpTitle = "Help"; 03046 03047 w = BigFontWidth * (strlen(HelpText[0])+1); 03048 h = BigFontHeight * (HelpLines + 1); 03049 x = (ScreenW - w) / 2; 03050 y = (ScreenH - h) / 2; 03051 HelpWindow = XCreateSimpleWindow(display,RootWindow(display,screen_num), 03052 x,y,w,h,BorderWidth,Yellow.pixel,DarkBlue.pixel); 03053 XStringListToTextProperty(&HelpTitle,1,&HelpName); 03054 XSetWMProtocols(display,HelpWindow,&Delwin,1); 03055 XSetWMProperties(display,HelpWindow,&HelpName,NULL,NULL,0,NULL,NULL,NULL); 03056 XSelectInput(display,HelpWindow,ButtonPressMask | ExposureMask); 03057 XMapWindow(display,HelpWindow); 03058 XMoveWindow(display,HelpWindow,x,y); 03059 DrawHelpWindow(); 03060 } 03061 03062 int HitGridButton(XEvent* xe) 03063 { 03064 return ( 03065 (xe->xbutton.button == Button1) && 03066 (xe->xbutton.x >= Grid_XL ) && 03067 (xe->xbutton.x <= Grid_XH ) && 03068 (xe->xbutton.y >= Grid_YL ) && 03069 (xe->xbutton.y <= Grid_YH )); 03070 } 03071 03072 int HitPauseButton(XEvent* xe) 03073 { 03074 return ( 03075 (xe->xbutton.button == Button1) && 03076 (xe->xbutton.x >= Pause_XL-2 ) && 03077 (xe->xbutton.x <= Pause_XH+2 ) && 03078 (xe->xbutton.y >= Pause_YL-2 ) && 03079 (xe->xbutton.y <= Pause_YH+2 )); 03080 } 03081 03082 int HitStartButton(XEvent* xe) 03083 { 03084 return ( 03085 (xe->xbutton.button == Button1) && 03086 (xe->xbutton.x >= Start_XL-2 ) && 03087 (xe->xbutton.x <= Start_XH+2 ) && 03088 (xe->xbutton.y >= Start_YL-2 ) && 03089 (xe->xbutton.y <= Start_YH+2 )); 03090 } 03091 03092 int HitStopButton(XEvent* xe) 03093 { 03094 return ( 03095 (xe->xbutton.button == Button1) && 03096 (xe->xbutton.x >= Stop_XL-2 ) && 03097 (xe->xbutton.x <= Stop_XH+2 ) && 03098 (xe->xbutton.y >= Stop_YL-2 ) && 03099 (xe->xbutton.y <= Stop_YH+2 )); 03100 } 03101 03102 int HitHelpButton(XEvent* xe) 03103 { 03104 return ( 03105 (xe->xbutton.button == Button1) && 03106 (xe->xbutton.x >= Help_XL-2 ) && 03107 (xe->xbutton.x <= Help_XH+2 ) && 03108 (xe->xbutton.y >= Help_YL-2 ) && 03109 (xe->xbutton.y <= Help_YH+2 )); 03110 } 03111 03112 int HitPlusButton(XEvent* xe) 03113 { 03114 return ( 03115 (xe->xbutton.button == Button1) && 03116 (xe->xbutton.x >= Plus_XL ) && 03117 (xe->xbutton.x <= Plus_XH ) && 03118 (xe->xbutton.y >= Plus_YL ) && 03119 (xe->xbutton.y <= Plus_YH )); 03120 } 03121 03122 int HitFFWDButton(XEvent* xe) 03123 { 03124 return ( 03125 (xe->xbutton.button == Button1) && 03126 (xe->xbutton.x >= FFWD_XL ) && 03127 (xe->xbutton.x <= FFWD_XH ) && 03128 (xe->xbutton.y >= FFWD_YL ) && 03129 (xe->xbutton.y <= FFWD_YH )); 03130 } 03131 03132 int HitMinusButton(XEvent* xe) 03133 { 03134 return ( 03135 (xe->xbutton.button == Button1) && 03136 (xe->xbutton.x >= Minus_XL ) && 03137 (xe->xbutton.x <= Minus_XH ) && 03138 (xe->xbutton.y >= Minus_YL ) && 03139 (xe->xbutton.y <= Minus_YH )); 03140 } 03141 03142 int HitFBWDButton(XEvent* xe) 03143 { 03144 return ( 03145 (xe->xbutton.button == Button1) && 03146 (xe->xbutton.x >= FBWD_XL ) && 03147 (xe->xbutton.x <= FBWD_XH ) && 03148 (xe->xbutton.y >= FBWD_YL ) && 03149 (xe->xbutton.y <= FBWD_YH )); 03150 } 03151 03152 int HitUpperPanel(XEvent* xe) 03153 { 03154 return ( 03155 (xe->xbutton.button == Button1) && 03156 (xe->xbutton.x >= Parc_XL ) && 03157 (xe->xbutton.x <= Parc_XH ) && 03158 (xe->xbutton.y >= Parc_YL-Parc_YD ) && 03159 (xe->xbutton.y <= Parc_YL )); 03160 } 03161 03162 int HitLowerPanel(XEvent* xe) 03163 { 03164 return ( 03165 (xe->xbutton.button == Button1) && 03166 (xe->xbutton.x >= Parc_XL ) && 03167 (xe->xbutton.x <= Parc_XH ) && 03168 (xe->xbutton.y >= Parc_YH ) && 03169 (xe->xbutton.y <= Parc_YH+Parc_YD)); 03170 } 03171 03172 int HitWindowSelect(XEvent* xe) 03173 { 03174 if ( 03175 (xe->xbutton.button == Button1) && 03176 (xe->xbutton.x >= Wbox_XL) && 03177 (xe->xbutton.x <= Wbox_XH) && 03178 (xe->xbutton.y >= Wbox_YL) && 03179 (xe->xbutton.y <= Wbox_YH)) 03180 return (xe->xbutton.y / FixFontHeight); /* Window number */ 03181 else return -1; 03182 } 03183 03184 void OnMouseClick(void) 03185 { 03186 int w; 03187 03188 if (HitStopButton(&CowEvent)) 03189 { 03190 Shutdown = 1; 03191 } 03192 else if (HitStartButton(&CowEvent)) 03193 { 03194 Paused = 0; 03195 XSetWMName(display,Cow,&WinconName1); 03196 } 03197 else if (HitGridButton(&CowEvent)) 03198 { 03199 Grid = !Grid; 03200 ShowGridStatus(); 03201 for (w=0 ; w < NUMWIN ; ++w) RedrawFlag[w] = 1; 03202 } 03203 else if (HitPauseButton(&CowEvent)) 03204 { 03205 if (Paused) 03206 { 03207 Paused = 0; 03208 XSetWMName(display,Cow,&WinconName1); 03209 } 03210 else 03211 { 03212 Paused = 1; 03213 XSetWMName(display,Cow,&WinconPause); 03214 } 03215 } 03216 else if (HitHelpButton(&CowEvent)) 03217 { 03218 if (!HelpWindow) DisplayHelpWindow(); 03219 } 03220 else if ((w = HitWindowSelect(&CowEvent)) >= 0) 03221 { 03222 if (Win[w]) CloseWindow(w); 03223 else ReopenWindow(w); 03224 } 03225 else if (HitPlusButton(&CowEvent)) 03226 { 03227 Parc[cpi].Val += Parc[cpi].Inc; 03228 if (Parc[cpi].Val > Parc[cpi].Max) Parc[cpi].Val = Parc[cpi].Max; 03229 } 03230 else if (HitFFWDButton(&CowEvent)) 03231 { 03232 Parc[cpi].Val += 10.0 * Parc[cpi].Inc; 03233 if (Parc[cpi].Val > Parc[cpi].Max) Parc[cpi].Val = Parc[cpi].Max; 03234 } 03235 else if (HitMinusButton(&CowEvent)) 03236 { 03237 Parc[cpi].Val -= Parc[cpi].Inc; 03238 if (Parc[cpi].Val < Parc[cpi].Min) Parc[cpi].Val = Parc[cpi].Min; 03239 } 03240 else if (HitFBWDButton(&CowEvent)) 03241 { 03242 Parc[cpi].Val -= 10.0 * Parc[cpi].Inc; 03243 if (Parc[cpi].Val < Parc[cpi].Min) Parc[cpi].Val = Parc[cpi].Min; 03244 } 03245 else if (HitUpperPanel(&CowEvent) && cpi > 0) --cpi; 03246 else if (HitLowerPanel(&CowEvent) && cpi < Parcs-1) ++cpi; 03247 } 03248 03249 03250 void SwitchIndez(int w, int d) 03251 { 03252 int jlat; 03253 REAL delphi; 03254 char *lpt; 03255 char levstr[20]; 03256 03257 if (Indez[w] < 0 || Indez[w] >= MaxZ[w]) 03258 { 03259 if (Debug) printf("### Indez[%d] = %d\n",w,Indez[w]); 03260 if (Debug) printf("### MaxZ[%d] = %d\n",w, MaxZ[w]); 03261 Indez[w] = 0; 03262 } 03263 if (Indez[w]+d < 0 ) return; 03264 if (Indez[w]+d >= MaxZ[w]) return; 03265 Indez[w] += d; 03266 lpt = strstr(WindowTitle[w],"Level"); 03267 if (lpt) 03268 { 03269 sprintf(levstr," %d",Indez[w]+1); 03270 strcpy(lpt+5,levstr); 03271 XStringListToTextProperty(&WindowTitle[w],1,WindowName+w); 03272 XSetWMProperties(display,Win[w],WindowName+w,NULL, 03273 NULL,0,&WinSizeHints,&wm_hints,&class_hints); 03274 LevelChanged[w] = 1; 03275 return; 03276 } 03277 lpt = strstr(WindowTitle[w],"Latitude"); 03278 if (lpt) 03279 { 03280 delphi = 180.0 / MaxZ[w]; 03281 jlat = 90.0 -Indez[w] * delphi - delphi * 0.5; 03282 if (jlat > 0) sprintf(levstr," %dN", jlat); 03283 else sprintf(levstr," %dS",-jlat); 03284 strcpy(lpt+8,levstr); 03285 XStringListToTextProperty(&WindowTitle[w],1,WindowName+w); 03286 XSetWMProperties(display,Win[w],WindowName+w,NULL, 03287 NULL,0,&WinSizeHints,&wm_hints,&class_hints); 03288 return; 03289 } 03290 } 03291 03292 03293 void HandleEvents(void) 03294 { 03295 int w,Key,KeyIndex; 03296 XEvent WinEvent; 03297 03298 if (nstep == 1) 03299 { 03300 RedrawControlWindow(); 03301 Paused = 1; /* Start in pause mode */ 03302 } 03303 03304 03305 do 03306 { 03307 /* Check for Termination */ 03308 03309 if (XCheckTypedWindowEvent(display,Cow,ClientMessage,&WinEvent)) 03310 { 03311 /* printf("delwin %d\n",WinEvent.xclient.data.l[0]); */ 03312 Shutdown = 1; 03313 return; 03314 } 03315 03316 /* Check for user request to close windows */ 03317 03318 for (w=0 ; w < NumWin ; ++w) 03319 if (Win[w]) 03320 { 03321 if (XCheckTypedWindowEvent(display,Win[w],ClientMessage,&WinEvent)) 03322 CloseWindow(w); 03323 } 03324 03325 /* Check for user request to close help window */ 03326 03327 if (HelpWindow && XCheckTypedWindowEvent(display,HelpWindow,ClientMessage,&WinEvent)) 03328 { 03329 XDestroyWindow(display,HelpWindow); 03330 HelpWindow = 0; 03331 } 03332 03333 /* Check for mouse click */ 03334 03335 if (XCheckTypedWindowEvent(display,Cow,ButtonPress,&CowEvent)) 03336 { 03337 OnMouseClick(); 03338 RedrawControlWindow(); 03339 } 03340 03341 /* Check for mouseclicks and expose events */ 03342 03343 for (w=0 ; w < NumWin ; ++w) 03344 if (Win[w]) 03345 { 03346 if (XCheckTypedWindowEvent(display,Win[w],ButtonPress,&CowEvent)) 03347 { 03348 if (CowEvent.xbutton.button == Button1) SwitchIndez(w,-1); 03349 if (CowEvent.xbutton.button == Button3) SwitchIndez(w, 1); 03350 if (CowEvent.xbutton.button == Button2) 03351 { 03352 if (++MapPro[w] >= MAXMAPS) MapPro[w] = 0; 03353 if (MapPro[w] == AZIMUTHAL && 03354 (WinAtt[w].Plot != MAPHOR && WinAtt[w].Plot != MAPTRA)) 03355 MapPro[w] = 0; 03356 } 03357 RedrawFlag[w] = 1; 03358 } 03359 if (XCheckTypedWindowEvent(display,Win[w],KeyPress,&CowEvent)) 03360 { 03361 KeyIndex = (CowEvent.xkey.keycode - FirstKey) * SymsPerKey; 03362 Key = KeyMap[KeyIndex]; 03363 if (Debug) printf("Windows %d got keyindex %d with symbol %x\n",w,KeyIndex,Key); 03364 if (Key == ROTATE_LEFT && MapLR[w].f < 5) MapLR[w].f++; 03365 if (Key == ROTATE_RIGHT && MapLR[w].f > -5) MapLR[w].f--; 03366 MapLR[w].r = MapLR[w].f * RotInc; 03367 if (Key == XK_Up ) SwitchIndez(w,-1); 03368 if (Key == XK_Down) SwitchIndez(w, 1); 03369 } 03370 if (Paused) 03371 if (XCheckTypedWindowEvent(display,Win[w],Expose,&CowEvent)) 03372 RedrawIsoWindow(w); 03373 } 03374 03375 if (XCheckTypedWindowEvent(display,Cow,Expose,&CowEvent)) 03376 RedrawControlWindow(); 03377 03378 if (HelpWindow && XCheckTypedWindowEvent(display,HelpWindow,Expose,&CowEvent)) 03379 DrawHelpWindow(); 03380 03381 } while (Paused && !Shutdown); 03382 } 03383 03384 void guiclose_(void) 03385 { 03386 int w; 03387 03388 if (MRpid >= 0) return; // Don't wait if multiple instances 03389 XSetWMName(display,Cow,&WinconName3); 03390 03391 do 03392 { 03393 for (w=0 ; w < NumWin ; ++w) 03394 if (Win[w]) 03395 { 03396 if (XCheckTypedWindowEvent(display,Win[w],Expose,&CowEvent)) 03397 RedrawIsoWindow(w); 03398 } 03399 03400 if (XCheckTypedWindowEvent(display,Cow,Expose,&CowEvent)) 03401 RedrawControlWindow(); 03402 } 03403 while (!(XCheckTypedWindowEvent(display,Cow,ButtonPress,&CowEvent) && 03404 HitStopButton(&CowEvent))); 03405 03406 // XCloseDisplay(display); // segmentation fault on sun compiler! 03407 } 03408 03409 void SaveConfig(void) 03410 { 03411 int i; 03412 FILE *scp; 03413 INTXS X,Y,xp,yp; 03414 unsigned int w,W,H,border,depth; 03415 Window Rootwin,Child; 03416 XWindowAttributes RootAtt; 03417 03418 scp = fopen(GUI_config,"w"); 03419 if (scp == NULL) return; 03420 03421 /* Save window properties */ 03422 03423 fprintf(scp,"Hamburg GUI Config File Version 16\n"); 03424 fprintf(scp,"Screen: %dx%d\n\n",ScreenW,ScreenH); 03425 fprintf(scp,"WinRows = %d\n",WinRows); 03426 fprintf(scp,"WinCols = %d\n",WinCols); 03427 for (w=0 ; w < NumWin ; ++w) 03428 { 03429 fprintf(scp,"\n[Window %02d]\n",w); 03430 fprintf(scp,"Array:%s\n",WinAtt[w].array_name); 03431 fprintf(scp,"Plot:%s\n",IsoNames[WinAtt[w].Plot]); 03432 if (WinAtt[w].Plot == ISOHOR || WinAtt[w].Plot == MAPHOR || 03433 WinAtt[w].Plot == ISOTRA || WinAtt[w].Plot == MAPTRA) 03434 { 03435 fprintf(scp,"Projection:%s\n",ProNames[MapPro[w]]); 03436 fprintf(scp,"Rotation factor:%d\n",MapLR[w].f); 03437 } 03438 fprintf(scp,"Palette:%s\n",PalNames[WinAtt[w].Palette]); 03439 fprintf(scp,"Title:%s\n",WindowTitle[w]+wto); 03440 if (Win[w]) 03441 { 03442 XGetGeometry(display,Win[w],&Rootwin,&xp,&yp,&W,&H,&border,&depth); 03443 XTranslateCoordinates(display,Win[w],Rootwin,0,0,&X,&Y,&Child); 03444 fprintf(scp,"Geometry: %4d %4d %4d %4d\n",W,H,X-WinLM,Y-WinTM); 03445 if (Debug) 03446 { 03447 printf("Geometry Window %d [%8x]: %4d / %4d %4d x %4d x %2d | %d\n", 03448 w,(int)Win[w],xp,yp,W,H,depth,border); 03449 printf("Translated UL corner: %4d / %4d\n",X,Y); 03450 } 03451 } 03452 else 03453 fprintf(scp,"Inactive: %4d %4d %4d %4d\n", 03454 WinAtt[w].w,WinAtt[w].h,WinAtt[w].x,WinAtt[w].y); 03455 } 03456 XGetGeometry(display,Cow,&Rootwin,&xp,&yp,&W,&H,&border,&depth); 03457 XTranslateCoordinates(display,Cow,Rootwin,0,0,&X,&Y,&Child); 03458 fprintf(scp,"\n[Control Window]\n"); 03459 fprintf(scp,"Geometry: %4d %4d %4d %4d\n",W,H,X-WinLM,Y-WinTM); 03460 03461 /* Scalar attributes for timeseries and tables */ 03462 03463 fprintf(scp,"\n# Scalar attributes for timeseries and table window\n"); 03464 03465 for (i=0 ; i < Parcs ; ++i) 03466 { 03467 fprintf(scp,"\n[Scalar %02d]\n",i); 03468 fprintf(scp,"Name:%s\n",TSName[i]); 03469 fprintf(scp,"Sub:%s\n",TSubsc[i]); 03470 fprintf(scp,"Unit:%s\n",TSUnit[i]); 03471 fprintf(scp,"Scale:%s\n",TScale[i]); 03472 } 03473 03474 /* Scalar attributes for timeseries and tables */ 03475 03476 fprintf(scp,"\n# Parameter attributes for change menu\n"); 03477 03478 for (i=0 ; i < NUMSCALARS ; ++i) 03479 { 03480 if (strlen(Parc[i].Name) == 0) break; 03481 fprintf(scp,"\n[Parameter %02d]\n",i); 03482 fprintf(scp,"ParName:%s\n",Parc[i].Name); 03483 fprintf(scp,"ParInc:%10.4f\n",Parc[i].Inc); 03484 fprintf(scp,"ParMin:%10.4f\n",Parc[i].Min); 03485 fprintf(scp,"ParMax:%10.4f\n",Parc[i].Max); 03486 } 03487 03488 fclose(scp); 03489 } 03490 03491 03492 void lp2ps(REAL *a, REAL *b) 03493 { 03494 int i,j,k,l,k1,l1; 03495 REAL xnp,ynp,xsp,ysp,dx,dy,x,y,lfa,ua,ub; 03496 03497 lfa = (DimX-1) / (2.0 * M_PI); 03498 xnp = (DimX-1) * 0.25; 03499 ynp = (DimY-1) * 0.50; 03500 xsp = (DimX-1) * 0.75; 03501 ysp = ynp; 03502 03503 /* Northern hemisphere */ 03504 03505 for (j = 0 ; j < DimY ; ++j) 03506 for (i = 0 ; i <= DimX/2 ; ++i) 03507 { 03508 dx = xnp - i; 03509 dy = ynp - j; 03510 x = atan2(dx,dy) * lfa; 03511 y = sqrt(dx * dx + dy * dy); 03512 if (x < 0.0) x += (DimX-1); 03513 k = x; 03514 l = y; 03515 k1 = k + 1; 03516 if (k1 >= DimX) k1 = 0; 03517 if (l <= DimY/2+1) 03518 { 03519 ua = (k+1-x) * a[k+l*DimX] + (x-k) * a[k1+l*DimX]; 03520 ub = (k+1-x) * a[k+(l+1)*DimX] + (x-k) * a[k+1+(l+1)*DimX]; 03521 b[i+j*DimX] = (l+1-y) * ua + (y-l) * ub; 03522 } 03523 else b[i+j*DimX] = - 99999.0; 03524 } 03525 03526 /* Souhern hemisphere */ 03527 03528 for (j = 0 ; j < DimY ; ++j) 03529 for (i = DimX/2+1 ; i < DimX ; ++i) 03530 { 03531 dx = i - xsp; 03532 dy = ysp - j; 03533 x = atan2(dx,dy) * lfa; 03534 y = (DimY-1) - sqrt(dx * dx + dy * dy); 03535 if (x < 0.0) x += (DimX-1); 03536 k = x; 03537 l = y; 03538 k1 = k + 1; 03539 if (k1 >= DimX) k1 = 0; 03540 if (l >= DimY/2-3) 03541 { 03542 ua = (k+1-x) * a[k+l*DimX] + (x-k) * a[k1+l*DimX]; 03543 ub = (k+1-x) * a[k+(l+1)*DimX] + (x-k) * a[k+1+(l+1)*DimX]; 03544 b[i+j*DimX] = (l+1-y) * ua + (y-l) * ub; 03545 } 03546 else b[i+j*DimX] = - 99999.0; 03547 } 03548 } 03549 03550 03551 /* ======================================================= */ 03552 /* lp2az - transform lon/lat array to azimuthal projection */ 03553 /* ======================================================= */ 03554 03555 void lp2az(REAL *a, REAL *b, float laz) 03556 { 03557 int x,y,dxc,k,k1,l; 03558 REAL dx,dy,lam,rho,rad,phi,ua,ub,l00,p00,xpi,ypi; 03559 03560 rad = DimY >> 1; 03561 dxc = DimX >> 1; 03562 xpi = DimX / M_PI * 0.5; 03563 ypi = DimY / M_PI; 03564 l00 = (int)((laz * DimX) / 360 + dxc) % DimX; 03565 p00 = DimY / 2; 03566 03567 for (y = 0 ; y < DimY ; ++y) 03568 { 03569 dy = y - rad; 03570 phi = y; 03571 for (x = 0 ; x < DimX ; ++x) 03572 { 03573 dx = x - dxc; 03574 rho = sqrt(dx * dx + dy * dy); 03575 if (rho < rad) 03576 { 03577 lam = l00 + xpi * atan2(dx / rad, cos(asin(rho / rad))); 03578 phi = p00 + ypi * asin(dy / rad); 03579 k = lam; 03580 k1 = k + 1; 03581 if (k1 >= DimX) k1 = 0; 03582 l = phi; 03583 ua = (k+1-lam) * a[k+ l *DimX] + (lam-k) * a[k1 + l *DimX]; 03584 ub = (k+1-lam) * a[k+(l+1)*DimX] + (lam-k) * a[k+1+(l+1)*DimX]; 03585 b[x+y*DimX] = (l+1-y) * ua + (y-l) * ub; 03586 } 03587 else b[x+y*DimX] = - 99999.0; 03588 } 03589 } 03590 } 03591 03592 void ShowGridCS(void) 03593 { 03594 int jlev,jlat,x,y,len; 03595 float dx,dy; 03596 char Text[80]; 03597 03598 /* Grid for zonal mean cross sections */ 03599 03600 XSetForeground(display,gc,WhitePix); 03601 XSetBackground(display,gc,BlackPix); 03602 XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound); 03603 dy = (InYSize - OffY) / (DimY - 1.0); 03604 for (jlev = 1 ; jlev < DimY-1 ; ++jlev) 03605 { 03606 y = OffY + jlev * dy; 03607 XDrawLine(display,pix,gc,OffX,y,InXSize-1,y); 03608 } 03609 dx = (InXSize - OffX) / 6.0; /* Every 30 degrees */ 03610 for (jlat = 1 ; jlat < 6 ; ++jlat) 03611 { 03612 x = OffX + jlat * dx; 03613 XDrawLine(display,pix,gc,x,OffY,x,InYSize-1); 03614 } 03615 if (GridLabel) 03616 { 03617 XDrawImageString(display,pix,gc,InXSize/2-FixFontWidth,InYSize-FixFont->descent,"EQ",2); 03618 XDrawImageString(display,pix,gc,OffX,InYSize-FixFont->descent,"N",1); 03619 XDrawImageString(display,pix,gc,InXSize-FixFontWidth,InYSize-FixFont->descent,"S",1); 03620 } 03621 XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound); 03622 } 03623 03624 void ShowGridCol(void) 03625 { 03626 int jlev,jtim,x,y,len; 03627 float dx,dy; 03628 char Text[80]; 03629 03630 /* Grid for column time series */ 03631 03632 XSetForeground(display,gc,WhitePix); 03633 XSetBackground(display,gc,BlackPix); 03634 XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound); 03635 dy = (InYSize - OffY) / (DimY - 1.0); 03636 for (jlev = 1 ; jlev < DimY-1 ; ++jlev) 03637 { 03638 y = OffY + jlev * dy; 03639 XDrawLine(display,pix,gc,OffX,y,InXSize-1,y); 03640 } 03641 dx = (InXSize - OffX) / 4.0; /* 4 slices */ 03642 for (jtim = 1 ; jtim < 4 ; ++jtim) 03643 { 03644 x = OffX + jtim * dx; 03645 XDrawLine(display,pix,gc,x,OffY,x,InYSize-1); 03646 } 03647 if (GridLabel) 03648 { 03649 XDrawImageString(display,pix,gc,InXSize/2-3*FixFontWidth/2,InYSize-FixFont->descent,"t-2",3); 03650 XDrawImageString(display,pix,gc,InXSize/4-3*FixFontWidth/2,InYSize-FixFont->descent,"t-3",3); 03651 XDrawImageString(display,pix,gc,3*InXSize/4-3*FixFontWidth/2,InYSize-FixFont->descent,"t-1",3); 03652 } 03653 XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound); 03654 } 03655 03656 void ShowGridLonsi(void) 03657 { 03658 int jlev,jlat,x,y,len; 03659 float dx,dy; 03660 char Text[80]; 03661 03662 /* Grid for Longitude Sigma section */ 03663 03664 XSetForeground(display,gc,WhitePix); 03665 XSetBackground(display,gc,BlackPix); 03666 XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound); 03667 dy = (InYSize - OffY) / (DimY - 1.0); 03668 for (jlev = 1 ; jlev < DimY-1 ; ++jlev) 03669 { 03670 y = OffY + jlev * dy; 03671 XDrawLine(display,pix,gc,OffX,y,InXSize-1,y); 03672 } 03673 dx = (InXSize - OffX) / 6.0; /* Every 60 degrees */ 03674 for (jlat = 1 ; jlat < 6 ; ++jlat) 03675 { 03676 x = OffX + jlat * dx; 03677 XDrawLine(display,pix,gc,x,OffY,x,InYSize-1); 03678 } 03679 if (GridLabel) 03680 { 03681 XDrawImageString(display,pix,gc,InXSize/2-3*FixFontWidth/2,InYSize-FixFont->descent,"180",3); 03682 XDrawImageString(display,pix,gc,OffX,InYSize-FixFont->descent,"0",1); 03683 XDrawImageString(display,pix,gc,InXSize-3*FixFontWidth,InYSize-FixFont->descent,"360",3); 03684 } 03685 XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound); 03686 } 03687 03688 void ShowGridCyl(void) 03689 { 03690 int jlon,jlat,x,y; 03691 float dx,dy; 03692 03693 /* Grid for cylinder projection */ 03694 03695 XSetForeground(display,gc,WhitePix); 03696 XSetBackground(display,gc,BlackPix); 03697 XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound); 03698 dy = (InYSize - OffY) / 6.0; 03699 for (jlat = 1 ; jlat < 6 ; ++jlat) 03700 { 03701 y = OffY + jlat * dy; 03702 XDrawLine(display,pix,gc,OffX,y,InXSize-1,y); 03703 } 03704 dx = (InXSize - OffX) / 6.0; /* Every 30 degrees */ 03705 for (jlon = 1 ; jlon < 6 ; ++jlon) 03706 { 03707 x = OffX + jlon * dx; 03708 XDrawLine(display,pix,gc,x,OffY,x,InYSize-1); 03709 } 03710 if (GridLabel) 03711 { 03712 XDrawImageString(display,pix,gc,OffX,OffY+(InYSize-OffY)/2+FixFontHeight/2-FixFont->descent,"EQ",2); 03713 XDrawImageString(display,pix,gc,OffX,OffY+FixFontHeight-FixFont->descent,"N",1); 03714 XDrawImageString(display,pix,gc,OffX,InYSize-FixFont->descent,"-180",4); 03715 XDrawImageString(display,pix,gc,InXSize-3*FixFontWidth,InYSize-FixFont->descent,"180",3); 03716 XDrawImageString(display,pix,gc,OffX+(InXSize-OffX)/2-3*FixFontWidth/2,InYSize-FixFont->descent,"0",1); 03717 } 03718 XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound); 03719 } 03720 03721 void ShowGridHov(void) 03722 { 03723 int jlon,jlat,x,y,len; 03724 float dx,dy; 03725 char Text[80]; 03726 03727 /* Grid for Hovmoeller */ 03728 03729 XSetForeground(display,gc,WhitePix); 03730 XSetBackground(display,gc,BlackPix); 03731 XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound); 03732 dx = (InXSize - OffX) / 6.0; 03733 for (jlon = 1 ; jlon < 6 ; ++jlon) 03734 { 03735 x = OffX + jlon * dx; 03736 XDrawLine(display,pix,gc,x,OffY,x,InYSize-1); 03737 } 03738 dy = (InYSize - OffY) / 5.0; /* Every 5 days */ 03739 for (jlat = 1 ; jlat < 5 ; ++jlat) 03740 { 03741 y = OffY + jlat * dy; 03742 XDrawLine(display,pix,gc,OffX,y,InXSize-1,y); 03743 } 03744 if (GridLabel) 03745 { 03746 XDrawImageString(display,pix,gc,OffX,InYSize-FixFont->descent,"0",1); 03747 XDrawImageString(display,pix,gc,InXSize-3*FixFontWidth,InYSize-FixFont->descent,"360",3); 03748 XDrawImageString(display,pix,gc,OffX+(InXSize-OffX)/2-3*FixFontWidth/2,InYSize-FixFont->descent,"180",3); 03749 XDrawImageString(display,pix,gc,OffX,OffY+FixFontHeight-FixFont->descent,"t0",2); 03750 XDrawImageString(display,pix,gc,OffX,OffY+2*InYSize/5+FixFontHeight/2-FixFont->descent,"t-2",3); 03751 XDrawImageString(display,pix,gc,OffX,OffY+4*InYSize/5+FixFontHeight/2-FixFont->descent,"t-4",3); 03752 } 03753 XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound); 03754 } 03755 03756 void ShowGridHovT(void) 03757 { 03758 int jlon,jlat,x,y,len; 03759 float dx,dy; 03760 char Text[80]; 03761 03762 /* Grid for Hovmoeller */ 03763 03764 XSetForeground(display,gc,WhitePix); 03765 XSetBackground(display,gc,BlackPix); 03766 XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound); 03767 dy = (InYSize - OffY) / 6.0; 03768 for (jlat = 1 ; jlat < 6 ; ++jlat) 03769 { 03770 y = OffY + jlat * dy; 03771 XDrawLine(display,pix,gc,OffX,y,InXSize-1,y); 03772 } 03773 dx = (InXSize - OffX) / 5.0; /* Every 5 days */ 03774 for (jlat = 1 ; jlat < 5 ; ++jlat) 03775 { 03776 x = OffX + jlat * dx; 03777 XDrawLine(display,pix,gc,x,OffY,x,InYSize-1); 03778 } 03779 if (GridLabel) 03780 { 03781 XDrawImageString(display,pix,gc,OffX,OffY+FixFontHeight-FixFont->descent,"0",1); 03782 XDrawImageString(display,pix,gc,OffX,OffY+(InYSize-OffY)/2+FixFontHeight/2-FixFont->descent,"180",3); 03783 XDrawImageString(display,pix,gc,OffX,InYSize-FixFont->descent,"360",3); 03784 XDrawImageString(display,pix,gc,InXSize-2*FixFontWidth,InYSize-FixFont->descent,"t0",2); 03785 XDrawImageString(display,pix,gc,3*InXSize/5-3*FixFontWidth/2,InYSize-FixFont->descent,"t-2",3); 03786 XDrawImageString(display,pix,gc, InXSize/5-3*FixFontWidth/2,InYSize-FixFont->descent,"t-4",3); 03787 } 03788 XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound); 03789 } 03790 03791 void ShowGridPolar(void) 03792 { 03793 int dx,dy,x,y,xh,yh,ox,oy; 03794 XPoint pxy[3]; 03795 03796 /* Grid for polar projection */ 03797 03798 dx = (InXSize - OffX) / 2; 03799 dy = (InYSize - OffY); 03800 xh = dx / 2; 03801 yh = dy / 2; 03802 ox = dx / 3.414; 03803 oy = dy / 3.414; 03804 03805 if (Grid) 03806 { 03807 XSetForeground(display,gc,WhitePix); 03808 XSetBackground(display,gc,BlackPix); 03809 XSetLineAttributes(display,gc,1,LineOnOffDash,CapButt,JoinRound); 03810 03811 /* Northern Hemisphere */ 03812 03813 XDrawArc(display,pix,gc,OffX+dx/6,OffY+dy/6,2*dx/3,2*dy/3,0,360*64); 03814 XDrawArc(display,pix,gc,OffX+dx/3,OffY+dy/3,dx/3,dy/3,0,360*64); 03815 03816 XDrawLine(display,pix,gc,OffX,yh,InXSize,yh); 03817 XDrawLine(display,pix,gc,OffX+xh,OffY,OffX+xh,InYSize); 03818 03819 /* Southern Hemisphere */ 03820 03821 XDrawArc(display,pix,gc,OffX+7*dx/6,OffY+dy/6,2*dx/3,2*dy/3,0,360*64); 03822 XDrawArc(display,pix,gc,OffX+4*dx/3,OffY+dy/3,dx/3,dy/3,0,360*64); 03823 03824 x = OffX + dx + xh; 03825 XDrawLine(display,pix,gc,x,OffY,x,InYSize); 03826 03827 if (GridLabel) 03828 { 03829 x = OffX + xh - FixFontWidth/2; 03830 y = OffY + yh + FixFontHeight/2 - FixFont->descent; 03831 XDrawImageString(display,pix,gc,x,y,"N",1); 03832 XDrawImageString(display,pix,gc,x+dx,y,"S",1); 03833 } 03834 XSetLineAttributes(display,gc,1,LineSolid,CapButt,JoinRound); 03835 } 03836 03837 /* Octagon mask */ 03838 03839 XSetForeground(display,gc,BlackPix); 03840 pxy[0].x = pxy[1].x = OffX; 03841 pxy[0].y = pxy[2].y = OffY; 03842 pxy[1].y = OffY + oy; 03843 pxy[2].x = OffX + ox; 03844 XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin); 03845 pxy[0].x = OffX + dx - ox; 03846 pxy[1].x = OffX + dx; 03847 pxy[2].x = OffX + dx + ox; 03848 XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin); 03849 pxy[0].x = InXSize - ox; 03850 pxy[1].x = InXSize; 03851 pxy[2].x = InXSize; 03852 XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin); 03853 03854 pxy[0].x = pxy[1].x = OffX; 03855 pxy[0].y = pxy[2].y = InYSize; 03856 pxy[1].y = InYSize - oy; 03857 pxy[2].x = OffX + ox; 03858 XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin); 03859 pxy[0].x = OffX + dx - ox; 03860 pxy[1].x = OffX + dx; 03861 pxy[2].x = OffX + dx + ox; 03862 XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin); 03863 pxy[0].x = InXSize - ox; 03864 pxy[1].x = InXSize; 03865 pxy[2].x = InXSize; 03866 XFillPolygon(display,pix,gc,pxy,3,Convex,CoordModeOrigin); 03867 } 03868 03869 03870 void AutoPalette(int w, struct ColorStrip Strip[], REAL f[], int Dim) 03871 { 03872 int i,nbands; 03873 double fmin, fmax, frange, delta, fdelta, xdelta, Lo; 03874 03875 fmin = fmax = f[0]; 03876 for (i=0; i < Dim ; ++i) 03877 { 03878 if (fmin > f[i]) fmin = f[i]; 03879 if (fmax < f[i]) fmax = f[i]; 03880 } 03881 frange = fmax - fmin; 03882 Lo = 0.0; 03883 xdelta = 0.1; 03884 if (frange > 1.0e-10) 03885 { 03886 delta = frange / AUTOCOLORS; 03887 if (delta > AutoDelta[w] / 1.4 && delta < 1.4 * AutoDelta[w]) 03888 { 03889 xdelta = AutoXdelt[w]; 03890 delta = AutoDelta[w]; 03891 Lo = AutoLo[w]; 03892 } 03893 else 03894 { 03895 fdelta = pow(10.0,rint(log10(delta))); 03896 xdelta = fdelta; 03897 nbands = frange / xdelta; 03898 if (nbands < AUTOCOLORS / 2) xdelta = 0.5 * fdelta; 03899 if (nbands > AUTOCOLORS ) xdelta = 2.0 * fdelta; 03900 nbands = frange / xdelta; 03901 if (nbands > AUTOCOLORS ) xdelta = 5.0 * fdelta; 03902 Lo = xdelta * floor(fmin / xdelta); 03903 AutoDelta[w] = delta; 03904 AutoXdelt[w] = xdelta; 03905 AutoLo[w] = Lo; 03906 /* 03907 if (Debug) 03908 { 03909 printf("Autopalette\n"); 03910 printf(" Range: %14.6e\n",frange); 03911 printf(" delta: %14.6e\n",delta); 03912 printf("fdelta: %14.6e\n",fdelta); 03913 printf("xdelta: %14.6e\n",xdelta); 03914 } 03915 */ 03916 } 03917 } 03918 Strip[0].Lo = Lo; 03919 for (i=0 ; i < AUTOCOLORS ; ++i) 03920 { 03921 Strip[i+1].Lo = Strip[i].Hi = Strip[i].Lo + xdelta; 03922 // if (Debug) printf("Auto[%2d] = %10.4f - %10.4f\n",i,Strip[i].Lo,Strip[i].Hi); 03923 } 03924 return; 03925 } 03926 03927 03928 // Interface routine to model code in FORTRAN 03929 03930 void guiput_(char *aname, float *array, int *dimx, int *dimy, int *dimz) 03931 { 03932 int i,nb,nf; 03933 03934 if (Debug) printf("guiput(%s,%12.4e,%d,%d,%d)\n", 03935 aname,*array,*dimx,*dimy,*dimz); 03936 nf = (*dimx) * (*dimz); 03937 if (*dimy > 0) nf *= (*dimy); 03938 else nf *= 2; 03939 nb = nf * sizeof(float); 03940 for (i=0 ; i < NumArrays ; ++i) 03941 if (!strcmp(aname,Array[i].Name)) break; 03942 if (i == NumArrays) 03943 { 03944 ++NumArrays; 03945 strcpy(Array[i].Name,aname); 03946 Array[i].Data = FloatAlloc(nf,aname); 03947 Array[i].DimX = *dimx; 03948 Array[i].DimY = *dimy; 03949 Array[i].DimZ = *dimz; 03950 if (strcmp(aname,"GU") == 0) Uindex = i; 03951 if (strcmp(aname,"GV") == 0) Vindex = i; 03952 } 03953 if (Array[i].Data) memcpy(Array[i].Data,array,nb); 03954 Array[i].Flag = 1; // Data have changed 03955 } 03956 03957 03958 void guisend_(char *aname, float *array, int *dimx, int *dimy, int *dimz) 03959 { 03960 int i,nb,nf; 03961 03962 nf = (*dimx) * (*dimz); 03963 if (*dimy > 0) nf *= (*dimy); 03964 else nf *= 2; 03965 nb = nf * sizeof(float); 03966 for (i=0 ; i < NumArrays ; ++i) 03967 if (!strcmp(aname,Array[i].Name)) break; 03968 if (i == NumArrays) 03969 { 03970 ++NumArrays; 03971 strcpy(Array[i].Name,aname); 03972 Array[i].DimX = *dimx; 03973 Array[i].DimY = *dimy; 03974 Array[i].DimZ = *dimz; 03975 } 03976 Array[i].Data = array; 03977 Array[i].Flag = 1; // Data have changed 03978 } 03979 03980 03981 // Do the plot 03982 03983 void iso(int w,int PicType,REAL *field,int dimx,int dimy,int dimz,int pal) 03984 { 03985 char Text[128]; 03986 03987 int i,j,k,len,lens,xp,yp,status,x; 03988 int y,dx,r,width,height; 03989 INTXU border,depth; 03990 REAL f,o,ra,rb; 03991 int CapLines; 03992 float *tspt; 03993 XEvent WinEvent; 03994 Window Rootwin,Child; 03995 03996 // if (Debug) printf("iso(%d,%s,%12.4e,%d,%d,%d,%d)\n",w,IsoNames[PicType],*field,dimx,dimy,dimz,pal); 03997 if (Win[w] == 0) return; 03998 win = w; 03999 if (SkipFreq > 1 && (nstep % SkipFreq) != 0 && 04000 (PicType == ISOCS || PicType == ISOHOR || PicType == MAPHOR || PicType == ISOCOL)) return; 04001 XGetGeometry(display,Win[w],&Rootwin,&xp,&yp,&WinXSize,&WinYSize, 04002 &border,&depth); 04003 WinAtt[w].w = WinXSize; 04004 WinAtt[w].h = WinYSize; 04005 InXSize = WinXSize - OffX; 04006 InYSize = WinYSize - OffY; 04007 if (PicType != ISOTRA && PicType != MAPTRA) InYSize -= 20; // Room for colorbar 04008 DimX = dimx; 04009 DimY = dimy; 04010 DimZ = dimz; 04011 if (DimY < 0) DimY = -DimY; // Get NTP1 for ISOSH 04012 DimXY = DimX * DimY; 04013 VGAX = (InXSize-1.0) / (DimX-1.0); 04014 if (DimY > 1) VGAY = (InYSize-1.0) / (DimY-1.0); 04015 else VGAY = 1.0; 04016 Field = field; 04017 04018 if (PicType == ISOTRA || PicType == MAPTRA) 04019 { 04020 DimX = dimx; // NLON 04021 DimY = dimy; // NLAT 04022 DimZ = dimz; // NLEV 04023 DimXY = DimX * DimY; 04024 VGAX = (InXSize-1.0) / (DimX-1.0); 04025 VGAY = (InYSize-1.0) / (DimY-1.0); 04026 if (MaxZ[w] < DimZ) 04027 { 04028 MaxZ[w] = DimZ; 04029 Indez[w] = DimZ / 4; 04030 SwitchIndez(w,0); // Initialize title 04031 } 04032 } 04033 04034 if (PicType == ISOHOR || PicType == MAPHOR) 04035 { 04036 DimX = dimx; // NLON 04037 DimY = dimy; // NLAT 04038 DimZ = dimz; // NLEV 04039 DimXY = DimX * DimY; 04040 VGAX = (InXSize-1.0) / (DimX-1.0); 04041 VGAY = (InYSize-1.0) / (DimY-1.0); 04042 if (MaxZ[w] < DimZ) 04043 { 04044 MaxZ[w] = DimZ; 04045 Indez[w] = DimZ / 4; 04046 SwitchIndez(w,0); // Initialize title 04047 TSdata[w] = FloatAlloc(DimXY,"ISOLON"); 04048 } 04049 if (MapPro[w] == POLAR) 04050 { 04051 Field = TSdata[w]; 04052 lp2ps(field + Indez[w] * DimXY,Field); 04053 } 04054 /* 04055 else if (MapPro[w] == AZIMUTHAL) 04056 { 04057 Field = TSdata[w]; 04058 lp2az(field + Indez[w] * DimXY,Field,MapLR[w].l); 04059 } 04060 */ 04061 else Field = field + Indez[w] * DimXY; 04062 } 04063 04064 if (PicType == ISOLON) 04065 { 04066 DimX = dimx; // NLON 04067 DimY = dimz; // NLEV 04068 DimZ = dimy; // NLAT 04069 DimXY = DimX * DimY; 04070 VGAX = (InXSize-1.0) / (DimX-1.0); 04071 VGAY = (InYSize-1.0) / (DimY-1.0); 04072 if (!TSdata[w]) 04073 { 04074 TSdata[w] = FloatAlloc(DimXY,"ISOLON"); 04075 MaxZ[w] = DimZ; 04076 Indez[w] = DimZ / 4; 04077 SwitchIndez(w,0); // Initialize title 04078 } 04079 Field = TSdata[w]; 04080 for (j=0,i=0,k=DimX*Indez[w] ; j < DimY ; ++j,i+=DimX,k+=DimX*DimZ) 04081 { 04082 memcpy(Field+i,field+k,DimX * sizeof(REAL)); // copy latitude 04083 } 04084 } 04085 04086 if (PicType == ISOHOV) 04087 { 04088 DimX = dimx; // NLON 04089 DimY = DimT; // time 04090 DimZ = dimy; // NLAT 04091 DimXY = DimX * DimY; 04092 VGAX = (InXSize-1.0) / (DimX-1.0); 04093 VGAY = (InYSize-1.0) / (DimY-1.0); 04094 if (!TSdata[w]) 04095 { 04096 TSdata[w] = FloatAlloc(DimXY,"ISOHOV"); 04097 MaxZ[w] = DimZ; 04098 Indez[w] = DimZ / 4; 04099 SwitchIndez(w,0); // Initialize title 04100 } 04101 Field = TSdata[w]; 04102 memmove(Field+DimX,Field,(DimXY-DimX) * sizeof(REAL)); // scroll array 04103 memcpy(Field,field+Indez[w]*DimX,DimX * sizeof(REAL)); // add line 04104 } 04105 04106 // Advance write pointer HovInx until end of DimX 04107 // then scroll array and reset pointer 04108 04109 if (PicType == ISOTS) 04110 { 04111 DimX = DimT; // time 04112 DimY = dimx; // # of variables 04113 DimZ = dimz; 04114 DimXY = DimX * DimY; 04115 VGAX = (InXSize-1.0) / (DimX-1.0); 04116 VGAY = (InYSize-1.0) / (DimY-1.0); 04117 if (!TSdata[w]) 04118 { 04119 TSdata[w] = FloatAlloc(DimXY+DimX,"ISOTS"); 04120 } 04121 tspt = TSdata[w]; 04122 ++HovInx[w]; 04123 if (HovInx[w] >= DimX) 04124 { 04125 HovInx[w] = 0; 04126 memmove(tspt,tspt+DimX,DimXY * sizeof(REAL)); // scroll array 04127 } 04128 for (i=HovInx[w]+DimX-1,j=0 ; j < DimY ; i+=DimX,++j) 04129 tspt[i] = field[j]; // add column 04130 Field = tspt+HovInx[w]; 04131 } 04132 04133 if (PicType == ISOCOL) 04134 { 04135 DimX = DimT; // time 04136 DimY = dimx; // level 04137 DimZ = dimy; // clickable index 04138 DimXY = DimX * DimY; 04139 VGAX = (InXSize-1.0) / (DimX-1.0); 04140 VGAY = (InYSize-1.0) / (DimY-1.0); 04141 if (!TSdata[w]) 04142 { 04143 TSdata[w] = FloatAlloc(DimXY+DimX,"ISOCOL"); 04144 MaxZ[w] = DimZ; 04145 Indez[w] = DimZ / 2; 04146 SwitchIndez(w,0); // Initialize title 04147 } 04148 tspt = TSdata[w]; 04149 ++HovInx[w]; 04150 if (HovInx[w] >= DimX) 04151 { 04152 HovInx[w] = 0; 04153 memmove(tspt,tspt+DimX,DimXY * sizeof(REAL)); // scroll array 04154 } 04155 for (i=HovInx[w]+DimX-1,j=0 ; j < DimY ; i+=DimX,++j) 04156 tspt[i] = field[j+Indez[w]*DimY]; // add column 04157 Field = tspt+HovInx[w]; 04158 } 04159 04160 if (DimX > FlagSize) 04161 { 04162 if (Flag) free(Flag); 04163 Flag = IntAlloc(DimX,"Flag"); 04164 FlagSize = DimX; 04165 } 04166 04167 if (PicType == ISOSH) pal = 1; // ISOSH has its own palette 04168 if (pal < 1 || pal >= NUMPAL) 04169 { 04170 Cstrip = Autostrip; 04171 AutoPalette(w,Cstrip,Field,DimXY); 04172 Lines = AUTOCOLORS; 04173 // printf("Autopalette %d for Win %d\n",pal,w); 04174 } 04175 else 04176 { 04177 Cstrip = Pallet[pal]; 04178 Lines = LineCo[pal]; 04179 } 04180 04181 SizeChanged = (WinPixMap[w].DimX != WinXSize || WinPixMap[w].DimY != WinYSize); 04182 if (SizeChanged) 04183 { 04184 if (WinPixMap[w].Pix) XFreePixmap(display,WinPixMap[w].Pix); 04185 WinPixMap[w].Pix = XCreatePixmap(display,Win[w],WinXSize,WinYSize,ScreenD); 04186 if (Debug) 04187 printf("CreatePixmap %10x %6d bytes\n", 04188 (unsigned int)WinPixMap[w].Pix,WinXSize*WinYSize); 04189 WinPixMap[w].DimX = WinXSize; 04190 WinPixMap[w].DimY = WinYSize; 04191 } 04192 pix = WinPixMap[w].Pix; /* Set current pixmap */ 04193 04194 /* Draw colour bar */ 04195 04196 if ((SizeChanged || Cstrip == Autostrip) && 04197 (PicType == ISOCS || PicType == ISOHOR || 04198 PicType == ISOHOV || PicType == ISOLON || 04199 PicType == ISOCOL || PicType == MAPHOR )) 04200 { 04201 XSetForeground(display,gc,BlackPix); 04202 XFillRectangle(display,pix,gc,0,InYSize,WinXSize,WinYSize); 04203 04204 CapLines = WinXSize / (20 + 3 * FixFontWidth); 04205 if (CapLines > Lines) CapLines = Lines; 04206 for (i=0 ; i < CapLines ; ++i) 04207 { 04208 XSetForeground(display,gc,Cstrip[i].pixel); 04209 XFillRectangle(display,pix,gc,OffX+5+i*(WinXSize-20)/(CapLines-1), 04210 OffY+InYSize+5,10,10); 04211 XSetForeground(display,gc,BlackPix); 04212 XDrawRectangle(display,pix,gc,OffX+5+i*(WinXSize-20)/(CapLines-1), 04213 OffY+InYSize+5,10,10); 04214 } 04215 XSetForeground(display,gc,WhitePix); 04216 XSetBackground(display,gc,BlackPix); 04217 rb = Cstrip[CapLines-2].Hi - Cstrip[0].Hi; 04218 for (i=0 ; i < CapLines-1 ; ++i) 04219 { 04220 Text[0] = 0; 04221 ra = Cstrip[i].Hi; 04222 j = ra; 04223 if (j > -1000 && j < 10000) sprintf(Text,"%d",j); 04224 if (ra < 100.0 && ra > -9.99) 04225 { 04226 sprintf(Text,"%4.1f",ra); 04227 if (!strcmp(Text+2,".0")) Text[2] = 0; 04228 } 04229 if (ra < 10.0 && ra >= 0.0) 04230 { 04231 sprintf(Text,"%4.2f",ra); 04232 if (!strcmp(Text+1,".00")) Text[1] = 0; 04233 } 04234 len = strlen(Text); 04235 if (len) 04236 { 04237 width = XTextWidth(FixFont,Text,len); 04238 height = FixFont->ascent + FixFont->descent; 04239 xp = OffX + 10 + (i+0.5) * (WinXSize-20)/(CapLines-1) - width/2; 04240 yp = WinYSize - height + 10; 04241 XDrawImageString(display,pix,gc,xp,yp,Text,len); 04242 } 04243 } 04244 } 04245 04246 /* Draw mode legend */ 04247 04248 if (SizeChanged && PicType == ISOSH) 04249 { 04250 dx = WinXSize / 23; 04251 XSetForeground(display,gc,BlackPix); 04252 XFillRectangle(display,pix,gc,0,0,WinXSize,WinYSize); 04253 04254 XSetForeground(display,gc,LightGreen.pixel); 04255 XSetBackground(display,gc,BlackPix); 04256 for (i=0 ; i < 21 ; i+=2) 04257 { 04258 sprintf(Text,"%d",i); 04259 len = strlen(Text); 04260 width = XTextWidth(FixFont,Text,len); 04261 height = FixFont->ascent + FixFont->descent; 04262 xp = dx + i * dx - width/2 - FixFontWidth/2 + 1; 04263 yp = FixFontHeight; 04264 XDrawImageString(display,pix,gc,xp,yp,Text,len); 04265 } 04266 XSetForeground(display,gc,LightBlue.pixel); 04267 for (i=0 ; i < 21 ; i+=2) 04268 { 04269 sprintf(Text,"%d",i); 04270 len = strlen(Text); 04271 width = XTextWidth(FixFont,Text,len); 04272 height = FixFont->ascent + FixFont->descent; 04273 xp = WinXSize - width - 2; 04274 yp = 2 * FixFontHeight + i * dx; 04275 if (yp+FixFont->descent > InYSize) break; 04276 XDrawImageString(display,pix,gc,xp,yp,Text,len); 04277 } 04278 strcpy(Text,"n/m"); 04279 len = strlen(Text); 04280 width = XTextWidth(FixFont,Text,len); 04281 xp = WinXSize - width - 2; 04282 yp = FixFontHeight; 04283 XSetForeground(display,gc,WhitePix); 04284 XDrawImageString(display,pix,gc,xp,yp,Text,len); 04285 strcpy(Text,"High "); 04286 len = strlen(Text); 04287 width = XTextWidth(FixFont,Text,len); 04288 xp = WinXSize/2 - AMPLI_COLS * 10 - width; 04289 yp = WinYSize - FixFontHeight + 10; 04290 r = FixFontHeight-2; 04291 XSetForeground(display,gc,WhitePix); 04292 if (xp > 0) XDrawImageString(display,pix,gc,xp,yp,Text,len); 04293 strcpy(Text," Low"); 04294 len = strlen(Text); 04295 width = XTextWidth(FixFont,Text,len); 04296 xp = WinXSize/2 + AMPLI_COLS * 10; 04297 if (xp + width < WinXSize) XDrawImageString(display,pix,gc,xp,yp,Text,len); 04298 yp = InYSize; 04299 XDrawLine(display,pix,gc,OffX,yp,WinXSize,yp); 04300 yp = WinYSize - r - FixFont->descent; 04301 04302 for (i=0 ; i < AMPLI_COLS ; ++i) 04303 { 04304 xp = WinXSize/2 - AMPLI_COLS * 10 + i * 20; 04305 XSetForeground(display,gc,AmpliStrip[AMPLI_COLS-i-1].pixel); 04306 XFillArc(display,pix,gc,xp,yp,r,r,0,360*64); 04307 } 04308 } 04309 04310 if (SizeChanged && PicType == ISOTS) /* Timeseries Caption */ 04311 { 04312 XSetForeground(display,gc,BlackPix); 04313 XFillRectangle(display,pix,gc,0,InYSize,WinXSize,WinYSize); 04314 XSetBackground(display,gc,BlackPix); 04315 04316 xp = FixFontWidth; 04317 yp = WinYSize - FixFontHeight + 10; 04318 for (j=0 ; j < DimY ; ++j) 04319 { 04320 if (TSName[j][0]) 04321 { 04322 strcpy(Text,TSName[j]); 04323 len = strlen(Text); 04324 width = XTextWidth(FixFont,Text,len); 04325 XSetForeground(display,gc,TSColor[j]); 04326 XDrawImageString(display,pix,gc,xp,yp,Text,len); 04327 xp += width; 04328 } 04329 if (TSubsc[j][0]) 04330 { 04331 XSetFont(display, gc, SubFont->fid); 04332 strcpy(Text,TSubsc[j]); 04333 len = strlen(Text); 04334 width = XTextWidth(SubFont,Text,len); 04335 XSetForeground(display,gc,TSColor[j]); 04336 XDrawImageString(display,pix,gc,xp,yp,Text,len); 04337 xp += width; 04338 XSetFont(display, gc, FixFont->fid); 04339 } 04340 xp += FixFontWidth; 04341 } 04342 } 04343 04344 if (SizeChanged && PicType == ISOTAB) /* Table Caption */ 04345 { 04346 XSetForeground(display,gc,BlackPix); 04347 XFillRectangle(display,pix,gc,0,0,WinXSize,WinYSize); 04348 XSetBackground(display,gc,BlackPix); 04349 } 04350 04351 if (PicType == ISOTS) 04352 { 04353 if (TSxp[w] == NULL) TSxp[w] = SizeAlloc(DimX * DimY , sizeof(XPoint),"TSxp"); 04354 if (Dmin[w] == NULL) Dmin[w] = FloatAlloc(DimY ,"Dmin"); 04355 if (Dmax[w] == NULL) Dmax[w] = FloatAlloc(DimY ,"Dmax"); 04356 XSetForeground(display,gc,BlackPix); 04357 XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize); 04358 04359 for (j=0 ; j < DimY ; ++j) Dmin[w][j] = Dmax[w][j] = field[j]; 04360 if (nstep > 2) 04361 { 04362 for (j=0 ; j < DimY ; ++j) 04363 { 04364 for (i=1 ; i < DimX ; ++i) 04365 { 04366 Dmin[w][j] = MIN(Dmin[w][j],Field[i+j*DimX]); 04367 Dmax[w][j] = MAX(Dmax[w][j],Field[i+j*DimX]); 04368 } 04369 } 04370 } 04371 04372 if (nstep > 2) 04373 for (j=0 ; j < DimY ; ++j) 04374 { 04375 XSetForeground(display,gc,TSColor[j]); 04376 o = Dmin[w][j]; 04377 if ((Dmax[w][j] - Dmin[w][j]) > 1.0e-20) f = (InYSize-2) / (Dmax[w][j] - Dmin[w][j]); 04378 else f = 1.0; 04379 04380 for (i=1 ; i < DimX ; ++i) 04381 { 04382 TSxp[w][i].x = VGAX * i; 04383 TSxp[w][i].y = InYSize - 1 - f * (Field[i+j*DimX] - o); 04384 } 04385 XDrawLines(display,pix,gc,TSxp[w]+1,DimX-1,CoordModeOrigin); 04386 } 04387 } 04388 04389 if (PicType == ISOTAB) 04390 { 04391 XSetForeground(display,gc,BlackPix); 04392 XSetBackground(display,gc,BlackPix); 04393 XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize); 04394 XSetFont(display, gc, BigFont->fid); 04395 yp = BigFontHeight; 04396 for (j=0 ; j < DimX ; ++j) 04397 if (TSName[j][0]) 04398 { 04399 XSetForeground(display,gc,TSColor[j]); 04400 xp = BigFontWidth; 04401 strcpy(Text,TSName[j]); 04402 len = strlen(Text); 04403 XDrawImageString(display,pix,gc,xp,yp,Text,len); 04404 xp += XTextWidth(BigFont,Text,len); 04405 if (TSubsc[j][0]) 04406 { 04407 XSetFont(display, gc, FixFont->fid); 04408 XDrawImageString(display,pix,gc,xp,yp,TSubsc[j],strlen(TSubsc[j])); 04409 XSetFont(display, gc, BigFont->fid); 04410 } 04411 xp = 8 * BigFontWidth; 04412 if (TSUnit[j][0]) 04413 { 04414 sprintf(Text,"= %7.3f [%s]",field[j],TSUnit[j]); 04415 if (TScale[j][0]) strcat(Text," 10"); 04416 len = strlen(Text); 04417 XDrawImageString(display,pix,gc,xp,yp,Text,len); 04418 if (TScale[j][0] > ' ') 04419 { 04420 lens = strlen(TScale[j]); 04421 XSetFont(display, gc, FixFont->fid); 04422 XDrawImageString(display,pix,gc,xp+len*BigFontWidth,yp-BigFontHeight+FixFontHeight,TScale[j],lens); 04423 XSetFont(display, gc, BigFont->fid); 04424 } 04425 } 04426 yp += BigFontHeight; 04427 } 04428 XSetFont(display, gc, FixFont->fid); 04429 } 04430 04431 if (PicType == ISOTRA) 04432 { 04433 XSetForeground(display,gc,BlackPix); 04434 XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize); 04435 if (SizeChanged) ClearTracer(); 04436 TracerPlot(w); 04437 } 04438 if (PicType == MAPTRA) 04439 { 04440 if (SizeChanged) ClearTracer(); 04441 if (MapHR.X) 04442 { 04443 if (MapPro[w] == AZIMUTHAL) 04444 { 04445 if (RedrawFlag[w] || MapLR[w].w != WinXSize || MapLR[w].h != InYSize || 04446 (nstep % rmui == 0 && MapLR[w].f != 0)) 04447 { 04448 RedrawFlag[w] = 0; 04449 MapLR[w].w = WinXSize; 04450 MapLR[w].h = InYSize; 04451 MapLR[w].l += MapLR[w].r; 04452 if (MapLR[w].l < -180.0) MapLR[w].l += 360.0; 04453 if (MapLR[w].l > 180.0) MapLR[w].l -= 360.0; 04454 AzimuthalImage(&MapHR,&MapLR[w]); 04455 } 04456 } 04457 else 04458 { 04459 if (RedrawFlag[w] || MapLR[w].w != WinXSize || MapLR[w].h != InYSize) 04460 { 04461 RedrawFlag[w] = 0; 04462 MapLR[w].w = WinXSize; 04463 MapLR[w].h = InYSize; 04464 if (MapPro[w] == 1) PolarImage(&MapHR,&MapLR[w]); 04465 else ScaleImage(&MapHR,&MapLR[w]); 04466 } 04467 } 04468 XPutImage(display,pix,gc,MapLR[w].X,0,0,0,0,MapLR[w].w,MapLR[w].h); 04469 } 04470 else 04471 { 04472 XSetForeground(display,gc,BlackPix); 04473 XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize); 04474 } 04475 TracerPlot(w); 04476 } 04477 if (PicType == ISOCS || PicType == ISOHOR || PicType == ISOLON || PicType == ISOCOL) 04478 { 04479 XSetForeground(display,gc,BlackPix); 04480 XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize); 04481 IsoAreas(Cstrip); 04482 IsoLines(Cstrip,0); 04483 } 04484 if (PicType == MAPHOR) 04485 { 04486 if (MapHR.X) 04487 { 04488 if (MapPro[w] == AZIMUTHAL) 04489 { 04490 if (RedrawFlag[w] || MapLR[w].w != WinXSize || MapLR[w].h != InYSize || 04491 (nstep % rmui == 0 && MapLR[w].f != 0)) 04492 { 04493 RedrawFlag[w] = 0; 04494 MapLR[w].w = WinXSize; 04495 MapLR[w].h = InYSize; 04496 MapLR[w].l += MapLR[w].r; 04497 if (MapLR[w].l < -180.0) MapLR[w].l += 360.0; 04498 if (MapLR[w].l > 180.0) MapLR[w].l -= 360.0; 04499 AzimuthalImage(&MapHR,&MapLR[w]); 04500 } 04501 XPutImage(display,pix,gc,MapLR[w].X,0,0,0,0,MapLR[w].w,MapLR[w].h); 04502 MapLines(Cstrip,1); 04503 } 04504 else 04505 { 04506 if (RedrawFlag[w] || MapLR[w].w != WinXSize || MapLR[w].h != InYSize) 04507 { 04508 RedrawFlag[w] = 0; 04509 MapLR[w].w = WinXSize; 04510 MapLR[w].h = InYSize; 04511 if (MapPro[w] == 1) PolarImage(&MapHR,&MapLR[w]); 04512 else ScaleImage(&MapHR,&MapLR[w]); 04513 } 04514 XPutImage(display,pix,gc,MapLR[w].X,0,0,0,0,MapLR[w].w,MapLR[w].h); 04515 IsoLines(Cstrip,1); 04516 } 04517 } 04518 else 04519 { 04520 XSetForeground(display,gc,BlackPix); 04521 XFillRectangle(display,pix,gc,0,0,WinXSize,InYSize); 04522 IsoLines(Cstrip,1); 04523 } 04524 } 04525 if (PicType == ISOHOV) 04526 { 04527 IsoAreas(Cstrip); 04528 } 04529 04530 if (PicType == ISOSH) 04531 { 04532 AmplitudePlot(); 04533 } 04534 04535 if (Grid && PicType == ISOCS) ShowGridCS(); 04536 if (Grid && PicType == ISOLON) ShowGridLonsi(); 04537 if (Grid && PicType == ISOHOV && MapPro[w] == 0) ShowGridHov(); 04538 if (Grid && PicType == ISOHOV && MapPro[w] == 1) ShowGridHovT(); 04539 if (PicType == ISOHOR && MapPro[w] == 1) ShowGridPolar(); 04540 if (Grid && PicType == ISOHOR && MapPro[w] == 0) ShowGridCyl(); 04541 if (Grid && PicType == ISOCOL) ShowGridCol(); 04542 04543 XCopyArea(display,pix,Win[w],gc,0,0,WinXSize,WinYSize,0,0); 04544 } 04545 04546 04547 /* ==================================================================== */ 04548 /* iguistep - this function is called from the model for every timestep */ 04549 /* ==================================================================== */ 04550 04551 int iguistep_(float pparcs[],int kdatim[]) 04552 { 04553 int i,j,w; // Loop indices 04554 struct timeval TimeVal; // Retrieve time info 04555 04556 if (Debug) printf("iguistep(%12.2e,%d-%d-%d)\n", 04557 pparcs[0],kdatim[0],kdatim[1],kdatim[2]); 04558 nstep++; 04559 memcpy(ndatim,kdatim,sizeof(ndatim)); 04560 DeltaTime = ndatim[4] - LastMinute; 04561 if (DeltaTime < 0) DeltaTime += 60; 04562 if (DeltaTime ==0) DeltaTime = 60; 04563 LastMinute = ndatim[4]; 04564 04565 // Compute frames per second every 20 calls 04566 04567 gettimeofday(&TimeVal,NULL); 04568 LastSecond = ThisSecond; 04569 ThisSecond = TimeVal.tv_sec; 04570 04571 if (SecEvent = ThisSecond > LastSecond) 04572 { 04573 fps = nstep - LastStep; 04574 LastStep = nstep; 04575 rmui = fps / rmuf; 04576 if (rmui < 1) rmui = 1; 04577 } 04578 04579 SkipFreq = 1 + fps / 30; // Reduce plot rate on fast cpu's 04580 if (SkipFreq < 0 || SkipFreq > 10) SkipFreq = 0; 04581 04582 for (w=0 ; w < NumWin ; ++w) 04583 { 04584 for (j=0 ; j < NumArrays ; ++j) 04585 { 04586 if (!strcmp(WinAtt[w].array_name,Array[j].Name)) 04587 { 04588 if (Array[j].Flag || RedrawFlag[w]) 04589 iso(w,WinAtt[w].Plot,Array[j].Data,Array[j].DimX,Array[j].DimY, 04590 Array[j].DimZ,WinAtt[w].Palette); 04591 } 04592 } 04593 } 04594 04595 for (i=0 ; i < Parcs ; ++i) Parc[i].Val = pparcs[i]; 04596 ShowStep(); 04597 ShowParcs(); 04598 HandleEvents(); 04599 if (XCheckTypedWindowEvent(display,Cow,Expose,&CowEvent)) 04600 RedrawControlWindow(); 04601 for (i=0 ; i < Parcs ; ++i) pparcs[i] = Parc[i].Val; 04602 04603 XSync(display,1); 04604 if (Shutdown && MRpid < 1) SaveConfig(); 04605 if (Debug) printf("iguistep returns %d\n",Shutdown); 04606 return Shutdown; 04607 } 04608 04609 int nresources_(double *ut, double *st, long *mem, long *par, long *paf, 04610 long *swa, long *dr, long *dw) 04611 { 04612 struct rusage ru; 04613 getrusage(RUSAGE_SELF,&ru); 04614 *ut = ru.ru_utime.tv_sec + 0.000001 * ru.ru_utime.tv_usec; 04615 *st = ru.ru_stime.tv_sec + 0.000001 * ru.ru_stime.tv_usec; 04616 *mem = ru.ru_maxrss; 04617 *par = ru.ru_minflt; 04618 *paf = ru.ru_majflt; 04619 *swa = ru.ru_nswap; 04620 *dr = ru.ru_inblock; 04621 *dw = ru.ru_oublock; 04622 return 1; 04623 } 04624 04625 /* ------------------------------------------------ */ 04626 /* Stub routines for Absoft Compiler and others, */ 04627 /* which require, that FORTRAN callable C-functions */ 04628 /* are written in uppercase letters only */ 04629 /* ------------------------------------------------ */ 04630 04631 04632 void INITGUI(int *model, int *debug, int *lats, int *mrpid, int *mrnum) 04633 { 04634 initgui_(model,debug,lats,mrpid,mrnum); 04635 } 04636 04637 void GUICLOSE(void) 04638 { 04639 guiclose_(); 04640 } 04641 04642 int IGUISTEP(float pparcs[], int kdatim[]) 04643 { 04644 return iguistep_(pparcs,kdatim); 04645 } 04646 04647 void GUIPUT(char *aname, float *array, int *dimx, int *dimy, int *dimz) 04648 { 04649 guiput_(aname, array, dimx, dimy, dimz); 04650 } 04651 04652 int NRESOURCES(double *ut, double *st, long *mem, long *par, long *paf, 04653 long *swa, long *dr, long *dw) 04654 { 04655 return nresources_(ut,st,mem,par,paf,swa,dr,dw); 04656 } 04657 04658 /* ------------------------------------------------ */ 04659 /* Stub routines for IBM Compiler and others, */ 04660 /* which require, that FORTRAN callable C-functions */ 04661 /* are written in lowercase without underscore */ 04662 /* ------------------------------------------------ */ 04663 04664 04665 void initgui(int *model, int *debug, int *lats, int *mrpid, int *mrnum) 04666 { 04667 initgui_(model,debug,lats,mrpid,mrnum); 04668 } 04669 04670 void guiclose(void) 04671 { 04672 guiclose_(); 04673 } 04674 04675 int iguistep(float pparcs[], int kdatim[]) 04676 { 04677 return iguistep_(pparcs,kdatim); 04678 } 04679 04680 void guiput(char *aname, float *array, int *dimx, int *dimy, int *dimz) 04681 { 04682 guiput_(aname, array, dimx, dimy, dimz); 04683 } 04684 04685 int iguinan_(double *p) 04686 { 04687 return isnan(*p); 04688 } 04689 04690 int nresources(double *ut, double *st, long *mem, long *par, long *paf, 04691 long *swa, long *dr, long *dw) 04692 { 04693 return nresources_(ut,st,mem,par,paf,swa,dr,dw); 04694 }