home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xephem / part20 / marsmenu.c < prev    next >
C/C++ Source or Header  |  1993-05-15  |  15KB  |  564 lines

  1. /* code to manage the stuff on the "mars" menu.
  2.  */
  3.  
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <math.h>
  7. #if defined(__STDC__)
  8. #include <stdlib.h>
  9. #endif
  10. #include <X11/Xlib.h>
  11. #include <Xm/Xm.h>
  12. #include <Xm/Form.h>
  13. #include <Xm/Frame.h>
  14. #include <Xm/Label.h>
  15. #include <Xm/PushB.h>
  16. #include <Xm/RowColumn.h>
  17. #include <Xm/DrawingA.h>
  18. #include <Xm/Separator.h>
  19. #include <Xm/ToggleB.h>
  20. #include "astro.h"
  21. #include "circum.h"
  22. #include "map.h"
  23.  
  24.  
  25. #if defined(__STDC__) || defined(__cplusplus)
  26. #define P_(s) s
  27. #else
  28. #define P_(s) ()
  29. #endif
  30.  
  31. extern Now *mm_get_now P_((void));
  32. extern Obj *db_basic P_((int id));
  33. extern int any_ison P_((void));
  34. extern void db_update P_((Obj *op));
  35. extern void f_double P_((Widget w, char *fmt, double f));
  36. extern void get_something P_((Widget w, char *resource, char *value));
  37. extern void hlp_dialog P_((char *tag, char *deflt[], int ndeflt));
  38. extern void range P_((double *v, double r));
  39. extern void register_selection P_((char *name));
  40. extern void timestamp P_((Now *np, Widget w));
  41.  
  42. void mars_manage P_((void));
  43. void mars_update P_((Now *np, int force));
  44. int mars_ison P_((void));
  45. void mars_selection_mode P_((int whether));
  46. void mars_cursor P_((Cursor c));
  47. static void mars_create_form P_((void));
  48. static void mars_cml_cb P_((Widget w, XtPointer client, XtPointer call));
  49. static void mars_close_cb P_((Widget w, XtPointer client, XtPointer call));
  50. static void mars_help_cb P_((Widget w, XtPointer client, XtPointer call));
  51. static void mars_exp_cb P_((Widget w, XtPointer client, XtPointer call));
  52. static void mars_set_buttons P_((int whether));
  53. static double mars_cml P_((Now *np));
  54. static void mars_map P_((Now *np, double cml));
  55.  
  56. #undef P_
  57.  
  58. extern MRegion mreg[];
  59. extern int nmreg;
  60.  
  61. extern Widget toplevel_w;
  62. #define    XtD    XtDisplay(toplevel_w)
  63.  
  64. #define    M_CML0    degrad(325.845)        /* Mars' CML towards Aries at M_MJD0 */
  65. #define    M_PER    degrad(350.891962)    /* Mars' rotation period, rads/day */
  66. #define    M_MJD0    (2418322.0 - MJD0)    /* mjd date of M_CML0 */
  67.  
  68. static int mars_selecting;    /* set while our fields are being selected */
  69.  
  70. static Widget marsform_w;    /* main form dialog */
  71. static Widget mars_cml_w;    /* CML numberic display widget */
  72. static Widget mars_da_w;    /* map DrawingArea widget */
  73. static Widget mars_dt_w;    /* data/time stamp label widget */
  74.  
  75. #define    DSIN(x)        sin(degrad(x))
  76. #define    DCOS(x)        cos(degrad(x))
  77.  
  78. #ifdef __STDC__
  79. static double mars_cml(Now *np);
  80. #else
  81. static double mars_cml();
  82. #endif
  83.  
  84. void
  85. mars_manage()
  86. {
  87.     if (!marsform_w)
  88.         mars_create_form();
  89.  
  90.     if (XtIsManaged(marsform_w))
  91.         XtUnmanageChild(marsform_w);
  92.     else {
  93.         XtManageChild(marsform_w);
  94.         mars_set_buttons(mars_selecting);
  95.     }
  96. }
  97.  
  98. /* display the map and CML info for circumstances described by *np..
  99.  * don't bother with the computation of CML unless we are managed or someone
  100.  *   cares.
  101.  * don't bother with the map unless we are managed.
  102.  */
  103. void
  104. mars_update(np, force)
  105. Now *np;
  106. int force;
  107. {
  108.     double cml;
  109.  
  110.     if (!marsform_w)
  111.         return;
  112.     if (!XtIsManaged(marsform_w) && !any_ison() && !force)
  113.         return;
  114.  
  115.     cml = mars_cml (np);
  116.     f_double (mars_cml_w, "%5.1f", cml);
  117.  
  118.     if (XtIsManaged(marsform_w))
  119.         mars_map (np, cml);
  120. }
  121.  
  122. mars_ison()
  123. {
  124.     return (marsform_w && XtIsManaged(marsform_w));
  125. }
  126.  
  127. /* called by other menus as they want to hear from our buttons or not.
  128.  * the ons and offs stack.
  129.  */
  130. void
  131. mars_selection_mode (whether)
  132. int whether;
  133. {
  134.     mars_selecting += whether ? 1 : -1;
  135.  
  136.     if (mars_ison())
  137.         if (whether && mars_selecting == 1       /* first one to want on */
  138.         || !whether && mars_selecting == 0 /* first one to want off */)
  139.         mars_set_buttons (whether);
  140. }
  141.  
  142. void
  143. mars_cursor(c)
  144. Cursor c;
  145. {
  146.     Window win;
  147.  
  148.     if (marsform_w && (win = XtWindow(marsform_w))) {
  149.         Display *dsp = XtDisplay(marsform_w);
  150.         if (c)
  151.         XDefineCursor(dsp, win, c);
  152.         else
  153.         XUndefineCursor(dsp, win);
  154.     }
  155. }
  156.  
  157. static void
  158. mars_create_form()
  159. {
  160.     static struct {
  161.         char *name;
  162.         void (*cb)();
  163.     } ctls[] = {
  164.         {"Close", mars_close_cb},
  165.         {"Help", mars_help_cb}
  166.     };
  167.     Widget w;
  168.     Widget fr_w;
  169.     Widget f_w;
  170.     Widget sep_w;
  171.     XmString str;
  172.     Arg args[20];
  173.     int n;
  174.     int i;
  175.  
  176.     /* create form */
  177.     n = 0;
  178.     XtSetArg (args[n], XmNautoUnmanage, False); n++;
  179.     XtSetArg (args[n], XmNdefaultPosition, False); n++;
  180.     XtSetArg (args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
  181.     XtSetArg (args[n], XmNhorizontalSpacing, 4); n++;
  182.     XtSetArg (args[n], XmNverticalSpacing, 4); n++;
  183.     marsform_w = XmCreateFormDialog (toplevel_w, "Mars", args, n);
  184.  
  185.     /* set some stuff in the parent DialogShell.
  186.      * setting XmNdialogTitle in the Form didn't work..
  187.      */
  188.     n = 0;
  189.     XtSetArg (args[n], XmNtitle, "xephem Mars view"); n++;
  190.     XtSetValues (XtParent(marsform_w), args, n);
  191.  
  192.     /* make the bottom control panel form */
  193.  
  194.     n = 0;
  195.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  196.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  197.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  198.     XtSetArg (args[n], XmNfractionBase, 9); n++;
  199.     XtSetArg (args[n], XmNverticalSpacing, 5); n++;
  200.     f_w = XmCreateForm (marsform_w, "CtlF", args, n);
  201.     XtManageChild (f_w);
  202.  
  203.         for (i = 0; i < XtNumber(ctls); i++) {
  204.         n = 0;
  205.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  206.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  207.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  208.         XtSetArg (args[n], XmNleftPosition, 1+i*4); n++;
  209.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  210.         XtSetArg (args[n], XmNrightPosition, 4+i*4); n++;
  211.         w = XmCreatePushButton (f_w, ctls[i].name, args, n);
  212.         XtManageChild (w);
  213.         XtAddCallback (w, XmNactivateCallback, ctls[i].cb, NULL);
  214.         }
  215.  
  216.     /* make a separator */
  217.  
  218.     n = 0;
  219.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  220.     XtSetArg (args[n], XmNbottomWidget, f_w); n++;
  221.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  222.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  223.     sep_w = XmCreateSeparator (marsform_w, "Sep", args, n);
  224.     XtManageChild(sep_w);
  225.  
  226.     /* make the "cml" label and push button pair */
  227.  
  228.     str = XmStringCreateLtoR("Central Meridian Longitude (degs): ",
  229.                         XmSTRING_DEFAULT_CHARSET);
  230.     n = 0;
  231.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  232.     XtSetArg (args[n], XmNbottomWidget, sep_w); n++;
  233.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  234.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
  235.     XtSetArg (args[n], XmNlabelString, str); n++;
  236.     w = XmCreateLabel (marsform_w, "CMLLbl", args, n);
  237.     XtManageChild (w);
  238.     XmStringFree(str);
  239.  
  240.     n = 0;
  241.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  242.     XtSetArg (args[n], XmNbottomWidget, sep_w); n++;
  243.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  244.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  245.     XtSetArg (args[n], XmNleftWidget, w); n++;
  246.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  247.     XtSetArg (args[n], XmNuserData, "Mars.CML"); n++;
  248.     mars_cml_w = XmCreatePushButton (marsform_w, "CMLVal", args, n);
  249.     XtAddCallback (mars_cml_w, XmNactivateCallback, mars_cml_cb, 0);
  250.     XtManageChild (mars_cml_w);
  251.  
  252.     /* make the date/time indicator label */
  253.  
  254.     n = 0;
  255.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  256.     XtSetArg (args[n], XmNbottomWidget, mars_cml_w); n++;
  257.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  258.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  259.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_CENTER); n++;
  260.     mars_dt_w = XmCreateLabel (marsform_w, "DTstamp", args, n);
  261.     XtManageChild (mars_dt_w);
  262.  
  263.     /* make a drawing area in a frame on top */
  264.  
  265.     n = 0;
  266.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  267.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  268.     XtSetArg (args[n], XmNbottomWidget, mars_dt_w); n++;
  269.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  270.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  271.     XtSetArg (args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); n++;
  272.     fr_w = XmCreateFrame (marsform_w, "MarsFrame", args, n);
  273.     XtManageChild (fr_w);
  274.  
  275.         n = 0;
  276.         mars_da_w = XmCreateDrawingArea (fr_w, "Map", args, n);
  277.         XtAddCallback (mars_da_w, XmNexposeCallback, mars_exp_cb, NULL);
  278.         XtManageChild (mars_da_w);
  279. }
  280.  
  281. /* callback for when the mars CML button is activated. */
  282. /* ARGSUSED */
  283. static void
  284. mars_cml_cb (w, client, call)
  285. Widget w;
  286. XtPointer client;
  287. XtPointer call;
  288. {
  289.     if (mars_selecting) {
  290.         char *userD;
  291.         get_something (w, XmNuserData, (char *)&userD);
  292.         register_selection (userD);
  293.     }
  294. }
  295.  
  296. /* callback for when the Close button is activated. */
  297. /* ARGSUSED */
  298. static void
  299. mars_close_cb (w, client, call)
  300. Widget w;
  301. XtPointer client;
  302. XtPointer call;
  303. {
  304.     XtUnmanageChild (marsform_w);
  305. }
  306.  
  307. /* callback from the Help button
  308.  */
  309. /* ARGSUSED */
  310. static void
  311. mars_help_cb (w, client, call)
  312. Widget w;
  313. XtPointer client;
  314. XtPointer call;
  315. {
  316.     static char *msg[] = {
  317. "This is a simple schematic depiction of the Martian surface at the given time.",
  318. "Also included is the current Central Meridian Longitude, in degrees.",
  319. "South is up and longitude increases to the right; therefore, the planet",
  320. "appears to rotate CW as seen from above."
  321. };
  322.  
  323.     hlp_dialog ("Mars", msg, XtNumber(msg));
  324. }
  325.  
  326. /* called whenever the mars drawing area gets an expose.
  327.  */
  328. /* ARGSUSED */
  329. static void
  330. mars_exp_cb (w, client, call)
  331. Widget w;
  332. XtPointer client;
  333. XtPointer call;
  334. {
  335.     XmDrawingAreaCallbackStruct *c = (XmDrawingAreaCallbackStruct *)call;
  336.  
  337.     /* filter out a few oddball cases */
  338.     switch (c->reason) {
  339.     case XmCR_EXPOSE: {
  340.         /* turn off gravity so we get expose events for either shrink or
  341.          * expand.
  342.          */
  343.         static before;
  344.         XExposeEvent *e = &c->event->xexpose;
  345.  
  346.         if (!before) {
  347.         XSetWindowAttributes swa;
  348.         swa.bit_gravity = ForgetGravity;
  349.         XChangeWindowAttributes (e->display, e->window, 
  350.                                 CWBitGravity, &swa);
  351.         before = 1;
  352.         }
  353.         /* wait for the last in the series */
  354.         if (e->count != 0)
  355.         return;
  356.         break;
  357.         }
  358.     default:
  359.         printf ("Unexpected marsform_w event. type=%d\n", c->reason);
  360.         exit(1);
  361.     }
  362.  
  363.     mars_update (mm_get_now(), 1);
  364. }
  365.  
  366. /* go through all the buttons and set whether they
  367.  * should appear to look like buttons or just flat labels.
  368.  */
  369. static void
  370. mars_set_buttons (whether)
  371. int whether;    /* whether setting up for plotting or for not plotting */
  372. {
  373.     static Arg look_like_button[] = {
  374.         {XmNtopShadowColor, (XtArgVal) 0},
  375.         {XmNbottomShadowColor, (XtArgVal) 0},
  376.         {XmNfillOnArm, (XtArgVal) True},
  377.     };
  378.     static Arg look_like_label[] = {
  379.         {XmNtopShadowColor, (XtArgVal) 0},
  380.         {XmNbottomShadowColor, (XtArgVal) 0},
  381.         {XmNfillOnArm, (XtArgVal) False},
  382.     };
  383.     static int called;
  384.     Arg *ap;
  385.     int na;
  386.  
  387.     if (!called) {
  388.         /* get baseline label and shadow appearances.
  389.          */
  390.         Pixel topshad, botshad, bgcol;
  391.         Arg args[20];
  392.         int n;
  393.  
  394.         n = 0;
  395.         XtSetArg (args[n], XmNtopShadowColor, &topshad); n++;
  396.         XtSetArg (args[n], XmNbottomShadowColor, &botshad); n++;
  397.         XtSetArg (args[n], XmNbackground, &bgcol); n++;
  398.         XtGetValues (mars_cml_w, args, n);
  399.  
  400.         look_like_button[0].value = topshad;
  401.         look_like_button[1].value = botshad;
  402.         look_like_label[0].value = bgcol;
  403.         look_like_label[1].value = bgcol;
  404.  
  405.         called = 1;
  406.     }
  407.  
  408.     if (whether) {
  409.         ap = look_like_button;
  410.         na = XtNumber(look_like_button);
  411.     } else {
  412.         ap = look_like_label;
  413.         na = XtNumber(look_like_label);
  414.     }
  415.  
  416.     XtSetValues (mars_cml_w, ap, na);
  417. }
  418.  
  419. /* return the Martian central meridian longitude at np, in degrees. */
  420. static double
  421. mars_cml(np)
  422. Now *np;
  423. {
  424.     Obj *sp, *mp;
  425.     double a;    /* angle from Sun ccw to Earth seen from Mars, rads */
  426.     double Ae;    /* planetocentric longitude of Earth from Mars, rads */
  427.     double cml0;    /* Mar's CML towards Aries, rads */
  428.     double lc;    /* Mars rotation correction for light travel, rads */
  429.     double cml;
  430.  
  431.     sp = db_basic (SUN);
  432.     db_update (sp);
  433.     mp = db_basic (MARS);
  434.     db_update (mp);
  435.  
  436.     a = asin (sp->s_edist/mp->s_edist*sin(mp->s_hlong-sp->s_hlong));
  437.     Ae = mp->s_hlong + PI + a;
  438.     cml0 = M_CML0 + M_PER*(mjd-M_MJD0) + PI/2;
  439.     range(&cml0, 2*PI);
  440.     lc = LTAU * mp->s_edist/SPD*M_PER;
  441.     cml = cml0 - Ae - lc;
  442.     range (&cml, 2*PI);
  443.     cml = raddeg(cml);
  444.     /*
  445.     printf ("a=%g Ae=%g cml0=%g lc=%g cml=%g\n", raddeg(a), raddeg(Ae),
  446.                         raddeg(cml0), raddeg(lc), cml);
  447.      */
  448.     return (cml);
  449. }
  450.  
  451. static void
  452. mars_map(np, cml)
  453. Now *np;
  454. double cml;
  455. {
  456.     static unsigned long last_w, last_h;
  457.     static Pixmap mars_pm;
  458.     static GC mars_gc;
  459.     static Pixel mars_fg, mars_bg;
  460.     Display *dsp = XtDisplay(mars_da_w);
  461.     Window win = XtWindow(mars_da_w);
  462.     int x, y;
  463.     unsigned w, h, b, d;
  464.     MRegion *rp;
  465.     XPoint p[128];
  466.     int npts;
  467.     Window root;
  468.     int wb, hb, r;
  469.     MCoord *cp;
  470.     int maxx, minx, maxy, miny;
  471.  
  472.     /* make the GC if this is our first time */
  473.     if (!mars_gc) {
  474.         XGCValues gcv;
  475.         unsigned long gcm;
  476.  
  477.         gcm = 0;
  478.         mars_gc = XCreateGC (dsp, win, gcm, &gcv);
  479.  
  480.         get_something (mars_da_w, XmNforeground, (char *)&mars_fg);
  481.         get_something (mars_da_w, XmNbackground, (char *)&mars_bg);
  482.     }
  483.  
  484.     /* set up width and height borders and the radius so the
  485.      * planetary sphere is a circle centered within the window.
  486.      */
  487.     XGetGeometry (dsp, win, &root, &x, &y, &w, &h, &b, &d);
  488.     if (w > h) {
  489.         wb = (w - h)/2;
  490.         hb = 0;
  491.         r = h/2;
  492.     } else {
  493.         wb = 0;
  494.         hb = (h - w)/2;
  495.         r = w/2;
  496.     }
  497.  
  498.     /* make the pixmap if this is our first time or the size has changed */
  499.     if (!mars_pm || w != last_w || h != last_h) {
  500.         last_w = w;
  501.         last_h = h;
  502.         if (mars_pm)
  503.         XFreePixmap (dsp, mars_pm);
  504.         mars_pm = XCreatePixmap (dsp, win, w, h, d);
  505.     }
  506.  
  507.     /* clear the scene, draw filled circle in foreground then fill in
  508.      * regions in background. Then make another pass and overlay the names.
  509.      * we draw south (negative latitudes) downwards (in X's +y diretion)
  510.      * and with increasing longitudes progressing to the right. this
  511.      * means the planet appears to rotate CW as seen from above.
  512.      */
  513.     XSetFunction (dsp, mars_gc, GXcopy);
  514.     XSetForeground (dsp, mars_gc, mars_bg);
  515.     XFillRectangle (dsp, mars_pm, mars_gc, 0, 0, w, h);
  516.     XSetForeground (dsp, mars_gc, mars_fg);
  517.     XFillArc (dsp, mars_pm, mars_gc, wb, hb, 2*r, 2*r, 0, 360*64);
  518.     XSetForeground (dsp, mars_gc, mars_bg);
  519.     for (rp = mreg; rp < mreg+nmreg; rp++) {
  520.         npts = 0;
  521.         for (cp = rp->mcp; cp < rp->mcp+rp->nmcp; cp++) {
  522.         double dlg = cp->lg - cml;
  523.         range (&dlg, 360.0);
  524.         if (dlg >= 90 && dlg <= 270)
  525.             goto skip_region;
  526.         p[npts].x = wb + r*(1 + DSIN(dlg)*DCOS(cp->lt));
  527.         p[npts].y = hb + r*(1 + DSIN(cp->lt));
  528.         npts++;
  529.         }
  530.         XFillPolygon (dsp, mars_pm, mars_gc, p, npts,Nonconvex,CoordModeOrigin);
  531.  
  532.       skip_region:
  533.         continue;
  534.     }
  535.  
  536.     XSetFunction (dsp, mars_gc, GXxor);
  537.     XSetForeground (dsp, mars_gc, mars_fg^mars_bg);
  538.     for (rp = mreg; rp < mreg+nmreg; rp++) {
  539.         maxx = 0; minx = w; maxy = 0; miny = h;
  540.         for (cp = rp->mcp; cp < rp->mcp+rp->nmcp; cp++) {
  541.         double dlg = cp->lg - cml;
  542.         range (&dlg, 360.0);
  543.         if (dlg >= 90 && dlg <= 270)
  544.             goto skip_name;
  545.         x = wb + r*(1 + DSIN(dlg)*DCOS(cp->lt));
  546.         y = hb + r*(1 + DSIN(cp->lt));
  547.         if (x > maxx) maxx = x;
  548.         if (x < minx) minx = x;
  549.         if (y > maxy) maxy = y;
  550.         if (y < miny) miny = y;
  551.         }
  552.         XDrawString (dsp, mars_pm, mars_gc, (minx+maxx)/2, (miny+maxy)/2,
  553.         rp->rname, strlen(rp->rname));
  554.  
  555.       skip_name:
  556.         continue;
  557.     }
  558.  
  559.     XSetFunction (dsp, mars_gc, GXcopy);
  560.     XCopyArea (dsp, mars_pm, win, mars_gc, 0, 0, w, h, 0, 0);
  561.  
  562.     timestamp (np, mars_dt_w);
  563. }
  564.