Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

xstarplot.C

Go to the documentation of this file.
00001 
00027 
00028 //.............................................................................
00029 //    version 1:  May 1989   Piet Hut            email: piet@iassns.bitnet
00030 //                           Institute for Advanced Study, Princeton, NJ, USA
00031 //    version 2:  Dec 1992   Piet Hut      adapted to the new C++-based Starlab
00032 //    version 3:  Dec 1992   Steve McMillan      email: steve@zonker.drexel.edu
00033 //                           Drexel University, Philadelphia, PA, USA
00034 //                           Converted original ASCIIplot to X --- FIRST DRAFT!
00035 //    version 4:  Jan 1994   Biao Lu             email: biao@eagle.drexel.edu
00036 //                           Drexel University, Philadelphia, PA, USA
00037 //                           Use new X interface for movie.
00038 //            Aug/Sep 1994   Cleaned up and expanded, SMcM
00039 //                Sep 1995   Extended to sdyn3 and nonzero radii, SMcM
00040 //                Aug 1996   Added forward/backward step modes, SMcM
00041 //                Aug 1996   Reworked for hdyn and nonzero radii, SMcM
00042 //                Jul 1998   New end-of-data behavior; more robust
00043 //                           X interface, SMcM
00044 //.............................................................................
00045 //  non-local functions: 
00046 //    xstarplot
00047 //.............................................................................
00048 //  uses:
00049 //    liblux.a (X interface)
00050 //    The X graphics library
00051 //.............................................................................
00052 
00053 // NOTE: On some systems, it appears that overflow can occur, causing the
00054 //       win.lnx and win.lny entries to be overwritten and leading to
00055 //       spurious "log10" errors in draw.c (in lux_set_item, specifically).
00056 //       This isn't fatal, but it should be fixed someday...
00057 
00058 #include "hdyn.h"
00059 #include "xstarplot.h"
00060 #include "dyn_util.h"
00061 
00062 //-------------------------------------------------------------------------
00063 
00064 
00065 // These shouldn't really be global, but keep them this way for now...
00066 
00067 unsigned long  win, dia, instr, colwin;
00068 unsigned long c_energy[10], c_index[N_COLORS+1];
00069 int      init_status = 0;
00070 
00071 // The plotting box is determined completely by origin and lmax3d.
00072 // Its projection onto the viewing plane is xmin, xmax, ymin, ymax
00073 
00074 float  xmin, xmax, ymin, ymax, base_point_size, lmax3d, origin[3];
00075 
00076 int   win_size;
00077 int   point_scale_mode = 0;
00078 int   kx = 1, ky = 2, kproj = 3;
00079 int   origin_star = -1;
00080 int   nodes = 0, links = 0, root = 0, multiples = 0, unperturbed = 0;
00081 float theta = 0.33, costheta = cos(0.33), sintheta = sin(0.33), dtheta = 0.03;
00082 float phi = 0.33, cosphi = cos(0.33), sinphi = sin(0.33);
00083 real  local_offset[3];
00084 
00085 #define MIN_DELAY  1.0
00086 float delay_time = MIN_DELAY;
00087 
00088 float r_factor = 1.0;
00089 
00090 char  graph3d = 1, track = 0, cenergy = 0; // convenient to distinguish these
00091 
00092 char   temp_buffer[255];        // convenient to share this temporary space
00093 
00094 //-------------------------------------------------------------------------
00095 
00096 // base_point_size defines the size of the default "dot" size on the display.
00097 // It is used (with scaling) for stars and (without scaling) for nodes.
00098 
00099 local void set_base_point_size(hdyn* b, float rel_point_size)
00100 {
00101     base_point_size = 2 * SMALL_DOT_SIZE;       // default point size
00102 
00103     if (point_scale_mode == 1) {
00104 
00105         // Scale so the average initial mass has a reasonable size.
00106 
00107         real m_tot = 0;
00108         real n_tot = 0;
00109         for_all_leaves(hdyn, b, bi) {
00110             n_tot++;
00111             m_tot += bi->get_mass();
00112         }
00113 
00114         if (n_tot > 0) base_point_size /= sqrt(m_tot/n_tot);    // NB sqrt below
00115 
00116     } else if (point_scale_mode == 2 || point_scale_mode == 3) {
00117 
00118         // In the case point_scale_mode = 2, use unscaled (i.e. true)
00119         // radii if rel_point_size < 0.
00120 
00121         if (point_scale_mode == 2 && rel_point_size < 0) {
00122 
00123             base_point_size = 1;
00124 
00125         } else {
00126 
00127             // Scale so the average initial radius has a reasonable size.
00128 
00129             real r_tot = 0;
00130             real n_tot = 0;
00131             for_all_leaves(hdyn, b, bi) {
00132                 n_tot++;
00133                 r_tot += bi->get_radius();
00134             }
00135 
00136             if (n_tot > 0) {
00137                 if (point_scale_mode == 2)
00138                     base_point_size /= r_tot/n_tot;
00139                 else
00140                     base_point_size /= sqrt(r_tot/n_tot);
00141             }
00142         }
00143     }
00144 
00145     // Optional additional scaling:
00146 
00147     if (rel_point_size > 0.0)  base_point_size *= rel_point_size;
00148 }
00149 
00150 local float get_point_size(hdyn* bi)
00151 {
00152     // Scaling by mass is too extreme.  Use sqrt(mass).
00153     // Also, impose a lower limit on the point size.
00154 
00155     if (point_scale_mode == 1)
00156         return max(SMALL_DOT_SIZE, base_point_size * sqrt(bi->get_mass()));
00157     else if (point_scale_mode == 2)
00158         return max(SMALL_DOT_SIZE, base_point_size * bi->get_radius());
00159     else if (point_scale_mode == 3)
00160         return max(SMALL_DOT_SIZE, base_point_size * sqrt(bi->get_radius()));
00161     else
00162         return base_point_size;
00163 }
00164 
00165 local void draw_star_point(unsigned long win, float r, float s,
00166                            float actual_point_size, bool f_flag)
00167 
00168 // Plot a point of size actual_point_size at (r,s), filled or unfilled
00169 // according to the value of f_flag.
00170 
00171 {
00172     if (f_flag)
00173         lux_fill_arcf(win, r - actual_point_size/2, s - actual_point_size/2,
00174                       actual_point_size, actual_point_size, 0.0, 360.0);
00175     else
00176         lux_draw_arcf(win, r - actual_point_size/2, s - actual_point_size/2, 
00177                       actual_point_size, actual_point_size, 0.0, 360.0);
00178 }
00179 
00180 local void draw_links_2d(hdyn* b, float r, float s)
00181 {
00182     for_all_daughters(hdyn, b, bb) {
00183 
00184         float rr = bb->get_pos()[kx]-local_offset[kx];
00185         float ss = bb->get_pos()[ky]-local_offset[ky];
00186         float stemp;
00187 
00188         // Deal with the 9 possible locations of (rr,ss) with respect
00189         // to the box defined by xmin, xmax, ymin, and ymax.
00190 
00191         if (rr < xmin) {
00192 
00193             if (ss < ymin) {
00194                 float stemp = interp_to_x(r, s, rr, ss, xmin);
00195                 if (stemp >= ymin)
00196                     rr = xmin, ss = stemp;
00197                 else
00198                     rr = interp_to_y(r, s, rr, ss, ymin), ss = ymin;
00199             } else if (ss > ymax) {
00200                 if ((stemp = interp_to_x(r, s, rr, ss, xmin)) <= ymax)
00201                     rr = xmin, ss = stemp;
00202                 else
00203                     rr = interp_to_y(r, s, rr, ss, ymax), ss = ymax;
00204             } else
00205                 ss = interp_to_x(r, s, rr, ss, xmin), rr = xmin;
00206 
00207         } else if (rr > xmax) {
00208 
00209             if (ss < ymin) {
00210                 if ((stemp = interp_to_x(r, s, rr, ss, xmax)) >= ymin)
00211                     rr = xmax, ss = stemp;
00212                 else
00213                     rr = interp_to_y(r, s, rr, ss, ymin), ss = ymin;
00214             } else if (ss > ymax) {
00215                 if ((stemp = interp_to_x(r, s, rr, ss, xmax)) <= ymax)
00216                     rr = xmax, ss = stemp;
00217                 else
00218                     rr = interp_to_y(r, s, rr, ss, ymax), ss = ymax;
00219             } else
00220                 ss = interp_to_x(r, s, rr, ss, xmax), rr = xmax;
00221 
00222         } else {
00223 
00224             if (ss < ymin)
00225                 rr = interp_to_y(r, s, rr, ss, ymin), ss = ymin;
00226             else if (ss > ymax)
00227                 rr = interp_to_y(r, s, rr, ss, ymax), ss = ymax;
00228 
00229         }
00230         lux_draw_linef(win, r, s, rr, ss);
00231     }
00232 }                                          
00233 
00234 local void draw_links_3d(hdyn* b, float r, float s)
00235 {
00236     for_all_daughters(hdyn, b, bb) {
00237 
00238         float X = (float)bb->get_pos()[0] - local_offset[0] - origin[0];
00239         float Y = (float)bb->get_pos()[1] - local_offset[1] - origin[1];
00240         float Z = (float)bb->get_pos()[2] - local_offset[2] - origin[2];
00241 
00242         // Don't attempt to deal with the 27 possible locations
00243         // of (X, Y, Z) with respect to the box!
00244 
00245         float rr, ss;
00246         project3d(X, Y, Z, rr, ss, costheta, sintheta, cosphi, sinphi);
00247         lux_draw_linef(win, r, s, rr, ss);
00248     }
00249 }                                          
00250 
00251 local int clean_index(hdyn* b)
00252 {
00253     int clean_name = 0;
00254 
00255     if (b->get_index() > 0) 
00256         clean_name = b->get_index();
00257     else if (b->get_name()) {
00258         int i = 0;
00259         if (sscanf(b->get_name(), "%d", &i)) clean_name = i;
00260     }
00261 
00262     return clean_name;
00263 }
00264 
00265 local void plot_star(hdyn *bi, float r, float s,
00266                      float actual_point_size, int f_flag)
00267 {
00268     // Plot a point at (r, s) representing star bi.
00269 
00270     // Determine the color to use.
00271 
00272     bool temp_flag = f_flag;
00273     if (bi->get_oldest_daughter()) {
00274 
00275         lux_set_color(win, lux_lookup_color(win, "grey"));
00276         temp_flag =  1 - f_flag;
00277 
00278     } else {
00279 
00280         if (cenergy) {
00281 
00282             char c;
00283 
00284             compute_energies(bi->get_root(), bi, c);
00285             lux_set_color(win, c_energy[c]);
00286 
00287         } else if (clean_index(bi) > 0) {
00288 
00289             // Wrap the color map.
00290 
00291             int ii = clean_index(bi);
00292             while (ii > N_COLORS) ii -= N_COLORS;
00293 
00294             lux_set_color(win,c_index[ii]);
00295         }
00296     }
00297 
00298     if (track)
00299 
00300         lux_draw_pointf(win, r, s);
00301 
00302     else {
00303 
00304         real scale = 1.0;
00305         real reset_grey = false;
00306 
00307         // Deal with possible highlighted systems.
00308 
00309         if (multiples
00310             && bi->is_top_level_node()
00311             && bi->get_oldest_daughter()
00312             && bi->n_leaves() > 2) {
00313 
00314             scale = 4.0;
00315             if (bi->n_leaves() == 3)
00316                 lux_set_color(win, lux_lookup_color(win, "yellow"));
00317             else if (bi->n_leaves() == 4)
00318                 lux_set_color(win, lux_lookup_color(win, "orange"));
00319             else
00320                 lux_set_color(win, lux_lookup_color(win, "red"));
00321 
00322             reset_grey = true;
00323 
00324         } else if (unperturbed
00325                    && bi->get_oldest_daughter()
00326                    && bi->get_oldest_daughter()
00327                    ->get_fully_unperturbed()) {
00328 
00329             scale = 2.0;
00330             lux_set_color(win, lux_lookup_color(win, "blue"));
00331 
00332             reset_grey = true;
00333 
00334         }
00335 
00336         draw_star_point(win, r, s,
00337                         scale*actual_point_size, temp_flag);
00338         if (links && reset_grey)
00339             lux_set_color(win, lux_lookup_color(win, "grey"));
00340     }
00341 }
00342 
00343 local int plot_stars(hdyn* b, int f_flag)
00344 {
00345     int  n_stars = b->n_leaves();
00346     if (b->get_oldest_daughter() == NULL) n_stars = 0;
00347 
00348     int  n_nodes = count_nodes(b);
00349     float r, s;
00350 
00351     if (graph3d) {
00352 
00353         for_all_nodes(hdyn, b, bi) if (root || bi->get_parent()) {
00354             if (nodes
00355                 || (multiples && bi->is_top_level_node())
00356                 || (unperturbed && bi->get_oldest_daughter())
00357                 || (bi->get_oldest_daughter() == NULL)) {
00358                 
00359                 float X = (float)bi->get_pos()[0] - local_offset[0] - origin[0];
00360                 float Y = (float)bi->get_pos()[1] - local_offset[1] - origin[1];
00361                 float Z = (float)bi->get_pos()[2] - local_offset[2] - origin[2];
00362 
00363                 float actual_point_size = get_point_size(bi);
00364 
00365                 if (   (X > (-lmax3d + actual_point_size))
00366                     && (X < ( lmax3d - actual_point_size)) 
00367                     && (Y > (-lmax3d + actual_point_size))
00368                     && (Y < ( lmax3d - actual_point_size)) 
00369                     && (Z > (-lmax3d + actual_point_size))
00370                     && (Z < ( lmax3d - actual_point_size))) {
00371 
00372                     // Should really sort by depth here...
00373 
00374                     project3d(X, Y, Z, r, s,
00375                               costheta, sintheta,
00376                               cosphi, sinphi);
00377 
00378                     plot_star(bi, r, s, actual_point_size, f_flag);
00379 
00380                     if (links && bi->get_oldest_daughter())
00381                         draw_links_3d(bi, r, s);
00382                 }
00383             }
00384         }
00385 
00386     } else {
00387 
00388         // Make a list of all nodes, *including* the root node if root = 1.
00389         // Root will be at the start of the list if it is being displayed.
00390 
00391         hdynptr* p = new hdynptr[n_nodes+root];
00392 
00393         int ip = 0;
00394         for_all_nodes(hdyn, b, bi) if (root || bi != b) p[ip++] = bi;
00395         if (ip != n_nodes+root) {
00396             cerr << "plot_stars: n_nodes = " << n_nodes+root
00397                 << " counted " << ip << endl;
00398             exit(1);
00399         }
00400 
00401         // Sort by kproj (note that kproj = 1, 2, or 3 for x, y, or z):
00402 
00403         for (ip = 0; ip < n_nodes+root; ip++)
00404             for (int jp = ip+1; jp < n_nodes+root; jp++)
00405                 if (p[jp]->get_pos()[kproj-1] < p[ip]->get_pos()[kproj-1]) {
00406                     hdynptr bb = p[jp];
00407                     p[jp] = p[ip];
00408                     p[ip] = bb;
00409                 }
00410 
00411         // Plot ordered by depth.
00412 
00413         for (ip = 0; ip < n_nodes+root; ip++) {
00414             hdyn * bi = p[ip];
00415             if ( (root || bi != b)
00416                 && (nodes
00417                     || (multiples && bi->is_top_level_node())
00418                     || (unperturbed && bi->get_oldest_daughter())
00419                     || (bi->get_oldest_daughter() == NULL))) {
00420 
00421                 r = (float)bi->get_pos()[kx] - local_offset[kx];
00422                 s = (float)bi->get_pos()[ky] - local_offset[ky];
00423 
00424                 float actual_point_size = get_point_size(bi);
00425 
00426                 if (   (r > (xmin + actual_point_size))
00427                     && (r < (xmax - actual_point_size)) 
00428                     && (s > (ymin + actual_point_size))
00429                     && (s < (ymax - actual_point_size)) ) {
00430 
00431                     plot_star(bi, r, s, actual_point_size, f_flag);
00432 
00433                     if (links && bi->get_oldest_daughter())
00434                         draw_links_2d(bi, r, s);
00435                 }
00436             }
00437         }
00438         delete p;
00439     }
00440     return n_stars;
00441 }
00442 
00443 local int type(int which)
00444 {
00445     if (which == tracking || which == graph3dim || which == colorenergy)
00446         return BUTTON_WINDOW;
00447     else
00448         return INPUT_WINDOW;
00449 }
00450 
00451 local int subtype(int which)
00452 {
00453     if (which == tracking || which == graph3dim || which == colorenergy)
00454         return CHECK_BUTTON;
00455     else
00456         return NO_TYPE;
00457 }
00458 
00459 local void set_temp_buffer(int which)
00460 {
00461     // Translate ID into a string representing the value.
00462 
00463     char c = -1;
00464     int i = -1;
00465     float f = 1.e30;    // Don't use VERY_LARGE_NUMBER here (DEC may object!)
00466 
00467     switch (which) {
00468         case colorenergy:       c = cenergy; break;
00469         case tracking:          c = track;   break;
00470         case graph3dim:         c = graph3d; break;
00471         case xminimum:          f = xmin; break;
00472         case xmaximum:          f = xmax; break;
00473         case yminimum:          f = ymin; break;
00474         case ymaximum:          f = ymax; break;
00475         case basepointsize:     f = base_point_size; break;
00476         case pointscalemode:    i = point_scale_mode; break;
00477         case lmax3D:            f = 2*lmax3d; break;
00478         case theta3D:           f = theta; break;
00479         case phi3D:             f = phi; break;
00480         case DelayTime:         f = delay_time; break;
00481         case dtheta3D:          f = dtheta; break;
00482         case Xorigin:           f = origin[0]; break;
00483         case Yorigin:           f = origin[0]; break;
00484         case Zorigin:           f = origin[0]; break;
00485         case view2D:            i = kproj; break;
00486         case originstar:        i = origin_star; break;
00487         default:                cerr << "xstarplot: diag error...\n";
00488     }
00489 
00490     if (f < 1.e30)
00491         sprintf(temp_buffer, "%f", f);
00492     else if (c == -1)
00493         sprintf(temp_buffer, " %d ", i);
00494     else
00495         temp_buffer[0] = c;
00496 }
00497 
00498 local void set_diag_item(int which, char* id, int label_on_left,
00499                          int x1, int x2, int y)
00500 {
00501     set_temp_buffer(which);
00502 
00503     if (label_on_left) {        // label to left of (real) input box
00504 
00505         lux_set_item(dia, which, TEXT_WINDOW, NO_TYPE,
00506                      _R_(x1), _R_(y), strlen(id), id);
00507         lux_set_item(dia, which, INPUT_WINDOW, NO_TYPE,
00508                      _R_(x2), _R_(y), 10, temp_buffer);
00509 
00510     } else {                    // label to right of (integer) input box/button
00511 
00512         if (type(which) == INPUT_WINDOW) {
00513 
00514             lux_set_item(dia, which, INPUT_WINDOW, NO_TYPE,
00515                          _R_(x1), _R_(y), 3, temp_buffer);
00516             lux_set_item(dia, which, TEXT_WINDOW, NO_TYPE,
00517                          _R_(x2), _R_(y), strlen(id), id);
00518 
00519         } else {
00520 
00521             lux_set_item(dia, which, BUTTON_WINDOW, CHECK_BUTTON,
00522                          _R_(x1), _R_(y), 1, temp_buffer);
00523             lux_set_item(dia, which, TEXT_WINDOW, CHECK_BUTTON,
00524                          _R_(x2), _R_(y), strlen(id), id);
00525         }
00526     }
00527 }
00528 
00529 local void initialize_dialog(int xorigin, int yorigin)
00530 {
00531     // Initialize dialog box material (note: y is measured up from bottom!)
00532 
00533     float save = r_factor;
00534     if (r_factor > 1) r_factor = 1;
00535 
00536     int xsize = 550;
00537     int ysize = 550;
00538     if (r_factor <= 0.6) xsize = (int) (xsize / (r_factor/0.6));
00539     dia = lux_open_dialog(xorigin, yorigin, _R_(xsize), _R_(ysize));
00540 
00541     // ---------- 3-D origin info across top of box (special case): ----------
00542 
00543      lux_set_item(dia, Origin, TEXT_WINDOW, NO_TYPE,
00544                  _R_(70), _R_(500), 6, "origin");
00545 
00546     sprintf(temp_buffer, "%f", origin[0]);
00547     lux_set_item(dia, Xorigin, INPUT_WINDOW, NO_TYPE,
00548                  _R_(160), _R_(500), 10, temp_buffer);
00549 
00550     sprintf(temp_buffer, "%f", origin[1]);
00551     lux_set_item(dia, Yorigin, INPUT_WINDOW, NO_TYPE,
00552                  _R_(280), _R_(500), 10, temp_buffer);
00553 
00554     sprintf(temp_buffer, "%f", origin[2]);
00555     lux_set_item(dia, Zorigin, INPUT_WINDOW, NO_TYPE,
00556                  _R_(400), _R_(500), 10, temp_buffer);
00557 
00558 
00559     // ---------- Left-hand column of dialog box: ----------
00560 
00561     //          xmin
00562     //          xmax
00563     //          ymin
00564     //          ymax
00565     //          3-D cube size
00566     //          projection theta
00567     //          projection phi
00568     //          projection dtheta
00569     //          point scale
00570     //          delay time
00571 
00572     // Minima and maxima of 2-D display:
00573 
00574     set_diag_item(xminimum, "xmin", 1, 70, 160, 460);
00575     set_diag_item(xmaximum, "xmax", 1, 70, 160, 420);
00576     set_diag_item(yminimum, "ymin", 1, 70, 160, 380);
00577     set_diag_item(ymaximum, "ymax", 1, 70, 160, 340);
00578 
00579     // 3-D cube size:
00580 
00581     set_diag_item(lmax3D, "cube size", 1, 70, 180, 300);
00582 
00583     // 3-D projection direction:
00584 
00585     set_diag_item(theta3D,  "theta",  1, 70, 180, 260);
00586     set_diag_item(phi3D,    "phi",    1, 70, 180, 220);
00587     set_diag_item(dtheta3D, "dtheta", 1, 70, 180, 180);
00588 
00589     // Point size:
00590 
00591     set_diag_item(basepointsize, "point scale", 1, 70, 180, 140);
00592 
00593     // Delay time:
00594 
00595     set_diag_item(DelayTime, "delay time", 1, 70, 180, 100);
00596 
00597 
00598     // ---------- Right-hand column of dialog box: ----------
00599 
00600     //          origin star
00601     //          2-D view axis
00602     //          3-D plot?
00603 
00604     //          point display mode
00605     //          color by energy?
00606     //          track particles?
00607 
00608     // Origin star:
00609 
00610     set_diag_item(originstar, "Origin Star", 0, 320, 360, 460);
00611 
00612     // 2-D view axis:
00613 
00614     set_diag_item(view2D, "2-D view axis", 0, 320, 360, 420);
00615 
00616     // 3D graphics:
00617 
00618     set_diag_item(graph3dim, "3-D graph", 0, 320, 350, 380);
00619 
00620     // Point display mode
00621 
00622     set_diag_item(pointscalemode, "point display mode", 0, 320, 360, 300);
00623 
00624     // Color by energy:
00625 
00626     set_diag_item(colorenergy, "color by energy", 0, 320, 350, 260);
00627 
00628     // Track particles:
00629 
00630     set_diag_item(tracking, "track particles", 0, 320, 350, 220);
00631 
00632     // lux_draw_palette(dia);
00633 
00634     // OK/cancel:
00635 
00636     lux_set_item(dia, ok, BUTTON_WINDOW, OK_BUTTON,
00637                  _R_(100), _R_(25), 9, "OK, CLEAR");
00638     lux_set_item(dia, ok_keep, BUTTON_WINDOW, OK_KEEP_BUTTON,
00639                  _R_(250), _R_(25), 8, "OK, KEEP");
00640     lux_set_item(dia, cancel, BUTTON_WINDOW, CANCEL_BUTTON,
00641                  _R_(400), _R_(25), 6, "CANCEL");
00642 
00643     r_factor = save;
00644 }
00645 
00646 local void make_relative_to_root(hdyn* b)
00647 {
00648     vector root_pos = b->get_pos();
00649     vector root_vel = b->get_vel();
00650     for_all_nodes(hdyn, b, bi) {
00651         bi->inc_pos(-root_pos);
00652         bi->inc_vel(-root_vel);
00653     }
00654 }
00655 
00656 local void update_diag_item(int which)
00657 {
00658     set_temp_buffer(which);
00659     lux_update_itemvalue(dia, which, type(which), subtype(which),
00660                          temp_buffer);
00661 }
00662 
00663 local void get_diag_string(int which) {
00664 }
00665 
00666 // Overloaded function:
00667 
00668 local void read_diag_item(int which, float& f)
00669 {
00670     lux_get_itemvalue(dia, which, type(which), subtype(which),
00671                       temp_buffer);
00672     sscanf(temp_buffer, "%f", &f);
00673 }
00674 
00675 local void read_diag_item(int which, int& i)
00676 {
00677     lux_get_itemvalue(dia, which, type(which), subtype(which),
00678                       temp_buffer);
00679     sscanf(temp_buffer, "%d", &i);
00680 }
00681 
00682 local void read_diag_item(int which, char& c)
00683 {
00684     lux_get_itemvalue(dia, which, type(which), subtype(which),
00685                       temp_buffer);
00686     c = temp_buffer[0];
00687 }
00688 
00689 local void update_from_dialog(bool r_flag)
00690 {
00691     // Read all data from the dialog box.  Note that it is
00692     // important that the box be maintained correctly.
00693     // Any errors in the data displayed in the box will be
00694     // propogated to the "real" data by this procedure.
00695 
00696     read_diag_item(view2D, kproj);
00697     if (kproj == 1)
00698         kx = 1, ky = 2;
00699     else if (kproj == 2)
00700         kx = 2, ky = 0;
00701     else
00702         kx = 0, ky = 1;
00703 
00704     read_diag_item(originstar, origin_star);
00705 
00706     read_diag_item(Xorigin, origin[0]);
00707     read_diag_item(Yorigin, origin[1]);
00708     read_diag_item(Zorigin, origin[2]);
00709 
00710     read_diag_item(lmax3D, lmax3d);
00711     lmax3d /= 2;                        // display twice lmax3d
00712 
00713     // ------------------------------------------------------
00714 
00715     // NOTE: xmin, xmax, ymin, ymax are IRRELEVANT, since they
00716     // will be forced to be consistent with origin and lmax3d.
00717 
00718     read_diag_item(xminimum, xmin);
00719     read_diag_item(xmaximum, xmax);
00720     read_diag_item(yminimum, ymin);
00721     read_diag_item(ymaximum, ymax);
00722 
00723     set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
00724 
00725     // Make sure entries in the dialog box are consistent:
00726 
00727     update_diag_item(xminimum);
00728     update_diag_item(xmaximum);
00729     update_diag_item(yminimum);
00730     update_diag_item(ymaximum);
00731 
00732     // ------------------------------------------------------
00733 
00734     read_diag_item(basepointsize,base_point_size);
00735 
00736     read_diag_item(theta3D, theta);
00737     costheta = cos(theta);
00738     sintheta = sin(theta);
00739 
00740     read_diag_item(phi3D, phi);
00741     cosphi = cos(phi);
00742     sinphi = sin(phi);
00743 
00744     read_diag_item(dtheta3D, dtheta);
00745 
00746     read_diag_item(DelayTime, delay_time);
00747     if (delay_time < MIN_DELAY) delay_time = MIN_DELAY;
00748 
00749     read_diag_item(colorenergy, cenergy);
00750     show_color_scheme(colwin, c_energy, c_index,
00751                       r_factor, cenergy, r_flag, 1);
00752 
00753     read_diag_item(tracking, track);
00754     read_diag_item(graph3dim, graph3d);
00755 
00756     lux_clear_window(win);
00757 
00758     if (graph3d) {
00759         lux_setup_axis(win, -FAC3D*lmax3d, FAC3D*lmax3d, 
00760                             -FAC3D*lmax3d, FAC3D*lmax3d);
00761         draw3d_axis(win, lmax3d, costheta, sintheta,
00762                     cosphi, sinphi);
00763     } else {
00764         lux_setup_axis(win, xmin, xmax, ymin, ymax);
00765         draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
00766     }
00767 
00768     read_diag_item(pointscalemode, point_scale_mode);
00769 }
00770 
00771 local void show_static_rotation(hdyn* b, bool f_flag)
00772 {
00773     // Handle static rotation using lux_check_keypress:
00774 
00775     show_instructions(instr, r_factor,
00776                       "Pause...\n  r: rotate, (p,c): continue                ",
00777                       1);
00778 
00779     char rotate = 0;
00780     do {
00781         if (lux_check_keypress(win,'r')) {
00782             show_instructions(instr, r_factor,
00783                       "Rotate... p: pause, c: continue, c: exit rotation     ",
00784                               0);
00785             rotate = 1;
00786 
00787             do {
00788                 theta += dtheta;
00789                 if (theta < 0.0)
00790                     theta += 2*PI;
00791                 else if (theta > PI*2)
00792                     theta -= 2*PI;
00793                 costheta = cos(theta);
00794                 sintheta = sin(theta);
00795                 update_diag_item(theta3D);
00796 
00797                 lux_clear_current_region(win);
00798                 draw3d_axis(win, lmax3d, costheta, sintheta,
00799                             cosphi, sinphi);
00800 
00801                 for_all_leaves(hdyn, b, bi) {
00802 
00803                     float X = (float)bi->get_pos()[0] - origin[0];
00804                     float Y = (float)bi->get_pos()[1] - origin[1];
00805                     float Z = (float)bi->get_pos()[2] - origin[2];
00806 
00807                     float actual_point_size = get_point_size(bi);
00808 
00809                     if (   (X > (-lmax3d + actual_point_size))
00810                         && (X < ( lmax3d - actual_point_size)) 
00811                         && (Y > (-lmax3d + actual_point_size))
00812                         && (Y < ( lmax3d - actual_point_size)) 
00813                         && (Z > (-lmax3d + actual_point_size))
00814                         && (Z < ( lmax3d - actual_point_size))){
00815 
00816                         float r, s;
00817                         project3d(X, Y, Z, r, s,
00818                                   costheta, sintheta,
00819                                   cosphi, sinphi);
00820 
00821                         if (cenergy) {
00822                             char c;
00823                             compute_energies(b, bi, c);
00824                             lux_set_color(win,c_energy[c]);
00825                         } else if (clean_index(bi)>0) {
00826                             if (clean_index(bi) <= N_COLORS)
00827                                 lux_set_color(win,
00828                                               c_index[clean_index(bi)]);
00829                             else
00830                                 lux_set_color(win,c_index[1]);
00831                         }
00832 
00833                         if (track) 
00834                             lux_draw_pointf(win,r,s);
00835                         else
00836                             if (f_flag)
00837                                 lux_fill_arcf(win,
00838                                               r - actual_point_size/2,
00839                                               s - actual_point_size/2, 
00840                                               actual_point_size,
00841                                               actual_point_size,
00842                                               0.0, 360.0);
00843                             else
00844                                 lux_draw_arcf(win,
00845                                               r - actual_point_size/2,
00846                                               s - actual_point_size/2, 
00847                                               actual_point_size,
00848                                               actual_point_size,
00849                                               0.0, 360.0);
00850                     }
00851                 }
00852                 update_with_delay(win, max(MIN_DELAY, delay_time));
00853 
00854                 if (lux_check_keypress(win,'p')) 
00855                     while(!lux_check_keypress(win,'c'));
00856 
00857             } while(!lux_check_keypress(win,'c'));
00858 
00859             // Flush "c"s from input stream:
00860 
00861             while(lux_check_keypress(win,'c'));
00862         }
00863 
00864     } while(!lux_check_keypress(win,'p')
00865             && !lux_check_keypress(win,'c') && !rotate);
00866 
00867     rotate = 0;
00868     lux_set_color(win,c_energy[default_color]);
00869 }
00870 
00871 local char check_for_input(unsigned long win, hdyn* b,
00872                            bool r_flag, bool f_flag, bool eod)
00873 {
00874     // Check for (and immediately act upon) interactive input.
00875     // Loop through the input buffer until no more events remain.
00876 
00877     // lux_next_keypress gets and discards the next key in the input stream.
00878 
00879     char key, string[20], shift, control;
00880     bool key_pressed = false;
00881 
00882     while (lux_next_keypress(win, &key, string, &shift, &control)) {
00883 
00884         // A "defined" key has been pressed.  See if it is one we want.
00885 
00886         key_pressed = true;
00887 
00888         if (key == 0                    // key = 0 for non-ASCII character
00889                                         // e.g. Up, Down, Home, etc.--see win.c
00890             || key == 'h'
00891             || key == 'a') {
00892 
00893             // "Shift" functions:
00894 
00895             int change = 0;
00896 
00897             if (key == 'h')             // keyboard lookalikes for
00898                 change = 4;             // function keys
00899             else if (key == 'a')
00900                 change = 5;
00901 
00902             else if (strcmp(string, "Up") == 0) {
00903                 change = ky + 1;
00904                 origin[ky] += lmax3d/2;
00905             } else if (strcmp(string, "Down") == 0) {
00906                 change = ky + 1;
00907                 origin[ky] -= lmax3d/2;
00908             } else if (strcmp(string, "Right") == 0) {
00909                 change = kx + 1;
00910                 origin[kx] += lmax3d/2;
00911             } else if (strcmp(string, "Left") == 0) {
00912                 change = kx + 1;
00913                 origin[kx] -= lmax3d/2;
00914             } else if (strcmp(string, "PgUp") == 0) {
00915                 change = kproj;
00916                 origin[kproj-1] += lmax3d/2;
00917             } else if (strcmp(string, "PgDn") == 0) {
00918                 change = kproj;
00919                 origin[kproj-1] -= lmax3d/2;
00920             } else if (strcmp(string, "Home") == 0)
00921                 change = 4;
00922             else if (strcmp(string, "R11") == 0)
00923                 change = 5;
00924 
00925             if (change) {
00926 
00927                 if (change == 4) {
00928                     origin[kx] = origin[ky] = origin[kproj-1] = 0;
00929                 } else if (change == 5) {
00930 
00931                     real save = lmax3d;
00932                     lmax3d = 0;
00933 
00934                     // Use all dimensions in redetermining the scale!
00935 
00936                     for_all_leaves(hdyn, b, bi)
00937                         for (int kk = 0; kk < 3; kk++)
00938                             lmax3d = max(lmax3d, abs(bi->get_pos()[kk]
00939                                                      - local_offset[kk]));
00940                 
00941                     // Round lmax3d up to something reasonable:
00942                 
00943                     lmax3d *= 1.2;
00944                     if (lmax3d <= 0) lmax3d = 1;
00945                 
00946                     real m_log = log10(lmax3d);
00947                     int i_log = (int) m_log;
00948                     if (m_log - i_log > 0.699) i_log++;
00949                     real scale = pow(10.0, i_log);
00950                     lmax3d = ((int) (lmax3d/scale) + 1) * scale;
00951 
00952                     origin[kx] = origin[ky] = origin[kproj-1] = 0;              
00953                     base_point_size *= lmax3d/save;
00954                 }
00955 
00956                 set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
00957 
00958                 // Update all entries in the dialog box, as needed:
00959 
00960                 update_diag_item(xminimum);
00961                 update_diag_item(xmaximum);
00962                 update_diag_item(yminimum);
00963                 update_diag_item(ymaximum);
00964 
00965                 if (change == 1 || change >= 4) update_diag_item(Xorigin);
00966                 if (change == 2 || change >= 4) update_diag_item(Yorigin);
00967                 if (change == 3 || change >= 4) update_diag_item(Zorigin);
00968 
00969                 if (change == 5) {
00970                     update_diag_item(basepointsize);
00971                     update_diag_item(lmax3D);
00972                 }
00973 
00974                 // No redrawing of axes is needed for 3D graphs for change != 5.
00975                 
00976                 if (!graph3d) {
00977                     lux_clear_window(win);
00978                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
00979                     draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
00980                 } else if (change == 5) {
00981                     lux_clear_window(win);
00982                     lux_setup_axis(win, -FAC3D*lmax3d, FAC3D*lmax3d, 
00983                                    -FAC3D*lmax3d, FAC3D*lmax3d);
00984                     draw3d_axis(win, lmax3d, costheta, sintheta,
00985                                 cosphi, sinphi);
00986                 }
00987             }
00988 
00989         } else {                        // key is the ASCII code
00990 
00991             // Check for "quit" first.
00992 
00993             if (key == 'q') {
00994                 show_instructions(instr, r_factor,
00995                     "\n   Quitting...                                        ",
00996                                   1);
00997                 lux_exit();             // note that this is now quick_exit
00998             }
00999 
01000             //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
01001 
01002             if (graph3d && !track) {
01003                 int button;
01004 
01005                 // 3-D operations:
01006 
01007                 if (key== 'R') {
01008 
01009                     show_static_rotation(b, f_flag);
01010 
01011                 } else {
01012 
01013                     button = lux_check_buttonpress(win);
01014 
01015                     if (key == '^') {
01016                         phi = phi - dtheta;
01017                         if (phi < -PI) phi = phi + 2.0*PI;
01018                         cosphi = cos(phi);
01019                         sinphi = sin(phi);
01020                         update_diag_item(phi3D);
01021                     } else if (key == 'V') {
01022                         phi = phi + dtheta;
01023                         if (phi > PI) phi = phi - 2.0*PI;
01024                         cosphi = cos(phi);
01025                         sinphi = sin(phi);
01026                         update_diag_item(phi3D);
01027                     } else if (key == '<') {
01028                         theta = theta + dtheta;
01029                         if (theta > 2*PI) theta -= 2*PI;
01030                         costheta = cos(theta);
01031                         sintheta = sin(theta);
01032                         update_diag_item(theta3D);
01033                     } else if (key == '>') {
01034                         theta = theta - dtheta;
01035                         if (theta < 0.0) theta += 2*PI;
01036                         costheta = cos(theta);
01037                         sintheta = sin(theta);
01038                         update_diag_item(theta3D);
01039                     }
01040                 }
01041             }
01042 
01043             //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
01044 
01045             if (key == 'p' || key == 'P') {     // modify base point size
01046 
01047                 if (key == 'p') {
01048                     if (base_point_size > 4*lmax3d/win_size)
01049                         base_point_size /= PFAC;
01050                 } else
01051                     base_point_size *= PFAC;
01052 
01053                 update_diag_item(basepointsize);
01054 
01055             } else if (key == 'm') {            // toggle multiple display
01056 
01057                 multiples = 1 - multiples;
01058                 if (multiples == 1) nodes = 1;
01059 
01060             } else if (key == 'n') {            // toggle tree display
01061 
01062                 nodes = 1 - nodes;
01063                 if (nodes == 0) links = 0;
01064 
01065             } else if (key == 'l') {            // toggle links/nodes
01066 
01067                 links = 1 - links;
01068                 if (links == 1) nodes = 1;
01069 
01070             } else if (key == 'r') {            // show root node
01071 
01072                 root = 1 - root;
01073 
01074             } else if (key == 't') {            // toggle tracking
01075 
01076                 track = 1 - track;
01077                 update_diag_item(tracking);
01078 
01079             } else if (key == 'u') {            // toggle unperturbed display
01080 
01081                 unperturbed = 1 - unperturbed;
01082 
01083             } else if (key == '3' && !graph3d) {    // enter 3D mode
01084 
01085                 graph3d = 1;
01086                 update_diag_item(graph3dim);
01087                 lux_clear_window(win);
01088                 lux_setup_axis(win, -FAC3D*lmax3d, FAC3D*lmax3d, 
01089                                -FAC3D*lmax3d, FAC3D*lmax3d);
01090                 draw3d_axis(win, lmax3d, costheta, sintheta, cosphi, sinphi);
01091 
01092                 // Refresh the color window.
01093 
01094 //              show_color_scheme(colwin, c_energy, c_index,
01095 //                                r_factor, cenergy, r_flag, 1);
01096 
01097             } else if (graph3d &&
01098                        (key == '2' || key == 'x'
01099                           || key == 'y' || key == 'k')) {   // enter 2D mode
01100 
01101                 graph3d = 0;
01102                 update_diag_item(graph3dim);
01103                 lux_clear_window(win);
01104                 lux_setup_axis(win, xmin, xmax, ymin, ymax);
01105                 draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
01106 
01107                 // Refresh the color window.
01108 
01109 //              show_color_scheme(colwin, c_energy, c_index,
01110 //                                r_factor, cenergy, r_flag, 1);
01111 
01112             } else if (key == 'e') {            // color by energy
01113 
01114                 cenergy = !cenergy;
01115                 update_diag_item(colorenergy);
01116                 show_color_scheme(colwin, c_energy, c_index,
01117                                   r_factor, cenergy, r_flag, 1);
01118 
01119             } else if (key == '+' || key == '=') {    // increase delay time
01120 
01121                 delay_time *= 2;
01122                 update_diag_item(DelayTime);
01123 
01124             } else if (key == '-') {            // decrease delay time
01125 
01126                 delay_time /= 2;
01127                 if (delay_time < MIN_DELAY) delay_time = MIN_DELAY;
01128                 update_diag_item(DelayTime);
01129 
01130             } else if (key == '0') {            // set delay time = "0"
01131 
01132                 delay_time = MIN_DELAY;
01133                 update_diag_item(DelayTime);
01134 
01135                 // Flush the queue:
01136 
01137                 while(lux_check_keypress(win,'+')
01138                       || lux_check_keypress(win,'-'));
01139 
01140             } else if (key == 'R') {            // color by energy
01141 
01142                 show_color_scheme(colwin, c_energy, c_index,
01143                                   r_factor, cenergy, r_flag, 1);
01144 
01145             } else if (key == 'z') {            // zoom in
01146                                                 // (fixed axes and origin)
01147 
01148                 lmax3d /= ZOOM;
01149                 set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01150                 base_point_size /= ZOOM;
01151 
01152                 if (graph3d) {
01153                     lux_clear_window(win);
01154                     lux_setup_axis(win,-FAC3D*lmax3d,FAC3D*lmax3d, 
01155                                    -FAC3D*lmax3d, FAC3D*lmax3d);
01156                     draw3d_axis(win, lmax3d, costheta, sintheta,
01157                                 cosphi, sinphi);
01158                 } else {
01159                     lux_clear_window(win);
01160                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01161                     draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
01162                 }
01163 
01164                 update_diag_item(basepointsize);
01165                 update_diag_item(lmax3D);
01166                 update_diag_item(xminimum);
01167                 update_diag_item(xmaximum);
01168                 update_diag_item(yminimum);
01169                 update_diag_item(ymaximum);
01170 
01171             } else if (key == 'Z') {            // zoom out
01172 
01173                 lmax3d *= ZOOM;
01174                 set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01175                 base_point_size *= ZOOM;
01176 
01177                 if (graph3d) {
01178                     lux_clear_window(win);
01179                     lux_setup_axis(win, -FAC3D*lmax3d, FAC3D*lmax3d, 
01180                                    -FAC3D*lmax3d, FAC3D*lmax3d);
01181                     draw3d_axis(win, lmax3d, costheta, sintheta,
01182                                 cosphi, sinphi);
01183                 } else {
01184                     lux_clear_window(win);
01185                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01186                     draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
01187                 }
01188 
01189                 update_diag_item(basepointsize);
01190                 update_diag_item(lmax3D);
01191                 update_diag_item(xminimum);
01192                 update_diag_item(xmaximum);
01193                 update_diag_item(yminimum);
01194                 update_diag_item(ymaximum);
01195 
01196             } else if (key == 'k') {            // change projection axis to z
01197                                                 // (fixed origin, scale)
01198                 if (graph3d) {
01199 
01200                     theta = -PI/2;
01201                     phi = PI/2.0;
01202                     costheta = cos(theta);
01203                     sintheta = sin(theta);
01204                     cosphi = cos(phi);
01205                     sinphi = sin(phi);
01206 
01207                     update_diag_item(theta3D);
01208                     update_diag_item(phi3D);
01209 
01210                     while (lux_check_keypress(win,'<')
01211                            || lux_check_keypress(win,'>')
01212                            || lux_check_keypress(win,'^')
01213                            || lux_check_keypress(win,'V') );
01214 
01215                 } else {
01216 
01217                     kproj = 3;
01218                     kx = 0;
01219                     ky = 1;
01220                     set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01221                     lux_clear_window(win);
01222                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01223                     draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
01224 
01225                     update_diag_item(view2D);
01226 
01227                 }
01228 
01229             } else if (key == 'y') {            // change projection axis to y
01230 
01231                 if (graph3d) {
01232 
01233                     theta = -PI/2.0;
01234                     phi = 0.0;
01235                     costheta = cos(theta);
01236                     sintheta = sin(theta);
01237                     cosphi = cos(phi);
01238                     sinphi = sin(phi);
01239 
01240                     while (lux_check_keypress(win,'<')
01241                            || lux_check_keypress(win,'>')
01242                            || lux_check_keypress(win,'^')
01243                            || lux_check_keypress(win,'V') );
01244 
01245                     update_diag_item(theta3D);
01246                     update_diag_item(phi3D);
01247 
01248                 } else {
01249 
01250                     kproj = 2;
01251                     kx = 2;
01252                     ky = 0;
01253                     set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01254                     lux_clear_window(win);
01255                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01256                     draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
01257 
01258                     update_diag_item(view2D);
01259 
01260                 }
01261 
01262             } else if (key == 'x') {            // change projection axis to x
01263 
01264                 if (graph3d) {
01265                     theta = 0.0;
01266                     phi = 0.0;
01267                     costheta = cos(theta);
01268                     sintheta = sin(theta);
01269                     cosphi = cos(phi);
01270                     sinphi = sin(phi);
01271 
01272                     while (lux_check_keypress(win,'<')
01273                            || lux_check_keypress(win,'>')
01274                            || lux_check_keypress(win,'^')
01275                            || lux_check_keypress(win,'V') );
01276 
01277                     update_diag_item(theta3D);
01278                     update_diag_item(phi3D);
01279 
01280                 } else {
01281 
01282                     kproj = 1;
01283                     kx = 1;
01284                     ky = 2;
01285                     set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01286                     lux_clear_window(win);
01287                     lux_setup_axis(win, xmin, xmax, ymin, ymax);
01288                     draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
01289 
01290                     update_diag_item(view2D);
01291 
01292                 }
01293             }
01294 
01295             // Select new origin: 'o' ==> point in space, 'O' ==> star
01296 
01297             if (key == 'o' && !graph3d) {
01298 
01299                 show_instructions(instr, r_factor,
01300                 " Use mouse-right to select new origin...\n",1);
01301                 float r, s;
01302                 get_mouse_position(win, &r, &s);
01303 
01304                 // Looks like r and s come back in the correct units!
01305 
01306                 origin[kx] = r;
01307                 origin[ky] = s;
01308                 set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01309 
01310                 lux_clear_window(win);
01311                 lux_setup_axis(win, xmin, xmax, ymin, ymax);
01312                 draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
01313 
01314                 origin_star = -1;
01315 
01316                 update_diag_item(Xorigin);
01317                 update_diag_item(Yorigin);
01318                 update_diag_item(Zorigin);
01319                 update_diag_item(xminimum);
01320                 update_diag_item(xmaximum);
01321                 update_diag_item(yminimum);
01322                 update_diag_item(ymaximum);
01323                 update_diag_item(originstar);
01324 
01325             } else if (!graph3d && key == 'O') {
01326 
01327                 show_instructions(instr, r_factor,
01328                 " Use mouse-right to select new origin star...\n",1);
01329                 float r, s;
01330                 get_mouse_position(win, &r, &s);
01331 
01332                 // Looks like r and s come back in the correct units!
01333 
01334                 // Find the star closest to the (2-D) mouse position.
01335 
01336                 origin_star = nearest_index(b, r, s, kx, ky);
01337 
01338                 if (origin_star > 0) {
01339                     for (int kk = 0; kk < 3; kk++) origin[kk] = 0;
01340                     set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01341                 }
01342 
01343                 lux_clear_window(win);
01344                 lux_setup_axis(win, xmin, xmax, ymin, ymax);
01345                 draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
01346 
01347                 update_diag_item(Xorigin);
01348                 update_diag_item(Yorigin);
01349                 update_diag_item(Zorigin);
01350                 update_diag_item(xminimum);
01351                 update_diag_item(xmaximum);
01352                 update_diag_item(yminimum);
01353                 update_diag_item(ymaximum);
01354                 update_diag_item(originstar);
01355 
01356             } else if (key == 'b' || key == 'B') {
01357 
01358                 return 'b';
01359 
01360             } else if (key == 'c' || key == 'C') {
01361 
01362                 return 'c';
01363 
01364             } else if (key == 'f' || key == 'F' || key == 's' || key == 'S') {
01365 
01366                 return 'f';
01367 
01368             }
01369 
01370             // -------------------------------------------------------------
01371 
01372             while(lux_check_keypress(win,'r'));  // clean up any replay garbage
01373 
01374             // Idle mode and dialog box input:
01375 
01376             int return_value = 0;
01377 
01378             if (key == 'i') {
01379 
01380                 show_instructions(instr, r_factor,
01381                   " Idle...\n  d: dialog, r: replay, c: continue, q: quit",1);
01382                 return_value = lux_getevent();
01383 
01384             } else if (key == 'd') {
01385 
01386                 show_instructions(instr, r_factor,
01387 "Dialog mode keyboard options\n\n\
01388   Dialog window:\n\
01389     o   OK, keep dialog window\n\
01390     O   OK, close dialog window\n\
01391     c   CANCEL, keep dialog window\n\
01392     C   CANCEL, close dialog window\n\n\
01393   Other windows:\n\
01394     r   replay\n\
01395     c   continue (keep dialog window,\n\
01396                   ignore dialog changes)\n\
01397     q   quit\n\
01398 ",1);
01399                 lux_show_dialog(dia);
01400                 return_value = lux_getevent();
01401             }
01402             
01403             // Update all values if OK button was clicked (clicking
01404             // OK forces a return value of 3).
01405             
01406             if (return_value == 3) update_from_dialog(r_flag);
01407 
01408         }
01409     }
01410 
01411     if (key_pressed) {
01412 
01413         // Hitting any key will cause the instruction and color
01414         // windows to be updated immediately.
01415 
01416         show_main_instructions(instr, r_factor, graph3d, 1, eod,
01417                                nodes, links, multiples, unperturbed, root);
01418         show_color_scheme(colwin, c_energy, c_index,
01419                           r_factor, cenergy, r_flag, 1);
01420 
01421         return ' ';
01422     }
01423 
01424     return 0;
01425 }
01426 
01427 /*-----------------------------------------------------------------------------
01428  *  xstarplot.C  --  project the positions of all particles onto the screen
01429  *                   input:   pn: a pointer to a nbody system,
01430  *                              k: the number of the coordinate axis along which
01431  *                                 the projection is directed, with {k,x,y}
01432  *                                 having a right-handed orientation,
01433  *                           xmax: displayed x-axis spans [-xmax, xmax]
01434  *                           ymax: displayed y-axis spans [-ymax, ymax]
01435  *-----------------------------------------------------------------------------
01436  */
01437 
01438 #define INSTR_FREQ_MAX 32
01439 #define INSTR_FREQ_FAC 64
01440 static int instr_freq = INSTR_FREQ_MAX;
01441 static int count_instr = 0;
01442 
01443 void xstarplot(hdyn* b, float scale, int k, int d, float lmax,
01444                int point_mode, float rel_point_size,
01445                float D, int ce,
01446                bool r_flag, bool f_flag, bool t_flag,
01447                int init_flag, int& step_mode, bool eod)
01448 {
01449     r_factor = scale;
01450 
01451     if (!eod && init_flag == 0) {
01452 
01453         int xorigin, yorigin;
01454 
01455         if (t_flag) nodes = links = 1;
01456 
01457         // Open windows for plotting and instructions, set up color
01458         // schemes, etc.
01459 
01460         if (init_status == 0) initialize_graphics(r_factor, r_flag,
01461                                                   win, instr, colwin,
01462                                                   c_index, c_energy,
01463                                                   win_size, xorigin, yorigin);
01464         lux_clear_window(win);
01465         lux_update_fg(win);
01466         lux_clear_window(colwin);
01467         lux_update_fg(colwin);
01468         lux_clear_window(instr);
01469         lux_update_fg(instr);
01470 
01471         // Determine which axes to plot:
01472 
01473         kproj = k;
01474         switch (kproj) {
01475             case 1:     kx = 1; ky = 2; graph3d = 0; break;
01476             case 2:     kx = 2; ky = 0; graph3d = 0; break;
01477             case 3:     kx = 0; ky = 1; graph3d = 0; break;
01478             default:    cerr << "xstarplot: k = " << k
01479                              << ": illegal value; choose from {1, 2, 3}"
01480                              << endl;
01481                         exit(0);
01482         }
01483 
01484         switch(d) {
01485             case 2:     graph3d = 0;  break;
01486             case 3:     graph3d = 1;  break;
01487             default:    cerr << "xstarplot: d = " << d
01488                              << " illegal value; choose from {2, 3)"
01489                              << endl;
01490                         exit(0);
01491         }
01492 
01493         point_scale_mode = point_mode;
01494 
01495         cenergy = ce?1:0;
01496         show_color_scheme(colwin, c_energy, c_index,
01497                           r_factor, cenergy, r_flag, 1);
01498 
01499         delay_time = D;
01500 
01501         if (lmax > 0.0)
01502 
01503             lmax3d = lmax;
01504 
01505         else {
01506 
01507             lmax3d = 0;
01508 
01509             // Use all dimensions in determining the initial scale!
01510 
01511             for_all_leaves(hdyn, b, bi)
01512                 for (int kk = 0; kk < 3; kk++)
01513                     lmax3d = max(lmax3d, abs(bi->get_pos()[kk]));
01514 
01515             // Round lmax3d up to something reasonable:
01516 
01517             lmax3d *= 1.2;
01518             if (lmax3d <= 0) lmax3d = 1;
01519 
01520             real m_log = log10(lmax3d);
01521             int i_log = (int) m_log;
01522             if (m_log - i_log > 0.699) i_log++;
01523             real scale = pow(10.0, i_log);
01524             lmax3d = ((int) (lmax3d/scale) + 1) * scale;
01525         }
01526 
01527         for (int ko = 0; ko < 3; ko++)
01528             origin[ko] = 0;
01529 
01530         set_limits(origin, lmax3d, kx, xmin, xmax, ky, ymin, ymax);
01531         set_base_point_size(b, rel_point_size);
01532         
01533         if (graph3d) {
01534             lux_setup_axis(win, -FAC3D*lmax3d, FAC3D*lmax3d, 
01535                            -FAC3D*lmax3d, FAC3D*lmax3d);      
01536             draw3d_axis(win, lmax3d, costheta, sintheta, cosphi, sinphi);
01537         } else {
01538             lux_setup_axis(win, xmin, xmax, ymin, ymax);
01539             draw2d_axis(win, xmin, xmax, ymin, ymax, kproj);
01540         }
01541 
01542         // Complete the initialization with the dialog box.
01543 
01544         if (init_status == 0)
01545             initialize_dialog(xorigin, yorigin);
01546 
01547         init_status = 1;
01548             
01549     }
01550 
01551     //------------------------------------------------------------------------
01552 
01553     // End of initialization or start of next plot.
01554     // Delete current points, and possibly redraw axes and instructions.
01555 
01556     if (track == 0) {
01557         lux_clear_current_region(win);
01558         if (graph3d) draw3d_axis(win, lmax3d, costheta, sintheta,
01559                                  cosphi, sinphi);
01560     }
01561 
01562     if (!eod) {
01563 
01564         // Showing these instructions too frequently causes malloc problems
01565         // in lux_draw_image_string (for unknown reasons; possibly this is
01566         // a timing problem of some sort with the X display).
01567         //
01568         // Work around the problem by reducing the display frequency.
01569         // See also gfx_util for further limitations.
01570 
01571         instr_freq = INSTR_FREQ_FAC / b->n_leaves();
01572         if (instr_freq > INSTR_FREQ_MAX) instr_freq = INSTR_FREQ_MAX;
01573         if (instr_freq < 1) instr_freq = 1;
01574 
01575         if (count_instr++%instr_freq == 0)
01576             show_main_instructions(instr, r_factor, graph3d, 1, eod,
01577                                    nodes, links, multiples, unperturbed, root);
01578     }
01579 
01580     //------------------------------------------------------------------------
01581 
01582     // Always express all positions and velocities relative to the root node.
01583     // (There is no requirement that the root node be at rest at the origin...)
01584 
01585     make_relative_to_root(b);
01586 
01587     // Determine local offset, if any.
01588 
01589     if (origin_star > 0) {
01590         for_all_leaves(hdyn, b, bi)
01591             if (clean_index(bi) == origin_star) {
01592                 for (int kk = 0; kk < 3; kk++)
01593                     local_offset[kk] = bi->get_pos()[kk];
01594                 break;
01595             }
01596     } else
01597         for (int kk = 0; kk < 3; kk++)
01598             local_offset[kk] = 0;
01599 
01600     // Plot the data points (sorted by kproj-component in the 2D case):
01601 
01602     int n_stars = plot_stars(b, f_flag);
01603 
01604     // Update headers.
01605 
01606     lux_set_color(win, c_energy[default_color]);
01607 
01608     if (graph3d) {
01609 
01610         //sprintf(temp_buffer, "   N = %d (snapshot #%5d) max=%5.3f   ",
01611         //      n_stars, init_flag + 1, lmax3d);
01612         sprintf(temp_buffer, "   N = %d (t = %.3f) max=%5.3f   ",
01613                 n_stars, b->get_real_system_time(), lmax3d);
01614         lux_draw_image_string(win, 0.0, lmax3d*FAC3D, 0.5, temp_buffer, 0);
01615 
01616     } else {
01617 
01618         //sprintf(temp_buffer, "   N = %d  (snapshot #%5d)   ",
01619         //      n_stars, init_flag + 1);
01620         sprintf(temp_buffer, "   N = %d  (frame %d, t = %.3f)   ",
01621                 n_stars, init_flag + 1, b->get_real_system_time());
01622         lux_draw_image_string(win, (xmin+xmax)/2.0, ymax, 0.5, temp_buffer, 0);
01623 
01624     }
01625 
01626     // Update the display.
01627 
01628     update_with_delay(win, max(MIN_DELAY, delay_time));
01629 
01630     // Deal with user input.  In step mode, wait for
01631     // 'b', 'c', or 's' before continuing.
01632 
01633     while (true) {
01634 
01635         char c = check_for_input(win, b, r_flag, f_flag, eod);
01636 
01637         // Special treatment required for forward/backward step modes.
01638 
01639         if (c == 'b' || c == 'f') {             // Enter/continue step mode
01640 
01641             step_mode = (c == 'b' ? -1 : 1);
01642             return;
01643 
01644         } else if (c == 'c') {                  // Cancel step mode
01645 
01646             if (eod)
01647                 step_mode = 1;
01648             else
01649                 step_mode = 0;
01650 
01651             return;
01652         }
01653 
01654         // In eod mode, hitting 'b' or 'f' will go to a new frame.
01655         // Hitting any other key will cause the current frame to be
01656         // redisplayed (with any specified changes made).
01657 
01658         if (eod && c != 0) {
01659             step_mode = 0;
01660             return;
01661         }
01662         if (!eod && step_mode == 0) return;
01663 
01664         // Wait for 10 milliseconds before retrying.
01665 
01666         lux_pause(10000);
01667     }
01668 
01669 }
01670 
01671 /*-----------------------------------------------------------------------------
01672  *  main  --  driver to use  xstarplot()  as a tool. 
01673  *               The argument -a is interpreted as the axis along which to
01674  *            view the N-body system: the number of the coordinate axis along
01675  *            which the projection is directed, with {k,x,y} having a
01676  *            right-handend orientation.
01677  *               If an argument -l is provided, it defines the maximum
01678  *            lengths along the remaining axes.
01679  *-----------------------------------------------------------------------------
01680  */
01681 
01682 main(int argc, char** argv)
01683 {
01684     // Establish some defaults:
01685 
01686     int   k = 3;                // Note x = 1, y = 2, z = 3 here!
01687     int   d = 2;
01688     float D = 16*MIN_DELAY;
01689     int   cenergy = 0;
01690     float lmax = -1.0;
01691     int   point_mode = 0;
01692     float rel_point_size = 0.0;
01693     float scale = 1.0;
01694 
01695     bool  f_flag = TRUE;        // if TRUE, the star is solid
01696     bool  o_flag = FALSE;       // if TRUE, output stdin to stdout
01697     bool  r_flag = TRUE;        // if TRUE, the background is black
01698     bool  t_flag = FALSE;       // if TRUE, show tree structure
01699 
01700     bool verbose = false;
01701 
01702     // Store snapshots in a short circular list to allow backward steps.
01703     // Note: "short" is relative.  Currently, 128 copies of a 1000-body
01704     // is too much to keep in memory!
01705 
01706 #define MAX_SNAP 64
01707 
01708     hdynptr b[MAX_SNAP];        // Array of snapshots
01709     int max_snap = 1;
01710 
01711     check_help();
01712 
01713     extern char *poptarg;
01714     char* params = "a:bd:D:efl:L:mop:P:rs:tuv";
01715     int   c;
01716 
01717     while ((c = pgetopt(argc, argv, params)) != -1)
01718         switch(c) {
01719 
01720             case 'a': k = atoi(poptarg);        // projection axis [z]
01721                       break;
01722             case 'b': max_snap = MAX_SNAP;      // allow backward steps [no]
01723                       break;
01724             case 'd': d = atoi(poptarg);        // number of dimensions [2]
01725                       break;
01726             case 'D': D = atof(poptarg);        // delay between frames [0]
01727                       break;
01728             case 'e': cenergy = 1;              // color by energy [no]
01729                       break;
01730             case 'f': f_flag = FALSE;           // fill star points [yes]
01731                       break;
01732             case 'L':
01733             case 'l': lmax = atof(poptarg);     // axes +/- lmax [use data]
01734                       break;
01735             case 'm': multiples = 1 - multiples;
01736                       break;
01737             case 'o': o_flag = TRUE;            // output stdin to stdout [no]
01738                       break;
01739             case 'p': point_mode = atoi(poptarg);       // point scale mode [0]
01740                       break;
01741             case 'P': rel_point_size = atof(poptarg);   // point scale factor
01742                       if (rel_point_size < 0.5)
01743                           rel_point_size = 0.5;
01744                       break;
01745             case 'r': r_flag = FALSE;           // black background [yes]
01746                       break;
01747             case 's': scale = atof(poptarg);    // rescale display [1.0]
01748                       break;
01749             case 't': t_flag = TRUE;            // show tree links [no]
01750                       break;
01751             case 'u': unperturbed = 1 - unperturbed;
01752                       break;
01753             case 'v': verbose = true;           // verbose mode [no]
01754                       break;
01755             case '?': params_to_usage(cerr, argv[0], params);
01756                       get_help();
01757                       exit(0);
01758         }            
01759 
01760     int * frame_id = new int[max_snap]; // Global ids of snapshots
01761     frame_id[max_snap-1] = -1;
01762 
01763     int snap_counter = -1;      // Index of frame in snapshot array.
01764     int first_snap = 0;         // The usable list runs from first_snap to
01765     bool wrapped = false;       // snap_counter, wrapping if necessary.
01766     int step_mode = 0;
01767     int snap_display = -1;      // Index of frame currently being displayed.
01768     int isnap = 0;
01769 
01770     bool eod = false;
01771 
01772     while (true) {
01773 
01774         // Get index of next location to be filled, and update bookeeping.
01775         // Definition of "next" depends on step_mode.
01776 
01777         if (step_mode >= 0) {
01778 
01779             // Obtain the next snapshot to display.
01780 
01781             if (!eod && snap_display == snap_counter) {
01782 
01783                 // Read in a new snapshot from stdin.
01784 
01785                 hdyn* bbb;
01786                 bbb = get_hdyn(cin);
01787 
01788                 if (bbb == NULL) {
01789 
01790                     // End of input data.
01791 
01792                     cerr << "End of input data reached;"
01793                          << " entering step mode."
01794                          << endl << flush;
01795                     step_mode = 1;
01796                     eod = true;
01797 
01798                     if (o_flag) cout << "End of data\n" << flush;
01799 
01800                 } else {
01801 
01802                     // Place the new snapshot on the list.
01803 
01804                     if (++snap_counter >= max_snap) {
01805                         snap_counter = 0;
01806                         wrapped = true;
01807                     }
01808 
01809                     if (wrapped) {
01810 
01811                         // Clean up the contents of the element we are
01812                         // about to overwrite.
01813 
01814                         rmtree(b[snap_counter]);
01815                         first_snap = snap_counter + 1;
01816                         if (first_snap >= max_snap) first_snap = 0;
01817                     }
01818 
01819                     b[snap_counter] = bbb;
01820                     if (verbose)
01821                         cerr << "Snap " << isnap++
01822                              << ":  t = " << bbb->get_system_time()
01823                              << ",  N = " << bbb->n_leaves() << endl;
01824 
01825                     // Convert all coordinates to absolute values.
01826 
01827                     convert_relative_to_absolute(b[snap_counter]);
01828 
01829                     int prev_snap = snap_counter - 1;
01830                     if (prev_snap < 0) prev_snap = max_snap -1;
01831                     frame_id[snap_counter] = frame_id[prev_snap] + 1;
01832 
01833                     snap_display = snap_counter;
01834                     if (o_flag) put_node(cout, *b[snap_display]);
01835                 }
01836 
01837             } else {
01838 
01839                 // Use an existing snapshot.
01840 
01841                 if (!eod || step_mode > 0) snap_display++;
01842 
01843                 if (snap_display >= max_snap) snap_display = 0;
01844                 if (!wrapped && snap_display > snap_counter)
01845                     snap_display = 0;
01846 
01847             }
01848 
01849         } else {
01850 
01851             // Use an existing snapshot.
01852 
01853             if (--snap_display < 0) {
01854                 if (!wrapped)
01855                     snap_display = snap_counter;
01856                 else
01857                     snap_display = max_snap - 1;
01858             }
01859 
01860         }
01861 
01862         // We have a legal snapshot.  Transform and display it.
01863 
01864         xstarplot(b[snap_display], scale, k, d, lmax,
01865                   point_mode, rel_point_size, D, cenergy,
01866                   r_flag, f_flag, t_flag, frame_id[snap_display],
01867                   step_mode, eod);
01868 
01869     }
01870 }

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