home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / pd8.lzh / SRC / plot.c < prev    next >
C/C++ Source or Header  |  1990-04-13  |  11KB  |  437 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. #ifndef OSK
  19. extern char *sys_errlist[];
  20. #define    errsys    (sys_errlist[errno])
  21. #endif
  22.  
  23. #define    TRACE(x)    {FILE *fp = fopen("trace","a"); fprintf x; fclose(fp);}
  24.  
  25. #define    MAXPLTLINES    10    /* max number of labeled lines we can track.
  26.                  * note we can't store more than NFLOGS fields
  27.                  * anyway (see flog.c).
  28.                  */
  29. #define    FNLEN        (14+1)    /* longest filename; plus 1 for \0 */
  30.  
  31. static char plt_filename[FNLEN] = "ephem.plt";    /* default plot file name */
  32. static FILE *plt_fp;        /* the plot file; == 0 means don't plot */
  33.  
  34. /* store the label and rcfpack()s for each line to track. */
  35. typedef struct {
  36.     char pl_label;
  37.     int pl_rcpx, pl_rcpy, pl_rcpz;
  38. } PltLine;
  39. static PltLine pltlines[MAXPLTLINES];
  40. static int npltlines;        /* number of pltlines[] in actual use */
  41.  
  42. static int plt_in_polar;    /*if true plot in polar coords, else cartesian*/
  43. static int pltsrchfld;        /* set when the Search field is to be plotted */
  44.  
  45. /* picked the Plot label:
  46.  * if on, just turn it off.
  47.  * if off, turn on, define fields or select name of file to plot and do it.
  48.  * TODO: more flexibility, more relevance.
  49.  */
  50. plot_setup()
  51. {
  52.     if (plt_fp)
  53.         plt_turn_off();
  54.     else {
  55.         static char *chcs[4] = {
  56.         "Select fields", "Display a plot file", (char *)0,
  57.         "Begin plotting"
  58.         };
  59.         int ff = 0;
  60.     ask:
  61.         chcs[2] = plt_in_polar ? "Polar coords" : "Cartesian coords";
  62.         switch (popup(chcs, ff, npltlines > 0 ? 4 : 3)) {
  63.         case 0: plt_select_fields(); break;
  64.         case 1: plt_file(); break;
  65.         case 2: plt_in_polar ^= 1; ff = 2; goto ask;
  66.         case 3: plt_turn_on(); break;
  67.         }
  68.     }
  69. }
  70.  
  71. /* write the active plotfields to the current plot file, if one is open. */
  72. plot()
  73. {
  74.     if (plt_fp) {
  75.         PltLine *plp;
  76.         double x, y, z;
  77.         if (!srch_ison() && pltsrchfld) {
  78.         /* if searching is not on but we are plotting the search
  79.          * funtion we must evaluate and log it ourselves here and now.
  80.          * plt_turn_on() insured there is a good function to eval.
  81.          * N.B. if searching IS on, we rely on main() having called
  82.          * srch_eval() BEFORE plot() so it is already evaluated.
  83.          */
  84.         double e;
  85.         char errmsg[128];
  86.         if (execute_expr (&e, errmsg) < 0) {
  87.             f_msg (errmsg);
  88.             plt_turn_off();
  89.             return;
  90.         } else
  91.             (void) flog_log (R_SRCH, C_SRCH, e);
  92.         }
  93.         /* plot in order of original selection */
  94.         for (plp = pltlines; plp < &pltlines[npltlines]; plp++) {
  95.         if (flog_get (plp->pl_rcpx, &x) == 0 
  96.             && flog_get (plp->pl_rcpy, &y) == 0) {
  97.             fprintf (plt_fp, "%c,%.12g,%.12g", plp->pl_label, x, y);
  98.             if (flog_get (plp->pl_rcpz, &z) == 0)
  99.             fprintf (plt_fp, ",%.12g", z);
  100.             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.         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.         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.         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.         sprintf (buf, "enter a one-character label for line %d: ", i+1);
  201.         f_prompt (buf);
  202.         } while (read_line (buf, 1) != 1);
  203.         pltlines[i].pl_label = *buf;
  204.     }
  205.     npltlines = i;
  206. }
  207.  
  208. static
  209. plt_turn_off ()
  210. {
  211.     fclose (plt_fp);
  212.     plt_fp = 0;
  213.     plot_prstate(0);
  214. }
  215.  
  216. /* turn on plotting.
  217.  * establish a file to use (and thereby set plt_fp, the plotting_is_on flag).
  218.  * also check that there is a srch function if it is being plotted.
  219.  */
  220. static
  221. plt_turn_on ()
  222. {
  223.     int sf = rcfpack(R_SRCH, C_SRCH, 0);
  224.     char fn[FNLEN], fnq[64];
  225.     char *optype;
  226.     int n;
  227.     PltLine *plp;
  228.  
  229.     /* insure there is a valid srch function if we are to plot it */
  230.     for (plp = &pltlines[npltlines]; --plp >= pltlines; )
  231.         if ((plp->pl_rcpx == sf || plp->pl_rcpy == sf || plp->pl_rcpz == sf)
  232.             && !prog_isgood()) {
  233.         f_msg ("Plotting search function but it is not defined.");
  234.         return;
  235.         }
  236.  
  237.     /* prompt for file name, giving current as default */
  238.     sprintf (fnq, "file to write <%s>: ", plt_filename);
  239.     f_prompt (fnq);
  240.     n = read_line (fn, sizeof(fn)-1);
  241.  
  242.     /* leave plotting off if type END.
  243.      * reuse same fn if just type \n
  244.      */
  245.     if (n < 0)
  246.         return;
  247.     if (n > 0)
  248.         strcpy (plt_filename, fn);
  249.  
  250.     /* give option to append if file already exists */
  251.     optype = "w";
  252.     if (access (plt_filename, 2) == 0) {
  253.         while (1) {
  254.         f_prompt ("files exists; append or overwrite (a/o)?: ");
  255.         n = read_char();
  256.         if (n == 'a') {
  257.             optype = "a";
  258.             break;
  259.         }
  260.         if (n == 'o')
  261.             break;
  262.         }
  263.     }
  264.  
  265.     /* plotting is on if file opens ok */
  266.     plt_fp = fopen (plt_filename, optype);
  267.     if (!plt_fp) {
  268.         char buf[NC];
  269. #ifndef OSK
  270.             sprintf (buf, "can not open %s: %s", plt_filename, errsys);
  271. #else
  272.             sprintf (buf, "can not open %s: Error 000:%03d", plt_filename, errno);
  273. #endif
  274.         f_prompt (buf);
  275.         (void)read_char();
  276.     }
  277.     plot_prstate (0);
  278. }
  279.  
  280. /* ask operator for a file to plot. if it's ok, do it.
  281.  */
  282. static
  283. plt_file ()
  284. {
  285.     char fn[FNLEN], fnq[64];
  286.     FILE *pfp;
  287.     int n;
  288.  
  289.     /* prompt for file name, giving current as default */
  290.     sprintf (fnq, "file to read <%s>: ", plt_filename);
  291.     f_prompt (fnq);
  292.     n = read_line (fn, sizeof(fn)-1);
  293.  
  294.     /* forget it if type END.
  295.      * reuse same fn if just type \n
  296.      */
  297.     if (n < 0)
  298.         return;
  299.     if (n > 0)
  300.         strcpy (plt_filename, fn);
  301.  
  302.     /* do the plot if file opens ok */
  303.     pfp = fopen (plt_filename, "r");
  304.     if (pfp) {
  305.         if (plt_in_polar)
  306.         plot_polar (pfp);
  307.         else
  308.         plot_cartesian (pfp);
  309.         fclose (pfp);
  310.     } else {
  311.         char buf[NC];
  312. #ifndef OSK
  313.             sprintf (buf, "can not open %s: %s", plt_filename, errsys);
  314. #else
  315.             sprintf (buf, "can not open %s: Error 000:%03d", plt_filename, errno);
  316. #endif
  317.         f_prompt (buf);
  318.         (void)read_char();
  319.     }
  320. }
  321.  
  322. /* plot the given file on the screen in cartesian coords.
  323.  * TODO: add z tags somehow
  324.  * N.B. do whatever you like but redraw the screen when done.
  325.  */
  326. static
  327. plot_cartesian (pfp)
  328. FILE *pfp;
  329. {
  330.     static char fmt[] = "%c,%lf,%lf";
  331.     double x, y;    /* N.B. be sure these match what scanf's %lf wants*/
  332.     double minx, maxx, miny, maxy;
  333.     char buf[128];
  334.     int npts = 0;
  335.     char c;
  336.  
  337.     /* find ranges and number of points */
  338.     while (fgets (buf, sizeof(buf), pfp)) {
  339.         if (sscanf (buf, fmt, &c, &x, &y) != 3)
  340.         continue;
  341.         if (npts++ == 0) {
  342.         maxx = minx = x;
  343.         maxy = miny = y;
  344.         } else {
  345.         if (x > maxx) maxx = x;
  346.         else if (x < minx) minx = x;
  347.         if (y > maxy) maxy = y;
  348.         else if (y < miny) miny = y;
  349.         }
  350.     }
  351.  
  352. #define    SMALL    (1e-10)
  353.     if (npts < 2 || fabs(minx-maxx) < SMALL || fabs(miny-maxy) < SMALL)
  354.         f_prompt ("At least two different points required to plot.");
  355.     else {
  356.         /* read file again, this time plotting */
  357.         rewind (pfp);
  358.         c_erase();
  359.         while (fgets (buf, sizeof(buf), pfp)) {
  360.         int row, col;
  361.         if (sscanf (buf, fmt, &c, &x, &y) != 3)
  362.             continue;
  363.         row = NR-(int)((NR-1)*(y-miny)/(maxy-miny)+0.5);
  364.         col =  1+(int)((NC-1)*(x-minx)/(maxx-minx)+0.5);
  365.         if (row == NR && col == NC)
  366.             col--;    /* avoid lower right scrolling corner */
  367.         f_char (row, col, c);
  368.         }
  369.  
  370.         /* label axes */
  371.         f_double (1, 1, "%g", maxy);
  372.         f_double (NR-1, 1, "%g", miny);
  373.         f_double (NR, 1, "%g", minx);
  374.         f_double (NR, NC-10, "%g", maxx);
  375.     }
  376.  
  377.     /* hit any key to resume... */
  378.     (void) read_char();
  379.     redraw_screen (2);    /* full redraw */
  380. }
  381.  
  382. /* plot the given file on the screen in polar coords.
  383.  * first numberic field in plot file is r, second is theta in degrees.
  384.  * TODO: add z tags somehow
  385.  * N.B. do whatever you like but redraw the screen when done.
  386.  */
  387. static
  388. plot_polar (pfp)
  389. FILE *pfp;
  390. {
  391.     static char fmt[] = "%c,%lf,%lf";
  392.     double r, th;    /* N.B. be sure these match what scanf's %lf wants*/
  393.     double maxr;
  394.     char buf[128];
  395.     int npts = 0;
  396.     char c;
  397.  
  398.     /* find ranges and number of points */
  399.     while (fgets (buf, sizeof(buf), pfp)) {
  400.         if (sscanf (buf, fmt, &c, &r, &th) != 3)
  401.         continue;
  402.         if (npts++ == 0)
  403.         maxr = r;
  404.         else
  405.         if (r > maxr)
  406.             maxr = r;
  407.     }
  408.  
  409.     if (npts < 2)
  410.         f_prompt ("At least two points required to plot.");
  411.     else {
  412.         /* read file again, this time plotting */
  413.         rewind (pfp);
  414.         c_erase();
  415.         while (fgets (buf, sizeof(buf), pfp)) {
  416.         int row, col;
  417.         double x, y;
  418.         if (sscanf (buf, fmt, &c, &r, &th) != 3)
  419.             continue;
  420.         x = r * cos(th/57.2958);    /* degs to rads */
  421.         y = r * sin(th/57.2958);
  422.         row = NR-(int)((NR-1)*(y+maxr)/(2.0*maxr)+0.5);
  423.         col =  1+(int)((NC-1)*(x+maxr)/(2.0*maxr)/ASPECT+0.5);
  424.         if (row == NR && col == NC)
  425.             col--;    /* avoid lower right scrolling corner */
  426.         f_char (row, col, c);
  427.         }
  428.  
  429.         /* label radius */
  430.         f_double (NR/2, NC-10, "%g", maxr);
  431.     }
  432.  
  433.     /* hit any key to resume... */
  434.     (void) read_char();
  435.     redraw_screen (2);    /* full redraw */
  436. }
  437.