Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

xstarplot.C

Go to the documentation of this file.
00001 
00015 
00016 //.............................................................................
00017 //    version 1:  May 1989   Piet Hut            email: piet@iassns.bitnet
00018 //                           Institute for Advanced Study, Princeton, NJ, USA
00019 //    version 2:  Dec 1992   Piet Hut      adapted to the new C++-based Starlab
00020 //    version 3:  Dec 1992   Steve McMillan      email: steve@zonker.drexel.edu
00021 //                           Drexel University, Philadelphia, PA, USA
00022 //                           Converted original ASCIIplot to X --- FIRST DRAFT!
00023 //    version 4:  Jan 1994   Biao Lu             email: biao@eagle.drexel.edu
00024 //                           Drexel University, Philadelphia, PA, USA
00025 //                           Use new X interface for movie.
00026 //            Aug/Sep 1994   Cleaned up and expanded, SMcM
00027 //.............................................................................
00028 //  non-local functions: 
00029 //    xstarplot
00030 //.............................................................................
00031 //  uses:
00032 //    liblux.a (X interface)
00033 //    The X graphics library
00034 //.............................................................................
00035 
00036 // NOTE: On some systems, it appears that overflow can occur, causing the
00037 //       win.lnx and win.lny entries to be overwritten and leading to
00038 //       spurious "log10" errors in draw.c (in lux_set_item, specifically).
00039 //       This isn't fatal, but it should be fixed someday...
00040 
00041 #include "dyn.h"
00042 #include <strstream.h>
00043 
00044 #define HALF_ROOT2   0.707106781186547524400844362105   // Root2/2
00045 #define ROOT2        1.414213562373095048801688724210   // sqrt(2)
00046 
00047 #define GRAPH_WINDOW    1
00048 #define POPUP_WINDOW    2
00049 #define DIALOG_WINDOW   3
00050 #define BUTTON_WINDOW   4
00051 #define INPUT_WINDOW    5
00052 #define TEXT_WINDOW     6    
00053 
00054 #define NO_TYPE         0
00055 #define OK_BUTTON       1
00056 #define CANCEL_BUTTON   2
00057 #define CHECK_BUTTON    3
00058 #define OK_KEEP_BUTTON  4
00059 
00060 // The following #defines used to be conditional on g++...
00061 // The LUX functions are in lux/interface.c.
00062 
00063 #define lux_openwin                 LUX_openwin
00064 #define lux_setup_region            LUX_setup_region
00065 #define lux_clear_current_region    LUX_clear_current_region
00066 #define lux_setup_axis              LUX_setup_axis
00067 #define lux_draw_linef              LUX_draw_linef
00068 #define lux_draw_pointf             LUX_draw_pointf
00069 #define lux_draw_rectanglef         LUX_draw_rectanglef
00070 #define lux_draw_arcf               LUX_draw_arcf
00071 #define lux_fill_arcf               LUX_fill_arcf
00072 #define lux_draw_axis               LUX_draw_axis
00073 #define lux_getevent                LUX_getevent 
00074 #define lux_exit                    LUX_quick_exit      // Note!
00075 #define lux_set_color               LUX_set_color
00076 #define lux_lookup_color            LUX_lookup_color
00077 #define lux_rgb_pixel               LUX_rgb_pixel
00078 #define lux_draw_vstring            LUX_draw_vstring 
00079 #define lux_draw_string             LUX_draw_string
00080 #define lux_draw_image_string       LUX_draw_image_string
00081 #define lux_check_keypress          LUX_check_keypress
00082 #define lux_check_buttonpress       LUX_check_buttonpress
00083 #define lux_open_dialog             LUX_open_dialog
00084 #define lux_draw_palette            LUX_draw_palette 
00085 #define lux_set_item                LUX_set_item
00086 #define lux_get_itemvalue           LUX_get_itemvalue
00087 #define lux_update_itemvalue        LUX_update_itemvalue
00088 #define lux_clear_window            LUX_clear_window
00089 #define lux_reset_window            LUX_reset_window
00090 #define lux_update_fg               LUX_update_fg
00091 #define lux_show_dialog             LUX_show_dialog
00092 #define lux_reconvert_rcoord        LUX_reconvert_rcoord
00093 #define lux_set_linestyle           LUX_set_linestyle
00094 #define lux_set_window_name         LUX_set_window_name      
00095 #define lux_set_window_bgcolor      LUX_set_window_bgcolor      
00096 #define lux_set_bgcolor             LUX_set_bgcolor      
00097 #define lux_set_noupdate            LUX_set_noupdate
00098 #define lux_next_keypress           LUX_next_keypress
00099 
00100 extern "C" unsigned long lux_openwin(int , int , int , int );
00101 extern "C" int lux_set_window_name(unsigned long, char*);
00102 extern "C" int lux_setup_region(unsigned long, float,float,float,float );
00103 extern "C" int lux_clear_current_region(unsigned long);
00104 extern "C" int lux_setup_axis(unsigned long, float,float,float,float );
00105 extern "C" int lux_draw_linef(unsigned long,float,float,float,float);
00106 extern "C" int lux_draw_pointf(unsigned long,float,float);
00107 extern "C" int lux_draw_rectanglef(unsigned long,float,float,float,float);
00108 extern "C" int lux_draw_arcf(unsigned long,float,float,float,float,float,float);
00109 extern "C" int lux_fill_arcf(unsigned long,float,float,float,float,float,float);
00110 extern "C" int lux_draw_axis(unsigned long);
00111 extern "C" int lux_getevent();
00112 extern "C" int lux_exit();
00113 extern "C" int lux_set_color(unsigned long, long);
00114 extern "C" int lux_set_window_bgcolor(unsigned long, long);
00115 extern "C" int lux_set_bgcolor(unsigned long, long);
00116 extern "C" unsigned long lux_rgb_pixel(unsigned long, float, float,float);
00117 extern "C" unsigned long lux_lookup_color(unsigned long, char*);
00118 extern "C" int lux_draw_string(unsigned long, float, float, float,
00119                                char*, char);
00120 extern "C" int lux_draw_vstring(unsigned long, float, float, float,
00121                                 char*, char);
00122 extern "C" int lux_draw_image_string(unsigned long, float, float, float,
00123                                      char*, char);
00124 extern "C" int lux_check_keypress(unsigned long,char);
00125 extern "C" int lux_check_buttonpress(unsigned long);
00126 extern "C" unsigned long lux_open_dialog(int, int, int, int);
00127 extern "C" int lux_set_item(unsigned long, int, int, int, int,
00128                             int, int, char*);
00129 extern "C" int lux_draw_palette(unsigned long);
00130 extern "C" int lux_get_itemvalue(unsigned long, int, int, int, char*);
00131 extern "C" int lux_update_itemvalue(unsigned long, int, int, int, char*);
00132 extern "C" int lux_clear_window(unsigned long);
00133 extern "C" int lux_reset_window(unsigned long);
00134 extern "C" int lux_update_fg(unsigned long);
00135 extern "C" int lux_show_dialog(unsigned long);
00136 extern "C" int lux_reconvert_rcoord(unsigned long, int, int, float*, float*);
00137 extern "C" int lux_set_linestyle(unsigned long, int);
00138 extern "C" int lux_set_noupdate(unsigned long);
00139 extern "C" int lux_next_keypress(unsigned long, char*, char*, char*, char*);
00140 
00141 // These should probably be made into "interface" routines someday...
00142 
00143 extern "C" int get_mouse_position(unsigned long, float*, float*);
00144 extern "C" void set_default_font(char*);
00145 extern "C" void lux_pause(int);
00146 
00147 #define background_color 0
00148 #define default_color    1
00149 #define bound_single     2
00150 #define bound_binary     3
00151 #define unbound_single   4
00152 #define unbound_binary   5
00153 
00154 // Define index color scheme here (NV = normal video, RV = reverse video):
00155 
00156 #define N_COLORS 16
00157 
00158 // First 8 are good, next 8 need work, especially in the NV case...
00159 
00160 #define NV_COLOR1 "black"
00161 #define NV_COLOR2 "red"
00162 #define NV_COLOR3 "limegreen"
00163 #define NV_COLOR4 "blue"
00164 #define NV_COLOR5 "gold"
00165 #define NV_COLOR6 "magenta"
00166 #define NV_COLOR7 "dark goldenrod"
00167 #define NV_COLOR8 "lightpink"
00168 #define NV_COLOR9 "aquamarine"
00169 #define NV_COLORa "cyan"
00170 #define NV_COLORb "lightgrey"
00171 #define NV_COLORc "turquoise"
00172 #define NV_COLORd "gold"
00173 #define NV_COLORe "thistle"
00174 #define NV_COLORf "beige"
00175 #define NV_COLORg "plum"
00176 
00177 #define RV_COLOR1 "white"
00178 #define RV_COLOR2 "red"
00179 #define RV_COLOR3 "green"
00180 #define RV_COLOR4 "lightblue"
00181 #define RV_COLOR5 "yellow"
00182 #define RV_COLOR6 "magenta"
00183 #define RV_COLOR7 "orange"
00184 #define RV_COLOR8 "pink"
00185 #define RV_COLOR9 "aquamarine"
00186 #define RV_COLORa "cyan"
00187 #define RV_COLORb "lightgrey"
00188 #define RV_COLORc "turquoise"
00189 #define RV_COLORd "gold"
00190 #define RV_COLORe "thistle"
00191 #define RV_COLORf "beige"
00192 #define RV_COLORg "plum"
00193 
00194 #define TAB "               "
00195 
00196 //#define FAC3D         2.13
00197 //#define FAC3D         1.5
00198 #define FAC3D           1.75
00199 
00200 #define ZOOM            ROOT2
00201 #define PFAC            1.1892
00202 
00203 enum   {colorenergy=1, tracking, graph3dim};
00204 enum   {xminimum=1, xmaximum, yminimum, ymaximum,
00205         pointsize, lmax3D,
00206         theta3D, phi3D,  
00207         DelayTime, dtheta3D, color,
00208         Origin, Xorigin, Yorigin, Zorigin,
00209         View2D, view2D, originstar, OriginStar};
00210 enum   {ok=1, ok_keep, cancel};
00211 
00212 char   temp_buffer[255];        // Convenient to share this temporary space.
00213 
00214 void accumulate_potential_energy(dyn* bj, dyn*bi,
00215                                  real& epot, real& rmin, dynptr& bmin)
00216 
00217 // Determine the potential energy of bi with respect to bj, along
00218 // with bi's nearest neighbor and minimum neighbor distance.
00219 
00220 {
00221     if (bj->get_oldest_daughter() != (dyn*)NULL)
00222         for (dyn * bb = bj->get_oldest_daughter(); bb != (dyn*)NULL;
00223             bb = bb->get_younger_sister()) {
00224             accumulate_potential_energy(bb, bi, epot, rmin, bmin);
00225         }
00226     else
00227         if (bi != bj) {
00228             vector d_pos = bi->get_pos() - bj->get_pos();
00229             real mi = bi->get_mass();
00230             real mj = bj->get_mass();
00231             real r = sqrt(d_pos * d_pos);
00232             epot += -mi*mj/r;
00233             if (r < rmin) {rmin = r; bmin = bj;}
00234         }
00235 }
00236 
00237 // compute_energies: calculate the appropriate color code for particle bi
00238 //                   relative to "particle" bj (usually the root node).
00239 
00240 void compute_energies(dyn* bj, dyn* bi, char& c)
00241 {
00242     c = default_color;
00243 
00244     real   epot = 0, rmin = VERY_LARGE_NUMBER;
00245     dynptr bmin = bi;
00246 
00247     accumulate_potential_energy(bj, bi, epot, rmin, bmin);
00248 
00249     real   mi = bi->get_mass();
00250     real   mj = bmin->get_mass();
00251     vector d_vel = bi->get_vel() - bmin->get_vel();
00252     vector d_pos = bi->get_pos() - bmin->get_pos();
00253     real   r = sqrt(d_pos * d_pos);
00254     real   e0 = (0.5 * d_vel * d_vel - (mi + mj)/r);
00255 
00256     if (e0 < 0) {
00257         real   epot1 = 0, rmin1 = VERY_LARGE_NUMBER;
00258         dynptr bmin1 = bi;
00259 
00260         accumulate_potential_energy(bj, bmin, epot1, rmin1, bmin1);
00261 
00262         if (bi == bmin1) {
00263             real e  = - mi*mj / r;
00264             vector R_vel = (mi*bi->get_vel()+mj*bmin->get_vel())/(mi+mj);
00265             real ekin = 0.5*(mi+mj)*R_vel*R_vel;
00266 
00267             if (epot + epot1 - 2*e + ekin < 0) c = bound_binary;
00268             else c = unbound_binary;
00269 
00270         } else c = bound_single;
00271 
00272     } else {
00273         vector vel = bi->get_vel();
00274         real ekin = 0.5*bi->get_mass()*vel*vel;
00275         
00276         if (ekin + epot > 0.0) c = unbound_single;
00277     }
00278 }
00279 
00280 // Note overloaded function project3d:
00281 
00282 void project3d(float x, float y, float z, float& X, float& Y,
00283                float ct, float st, float cp, float sp,
00284                float vx, float vy, float vz, float& dv2)
00285 {
00286     float xp, yp, zp, xf, yf, zf;
00287 
00288     // Along z-axis rotate theta
00289     xp =  ct*x + st*y;
00290     yp = -st*x + ct*y;
00291     zp =  z;
00292 
00293     // Along y-axis rotate phi
00294     xf =  cp*xp + sp*zp;
00295     yf =  yp;
00296     zf = -sp*xp + cp*zp;
00297 
00298     // Project
00299     X  = yf; Y=zf;
00300     dv2 = (vx-xf)*(vx-xf) + (vy-yf)*(vy-yf) + (vz-zf)*(vz-zf);
00301 }
00302 
00303 void project3d(float x, float y, float z, float& X, float& Y,
00304                float ct, float st, float cp, float sp)
00305 {
00306     float xp, yp, zp, xf, yf, zf;
00307 
00308     // Along z-axis rotate theta
00309     xp =  ct*x + st*y;
00310     yp = -st*x + ct*y;
00311     zp =  z;
00312 
00313     // Along y-axis rotate phi
00314     xf =  cp*xp + sp*zp;
00315     yf =  yp;
00316     zf = -sp*xp + cp*zp;
00317 
00318     // Project
00319     X  = yf; Y=zf;
00320 }
00321 
00322 void draw3d_axis(unsigned long win, float lmax,
00323                  float ct, float st, float cp, float sp)
00324 {
00325     float X[8], Y[8], Z[8], XP[8], YP[8], D[8], X0, Y0, Z0, dmax = 0.0;
00326     float xp,yp;
00327     int i, i0;
00328     static int od1[] = {1,2,4,3,5,6,8,7,1,2,4,3};
00329     static int od2[] = {2,4,3,1,6,8,7,5,5,6,8,7};
00330 
00331     X0 = lmax; Y0 = 0.0; Z0 = 0.0;
00332     for (i=0;i<8;i++) {
00333         X[i] = lmax*((i&0x0001)?-1:1);
00334         Y[i] = lmax*((i&0x0002)?-1:1);
00335         Z[i] = lmax*((i&0x0004)?-1:1);
00336         project3d(X[i], Y[i], Z[i], XP[i], YP[i],
00337                   ct, st, cp, sp,
00338                   X0, Y0, Z0, D[i]);
00339         if (D[i] > dmax) {dmax = D[i]; i0 = i;}
00340     }
00341 
00342     for (i=0;i<12;i++) {
00343         if (od1[i] == i0+1 || od2[i] == i0+1) lux_set_linestyle(win,1);
00344         else lux_set_linestyle(win,0);
00345         lux_draw_linef(win,XP[od1[i]-1],YP[od1[i]-1],XP[od2[i]-1],YP[od2[i]-1]);
00346     }
00347     lux_set_linestyle(win,0);
00348 
00349     // labels:
00350     project3d(0.0,-lmax*1.1,-lmax*1.1, xp, yp, ct,st,cp,sp);
00351     lux_draw_string(win, xp, yp, -0.5, "x", 0); 
00352     project3d(-lmax*1.1,0.0,-lmax*1.1, xp, yp, ct,st,cp,sp);
00353     lux_draw_string(win, xp, yp, -0.5, "y", 0); 
00354     project3d(-lmax*1.1,-lmax*1.1,0.0, xp, yp, ct,st,cp,sp);
00355     lux_draw_string(win, xp, yp, -0.5, "z", 0); 
00356 }
00357 
00358 void draw2d_axis(unsigned long win, float xmin, float xmax,
00359                  float ymin, float ymax, int k)
00360 {
00361     lux_draw_axis(win);
00362 
00363     // X-axis label:
00364             
00365     switch (k) {
00366         case 3: lux_draw_string(win, (xmin+xmax)/2, ymin, -2.2, "x", 0); break;
00367         case 1: lux_draw_string(win, (xmin+xmax)/2, ymin, -2.2, "y", 0); break;
00368         case 2: lux_draw_string(win, (xmin+xmax)/2, ymin, -2.2, "z", 0); break;
00369     }
00370 
00371     // Y-axis label:
00372             
00373     switch (k) {
00374         case 3: lux_draw_vstring(win, xmin, (ymin+ymax)/2,
00375                                  1.2, " y ", 0); break;
00376         case 1: lux_draw_vstring(win, xmin, (ymin+ymax)/2,
00377                                  1.2, " z ", 0); break;
00378         case 2: lux_draw_vstring(win, xmin, (ymin+ymax)/2,
00379                                  1.2, " x ", 0); break;
00380     }
00381 }
00382 
00383 
00384 void update_with_delay(unsigned long win, float t)
00385 {
00386     lux_update_fg(win);
00387     if (t > 0.0)  lux_pause((int)(t*1000000.0));
00388 }
00389 
00390 
00391 static float linespacing = 1.0;
00392 
00393 void show_instructions(unsigned long  win, float r, char* buffer, int update)
00394 {
00395     float statusx, statusy; 
00396     char s[255];
00397     int ptr = 0, len, line = 0;
00398 
00399     lux_clear_window(win);
00400     lux_reconvert_rcoord(win,0,0,&statusx, &statusy);
00401     istrstream ins(buffer,strlen(buffer));
00402     while(ins.get(s,255,'\n')) {
00403         lux_draw_image_string(win, statusx, statusy,
00404                               -(line+1)*linespacing, s, -1);
00405         ins.get(s[0]);  /* Clean "\n" */
00406         line = line+1;
00407     }
00408     if (update) lux_update_fg(win);
00409 }
00410 
00411 void show_instructions(unsigned long win, float r, char* buffer,
00412                        int line, int update)
00413 {
00414     float statusx, statusy; 
00415     char s[255];
00416     int ptr = 0, len;
00417 
00418     lux_reconvert_rcoord(win,0,0,&statusx, &statusy);
00419     istrstream ins(buffer,strlen(buffer));
00420     while(ins.get(s,255,'\n')) {
00421         lux_draw_string(win, statusx, statusy, -(line+1)*linespacing, s, -1);
00422         ins.get(s[0]);  /* Clean "\n" */
00423         line = line+1;
00424     }
00425     if (update) lux_update_fg(win);
00426 }
00427 
00428 void show_main_instructions(unsigned long instr,float r,int d,int u)
00429 {
00430     if (d)
00431         show_instructions(instr, r,
00432 "Running in 3-D mode\n\
00433   d: dialog, R: rotate, i: idle, q: quit\n\
00434   p/P         decrease/increase point size\n\
00435   t           add/remove tracking\n\
00436   n/l         show nodes and/or links\n\
00437   2           enter 2-D mode\n\
00438   x/y/k       2-D and change viewing axis\n\
00439   e           toggle energy color\n\
00440   < > ^ V     rotate left right up down\n\
00441   +/-         change delay time (0: fastest)\n\
00442   z/Z         zoom in or out \n\
00443   arrow/page  shift in x, y, z\n\
00444   h/home      restore origin to (0,0,0)\n\
00445   a           resize to enclose all stars\n\
00446 ",u);
00447 
00448     else
00449 
00450         show_instructions(instr, r,
00451 "Running in 2-D mode\n\
00452   d: dialog, i: idle, q: quit\n\
00453   p/P     decrease/increase point size\n\
00454   t       add/remove tracking\n\
00455   n/l     show nodes and/or links (r: root)\n\
00456   3       enter 3-D mode\n\
00457   x/y/k   change viewing axis\n\
00458   o/O     set origin using mouse\n\
00459   e       toggle energy color\n\
00460   +/-     change delay time (0: fastest)\n\
00461   z/Z     zoom in or out \n\
00462   arrow   shift horizontally/vertically\n\
00463   h/home  restore origin to (0,0,0)\n\
00464   a       resize to enclose all stars\n\
00465 ",u);
00466 }
00467 
00468 local void format_and_show_instructions(unsigned long co, float r,
00469                                         unsigned long *c_i, int index, int tab,
00470                                         char* cstring, int line, int u)
00471 {
00472     if (index > 0) lux_set_color(co, c_i[index]);
00473 
00474     char temp[80], temp1[80];
00475     sprintf(temp, " ");
00476     for (int i = 0; i < tab; i++) strcat(temp, TAB);
00477     sprintf(temp1, "%d - %s", index, cstring);
00478     strcat(temp, temp1);
00479     
00480     show_instructions(co, r, temp, line, u);
00481 }
00482 
00483 void show_color_scheme(unsigned long co, unsigned long *c_e, unsigned long *c_i,
00484                        float r, char ce, bool b_flag, int u)
00485 {
00486     lux_clear_window(co);
00487 
00488     if (ce) {
00489         show_instructions(co, r, "Color by energy:\n",0,u);
00490         lux_set_color(co, c_e[default_color]);
00491         if (b_flag) 
00492             show_instructions(co, r,
00493                               "  White  = default (bound to cluster)\n",1,u);
00494         else 
00495             show_instructions(co, r,
00496                               "  Black  = default (bound to cluster)\n",1,u);
00497         lux_set_color(co, c_e[bound_single]);
00498         show_instructions(co, r, "  Blue   = bound to nearest neighbor\n",2,u);
00499         lux_set_color(co, c_e[bound_binary]);
00500         show_instructions(co, r, "  Green  = bound binary\n",3,u);
00501         lux_set_color(co, c_e[unbound_single]);
00502         show_instructions(co, r, "  Red    = unbound single star\n",4,u);
00503         lux_set_color(co, c_e[unbound_binary]);
00504         show_instructions(co, r, "  Gold   = unbound binary\n",5,u);
00505         lux_set_color(co, c_e[default_color]);
00506 
00507     } else {
00508 
00509         show_instructions(co, r, "Color by index:\n",0,u);
00510         lux_set_color(co, c_i[1]);
00511 
00512         if (b_flag) {
00513             format_and_show_instructions(co, r, c_i,  1, 0, "white",   1, u);
00514             format_and_show_instructions(co, r, c_i,  2, 1, RV_COLOR2, 1, u);
00515             format_and_show_instructions(co, r, c_i,  3, 2, RV_COLOR3, 1, u);
00516             format_and_show_instructions(co, r, c_i,  4, 0, RV_COLOR4, 2, u);
00517             format_and_show_instructions(co, r, c_i,  5, 1, RV_COLOR5, 2, u);
00518             format_and_show_instructions(co, r, c_i,  6, 2, RV_COLOR6, 2, u);
00519             format_and_show_instructions(co, r, c_i,  7, 0, RV_COLOR7, 3, u);
00520             format_and_show_instructions(co, r, c_i,  8, 1, RV_COLOR8, 3, u);
00521             format_and_show_instructions(co, r, c_i,  9, 2, RV_COLOR9, 3, u);
00522             format_and_show_instructions(co, r, c_i, 10, 0, RV_COLORa, 4, u);
00523             format_and_show_instructions(co, r, c_i, 11, 1, RV_COLORb, 4, u);
00524             format_and_show_instructions(co, r, c_i, 12, 2, RV_COLORc, 4, u);
00525             format_and_show_instructions(co, r, c_i, 13, 0, RV_COLORd, 5, u);
00526             format_and_show_instructions(co, r, c_i, 14, 1, RV_COLORe, 5, u);
00527             format_and_show_instructions(co, r, c_i, 15, 2, RV_COLORf, 5, u);
00528             format_and_show_instructions(co, r, c_i, 16, 0, RV_COLORg, 6, u);
00529         } else {
00530             format_and_show_instructions(co, r, c_i,  1, 0, "black",   1, u);
00531             format_and_show_instructions(co, r, c_i,  2, 1, NV_COLOR2, 1, u);
00532             format_and_show_instructions(co, r, c_i,  3, 2, NV_COLOR3, 1, u);
00533             format_and_show_instructions(co, r, c_i,  4, 0, NV_COLOR4, 2, u);
00534             format_and_show_instructions(co, r, c_i,  5, 1, NV_COLOR5, 2, u);
00535             format_and_show_instructions(co, r, c_i,  6, 2, NV_COLOR6, 2, u);
00536             format_and_show_instructions(co, r, c_i,  7, 0, NV_COLOR7, 3, u);
00537             format_and_show_instructions(co, r, c_i,  8, 1, NV_COLOR8, 3, u);
00538             format_and_show_instructions(co, r, c_i,  9, 2, NV_COLOR9, 3, u);
00539             format_and_show_instructions(co, r, c_i, 10, 0, NV_COLORa, 4, u);
00540             format_and_show_instructions(co, r, c_i, 11, 1, NV_COLORb, 4, u);
00541             format_and_show_instructions(co, r, c_i, 12, 2, NV_COLORc, 4, u);
00542             format_and_show_instructions(co, r, c_i, 13, 0, NV_COLORd, 5, u);
00543             format_and_show_instructions(co, r, c_i, 14, 1, NV_COLORe, 5, u);
00544             format_and_show_instructions(co, r, c_i, 15, 2, NV_COLORf, 5, u);
00545             format_and_show_instructions(co, r, c_i, 16, 0, NV_COLORg, 6, u);
00546         }
00547         lux_set_color(co, c_i[default_color]);
00548     }
00549 }
00550 
00551 void init_colors(unsigned long win, unsigned long *ce, unsigned long *ci,
00552                  bool b_flag)
00553 {
00554     if (b_flag) {
00555 
00556         // Reverse video color scheme
00557 
00558         // Color by energy:
00559 
00560         ce[background_color] = ci[background_color]
00561             = lux_rgb_pixel(win, 0.0,0.0,0.0);                  // white
00562         ce[default_color] = ci[default_color]
00563             = lux_rgb_pixel(win, 1.0,1.0,1.0);                  // black
00564     
00565         ce[bound_single] = lux_lookup_color(win, "deepskyblue");
00566         ce[bound_binary] = lux_lookup_color(win, "green");
00567         ce[unbound_single] = lux_lookup_color(win, "red");
00568         ce[unbound_binary] = lux_lookup_color(win, "goldenrod");
00569 
00570         // Color by index:
00571 
00572         ci[2]  = lux_lookup_color(win, RV_COLOR2);
00573         ci[3]  = lux_lookup_color(win, RV_COLOR3);
00574         ci[4]  = lux_lookup_color(win, RV_COLOR4);
00575         ci[5]  = lux_lookup_color(win, RV_COLOR5);
00576         ci[6]  = lux_lookup_color(win, RV_COLOR6);
00577         ci[7]  = lux_lookup_color(win, RV_COLOR7);
00578         ci[8]  = lux_lookup_color(win, RV_COLOR8);
00579         ci[9]  = lux_lookup_color(win, RV_COLOR9);
00580         ci[10] = lux_lookup_color(win, RV_COLORa);
00581         ci[11] = lux_lookup_color(win, RV_COLORb);
00582         ci[12] = lux_lookup_color(win, RV_COLORc);
00583         ci[13] = lux_lookup_color(win, RV_COLORd);
00584         ci[14] = lux_lookup_color(win, RV_COLORe);
00585         ci[15] = lux_lookup_color(win, RV_COLORf);
00586         ci[16] = lux_lookup_color(win, RV_COLORg);
00587     
00588     } else {
00589 
00590         // Color by energy:
00591 
00592         ce[background_color] = ci[background_color]
00593             = lux_rgb_pixel(win, 1.0,1.0,1.0);                  // white
00594         ce[default_color] = ci[default_color]
00595             = lux_rgb_pixel(win, 0.0,0.0,0.0);                  // black
00596     
00597         ce[bound_single] = lux_lookup_color(win, "blue");
00598         ce[bound_binary] = lux_lookup_color(win, "limegreen");
00599         ce[unbound_single] = lux_lookup_color(win, "red");
00600         ce[unbound_binary] = lux_lookup_color(win, "goldenrod");
00601 
00602         // Color by index:
00603     
00604         ci[2] = lux_lookup_color(win, NV_COLOR2);
00605         ci[3] = lux_lookup_color(win, NV_COLOR3);
00606         ci[4] = lux_lookup_color(win, NV_COLOR4);
00607         ci[5] = lux_lookup_color(win, NV_COLOR5);
00608         ci[6] = lux_lookup_color(win, NV_COLOR6);
00609         ci[7] = lux_lookup_color(win, NV_COLOR7);
00610         ci[8] = lux_lookup_color(win, NV_COLOR8);
00611         ci[9]  = lux_lookup_color(win, NV_COLOR9);
00612         ci[10] = lux_lookup_color(win, NV_COLORa);
00613         ci[11] = lux_lookup_color(win, NV_COLORb);
00614         ci[12] = lux_lookup_color(win, NV_COLORc);
00615         ci[13] = lux_lookup_color(win, NV_COLORd);
00616         ci[14] = lux_lookup_color(win, NV_COLORe);
00617         ci[15] = lux_lookup_color(win, NV_COLORf);
00618         ci[16] = lux_lookup_color(win, NV_COLORg);
00619     
00620     }
00621 }
00622 
00623 void set_limits(float* origin, float lmax3d,
00624                 int kx, float& xmin, float& xmax,
00625                 int ky, float& ymin, float& ymax)
00626 {
00627     xmin = origin[kx] - lmax3d;
00628     xmax = origin[kx] + lmax3d;
00629     ymin = origin[ky] - lmax3d;
00630     ymax = origin[ky] + lmax3d;
00631 }
00632 
00633 local int nearest_index(dyn* b, float r, float s, int kx, int ky)
00634 {
00635     real r2_min = VERY_LARGE_NUMBER;
00636     int index = -1;
00637     for_all_leaves(dyn, b, bb) {
00638         real dx = bb->get_pos()[kx] - r;
00639         real dy = bb->get_pos()[ky] - s;
00640         real r2 = dx*dx + dy*dy;
00641         if (r2 < r2_min) {
00642             r2_min = r2;
00643             index = bb->get_index();
00644         }
00645     }
00646     return index;
00647 }
00648 
00649 local int count_nodes(dyn* b)
00650 // Return the total number of nodes BELOW the node b.
00651 {
00652     if(b->get_oldest_daughter() == NULL)
00653         return 0;
00654     else {
00655         int  n = 0;
00656         for (dyn* daughter = b->get_oldest_daughter();
00657              daughter != NULL; daughter = daughter->get_younger_sister())
00658             n += 1 + count_nodes(daughter);
00659         return n;
00660     }
00661 }
00662 
00663 //-------------------------------------------------------------------------
00664 
00665 // These shouldn't really be global, but keep them this way for now...
00666 
00667 static int kx = 1, ky = 2; 
00668 
00669 static unsigned long  win, dia, instr, colwin;
00670 static int    status = 0;
00671 
00672 static float  xmin, xmax, ymin, ymax, point_size, lmax3d, origin[3];
00673 
00674 // The plotting box is determined completely by origin and lmax3d.
00675 // Its projection onto the viewing plane is xmin, xmax, ymin, ymax
00676 
00677 static float  theta = 0.33, costheta = cos(0.33), sintheta = sin(0.33);
00678 static float  dtheta = 0.03;
00679 static float  phi = 0.33, cosphi = cos(0.33), sinphi = sin(0.33);
00680 static int    graph3d = 1;
00681 static int    nodes = 0, links = 0, root = 0;
00682 static char   track = 0, cenergy = 0;
00683 static char   c = 0;
00684 static char   rotate = 0;
00685 static float  delay_time;
00686 static unsigned long c_energy[10], c_index[N_COLORS+1];
00687 
00688 static real local_offset[3];
00689 static int  origin_star;
00690 
00691 //-------------------------------------------------------------------------
00692 
00693 local void convert_relative_to_absolute(dyn* b)
00694 {
00695     if (b->get_parent()) b->inc_pos(b->get_parent()->get_pos());
00696     for_all_daughters(dyn, b, bb) convert_relative_to_absolute(bb);
00697 }
00698 
00699 local void draw_star_point(unsigned long win, float r, float s,
00700                            float point_size, bool f_flag)
00701 
00702 // Plot a point of size point_size at (r,s), filled or unfilled
00703 // according to the value of f_flag.
00704 
00705 {
00706     if (f_flag)
00707         lux_fill_arcf(win, r-point_size/2, s-point_size/2,
00708                       point_size, point_size, 0.0, 360.0);
00709     else
00710         lux_draw_arcf(win, r-point_size/2, s-point_size/2, 
00711                       point_size,point_size, 0.0, 360.0);
00712 }
00713 
00714 local float interp_to_x(float r, float s, float rr, float ss, float x)
00715 {
00716     return s + (ss - s) * (x - r) / (rr - r);
00717 }
00718 
00719 local float interp_to_y(float r, float s, float rr, float ss, float y)
00720 {
00721     return r + (rr - r) * (y - s) / (ss - s);
00722 }
00723 
00724 local void draw_links_2d(dyn* b, float r, float s)
00725 {
00726     for_all_daughters(dyn, b, bb) {
00727 
00728         float rr = bb->get_pos()[kx]-local_offset[kx];
00729         float ss = bb->get_pos()[ky]-local_offset[ky];
00730         float stemp;
00731 
00732         // Deal with the 9 possible locations of (rr,ss) with respect
00733         // to the box defined by xmin, xmax, ymin, and ymax.
00734 
00735         if (rr < xmin) {
00736 
00737             if (ss < ymin) {
00738                 float stemp = interp_to_x(r, s, rr, ss, xmin);
00739                 if (stemp >= ymin)
00740                     rr = xmin, ss = stemp;
00741                 else
00742                     rr = interp_to_y(r, s, rr, ss, ymin), ss = ymin;
00743             } else if (ss > ymax) {
00744                 if ((stemp = interp_to_x(r, s, rr, ss, xmin)) <= ymax)
00745                     rr = xmin, ss = stemp;
00746                 else
00747                     rr = interp_to_y(r, s, rr, ss, ymax), ss = ymax;
00748             } else
00749                 ss = interp_to_x(r, s, rr, ss, xmin), rr = xmin;
00750 
00751         } else if (rr > xmax) {
00752 
00753             if (ss < ymin) {
00754                 if ((stemp = interp_to_x(r, s, rr, ss, xmax)) >= ymin)
00755                     rr = xmax, ss = stemp;
00756                 else
00757                     rr = interp_to_y(r, s, rr, ss, ymin), ss = ymin;
00758             } else if (ss > ymax) {
00759                 if ((stemp = interp_to_x(r, s, rr, ss, xmax)) <= ymax)
00760                     rr = xmax, ss = stemp;
00761                 else
00762                     rr = interp_to_y(r, s, rr, ss, ymax), ss = ymax;
00763             } else
00764                 ss = interp_to_x(r, s, rr, ss, xmax), rr = xmax;
00765 
00766         } else {
00767 
00768             if (ss < ymin)
00769                 rr = interp_to_y(r, s, rr, ss, ymin), ss = ymin;
00770             else if (ss > ymax)
00771                 rr = interp_to_y(r, s, rr, ss, ymax), ss = ymax;
00772 
00773         }
00774         lux_draw_linef(win, r, s, rr, ss);
00775     }
00776 }                                          
00777 local void draw_links_3d(dyn* b, float r, float s)
00778 {
00779     for_all_daughters(dyn, b, bb) {
00780 
00781         float X = (float)bb->get_pos()[0] - local_offset[0] - origin[0];
00782         float Y = (float)bb->get_pos()[1] - local_offset[1] - origin[1];
00783         float Z = (float)bb->get_pos()[2] - local_offset[2] - origin[2];
00784 
00785         // Don't attempt to deal with the 27 possible locations
00786         // of (X, Y, Z) with respect to the box!
00787 
00788         float rr, ss;
00789         project3d(X, Y, Z, rr, ss, costheta, sintheta, cosphi, sinphi);
00790         lux_draw_linef(win, r, s, rr, ss);
00791     }
00792 }                                          
00793 
00794 local int xplot_stars(dyn* b, int k, int f_flag)
00795 {
00796     int  n_stars = b->n_leaves();
00797     int  n_nodes = count_nodes(b);
00798     float r, s;
00799 
00800     if (graph3d) {
00801 
00802         for_all_nodes(dyn, b, bi) if (root || bi->get_parent()) {
00803             if (nodes || (bi->get_oldest_daughter() == NULL)) {
00804                 
00805                 float X = (float)bi->get_pos()[0] - local_offset[0] - origin[0];
00806                 float Y = (float)bi->get_pos()[1] - local_offset[1] - origin[1];
00807                 float Z = (float)bi->get_pos()[2] - local_offset[2] - origin[2];
00808 
00809                 if ( (X > (-lmax3d+point_size)) && (X < (lmax3d-point_size)) 
00810                     && (Y > (-lmax3d+point_size)) && (Y < (lmax3d-point_size)) 
00811                     && (Z > (-lmax3d+point_size)) && (Z < (lmax3d-point_size))){
00812 
00813                     // Should really sort by depth here...
00814 
00815                     project3d(X, Y, Z, r, s, costheta, sintheta,
00816                               cosphi, sinphi);
00817 
00818                     // Determine the color to use.
00819 
00820                     bool temp_flag = f_flag;
00821                     if (bi->get_oldest_daughter()) {
00822                         lux_set_color(win, lux_lookup_color(win, "grey"));
00823                         temp_flag =  1 - f_flag;
00824                     } else {
00825                         if (cenergy) { 
00826                             compute_energies(b, bi, c);
00827                             lux_set_color(win,c_energy[c]);
00828                         } else if (bi->get_index() > 0) {
00829 
00830                             // Wrap the color map.
00831 
00832                             int ii = bi->get_index();
00833                             while (ii > N_COLORS) ii -= N_COLORS;
00834 
00835                             lux_set_color(win,c_index[ii]);
00836                         }
00837                     }
00838                     
00839                     if (track) 
00840                         lux_draw_pointf(win, r, s);
00841                     else
00842                         draw_star_point(win, r, s, point_size, f_flag);
00843 
00844                     if (links && bi->get_oldest_daughter())
00845                         draw_links_3d(bi, r, s);
00846                 }
00847             }
00848         }
00849 
00850     } else {
00851 
00852         // Make a list of nodes, *including* the root node if root = 1.
00853         // Root will be at the start of the list if it is being displayed.
00854 
00855         dynptr* p = new dynptr[n_nodes+root];
00856 
00857         int ip = 0;
00858         for_all_nodes(dyn, b, bi) if (root || bi != b) p[ip++] = bi;
00859         if (ip != n_nodes+root) {
00860             cerr << "xplot_stars: n_nodes = " << n_nodes+root
00861                 << " counted " << ip << endl;
00862             exit(1);
00863         }
00864 
00865         // Sort by k (note that k = 1, 2, or 3 for x, y, or z):
00866 
00867         for (ip = 0; ip < n_nodes+root; ip++)
00868             for (int jp = ip+1; jp < n_nodes+root; jp++)
00869                 if (p[jp]->get_pos()[k-1] < p[ip]->get_pos()[k-1]) {
00870                     dynptr bb = p[jp];
00871                     p[jp] = p[ip];
00872                     p[ip] = bb;
00873                 }
00874 
00875         // Plot ordered by depth.
00876 
00877         for (ip = 0; ip < n_nodes+root; ip++) {
00878             dyn* bi = p[ip];
00879             if ( (root || bi != b)
00880                 && (nodes || bi->get_oldest_daughter() == NULL)) {
00881 
00882                 r = (float)bi->get_pos()[kx] - local_offset[kx];
00883                 s = (float)bi->get_pos()[ky] - local_offset[ky];
00884 
00885                 if ( (r > (xmin+point_size)) && (r < (xmax-point_size)) 
00886                     && (s > (ymin+point_size)) && (s < (ymax-point_size)) ) {
00887 
00888                     // Determine the color to use.
00889 
00890                     bool temp_flag = f_flag;
00891                     if (bi->get_oldest_daughter()) {
00892                         lux_set_color(win, lux_lookup_color(win, "grey"));
00893                         temp_flag =  1 - f_flag;
00894                     } else {
00895                         if (cenergy) { 
00896                             compute_energies(b, bi, c);
00897                             lux_set_color(win, c_energy[c]);
00898                         } else if (bi->get_index() > 0) {
00899 
00900                             // Wrap the color map.
00901 
00902                             int ii = bi->get_index();
00903                             while (ii > N_COLORS) ii -= N_COLORS;
00904 
00905                             lux_set_color(win,c_index[ii]);
00906                         }
00907                     }
00908 
00909                     if (track) 
00910                         lux_draw_pointf(win, r, s);
00911                     else
00912                         draw_star_point(win, r, s, point_size, temp_flag);
00913 
00914                     if (links && bi->get_oldest_daughter())
00915                         draw_links_2d(bi, r, s);
00916                 }
00917             }
00918         }
00919         delete p;
00920     }
00921     return n_stars;
00922 }
00923 
00924 //-------------------------------------------------------------------------
00925 
00926 // Convenient scaling macro:
00927 
00928 #define _R_(i)  ((int)( ((float)i)*r_factor + 0.5 ))
00929 
00930 /*-----------------------------------------------------------------------------
00931  *  xstarplot.C  --  project the positions of all particles onto the screen
00932  *                   input:   pn: a pointer to a nbody system,
00933  *                              k: the number of the coordinate axis along which
00934  *                                 the projection is directed, with {k,x,y}
00935  *                                 having a right-handed orientation,
00936  *                           xmax: displayed x-axis spans [-xmax, xmax]
00937  *                           ymax: displayed y-axis spans [-ymax, ymax]
00938  *-----------------------------------------------------------------------------
00939  */
00940 
00941 void  xstarplot(dyn* b, float r_factor, int& k, int d, float lmax,
00942                 float size, float D, int ce,
00943                 bool b_flag, bool f_flag, bool t_flag,
00944                 int init_flag)
00945 {
00946     int xorigin, yorigin;
00947     static int win_size;
00948     float r, s;
00949 
00950     if (init_flag == 0) {
00951 
00952         // Open windows for plot and instructions.
00953 
00954         if (t_flag) nodes = links = 1;
00955 
00956         if (!status) {
00957 
00958             // Sort of a kludge to try to get the font size right...
00959             // Note that the same font is used everywhere.
00960 
00961             if (r_factor >= 1.0) {
00962                 set_default_font("9x15");
00963                 linespacing = 1.2;
00964             } else if (r_factor >= 0.8) {
00965                 set_default_font("7x13");
00966                 if (r_factor >= 0.9)
00967                     linespacing = 1.15;
00968                 else
00969                     linespacing = 1.1;
00970             } else if (r_factor >= 0.65) {
00971                 set_default_font("6x12");
00972                 if (r_factor >= 0.725)
00973                     linespacing = 1.05;
00974                 else
00975                     linespacing = 1.0;
00976             } else if (r_factor >= 0.5) {
00977                 set_default_font("6x10");
00978                 if (r_factor >= 0.575)
00979                     linespacing = 1.05;
00980                 else
00981                     linespacing = 1.0;
00982             } else if (r_factor >= 0.4) {
00983                 set_default_font("6x9");
00984                 linespacing = 1.0;
00985             } else {
00986                 set_default_font("5x8");
00987                 linespacing = 1.0;
00988             }
00989 
00990             // twm title bar is ~27-30 pixels (independent of scaling), but
00991             // the bar doesn't count in the location of the window!
00992             // Mac windows need more space (frame at bottom too).
00993             // Assume that scale factors less than 0.75 mean we are
00994             // using a Mac display.  For r_factor > 1.1, move the 
00995             // "colwin" box up and over.
00996 
00997             int title = 27;
00998             int bottom = 0;
00999             if (r_factor < 0.75) {
01000                 title = 20;
01001                 bottom = 20;
01002             }
01003 
01004             xorigin = 0;
01005             yorigin = 0;
01006             int xsize = _R_(400);
01007             int ysize = _R_(400);
01008             win = lux_openwin(xorigin, yorigin, xsize, ysize);
01009             lux_set_window_name(win, "Starlab");
01010 
01011             win_size = xsize;
01012 
01013             // ???
01014 
01015             if (r_factor <= 1) 
01016                 yorigin += ysize + title + bottom;
01017             else
01018                 yorigin += ysize + 2*title + bottom;
01019 
01020             ysize = _R_(260);
01021             instr = lux_openwin(xorigin, yorigin, xsize, ysize);
01022             lux_set_window_name(instr, "Status & Commands");
01023 
01024             if (r_factor <= 1.1) {
01025                 yorigin += ysize + title + bottom;
01026             } else {
01027                 int edge = 3;
01028                 xorigin += xsize + edge;
01029                 yorigin = 0;
01030             }
01031             ysize = _R_(140);
01032             colwin = lux_openwin(xorigin, yorigin, xsize, ysize);
01033             lux_set_window_name(colwin, "Color Scheme");
01034 
01035             init_colors(win, c_energy, c_index, b_flag);
01036 
01037             lux_set_noupdate(win);
01038             lux_set_bgcolor(win,c_energy[background_color]);
01039             lux_set_window_bgcolor(win,c_energy[background_color]);
01040             lux_set_color(win,c_energy[default_color]);
01041 
01042             lux_set_noupdate(colwin);
01043             lux_set_bgcolor(colwin,c_energy[background_color]);
01044             lux_set_window_bgcolor(colwin,c_energy[background_color]);
01045             lux_set_color(colwin,c_energy[default_color]);
01046 
01047             lux_set_noupdate(instr);
01048             lux_set_bgcolor(instr,c_energy[background_color]);
01049             lux_set_window_bgcolor(instr,c_energy[background_color]);
01050             lux_set_color(instr,c_energy[default_color]);
01051 
01052             lux_setup_region(win, 1.0, 1.0, 8.0, 8.0);
01053 
01054             if (r_factor <= 1.1) {
01055                 int edge = 3;
01056                 xorigin += xsize + edge;
01057                 yorigin = 0;
01058             } else
01059                 yorigin += ysize + title + bottom;
01060         }
01061 
01062         lux_clear_window(win);
01063         lux_update_fg(win);
01064         lux_clear_window(colwin);
01065         lux_update_fg(colwin);
01066         lux_clear_window(instr);
01067         lux_update_fg(instr);
01068 
01069         // Determine axes to plot:
01070 
01071         switch (k) {
01072             case 1:     kx = 1; ky = 2; graph3d = 0; break;
01073             case 2:     kx = 2; ky = 0; graph3d = 0; break;
01074             case 3:     kx = 0; ky = 1; graph3d = 0; break;
01075             default:    cerr << "xstarplot: k = " << k
01076                              << ": illegal value; choose from {1, 2, 3}"
01077                              << endl;
01078                         exit(0);
01079         }
01080 
01081         switch(d) {
01082             case 2:     graph3d = 0;  break;
01083             case 3:     graph3d = 1;  break;
01084             default:    cerr << "xstarplot: d = " << d
01085                              << " illegal value; choose from {2, 3)"
01086                              << endl;
01087                         exit(0);
01088         }
01089 
01090         cenergy = ce?1:0;
01091         show_color_scheme(colwin, c_energy, c_index,
01092                           r_factor, cenergy, b_flag,1);
01093 
01094         delay_time = D;
01095 
01096         if (lmax > 0.0)
01097 
01098             lmax3d = lmax;
01099 
01100         else {
01101 
01102             lmax3d = 0;
01103 
01104             // Use all dimensions in determining the initial scale!
01105 
01106             for_all_leaves(dyn, b, bi)
01107                 for (int kk = 0; kk < 3; kk++)
01108                     lmax3d = max(lmax3d, abs(bi->get_pos()[kk]));
01109 
01110             // Round lmax3d up to something reasonable:
01111 
01112             lmax3d *= 1.2;
01113             if (lmax3d <= 0) lmax3d = 1;
01114 
01115             real m_log = log10(lmax3d);
01116             int i_log = (int) m_log;
01117             if (m_log - i_log > 0.699) i_log++;
01118             real scale = pow(10.0, i_log);
01119             lmax3d = ((int) (lmax3d/scale) + 1) * scale;
01120         }
01121 
01122         for (int ko = 0; ko < 3; ko++) origin[ko] = 0;
01123 
01124         set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01125 
01126         point_size = lmax3d/30.0;
01127         if (size > 0.0) point_size *= size;
01128         
01129         if (graph3d) {
01130             lux_setup_axis(win, -FAC3D*lmax3d, FAC3D*lmax3d, 
01131                            -FAC3D*lmax3d, FAC3D*lmax3d);      
01132             draw3d_axis(win, lmax3d, costheta, sintheta, cosphi, sinphi);
01133         } else {
01134             lux_setup_axis(win, xmin, xmax, ymin, ymax);
01135             draw2d_axis(win, xmin, xmax, ymin, ymax, k);
01136         }
01137 
01138         if (!status) {
01139 
01140             int i = 0;
01141 //          cout << "setting dialog...\n";
01142 
01143             // Initialize dialog stuff (note: y is measured up from bottom!)
01144 
01145             real save = r_factor;
01146             if (r_factor > 1) r_factor = 1;
01147             dia = lux_open_dialog(xorigin, yorigin, _R_(512), _R_(550));
01148 
01149 //          cout << i++ << endl;
01150             // 3-D origin:
01151 
01152             lux_set_item(dia, Origin, TEXT_WINDOW, NO_TYPE,
01153                          _R_(70), _R_(500), 6, "origin");
01154 
01155 //          cout << i++ << endl;
01156             sprintf(temp_buffer, "%f", origin[0]);
01157             lux_set_item(dia, Xorigin, INPUT_WINDOW, NO_TYPE,
01158                          _R_(160), _R_(500), 10, temp_buffer);
01159 //          cout << i++ << endl;
01160             sprintf(temp_buffer, "%f", origin[1]);
01161             lux_set_item(dia, Yorigin, INPUT_WINDOW, NO_TYPE,
01162                          _R_(280), _R_(500), 10, temp_buffer);
01163 //          cout << i++ << endl;
01164             sprintf(temp_buffer, "%f", origin[2]);
01165             lux_set_item(dia, Zorigin, INPUT_WINDOW, NO_TYPE,
01166                          _R_(400), _R_(500), 10, temp_buffer);
01167 
01168 //          exit(1);
01169 //          cout << i++ << endl;
01170             // Minima and maxima of 2-D display:
01171 
01172             lux_set_item(dia, xminimum, TEXT_WINDOW, NO_TYPE,
01173                          _R_(70), _R_(460), 4, "xmin");
01174             lux_set_item(dia, xmaximum, TEXT_WINDOW, NO_TYPE,
01175                          _R_(70), _R_(420), 4, "xmax");
01176             lux_set_item(dia, yminimum, TEXT_WINDOW, NO_TYPE,
01177                          _R_(70), _R_(380), 4, "ymin");
01178             lux_set_item(dia, yminimum, TEXT_WINDOW, NO_TYPE,
01179                          _R_(70), _R_(340), 4, "ymax");
01180 
01181             sprintf(temp_buffer, "%f", xmin);
01182             lux_set_item(dia, xminimum, INPUT_WINDOW, NO_TYPE,
01183                          _R_(160), _R_(460), 10, temp_buffer);
01184             sprintf(temp_buffer, "%f", xmax);
01185             lux_set_item(dia, xmaximum, INPUT_WINDOW, NO_TYPE,
01186                          _R_(160), _R_(420), 10, temp_buffer);
01187             sprintf(temp_buffer, "%f", ymin);
01188             lux_set_item(dia, yminimum, INPUT_WINDOW, NO_TYPE,
01189                          _R_(160), _R_(380), 10, temp_buffer);
01190             sprintf(temp_buffer, "%f", ymax);
01191             lux_set_item(dia, ymaximum, INPUT_WINDOW, NO_TYPE,
01192                          _R_(160), _R_(340), 10, temp_buffer);
01193 
01194 //          cout << i++ << endl;
01195             // 3-D cube size:
01196 
01197             lux_set_item(dia, lmax3D, TEXT_WINDOW, NO_TYPE,
01198                          _R_(70), _R_(300), 10, "cube size");
01199             sprintf(temp_buffer, "%f", 2*lmax3d);
01200             lux_set_item(dia, lmax3D, INPUT_WINDOW, NO_TYPE,
01201                          _R_(180), _R_(300), 10, temp_buffer);
01202 
01203 //          cout << i++ << endl;
01204             // 3-D projection direction:
01205 
01206             lux_set_item(dia, theta3D, TEXT_WINDOW, NO_TYPE,
01207                          _R_(70), _R_(260), 10, "theta");
01208             sprintf(temp_buffer, "%f", theta);
01209             lux_set_item(dia, theta3D, INPUT_WINDOW, NO_TYPE,
01210                          _R_(180), _R_(260), 10, temp_buffer);
01211             lux_set_item(dia, phi3D, TEXT_WINDOW, NO_TYPE,
01212                          _R_(70), _R_(220), 10, "phi");
01213             sprintf(temp_buffer, "%f", phi);
01214             lux_set_item(dia, phi3D, INPUT_WINDOW, NO_TYPE,
01215                          _R_(180), _R_(220), 10, temp_buffer);
01216             lux_set_item(dia, dtheta3D, TEXT_WINDOW, NO_TYPE,
01217                          _R_(70), _R_(180), 10, "dtheta");
01218             sprintf(temp_buffer, "%f", dtheta);
01219             lux_set_item(dia, dtheta3D, INPUT_WINDOW, NO_TYPE,
01220                          _R_(180), _R_(180), 10, temp_buffer);
01221 
01222 //          cout << i++ << endl;
01223             // Point size:
01224 
01225             lux_set_item(dia, pointsize, TEXT_WINDOW, NO_TYPE,
01226                          _R_(70), _R_(140), 10, "point size");
01227             sprintf(temp_buffer, "%f", point_size);
01228             lux_set_item(dia, pointsize, INPUT_WINDOW, NO_TYPE,
01229                          _R_(180), _R_(140), 10, temp_buffer);
01230 
01231 //          cout << i++ << endl;
01232             // Delay time:
01233 
01234             lux_set_item(dia, DelayTime, TEXT_WINDOW, NO_TYPE,
01235                          _R_(70), _R_(100), 10, "delay time");
01236             sprintf(temp_buffer, "%f", delay_time);
01237             lux_set_item(dia, DelayTime, INPUT_WINDOW, NO_TYPE,
01238                          _R_(180), _R_(100), 10, temp_buffer);
01239 
01240 //          cout << i++ << endl;
01241             // 2-D view axis:
01242 
01243             sprintf(temp_buffer, " %d ", k);
01244             lux_set_item(dia, view2D, INPUT_WINDOW, NO_TYPE,
01245                          _R_(320), _R_(460), 3, temp_buffer);
01246             lux_set_item(dia, View2D, TEXT_WINDOW, NO_TYPE,
01247                          _R_(360), _R_(460), 8, "2-D view axis");
01248 
01249 //          cout << i++ << endl;
01250             // Energy/tracking/3D selection boxes:
01251 
01252             temp_buffer[0] = cenergy;
01253             lux_set_item(dia, colorenergy, BUTTON_WINDOW, CHECK_BUTTON,
01254                          _R_(320), _R_(420), 1, temp_buffer);
01255             temp_buffer[0] = track;
01256             lux_set_item(dia, tracking, BUTTON_WINDOW, CHECK_BUTTON,
01257                          _R_(320), _R_(380), 1, temp_buffer);
01258             temp_buffer[0] = graph3d;
01259             lux_set_item(dia, graph3dim, BUTTON_WINDOW, CHECK_BUTTON,
01260                          _R_(320), _R_(340), 1, temp_buffer);
01261 
01262             lux_set_item(dia, colorenergy, TEXT_WINDOW, CHECK_BUTTON,
01263                          _R_(350), _R_(420), 11, "color by energy");
01264             lux_set_item(dia, tracking, TEXT_WINDOW, CHECK_BUTTON,
01265                          _R_(350), _R_(380), 14, "track particle");
01266             lux_set_item(dia, graph3dim, TEXT_WINDOW, CHECK_BUTTON,
01267                          _R_(350), _R_(340), 8, "3-D graph");
01268 
01269 //          cout << i++ << endl;
01270             // Origin star:
01271 
01272             sprintf(temp_buffer, " %d ", 0);
01273             lux_set_item(dia, originstar, INPUT_WINDOW, NO_TYPE,
01274                          _R_(320), _R_(300), 3, temp_buffer);
01275             lux_set_item(dia, OriginStar, TEXT_WINDOW, NO_TYPE,
01276                          _R_(360), _R_(300), 8, "Origin Star");
01277 
01278 //          lux_draw_palette(dia);
01279 
01280             status = 1;
01281 
01282 //          cout << i++ << endl;
01283             // OK/cancel:
01284 
01285             lux_set_item(dia, ok, BUTTON_WINDOW, OK_BUTTON,
01286                          _R_(100), _R_(25), 9, "OK, CLEAR");
01287             lux_set_item(dia, ok_keep, BUTTON_WINDOW, OK_KEEP_BUTTON,
01288                          _R_(250), _R_(25), 8, "OK, KEEP");
01289             lux_set_item(dia, cancel, BUTTON_WINDOW, CANCEL_BUTTON,
01290                          _R_(400), _R_(25), 6, "CANCEL");
01291 
01292             r_factor = save;
01293 
01294         } else ;  // Here we should update the all the values for dialog
01295             
01296     } else if (init_flag < 0) {
01297         show_instructions(instr, r_factor,
01298                   "End of Data.  Idle now\n  r: replay, (c,q): quit", 1);
01299         lux_getevent();
01300         exit(0);
01301     }
01302 
01303 //    lux_getevent();
01304 //    exit(1);
01305     
01306 
01307 //----------------------------------------------------------------------------//
01308 
01309     // End of initialization.  Start by redrawing axes and instructions(?)
01310 
01311     if (!track) {
01312         lux_clear_current_region(win);
01313         if (graph3d) draw3d_axis(win, lmax3d, costheta, sintheta,
01314                                  cosphi, sinphi);
01315     }
01316 
01317     show_main_instructions(instr, r_factor, graph3d, 1);
01318 
01319 //----------------------------------------------------------------------------//
01320 
01321     // Always express all positions and velocities relative to the root node.
01322     // (There is no requirement that the root node be at rest at the origin...)
01323 
01324     {
01325         vector root_pos = b->get_pos();
01326         vector root_vel = b->get_vel();
01327         for_all_nodes(dyn, b, bi) {
01328             bi->inc_pos(-root_pos);
01329             bi->inc_vel(-root_vel);
01330         }
01331     }
01332 
01333     // Determine local offset, if any.
01334 
01335     if (origin_star > 0) {
01336         for_all_leaves(dyn, b, bi)
01337             if (bi->get_index() == origin_star) {
01338                 for (int kk = 0; kk < 3; kk++)
01339                     local_offset[kk] = bi->get_pos()[kk];
01340                 break;
01341             }
01342     } else
01343         for (int kk = 0; kk < 3; kk++) local_offset[kk] = 0;
01344 
01345     // Plot the data points (sorted by k-component in the 2D case):
01346 
01347     int n_stars = xplot_stars(b, k, f_flag);
01348 
01349 //----------------------------------------------------------------------------//
01350 
01351     // Headers, etc.
01352 
01353     lux_set_color(win,c_energy[default_color]);
01354 
01355     // Other labels:
01356 
01357     if (graph3d) {
01358         sprintf(temp_buffer, "N = %d (snapshot #%5d) max=%5.3f",
01359                 n_stars, init_flag + 1, lmax3d);
01360         lux_draw_image_string(win, 0.0, lmax3d*FAC3D, 0.5, temp_buffer, 0);
01361     } else {
01362         sprintf(temp_buffer, "N = %d  (snapshot #%5d)", n_stars, init_flag + 1);
01363         lux_draw_image_string(win, (xmin+xmax)/2.0, ymax, 0.5, temp_buffer, 0);
01364     }
01365     update_with_delay(win, delay_time);
01366 
01367 //----------------------------------------------------------------------------//
01368 
01369     // Loop through the input temp_buffer until no more events remain.
01370     // lux_next_keypress gets and discards the next key in the input stream.
01371 
01372     char key, string[20], shift, control;
01373     while (lux_next_keypress(win, &key, string, &shift, &control)) {
01374 
01375         // A "defined" key has been pressed.  See if it is one we want.
01376 
01377         if (key == 0                    // key = 0 for non-ASCII character
01378                                         // e.g. Up, Down, Home, etc.--see win.c
01379             || key == 'h'
01380             || key == 'a') {
01381 
01382             // "Shift" functions:
01383 
01384             int change = 0;
01385 
01386             if (key == 'h')             // Keyboard lookalikes for
01387                 change = 4;             // function keys.
01388             else if (key == 'a')
01389                 change = 5;
01390 
01391             else if (strcmp(string, "Up") == 0) {
01392                 change = ky + 1;
01393                 origin[ky] += lmax3d/2;
01394             } else if (strcmp(string, "Down") == 0) {
01395                 change = ky + 1;
01396                 origin[ky] -= lmax3d/2;
01397             } else if (strcmp(string, "Right") == 0) {
01398                 change = kx + 1;
01399                 origin[kx] += lmax3d/2;
01400             } else if (strcmp(string, "Left") == 0) {
01401                 change = kx + 1;
01402                 origin[kx] -= lmax3d/2;
01403             } else if (strcmp(string, "PgUp") == 0) {
01404                 change = k;
01405                 origin[k-1] += lmax3d/2;
01406             } else if (strcmp(string, "PgDn") == 0) {
01407                 change = k;
01408                 origin[k-1] -= lmax3d/2;
01409             } else if (strcmp(string, "Home") == 0)
01410                 change = 4;
01411             else if (strcmp(string, "R11") == 0)
01412                 change = 5;
01413 
01414             if (change) {
01415 
01416                 if (change == 4) {
01417                     origin[kx] = origin[ky] = origin[k-1] = 0;
01418                 } else if (change == 5) {
01419                     lmax3d = 0;
01420 
01421                     // Use all dimensions in redetermining the scale!
01422 
01423                     for_all_leaves(dyn, b, bi)
01424                         for (int kk = 0; kk < 3; kk++)
01425                             lmax3d = max(lmax3d, abs(bi->get_pos()[kk]
01426                                                      - local_offset[kk]));
01427                 
01428                     // Round lmax3d up to something reasonable:
01429                 
01430                     lmax3d *= 1.2;
01431                     if (lmax3d <= 0) lmax3d = 1;
01432                 
01433                     real m_log = log10(lmax3d);
01434                     int i_log = (int) m_log;
01435                     if (m_log - i_log > 0.699) i_log++;
01436                     real scale = pow(10.0, i_log);
01437                     lmax3d = ((int) (lmax3d/scale) + 1) * scale;
01438 
01439                     origin[kx] = origin[ky] = origin[k-1] = 0;          
01440                     point_size  = lmax3d/30.0;
01441                     if (size > 0.0) point_size *= size;
01442                 }
01443 
01444                 set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01445 
01446                 // Update all entries in the dialog box:
01447 
01448                 if (change == 1 || change >= 4) {
01449                     sprintf(temp_buffer,"%f",origin[0]);
01450                     lux_update_itemvalue(dia, Xorigin,
01451                                          INPUT_WINDOW, NO_TYPE, temp_buffer);
01452                 }
01453                 if (change == 2 || change >= 4) {
01454                     sprintf(temp_buffer,"%f",origin[1]);
01455                     lux_update_itemvalue(dia, Yorigin,
01456                                          INPUT_WINDOW, NO_TYPE, temp_buffer);
01457                 }
01458                 if (change == 3 || change >= 4) {
01459                     sprintf(temp_buffer,"%f",origin[2]);
01460                     lux_update_itemvalue(dia, Zorigin,
01461                                          INPUT_WINDOW, NO_TYPE, temp_buffer);
01462                 }
01463 
01464                 if (change == 5) {
01465                     sprintf(temp_buffer,"%f",point_size);
01466                     lux_update_itemvalue(dia, pointsize, INPUT_WINDOW,
01467                                          NO_TYPE, temp_buffer);
01468                     sprintf(temp_buffer,"%f",2*lmax3d);
01469                     lux_update_itemvalue(dia, lmax3D,
01470                                          INPUT_WINDOW,NO_TYPE,temp_buffer);
01471                 }
01472 
01473                 sprintf(temp_buffer,"%f",xmin);
01474                 lux_update_itemvalue(dia,xminimum,
01475                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01476                 sprintf(temp_buffer,"%f",xmax);
01477                 lux_update_itemvalue(dia,xmaximum,
01478                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01479                 sprintf(temp_buffer,"%f",ymin);
01480                 lux_update_itemvalue(dia,yminimum,
01481                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01482                 sprintf(temp_buffer,"%f",ymax);
01483                 lux_update_itemvalue(dia,ymaximum,
01484                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01485 
01486                 // No redrawing of axes is needed for 3D graphs for change != 5.
01487                 
01488                 if (!graph3d) {
01489 
01490                     lux_clear_window(win);
01491                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01492                     draw2d_axis(win, xmin, xmax, ymin, ymax, k);
01493 
01494                 } else if (change == 5) {
01495                     lux_clear_window(win);
01496                     lux_setup_axis(win, -FAC3D*lmax3d, FAC3D*lmax3d, 
01497                                    -FAC3D*lmax3d, FAC3D*lmax3d);
01498                     draw3d_axis(win, lmax3d, costheta, sintheta,
01499                                 cosphi, sinphi);
01500                 }
01501             }
01502 
01503         } else {                        // Key is the ASCII code.
01504 
01505             // Check for "quit" first.
01506 
01507             if (key == 'q') {
01508                 show_instructions(instr, r_factor,
01509                     "\n   Quitting...                                        ",
01510                                   1);
01511                 lux_exit();     // Note that this is now quick_exit
01512             }
01513 
01514 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -//
01515 
01516             if (graph3d && !track) {
01517                 int button;
01518 
01519                 // 3-D operations:
01520 
01521                 if (key== 'R') {
01522 
01523                     // Handle static rotation using lux_check_keypress:
01524 
01525                     show_instructions(instr, r_factor,
01526                       "Pause...\n  r: rotate, (p,c): continue                ",
01527                                       1);
01528 
01529                     do {
01530                         if (lux_check_keypress(win,'r')) {
01531                             show_instructions(instr, r_factor,
01532                       "Rotate... p: pause, c: continue, c: exit rotation     ",
01533                                               0);
01534                             rotate = 1;
01535 
01536                             do {
01537                                 theta = theta + dtheta;
01538                                 if (theta < 0.0) theta += 2*PI;
01539                                 else if (theta > PI*2) theta -= 2*PI;
01540                                 sprintf(temp_buffer, "%f", theta);
01541                                 lux_update_itemvalue(dia, theta3D, INPUT_WINDOW,
01542                                                      NO_TYPE, temp_buffer);
01543                                 costheta = cos(theta);
01544                                 sintheta = sin(theta);
01545                                 lux_clear_current_region(win);
01546                                 draw3d_axis(win, lmax3d, costheta, sintheta,
01547                                             cosphi, sinphi);
01548                                 for_all_leaves(dyn, b, bi) {
01549                                     float X, Y, Z;
01550                                     X = (float)bi->get_pos()[0] - origin[0];
01551                                     Y = (float)bi->get_pos()[1] - origin[1];
01552                                     Z = (float)bi->get_pos()[2] - origin[2];
01553                                     if ( (X > (-lmax3d+point_size))
01554                                         && (X < (lmax3d-point_size)) 
01555                                         && (Y > (-lmax3d+point_size))
01556                                         && (Y < (lmax3d-point_size)) 
01557                                         && (Z > (-lmax3d+point_size))
01558                                         && (Z < (lmax3d-point_size))) {
01559                                         project3d( X, Y, Z, r, s,
01560                                                   costheta, sintheta,
01561                                                   cosphi, sinphi);
01562 
01563                                         if (cenergy) { 
01564                                             compute_energies(b, bi, c);
01565                                             lux_set_color(win,c_energy[c]);
01566                                         } else if (bi->get_index()>0) {
01567                                             if (bi->get_index() <= N_COLORS)
01568                                                 lux_set_color(win,
01569                                                     c_index[bi->get_index()]);
01570                                             else lux_set_color(win,c_index[1]);
01571                                         }
01572 
01573                                         if (track) 
01574                                             lux_draw_pointf(win,r,s);
01575                                         else
01576                                             if (f_flag)
01577                                                 lux_fill_arcf(win,
01578                                                               r-point_size/2,
01579                                                               s-point_size/2, 
01580                                                               point_size,
01581                                                               point_size,
01582                                                               0.0, 360.0);
01583                                             else
01584                                                 lux_draw_arcf(win,
01585                                                               r-point_size/2,
01586                                                               s-point_size/2, 
01587                                                               point_size,
01588                                                               point_size,
01589                                                               0.0, 360.0);
01590                                     }
01591                                 }
01592                                 update_with_delay(win, delay_time);
01593 
01594                                 if (lux_check_keypress(win,'p')) 
01595                                     while(!lux_check_keypress(win,'c'));
01596 
01597                             } while(!lux_check_keypress(win,'c'));
01598 
01599                             // Flush "c"s from input stream:
01600 
01601                             while(lux_check_keypress(win,'c'));
01602                         }
01603                     } while(!lux_check_keypress(win,'p')
01604                             && !lux_check_keypress(win,'c') && !rotate);
01605 
01606                     rotate = 0;
01607                     lux_set_color(win,c_energy[default_color]);
01608 
01609                     // *** End of static rotation loop. ***
01610 
01611                 } else {
01612 
01613                     button = lux_check_buttonpress(win);
01614 
01615                     if (key == '^') {
01616                         phi = phi - dtheta;
01617                         if (phi < -PI) phi = phi + 2.0*PI;
01618                         cosphi = cos(phi); sinphi = sin(phi);
01619                         sprintf(temp_buffer, "%f", phi);
01620                         lux_update_itemvalue(dia, phi3D, INPUT_WINDOW,
01621                                              NO_TYPE, temp_buffer);
01622                     } else if (key == 'V') {
01623                         phi = phi + dtheta;
01624                         if (phi > PI) phi = phi - 2.0*PI;
01625                         cosphi = cos(phi); sinphi = sin(phi);
01626                         sprintf(temp_buffer, "%f", phi);
01627                         lux_update_itemvalue(dia, phi3D, INPUT_WINDOW,
01628                                              NO_TYPE, temp_buffer);
01629                     } else if (key == '<') {
01630                         theta = theta + dtheta;
01631                         if (theta > 2*PI) theta -= 2*PI;
01632                         sprintf(temp_buffer, "%f", theta);
01633                         lux_update_itemvalue(dia, theta3D, INPUT_WINDOW,
01634                                              NO_TYPE, temp_buffer);
01635                         costheta = cos(theta);
01636                         sintheta = sin(theta);
01637                     } else if (key == '>') {
01638                         theta = theta - dtheta;
01639                         if (theta < 0.0) theta += 2*PI;
01640                         sprintf(temp_buffer, "%f", theta);
01641                         lux_update_itemvalue(dia, theta3D, INPUT_WINDOW,
01642                                              NO_TYPE, temp_buffer);
01643                         costheta = cos(theta);sintheta = sin(theta);
01644                     }
01645                 }
01646             }           // End of 3-D.
01647 
01648 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -//
01649 
01650             // Modify point size:
01651 
01652             if (key == 'p' || key == 'P') {
01653                 if (key == 'p') {
01654                     if (point_size > 4*lmax3d/win_size) point_size /= PFAC;
01655                 } else
01656                     point_size *= PFAC;
01657                 sprintf(temp_buffer,"%f",point_size);
01658                 lux_update_itemvalue(dia, pointsize, INPUT_WINDOW,
01659                                      NO_TYPE, temp_buffer);
01660             }
01661 
01662             // Toggle tree display:
01663 
01664             if (key == 'n') {
01665                 nodes = 1 - nodes;
01666                 if (nodes == 0) links = 0;
01667             }
01668 
01669             if (key == 'l') {
01670                 links = 1 - links;
01671                 if (links == 1) nodes = 1;
01672             }
01673 
01674             if (key == 'r') root = 1 - root;
01675 
01676             // Toggle tracking:
01677 
01678             if (key == 't') {
01679                 track = 1 - track;
01680                 temp_buffer[0] = track;
01681                 lux_update_itemvalue(dia, tracking, BUTTON_WINDOW, CHECK_BUTTON,
01682                                      temp_buffer);
01683             }
01684 
01685             // Toggle 2D/3D mode:
01686 
01687             if (key == '3' && (!graph3d)) {
01688                 graph3d = 1;
01689                 lux_update_itemvalue(dia, graph3dim, BUTTON_WINDOW,
01690                                      CHECK_BUTTON,"\1");
01691                 lux_clear_window(win);
01692                 lux_setup_axis(win, -FAC3D*lmax3d, FAC3D*lmax3d, 
01693                                -FAC3D*lmax3d, FAC3D*lmax3d);
01694                 draw3d_axis(win, lmax3d, costheta, sintheta, cosphi, sinphi);
01695             } else if (graph3d &&
01696                        (key == '2' || key == 'x' || key == 'y' || key == 'k')) {
01697                 graph3d = 0;
01698                 lux_update_itemvalue(dia, graph3dim, BUTTON_WINDOW,
01699                                      CHECK_BUTTON,"\0");
01700                 lux_clear_window(win);
01701                 lux_setup_axis(win, xmin, xmax, ymin, ymax);
01702                 draw2d_axis(win, xmin, xmax, ymin, ymax, k);
01703             }
01704 
01705             if (key == 'e') {
01706                 temp_buffer[0] = cenergy = !cenergy;
01707                 lux_update_itemvalue(dia, colorenergy, BUTTON_WINDOW,
01708                                      CHECK_BUTTON,temp_buffer);
01709                 show_color_scheme(colwin, c_energy, c_index,
01710                                   r_factor, cenergy, b_flag, 1);
01711             }
01712 
01713             // Update speed:
01714 
01715             if (key == '+' || key == '=') {
01716                 delay_time = delay_time + 0.05;
01717                 sprintf(temp_buffer, "%f",delay_time);
01718                 lux_update_itemvalue(dia, DelayTime, INPUT_WINDOW,
01719                                      NO_TYPE,temp_buffer);
01720             }else if (key == '-') {
01721                 delay_time = delay_time - 0.05;
01722                 if (delay_time < 0.0) delay_time = 0.0;
01723                 sprintf(temp_buffer, "%f",delay_time);
01724                 lux_update_itemvalue(dia, DelayTime, INPUT_WINDOW,
01725                                      NO_TYPE,temp_buffer);
01726             } if (key == '0') {
01727                 delay_time = 0.0;
01728                 sprintf(temp_buffer, "%f",delay_time);
01729                 lux_update_itemvalue(dia, DelayTime, INPUT_WINDOW,
01730                                      NO_TYPE,temp_buffer);
01731 
01732                 // Flush the queue:
01733 
01734                 while(lux_check_keypress(win,'+')
01735                       || lux_check_keypress(win,'-'));
01736             }
01737 
01738             // Zoom in/out (fixed axes and origin):
01739 
01740             if (key == 'z') {
01741 
01742                 lmax3d /= ZOOM;
01743                 set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01744                 point_size /= ZOOM;
01745 
01746                 sprintf(temp_buffer,"%f",point_size);
01747                 lux_update_itemvalue(dia, pointsize, INPUT_WINDOW,
01748                                      NO_TYPE, temp_buffer);
01749                 sprintf(temp_buffer,"%f",2*lmax3d);
01750                 lux_update_itemvalue(dia, lmax3D,
01751                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01752                 sprintf(temp_buffer,"%f",xmin);
01753                 lux_update_itemvalue(dia,xminimum,
01754                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01755                 sprintf(temp_buffer,"%f",xmax);
01756                 lux_update_itemvalue(dia,xmaximum,
01757                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01758                 sprintf(temp_buffer,"%f",ymin);
01759                 lux_update_itemvalue(dia,yminimum,
01760                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01761                 sprintf(temp_buffer,"%f",ymax);
01762                 lux_update_itemvalue(dia,ymaximum,
01763                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01764 
01765                 if (graph3d) {
01766                     lux_clear_window(win);
01767                     lux_setup_axis(win,-FAC3D*lmax3d,FAC3D*lmax3d, 
01768                                    -FAC3D*lmax3d, FAC3D*lmax3d);
01769                     draw3d_axis(win, lmax3d, costheta, sintheta,
01770                                 cosphi, sinphi);
01771                 } else {
01772                     lux_clear_window(win);
01773                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01774                     draw2d_axis(win, xmin, xmax, ymin, ymax, k);
01775                 }
01776 
01777             } else if (key == 'Z') {
01778 
01779                 lmax3d *= ZOOM;
01780                 set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01781                 point_size *= ZOOM;
01782 
01783                 sprintf(temp_buffer,"%f",point_size);
01784                 lux_update_itemvalue(dia, pointsize, INPUT_WINDOW,
01785                                      NO_TYPE, temp_buffer);
01786                 sprintf(temp_buffer,"%f",2*lmax3d);
01787                 lux_update_itemvalue(dia, lmax3D,
01788                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01789                 sprintf(temp_buffer,"%f",xmin);
01790                 lux_update_itemvalue(dia,xminimum,
01791                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01792                 sprintf(temp_buffer,"%f",xmax);
01793                 lux_update_itemvalue(dia,xmaximum,
01794                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01795                 sprintf(temp_buffer,"%f",ymin);
01796                 lux_update_itemvalue(dia,yminimum,
01797                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01798                 sprintf(temp_buffer,"%f",ymax);
01799                 lux_update_itemvalue(dia,ymaximum,
01800                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01801 
01802                 if (graph3d) {
01803                     lux_clear_window(win);
01804                     lux_setup_axis(win, -FAC3D*lmax3d, FAC3D*lmax3d, 
01805                                    -FAC3D*lmax3d, FAC3D*lmax3d);
01806                     draw3d_axis(win, lmax3d, costheta, sintheta,
01807                                 cosphi, sinphi);
01808                 } else {
01809                     lux_clear_window(win);
01810                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01811                     draw2d_axis(win, xmin, xmax, ymin, ymax, k);
01812                 }
01813             }
01814 
01815             // Change projection axis (fixed origin, scale; x=1, y=2, z=3):
01816 
01817             if (key == 'k') {
01818                 if (graph3d) {
01819                     theta = -PI/2; phi = PI/2.0;
01820                     costheta = cos(theta); sintheta = sin(theta);
01821                     cosphi = cos(phi); sinphi = sin(phi);
01822 
01823                     while (lux_check_keypress(win,'<')
01824                            || lux_check_keypress(win,'>')
01825                            || lux_check_keypress(win,'^')
01826                            || lux_check_keypress(win,'V') );
01827                 } else {
01828                     k = 3; kx = 0; ky = 1;
01829                     set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01830                     lux_clear_window(win);
01831                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01832                     draw2d_axis(win, xmin, xmax, ymin, ymax, k);
01833 
01834                     sprintf(temp_buffer, " %d ", k);
01835                     lux_update_itemvalue(dia, view2D, INPUT_WINDOW, NO_TYPE,
01836                                          temp_buffer);
01837                 }
01838             } else if (key == 'y') {
01839                 if (graph3d) {
01840                     theta = -PI/2.0; phi = 0.0;
01841                     costheta = cos(theta); sintheta = sin(theta);
01842                     cosphi = cos(phi); sinphi = sin(phi);
01843 
01844                     while (lux_check_keypress(win,'<')
01845                            || lux_check_keypress(win,'>')
01846                            || lux_check_keypress(win,'^')
01847                            || lux_check_keypress(win,'V') );
01848                 } else {
01849                     k = 2; kx = 2; ky = 0;
01850                     set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01851                     lux_clear_window(win);
01852                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01853                     draw2d_axis(win, xmin, xmax, ymin, ymax, k);
01854 
01855                     sprintf(temp_buffer, " %d ", k);
01856                     lux_update_itemvalue(dia, view2D, INPUT_WINDOW, NO_TYPE,
01857                                          temp_buffer);
01858                 }
01859             } else if (key == 'x') {
01860                 if (graph3d) {
01861                     theta = 0.0; phi = 0.0;
01862                     costheta = cos(theta); sintheta = sin(theta);
01863                     cosphi = cos(phi); sinphi = sin(phi);
01864 
01865                     while (lux_check_keypress(win,'<')
01866                            || lux_check_keypress(win,'>')
01867                            || lux_check_keypress(win,'^')
01868                            || lux_check_keypress(win,'V') );
01869                 } else {
01870                     k = 1; kx = 1; ky = 2;
01871                     set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01872                     lux_clear_window(win);
01873                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01874                     draw2d_axis(win, xmin, xmax, ymin, ymax, k);
01875 
01876                     sprintf(temp_buffer, " %d ", k);
01877                     lux_update_itemvalue(dia, view2D, INPUT_WINDOW, NO_TYPE,
01878                                          temp_buffer);
01879                 }
01880             }
01881 
01882             // Select new origin: 'o' ==> point in space, 'O' ==> star
01883 
01884             if (!graph3d && key == 'o') {
01885                 show_instructions(instr, r_factor,
01886                 " Use mouse-right to select new origin...\n",1);
01887                 float r, s;
01888                 get_mouse_position(win, &r, &s);
01889 
01890                 // Looks like r and s come back in the correct units!
01891 
01892                 origin[kx] = r;
01893                 origin[ky] = s;
01894                 set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01895 
01896                 lux_clear_window(win);
01897                 lux_setup_axis(win, xmin, xmax, ymin, ymax);
01898                 draw2d_axis(win, xmin, xmax, ymin, ymax, k);
01899 
01900                 sprintf(temp_buffer,"%f",origin[0]);
01901                 lux_update_itemvalue(dia, Xorigin,
01902                                      INPUT_WINDOW, NO_TYPE, temp_buffer);
01903                 sprintf(temp_buffer,"%f",origin[1]);
01904                 lux_update_itemvalue(dia, Yorigin,
01905                                      INPUT_WINDOW, NO_TYPE, temp_buffer);
01906                 sprintf(temp_buffer,"%f",origin[2]);
01907                 lux_update_itemvalue(dia, Zorigin,
01908                                      INPUT_WINDOW, NO_TYPE, temp_buffer);
01909                 sprintf(temp_buffer,"%f",xmin);
01910                 lux_update_itemvalue(dia,xminimum,
01911                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01912                 sprintf(temp_buffer,"%f",xmax);
01913                 lux_update_itemvalue(dia,xmaximum,
01914                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01915                 sprintf(temp_buffer,"%f",ymin);
01916                 lux_update_itemvalue(dia,yminimum,
01917                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01918                 sprintf(temp_buffer,"%f",ymax);
01919                 lux_update_itemvalue(dia,ymaximum,
01920                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01921 
01922                 origin_star = -1;
01923                 sprintf(temp_buffer," %d",origin_star);
01924                 lux_update_itemvalue(dia,originstar,
01925                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01926 
01927             } else if (!graph3d && key == 'O') {
01928 
01929                 show_instructions(instr, r_factor,
01930                 " Use mouse-right to select new origin star...\n",1);
01931                 float r, s;
01932                 get_mouse_position(win, &r, &s);
01933 
01934                 // Looks like r and s come back in the correct units!
01935 
01936                 // Find the star closest to the (2-D) mouse position.
01937 
01938                 origin_star = nearest_index(b, r, s, kx, ky);
01939 
01940                 if (origin_star > 0) {
01941                     for (int kk = 0; kk < 3; kk++) origin[kk] = 0;
01942                     set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01943                 }
01944 
01945                 lux_clear_window(win);
01946                 lux_setup_axis(win, xmin, xmax, ymin, ymax);
01947                 draw2d_axis(win, xmin, xmax, ymin, ymax, k);
01948 
01949                 sprintf(temp_buffer,"%f",origin[0]);
01950                 lux_update_itemvalue(dia, Xorigin,
01951                                      INPUT_WINDOW, NO_TYPE, temp_buffer);
01952                 sprintf(temp_buffer,"%f",origin[1]);
01953                 lux_update_itemvalue(dia, Yorigin,
01954                                      INPUT_WINDOW, NO_TYPE, temp_buffer);
01955                 sprintf(temp_buffer,"%f",origin[2]);
01956                 lux_update_itemvalue(dia, Zorigin,
01957                                      INPUT_WINDOW, NO_TYPE, temp_buffer);
01958                 sprintf(temp_buffer,"%f",xmin);
01959                 lux_update_itemvalue(dia,xminimum,
01960                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01961                 sprintf(temp_buffer,"%f",xmax);
01962                 lux_update_itemvalue(dia,xmaximum,
01963                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01964                 sprintf(temp_buffer,"%f",ymin);
01965                 lux_update_itemvalue(dia,yminimum,
01966                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01967                 sprintf(temp_buffer,"%f",ymax);
01968                 lux_update_itemvalue(dia,ymaximum,
01969                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01970 
01971                 sprintf(temp_buffer," %d",origin_star);
01972                 lux_update_itemvalue(dia,originstar,
01973                                      INPUT_WINDOW,NO_TYPE,temp_buffer);
01974             }
01975 
01976 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -//
01977 
01978             // Handle dialog box input:
01979 
01980             {
01981                 int return_value;
01982                 return_value = 0;
01983                 while(lux_check_keypress(win,'r')); // Clean garbage
01984 
01985                 if (key == 'i') {
01986                     show_instructions(instr, r_factor,
01987                 " Idle...\n  d: dialog, r: replay, c: continue: q-quit",1);
01988                     return_value = lux_getevent();
01989                 } else if (key == 'd') {
01990                     show_instructions(instr, r_factor,
01991 "Dialog mode keyboard options\n\n\
01992   Dialog window:\n\
01993     o   OK, keep dialog window\n\
01994     O   OK, close dialog window\n\
01995     c   CANCEL, keep dialog window\n\
01996     C   CANCEL, close dialog window\n\n\
01997   Other windows:\n\
01998     r   replay\n\
01999     c   continue (keep dialog window,\n\
02000                   ignore dialog changes)\n\
02001     q   quit\n\
02002 ",1);
02003                     lux_show_dialog(dia); return_value = lux_getevent();
02004                 }
02005                 
02006                 // Get all the values if OK button being clicked (clicking
02007                 // OK forces a return value of 3).
02008                 
02009                 if (return_value == 3) {
02010 
02011                     // Read all data from the dialog box.  Note that it is
02012                     // important that the box be maintained correctly.
02013                     // Any errors in the data displayed in the box will be
02014                     // propogated to the "real" data by this procedure.
02015 
02016                     lux_get_itemvalue(dia, view2D, INPUT_WINDOW, NO_TYPE,
02017                                       temp_buffer);
02018                     sscanf(temp_buffer, "%d", &k);
02019                     if (k == 1)
02020                         kx = 1, ky = 2;
02021                     else if (k == 2)
02022                         kx = 2, ky = 0;
02023                     else
02024                         kx = 0, ky = 1;
02025 
02026                     lux_get_itemvalue(dia, originstar, INPUT_WINDOW, NO_TYPE,
02027                                       temp_buffer);
02028                     sscanf(temp_buffer, "%d", &origin_star);
02029 
02030                     lux_get_itemvalue(dia, Xorigin, INPUT_WINDOW, NO_TYPE,
02031                                       temp_buffer);
02032                     sscanf(temp_buffer,"%f",origin);
02033 
02034                     lux_get_itemvalue(dia, Yorigin, INPUT_WINDOW, NO_TYPE,
02035                                       temp_buffer);
02036                     sscanf(temp_buffer,"%f",&origin[1]);
02037 
02038                     lux_get_itemvalue(dia, Zorigin, INPUT_WINDOW, NO_TYPE,
02039                                       temp_buffer);
02040                     sscanf(temp_buffer,"%f",&origin[2]);
02041 
02042                     lux_get_itemvalue(dia, lmax3D, INPUT_WINDOW, NO_TYPE,
02043                                       temp_buffer);
02044                     sscanf(temp_buffer,"%f",&lmax3d);
02045                     lmax3d /= 2;                        // Display twice lmax3d
02046 
02047                     // ------------------------------------------------------
02048 
02049                     // NOTE: xmin, xmax, ymin, ymax are IRRELEVANT, since they
02050                     // will be forced to be consistent with origin and lmax3d.
02051 
02052                     lux_get_itemvalue(dia, xminimum, INPUT_WINDOW, NO_TYPE,
02053                                       temp_buffer);
02054                     sscanf(temp_buffer,"%f",&xmin);
02055 
02056                     lux_get_itemvalue(dia, xmaximum, INPUT_WINDOW, NO_TYPE,
02057                                       temp_buffer);
02058                     sscanf(temp_buffer,"%f",&xmax);
02059 
02060                     lux_get_itemvalue(dia, yminimum, INPUT_WINDOW, NO_TYPE,
02061                                       temp_buffer);
02062                     sscanf(temp_buffer,"%f",&ymin);
02063 
02064                     lux_get_itemvalue(dia, ymaximum, INPUT_WINDOW, NO_TYPE,
02065                                       temp_buffer);
02066                     sscanf(temp_buffer,"%f",&ymax);
02067 
02068                     set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
02069 
02070                     // Make sure entries in the dialog box are consistent:
02071 
02072                     sprintf(temp_buffer,"%f",xmin);
02073                     lux_update_itemvalue(dia,xminimum,
02074                                          INPUT_WINDOW,NO_TYPE,temp_buffer);
02075                     sprintf(temp_buffer,"%f",xmax);
02076                     lux_update_itemvalue(dia,xmaximum,
02077                                          INPUT_WINDOW,NO_TYPE,temp_buffer);
02078                     sprintf(temp_buffer,"%f",ymin);
02079                     lux_update_itemvalue(dia,yminimum,
02080                                          INPUT_WINDOW,NO_TYPE,temp_buffer);
02081                     sprintf(temp_buffer,"%f",ymax);
02082                     lux_update_itemvalue(dia,ymaximum,
02083                                          INPUT_WINDOW,NO_TYPE,temp_buffer);
02084 
02085                     // ------------------------------------------------------
02086 
02087                     lux_get_itemvalue(dia, pointsize, INPUT_WINDOW, NO_TYPE,
02088                                       temp_buffer);
02089                     sscanf(temp_buffer,"%f",&point_size);
02090 
02091                     lux_get_itemvalue(dia, theta3D, INPUT_WINDOW, NO_TYPE,
02092                                       temp_buffer);
02093                     sscanf(temp_buffer, "%f", &theta);
02094                     costheta = cos(theta); sintheta = sin(theta);
02095 
02096                     lux_get_itemvalue(dia, phi3D, INPUT_WINDOW, NO_TYPE,
02097                                       temp_buffer);
02098                     sscanf(temp_buffer, "%f", &phi);
02099                     cosphi = cos(phi); sinphi = sin(phi);
02100 
02101                     lux_get_itemvalue(dia, dtheta3D, INPUT_WINDOW, NO_TYPE,
02102                                       temp_buffer);
02103                     sscanf(temp_buffer, "%f", &dtheta);
02104 
02105                     lux_get_itemvalue(dia, DelayTime, INPUT_WINDOW, NO_TYPE,
02106                                       temp_buffer);
02107                     sscanf(temp_buffer,"%f",&delay_time);
02108 
02109                     lux_get_itemvalue(dia, colorenergy, BUTTON_WINDOW,
02110                                       CHECK_BUTTON, temp_buffer);
02111                     cenergy = temp_buffer[0];
02112                     show_color_scheme(colwin, c_energy, c_index,
02113                                       r_factor, cenergy, b_flag, 1);
02114 
02115                     lux_get_itemvalue(dia, tracking, BUTTON_WINDOW,
02116                                       CHECK_BUTTON,  temp_buffer);
02117                     track = temp_buffer[0];
02118 
02119                     lux_get_itemvalue(dia, graph3dim, BUTTON_WINDOW,
02120                                       CHECK_BUTTON, temp_buffer);
02121                     graph3d = temp_buffer[0];
02122 
02123                     lux_clear_window(win);
02124 
02125                     if (graph3d) {
02126                         lux_setup_axis(win, -FAC3D*lmax3d, FAC3D*lmax3d, 
02127                                        -FAC3D*lmax3d, FAC3D*lmax3d);
02128                         draw3d_axis(win, lmax3d, costheta, sintheta,
02129                                     cosphi, sinphi);
02130                     } else {
02131                         lux_setup_axis(win, xmin, xmax, ymin, ymax);
02132                         draw2d_axis(win, xmin, xmax, ymin, ymax, k);
02133                     }
02134                 }
02135             }
02136         }
02137     }
02138 }
02139 
02140 /*-----------------------------------------------------------------------------
02141  *  main  --  driver to use  xstarplot()  as a tool. 
02142  *               The argument -a is interpreted as the axis along which to
02143  *            view the N-body system: the number of the coordinate axis along
02144  *            which the projection is directed, with {k,x,y} having a
02145  *            right-handend orientation.
02146  *               If an argument -l is provided, it defines the maximum
02147  *            lengths along the remaining axes.
02148  *-----------------------------------------------------------------------------
02149  */
02150 main(int argc, char** argv)
02151 {
02152     dyn *b;
02153 
02154     // Establish some defaults:
02155 
02156     int  k = 3;         // Note x = 1, y = 2, z = 3 here!
02157     float lmax = -1.0;
02158     int cenergy = 0;
02159     int d = 2;
02160     float D = 0.0;
02161     float rel_point_size = -1.0;
02162     float scale = 1.0;
02163 
02164     bool  b_flag = TRUE;        // if TRUE, the background is black
02165     bool  f_flag = TRUE;        // if TRUE, the star is solid
02166     bool  p_flag = FALSE;       // if TRUE, output stdin to stdout
02167     bool  t_flag = FALSE;       // if TRUE, show tree structure
02168 
02169     check_help();
02170 
02171     extern char *poptarg;
02172     int c;
02173     char* param_string = "a:d:D:efl:pP:rs:t";
02174 
02175     while ((c = pgetopt(argc, argv, param_string)) != -1)
02176       switch(c) {
02177 
02178             case 'a': k = atoi(poptarg);
02179                       break;
02180             case 'd': d = atoi(poptarg);
02181                       break;
02182             case 'D': D = atof(poptarg);
02183                       break;
02184             case 'e': cenergy = 1;
02185                       break;
02186             case 'f': f_flag = FALSE;
02187                       break;
02188             case 'l': lmax = atof(poptarg);
02189                       break;
02190             case 'p': p_flag = TRUE;
02191                       break;
02192             case 'P': rel_point_size = atof(poptarg);
02193                       break;
02194             case 'r': b_flag = FALSE;
02195                       break;
02196             case 's': scale = atof(poptarg);
02197                       break;
02198             case 't': t_flag = TRUE;
02199                       break;
02200             case '?': params_to_usage(cerr, argv[0], param_string);
02201                       get_help();
02202                       exit(1);
02203         }
02204         
02205     int gfx_counter = 0;
02206     while (b = get_dyn(cin)) {
02207         convert_relative_to_absolute(b);
02208         xstarplot(b, scale, k, d, lmax, rel_point_size, D, cenergy,
02209                   b_flag, f_flag, t_flag, gfx_counter++);
02210         if (p_flag) put_node(cout, *b);
02211         rmtree(b);
02212     }
02213 
02214     if (p_flag) cout << "End of data\n" << flush;
02215 
02216     // idle, wait to leave
02217 
02218     xstarplot(b, scale, k, d, lmax, rel_point_size, D, cenergy,
02219               b_flag, f_flag, t_flag, -1);
02220 }

Generated at Sun Feb 24 09:57:22 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001