home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
x
/
volume19
/
xephem
/
part20
/
moonmenu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-15
|
15KB
|
526 lines
/* code to manage the stuff on the moon display.
*/
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#if defined(__STDC__)
#include <stdlib.h>
#endif
#include <X11/Xlib.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/DrawingA.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/ToggleB.h>
#include <Xm/Text.h>
#include "astro.h"
#include "circum.h"
extern Widget toplevel_w;
#if defined(__STDC__) || defined(__cplusplus)
#define P_(s) s
#else
#define P_(s) ()
#endif
extern Now *mm_get_now P_((void));
extern Obj *db_basic P_((int id));
extern void db_update P_((Obj *op));
extern void get_something P_((Widget w, char *resource, char *value));
extern void timestamp P_((Now *np, Widget w));
void m_manage P_((void));
int m_ison P_((void));
void m_update P_((Now *np, int how_much));
void m_cursor P_((Cursor c));
static void m_create_form P_((void));
static void m_close_cb P_((Widget w, XtPointer client, XtPointer call));
static void m_mapvw_cb P_((Widget w, XtPointer client, XtPointer call));
static void m_eshine_cb P_((Widget w, XtPointer client, XtPointer call));
static void m_da_exp_cb P_((Widget w, XtPointer client, XtPointer call));
static void m_draw P_((int force));
static void m_draw_mapview P_((double el));
static void m_draw_grview P_((double el));
#undef P_
/* get the small moonbit map and its dimension defines.
* moon is roughly centered within the map, with a radius of some 200 pixels.
* exact values set by trial and error.
*/
#include "smallfm.xbm"
#define MRAD 191 /* radius of moon image */
#define TOPMAR (smallfm_height/2 - MRAD + 2) /* top margin */
#define LEFTMAR (smallfm_width/2 - MRAD) /* left margin */
#define NSTARS 300 /* number of fake background stars in graphical view */
static Widget mform_w; /* main moon form dialog */
static Widget mda_w; /* moon drawring area */
static Widget eshine_w; /* whether we want to show earthshine */
static Widget mapvw_w; /* toggle button that selects which view */
static Widget dt_w; /* date/time stamp widget */
#define MAPVW_W (smallfm_width+20)
#define MAPVW_H (smallfm_height+40)
/* called when the moon view is activated via the main menu pulldown.
* if never called before, create and manage all the widgets as a child of a
* form. otherwise, just toggle whether the form is managed.
*/
void
m_manage ()
{
if (!mform_w)
m_create_form();
if (XtIsManaged(mform_w))
XtUnmanageChild (mform_w);
else {
XtManageChild (mform_w);
/* let the initial expose do the drawing */
}
}
m_ison()
{
return (mform_w && XtIsManaged(mform_w));
}
void
m_update (np, how_much)
Now *np;
int how_much;
{
if (!mform_w || !XtIsManaged(mform_w))
return;
m_draw (how_much);
timestamp (np, dt_w);
}
/* called to put up or remove the watch cursor. */
void
m_cursor (c)
Cursor c;
{
Window win;
if (mform_w && (win = XtWindow(mform_w))) {
Display *dsp = XtDisplay(mform_w);
if (c)
XDefineCursor (dsp, win, c);
else
XUndefineCursor (dsp, win);
}
}
static void
m_create_form()
{
Widget frame_w;
Widget f_w, fr_w;
Widget w;
XmString str;
Arg args[20];
int n;
/* create master form */
n = 0;
XtSetArg (args[n], XmNautoUnmanage, False); n++;
XtSetArg (args[n], XmNhorizontalSpacing, 5); n++;
XtSetArg (args[n], XmNverticalSpacing, 5); n++;
XtSetArg (args[n], XmNdefaultPosition, False); n++;
mform_w = XmCreateFormDialog (toplevel_w, "Moon", args, n);
/* set some stuff in the parent DialogShell.
* setting XmNdialogTitle in the Form didn't work..
*/
n = 0;
XtSetArg (args[n], XmNtitle, "xephem Moon View"); n++;
XtSetValues (XtParent(mform_w), args, n);
/* make a Form to hold the bottom controls */
n = 0;
XtSetArg (args[n], XmNfractionBase, 13); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
f_w = XmCreateForm (mform_w, "MoonCtlForm", args, n);
XtManageChild (f_w);
/* make the close button */
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNleftPosition, 1); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNrightPosition, 4); n++;
w = XmCreatePushButton (f_w, "Close", args, n);
XtAddCallback (w, XmNactivateCallback, m_close_cb, 0);
XtManageChild (w);
/* make the earthshine toggle button in a frame */
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNleftPosition, 5); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNrightPosition, 8); n++;
fr_w = XmCreateFrame (f_w, "EarthshineFr", args, n);
XtManageChild (fr_w);
eshine_w = XmCreateToggleButton (fr_w, "Earthshine", args, n);
XtAddCallback (eshine_w, XmNvalueChangedCallback, m_eshine_cb, 0);
XtManageChild (eshine_w);
/* make the view option toggle button in a frame */
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNleftPosition, 9); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNrightPosition, 12); n++;
fr_w = XmCreateFrame(f_w,"MMapViewFr", args, n);
XtManageChild (fr_w);
str = XmStringCreate("Bitmap View", XmSTRING_DEFAULT_CHARSET);
n = 0;
XtSetArg (args[n], XmNlabelString, str); n++;
mapvw_w = XmCreateToggleButton(fr_w, "BitmapView", args, n);
XtAddCallback(mapvw_w, XmNvalueChangedCallback, m_mapvw_cb, 0);
XtManageChild (mapvw_w);
XmStringFree (str);
/* make a label for the date stamp */
n = 0;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNbottomWidget, f_w); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNrecomputeSize, False); n++;
dt_w = XmCreateLabel (mform_w, "DateStamp", args, n);
timestamp (mm_get_now(), dt_w); /* sets initial size */
XtManageChild (dt_w);
/* make a frame for the drawing area */
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNbottomWidget, dt_w); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); n++;
frame_w = XmCreateFrame (mform_w, "MoonFrame", args, n);
XtManageChild (frame_w);
/* make a drawing area in the frame for the sky */
n = 0;
XtSetArg (args[n], XmNwidth, MAPVW_W); n++;
XtSetArg (args[n], XmNheight, MAPVW_H); n++;
XtSetArg (args[n], XmNmarginWidth, 0); n++;
XtSetArg (args[n], XmNmarginHeight, 0); n++;
mda_w = XmCreateDrawingArea (frame_w, "MoonDA", args, n);
XtManageChild (mda_w);
XtAddCallback (mda_w, XmNexposeCallback, m_da_exp_cb, 0);
}
/* callback from the Close button.
*/
/* ARGSUSED */
static void
m_close_cb (w, client, call)
Widget w;
XtPointer client;
XtPointer call;
{
XtUnmanageChild (mform_w);
}
/* callback from the Map view toggle button.
*/
/* ARGSUSED */
static void
m_mapvw_cb (w, client, call)
Widget w;
XtPointer client;
XtPointer call;
{
m_update (mm_get_now(), 1);
}
/* callback from the earthshine toggle button.
*/
/* ARGSUSED */
static void
m_eshine_cb (w, client, call)
Widget w;
XtPointer client;
XtPointer call;
{
m_update (mm_get_now(), 1);
}
/* expose (or reconfig) of moon drawing area.
* just redraw the scene to the current window size.
*/
/* ARGSUSED */
static void
m_da_exp_cb (w, client, call)
Widget w;
XtPointer client;
XtPointer call;
{
XmDrawingAreaCallbackStruct *c = (XmDrawingAreaCallbackStruct *)call;
switch (c->reason) {
case XmCR_EXPOSE: {
/* turn off gravity so we get expose events for either shrink or
* expand.
*/
static before;
XExposeEvent *e = &c->event->xexpose;
if (!before) {
XSetWindowAttributes swa;
swa.bit_gravity = ForgetGravity;
XChangeWindowAttributes (e->display, e->window,
CWBitGravity, &swa);
before = 1;
}
/* wait for the last in the series */
if (e->count != 0)
return;
break;
}
default:
printf ("Unexpected mda_w event. type=%d\n", c->reason);
exit(1);
}
m_update (mm_get_now(), 1);
}
/* draw moon, always if force or scene has changed.
*/
static void
m_draw (force)
int force;
{
static double last_el;
Obj *op;
double el;
/* get new elongation */
op = db_basic (MOON);
db_update (op);
el = degrad(op->s_elong);
/* don't bother if not forcing and hasn't changed 1 degree */
if (!force && fabs (el - last_el) < degrad(1.0))
return;
last_el = el;
if (XmToggleButtonGetState(mapvw_w)) {
/* drawing pixmap view so insure a good initial size at least
*/
Arg args[20];
int n;
n = 0;
XtSetArg (args[n], XmNwidth, MAPVW_W); n++;
XtSetArg (args[n], XmNheight, MAPVW_H); n++;
XtSetValues (mda_w, args, n);
XtManageChild (XtParent(eshine_w));
XtManageChild (eshine_w);
m_draw_mapview (el);
} else {
/* want graphical view */
XtUnmanageChild (eshine_w);
XtUnmanageChild (XtParent(eshine_w));
m_draw_grview (el);
}
}
/* version that draws moon using genuine bitmap image. */
static void
m_draw_mapview (el)
double el;
{
static GC m_fgc;
Display *dsp = XtDisplay (mda_w);
Window win = XtWindow (mda_w);
double cosel;
XImage *xim;
unsigned char *m;
int y; /* y coord: 0 is center, up is + */
int earthshine = XmToggleButtonGetState(eshine_w);
if (!m_fgc) {
/* make gc from MoonDA colors
*/
XGCValues gcv;
unsigned int gcm;
gcm = GCForeground | GCBackground;
get_something (mda_w, XmNforeground, (char *)&gcv.background);
get_something (mda_w, XmNbackground, (char *)&gcv.foreground);
m_fgc = XCreateGC (dsp, win, gcm, &gcv);
}
/* make a copy so we can darken some of it */
m = (unsigned char *)XtMalloc(smallfm_width*smallfm_height/8);
(void) memcpy (m, smallfm_bits, smallfm_width*smallfm_height/8);
cosel = cos(el);
for (y = MRAD; y > -MRAD; y--) {
int lx, rx; /* left and right edge of scan line to darken */
int r, c; /* X row/col coords */
lx = -sqrt((double)(MRAD*MRAD - y*y));
rx = -lx * cosel;
if (el < 0) {
int tmp = rx;
rx = -lx;
lx = -tmp;
}
r = TOPMAR + MRAD - y;
for (c = LEFTMAR + MRAD + lx; c < LEFTMAR + MRAD + rx; c++)
if (!earthshine || (c & 3) != 3 || (y & 3) != 3)
m[r*smallfm_width/8 + c/8] |= (1 << (c%8)); /* 1 is bkgnd */
}
xim = XCreateImage (dsp, XDefaultVisual (dsp, 0),
/* depth */ 1,
/* format */ XYBitmap,
/* offset */ 0,
/* data */ (char *)m,
/* width */ smallfm_width,
/* height */ smallfm_height,
/* pad */ 8,
/* bpl */ 0);
xim->bitmap_bit_order = LSBFirst;
xim->byte_order = LSBFirst;
XPutImage (dsp, win, m_fgc, xim, 0, 0, 0, 0,
smallfm_width, smallfm_height);
XDestroyImage (xim); /* also frees m */
}
/* version that draws moon using just simple graphics */
static void
m_draw_grview (el)
double el;
{
static GC m_fgc, m_bgc;
static XPoint *stars;
static int last_w, last_h;
Display *dsp = XtDisplay (mda_w);
Window win = XtWindow (mda_w);
Window root;
int x, y;
unsigned int bw, d;
unsigned w, h; /* actual size of drawing area window */
unsigned md; /* moon circle diameter */
int la1, la2, ta1, ta2; /* limb and terminator start and extent */
int wid; /* distance from meridian to terminator */
int xb, yb; /* x and y borders, eg, (w-nx)/2 */
Pixmap pm;
if (!m_fgc) {
/* make gcs from MoonDA colors
*/
XGCValues gcv;
unsigned int gcm;
gcm = GCForeground | GCBackground;
get_something (mda_w, XmNforeground, (char *)&gcv.foreground);
get_something (mda_w, XmNbackground, (char *)&gcv.background);
m_fgc = XCreateGC (dsp, win, gcm, &gcv);
get_something (mda_w, XmNbackground, (char *)&gcv.foreground);
get_something (mda_w, XmNforeground, (char *)&gcv.background);
m_bgc = XCreateGC (dsp, win, gcm, &gcv);
}
/* get size of window now and make a fresh pixmap to match.
* we draw the scene in the pixmap then copy it to the window.
* otherwise, you can see it drawing and it flashes and looks ugly.
*/
XGetGeometry (dsp, win, &root, &x, &y, &w, &h, &bw, &d);
pm = XCreatePixmap (dsp, win, w, h, d);
XFillRectangle (dsp, pm, m_bgc, 0, 0, w, h);
/* set moon diameter so it is centered within the bounding rectangle
* of the window.
* this code sets it to match the borders of the map view and makes
* the diameter even so it divides evenly.
*/
md = ((w > h) ? MRAD*h/(MRAD+TOPMAR) : MRAD*w/(MRAD+LEFTMAR)) & (~1);
xb = (w - md)/2;
yb = (h - md)/2;
la1 = el >= 0.0 ? -90*64 : 90*64;
la2 = 180*64;
wid = fabs(md/2*cos(el))+0.5;
ta1 = el >= PI/2 || (el <= 0 && el >= -PI/2) ? 90*64 : -90*64;
ta2 = 180*64;
/* dsp, win, gc, x, y, w, h, start_ang, ang_extent */
/* draw the lit hemisphere to the limb */
XFillArc (dsp, pm, m_fgc, xb, yb, md, md, la1, la2);
/* draw the portion from the terminator to the meridian */
if (la1 < 0 && ta1 < 0 || la1 > 0 && ta1 > 0) {
/* crescent, so draw in background color */
XFillArc (dsp, pm, m_bgc, md/2-wid+xb, yb, 2*wid, md, ta1, ta2);
} else {
/* gibbous, so draw in foreground color */
XFillArc (dsp, pm, m_fgc, md/2-wid+xb, yb, 2*wid, md, ta1, ta2);
}
/* add in the background stars */
if (!stars || last_w != w || last_h != h) {
/* sprinkle NSTARS stars outside the moon's circle of radius r.
*/
double rr = 0.25*md*md; /* = (md/2)*(md/2); */
int i;
if (stars)
XtFree ((char *)stars);
stars = (XPoint *) XtMalloc (NSTARS * sizeof(XPoint));
for (i = 0; i < NSTARS; ) {
x = ((rand() >> 2) & 0xfff) * (w-1) / 0xfff;
y = ((rand() >> 2) & 0xfff) * (h-1) / 0xfff;
/* compare the candidate y with the y on the ellipse at the
* candidate x to decide whether to draw the point.
*/
#define SQR(x) ((x)*(x))
if (SQR(y-h/2) > rr - SQR(x-w/2)) {
stars[i].x = (short)x;
stars[i].y = (short)y;
i++;
}
}
}
XDrawPoints (dsp, pm, m_fgc, stars, NSTARS, CoordModeOrigin);
XCopyArea (dsp, pm, win, m_fgc, 0, 0, w, h, 0, 0);
XFreePixmap (dsp, pm);
last_w = w;
last_h = h;
}