home *** CD-ROM | disk | FTP | other *** search
/ Collection of Education / collectionofeducationcarat1997.iso / SCIENCE / EPHEM421.ZIP / PLOT.C < prev    next >
C/C++ Source or Header  |  1990-09-13  |  12KB  |  436 lines

  1. /* code to support the plotting capabilities.
  2.  * idea is to let the operator name a plot file and mark some fields for
  3.  * logging. then after each screen update, the logged fields are written to
  4.  * the plot file. later, the file may be plotted (very simplistically by 
  5.  * ephem, for now anyway, or by some other program entirely.).
  6.  * 
  7.  * format of the plot file is one line per coordinate: label,x,y
  8.  * if z was specified, it is a fourth field.
  9.  * x,y,z are plotted using %g format.
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <math.h>
  14. #include "screen.h"
  15.  
  16. extern char *strcpy();
  17. extern errno;
  18. extern char *sys_errlist[];
  19. #define    errsys    (sys_errlist[errno])
  20.  
  21. #define    TRACE(x)    {FILE *fp = fopen("trace","a"); fprintf x; fclose(fp);}
  22.  
  23. #define    MAXPLTLINES    10    /* max number of labeled lines we can track.
  24.                  * note we can't store more than NFLOGS fields
  25.                  * anyway (see flog.c).
  26.                  */
  27. #define    FNLEN        (14+1)    /* longest filename; plus 1 for \0 */
  28.  
  29. static char plt_filename[FNLEN] = "ephem.plt";    /* default plot file name */
  30. static FILE *plt_fp;        /* the plot file; == 0 means don't plot */
  31.  
  32. /* store the label and rcfpack()s for each line to track. */
  33. typedef struct {
  34.     char pl_label;
  35.     int pl_rcpx, pl_rcpy, pl_rcpz;
  36. } PltLine;
  37. static PltLine pltlines[MAXPLTLINES];
  38. static int npltlines;        /* number of pltlines[] in actual use */
  39.  
  40. static int plt_in_polar;    /*if true plot in polar coords, else cartesian*/
  41. static int pltsrchfld;        /* set when the Search field is to be plotted */
  42.  
  43. /* picked the Plot label:
  44.  * if on, just turn it off.
  45.  * if off, turn on, define fields or select name of file to plot and do it.
  46.  * TODO: more flexibility, more relevance.
  47.  */
  48. plot_setup()
  49. {
  50.     if (plt_fp)
  51.         plt_turn_off();
  52.     else {
  53.         static char *chcs[4] = {
  54.         "Select fields", "Display a plot file", (char *)0,
  55.         "Begin plotting"
  56.         };
  57.         static int fn;    /* start with 0, then remember for next time */
  58.     ask:
  59.         chcs[2] = plt_in_polar ? "Polar coords" : "Cartesian coords";
  60.         switch (popup(chcs, fn, npltlines > 0 ? 4 : 3)) {
  61.         case 0: fn = 0; plt_select_fields(); goto ask;
  62.         case 1: fn = 1; plt_file(); goto ask;
  63.         case 2: fn = 2; plt_in_polar ^= 1; goto ask;
  64.         case 3: fn = 3; plt_turn_on(); break;
  65.         default: break;
  66.         }
  67.     }
  68. }
  69.  
  70. /* write the active plotfields to the current plot file, if one is open. */
  71. plot()
  72. {
  73.     if (plt_fp) {
  74.         PltLine *plp;
  75.         double x, y, z;
  76.         if (!srch_ison() && pltsrchfld) {
  77.         /* if searching is not on but we are plotting the search
  78.          * funtion we must evaluate and log it ourselves here and now.
  79.          * plt_turn_on() insured there is a good function to eval.
  80.          * N.B. if searching IS on, we rely on main() having called
  81.          * srch_eval() BEFORE plot() so it is already evaluated.
  82.          */
  83.         double e;
  84.         char errmsg[128];
  85.         if (execute_expr (&e, errmsg) < 0) {
  86.             f_msg (errmsg);
  87.             plt_turn_off();
  88.             return;
  89.         } else
  90.             (void) flog_log (R_SRCH, C_SRCH, e, "");
  91.         }
  92.         /* plot in order of original selection */
  93.         for (plp = pltlines; plp < &pltlines[npltlines]; plp++) {
  94.         if (flog_get (plp->pl_rcpx, &x, (char *)0) == 0 
  95.             && flog_get (plp->pl_rcpy, &y, (char *)0) == 0) {
  96.             (void) fprintf (plt_fp, "%c,%.12g,%.12g", plp->pl_label,
  97.                                     x, y);
  98.             if (flog_get (plp->pl_rcpz, &z, (char *)0) == 0)
  99.             (void) fprintf (plt_fp, ",%.12g", z);
  100.             (void) fprintf (plt_fp, "\n");
  101.         }
  102.         }
  103.     }
  104. }
  105.  
  106. plot_prstate (force)
  107. int force;
  108. {
  109.     static last;
  110.     int this = plt_fp != 0;
  111.  
  112.     if (force || this != last) {
  113.         f_string (R_PLOT, C_PLOTV, this ? " on" : "off");
  114.         last = this;
  115.     }
  116. }
  117.  
  118. plot_ison()
  119. {
  120.     return (plt_fp != 0);
  121. }
  122.  
  123. static
  124. plt_reset()
  125. {
  126.     PltLine *plp;
  127.  
  128.     for (plp = &pltlines[npltlines]; --plp >= pltlines; ) {
  129.         (void) flog_delete (plp->pl_rcpx);
  130.         (void) flog_delete (plp->pl_rcpy);
  131.         (void) flog_delete (plp->pl_rcpz);
  132.         plp->pl_rcpx = plp->pl_rcpy = plp->pl_rcpz = 0;
  133.     }
  134.     npltlines = 0;
  135.     pltsrchfld = 0;
  136. }
  137.  
  138. /* let operator select the fields he wants to plot.
  139.  * register them with flog and keep rcfpack() in pltlines[] array.
  140.  * as a special case, set pltsrchfld if Search field is selected.
  141.  */
  142. static
  143. plt_select_fields()
  144. {
  145.     static char hlp[] = "move and RETURN to select a field, or q to quit";
  146.     static char sry[] = "Sorry; can not log any more fields.";
  147.     int r = R_UT, c = C_UTV; /* TODO: start where main was? */
  148.     int sf = rcfpack (R_SRCH, C_SRCH, 0);
  149.     char buf[64];
  150.     int rcp;
  151.     int i;
  152.  
  153.     plt_reset();
  154.     for (i = 0; i < MAXPLTLINES; i++) {
  155.         (void) sprintf (buf, "select x field for line %d", i+1);
  156.         rcp = sel_fld (r, c, alt_menumask()|F_PLT, buf, hlp);
  157.         if (!rcp)
  158.         break;
  159.         if (flog_add (rcp) < 0) {
  160.         f_msg (sry);
  161.         break;
  162.         }
  163.         pltlines[i].pl_rcpx = rcp;
  164.         if (rcp == sf)
  165.         pltsrchfld = 1;
  166.  
  167.         (void) sprintf (buf, "select y field for line %d", i+1);
  168.         r = unpackr (rcp); c = unpackc (rcp);
  169.         rcp = sel_fld (r, c, alt_menumask()|F_PLT, buf, hlp);
  170.         if (!rcp) {
  171.         (void) flog_delete (pltlines[i].pl_rcpx);
  172.         break;
  173.         }
  174.         if (flog_add (rcp) < 0) {
  175.         (void) flog_delete (pltlines[i].pl_rcpx);
  176.         f_msg (sry);
  177.         break;
  178.         }
  179.         pltlines[i].pl_rcpy = rcp;
  180.         if (rcp == sf)
  181.         pltsrchfld = 1;
  182.  
  183.         (void) sprintf (buf, "select z field for line %d", i+1);
  184.         r = unpackr (rcp); c = unpackc (rcp);
  185.         rcp = sel_fld (r, c, alt_menumask()|F_PLT, buf, hlp);
  186.         if (rcp) {
  187.         if (flog_add (rcp) < 0) {
  188.             (void) flog_delete (pltlines[i].pl_rcpx);
  189.             (void) flog_delete (pltlines[i].pl_rcpy);
  190.             f_msg (sry);
  191.             break;
  192.         }
  193.         pltlines[i].pl_rcpz = rcp;
  194.         if (rcp == sf)
  195.             pltsrchfld = 1;
  196.         r = unpackr (rcp); c = unpackc (rcp);
  197.         }
  198.  
  199.         do {
  200.         (void) sprintf(buf,"enter a one-character label for line %d: ",
  201.                                     i+1);
  202.         f_prompt (buf);
  203.         } while (read_line (buf, 1) != 1);
  204.         pltlines[i].pl_label = *buf;
  205.     }
  206.     npltlines = i;
  207. }
  208.  
  209. static
  210. plt_turn_off ()
  211. {
  212.     (void) fclose (plt_fp);
  213.     plt_fp = 0;
  214.     plot_prstate(0);
  215. }
  216.  
  217. /* turn on plotting.
  218.  * establish a file to use (and thereby set plt_fp, the plotting_is_on flag).
  219.  * also check that there is a srch function if it is being plotted.
  220.  */
  221. static
  222. plt_turn_on ()
  223. {
  224.     int sf = rcfpack(R_SRCH, C_SRCH, 0);
  225.     char fn[FNLEN], fnq[NC];
  226.     char *optype;
  227.     int n;
  228.     PltLine *plp;
  229.  
  230.     /* insure there is a valid srch function if we are to plot it */
  231.     for (plp = &pltlines[npltlines]; --plp >= pltlines; )
  232.         if ((plp->pl_rcpx == sf || plp->pl_rcpy == sf || plp->pl_rcpz == sf)
  233.             && !prog_isgood()) {
  234.         f_msg ("Plotting search function but it is not defined.");
  235.         return;
  236.         }
  237.  
  238.     /* prompt for file name, giving current as default */
  239.     (void) sprintf (fnq, "file to write <%s>: ", plt_filename);
  240.     f_prompt (fnq);
  241.     n = read_line (fn, sizeof(fn)-1);
  242.  
  243.     /* leave plotting off if type END.
  244.      * reuse same fn if just type \n
  245.      */
  246.     if (n < 0)
  247.         return;
  248.     if (n > 0)
  249.         (void) strcpy (plt_filename, fn);
  250.  
  251.     /* give option to append if file already exists */
  252.     optype = "w";
  253.     if (access (plt_filename, 2) == 0) {
  254.         while (1) {
  255.         f_prompt ("files exists; append or overwrite (a/o)?: ");
  256.         n = read_char();
  257.         if (n == 'a') {
  258.             optype = "a";
  259.             break;
  260.         }
  261.         if (n == 'o')
  262.             break;
  263.         }
  264.     }
  265.  
  266.     /* plotting is on if file opens ok */
  267.     plt_fp = fopen (plt_filename, optype);
  268.     if (!plt_fp) {
  269.         char buf[NC];
  270.         (void) sprintf (buf, "can not open %s: %s", plt_filename, errsys);
  271.         f_prompt (buf);
  272.         (void)read_char();
  273.     } else {
  274.         /* add a title if desired */
  275.         static char tp[] = "Title (q to skip): ";
  276.         f_prompt (tp);
  277.         if (read_line (fnq, PW - sizeof(tp)) > 0)
  278.         (void) fprintf (plt_fp, "* %s\n", fnq);
  279.     }
  280.     plot_prstate (0);
  281. }
  282.  
  283. /* ask operator for a file to plot. if it's ok, do it.
  284.  */
  285. static
  286. plt_file ()
  287. {
  288.     char fn[FNLEN], fnq[64];
  289.     FILE *pfp;
  290.     int n;
  291.  
  292.     /* prompt for file name, giving current as default */
  293.     (void) sprintf (fnq, "file to read <%s>: ", plt_filename);
  294.     f_prompt (fnq);
  295.     n = read_line (fn, sizeof(fn)-1);
  296.  
  297.     /* forget it if type END.
  298.      * reuse same fn if just type \