Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

new_xstarplot3.C

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

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