home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
x
/
volume19
/
xephem
/
part18
/
misc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-15
|
20KB
|
813 lines
/* 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);
}