home *** CD-ROM | disk | FTP | other *** search
- /* misc handy functions.
- * every system has such, no?
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #if defined(__STDC__)
- #include <stdlib.h>
- #endif
- #include <X11/Xlib.h>
- #include <X11/cursorfont.h>
- #include <Xm/Xm.h>
- #include <Xm/PushB.h>
- #include "astro.h"
- #include "circum.h"
-
- #if defined(__STDC__) || defined(__cplusplus)
- #define P_(s) s
- #else
- #define P_(s) ()
- #endif
-
- extern Now *mm_get_now P_((void));
- extern int listing_ison P_((void));
- extern int plot_ison P_((void));
- extern int srch_ison P_((void));
- extern void dm_newobj P_((int dbidx));
- extern void dm_selection_mode P_((int whether));
- extern void dm_update P_((Now *np, int how_much));
- extern void e_cursor P_((Cursor c));
- extern void e_selection_mode P_((int whether));
- extern void e_update P_((Now *np, int force));
- extern void f_showit P_((Widget w, char *s));
- extern void fs_date P_((char out[], double jd));
- extern void fs_time P_((char out[], double t));
- extern void jm_selection_mode P_((int whether));
- extern void jm_update P_((Now *np, int how_much));
- extern void lst_log P_((char *name, char *str));
- extern void lst_selection P_((char *name));
- extern void m_update P_((Now *np, int how_much));
- extern void mars_cursor P_((Cursor c));
- extern void mars_selection_mode P_((int whether));
- extern void mars_update P_((Now *np, int force));
- extern void mm_selection_mode P_((int whether));
- extern void obj_newdb P_((int appended));
- extern void obj_update P_((Now *np, int howmuch));
- extern void plt_log P_((char *name, double value));
- extern void plt_selection P_((char *name));
- extern void sm_selection_mode P_((int whether));
- extern void sm_update P_((Now *np, int how_much));
- extern void srch_log P_((char *name, double value));
- extern void srch_selection P_((char *name));
- extern void srch_selection_mode P_((int whether));
- extern void ss_newobj P_((int dbidx));
- extern void ss_update P_((Now *np, int how_much));
- extern void sv_newdb P_((int appended));
- extern void sv_newobj P_((int dbidx));
- extern void sv_update P_((Now *np, int how_much));
- extern void utc_gst P_((double Mjd, double utc, double *gst));
- extern void xe_msg P_((char *msg, int app_modal));
-
- void set_something P_((Widget w, char *resource, char *value));
- void get_something P_((Widget w, char *resource, char *value));
- void get_xmstring P_((Widget w, char *resource, char **txtp));
- void set_xmstring P_((Widget w, char *resource, char *txt));
- void range P_((double *v, double r));
- void now_lst P_((Now *np, double *lst));
- void rnd_second P_((double *t));
- double mjd_day P_((double jd));
- double mjd_hr P_((double jd));
- void zero_mem P_((char *loc, unsigned len));
- void watch_cursor P_((int want));
- void all_update P_((Now *np, int how_much));
- void all_newobj P_((int dbidx));
- void all_newdb P_((int appended));
- void all_selection_mode P_((int whether));
- void register_selection P_((char *name));
- void field_log P_((Widget w, double value, int logv, char *str));
- void prompt_map_cb P_((Widget w, XtPointer client, XtPointer call));
- static void get_color_resource P_((Widget w, char *cname, Pixel *p));
- static get_views_font P_((Display *dsp, Font *fp));
- void obj_pickgc P_((Obj *op, Widget w, GC *gcp));
- int tickmarks P_((double min, double max, int numdiv, double ticks[]));
- char *obj_description P_((Obj *op));
- void timestamp P_((Now *np, Widget w));
- int any_ison P_((void));
- int lc P_((int cx, int cy, int cw, int x1, int y1, int x2, int y2, int *sx1, int *sy1, int *sx2, int *sy2));
- void hg_mag P_((double h, double g, double rp, double rho, double rsn, double *mp));
- void gk_mag P_((double g, double k, double rp, double rho, double *mp));
-
- #undef P_
-
- extern Widget toplevel_w;
- extern char *myclass;
- #define XtD XtDisplay(toplevel_w)
-
- /* handy way to set one resource for a widget.
- * shouldn't use this if you have several things to set for the same widget.
- */
- void
- set_something (w, resource, value)
- Widget w;
- char *resource;
- char *value;
- {
- Arg a[1];
-
- if (!w) {
- printf ("set_something (%s) called with w==0\n", resource);
- exit(1);
- }
-
- XtSetArg (a[0], resource, value);
- XtSetValues (w, a, 1);
- }
-
- /* handy way to get one resource for a widget.
- * shouldn't use this if you have several things to get for the same widget.
- */
- void
- get_something (w, resource, value)
- Widget w;
- char *resource;
- char *value;
- {
- Arg a[1];
-
- if (!w) {
- printf ("get_something (%s) called with w==0\n", resource);
- exit(1);
- }
-
- XtSetArg (a[0], resource, value);
- XtGetValues (w, a, 1);
- }
-
- /* return the given XmString resource from the given widget as a char *.
- * N.B. based on a sample in Heller, pg 178, the string back from
- * XmStringGetLtoR should be XtFree'd. Therefore, OUR caller should always
- * XtFree (*txtp).
- */
- void
- get_xmstring (w, resource, txtp)
- Widget w;
- char *resource;
- char **txtp;
- {
- static char me[] = "get_xmstring()";
- static char hah[] = "??";
-
- if (!w) {
- printf ("%s: called for %s with w==0\n", me, resource);
- exit(1);
- } else {
- XmString str;
- get_something(w, resource, (char *)&str);
- if (!XmStringGetLtoR (str, XmSTRING_DEFAULT_CHARSET, txtp)) {
- /*
- fprintf (stderr, "%s: can't get string resource %s\n", me,
- resource);
- exit (1);
- */
- (void) strcpy (*txtp = XtMalloc(sizeof(hah)), hah);
- }
- XmStringFree (str);
- }
- }
-
- void
- set_xmstring (w, resource, txt)
- Widget w;
- char *resource;
- char *txt;
- {
- XmString str;
-
- if (!w) {
- printf ("set_xmstring called for %s with w==0\n", resource);
- return;
- }
-
- str = XmStringCreateLtoR (txt, XmSTRING_DEFAULT_CHARSET);
- set_something (w, resource, (char *)str);
- XmStringFree (str);
- }
-
- /* insure 0 <= *v < r.
- */
- void
- range (v, r)
- double *v, r;
- {
- *v -= r*floor(*v/r);
- }
-
- void
- now_lst (np, lst)
- Now *np;
- double *lst;
- {
- utc_gst (mjd_day(mjd), mjd_hr(mjd), lst);
- *lst += radhr(lng);
- range (lst, 24.0);
- }
-
- /* round a time in days, *t, to the nearest second, IN PLACE. */
- void
- rnd_second (t)
- double *t;
- {
- *t = floor(*t*SPD+0.5)/SPD;
- }
-
- double
- mjd_day(jd)
- double jd;
- {
- return (floor(jd-0.5)+0.5);
- }
-
- double
- mjd_hr(jd)
- double jd;
- {
- return ((jd-mjd_day(jd))*24.0);
- }
-
- /* zero from loc for len bytes */
- void
- zero_mem (loc, len)
- char *loc;
- unsigned len;
- {
- (void) memset (loc, 0, len);
- }
-
- /* called to set or unset the watch cursor on all menus.
- * allow for nested requests.
- */
- void
- watch_cursor(want)
- int want;
- {
- extern void dm_cursor();
- extern void db_cursor();
- extern void jm_cursor();
- extern void lst_cursor();
- extern void main_cursor();
- extern void m_cursor();
- extern void msg_cursor();
- extern void obj_cursor();
- extern void plt_cursor();
- extern void sm_cursor();
- extern void sv_cursor();
- extern void svf_cursor();
- extern void ss_cursor();
- extern void srch_cursor();
- extern void v_cursor();
- static Cursor wc;
- static nreqs;
- Cursor c;
-
- if (!wc)
- wc = XCreateFontCursor (XtD, XC_watch);
-
- if (want) {
- if (nreqs++ > 0)
- return;
- c = wc;
- } else {
- if (--nreqs > 0)
- return;
- c = (Cursor)0;
- }
-
- dm_cursor(c);
- db_cursor(c);
- jm_cursor(c);
- mars_cursor(c);
- e_cursor(c);
- lst_cursor(c);
- main_cursor(c);
- m_cursor(c);
- msg_cursor(c);
- obj_cursor(c);
- plt_cursor(c);
- sm_cursor(c);
- sv_cursor(c);
- svf_cursor(c);
- ss_cursor(c);
- srch_cursor(c);
- v_cursor(c);
-
- XSync (XtD, 0);
- }
-
- /* print stuff on other menus */
- void
- all_update(np, how_much)
- Now *np;
- int how_much;
- {
- dm_update (np, how_much);
- mars_update (np, how_much);
- e_update (np, how_much);
- jm_update (np, how_much);
- sm_update (np, how_much);
- ss_update (np, how_much);
- sv_update (np, how_much);
- m_update (np, how_much);
- obj_update (np, how_much);
- }
-
- /* tell everyone who might care that a user-defined object has changed
- * then recompute and redisplay new values.
- */
- void
- all_newobj(dbidx)
- int dbidx;
- {
- watch_cursor (1);
-
- dm_newobj(dbidx);
- ss_newobj(dbidx);
- sv_newobj(dbidx);
- all_update (mm_get_now(), 1);
-
- watch_cursor (0);
- }
-
- /* tell everyone who might care that the db (beyond NOBJ) has changed.
- * appended is true if it grew; else it was replaced.
- */
- void
- all_newdb(appended)
- int appended;
- {
- watch_cursor (1);
-
- obj_newdb(appended);
- sv_newdb(appended);
-
- watch_cursor (0);
- }
-
- /* inform all menus that have something selectable for plotting/listing/srching
- * wether we are now in a mode that they should report when those fields are
- * selected.
- */
- void
- all_selection_mode(whether)
- int whether;
- {
- dm_selection_mode(whether);
- mm_selection_mode(whether);
- jm_selection_mode(whether);
- mars_selection_mode(whether);
- e_selection_mode(whether);
- sm_selection_mode(whether);
- srch_selection_mode(whether);
- }
-
- /* inform all potentially interested parties of the name of a field that
- * it might want to use for latter.
- * this is just to collect in one place all the modules that gather care.
- */
- void
- register_selection (name)
- char *name;
- {
- plt_selection (name);
- lst_selection (name);
- srch_selection (name);
- }
-
- /* if we are plotting/listing/searching, send the current field info to them.
- * N.B. only send `value' to plot and search if logv is not 0.
- */
- void
- field_log (w, value, logv, str)
- Widget w;
- double value;
- int logv;
- char *str;
- {
- char *name;
-
- if (!any_ison())
- return;
-
- get_something (w, XmNuserData, (char *)&name);
- if (name) {
- if (logv) {
- plt_log (name, value);
- srch_log (name, value);
- }
- lst_log (name, str);
- }
- }
-
- /* may be connected as the mapCallback to any convenience Dialog to
- * position it centered the cursor (allowing for the screen edges).
- */
- /* ARGSUSED */
- void
- prompt_map_cb (w, client, call)
- Widget w;
- XtPointer client;
- XtPointer call;
- {
- Window root, child;
- int rx, ry, wx, wy; /* rx/y: cursor loc on root window */
- unsigned sw, sh; /* screen width/height */
- Dimension ww, wh; /* this widget's width/height */
- Position x, y; /* final location */
- unsigned mask;
- Arg args[20];
- int n;
-
- XQueryPointer (XtDisplay(w), XtWindow(w),
- &root, &child, &rx, &ry, &wx, &wy, &mask);
- sw = WidthOfScreen (XtScreen(w));
- sh = HeightOfScreen(XtScreen(w));
- n = 0;
- XtSetArg (args[n], XmNwidth, &ww); n++;
- XtSetArg (args[n], XmNheight, &wh); n++;
- XtGetValues (w, args, n);
-
- x = rx - ww/2;
- if (x < 0)
- x = 0;
- else if (x + ww >= sw)
- x = sw - ww;
- y = ry - wh/2;
- if (y < 0)
- y = 0;
- else if (y + wh >= sh)
- y = sh - wh;
-
- n = 0;
- XtSetArg (args[n], XmNx, x); n++;
- XtSetArg (args[n], XmNy, y); n++;
- XtSetValues (w, args, n);
- }
-
- /* get the named color in *p, else set to w's XmNforeground.
- */
- static void
- get_color_resource (w, cname, p)
- Widget w;
- char *cname;
- Pixel *p;
- {
- Display *dsp = XtDisplay(w);
- Colormap def_cm = DefaultColormap (dsp, 0);
- XColor defxc, dbxc;
- char *cval;
-
- cval = XGetDefault (dsp, myclass, cname);
-
- if (!cval || !XAllocNamedColor (dsp, def_cm, cval, &defxc, &dbxc)) {
- char msg[128];
- if (!cval)
- (void) sprintf (msg, "Can't find resource `%.80s'", cname);
- else
- (void) sprintf (msg, "Can't Alloc color `%.80s'", cval);
- (void) strcat (msg, "... so using *foreground.\n");
- xe_msg(msg, 0);
- get_something (w, XmNforeground, (char *)p);
- } else
- *p = defxc.pixel;
- }
-
- /* get the Font we want to use when drawing text for the display views.
- * return 0 if ok, else -1.
- */
- static
- get_views_font (dsp, fp)
- Display *dsp;
- Font *fp;
- {
- static char resname[] = "viewsFont";
- char *fname;
- XFontStruct *fsp;
-
- fname = XGetDefault (dsp, myclass, resname);
-
- /* use XLoadQueryFont because it returns gracefully if font is not
- * found; XloadFont calls the default X error handler.
- */
- if (!fname || !(fsp = XLoadQueryFont (dsp, fname))) {
- char msg[256];
-
- if (!fname)
- (void) sprintf (msg, "Can't find resource `%.180s'", resname);
- else
- (void) sprintf (msg, "Can't load font `%.180s'", fname);
- (void) strcat (msg, "... using default server font");
- xe_msg(msg, 0);
- return (-1);
- }
-
- *fp = fsp->fid;
- return (0);
- }
-
- /* given an object, return a GC for it.
- * Use the colors defined in the X resoucres, else use the foreground of the
- * given widget.
- */
- void
- obj_pickgc(op, w, gcp)
- Obj *op;
- Widget w;
- GC *gcp;
- {
- /* names of resource colors for the planets.
- * N.B. should be in the same order as the defines in astro.h
- */
- static char *objcolnames[NOBJ-2] = {
- "mercuryColor", "venusColor", "marsColor", "jupiterColor",
- "saturnColor", "uranusColor", "neptuneColor", "plutoColor",
- "sunColor", "moonColor"
- };
- /* names of resource colors for stellar types.
- */
- static char *starcolnames[] = {
- "hotStarColor", "mediumStarColor", "coolStarColor"
- };
- static GC objgcs[XtNumber(objcolnames)];
- static GC stargcs[XtNumber(starcolnames)];
- static GC other_gc;
-
- /* make all the gcs the first time through */
- if (!other_gc) {
- Display *dsp = XtDisplay(w);
- Window win = XtWindow(w);
- unsigned gcm = GCForeground;
- Font f;
- XGCValues gcv;
- Pixel p;
- int i;
-
- if (get_views_font (dsp, &f) == 0) {
- gcm |= GCFont;
- gcv.font = f;
- }
-
- /* make the planet gcs */
- for (i = 0; i < XtNumber(objgcs); i++) {
- get_color_resource (w, objcolnames[i], &p);
- gcv.foreground = p;
- objgcs[i] = XCreateGC (dsp, win, gcm, &gcv);
- }
-
- /* make the star color gcs */
- for (i = 0; i < XtNumber(stargcs); i++) {
- get_color_resource (w, starcolnames[i], &p);
- gcv.foreground = p;
- stargcs[i] = XCreateGC (dsp, win, gcm, &gcv);
- }
-
- /* make the gc for everything else */
- get_something (w, XmNforeground, (char *)&p);
- gcv.foreground = p;
- other_gc = XCreateGC (dsp, win, gcm, &gcv);
- }
-
- if (op->type == PLANET && op->pl.code < XtNumber(objgcs))
- *gcp = objgcs[op->pl.code];
- else if (op->type == FIXED && op->f_spect[0])
- switch (op->f_spect[0]) {
- case 'O': case 'B': case 'A': case 'W':
- *gcp = stargcs[0];
- break;
- case 'F': case 'G':
- *gcp = stargcs[1];
- break;
- case 'K': case 'M': case 'N': case 'R': case 'S':
- *gcp = stargcs[2];
- break;
- default:
- *gcp = other_gc;
- break;
- }
- else
- *gcp = other_gc;
- }
-
- /* given min and max and an approximate number of divisions desired,
- * fill in ticks[] with nicely spaced values and return how many.
- * N.B. return value, and hence number of entries to ticks[], might be as
- * much as 2 more than numdiv.
- */
- int
- tickmarks (min, max, numdiv, ticks)
- double min, max;
- int numdiv;
- double ticks[];
- {
- static int factor[] = { 1, 2, 5 };
- double minscale;
- double delta;
- double lo;
- double v;
- int n;
-
- minscale = fabs(max - min);
- delta = minscale/numdiv;
- for (n=0; n < sizeof(factor)/sizeof(factor[0]); n++) {
- double scale;
- double x = delta/factor[n];
- if ((scale = (pow(10.0, ceil(log10(x)))*factor[n])) < minscale)
- minscale = scale;
- }
- delta = minscale;
-
- lo = floor(min/delta);
- for (n = 0; (v = delta*(lo+n)) < max+delta; )
- ticks[n++] = v;
-
- return (n);
- }
-
- /* given an Obj *, return its type as a descriptive string.
- * if it's of type fixed then return its class description.
- * N.B. we return the address of static storage -- do not free or change.
- */
- char *
- obj_description (op)
- Obj *op;
- {
- static struct {
- char class;
- char *desc;
- } fixed_class_map[] = {
- {'C', "Globular Cluster"},
- {'U', "Cluster, with nebulosity"},
- {'O', "Open Cluster"},
- {'G', "Spiral Galaxy"},
- {'H', "Spherical Galaxy"},
- {'A', "Cluster of Galaxies"},
- {'N', "Bright Nebula"},
- {'F', "Diffuse Nebula"},
- {'K', "Dark Nebula"},
- {'P', "Planetary Nebula"},
- {'Q', "Quasar"},
- {'T', "Stellar Object"},
- {'B', "Binary Star"},
- {'D', "Double Star"},
- {'M', "Multiple Star"},
- {'S', "Star"},
- {'V', "Variable Star"},
- };
-
- switch (op->type) {
- case FIXED:
- if (op->f_class) {
- int i;
- for (i = 0; i < XtNumber(fixed_class_map); i++)
- if (fixed_class_map[i].class == op->f_class)
- return (fixed_class_map[i].desc);
- }
- return ("Fixed");
- case PARABOLIC:
- return ("Solar - Parabolic");
- case HYPERBOLIC:
- return ("Solar - Hyperbolic");
- case ELLIPTICAL:
- return ("Solar - Elliptical");
- case PLANET:
- return ("Planet");
- default:
- printf ("obj_description: unknown type: 0x%x\n", op->type);
- exit (1);
- return (NULL); /* for lint */
- }
- }
-
- /* set the XmNlabelString resource of the given widget to the date and time
- * as given in the Now struct at *np.
- * avoid unnecessary blinking by using f_showit().
- */
- void
- timestamp (np, w)
- Now *np;
- Widget w;
- {
- char d[32], t[32], out[64];
- double lmjd = mjd - tz/24.0;
- char timezonename[32];
-
- fs_date (d, mjd_day(lmjd));
- fs_time (t, mjd_hr(lmjd));
- if (tznm[0] == '\0') {
- if (tz == 0)
- (void) strcpy(timezonename, "UTC");
- else
- (void) sprintf(timezonename, "UTC%c%g", tz<0?'+':'-', fabs(tz));
- } else
- (void) strcpy (timezonename, tznm);
- (void) sprintf (out, "%s %s %s", d, t, timezonename);
- f_showit (w, out);
- }
-
- /* return !0 if any of the button/data capture tools are active, else 0.
- */
- any_ison()
- {
- return (srch_ison() || plot_ison() || listing_ison());
- }
-
- /* given a circle and a line segment, find a segment of the line inside the
- * circle.
- * return 0 and the segment end points if one exists, else 0.
- * We use a parametric representation of the line:
- * x = x1 + (x2-x1)*t and y = y1 + (y2-y1)*t, 0 < t < 1
- * and a centered representation of the circle:
- * (x - xc)**2 + (y - yc)**2 = r**2
- * and solve for the t's that work, checking for usual conditions.
- */
- lc (cx, cy, cw, x1, y1, x2, y2, sx1, sy1, sx2, sy2)
- int cx, cy, cw; /* circle bounding box corner and width */
- int x1, y1, x2, y2; /* line segment endpoints */
- int *sx1, *sy1, *sx2, *sy2; /* segment inside the circle */
- {
- int dx = x2 - x1;
- int dy = y2 - y1;
- int r = cw/2;
- int xc = cx + r;
- int yc = cy + r;
- int A = x1 - xc;
- int B = y1 - yc;
- double a = dx*dx + dy*dy; /* O(2 * 2**16 * 2**16) */
- double b = 2*(dx*A + dy*B); /* O(4 * 2**16 * 2**16) */
- double c = A*A + B*B - r*r; /* O(2 * 2**16 * 2**16) */
- double d = b*b - 4*a*c; /* O(2**32 * 2**32) */
- double sqrtd;
- double t1, t2;
-
- if (d <= 0)
- return (-1); /* containing line is purely outside circle */
-
- sqrtd = sqrt(d);
- t1 = (-b - sqrtd)/(2.0*a);
- t2 = (-b + sqrtd)/(2.0*a);
-
- if (t1 >= 1.0 || t2 <= 0.0)
- return (-1); /* segment is purely outside circle */
-
- /* we know now that some part of the segment is inside,
- * ie, t1 < 1 && t2 > 0
- */
-
- if (t1 <= 0.0) {
- /* (x1,y1) is inside circle */
- *sx1 = x1;
- *sy1 = y1;
- } else {
- *sx1 = x1 + dx*t1;
- *sy1 = y1 + dy*t1;
- }
-
- if (t2 >= 1.0) {
- /* (x2,y2) is inside circle */
- *sx2 = x2;
- *sy2 = y2;
- } else {
- *sx2 = x1 + dx*t2;
- *sy2 = y1 + dy*t2;
- }
-
- return (0);
- }
-
- /* compute visual magnitude using the H/G parameters used in the Astro Almanac.
- * these are commonly used for asteroids.
- */
- void
- hg_mag (h, g, rp, rho, rsn, mp)
- double h, g;
- double rp; /* sun-obj dist, AU */
- double rho; /* earth-obj dist, AU */
- double rsn; /* sun-earth dist, AU */
- double *mp;
- {
- double psi_t, Psi_1, Psi_2, beta;
- double tb2;
-
- beta = acos((rp*rp + rho*rho - rsn*rsn)/ (2*rp*rho));
- tb2 = tan(beta/2.0);
- /* psi_t = exp(log(tan(beta/2.0))*0.63); */
- psi_t = pow (tb2, 0.63);
- Psi_1 = exp(-3.33*psi_t);
- /* psi_t = exp(log(tan(beta/2.0))*1.22); */
- psi_t = pow (tb2, 1.22);
- Psi_2 = exp(-1.87*psi_t);
- *mp = h + 5.0*log10(rp*rho) - 2.5*log10((1-g)*Psi_1 + g*Psi_2);
- }
-
- /* computer visual magnitude using the g/k parameters commonly used for comets.
- */
- void
- gk_mag (g, k, rp, rho, mp)
- double g, k;
- double rp; /* sun-obj dist, AU */
- double rho; /* earth-obj dist, AU */
- double *mp;
- {
- *mp = g + 5.0*log10(rho) + 2.5*k*log10(rp);
- }
-