4023 lines
88 KiB
C
4023 lines
88 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include <getopt.h>
|
|
#include <ctype.h>
|
|
#include <wcslib/cel.h>
|
|
#include "sgdp4h.h"
|
|
#include <giza.h>
|
|
|
|
#define LIM 384
|
|
#define MMAX 1024
|
|
#define D2R M_PI/180.0
|
|
#define R2D 180.0/M_PI
|
|
#define XKMPER 6378.135 // Earth radius in km
|
|
#define XKMPAU 149597879.691 // AU in km
|
|
#define FLAT (1.0/298.257)
|
|
#define STDMAG 6.0
|
|
|
|
|
|
long Isat = 0;
|
|
long Isatsel = 0;
|
|
extern double SGDP4_jd0;
|
|
|
|
struct map
|
|
{
|
|
double alpha0, delta0, ra0, de0, azi0, alt0, q;
|
|
double fov, mjd, gmst, w, wl, wb;
|
|
float length;
|
|
float minmag, maxmag, minrad, maxrad;
|
|
char orientation[LIM], projection[4], observer[32], camera[16];
|
|
char nfd[LIM], starfile[LIM], tlefile[LIM], iodfile[LIM], xyzfile[LIM];
|
|
char datadir[LIM], tledir[LIM];
|
|
float saltmin;
|
|
double lat, lng;
|
|
double h, sra, sde, sazi, salt;
|
|
float alt, timezone;
|
|
float fw, fh, agelimit;
|
|
int level, grid, site_id, plotstars, plotapex;
|
|
int leoflag, iodflag, iodpoint, visflag, planar, pssatno, psnr, xyzflag,
|
|
pflag, graves;
|
|
float psrmin, psrmax, rvis, width, height, nmax;
|
|
} m;
|
|
struct sat
|
|
{
|
|
long Isat;
|
|
char state[10];
|
|
float mag, age;
|
|
double jd;
|
|
double dx, dy, dz;
|
|
double x, y, z, vx, vy, vz;
|
|
double rsun, rearth, h;
|
|
double psun, pearth, p, phase;
|
|
double r, v, ra, de, vang;
|
|
double azi, alt, salt;
|
|
double rx, ry;
|
|
double rg, vg, azig, altg, rag, deg;
|
|
int illumg;
|
|
};
|
|
struct star
|
|
{
|
|
double ra, de;
|
|
float pmra, pmde;
|
|
float mag;
|
|
};
|
|
struct observation
|
|
{
|
|
int ssn, site;
|
|
char iod_line[LIM];
|
|
double mjd, ra, de, azi, alt;
|
|
double lng, lat;
|
|
float elv;
|
|
float dt, st, dr, sr, dx, dy, t;
|
|
int flag;
|
|
};
|
|
struct coeff_lr
|
|
{
|
|
int nd, nm, nm1, nf;
|
|
double sa, ca;
|
|
} clr[60];
|
|
struct coeff_b
|
|
{
|
|
int nd, nm, nm1, nf;
|
|
double sa;
|
|
} cb[60];
|
|
int fgetline (FILE *, char *, int);
|
|
double modulo (double, double);
|
|
void reverse (double, double, double *, double *);
|
|
void forward (double, double, double *, double *);
|
|
void init_plot (char *, float, float);
|
|
void skymap_plot_renew (void);
|
|
double gmst (double);
|
|
double dgmst (double);
|
|
void skymap_plothorizontal_grid ();
|
|
void skymap_plotequatorial_grid ();
|
|
void skymap_plotconstellations (char *);
|
|
void equatorial2horizontal (double, double, double, double *, double *);
|
|
void graves_equatorial2horizontal (double, double, double, double *,
|
|
double *);
|
|
void graves_horizontal2equatorial (double, double, double, double *,
|
|
double *);
|
|
void horizontal2equatorial (double, double, double, double *, double *);
|
|
void skymap_plotstars (char *);
|
|
void obspos_xyz (double, xyz_t *, xyz_t *);
|
|
void sunpos_xyz (double, xyz_t *, double *, double *);
|
|
void graves_xyz (double, xyz_t *, xyz_t *);
|
|
void skymap_plotsatellite (char *, int, double, double);
|
|
double date2mjd (int, int, double);
|
|
struct sat apparent_position (double);
|
|
long identify_satellite (char *, int, double, float, float);
|
|
int plot_skymap (void);
|
|
void rotate (int, float, float *, float *, float *);
|
|
int print_tle (char *, int);
|
|
void mjd2date (double mjd, char *date);
|
|
void dec2s (double x, char *s, int f, int len);
|
|
void precess (double mjd0, double ra0, double de0, double mjd, double *ra,
|
|
double *de);
|
|
double nfd2mjd (char *date);
|
|
void nfd_now (char *s);
|
|
double s2dec (char *s);
|
|
double doy2mjd (int year, double doy);
|
|
struct observation decode_iod_observation (char *iod_line);
|
|
void plot_iod (char *filename);
|
|
void get_site (int site_id);
|
|
void lunpos_xyz (double mjd, xyz_t * pos, double *ra, double *de);
|
|
void ecliptical2equatorial (double l, double b, double *ra, double *de);
|
|
void skymap_plotsun (void);
|
|
void skymap_plotmoon (void);
|
|
void mjd2date_iod (double mjd, char *date);
|
|
void dec2s_iod (double x, char *s, int type);
|
|
|
|
int giza_open_device_size_float (const char *, const char *, float, float,
|
|
int);
|
|
|
|
void
|
|
usage ()
|
|
{
|
|
|
|
printf ("Usage: skymap [OPTION]\n");
|
|
printf ("Visualize satellites on a map of the sky.\n\n");
|
|
printf
|
|
("-t, --time Date/time (yyyy-mm-ddThh:mm:ss.sss) [default: now]\n");
|
|
printf ("-c, --catalog TLE catalog file [default: satnogs.tle]\n");
|
|
printf ("-i, --id Satellite ID (NORAD) [default: all]\n");
|
|
printf ("-R, --ra R.A. [hh:mm:ss.sss]\n");
|
|
printf ("-D, --decl Decl. [+dd:mm:ss.ss]\n");
|
|
printf ("-A, --azimuth Azimuth (deg)\n");
|
|
printf ("-E, --elevation Elevation (deg)\n");
|
|
printf ("-w, --width Screen width (default: 1024). Set height too.\n");
|
|
printf ("-g, --height Screen height (default: 768). Set width too.\n");
|
|
printf ("-n, --nmax nmax line resolution/speed (default 128)\n");
|
|
printf ("-S, --all-night All night\n");
|
|
printf ("-Q, --no-stars No stars\n");
|
|
printf
|
|
("-a, --all-objects Show all objects from catalog (default: LEO)\n");
|
|
printf ("-h, --help This help\n");
|
|
printf ("-s, --site Site (COSPAR)\n");
|
|
printf ("-d, --iod IOD observations\n");
|
|
printf ("-l, --length Trail length [default: 60s]\n");
|
|
printf ("-P, --planar-id planar search satellite ID\n");
|
|
printf ("-r, --planar-alt planar search altitude\n");
|
|
printf ("-V, --visibility-alt altitude for visibility contours\n");
|
|
printf ("-p, --positions-file File with xyz positions\n");
|
|
printf ("-L, --longitude manual site longitude (deg)\n");
|
|
printf ("-B, --latitude manual site latitude (deg)\n");
|
|
printf ("-H, --elevation manual site elevation (m)\n");
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
interactive_usage ()
|
|
{
|
|
printf ("i Identify satellite\n");
|
|
printf ("\n");
|
|
printf ("f Select satellite\n");
|
|
printf ("a Select on age\n");
|
|
printf ("m Measure cursor RA/Dec, Alt/Azi\n");
|
|
printf ("\n");
|
|
printf ("G Toggle graves visibility (on/off)\n");
|
|
printf ("g Toggle grid (on/off)\n");
|
|
printf ("o Toggle orientation (horizontal/equatorial)\n");
|
|
printf ("P Toggle planar search\n");
|
|
printf ("p Toggle satellite name\n");
|
|
printf ("L Toggle satellite selection (All, LEO, HEO/GEO, none)\n");
|
|
printf ("v Toggle visibility contours\n");
|
|
printf ("F Toggle camera configuration (data/cameras.txt)\n");
|
|
printf ("Q Toggle plotting stars\n");
|
|
printf ("x Toggle plotting apex (GEO, HEO, NOSS)\n");
|
|
printf ("\n");
|
|
printf ("c Center on cursor\n");
|
|
printf ("z Center on zenith\n");
|
|
printf ("n Center on North\n");
|
|
printf ("s Center on South\n");
|
|
printf ("e Center on East\n");
|
|
printf ("w Center on West\n");
|
|
printf ("\n");
|
|
printf ("1-9 Zoom level\n");
|
|
printf ("+ Zoom in one level\n");
|
|
printf ("- Zoom out one level\n");
|
|
printf ("\n");
|
|
printf ("l Set integration length\n");
|
|
printf ("> Increase step size\n");
|
|
printf ("< Decrease step size\n");
|
|
printf ("\n");
|
|
printf (". Increase time by 1 step\n");
|
|
printf (", Decrease time by 1 step\n");
|
|
printf ("\n");
|
|
printf ("I Create IOD measurement for current time and position\n");
|
|
printf ("TAB Cycle IOD observations\n");
|
|
printf ("\n");
|
|
printf ("S Save observation position/time to schedule\n");
|
|
printf ("E Save observation end-time to schedule\n");
|
|
printf ("\n");
|
|
printf ("R Read catalog\n");
|
|
printf ("r Reset satellite selection/real time\n");
|
|
printf ("\n");
|
|
printf ("q quit\n");
|
|
}
|
|
|
|
void
|
|
init_skymap (void)
|
|
{
|
|
int i;
|
|
char *env, filename[128];
|
|
FILE *file;
|
|
|
|
// Default Map parameters
|
|
m.azi0 = 180;
|
|
m.alt0 = 90.0;
|
|
m.w = 120.0;
|
|
m.wl = 180.0;
|
|
m.wb = 180.0;
|
|
m.level = 1;
|
|
m.minmag = -2.0;
|
|
m.maxmag = 5.0;
|
|
m.maxrad = 2.0;
|
|
m.minrad = 0.02;
|
|
strcpy (m.orientation, "horizontal");
|
|
strcpy (m.starfile, "hip6mag.dat");
|
|
strcpy (m.projection, "STG");
|
|
|
|
m.lat = 0.0;
|
|
m.lng = 0.0;
|
|
m.alt = 0.0;
|
|
m.timezone = +0.0;
|
|
m.grid = 1;
|
|
m.length = 60.0;
|
|
m.mjd = -1.0;
|
|
m.leoflag = 1;
|
|
m.iodflag = 0;
|
|
m.xyzflag = 0;
|
|
m.visflag = 0;
|
|
m.planar = 0;
|
|
m.agelimit = -1.0;
|
|
m.saltmin = -6.0;
|
|
m.pflag = 1;
|
|
m.graves = 0;
|
|
m.plotstars = 1;
|
|
m.plotapex = 1;
|
|
m.width = 1024;
|
|
m.height = 768;
|
|
m.nmax = 128;
|
|
|
|
// Default settings
|
|
strcpy (m.observer, "Unknown");
|
|
m.site_id = 0;
|
|
|
|
// Get environment variables
|
|
env = getenv ("ST_DATADIR");
|
|
if (env != NULL)
|
|
{
|
|
strcpy (m.datadir, env);
|
|
}
|
|
else
|
|
{
|
|
printf ("ST_DATADIR environment variable not found.\n");
|
|
}
|
|
env = getenv ("ST_COSPAR");
|
|
if (env != NULL)
|
|
{
|
|
get_site (atoi (env));
|
|
}
|
|
else
|
|
{
|
|
printf ("ST_COSPAR environment variable not found.\n");
|
|
}
|
|
env = getenv ("ST_TLEDIR");
|
|
if (env != NULL)
|
|
{
|
|
strcpy (m.tledir, env);
|
|
}
|
|
else
|
|
{
|
|
printf ("ST_TLEDIR environment variable not found.\n");
|
|
}
|
|
sprintf (m.tlefile, "%s/satnogs.tle", m.tledir);
|
|
|
|
// Read LR coefficients
|
|
sprintf (filename, "%s/data/moonLR.dat", m.datadir);
|
|
file = fopen (filename, "r");
|
|
if (file == NULL)
|
|
{
|
|
printf ("Failed to open %s\n", filename);
|
|
exit (1);
|
|
}
|
|
for (i = 0; i < 60; i++)
|
|
fscanf (file, "%d %d %d %d %lf %lf", &clr[i].nd, &clr[i].nm, &clr[i].nm1,
|
|
&clr[i].nf, &clr[i].sa, &clr[i].ca);
|
|
fclose (file);
|
|
|
|
// Read B coefficients
|
|
sprintf (filename, "%s/data/moonB.dat", m.datadir);
|
|
file = fopen (filename, "r");
|
|
if (file == NULL)
|
|
{
|
|
printf ("Failed to open %s\n", filename);
|
|
exit (1);
|
|
}
|
|
for (i = 0; i < 60; i++)
|
|
fscanf (file, "%d %d %d %d %lf", &cb[i].nd, &cb[i].nm, &cb[i].nm1,
|
|
&cb[i].nf, &cb[i].sa);
|
|
fclose (file);
|
|
|
|
return;
|
|
}
|
|
|
|
// Get observing site
|
|
void
|
|
get_site (int site_id)
|
|
{
|
|
int i = 0;
|
|
char line[LIM];
|
|
FILE *file;
|
|
int id;
|
|
double lat, lng;
|
|
float alt;
|
|
char abbrev[3], observer[64], filename[LIM];
|
|
|
|
sprintf (filename, "%s/data/sites.txt", m.datadir);
|
|
file = fopen (filename, "r");
|
|
if (file == NULL)
|
|
{
|
|
printf ("Failed to open %s\n", filename);
|
|
exit (1);
|
|
}
|
|
while (fgets (line, LIM, file) != NULL)
|
|
{
|
|
// Skip
|
|
if (strstr (line, "#") != NULL)
|
|
continue;
|
|
|
|
// Strip newline
|
|
line[strlen (line) - 1] = '\0';
|
|
|
|
// Read data
|
|
sscanf (line, "%4d %2s %lf %lf %f", &id, abbrev, &lat, &lng, &alt);
|
|
strcpy (observer, line + 38);
|
|
|
|
// Change to km
|
|
alt /= 1000.0;
|
|
|
|
if (id == site_id)
|
|
{
|
|
m.lat = lat;
|
|
m.lng = lng;
|
|
m.alt = alt;
|
|
m.site_id = id;
|
|
strcpy (m.observer, observer);
|
|
}
|
|
|
|
}
|
|
fclose (file);
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
read_iod (char *filename, int iobs)
|
|
{
|
|
int i = 0;
|
|
char line[LIM];
|
|
FILE *file;
|
|
struct observation obs;
|
|
|
|
file = fopen (filename, "r");
|
|
if (file == NULL)
|
|
{
|
|
printf ("Failed to open %s\n", filename);
|
|
exit (1);
|
|
}
|
|
// Read data
|
|
while (fgets (line, LIM, file) != NULL)
|
|
{
|
|
if (strlen (line) < 10)
|
|
continue;
|
|
if (strstr (line, "#") == NULL)
|
|
{
|
|
obs = decode_iod_observation (line);
|
|
if (i == iobs)
|
|
{
|
|
printf ("%s\n", obs.iod_line);
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
fclose (file);
|
|
|
|
// Set parameters
|
|
get_site (obs.site);
|
|
m.mjd = obs.mjd;
|
|
m.ra0 = obs.ra;
|
|
m.de0 = obs.de;
|
|
strcpy (m.orientation, "equatorial");
|
|
m.level = 4;
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
plot_apex (float h, float beta)
|
|
{
|
|
int i;
|
|
xyz_t obspos, obsvel;
|
|
xyz_t satpos;
|
|
double rr, theta, dx, dy, dz, r, ra, de, azi, alt, rx, ry;
|
|
|
|
obspos_xyz (m.mjd, &obspos, &obsvel);
|
|
|
|
rr = h + XKMPER;
|
|
|
|
giza_set_colour_index (3);
|
|
for (theta = 0.0; theta <= 360.0; theta += 1.0)
|
|
{
|
|
satpos.x = rr * cos (theta * D2R) * cos (beta * D2R);
|
|
satpos.y = rr * sin (theta * D2R) * cos (beta * D2R);
|
|
satpos.z = rr * sin (beta * D2R);
|
|
|
|
// Position differences
|
|
dx = satpos.x - obspos.x;
|
|
dy = satpos.y - obspos.y;
|
|
dz = satpos.z - obspos.z;
|
|
|
|
// Celestial position
|
|
r = sqrt (dx * dx + dy * dy + dz * dz);
|
|
ra = modulo (atan2 (dy, dx) * R2D, 360.0);
|
|
de = asin (dz / r) * R2D;
|
|
|
|
// Convert and project
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
equatorial2horizontal (m.mjd, ra, de, &azi, &alt);
|
|
forward (azi, alt, &rx, &ry);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
forward (ra, de, &rx, &ry);
|
|
}
|
|
|
|
if (theta == 0.0)
|
|
giza_move_float ((float) rx, (float) ry);
|
|
else
|
|
{
|
|
giza_draw_float ((float) rx, (float) ry);
|
|
giza_move_float ((float) rx, (float) ry);
|
|
}
|
|
}
|
|
giza_set_colour_index (1);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// Plot XYZ point
|
|
void
|
|
plot_xyz (double mjd0, char *filename)
|
|
{
|
|
struct sat s;
|
|
double jd, rsun, rearth, rsat;
|
|
double dx, dy, dz, dvx, dvy, dvz;
|
|
xyz_t satpos, obspos, obsvel, satvel, sunpos;
|
|
double sra, sde, mjd, mjd1;
|
|
FILE *file;
|
|
char line[LIM];
|
|
|
|
file = fopen (filename, "r");
|
|
if (file == NULL)
|
|
{
|
|
printf ("Failed to open %s\n", filename);
|
|
exit (1);
|
|
}
|
|
|
|
if (file == NULL)
|
|
{
|
|
printf ("%s not found!\n", filename);
|
|
return;
|
|
}
|
|
while (fgetline (file, line, LIM) > 0)
|
|
{
|
|
sscanf (line, "%lf %lf %lf %lf", &mjd, &satpos.x, &satpos.y, &satpos.z);
|
|
if (mjd > mjd0)
|
|
break;
|
|
}
|
|
fclose (file);
|
|
|
|
// Get positions
|
|
obspos_xyz (mjd0, &obspos, &obsvel);
|
|
sunpos_xyz (mjd0, &sunpos, &sra, &sde);
|
|
|
|
// Age
|
|
s.age = 0.0;
|
|
|
|
// Sat positions
|
|
s.x = satpos.x;
|
|
s.y = satpos.y;
|
|
s.z = satpos.z;
|
|
s.vx = satvel.x;
|
|
s.vy = satvel.y;
|
|
s.vz = satvel.z;
|
|
|
|
// Sun position from satellite
|
|
dx = -satpos.x + sunpos.x;
|
|
dy = -satpos.y + sunpos.y;
|
|
dz = -satpos.z + sunpos.z;
|
|
|
|
// Distances
|
|
rsun = sqrt (dx * dx + dy * dy + dz * dz);
|
|
rearth =
|
|
sqrt (satpos.x * satpos.x + satpos.y * satpos.y + satpos.z * satpos.z);
|
|
s.h = rearth - XKMPER;
|
|
|
|
// Angles
|
|
s.psun = asin (696.0e3 / rsun) * R2D;
|
|
s.pearth = asin (6378.135 / rearth) * R2D;
|
|
s.p =
|
|
acos ((-dx * satpos.x - dy * satpos.y -
|
|
dz * satpos.z) / (rsun * rearth)) * R2D;
|
|
|
|
// Visibility state
|
|
if (s.p - s.pearth < -s.psun)
|
|
strcpy (s.state, "eclipsed");
|
|
else if (s.p - s.pearth > -s.psun && s.p - s.pearth < s.psun)
|
|
strcpy (s.state, "umbra");
|
|
else if (s.p - s.pearth > s.psun)
|
|
strcpy (s.state, "sunlit");
|
|
|
|
// Position differences
|
|
dx = satpos.x - obspos.x;
|
|
dy = satpos.y - obspos.y;
|
|
dz = satpos.z - obspos.z;
|
|
dvx = satvel.x - obsvel.x;
|
|
dvy = satvel.y - obsvel.y;
|
|
dvz = satvel.z - obsvel.z;
|
|
|
|
// Celestial position
|
|
s.r = sqrt (dx * dx + dy * dy + dz * dz);
|
|
s.v = (dvx * dx + dvy * dy + dvz * dz) / s.r;
|
|
s.ra = modulo (atan2 (dy, dx) * R2D, 360.0);
|
|
s.de = asin (dz / s.r) * R2D;
|
|
|
|
// Phase
|
|
s.phase =
|
|
acos (((obspos.x - satpos.x) * (sunpos.x - satpos.x) +
|
|
(obspos.y - satpos.y) * (sunpos.y - satpos.y) + (obspos.z -
|
|
satpos.z) *
|
|
(sunpos.z - satpos.z)) / (rsun * s.r)) * R2D;
|
|
|
|
// Magnitude
|
|
if (strcmp (s.state, "sunlit") == 0)
|
|
s.mag =
|
|
STDMAG - 15.0 + 5 * log10 (s.r) - 2.5 * log10 (sin (s.phase * D2R) +
|
|
(M_PI -
|
|
s.phase * D2R) *
|
|
cos (s.phase * D2R));
|
|
else
|
|
s.mag = 15;
|
|
|
|
|
|
// Convert and project
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
equatorial2horizontal (mjd, s.ra, s.de, &s.azi, &s.alt);
|
|
forward (s.azi, s.alt, &s.rx, &s.ry);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
forward (s.ra, s.de, &s.rx, &s.ry);
|
|
}
|
|
|
|
giza_set_colour_index (3);
|
|
giza_single_point_float (s.rx, s.ry, 17);
|
|
giza_set_character_height_float (0.6);
|
|
giza_text_float (s.rx, s.ry, " xyz");
|
|
giza_set_character_height_float (1.0);
|
|
giza_set_colour_index (1);
|
|
printf ("%s %6.3f %6.3f %.1f km\n", m.nfd, s.ra, s.de, s.r);
|
|
|
|
return;
|
|
}
|
|
|
|
// Write out the current position and time in IOD format
|
|
void
|
|
format_iod (double mjd, double ra, double de, int site)
|
|
{
|
|
char nfd[32];
|
|
double mjd0, ra0, de0;
|
|
char sra[16], sde[16];
|
|
|
|
// Get date/time
|
|
mjd2date_iod (mjd, nfd);
|
|
|
|
// Precess position to J2000
|
|
mjd0 = 51544.5;
|
|
precess (mjd, ra, de, mjd0, &ra0, &de0);
|
|
dec2s_iod (ra0 / 15.0, sra, 0);
|
|
dec2s_iod (de0, sde, 1);
|
|
|
|
// Print IOD line
|
|
printf ("99999 99 999A %04d G %s 17 25 %s%s 37 S\n", site, nfd, sra, sde);
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
allnight (void)
|
|
{
|
|
int flag;
|
|
xyz_t sunpos;
|
|
double ra, de, azi, alt, alt0;
|
|
double mjd, mjdrise = -1.0, mjdset = -1.0;
|
|
char nfd[32];
|
|
|
|
// Find solar altitude at reference time
|
|
sunpos_xyz (m.mjd, &sunpos, &ra, &de);
|
|
equatorial2horizontal (m.mjd, ra, de, &azi, &alt);
|
|
|
|
// Sun below limit, find rise, then set
|
|
if (alt < m.saltmin)
|
|
{
|
|
for (flag = 0, mjd = m.mjd; mjd < m.mjd + 0.5; mjd += 1.0 / 86400)
|
|
{
|
|
sunpos_xyz (mjd, &sunpos, &ra, &de);
|
|
equatorial2horizontal (mjd, ra, de, &azi, &alt);
|
|
|
|
if (flag != 0)
|
|
{
|
|
if (alt > m.saltmin && alt0 <= m.saltmin)
|
|
mjdrise = mjd;
|
|
}
|
|
|
|
if (flag == 0)
|
|
flag = 1;
|
|
|
|
alt0 = alt;
|
|
}
|
|
for (flag = 0, mjd = m.mjd - 0.5; mjd < m.mjd; mjd += 1.0 / 86400)
|
|
{
|
|
sunpos_xyz (mjd, &sunpos, &ra, &de);
|
|
equatorial2horizontal (mjd, ra, de, &azi, &alt);
|
|
|
|
if (flag != 0)
|
|
{
|
|
if (alt < m.saltmin && alt0 >= m.saltmin)
|
|
mjdset = mjd;
|
|
}
|
|
|
|
if (flag == 0)
|
|
flag = 1;
|
|
|
|
alt0 = alt;
|
|
}
|
|
// Sun above limit, find set, and rise
|
|
}
|
|
else
|
|
{
|
|
for (flag = 0, mjd = m.mjd; mjd < m.mjd + 1.0; mjd += 1.0 / 86400)
|
|
{
|
|
sunpos_xyz (mjd, &sunpos, &ra, &de);
|
|
equatorial2horizontal (mjd, ra, de, &azi, &alt);
|
|
|
|
if (flag != 0)
|
|
{
|
|
if (alt > m.saltmin && alt0 <= m.saltmin)
|
|
mjdrise = mjd;
|
|
if (alt < m.saltmin && alt0 >= m.saltmin)
|
|
mjdset = mjd;
|
|
}
|
|
|
|
if (flag == 0)
|
|
flag = 1;
|
|
|
|
alt0 = alt;
|
|
}
|
|
}
|
|
|
|
m.mjd = mjdset;
|
|
mjd2date (m.mjd, m.nfd);
|
|
mjd2date (mjdrise, nfd);
|
|
printf ("%s %s\n", m.nfd, nfd);
|
|
|
|
return;
|
|
}
|
|
|
|
static int verbose_flag;
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
int i, arg = 0, isite = 0;
|
|
double lat, lng;
|
|
float alt;
|
|
|
|
init_skymap ();
|
|
|
|
int c;
|
|
while (1)
|
|
{
|
|
static struct option long_options[] = {
|
|
{"time", required_argument, 0, 't'},
|
|
{"catalog", required_argument, 0, 'c'},
|
|
{"id", required_argument, 0, 'i'},
|
|
{"ra", required_argument, 0, 'R'},
|
|
{"decl", required_argument, 0, 'D'},
|
|
{"azimuth", required_argument, 0, 'A'},
|
|
{"elevation", required_argument, 0, 'E'},
|
|
{"site", required_argument, 0, 's'},
|
|
{"width", required_argument, 0, 'w'},
|
|
{"height", required_argument, 0, 'g'},
|
|
{"nmax", required_argument, 0, 'n'},
|
|
{"length", required_argument, 0, 'l'},
|
|
{"planar-id", required_argument, 0, 'P'},
|
|
{"planar-alt", required_argument, 0, 'r'},
|
|
{"visibility-alt", required_argument, 0, 'V'},
|
|
{"positions-file", required_argument, 0, 'p'},
|
|
{"longitude", required_argument, 0, 'L'},
|
|
{"latitude", required_argument, 0, 'B'},
|
|
{"elevation", required_argument, 0, 'H'},
|
|
{"iod", required_argument, 0, 'd'},
|
|
{"size", required_argument, 0, 'z'},
|
|
{"all-night", no_argument, 0, 'S'},
|
|
{"no-stars", no_argument, 0, 'Q'},
|
|
{"all-objects", no_argument, 0, 'a'},
|
|
{"help", no_argument, 0, 'h'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
int option_index = 0;
|
|
|
|
c =
|
|
getopt_long (argc, argv,
|
|
"t:c:i:R:D:A:E:s:w:g:n:l:P:r:V:p:L:B:H:d:SQah",
|
|
long_options, &option_index);
|
|
|
|
if (c == -1)
|
|
break;
|
|
|
|
switch (c)
|
|
{
|
|
case 0:
|
|
if (long_options[option_index].flag != 0)
|
|
break;
|
|
printf ("option %s", long_options[option_index].name);
|
|
if (optarg)
|
|
printf (" with arg %s", optarg);
|
|
printf ("\n");
|
|
break;
|
|
|
|
case 't':
|
|
strcpy (m.nfd, optarg);
|
|
m.mjd = nfd2mjd (m.nfd);
|
|
m.iodpoint = -1;
|
|
break;
|
|
|
|
case 'S':
|
|
m.saltmin = atof (optarg);
|
|
allnight ();
|
|
break;
|
|
|
|
case 'L':
|
|
lng = (double) atof (optarg);
|
|
isite++;
|
|
break;
|
|
|
|
case 'B':
|
|
lat = (double) atof (optarg);
|
|
isite++;
|
|
break;
|
|
|
|
case 'H':
|
|
alt = atof (optarg);
|
|
isite++;
|
|
break;
|
|
|
|
case 'c':
|
|
strcpy (m.tlefile, optarg);
|
|
break;
|
|
|
|
case 'd':
|
|
strcpy (m.iodfile, optarg);
|
|
m.iodpoint = 0;
|
|
m.leoflag = 0;
|
|
read_iod (m.iodfile, m.iodpoint);
|
|
m.iodflag = 1;
|
|
m.level = 6;
|
|
break;
|
|
|
|
case 'l':
|
|
m.length = atof (optarg);
|
|
break;
|
|
|
|
case 's':
|
|
get_site (atoi (optarg));
|
|
break;
|
|
|
|
case 'i':
|
|
Isatsel = atoi (optarg);
|
|
m.leoflag = 0;
|
|
break;
|
|
|
|
case 'P':
|
|
m.planar = 1;
|
|
m.pssatno = atoi (optarg);
|
|
m.psrmin = 300;
|
|
m.psrmax = 1000;
|
|
m.psnr = 8;
|
|
break;
|
|
|
|
case 'p':
|
|
strcpy (m.xyzfile, optarg);
|
|
m.xyzflag = 1;
|
|
break;
|
|
|
|
case 'r':
|
|
m.psrmin = atof (optarg);
|
|
m.psrmax = atof (optarg);
|
|
m.psnr = 1;
|
|
break;
|
|
|
|
case 'V':
|
|
m.visflag = 1;
|
|
m.rvis = atof (optarg);
|
|
break;
|
|
|
|
case 'R':
|
|
m.ra0 = 15.0 * s2dec (optarg);
|
|
strcpy (m.orientation, "equatorial");
|
|
m.level = 5;
|
|
break;
|
|
|
|
case 'D':
|
|
m.de0 = s2dec (optarg);
|
|
strcpy (m.orientation, "equatorial");
|
|
m.level = 5;
|
|
break;
|
|
|
|
case 'A':
|
|
m.azi0 = modulo (atof (optarg) + 180.0, 360.0);
|
|
strcpy (m.orientation, "horizontal");
|
|
m.level = 3;
|
|
break;
|
|
|
|
case 'E':
|
|
m.alt0 = atof (optarg);
|
|
if (m.alt0 > 90.0)
|
|
m.alt0 = 90.0;
|
|
strcpy (m.orientation, "horizontal");
|
|
m.level = 3;
|
|
break;
|
|
|
|
case 'w':
|
|
m.width = atof (optarg);
|
|
break;
|
|
|
|
case 'g':
|
|
m.height = atof (optarg);
|
|
break;
|
|
|
|
case 'n':
|
|
m.nmax = atof (optarg);
|
|
break;
|
|
|
|
case 'Q':
|
|
m.plotstars = 0;
|
|
break;
|
|
|
|
case 'a':
|
|
m.leoflag = 0;
|
|
break;
|
|
|
|
case 'h':
|
|
usage ();
|
|
return 0;
|
|
break;
|
|
|
|
default:
|
|
abort ();
|
|
}
|
|
}
|
|
|
|
if (verbose_flag)
|
|
puts ("verbose flag is set");
|
|
if (optind < argc)
|
|
{
|
|
printf ("Invalid argument: ");
|
|
while (optind < argc)
|
|
printf ("%s ", argv[optind++]);
|
|
putchar ('\n');
|
|
abort ();
|
|
}
|
|
|
|
// Set manual site
|
|
if (isite == 3)
|
|
{
|
|
m.lat = lat;
|
|
m.lng = lng;
|
|
m.alt = alt / 1000.0;
|
|
m.site_id = 0;
|
|
strcpy (m.observer, "Manual observer");
|
|
}
|
|
|
|
init_plot ("/xs", m.width, m.height);
|
|
|
|
plot_skymap ();
|
|
|
|
giza_close_device ();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
plot_graves_visibility (void)
|
|
{
|
|
int i, j, k, nx = 32, ny = 8;
|
|
double azi, alt, ra, de;
|
|
double ax, ay, az, dr, dx, dy, dz, h, r, r1, r2, rx, ry;
|
|
xyz_t grvpos, grvvel, satpos, obspos, obsvel;
|
|
float azil[] =
|
|
{ -90, -80, -70, -60, -50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50, 60,
|
|
70, 80, 90, 90, 90, 90, 90, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0, -10,
|
|
-20, -30,
|
|
-40, -50, -60, -70, -80, -90, -90, -90, -90, -90, -90
|
|
};
|
|
float altl[] =
|
|
{ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
15, 20, 25, 30, 35, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
|
|
40, 40, 40,
|
|
40, 40, 40, 35, 30, 25, 20, 15
|
|
};
|
|
|
|
|
|
// Get observer and solar position
|
|
graves_xyz (m.mjd, &grvpos, &grvvel);
|
|
obspos_xyz (m.mjd, &obspos, &obsvel);
|
|
|
|
giza_set_colour_index (2);
|
|
for (h = 300; h <= 1200; h += 100)
|
|
{
|
|
for (i = 0; i < sizeof (azil) / sizeof (azil[0]); i++)
|
|
{
|
|
graves_horizontal2equatorial (m.mjd, azil[i], altl[i], &ra, &de);
|
|
|
|
// Compute unit vector
|
|
ax = cos (ra * D2R) * cos (de * D2R);
|
|
ay = sin (ra * D2R) * cos (de * D2R);
|
|
az = sin (de * D2R);
|
|
|
|
// Find distance
|
|
for (k = 0, r1 = h; k < 20; k++)
|
|
{
|
|
dx = r1 * ax;
|
|
dy = r1 * ay;
|
|
dz = r1 * az;
|
|
satpos.x = grvpos.x + dx;
|
|
satpos.y = grvpos.y + dy;
|
|
satpos.z = grvpos.z + dz;
|
|
r =
|
|
sqrt (satpos.x * satpos.x + satpos.y * satpos.y +
|
|
satpos.z * satpos.z);
|
|
dr = h + XKMPER - r;
|
|
|
|
if (dr < 1.0)
|
|
break;
|
|
r1 += dr;
|
|
}
|
|
|
|
// Compute observer distance
|
|
dx = satpos.x - obspos.x;
|
|
dy = satpos.y - obspos.y;
|
|
dz = satpos.z - obspos.z;
|
|
r2 = sqrt (dx * dx + dy * dy + dz * dz);
|
|
ra = modulo (atan2 (dy, dx) * R2D, 360.0);
|
|
de = asin (dz / r2) * R2D;
|
|
|
|
// Convert and project
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
equatorial2horizontal (m.mjd, ra, de, &azi, &alt);
|
|
forward (azi, alt, &rx, &ry);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
forward (ra, de, &rx, &ry);
|
|
}
|
|
if (i == 0)
|
|
giza_move_float (rx, ry);
|
|
else
|
|
{
|
|
giza_draw_float (rx, ry);
|
|
giza_move_float (rx, ry);
|
|
}
|
|
}
|
|
}
|
|
giza_set_colour_index (1);
|
|
|
|
return;
|
|
}
|
|
|
|
// Plot visibility contours
|
|
void
|
|
plot_visibility (float h)
|
|
{
|
|
int i, j, k, nx = 300, ny = 200, nc;
|
|
float xmin, xmax, ymin, ymax;
|
|
double rx, ry, azi, alt, ra, de;
|
|
xyz_t obspos, obsvel, satpos, sunpos;
|
|
double dx, dy, dz, r, ax, ay, az, d, dr, sra, sde;
|
|
float rsun, rearth, psun, pearth, p, phase, mag;
|
|
char state[10];
|
|
float *cont, cmax;
|
|
float tr[6];
|
|
float c[] =
|
|
{ 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0,
|
|
13.0, 14.0, 15.0
|
|
};
|
|
|
|
// Allocate
|
|
cont = (float *) malloc (sizeof (float) * nx * ny);
|
|
|
|
// Limits
|
|
xmin = -1.5 * m.w;
|
|
xmax = 1.5 * m.w;
|
|
ymin = -m.w;
|
|
ymax = m.w;
|
|
|
|
// Transformation matrix
|
|
tr[2] = 0.0;
|
|
tr[1] = (xmax - xmin) / (float) nx;
|
|
tr[0] = xmin - 0.5 * tr[1];
|
|
tr[4] = 0.0;
|
|
tr[5] = (ymax - ymin) / (float) ny;
|
|
tr[3] = ymin - 0.5 * tr[5];
|
|
|
|
// Get observer and solar position
|
|
obspos_xyz (m.mjd, &obspos, &obsvel);
|
|
sunpos_xyz (m.mjd, &sunpos, &sra, &sde);
|
|
|
|
for (i = 0; i < nx; i++)
|
|
{
|
|
rx = xmin + (xmax - xmin) * (double) i / (double) (nx - 1);
|
|
for (j = 0; j < ny; j++)
|
|
{
|
|
ry = ymin + (ymax - ymin) * (double) j / (double) (ny - 1);
|
|
reverse (rx, ry, &azi, &alt);
|
|
|
|
// Skip low elevations
|
|
if (alt <= 0.0)
|
|
{
|
|
mag = 15.0;
|
|
}
|
|
else
|
|
{
|
|
horizontal2equatorial (m.mjd, azi, alt, &ra, &de);
|
|
|
|
// Compute unit vector
|
|
ax = cos (ra * D2R) * cos (de * D2R);
|
|
ay = sin (ra * D2R) * cos (de * D2R);
|
|
az = sin (de * D2R);
|
|
|
|
// Find distance
|
|
for (k = 0, d = h; k < 20; k++)
|
|
{
|
|
dx = d * ax;
|
|
dy = d * ay;
|
|
dz = d * az;
|
|
satpos.x = obspos.x + dx;
|
|
satpos.y = obspos.y + dy;
|
|
satpos.z = obspos.z + dz;
|
|
r =
|
|
sqrt (satpos.x * satpos.x + satpos.y * satpos.y +
|
|
satpos.z * satpos.z);
|
|
dr = h + XKMPER - r;
|
|
if (dr < 1.0)
|
|
break;
|
|
d += dr;
|
|
}
|
|
|
|
// Sun position from satellite
|
|
dx = -satpos.x + sunpos.x;
|
|
dy = -satpos.y + sunpos.y;
|
|
dz = -satpos.z + sunpos.z;
|
|
|
|
// Distances
|
|
rsun = sqrt (dx * dx + dy * dy + dz * dz);
|
|
rearth =
|
|
sqrt (satpos.x * satpos.x + satpos.y * satpos.y +
|
|
satpos.z * satpos.z);
|
|
// Angles
|
|
psun = asin (696.0e3 / rsun) * R2D;
|
|
pearth = asin (6378.135 / rearth) * R2D;
|
|
p =
|
|
acos ((-dx * satpos.x - dy * satpos.y -
|
|
dz * satpos.z) / (rsun * rearth)) * R2D;
|
|
p -= pearth;
|
|
|
|
// Visibility
|
|
if (p < -psun)
|
|
{
|
|
strcpy (state, "eclipsed");
|
|
giza_set_colour_index (14);
|
|
}
|
|
else if (p > -psun && p < psun)
|
|
{
|
|
strcpy (state, "umbra");
|
|
giza_set_colour_index (15);
|
|
}
|
|
else if (p > psun)
|
|
{
|
|
strcpy (state, "sunlit");
|
|
giza_set_colour_index (7);
|
|
}
|
|
|
|
// Phase
|
|
phase =
|
|
acos (((obspos.x - satpos.x) * (sunpos.x - satpos.x) +
|
|
(obspos.y - satpos.y) * (sunpos.y - satpos.y) +
|
|
(obspos.z - satpos.z) * (sunpos.z -
|
|
satpos.z)) / (rsun * d)) *
|
|
R2D;
|
|
|
|
// Magnitude
|
|
if (strcmp (state, "sunlit") == 0)
|
|
mag =
|
|
STDMAG - 15.0 + 5 * log10 (d) -
|
|
2.5 * log10 (sin (phase * D2R) +
|
|
(M_PI - phase * D2R) * cos (phase * D2R));
|
|
else
|
|
mag = 15;
|
|
}
|
|
k = i + nx * j;
|
|
cont[k] = mag;
|
|
}
|
|
}
|
|
|
|
// Find maximum contour value
|
|
for (i = 0, j = 0; i < nx * ny; i++)
|
|
{
|
|
if (cont[i] < 15.0)
|
|
{
|
|
if (j == 0 || cont[i] > cmax)
|
|
cmax = cont[i];
|
|
j++;
|
|
}
|
|
}
|
|
nc = (int) cmax + 1.0;
|
|
|
|
// Plot contours
|
|
giza_set_colour_index (7);
|
|
giza_contour_float (cont, nx, ny, 1, nx, 1, ny, c, nc, tr);
|
|
|
|
// Label contours
|
|
giza_set_character_height_float (0.8);
|
|
for (i = 0; i < nc; i++)
|
|
{
|
|
sprintf (state, "%.0f", c[i]);
|
|
// XXX Partially implmented in giza. Where does this appear? XXX
|
|
// cpgconl (cont, nx, ny, 1, nx, 1, ny, c[i], tr, state, 300, 18);
|
|
}
|
|
giza_set_character_height_float (1.0);
|
|
giza_set_colour_index (1);
|
|
|
|
return;
|
|
}
|
|
|
|
// Initialize plot
|
|
void
|
|
init_plot (char *psfile, float width, float height)
|
|
{
|
|
int i;
|
|
|
|
giza_open_device_size_float ("/xs", "skymap", width, height, 3);
|
|
giza_set_line_width_float (1);
|
|
|
|
skymap_plot_renew ();
|
|
|
|
return;
|
|
}
|
|
|
|
// Add to schedule
|
|
void
|
|
schedule (char *nfd, double ra, double de, char *startstop)
|
|
{
|
|
FILE *file;
|
|
char sra[16], sde[16];
|
|
|
|
// Compute strings
|
|
dec2s (ra / 15.0, sra, 0, 5);
|
|
dec2s (de, sde, 0, 4);
|
|
|
|
printf ("%s %s %s %s\n", nfd, sra, sde, startstop);
|
|
|
|
// Open file
|
|
file = fopen ("schedule.txt", "a");
|
|
if (file == NULL)
|
|
{
|
|
printf ("Failed to create schedule.txt\n");
|
|
return;
|
|
}
|
|
fprintf (file, "%s %s %s %s %s\n", nfd, sra, sde, m.camera, startstop);
|
|
fclose (file);
|
|
|
|
return;
|
|
}
|
|
|
|
// Initialize plot
|
|
void
|
|
skymap_plot_renew (void)
|
|
{
|
|
char filename[LIM];
|
|
|
|
// Size limit
|
|
if (m.w > 120.0)
|
|
m.w = 120.0;
|
|
|
|
if (m.level == 1)
|
|
{
|
|
m.w = 120;
|
|
m.minmag = -2.0;
|
|
m.maxmag = 5.0;
|
|
m.maxrad = 2.0;
|
|
m.minrad = 0.02;
|
|
sprintf (m.starfile, "%s/data/hip6mag.dat", m.datadir);
|
|
}
|
|
if (m.level == 2)
|
|
{
|
|
m.w = 90;
|
|
m.minmag = -1.5;
|
|
m.maxmag = 5.5;
|
|
m.maxrad = 2.0;
|
|
m.minrad = 0.02;
|
|
sprintf (m.starfile, "%s/data/hip6mag.dat", m.datadir);
|
|
}
|
|
if (m.level == 3)
|
|
{
|
|
m.w = 60;
|
|
m.minmag = -1.0;
|
|
m.maxmag = 6.0;
|
|
m.maxrad = 2.0;
|
|
m.minrad = 0.02;
|
|
sprintf (m.starfile, "%s/data/hip6mag.dat", m.datadir);
|
|
}
|
|
if (m.level == 4)
|
|
{
|
|
m.w = 30;
|
|
m.minmag = -0.5;
|
|
m.maxmag = 6.5;
|
|
m.maxrad = 2.0;
|
|
m.minrad = 0.02;
|
|
sprintf (m.starfile, "%s/data/tyc8mag.dat", m.datadir);
|
|
}
|
|
if (m.level == 5)
|
|
{
|
|
m.w = 20;
|
|
m.minmag = 0.0;
|
|
m.maxmag = 7.0;
|
|
m.maxrad = 2.0;
|
|
m.minrad = 0.02;
|
|
sprintf (m.starfile, "%s/data/tyc8mag.dat", m.datadir);
|
|
}
|
|
if (m.level == 6)
|
|
{
|
|
m.w = 10;
|
|
m.minmag = 1.0;
|
|
m.maxmag = 8.0;
|
|
m.maxrad = 2.0;
|
|
m.minrad = 0.02;
|
|
sprintf (m.starfile, "%s/data/tyc8mag.dat", m.datadir);
|
|
}
|
|
if (m.level == 7)
|
|
{
|
|
m.w = 5;
|
|
m.minmag = 2.0;
|
|
m.maxmag = 9.0;
|
|
m.maxrad = 2.0;
|
|
m.minrad = 0.02;
|
|
sprintf (m.starfile, "%s/data/tyc10mag.dat", m.datadir);
|
|
}
|
|
if (m.level == 8)
|
|
{
|
|
m.w = 2;
|
|
m.minmag = 3.0;
|
|
m.maxmag = 10.0;
|
|
m.maxrad = 2.0;
|
|
m.minrad = 0.02;
|
|
sprintf (m.starfile, "%s/data/tyc10mag.dat", m.datadir);
|
|
}
|
|
if (m.level == 9)
|
|
{
|
|
m.w = 1;
|
|
m.minmag = 3.0;
|
|
m.maxmag = 12.0;
|
|
m.maxrad = 2.0;
|
|
m.minrad = 0.02;
|
|
sprintf (m.starfile, "%s/data/tycho2.dat", m.datadir);
|
|
}
|
|
/*
|
|
// Star files
|
|
if (m.w>90.0 && m.w<=120.0) {
|
|
strcpy(m.starfile,"data/hip6mag.dat");
|
|
m.minmag=-2.0;
|
|
m.maxmag=4.5;
|
|
} else if (m.w>60.0 && m.w<=90.0) {
|
|
strcpy(m.starfile,"data/hip6mag.dat");
|
|
m.minmag=-2.0;
|
|
m.maxmag=5.0;
|
|
} else if (m.w>20.0 && m.w<=60.0) {
|
|
strcpy(m.starfile,"data/hip6mag.dat");
|
|
m.minmag=0.0;
|
|
m.maxmag=6.0;
|
|
} else if (m.w<=20.0) {
|
|
strcpy(m.starfile,"data/tyc8mag.dat");
|
|
m.minmag=2.0;
|
|
m.maxmag=8.0;
|
|
}
|
|
*/
|
|
|
|
return;
|
|
}
|
|
|
|
// Get a x and y from an AZI, ALT
|
|
void
|
|
forward (double alpha, double delta, double *x, double *y)
|
|
{
|
|
int i, status;
|
|
double phi, theta;
|
|
struct celprm cel;
|
|
|
|
// Initialize Reference Angles
|
|
celini (&cel);
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
cel.ref[0] = m.azi0;
|
|
cel.ref[1] = m.alt0;
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
cel.ref[0] = m.ra0;
|
|
cel.ref[1] = m.de0;
|
|
}
|
|
cel.ref[2] = 999.;
|
|
cel.ref[3] = 999.;
|
|
cel.flag = 0.;
|
|
strcpy (cel.prj.code, m.projection);
|
|
|
|
if (celset (&cel))
|
|
{
|
|
printf ("Error in Projection (celset)\n");
|
|
return;
|
|
}
|
|
cels2x (&cel, 1, 0, 1, 1, &alpha, &delta, &phi, &theta, x, y, &status);
|
|
|
|
// Flip equatorial axis
|
|
if (strcmp (m.orientation, "equatorial") == 0)
|
|
*x *= -1;
|
|
|
|
return;
|
|
}
|
|
|
|
// Get an AZI, ALT from x and y
|
|
void
|
|
reverse (double x, double y, double *alpha, double *delta)
|
|
{
|
|
int i, status;
|
|
double phi, theta;
|
|
struct celprm cel;
|
|
|
|
// Flip equatorial axis
|
|
if (strcmp (m.orientation, "equatorial") == 0)
|
|
x *= -1;
|
|
|
|
// Initialize Reference Angless
|
|
celini (&cel);
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
cel.ref[0] = m.azi0;
|
|
cel.ref[1] = m.alt0;
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
cel.ref[0] = m.ra0;
|
|
cel.ref[1] = m.de0;
|
|
}
|
|
cel.ref[2] = 999.;
|
|
cel.ref[3] = 999.;
|
|
cel.flag = 0.;
|
|
strcpy (cel.prj.code, m.projection);
|
|
|
|
if (celset (&cel))
|
|
{
|
|
printf ("Error in Projection (celset)\n");
|
|
return;
|
|
}
|
|
celx2s (&cel, 1, 0, 1, 1, &x, &y, &phi, &theta, alpha, delta, &status);
|
|
|
|
return;
|
|
}
|
|
|
|
// Greenwich Mean Sidereal Time
|
|
double
|
|
gmst (double mjd)
|
|
{
|
|
double t, gmst;
|
|
|
|
t = (mjd - 51544.5) / 36525.0;
|
|
|
|
gmst =
|
|
modulo (280.46061837 + 360.98564736629 * (mjd - 51544.5) +
|
|
t * t * (0.000387933 - t / 38710000), 360.0);
|
|
|
|
return gmst;
|
|
}
|
|
|
|
// Return x modulo y [0,y)
|
|
double
|
|
modulo (double x, double y)
|
|
{
|
|
x = fmod (x, y);
|
|
if (x < 0.0)
|
|
x += y;
|
|
|
|
return x;
|
|
}
|
|
|
|
|
|
// Read a line of maximum length int lim from file FILE into string s
|
|
int
|
|
fgetline (FILE * file, char *s, int lim)
|
|
{
|
|
int c, i = 0;
|
|
|
|
while (--lim > 0 && (c = fgetc (file)) != EOF && c != '\n')
|
|
s[i++] = c;
|
|
if (c == '\n')
|
|
s[i++] = c;
|
|
s[i] = '\0';
|
|
return i;
|
|
}
|
|
|
|
// Plot field of view
|
|
void
|
|
skymap_plot_fov ()
|
|
{
|
|
int i, j, n = 50;
|
|
double rx, ry, azi, alt;
|
|
float x, y;
|
|
// double azi0[]={44.0,7.0,30.0,44.0,44.0};
|
|
// double alt0[]={16.0,16.0,60.0,60.0,16.0};
|
|
double azi0[] = { 45.0, 7.0, 7.0, 45.0, 45.0 };
|
|
double alt0[] = { 20.0, 20.0, 50.0, 50.0, 20.0 };
|
|
double azi1[] = { 150.0, 140.0, 140.0, 150.0, 150.0 };
|
|
double alt1[] = { 26.0, 26.0, 31.0, 31.0, 26.0 };
|
|
|
|
/*
|
|
for (i=0;i<sizeof(alt0)/sizeof(alt0[0])-1;i++) {
|
|
for (j=0;j<n;j++) {
|
|
azi=azi0[i]+(azi0[i+1]-azi0[i])*(float) j/(float) (n-1);
|
|
alt=alt0[i]+(alt0[i+1]-alt0[i])*(float) j/(float) (n-1);
|
|
azi+=180.0;
|
|
forward(azi,alt,&rx,&ry);
|
|
x=(float) rx;
|
|
y=(float) ry;
|
|
if (j==0)
|
|
giza_move_float(x,y);
|
|
else {
|
|
giza_draw_float(x,y);
|
|
giza_move_float(x,y);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
for (i = 0; i < sizeof (alt1) / sizeof (alt1[0]) - 1; i++)
|
|
{
|
|
for (j = 0; j < n; j++)
|
|
{
|
|
azi =
|
|
azi1[i] + (azi1[i + 1] - azi1[i]) * (float) j / (float) (n - 1);
|
|
alt =
|
|
alt1[i] + (alt1[i + 1] - alt1[i]) * (float) j / (float) (n - 1);
|
|
azi += 180.0;
|
|
forward (azi, alt, &rx, &ry);
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
if (j == 0)
|
|
giza_move_float (x, y);
|
|
else
|
|
{
|
|
giza_draw_float (x, y);
|
|
giza_move_float (x, y);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Plot an horizontal grid
|
|
void
|
|
skymap_plothorizontal_grid ()
|
|
{
|
|
int i, j;
|
|
double rx, ry, azi, alt;
|
|
float x, y;
|
|
float sch;
|
|
int sci, sls, status;
|
|
FILE *file;
|
|
char line[LIM], filename[LIM];
|
|
|
|
// Get setup
|
|
giza_get_character_height_float (&sch);
|
|
giza_get_line_style (&sls);
|
|
giza_get_colour_index (&sci);
|
|
|
|
// Plot grid
|
|
giza_set_colour_index (15);
|
|
giza_set_line_style (2);
|
|
|
|
// Altitudes
|
|
if (m.grid == 1)
|
|
{
|
|
for (alt = 0.0; alt <= 80.0; alt += 20.0)
|
|
{
|
|
for (i = 0; i < m.nmax; i++)
|
|
{
|
|
azi = 360.0 * (double) i / (double) (m.nmax - 1);
|
|
|
|
forward (azi, alt, &rx, &ry);
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
if (i == 0)
|
|
giza_move_float (x, y);
|
|
if (fabs (x) <= 1.5 * m.w && fabs (y) <= m.w)
|
|
{
|
|
giza_draw_float (x, y);
|
|
giza_move_float (x, y);
|
|
}
|
|
else
|
|
giza_move_float (x, y);
|
|
}
|
|
}
|
|
|
|
// Azimuths
|
|
for (azi = 0.0; azi < 360.0; azi += 30.0)
|
|
{
|
|
for (i = 0; i < m.nmax; i++)
|
|
{
|
|
alt = 0.0 + 80.0 * (double) i / (double) (m.nmax - 1);
|
|
|
|
forward (azi, alt, &rx, &ry);
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
if (i == 0)
|
|
giza_move_float (x, y);
|
|
if (fabs (x) <= 1.5 * m.w && fabs (y) <= m.w)
|
|
{
|
|
giza_draw_float (x, y);
|
|
giza_move_float (x, y);
|
|
}
|
|
else
|
|
giza_move_float (x, y);
|
|
}
|
|
}
|
|
}
|
|
giza_set_colour_index (1);
|
|
giza_set_line_style (1);
|
|
|
|
// Plot horizon
|
|
for (i = 0; i < m.nmax; i++)
|
|
{
|
|
azi = 360.0 * (float) i / (float) (m.nmax - 1);
|
|
alt = 0.0;
|
|
|
|
forward (azi, alt, &rx, &ry);
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
if (i == 0)
|
|
giza_move_float (x, y);
|
|
if (fabs (x) <= 1.5 * m.w && fabs (y) <= m.w)
|
|
{
|
|
giza_set_colour_index (255);
|
|
giza_draw_float (x, y);
|
|
giza_move_float (x, y);
|
|
}
|
|
else
|
|
giza_move_float (x, y);
|
|
}
|
|
|
|
// Use real horizon
|
|
sprintf (filename, "%s/data/%04dhorizon.txt", m.datadir, m.site_id);
|
|
file = fopen (filename, "r");
|
|
if (file != NULL)
|
|
{
|
|
i = 0;
|
|
while (fgetline (file, line, LIM) > 0)
|
|
{
|
|
if (strlen (line) < 2)
|
|
{
|
|
i = 0;
|
|
continue;
|
|
}
|
|
status = sscanf (line, "%lf %lf", &azi, &alt);
|
|
forward (azi + 180.0, alt, &rx, &ry);
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
if (i == 0)
|
|
giza_move_float (x, y);
|
|
if (fabs (x) <= 1.5 * m.w && fabs (y) <= m.w)
|
|
{
|
|
giza_set_colour_index (255);
|
|
giza_draw_float (x, y);
|
|
giza_move_float (x, y);
|
|
}
|
|
else
|
|
giza_move_float (x, y);
|
|
i++;
|
|
}
|
|
fclose (file);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Plot an equatorial grid
|
|
void
|
|
skymap_plotequatorial_grid ()
|
|
{
|
|
int i, j;
|
|
double rx, ry, ra, de;
|
|
float x, y;
|
|
float sch;
|
|
int sci, sls;
|
|
|
|
// Get setup
|
|
giza_get_character_height_float (&sch);
|
|
giza_get_line_style (&sls);
|
|
giza_get_colour_index (&sci);
|
|
|
|
// Plot grid
|
|
giza_set_colour_index (15);
|
|
giza_set_line_style (2);
|
|
|
|
// Declinations
|
|
if (m.grid == 1)
|
|
{
|
|
for (de = -80.0; de <= 80.0; de += 20.0)
|
|
{
|
|
for (i = 0; i < m.nmax; i++)
|
|
{
|
|
ra = 360.0 * (double) i / (double) (m.nmax - 1);
|
|
|
|
forward (ra, de, &rx, &ry);
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
if (i == 0)
|
|
giza_move_float (x, y);
|
|
if (fabs (x) <= 1.5 * m.w && fabs (y) <= m.w)
|
|
{
|
|
giza_draw_float (x, y);
|
|
giza_move_float (x, y);
|
|
}
|
|
else
|
|
giza_move_float (x, y);
|
|
}
|
|
}
|
|
|
|
// Right ascensions
|
|
for (ra = 0.0; ra < 360.0; ra += 30.0)
|
|
{
|
|
for (i = 0; i < m.nmax; i++)
|
|
{
|
|
de = -80.0 + 160.0 * (double) i / (double) (m.nmax - 1);
|
|
|
|
forward (ra, de, &rx, &ry);
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
if (i == 0)
|
|
giza_move_float (x, y);
|
|
if (fabs (x) <= 1.5 * m.w && fabs (y) <= m.w)
|
|
{
|
|
giza_draw_float (x, y);
|
|
giza_move_float (x, y);
|
|
}
|
|
else
|
|
giza_move_float (x, y);
|
|
}
|
|
}
|
|
}
|
|
giza_set_colour_index (1);
|
|
giza_set_line_style (1);
|
|
|
|
// Plot equatorial
|
|
for (i = 0; i < m.nmax; i++)
|
|
{
|
|
ra = 360.0 * (float) i / (float) (m.nmax - 1);
|
|
de = 0.0;
|
|
|
|
forward (ra, de, &rx, &ry);
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
if (i == 0)
|
|
giza_move_float (x, y);
|
|
if (fabs (x) <= 1.5 * m.w && fabs (y) <= m.w)
|
|
{
|
|
giza_draw_float (x, y);
|
|
giza_move_float (x, y);
|
|
}
|
|
else
|
|
giza_move_float (x, y);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Plot constellation lines
|
|
void
|
|
skymap_plotconstellations (char *filename)
|
|
{
|
|
int i, flag;
|
|
unsigned long tyc;
|
|
double rx, ry, azi, alt, alt1;
|
|
double ra, de, ra0, de0, mjd0 = 51544.5;
|
|
// double mjd0=48348.3125; // J1991.25
|
|
float x, y, x1, y1;
|
|
char line[LIM];
|
|
FILE *file;
|
|
|
|
giza_set_colour_index (4);
|
|
// Loop over file
|
|
file = fopen (filename, "r");
|
|
if (file == NULL)
|
|
{
|
|
printf ("%s not found!\n", filename);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; fgetline (file, line, LIM) > 0; i++)
|
|
{
|
|
if (strchr (line, '#') != NULL)
|
|
continue;
|
|
sscanf (line, "%lu %i %lf %lf\n", &tyc, &flag, &ra0, &de0);
|
|
precess (mjd0, ra0, de0, m.mjd, &ra, &de);
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
equatorial2horizontal (m.mjd, ra, de, &azi, &alt);
|
|
forward (azi, alt, &rx, &ry);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
forward (ra, de, &rx, &ry);
|
|
}
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
if (i == 0)
|
|
giza_move_float (x, y);
|
|
// if (fabs(x)<=m.w && fabs(y)<=m.w) {
|
|
if (flag == 0)
|
|
giza_move_float (x, y);
|
|
if (flag == 1)
|
|
{
|
|
giza_draw_float (x, y);
|
|
giza_move_float (x, y);
|
|
}
|
|
// } else
|
|
// giza_move_float(x,y);
|
|
}
|
|
fclose (file);
|
|
giza_set_colour_index (1);
|
|
|
|
return;
|
|
}
|
|
|
|
// Convert equatorial into horizontal coordinates
|
|
void
|
|
equatorial2horizontal (double mjd, double ra, double de, double *azi,
|
|
double *alt)
|
|
{
|
|
double h;
|
|
|
|
h = gmst (mjd) + m.lng - ra;
|
|
|
|
*azi =
|
|
modulo (atan2
|
|
(sin (h * D2R),
|
|
cos (h * D2R) * sin (m.lat * D2R) -
|
|
tan (de * D2R) * cos (m.lat * D2R)) * R2D, 360.0);
|
|
*alt =
|
|
asin (sin (m.lat * D2R) * sin (de * D2R) +
|
|
cos (m.lat * D2R) * cos (de * D2R) * cos (h * D2R)) * R2D;
|
|
|
|
return;
|
|
}
|
|
|
|
// Convert equatorial into horizontal coordinates
|
|
void
|
|
graves_equatorial2horizontal (double mjd, double ra, double de, double *azi,
|
|
double *alt)
|
|
{
|
|
double h;
|
|
float lat = 47.3480, lng = 5.5151;
|
|
|
|
h = gmst (mjd) + lng - ra;
|
|
|
|
*azi =
|
|
modulo (atan2
|
|
(sin (h * D2R),
|
|
cos (h * D2R) * sin (lat * D2R) -
|
|
tan (de * D2R) * cos (lat * D2R)) * R2D, 360.0);
|
|
*alt =
|
|
asin (sin (lat * D2R) * sin (de * D2R) +
|
|
cos (lat * D2R) * cos (de * D2R) * cos (h * D2R)) * R2D;
|
|
|
|
return;
|
|
}
|
|
|
|
// Convert horizontal into equatorial coordinates
|
|
void
|
|
horizontal2equatorial (double mjd, double azi, double alt, double *ra,
|
|
double *de)
|
|
{
|
|
double h;
|
|
|
|
h =
|
|
atan2 (sin (azi * D2R),
|
|
cos (azi * D2R) * sin (m.lat * D2R) +
|
|
tan (alt * D2R) * cos (m.lat * D2R)) * R2D;
|
|
*ra = modulo (gmst (mjd) + m.lng - h, 360.0);
|
|
*de =
|
|
asin (sin (m.lat * D2R) * sin (alt * D2R) -
|
|
cos (m.lat * D2R) * cos (alt * D2R) * cos (azi * D2R)) * R2D;
|
|
if (*ra < 0.0)
|
|
*ra += 360.0;
|
|
|
|
return;
|
|
}
|
|
|
|
// Convert horizontal into equatorial coordinates
|
|
void
|
|
graves_horizontal2equatorial (double mjd, double azi, double alt, double *ra,
|
|
double *de)
|
|
{
|
|
double h;
|
|
float lat = 47.3480, lng = 5.5151;
|
|
|
|
h =
|
|
atan2 (sin (azi * D2R),
|
|
cos (azi * D2R) * sin (lat * D2R) +
|
|
tan (alt * D2R) * cos (lat * D2R)) * R2D;
|
|
*ra = modulo (gmst (mjd) + lng - h, 360.0);
|
|
*de =
|
|
asin (sin (lat * D2R) * sin (alt * D2R) -
|
|
cos (lat * D2R) * cos (alt * D2R) * cos (azi * D2R)) * R2D;
|
|
if (*ra < 0.0)
|
|
*ra += 360.0;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// Plot the stars
|
|
void
|
|
skymap_plotstars (char *filename)
|
|
{
|
|
int i, j;
|
|
unsigned long hip;
|
|
double rx, ry, azi, alt;
|
|
double ra, de, ra0, de0, mjd0 = 51544.5;
|
|
// double mjd0=48348.3125; // J1991.25
|
|
float x, y, vmag;
|
|
float rad;
|
|
char line[LIM];
|
|
FILE *file;
|
|
struct star s;
|
|
|
|
if (strstr (filename, "tycho2.dat") != NULL)
|
|
{
|
|
|
|
file = fopen (m.starfile, "rb");
|
|
while (!feof (file))
|
|
{
|
|
fread (&s, sizeof (struct star), 1, file);
|
|
vmag = s.mag;
|
|
ra0 = s.ra;
|
|
de0 = s.de;
|
|
if (vmag <= m.maxmag)
|
|
{
|
|
precess (mjd0, ra0, de0, m.mjd, &ra, &de);
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
equatorial2horizontal (m.mjd, ra, de, &azi, &alt);
|
|
forward (azi, alt, &rx, &ry);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
forward (ra, de, &rx, &ry);
|
|
}
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
|
|
// Star size
|
|
rad =
|
|
m.maxrad + (m.minrad - m.maxrad) * (vmag -
|
|
m.minmag) / (m.maxmag -
|
|
m.minmag);
|
|
rad *= m.w / 90.0;
|
|
giza_set_colour_index (255);
|
|
giza_circle_float (x, y, rad);
|
|
}
|
|
}
|
|
fclose (file);
|
|
}
|
|
else
|
|
{
|
|
// Loop over file
|
|
file = fopen (filename, "r");
|
|
if (file == NULL)
|
|
{
|
|
printf ("Star file not found\n");
|
|
exit (1);
|
|
}
|
|
while (fgetline (file, line, LIM) > 0)
|
|
{
|
|
// Failed for Tycho files
|
|
// sscanf(line,"%i %lf %lf %f\n",&hip,&ra,&de,&vmag);
|
|
// Skipping star ID
|
|
sscanf (line + 13, "%lf %lf %f\n", &ra0, &de0, &vmag);
|
|
|
|
if (vmag <= m.maxmag)
|
|
{
|
|
precess (mjd0, ra0, de0, m.mjd, &ra, &de);
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
equatorial2horizontal (m.mjd, ra, de, &azi, &alt);
|
|
forward (azi, alt, &rx, &ry);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
forward (ra, de, &rx, &ry);
|
|
}
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
|
|
if (fabs (rx) < 0.02 && fabs (ry) < 0.02)
|
|
printf ("%lf %lf %lf %lf %f\n", ra0, de0, ra, de, vmag);
|
|
|
|
// Star size
|
|
rad =
|
|
m.maxrad + (m.minrad - m.maxrad) * (vmag -
|
|
m.minmag) / (m.maxmag -
|
|
m.minmag);
|
|
rad *= m.w / 90.0;
|
|
giza_set_colour_index (255);
|
|
giza_circle_float (x, y, rad);
|
|
}
|
|
}
|
|
fclose (file);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Observer position
|
|
void
|
|
obspos_xyz (double mjd, xyz_t * pos, xyz_t * vel)
|
|
{
|
|
double ff, gc, gs, theta, s, dtheta;
|
|
|
|
s = sin (m.lat * D2R);
|
|
ff = sqrt (1.0 - FLAT * (2.0 - FLAT) * s * s);
|
|
gc = 1.0 / ff + m.alt / XKMPER;
|
|
gs = (1.0 - FLAT) * (1.0 - FLAT) / ff + m.alt / XKMPER;
|
|
|
|
theta = gmst (mjd) + m.lng;
|
|
dtheta = dgmst (mjd) * D2R / 86400;
|
|
|
|
pos->x = gc * cos (m.lat * D2R) * cos (theta * D2R) * XKMPER;
|
|
pos->y = gc * cos (m.lat * D2R) * sin (theta * D2R) * XKMPER;
|
|
pos->z = gs * sin (m.lat * D2R) * XKMPER;
|
|
vel->x = -gc * cos (m.lat * D2R) * sin (theta * D2R) * XKMPER * dtheta;
|
|
vel->y = gc * cos (m.lat * D2R) * cos (theta * D2R) * XKMPER * dtheta;
|
|
vel->z = 0.0;
|
|
|
|
return;
|
|
}
|
|
|
|
// Graves position
|
|
void
|
|
graves_xyz (double mjd, xyz_t * pos, xyz_t * vel)
|
|
{
|
|
double ff, gc, gs, theta, s, dtheta;
|
|
float lat = 47.3480, lng = 5.5151, alt = 0.1;
|
|
|
|
s = sin (lat * D2R);
|
|
ff = sqrt (1.0 - FLAT * (2.0 - FLAT) * s * s);
|
|
gc = 1.0 / ff + alt / XKMPER;
|
|
gs = (1.0 - FLAT) * (1.0 - FLAT) / ff + alt / XKMPER;
|
|
|
|
theta = gmst (mjd) + lng;
|
|
dtheta = dgmst (mjd) * D2R / 86400;
|
|
|
|
pos->x = gc * cos (lat * D2R) * cos (theta * D2R) * XKMPER;
|
|
pos->y = gc * cos (lat * D2R) * sin (theta * D2R) * XKMPER;
|
|
pos->z = gs * sin (lat * D2R) * XKMPER;
|
|
vel->x = -gc * cos (lat * D2R) * sin (theta * D2R) * XKMPER * dtheta;
|
|
vel->y = gc * cos (lat * D2R) * cos (theta * D2R) * XKMPER * dtheta;
|
|
vel->z = 0.0;
|
|
|
|
return;
|
|
}
|
|
|
|
// Plot satellite track
|
|
void
|
|
skymap_plotsatellite (char *filename, int satno, double mjd0, double dt)
|
|
{
|
|
orbit_t orb;
|
|
struct sat s;
|
|
int imode, flag, fflag, i;
|
|
FILE *fp = NULL;
|
|
xyz_t satpos, obspos, satvel, sunpos;
|
|
double mjd, jd, dx, dy, dz;
|
|
double rx, ry, ra, de, azi, alt, r, t;
|
|
float x, y;
|
|
char norad[7], satname[30], date[24];;
|
|
float isch;
|
|
float rsun, rearth, psun, pearth, p;
|
|
int priority[] = { 28888, 37348, 39232, 43941, 48247 };
|
|
char type[8];
|
|
|
|
// Open TLE file
|
|
fp = fopen (filename, "rb");
|
|
if (fp == NULL)
|
|
{
|
|
printf ("Failed to open TLE catalog %s\n", filename);
|
|
exit (1);
|
|
}
|
|
|
|
// Read TLEs
|
|
while (read_twoline (fp, satno, &orb) == 0)
|
|
{
|
|
Isat = orb.satno;
|
|
imode = init_sgdp4 (&orb);
|
|
|
|
if (orb.rev >= 10.0)
|
|
strcpy (type, "LEO");
|
|
else if (orb.rev < 10.0 && orb.eqinc * R2D > 50.0 && orb.ecc > 0.5)
|
|
strcpy (type, "HEO");
|
|
else if (orb.rev < 10.0 && orb.eqinc * R2D <= 50.0 && orb.ecc > 0.5)
|
|
strcpy (type, "GTO");
|
|
else
|
|
strcpy (type, "GEO");
|
|
|
|
if (m.leoflag == 1 && strcmp (type, "LEO") != 0)
|
|
continue;
|
|
if (m.leoflag == 2 && strcmp (type, "HEO") != 0)
|
|
continue;
|
|
if (m.leoflag == 3 && strcmp (type, "GEO") != 0)
|
|
continue;
|
|
if (m.leoflag == 4 && strcmp (type, "GTO") != 0)
|
|
continue;
|
|
|
|
sprintf (norad, " %ld", Isat);
|
|
|
|
if (imode == SGDP4_ERROR)
|
|
continue;
|
|
|
|
for (flag = 0, fflag = 0, t = 0.0; t <= dt; t += 1.0)
|
|
{
|
|
mjd = mjd0 + t / 86400.0;
|
|
|
|
// Compute apparent position
|
|
s = apparent_position (mjd);
|
|
|
|
// Skip bogus positions
|
|
if (s.h > 300000)
|
|
continue;
|
|
|
|
if (m.agelimit > 0 && s.age < m.agelimit)
|
|
continue;
|
|
|
|
// Convert to float
|
|
x = (float) s.rx;
|
|
y = (float) s.ry;
|
|
|
|
// Visibility
|
|
if (s.p - s.pearth < -s.psun)
|
|
{
|
|
giza_set_colour_index (14);
|
|
}
|
|
else if (s.p - s.pearth > -s.psun && s.p - s.pearth < s.psun)
|
|
{
|
|
giza_set_colour_index (15);
|
|
}
|
|
else if (s.p - s.pearth > s.psun)
|
|
{
|
|
for (i = 0; i < sizeof (priority) / sizeof (priority[0]); i++)
|
|
{
|
|
if (Isat == priority[i])
|
|
{
|
|
giza_set_colour_index (2);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (s.salt < 0.0)
|
|
giza_set_colour_index (7);
|
|
else
|
|
giza_set_colour_index (8);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Graves colouring
|
|
if (m.graves != 0)
|
|
{
|
|
if (s.illumg == 1)
|
|
giza_set_colour_index (2);
|
|
else
|
|
giza_set_colour_index (14);
|
|
}
|
|
|
|
// In field of view
|
|
if (fabs (x) < m.fw && fabs (y) < m.fh && fflag == 0)
|
|
{
|
|
mjd2date (mjd, date);
|
|
printf ("%.19s %05ld %6.1f %7.1f d %9.2f km %6.2f deg\n", date,
|
|
Isat, s.mag, s.age, s.r, s.phase);
|
|
fflag = 1;
|
|
}
|
|
|
|
// Plot satellites
|
|
if (flag == 0)
|
|
{
|
|
giza_set_character_height_float (0.8);
|
|
if (s.age < 25)
|
|
giza_single_point_float (x, y, 17);
|
|
else if (s.age < 50)
|
|
giza_single_point_float (x, y, 4);
|
|
else
|
|
giza_single_point_float (x, y, 6);
|
|
giza_set_character_height_float (0.6);
|
|
|
|
// Print name if in viewport
|
|
if (fabs (x) < 1.5 * m.w && fabs (y) < m.w && x < 1.32 * m.w
|
|
&& y < 0.96 * m.w && m.pflag == 1)
|
|
giza_text_float (x, y, norad);
|
|
giza_set_character_height_float (isch);
|
|
giza_move_float (x, y);
|
|
flag = 1;
|
|
}
|
|
else
|
|
{
|
|
giza_draw_float (x, y);
|
|
giza_move_float (x, y);
|
|
}
|
|
}
|
|
}
|
|
fclose (fp);
|
|
giza_set_colour_index (1);
|
|
|
|
return;
|
|
}
|
|
|
|
// Solar position
|
|
void
|
|
sunpos_xyz (double mjd, xyz_t * pos, double *ra, double *de)
|
|
{
|
|
double jd, t, l0, m, e, c, r;
|
|
double n, s, ecl;
|
|
|
|
jd = mjd + 2400000.5;
|
|
t = (jd - 2451545.0) / 36525.0;
|
|
l0 = modulo (280.46646 + t * (36000.76983 + t * 0.0003032), 360.0) * D2R;
|
|
m = modulo (357.52911 + t * (35999.05029 - t * 0.0001537), 360.0) * D2R;
|
|
e = 0.016708634 + t * (-0.000042037 - t * 0.0000001267);
|
|
c = (1.914602 + t * (-0.004817 - t * 0.000014)) * sin (m) * D2R;
|
|
c += (0.019993 - 0.000101 * t) * sin (2.0 * m) * D2R;
|
|
c += 0.000289 * sin (3.0 * m) * D2R;
|
|
|
|
r = 1.000001018 * (1.0 - e * e) / (1.0 + e * cos (m + c));
|
|
n = modulo (125.04 - 1934.136 * t, 360.0) * D2R;
|
|
s = l0 + c + (-0.00569 - 0.00478 * sin (n)) * D2R;
|
|
ecl =
|
|
(23.43929111 +
|
|
(-46.8150 * t - 0.00059 * t * t + 0.001813 * t * t * t) / 3600.0 +
|
|
0.00256 * cos (n)) * D2R;
|
|
|
|
*ra = atan2 (cos (ecl) * sin (s), cos (s)) * R2D;
|
|
*de = asin (sin (ecl) * sin (s)) * R2D;
|
|
|
|
pos->x = r * cos (*de * D2R) * cos (*ra * D2R) * XKMPAU;
|
|
pos->y = r * cos (*de * D2R) * sin (*ra * D2R) * XKMPAU;
|
|
pos->z = r * sin (*de * D2R) * XKMPAU;
|
|
|
|
return;
|
|
}
|
|
|
|
// Compute Julian Day from Date
|
|
double
|
|
date2mjd (int year, int month, double day)
|
|
{
|
|
int a, b;
|
|
double jd;
|
|
|
|
if (month < 3)
|
|
{
|
|
year--;
|
|
month += 12;
|
|
}
|
|
|
|
a = floor (year / 100.);
|
|
b = 2. - a + floor (a / 4.);
|
|
|
|
if (year < 1582)
|
|
b = 0;
|
|
if (year == 1582 && month < 10)
|
|
b = 0;
|
|
if (year == 1582 && month == 10 && day <= 4)
|
|
b = 0;
|
|
|
|
jd =
|
|
floor (365.25 * (year + 4716)) + floor (30.6001 * (month + 1)) + day + b -
|
|
1524.5;
|
|
|
|
return jd - 2400000.5;
|
|
}
|
|
|
|
// Present nfd
|
|
void
|
|
nfd_now (char *s)
|
|
{
|
|
time_t rawtime;
|
|
struct tm *ptm;
|
|
|
|
// Get UTC time
|
|
time (&rawtime);
|
|
ptm = gmtime (&rawtime);
|
|
|
|
sprintf (s, "%04d-%02d-%02dT%02d:%02d:%02d", ptm->tm_year + 1900,
|
|
ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min,
|
|
ptm->tm_sec);
|
|
|
|
return;
|
|
}
|
|
|
|
// nfd2mjd
|
|
double
|
|
nfd2mjd (char *date)
|
|
{
|
|
int year, month, day, hour, min;
|
|
double mjd, dday, sec;
|
|
|
|
sscanf (date, "%04d-%02d-%02dT%02d:%02d:%lf", &year, &month, &day, &hour,
|
|
&min, &sec);
|
|
dday =
|
|
(double) day + (double) hour / 24.0 + (double) min / 1440.0 +
|
|
sec / 86400.0;
|
|
|
|
mjd = date2mjd (year, month, dday);
|
|
|
|
return mjd;
|
|
}
|
|
|
|
|
|
// Computes apparent position
|
|
struct sat
|
|
apparent_position (double mjd)
|
|
{
|
|
struct sat s;
|
|
double jd, rsun, rearth, rsat;
|
|
double dx, dy, dz, dvx, dvy, dvz, vtot;
|
|
xyz_t satpos, obspos, obsvel, satvel, sunpos, grvpos, grvvel;
|
|
double sra, sde, azi;
|
|
|
|
// Sat ID
|
|
s.Isat = Isat;
|
|
|
|
// Get Julian Date
|
|
jd = mjd + 2400000.5;
|
|
|
|
// Get positions
|
|
obspos_xyz (mjd, &obspos, &obsvel);
|
|
satpos_xyz (jd, &satpos, &satvel);
|
|
sunpos_xyz (mjd, &sunpos, &sra, &sde);
|
|
|
|
// Sun altitude
|
|
equatorial2horizontal (mjd, sra, sde, &azi, &s.salt);
|
|
|
|
// Age
|
|
s.age = jd - SGDP4_jd0;
|
|
|
|
// Sat positions
|
|
s.x = satpos.x;
|
|
s.y = satpos.y;
|
|
s.z = satpos.z;
|
|
s.vx = satvel.x;
|
|
s.vy = satvel.y;
|
|
s.vz = satvel.z;
|
|
|
|
// Sun position from satellite
|
|
dx = -satpos.x + sunpos.x;
|
|
dy = -satpos.y + sunpos.y;
|
|
dz = -satpos.z + sunpos.z;
|
|
|
|
// Distances
|
|
rsun = sqrt (dx * dx + dy * dy + dz * dz);
|
|
rearth =
|
|
sqrt (satpos.x * satpos.x + satpos.y * satpos.y + satpos.z * satpos.z);
|
|
s.h = rearth - XKMPER;
|
|
// Angles
|
|
s.psun = asin (696.0e3 / rsun) * R2D;
|
|
s.pearth = asin (6378.135 / rearth) * R2D;
|
|
s.p =
|
|
acos ((-dx * satpos.x - dy * satpos.y -
|
|
dz * satpos.z) / (rsun * rearth)) * R2D;
|
|
|
|
// Visibility state
|
|
if (s.p - s.pearth < -s.psun)
|
|
strcpy (s.state, "eclipsed");
|
|
else if (s.p - s.pearth > -s.psun && s.p - s.pearth < s.psun)
|
|
strcpy (s.state, "umbra");
|
|
else if (s.p - s.pearth > s.psun)
|
|
strcpy (s.state, "sunlit");
|
|
|
|
// Position differences
|
|
dx = satpos.x - obspos.x;
|
|
dy = satpos.y - obspos.y;
|
|
dz = satpos.z - obspos.z;
|
|
dvx = satvel.x - obsvel.x;
|
|
dvy = satvel.y - obsvel.y;
|
|
dvz = satvel.z - obsvel.z;
|
|
|
|
// Celestial position
|
|
s.r = sqrt (dx * dx + dy * dy + dz * dz);
|
|
s.v = (dvx * dx + dvy * dy + dvz * dz) / s.r;
|
|
s.ra = modulo (atan2 (dy, dx) * R2D, 360.0);
|
|
s.de = asin (dz / s.r) * R2D;
|
|
|
|
// Angular velocity
|
|
vtot = sqrt (dvx * dvx + dvy * dvy + dvz * dvz);
|
|
s.vang = sqrt (vtot * vtot - s.v * s.v) / s.r * R2D;
|
|
|
|
// Phase
|
|
s.phase =
|
|
acos (((obspos.x - satpos.x) * (sunpos.x - satpos.x) +
|
|
(obspos.y - satpos.y) * (sunpos.y - satpos.y) + (obspos.z -
|
|
satpos.z) *
|
|
(sunpos.z - satpos.z)) / (rsun * s.r)) * R2D;
|
|
|
|
// Magnitude
|
|
if (strcmp (s.state, "sunlit") == 0)
|
|
s.mag =
|
|
STDMAG - 15.0 + 5 * log10 (s.r) - 2.5 * log10 (sin (s.phase * D2R) +
|
|
(M_PI -
|
|
s.phase * D2R) *
|
|
cos (s.phase * D2R));
|
|
else
|
|
s.mag = 15;
|
|
|
|
|
|
// Convert and project
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
equatorial2horizontal (mjd, s.ra, s.de, &s.azi, &s.alt);
|
|
forward (s.azi, s.alt, &s.rx, &s.ry);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
forward (s.ra, s.de, &s.rx, &s.ry);
|
|
}
|
|
|
|
// Compute position at Graves
|
|
if (m.graves != 0)
|
|
{
|
|
graves_xyz (mjd, &grvpos, &grvvel);
|
|
dx = satpos.x - grvpos.x;
|
|
dy = satpos.y - grvpos.y;
|
|
dz = satpos.z - grvpos.z;
|
|
dvx = satvel.x - grvvel.x;
|
|
dvy = satvel.y - grvvel.y;
|
|
dvz = satvel.z - grvvel.z;
|
|
|
|
// Celestial position
|
|
s.rg = sqrt (dx * dx + dy * dy + dz * dz);
|
|
s.vg = (dvx * dx + dvy * dy + dvz * dz) / s.rg;
|
|
s.rag = modulo (atan2 (dy, dx) * R2D, 360.0);
|
|
s.deg = asin (dz / s.rg) * R2D;
|
|
graves_equatorial2horizontal (mjd, s.rag, s.deg, &s.azig, &s.altg);
|
|
|
|
// Illuminated?
|
|
if (s.altg >= 15.0 && s.altg <= 40.0
|
|
&& modulo (s.azig - 180.0, 360.0) >= 90.0
|
|
&& modulo (s.azig - 180.0, 360.0) <= 270.0)
|
|
s.illumg = 1;
|
|
else
|
|
s.illumg = 0;
|
|
}
|
|
else
|
|
{
|
|
s.illumg = 0;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
// Planar search
|
|
void
|
|
planar_search (char *filename, int satno, float rmin, float rmax, int nr,
|
|
int graves)
|
|
{
|
|
int i, j, imode;
|
|
FILE *fp;
|
|
orbit_t orb;
|
|
kep_t K;
|
|
int withvel, rv;
|
|
double tsince, radius, jd;
|
|
double st, ct, sn, cn, si, ci, t;
|
|
xyz_t satpos, obspos, obsvel, sunpos, grvpos, grvvel;
|
|
double r, ra, de, dx, dy, dz, rsun, rearth, psun, pearth, p, azi, alt, rx,
|
|
ry, rx0, ry0, ra0, de0, rx1, ry1, altmax;
|
|
double sra, sde;
|
|
double rg, rag, deg, azig, altg;
|
|
float phase, mag, mmin;
|
|
char state[10];
|
|
int illumg;
|
|
|
|
// Open TLE file
|
|
fp = fopen (filename, "rb");
|
|
if (fp == NULL)
|
|
{
|
|
printf ("Failed to open TLE catalog %s\n", filename);
|
|
exit (1);
|
|
}
|
|
|
|
// Read TLEs
|
|
while (read_twoline (fp, satno, &orb) == 0)
|
|
{
|
|
Isat = orb.satno;
|
|
imode = init_sgdp4 (&orb);
|
|
|
|
if (imode == SGDP4_ERROR)
|
|
continue;
|
|
|
|
}
|
|
fclose (fp);
|
|
|
|
// Get Julian Date
|
|
jd = m.mjd + 2400000.5;
|
|
|
|
// Get kepler
|
|
tsince = 1440.0 * (jd - SGDP4_jd0);
|
|
rv = sgdp4 (tsince, 1, &K);
|
|
|
|
// Angles
|
|
sn = sin (K.ascn);
|
|
cn = cos (K.ascn);
|
|
si = sin (K.eqinc);
|
|
ci = cos (K.eqinc);
|
|
|
|
// Loop over radii
|
|
for (j = 0; j < nr; j++)
|
|
{
|
|
if (nr > 1)
|
|
radius = rmin + (rmax - rmin) * (float) j / (float) (nr - 1);
|
|
else
|
|
radius = rmin;
|
|
|
|
// Loop over angles
|
|
for (i = 0, mmin = 15.0, altmax = 0.0; i < MMAX; i++)
|
|
{
|
|
t = 2.0 * M_PI * (double) i / (double) (MMAX - 1);
|
|
st = sin (K.theta + t);
|
|
ct = cos (K.theta + t);
|
|
|
|
satpos.x = -sn * ci * st + cn * ct;
|
|
satpos.y = cn * ci * st + sn * ct;
|
|
satpos.z = si * st;
|
|
satpos.x *= (radius + XKMPER);
|
|
satpos.y *= (radius + XKMPER);
|
|
satpos.z *= (radius + XKMPER);
|
|
|
|
// Get positions
|
|
obspos_xyz (m.mjd, &obspos, &obsvel);
|
|
sunpos_xyz (m.mjd, &sunpos, &sra, &sde);
|
|
|
|
// Sun position from satellite
|
|
dx = -satpos.x + sunpos.x;
|
|
dy = -satpos.y + sunpos.y;
|
|
dz = -satpos.z + sunpos.z;
|
|
|
|
// Distances
|
|
rsun = sqrt (dx * dx + dy * dy + dz * dz);
|
|
rearth =
|
|
sqrt (satpos.x * satpos.x + satpos.y * satpos.y +
|
|
satpos.z * satpos.z);
|
|
// Angles
|
|
psun = asin (696.0e3 / rsun) * R2D;
|
|
pearth = asin (6378.135 / rearth) * R2D;
|
|
p =
|
|
acos ((-dx * satpos.x - dy * satpos.y -
|
|
dz * satpos.z) / (rsun * rearth)) * R2D;
|
|
p -= pearth;
|
|
|
|
// Position differences
|
|
dx = satpos.x - obspos.x;
|
|
dy = satpos.y - obspos.y;
|
|
dz = satpos.z - obspos.z;
|
|
|
|
// Celestial position
|
|
r = sqrt (dx * dx + dy * dy + dz * dz);
|
|
ra = atan2 (dy, dx) * R2D;
|
|
de = asin (dz / r) * R2D;
|
|
|
|
// Convert and project
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
equatorial2horizontal (m.mjd, ra, de, &azi, &alt);
|
|
forward (azi, alt, &rx, &ry);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
forward (ra, de, &rx, &ry);
|
|
}
|
|
|
|
// Visibility
|
|
if (p < -psun)
|
|
{
|
|
strcpy (state, "eclipsed");
|
|
giza_set_colour_index (14);
|
|
}
|
|
else if (p > -psun && p < psun)
|
|
{
|
|
strcpy (state, "umbra");
|
|
giza_set_colour_index (15);
|
|
}
|
|
else if (p > psun)
|
|
{
|
|
strcpy (state, "sunlit");
|
|
giza_set_colour_index (7);
|
|
}
|
|
|
|
// Phase
|
|
phase =
|
|
acos (((obspos.x - satpos.x) * (sunpos.x - satpos.x) +
|
|
(obspos.y - satpos.y) * (sunpos.y - satpos.y) + (obspos.z -
|
|
satpos.z)
|
|
* (sunpos.z - satpos.z)) / (rsun * r)) * R2D;
|
|
|
|
// Magnitude
|
|
if (strcmp (state, "sunlit") == 0)
|
|
mag =
|
|
STDMAG - 15.0 + 5 * log10 (r) - 2.5 * log10 (sin (phase * D2R) +
|
|
(M_PI -
|
|
phase * D2R) *
|
|
cos (phase * D2R));
|
|
else
|
|
mag = 15;
|
|
|
|
if (mag < mmin)
|
|
{
|
|
rx0 = rx;
|
|
ry0 = ry;
|
|
mmin = mag;
|
|
}
|
|
|
|
if (alt > 0.0 && alt > altmax && mag < 15.0)
|
|
{
|
|
rx1 = rx;
|
|
ry1 = ry;
|
|
altmax = alt;
|
|
}
|
|
|
|
// Compute position at Graves
|
|
if (graves != 0)
|
|
{
|
|
graves_xyz (m.mjd, &grvpos, &grvvel);
|
|
dx = satpos.x - grvpos.x;
|
|
dy = satpos.y - grvpos.y;
|
|
dz = satpos.z - grvpos.z;
|
|
|
|
// Celestial position
|
|
rg = sqrt (dx * dx + dy * dy + dz * dz);
|
|
rag = modulo (atan2 (dy, dx) * R2D, 360.0);
|
|
deg = asin (dz / rg) * R2D;
|
|
graves_equatorial2horizontal (m.mjd, rag, deg, &azig, &altg);
|
|
|
|
// Illuminated?
|
|
if (altg >= 15.0 && altg <= 40.0
|
|
&& modulo (azig - 180.0, 360.0) >= 90.0
|
|
&& modulo (azig - 180.0, 360.0) <= 270.0)
|
|
giza_set_colour_index (2);
|
|
else
|
|
giza_set_colour_index (15);
|
|
}
|
|
if (i == 0)
|
|
giza_move_float ((float) rx, (float) ry);
|
|
else
|
|
{
|
|
giza_draw_float ((float) rx, (float) ry);
|
|
giza_move_float ((float) rx, (float) ry);
|
|
}
|
|
giza_set_colour_index (1);
|
|
}
|
|
|
|
// Plot brightest point
|
|
if (graves == 0)
|
|
{
|
|
giza_set_character_height_float (1.0);
|
|
giza_set_colour_index (7);
|
|
giza_single_point_float ((float) rx0, (float) ry0, 4);
|
|
if (altmax > 0.0)
|
|
giza_single_point_float ((float) rx1, (float) ry1, 17);
|
|
giza_set_colour_index (1);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Print TLE
|
|
int
|
|
print_tle (char *filename, int satno)
|
|
{
|
|
FILE *fp;
|
|
struct sat s;
|
|
orbit_t orb;
|
|
char line[LIM], pline[LIM];
|
|
int flag = 0;
|
|
|
|
// Open TLE file
|
|
fp = fopen (filename, "rb");
|
|
if (fp == NULL)
|
|
{
|
|
printf ("Failed to open TLE catalog %s\n", filename);
|
|
exit (1);
|
|
}
|
|
|
|
// Read TLEs
|
|
while (fgetline (fp, line, LIM) > 0)
|
|
{
|
|
sscanf (line + 2, "%ld", &Isat);
|
|
if (line[0] == '1' && (long) Isat == satno)
|
|
{
|
|
printf ("\n%s%s", pline, line);
|
|
fgetline (fp, line, LIM);
|
|
printf ("%s\n", line);
|
|
flag = 1;
|
|
}
|
|
|
|
strcpy (pline, line);
|
|
}
|
|
fclose (fp);
|
|
|
|
return flag;
|
|
}
|
|
|
|
// Identify satellite
|
|
long
|
|
identify_satellite (char *filename, int satno, double mjd, float rx, float ry)
|
|
{
|
|
long Isatmin = 0;
|
|
int imode;
|
|
FILE *fp;
|
|
struct sat s, smin;
|
|
orbit_t orb;
|
|
float dr, drmin, agemin;
|
|
char line[LIM], pline[LIM];
|
|
char sra[16], sde[16];
|
|
float lat, lng;
|
|
double mjd0, ra0, de0;
|
|
|
|
// Open TLE file
|
|
fp = fopen (filename, "rb");
|
|
if (fp == NULL)
|
|
{
|
|
printf ("Failed to open TLE catalog %s\n", filename);
|
|
exit (1);
|
|
}
|
|
|
|
// Read TLEs
|
|
while (read_twoline (fp, satno, &orb) == 0)
|
|
{
|
|
Isat = orb.satno;
|
|
imode = init_sgdp4 (&orb);
|
|
|
|
if (imode == SGDP4_ERROR)
|
|
continue;
|
|
|
|
// Compute apparent position
|
|
s = apparent_position (mjd);
|
|
|
|
// Offset
|
|
dr = sqrt (pow (rx - s.rx, 2) + pow (ry - s.ry, 2));
|
|
|
|
if (Isatmin == 0 || dr < drmin)
|
|
{
|
|
Isatmin = Isat;
|
|
drmin = dr;
|
|
smin = s;
|
|
}
|
|
}
|
|
fclose (fp);
|
|
|
|
// Latitude and longitude
|
|
lng = modulo (atan2 (smin.y, smin.x) * R2D - gmst (mjd), 360.0);
|
|
if (lng > 180.0)
|
|
lng -= 360.0;
|
|
if (lng < -180.0)
|
|
lng += 360.0;
|
|
lat = asin (smin.z / (smin.h + XKMPER)) * R2D;
|
|
|
|
// Print TLE
|
|
print_tle (filename, Isatmin);
|
|
printf ("Age: %.1f d\n\n", smin.age);
|
|
printf
|
|
("x: %+12.4lf km; vx: %+8.5f km/s\ny: %+12.4lf km; vy: %+8.5f km/s\nz: %+12.4lf km; vz: %+8.5f km/s\nr: %10.2lf km; v: %6.3f km/s\nl: %6.2lf; b: %6.2lf; h: %10.2lf km\n\n",
|
|
smin.x, smin.vx, smin.y, smin.vy, smin.z, smin.vz, smin.r, smin.v, lng,
|
|
lat, smin.h);
|
|
dec2s (smin.ra / 15.0, sra, 0, 5);
|
|
dec2s (smin.de, sde, 0, 4);
|
|
|
|
printf ("R.A.: %s Decl.: %s\n", sra, sde);
|
|
|
|
// Precess position to J2000
|
|
mjd0 = 51544.5;
|
|
precess (mjd, smin.ra, smin.de, mjd0, &ra0, &de0);
|
|
dec2s (ra0 / 15.0, sra, 0, 5);
|
|
dec2s (de0, sde, 0, 4);
|
|
printf ("R.A.: %s Decl.: %s (J2000)\n", sra, sde);
|
|
printf ("Azi.: %.1f Alt.: %.1f\n\n", modulo (smin.azi - 180.0, 360.0),
|
|
smin.alt);
|
|
|
|
printf ("Phase: %.2f\nMagnitude: %.2f\nAngular velocity: %.4f (deg/s)\n",
|
|
smin.phase, smin.mag, smin.vang);
|
|
|
|
return Isatmin;
|
|
}
|
|
|
|
double
|
|
parallactic_angle (double mjd, double ra, double de)
|
|
{
|
|
double h, q;
|
|
|
|
h = gmst (mjd) + m.lng - ra;
|
|
|
|
q =
|
|
atan2 (sin (h * D2R),
|
|
(tan (m.lat * D2R) * cos (de * D2R) -
|
|
sin (de * D2R) * cos (h * D2R))) * R2D;
|
|
if (fabs (m.lat - de) < 0.001)
|
|
q = 0.0;
|
|
|
|
return q;
|
|
}
|
|
|
|
void
|
|
skymap_plotmoon (void)
|
|
{
|
|
double rx, ry, ra, de, azi, alt;
|
|
xyz_t lunpos;
|
|
|
|
// Get moon position
|
|
lunpos_xyz (m.mjd, &lunpos, &ra, &de);
|
|
equatorial2horizontal (m.mjd, ra, de, &azi, &alt);
|
|
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
forward (azi, alt, &rx, &ry);
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
forward (ra, de, &rx, &ry);
|
|
|
|
giza_set_colour_index (14);
|
|
if (m.w > 60.0)
|
|
giza_circle_float ((float) rx, (float) ry, 2.0);
|
|
else
|
|
giza_circle_float ((float) rx, (float) ry, 0.25);
|
|
giza_set_colour_index (1);
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
skymap_plotsun (void)
|
|
{
|
|
double rx, ry;
|
|
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
forward (m.sazi, m.salt, &rx, &ry);
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
forward (m.sra, m.sde, &rx, &ry);
|
|
|
|
giza_set_colour_index (7);
|
|
if (m.w > 60.0)
|
|
giza_circle_float ((float) rx, (float) ry, 2.0);
|
|
else
|
|
giza_circle_float ((float) rx, (float) ry, 0.25);
|
|
giza_set_colour_index (1);
|
|
|
|
return;
|
|
}
|
|
|
|
int
|
|
read_camera (int no)
|
|
{
|
|
int i = 0;
|
|
float f, f2;
|
|
char s[31];
|
|
FILE *file;
|
|
char line[LIM], filename[LIM];
|
|
|
|
sprintf (filename, "%s/data/cameras.txt", m.datadir);
|
|
file = fopen (filename, "r");
|
|
if (file == NULL)
|
|
{
|
|
printf ("Failed to open %s\n", filename);
|
|
return -1;
|
|
}
|
|
while (fgets (line, LIM, file) != NULL)
|
|
{
|
|
// Skip
|
|
if (strstr (line, "#") != NULL)
|
|
continue;
|
|
if (i == no)
|
|
{
|
|
f2 = -90;
|
|
// Retrieve complete line of selected camera parameters
|
|
sscanf (line, "%s %f %f %f %f %s %s %f %f", m.camera, &m.fw, &m.fh,
|
|
&f, &f, s, s, &f, &f2);
|
|
if (f2 >= 0)
|
|
{
|
|
// if Elevation is set, center map to camera position
|
|
m.azi0 = (double) f;
|
|
m.alt0 = (double) f2;
|
|
horizontal2equatorial (m.mjd, m.azi0, m.alt0, &m.ra0, &m.de0);
|
|
}
|
|
m.fw *= 0.5;
|
|
m.fh *= 0.5;
|
|
return 0;
|
|
}
|
|
i++;
|
|
}
|
|
fclose (file);
|
|
|
|
|
|
return -1;
|
|
}
|
|
|
|
// plot skymap
|
|
int
|
|
plot_skymap (void)
|
|
{
|
|
int redraw = 1, fov = 0, status;
|
|
float x, y;
|
|
char c, text[256], sra[16], sde[16], filename[LIM];
|
|
double ra, de, azi, alt, rx, ry;
|
|
xyz_t sunpos;
|
|
giza_set_colour_palette (1);
|
|
giza_set_font ("Helvetica");
|
|
|
|
status = read_camera (fov);
|
|
if (status == -1)
|
|
{
|
|
fov = 0;
|
|
status = read_camera (fov);
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
if (redraw > 0)
|
|
{
|
|
// Get present mjd
|
|
if (m.mjd < 0.0)
|
|
{
|
|
nfd_now (m.nfd);
|
|
m.mjd = nfd2mjd (m.nfd);
|
|
}
|
|
|
|
// Get locations
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
horizontal2equatorial (m.mjd, m.azi0, m.alt0, &m.ra0, &m.de0);
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
equatorial2horizontal (m.mjd, m.ra0, m.de0, &m.azi0, &m.alt0);
|
|
|
|
// Parallactic angle
|
|
m.q = parallactic_angle (m.mjd, m.ra0, m.de0);
|
|
|
|
// Get sun position
|
|
sunpos_xyz (m.mjd, &sunpos, &m.sra, &m.sde);
|
|
equatorial2horizontal (m.mjd, m.sra, m.sde, &m.sazi, &m.salt);
|
|
|
|
giza_set_colour_representation_float (0, 0.0, 0.0, 0.0);
|
|
giza_draw_background ();
|
|
|
|
// Create window
|
|
giza_set_viewport_float (0.01, 0.99, 0.01, 0.99);
|
|
giza_set_window_equal_scale_float (-1.5 * m.w, 1.5 * m.w, -m.w, m.w);
|
|
|
|
// Set background
|
|
if (m.salt > 0.0)
|
|
giza_set_colour_representation_float (0, 0.0, 0.0, 0.4);
|
|
else if (m.salt > -6.0)
|
|
giza_set_colour_representation_float (0, 0.0, 0.0, 0.3);
|
|
else if (m.salt > -12.0)
|
|
giza_set_colour_representation_float (0, 0.0, 0.0, 0.2);
|
|
else if (m.salt > -18.0)
|
|
giza_set_colour_representation_float (0, 0.0, 0.0, 0.1);
|
|
else
|
|
giza_set_colour_representation_float (0, 0.0, 0.0, 0.0);
|
|
giza_set_colour_index (0);
|
|
giza_rectangle (-1.5 * m.w, 1.5 * m.w, -m.w, m.w);
|
|
giza_set_colour_index (15);
|
|
giza_set_character_height_float (1.0);
|
|
giza_box ("BC", 0., 0, "BC", 0., 0);
|
|
giza_single_point_float (0.0, 0.0, 2);
|
|
|
|
// Plot field-of-view
|
|
if (fov >= 0)
|
|
{
|
|
giza_set_fill (2);
|
|
|
|
giza_rectangle (-m.fw, m.fw, -m.fh, m.fh);
|
|
giza_set_fill (1);
|
|
}
|
|
|
|
|
|
// Top left string
|
|
giza_set_character_height_float (0.8);
|
|
giza_set_colour_index (15);
|
|
mjd2date (m.mjd, m.nfd);
|
|
sprintf (text,
|
|
"%s UTC; %s (%04d) [%+.4f\\u\\(2218)\\d, %+.4f\\u\\(2218)\\d, %.0fm]",
|
|
m.nfd, m.observer, m.site_id, m.lat, m.lng,
|
|
m.alt * 1000.0);
|
|
giza_annotate_float ("T", 0.6, 0.0, 0.0, text);
|
|
|
|
// Top right string
|
|
if (m.planar == 0)
|
|
{
|
|
if (Isatsel == 0)
|
|
{
|
|
if (m.leoflag == -1)
|
|
sprintf (text, "None");
|
|
else if (m.leoflag == 0)
|
|
sprintf (text, "All");
|
|
else if (m.leoflag == 1)
|
|
sprintf (text, "LEO");
|
|
else if (m.leoflag == 2)
|
|
sprintf (text, "HEO");
|
|
else if (m.leoflag == 3)
|
|
sprintf (text, "GEO");
|
|
else if (m.leoflag == 4)
|
|
sprintf (text, "GTO");
|
|
}
|
|
else if (Isatsel > 0)
|
|
{
|
|
sprintf (text, "%05d", (int) Isatsel);
|
|
}
|
|
else
|
|
{
|
|
strcpy (text, "");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Isatsel == 0)
|
|
{
|
|
if (m.leoflag == 0)
|
|
sprintf (text, "Planar search: %05d; All", m.pssatno);
|
|
else if (m.leoflag == 1)
|
|
sprintf (text, "Planar search: %05d; LEO", m.pssatno);
|
|
else if (m.leoflag == 2)
|
|
sprintf (text, "Planar search: %05d; HEO", m.pssatno);
|
|
else if (m.leoflag == 3)
|
|
sprintf (text, "Planar search: %05d; GEO", m.pssatno);
|
|
else if (m.leoflag == 4)
|
|
sprintf (text, "Planar search: %05d; GTO", m.pssatno);
|
|
}
|
|
else if (Isatsel > 0)
|
|
{
|
|
sprintf (text, "Planar search: %05d; %05d", m.pssatno,
|
|
(int) Isatsel);
|
|
}
|
|
else
|
|
{
|
|
sprintf (text, "Planar search: %05d", m.pssatno);
|
|
}
|
|
}
|
|
giza_annotate_float ("T", 0.6, 1.0, 1.0, text);
|
|
|
|
// Bottom string
|
|
dec2s (m.ra0 / 15.0, sra, 0, 5);
|
|
dec2s (m.de0, sde, 0, 4);
|
|
sprintf (text,
|
|
"R:%s; D:%s; A: %.1f; E: %.1f; q: %.2f; S: %.1fx%.1f deg; L: %d; O: %s; m < %.1f; C: %s; l: %.0f s",
|
|
sra, sde, modulo (m.azi0 - 180.0, 360.0), m.alt0, m.q,
|
|
3.0 * m.w, 2.0 * m.w, m.level, m.orientation, m.maxmag,
|
|
m.camera, m.length);
|
|
giza_annotate_float ("B", 1.0, 0.0, 0.0, text);
|
|
giza_set_character_height_float (1.0);
|
|
|
|
// Plot everything
|
|
if (m.plotstars == 1)
|
|
{
|
|
sprintf (filename, "%s/data/constfig.dat", m.datadir);
|
|
skymap_plotconstellations (filename);
|
|
skymap_plotstars (m.starfile);
|
|
}
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
skymap_plothorizontal_grid ();
|
|
horizontal2equatorial (m.mjd, m.azi0, m.alt0, &m.ra0, &m.de0);
|
|
// skymap_plot_fov();
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
skymap_plotequatorial_grid ();
|
|
equatorial2horizontal (m.mjd, m.ra0, m.de0, &m.azi0, &m.alt0);
|
|
}
|
|
skymap_plotsun ();
|
|
skymap_plotmoon ();
|
|
|
|
if (m.plotapex == 1)
|
|
{
|
|
plot_apex (35786.0, 0.0);
|
|
plot_apex (39035, 63.4);
|
|
plot_apex (1100, 63.4);
|
|
// plot_apex(1100,63.4);
|
|
// plot_apex(1100,123.0);
|
|
plot_apex (800, 98.7);
|
|
plot_apex (1100, -63.4);
|
|
plot_apex (800, -98.7);
|
|
// plot_apex(480.0,141.7);
|
|
// plot_apex(400.0,40.0);
|
|
// plot_apex(320.0,38.0);
|
|
}
|
|
|
|
if (Isatsel >= 0 && m.leoflag >= 0)
|
|
{
|
|
giza_set_line_width_float (1);
|
|
skymap_plotsatellite (m.tlefile, Isatsel, m.mjd, m.length);
|
|
}
|
|
}
|
|
// Reset redraw
|
|
redraw = 0;
|
|
|
|
// Plot planar search
|
|
if (m.planar == 1)
|
|
{
|
|
if (m.pssatno == 0)
|
|
printf ("Please select a satellite.\n");
|
|
else
|
|
planar_search (m.tlefile, m.pssatno, m.psrmin, m.psrmax, m.psnr,
|
|
m.graves);
|
|
}
|
|
|
|
// Plot IOD points
|
|
if (m.iodflag == 1)
|
|
plot_iod (m.iodfile);
|
|
|
|
// Plot XYZ position
|
|
if (m.xyzflag == 1)
|
|
plot_xyz (m.mjd, m.xyzfile);
|
|
|
|
// Plot visibility
|
|
if (m.visflag == 1 && strcmp (m.orientation, "horizontal") == 0)
|
|
plot_visibility (m.rvis);
|
|
|
|
// Graves visibility
|
|
if (m.graves == 2)
|
|
plot_graves_visibility ();
|
|
|
|
// Get time
|
|
giza_get_key_press_float (&x, &y, &c);
|
|
|
|
// Help
|
|
if (c == 'h' || c == 'H')
|
|
{
|
|
interactive_usage ();
|
|
}
|
|
|
|
// Toggle plotting stars
|
|
if (c == 'Q')
|
|
{
|
|
if (m.plotstars == 1)
|
|
m.plotstars = 0;
|
|
else if (m.plotstars == 0)
|
|
m.plotstars = 1;
|
|
redraw = 1;
|
|
}
|
|
|
|
// Toggle plotting apex
|
|
if (c == 'x')
|
|
{
|
|
if (m.plotapex == 1)
|
|
m.plotapex = 0;
|
|
else if (m.plotapex == 0)
|
|
m.plotapex = 1;
|
|
redraw = 1;
|
|
}
|
|
|
|
// Cycle IOD points
|
|
if (c == '\t')
|
|
{
|
|
m.iodpoint++;
|
|
read_iod (m.iodfile, m.iodpoint);
|
|
redraw = 1;
|
|
}
|
|
|
|
if (c == 'a')
|
|
{
|
|
printf ("Limit on age [d]: \n");
|
|
scanf ("%f", &m.agelimit);
|
|
redraw = 1;
|
|
}
|
|
|
|
// Toggle planar search
|
|
if (c == 'P')
|
|
{
|
|
if (m.planar == 0)
|
|
{
|
|
printf ("Provide altitude range (km): [min max num] ");
|
|
status = scanf ("%f %f %d", &m.psrmin, &m.psrmax, &m.psnr);
|
|
m.pssatno = Isatsel;
|
|
m.planar = 1;
|
|
}
|
|
else if (m.planar == 1)
|
|
{
|
|
m.pssatno = 0;
|
|
m.planar = 0;
|
|
}
|
|
redraw = 1;
|
|
}
|
|
|
|
// Toggle satellite name
|
|
if (c == 'p')
|
|
{
|
|
if (m.pflag == 1)
|
|
m.pflag = 0;
|
|
else if (m.pflag == 0)
|
|
m.pflag = 1;
|
|
redraw = 1;
|
|
continue;
|
|
}
|
|
|
|
// Toggle visibility contours
|
|
if (c == 'v')
|
|
{
|
|
if (m.visflag == 0)
|
|
{
|
|
printf ("Provide altitude (km): ");
|
|
status = scanf ("%f", &m.rvis);
|
|
m.visflag = 1;
|
|
}
|
|
else if (m.visflag == 1)
|
|
{
|
|
m.visflag = 0;
|
|
}
|
|
redraw = 1;
|
|
}
|
|
|
|
// Identify
|
|
if (c == 'i')
|
|
identify_satellite (m.tlefile, Isatsel, m.mjd, x, y);
|
|
|
|
|
|
// Read catalog
|
|
if (c == 'R')
|
|
{
|
|
printf ("TLE catalog name: ");
|
|
status = scanf ("%s", m.tlefile);
|
|
redraw = 1;
|
|
}
|
|
|
|
// Increase/decrease time
|
|
if (c == '.')
|
|
{
|
|
m.mjd += m.length / 86400.0;
|
|
redraw = 1;
|
|
}
|
|
if (c == ',')
|
|
{
|
|
m.mjd -= m.length / 86400.0;
|
|
redraw = 1;
|
|
}
|
|
|
|
// Increase/decrease step
|
|
if (c == '>')
|
|
{
|
|
m.length *= 2.0;
|
|
redraw = 2;
|
|
}
|
|
if (c == '<')
|
|
{
|
|
m.length /= 2.0;
|
|
redraw = 2;
|
|
}
|
|
|
|
// Reset
|
|
if (c == 'r')
|
|
{
|
|
Isatsel = 0;
|
|
m.length = 60.0;
|
|
m.mjd = -1.0;
|
|
m.iodpoint = -1;
|
|
redraw = 1;
|
|
}
|
|
|
|
if (c == 'l')
|
|
{
|
|
printf ("Enter integration length (s): ");
|
|
status = scanf ("%f", &m.length);
|
|
redraw = 1;
|
|
}
|
|
|
|
// Toggle focal length
|
|
if (c == 'F')
|
|
{
|
|
fov++;
|
|
status = read_camera (fov);
|
|
if (status == -1)
|
|
{
|
|
fov = 0;
|
|
status = read_camera (fov);
|
|
}
|
|
redraw = 1;
|
|
}
|
|
|
|
if (c == 'L')
|
|
{
|
|
if (Isatsel == 0)
|
|
{
|
|
m.leoflag++;
|
|
if (m.leoflag > 4)
|
|
m.leoflag = -1;
|
|
redraw = 1;
|
|
}
|
|
else
|
|
{
|
|
printf ("Unable, please reset satellite selection\n");
|
|
}
|
|
}
|
|
|
|
// Find satellite
|
|
if (c == 'f')
|
|
{
|
|
printf ("Enter NORAD Satellite number: ");
|
|
status = scanf ("%ld", &Isatsel);
|
|
|
|
if (Isatsel != 0 && !print_tle (m.tlefile, Isatsel))
|
|
{
|
|
printf ("Satellite %ld not found!\n", Isatsel);
|
|
Isatsel = -1;
|
|
}
|
|
redraw = 1;
|
|
}
|
|
|
|
// Measure
|
|
if (c == 'm')
|
|
{
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
reverse (x, y, &azi, &alt);
|
|
horizontal2equatorial (m.mjd, azi, alt, &ra, &de);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
reverse (x, y, &ra, &de);
|
|
equatorial2horizontal (m.mjd, ra, de, &azi, &alt);
|
|
}
|
|
|
|
printf ("RA: %10.4f Dec: %10.4f Azi: %10.4f Alt: %10.4f\n%f %f\n",
|
|
ra, de, modulo (azi - 180.0, 360.0), alt, x, y);
|
|
}
|
|
|
|
// Format IOD output
|
|
if (c == 'I')
|
|
format_iod (m.mjd, m.ra0, m.de0, m.site_id);
|
|
|
|
// Grid on/off
|
|
if (c == 'g')
|
|
{
|
|
if (m.grid == 1)
|
|
m.grid = 0;
|
|
else if (m.grid == 0)
|
|
m.grid = 1;
|
|
redraw = 1;
|
|
}
|
|
|
|
// Toggle Graves illumination
|
|
if (c == 'G')
|
|
{
|
|
m.graves++;
|
|
if (m.graves == 3)
|
|
m.graves = 0;
|
|
redraw = 1;
|
|
}
|
|
|
|
// Exit
|
|
if (c == 'q')
|
|
{
|
|
giza_stop_prompting ();
|
|
giza_close_device ();
|
|
exit (0);
|
|
}
|
|
|
|
// Recenter
|
|
if (c == 'c' || c == 'C')
|
|
{
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
reverse (x, y, &m.azi0, &m.alt0);
|
|
horizontal2equatorial (m.mjd, m.azi0, m.alt0, &m.ra0, &m.de0);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
reverse (x, y, &m.ra0, &m.de0);
|
|
horizontal2equatorial (m.mjd, m.ra0, m.de0, &m.azi0, &m.alt0);
|
|
}
|
|
printf ("Centered at: %8.4f %8.4f, %8.4f %8.4f\n", m.ra0, m.de0,
|
|
m.azi0, m.alt0);
|
|
redraw = 1;
|
|
}
|
|
|
|
// Add to schedule
|
|
if (c == 'S')
|
|
schedule (m.nfd, m.ra0, m.de0, "start");
|
|
|
|
// Add to schedule
|
|
if (c == 'E')
|
|
schedule (m.nfd, m.ra0, m.de0, "stop");
|
|
|
|
// Polar
|
|
if (c == 'z')
|
|
{
|
|
m.azi0 = 180.0;
|
|
m.alt0 = 90.0;
|
|
m.w = 120.0;
|
|
strcpy (m.orientation, "horizontal");
|
|
m.level = 1;
|
|
redraw = 1;
|
|
}
|
|
|
|
// South
|
|
if (c == 's')
|
|
{
|
|
m.azi0 = 0.0;
|
|
m.alt0 = 45.0;
|
|
strcpy (m.orientation, "horizontal");
|
|
m.level = 3;
|
|
redraw = 1;
|
|
}
|
|
|
|
// North
|
|
if (c == 'n')
|
|
{
|
|
m.azi0 = 180.0;
|
|
m.alt0 = 45.0;
|
|
strcpy (m.orientation, "horizontal");
|
|
m.level = 3;
|
|
redraw = 1;
|
|
}
|
|
|
|
// East
|
|
if (c == 'e')
|
|
{
|
|
m.azi0 = 270.0;
|
|
m.alt0 = 45.0;
|
|
strcpy (m.orientation, "horizontal");
|
|
m.level = 3;
|
|
redraw = 1;
|
|
}
|
|
|
|
// West
|
|
if (c == 'w')
|
|
{
|
|
m.azi0 = 90.0;
|
|
m.alt0 = 45.0;
|
|
strcpy (m.orientation, "horizontal");
|
|
m.level = 3;
|
|
redraw = 1;
|
|
}
|
|
|
|
// Orientation
|
|
if (c == 'o' || c == 'O')
|
|
{
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
strcpy (m.orientation, "equatorial");
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
strcpy (m.orientation, "horizontal");
|
|
}
|
|
redraw = 1;
|
|
}
|
|
|
|
// Level
|
|
if (isdigit (c))
|
|
{
|
|
m.level = c - '0';
|
|
redraw = 1;
|
|
}
|
|
|
|
// Zoom
|
|
if (c == '-' && m.level > 1)
|
|
{
|
|
m.level--;
|
|
redraw = 1;
|
|
}
|
|
if ((c == '+' || c == '=') && m.level < 9)
|
|
{
|
|
m.level++;
|
|
redraw = 1;
|
|
}
|
|
|
|
// renew
|
|
skymap_plot_renew ();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// rotate vector
|
|
void
|
|
rotate (int axis, float angle, float *x, float *y, float *z)
|
|
{
|
|
float xx, yy, zz;
|
|
|
|
if (axis == 0)
|
|
{
|
|
xx = *x;
|
|
yy = *y * cos (angle * D2R) - *z * sin (angle * D2R);
|
|
zz = *z * cos (angle * D2R) + *y * sin (angle * D2R);
|
|
}
|
|
if (axis == 1)
|
|
{
|
|
xx = *x * cos (angle * D2R) - *z * sin (angle * D2R);
|
|
yy = *y;
|
|
zz = *z * cos (angle * D2R) + *x * sin (angle * D2R);
|
|
}
|
|
if (axis == 2)
|
|
{
|
|
xx = *x * cos (angle * D2R) - *y * sin (angle * D2R);
|
|
yy = *y * cos (angle * D2R) + *x * sin (angle * D2R);
|
|
zz = *z;
|
|
}
|
|
|
|
*x = xx;
|
|
*y = yy;
|
|
*z = zz;
|
|
|
|
return;
|
|
}
|
|
|
|
// Compute Date from Julian Day
|
|
void
|
|
mjd2date (double mjd, char *date)
|
|
{
|
|
double f, jd, dday;
|
|
int z, alpha, a, b, c, d, e;
|
|
int year, month, day, hour, min;
|
|
float sec, x;
|
|
|
|
jd = mjd + 2400000.5;
|
|
jd += 0.5;
|
|
|
|
z = floor (jd);
|
|
f = fmod (jd, 1.);
|
|
|
|
if (z < 2299161)
|
|
a = z;
|
|
else
|
|
{
|
|
alpha = floor ((z - 1867216.25) / 36524.25);
|
|
a = z + 1 + alpha - floor (alpha / 4.);
|
|
}
|
|
b = a + 1524;
|
|
c = floor ((b - 122.1) / 365.25);
|
|
d = floor (365.25 * c);
|
|
e = floor ((b - d) / 30.6001);
|
|
|
|
dday = b - d - floor (30.6001 * e) + f;
|
|
if (e < 14)
|
|
month = e - 1;
|
|
else
|
|
month = e - 13;
|
|
|
|
if (month > 2)
|
|
year = c - 4716;
|
|
else
|
|
year = c - 4715;
|
|
|
|
day = (int) floor (dday);
|
|
x = 24.0 * (dday - day);
|
|
x = 3600. * fabs (x) + 0.0001;
|
|
sec = fmod (x, 60.);
|
|
x = (x - sec) / 60.;
|
|
min = fmod (x, 60.);
|
|
x = (x - min) / 60.;
|
|
hour = x;
|
|
sec = floor (1000.0 * sec) / 1000.0;
|
|
|
|
sprintf (date, "%04d-%02d-%02dT%02d:%02d:%06.3f", year, month, day, hour,
|
|
min, sec);
|
|
|
|
return;
|
|
}
|
|
|
|
// Compute Date from Julian Day in IOD format
|
|
void
|
|
mjd2date_iod (double mjd, char *date)
|
|
{
|
|
double f, jd, dday;
|
|
int z, alpha, a, b, c, d, e;
|
|
int year, month, day, hour, min;
|
|
float sec, x, fsec;
|
|
|
|
jd = mjd + 2400000.5;
|
|
jd += 0.5;
|
|
|
|
z = floor (jd);
|
|
f = fmod (jd, 1.);
|
|
|
|
if (z < 2299161)
|
|
a = z;
|
|
else
|
|
{
|
|
alpha = floor ((z - 1867216.25) / 36524.25);
|
|
a = z + 1 + alpha - floor (alpha / 4.);
|
|
}
|
|
b = a + 1524;
|
|
c = floor ((b - 122.1) / 365.25);
|
|
d = floor (365.25 * c);
|
|
e = floor ((b - d) / 30.6001);
|
|
|
|
dday = b - d - floor (30.6001 * e) + f;
|
|
if (e < 14)
|
|
month = e - 1;
|
|
else
|
|
month = e - 13;
|
|
|
|
if (month > 2)
|
|
year = c - 4716;
|
|
else
|
|
year = c - 4715;
|
|
|
|
day = (int) floor (dday);
|
|
x = 24.0 * (dday - day);
|
|
x = 3600. * fabs (x) + 0.0001;
|
|
sec = fmod (x, 60.);
|
|
x = (x - sec) / 60.;
|
|
min = fmod (x, 60.);
|
|
x = (x - min) / 60.;
|
|
hour = x;
|
|
fsec = floor (1000.0 * (sec - floor (sec)));
|
|
|
|
sprintf (date, "%04d%02d%02d%02d%02d%02.0f%03.0f", (int) year, (int) month,
|
|
(int) day, (int) hour, (int) min, floor (sec), fsec);
|
|
|
|
return;
|
|
}
|
|
|
|
// Convert Decimal into Sexagesimal
|
|
void
|
|
dec2s (double x, char *s, int f, int len)
|
|
{
|
|
int i;
|
|
double sec, deg, min;
|
|
char sign;
|
|
char *form[] = { "::", ",,", "hms", " " };
|
|
|
|
sign = (x < 0 ? '-' : ' ');
|
|
x = 3600. * fabs (x);
|
|
|
|
sec = fmod (x, 60.);
|
|
x = (x - sec) / 60.;
|
|
min = fmod (x, 60.);
|
|
x = (x - min) / 60.;
|
|
// deg=fmod(x,60.);
|
|
deg = x;
|
|
|
|
if (len == 7)
|
|
sprintf (s, "%c%02i%c%02i%c%07.4f%c", sign, (int) deg, form[f][0],
|
|
(int) min, form[f][1], sec, form[f][2]);
|
|
if (len == 6)
|
|
sprintf (s, "%c%02i%c%02i%c%06.3f%c", sign, (int) deg, form[f][0],
|
|
(int) min, form[f][1], sec, form[f][2]);
|
|
if (len == 5)
|
|
sprintf (s, "%c%02i%c%02i%c%05.2f%c", sign, (int) deg, form[f][0],
|
|
(int) min, form[f][1], sec, form[f][2]);
|
|
if (len == 4)
|
|
sprintf (s, "%c%02i%c%02i%c%04.1f%c", sign, (int) deg, form[f][0],
|
|
(int) min, form[f][1], sec, form[f][2]);
|
|
if (len == 2)
|
|
sprintf (s, "%c%02i%c%02i%c%02i%c", sign, (int) deg, form[f][0],
|
|
(int) min, form[f][1], (int) floor (sec), form[f][2]);
|
|
|
|
return;
|
|
}
|
|
|
|
// Convert Decimal into Sexagesimal
|
|
void
|
|
dec2s_iod (double x, char *s, int type)
|
|
{
|
|
int i;
|
|
double sec, deg, min, fmin;
|
|
char sign;
|
|
|
|
sign = (x < 0 ? '-' : '+');
|
|
x = 60. * fabs (x);
|
|
|
|
min = fmod (x, 60.);
|
|
x = (x - min) / 60.;
|
|
// deg=fmod(x,60.);
|
|
deg = x;
|
|
if (type == 0)
|
|
fmin = floor (1000.0 * (min - floor (min)));
|
|
else
|
|
fmin = floor (100.0 * (min - floor (min)));
|
|
|
|
if (type == 0)
|
|
sprintf (s, "%02.0f%02.0f%03.0f", deg, floor (min), fmin);
|
|
else
|
|
sprintf (s, "%c%02.0f%02.0f%02.0f", sign, deg, floor (min), fmin);
|
|
|
|
return;
|
|
}
|
|
|
|
// Greenwich Mean Sidereal Time
|
|
double
|
|
dgmst (double mjd)
|
|
{
|
|
double t, dgmst;
|
|
|
|
t = (mjd - 51544.5) / 36525.0;
|
|
|
|
dgmst = 360.98564736629 + t * (0.000387933 - t / 38710000);
|
|
|
|
return dgmst;
|
|
}
|
|
|
|
// Precess a celestial position
|
|
void
|
|
precess (double mjd0, double ra0, double de0, double mjd, double *ra,
|
|
double *de)
|
|
{
|
|
double t0, t;
|
|
double zeta, z, theta;
|
|
double a, b, c;
|
|
|
|
// Angles in radians
|
|
ra0 *= D2R;
|
|
de0 *= D2R;
|
|
|
|
// Time in centuries
|
|
t0 = (mjd0 - 51544.5) / 36525.0;
|
|
t = (mjd - mjd0) / 36525.0;
|
|
|
|
// Precession angles
|
|
zeta = (2306.2181 + 1.39656 * t0 - 0.000139 * t0 * t0) * t;
|
|
zeta += (0.30188 - 0.000344 * t0) * t * t + 0.017998 * t * t * t;
|
|
zeta *= D2R / 3600.0;
|
|
z = (2306.2181 + 1.39656 * t0 - 0.000139 * t0 * t0) * t;
|
|
z += (1.09468 + 0.000066 * t0) * t * t + 0.018203 * t * t * t;
|
|
z *= D2R / 3600.0;
|
|
theta = (2004.3109 - 0.85330 * t0 - 0.000217 * t0 * t0) * t;
|
|
theta += -(0.42665 + 0.000217 * t0) * t * t - 0.041833 * t * t * t;
|
|
theta *= D2R / 3600.0;
|
|
|
|
a = cos (de0) * sin (ra0 + zeta);
|
|
b = cos (theta) * cos (de0) * cos (ra0 + zeta) - sin (theta) * sin (de0);
|
|
c = sin (theta) * cos (de0) * cos (ra0 + zeta) + cos (theta) * sin (de0);
|
|
|
|
*ra = (atan2 (a, b) + z) * R2D;
|
|
*de = asin (c) * R2D;
|
|
|
|
if (*ra < 360.0)
|
|
*ra += 360.0;
|
|
if (*ra > 360.0)
|
|
*ra -= 360.0;
|
|
|
|
return;
|
|
}
|
|
|
|
// Convert Sexagesimal into Decimal
|
|
double
|
|
s2dec (char *s)
|
|
{
|
|
double x;
|
|
float deg, min, sec;
|
|
char t[LIM];
|
|
|
|
strcpy (t, s);
|
|
|
|
deg = fabs (atof (strtok (t, " :")));
|
|
min = fabs (atof (strtok (NULL, " :")));
|
|
sec = fabs (atof (strtok (NULL, " :")));
|
|
|
|
x = (double) deg + (double) min / 60. + (double) sec / 3600.;
|
|
if (s[0] == '-')
|
|
x = -x;
|
|
|
|
return x;
|
|
}
|
|
|
|
// DOY to MJD
|
|
double
|
|
doy2mjd (int year, double doy)
|
|
{
|
|
int month, k = 2;
|
|
double day;
|
|
|
|
if (year % 4 == 0 && year % 400 != 0)
|
|
k = 1;
|
|
|
|
month = floor (9.0 * (k + doy) / 275.0 + 0.98);
|
|
|
|
if (doy < 32)
|
|
month = 1;
|
|
|
|
day =
|
|
doy - floor (275.0 * month / 9.0) + k * floor ((month + 9.0) / 12.0) +
|
|
30.0;
|
|
|
|
return date2mjd (year, month, day);
|
|
}
|
|
|
|
// Decode IOD Observations
|
|
struct observation
|
|
decode_iod_observation (char *iod_line)
|
|
{
|
|
int year, month, iday, hour, min;
|
|
int format, epoch, me, xe, sign;
|
|
int site_id;
|
|
double sec, ra, mm, ss, de, dd, ds, day, mjd0;
|
|
struct observation obs;
|
|
char secbuf[6], sn[2], degbuf[3];
|
|
|
|
// Strip newline
|
|
iod_line[strlen (iod_line) - 1] = '\0';
|
|
|
|
// Copy full line
|
|
strcpy (obs.iod_line, iod_line);
|
|
|
|
// Set usage
|
|
obs.flag = 1;
|
|
|
|
// Get SSN
|
|
sscanf (iod_line, "%5d", &obs.ssn);
|
|
|
|
// Get site
|
|
sscanf (iod_line + 16, "%4d", &obs.site);
|
|
|
|
// Decode date/time
|
|
sscanf (iod_line + 23, "%4d%2d%2d%2d%2d%5s", &year, &month, &iday, &hour,
|
|
&min, secbuf);
|
|
sec = atof (secbuf);
|
|
sec /= pow (10, strlen (secbuf) - 2);
|
|
day =
|
|
(double) iday + (double) hour / 24.0 + (double) min / 1440.0 +
|
|
(double) sec / 86400.0;
|
|
obs.mjd = date2mjd (year, month, day);
|
|
|
|
// Get uncertainty in time
|
|
sscanf (iod_line + 41, "%1d%1d", &me, &xe);
|
|
obs.st = (float) me *pow (10, xe - 8);
|
|
|
|
// Skip empty observations
|
|
if (strlen (iod_line) < 64 || (iod_line[54] != '+' && iod_line[54] != '-'))
|
|
obs.flag = 0;
|
|
|
|
// Get format, epoch
|
|
sscanf (iod_line + 44, "%1d%1d", &format, &epoch);
|
|
|
|
// Read position
|
|
sscanf (iod_line + 47, "%2lf%2lf%3lf%1s", &ra, &mm, &ss, sn);
|
|
sscanf (iod_line + 55, "%2lf%2lf%2s", &de, &dd, degbuf);
|
|
ds = atof (degbuf);
|
|
if (strlen (degbuf) == 1)
|
|
ds *= 10;
|
|
sign = (sn[0] == '-') ? -1 : 1;
|
|
sscanf (iod_line + 62, "%1d%1d", &me, &xe);
|
|
obs.sr = (float) me *pow (10, xe - 8);
|
|
|
|
// Decode position
|
|
switch (format)
|
|
{
|
|
// Format 1: RA/DEC = HHMMSSs+DDMMSS MX (MX in seconds of arc)
|
|
case 1:
|
|
ra += mm / 60 + ss / 36000;
|
|
de = sign * (de + dd / 60 + ds / 3600);
|
|
obs.sr /= 3600.0;
|
|
break;
|
|
// Format 2: RA/DEC = HHMMmmm+DDMMmm MX (MX in minutes of arc)
|
|
case 2:
|
|
ra += mm / 60 + ss / 60000;
|
|
de = sign * (de + dd / 60 + ds / 6000);
|
|
obs.sr /= 60.0;
|
|
break;
|
|
// Format 3: RA/DEC = HHMMmmm+DDdddd MX (MX in degrees of arc)
|
|
case 3:
|
|
ra += mm / 60 + ss / 60000;
|
|
de = sign * (de + dd / 100 + ds / 10000);
|
|
break;
|
|
// Format 7: RA/DEC = HHMMSSs+DDdddd MX (MX in degrees of arc)
|
|
case 7:
|
|
ra += mm / 60 + ss / 36000;
|
|
de = sign * (de + dd / 100 + ds / 10000);
|
|
break;
|
|
default:
|
|
printf ("%s\n", iod_line);
|
|
printf ("IOD Format not implemented\n");
|
|
obs.flag = 0;
|
|
break;
|
|
}
|
|
// Convert to degrees
|
|
ra *= 15.0;
|
|
|
|
// Get precession epoch
|
|
if (epoch == 0)
|
|
{
|
|
obs.ra = ra;
|
|
obs.de = de;
|
|
return obs;
|
|
}
|
|
else if (epoch == 4)
|
|
{
|
|
mjd0 = 33281.9235;
|
|
}
|
|
else if (epoch == 5)
|
|
{
|
|
mjd0 = 51544.5;
|
|
}
|
|
else
|
|
{
|
|
printf ("Observing epoch not implemented\n");
|
|
obs.flag = 0;
|
|
}
|
|
|
|
// Precess position
|
|
precess (mjd0, ra, de, obs.mjd, &obs.ra, &obs.de);
|
|
|
|
// Get horizontal position
|
|
equatorial2horizontal (obs.mjd, obs.ra, obs.de, &obs.azi, &obs.alt);
|
|
|
|
return obs;
|
|
}
|
|
|
|
void
|
|
plot_iod (char *filename)
|
|
{
|
|
int i = 0;
|
|
char line[LIM];
|
|
FILE *file;
|
|
struct observation obs;
|
|
double azi, alt, rx, ry;
|
|
float x, y;
|
|
|
|
giza_set_colour_index (2);
|
|
file = fopen (filename, "r");
|
|
if (file == NULL)
|
|
{
|
|
printf ("Failed to open %s\n", filename);
|
|
return;
|
|
}
|
|
|
|
// Read data
|
|
while (fgets (line, LIM, file) != NULL)
|
|
{
|
|
if (strstr (line, "#") == NULL)
|
|
{
|
|
obs = decode_iod_observation (line);
|
|
|
|
if (m.site_id == obs.site)
|
|
{
|
|
if (strcmp (m.orientation, "horizontal") == 0)
|
|
{
|
|
forward (obs.azi, obs.alt, &rx, &ry);
|
|
}
|
|
else if (strcmp (m.orientation, "equatorial") == 0)
|
|
{
|
|
forward (obs.ra, obs.de, &rx, &ry);
|
|
}
|
|
x = (float) rx;
|
|
y = (float) ry;
|
|
|
|
giza_single_point_float (x, y, 4);
|
|
}
|
|
}
|
|
}
|
|
fclose (file);
|
|
giza_set_colour_index (1);
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
// Moon position
|
|
void
|
|
lunpos_xyz (double mjd, xyz_t * pos, double *ra, double *de)
|
|
{
|
|
int i;
|
|
double t, t2, t3, t4;
|
|
double l1, d, m, m1, f, a1, a2, a3, e, ef;
|
|
double suml, sumb, sumr, arglr, argb;
|
|
double l, b, r;
|
|
|
|
// Julian Centuries
|
|
t = (mjd - 51544.5) / 36525.0;
|
|
|
|
// Powers of t
|
|
t2 = t * t;
|
|
t3 = t2 * t;
|
|
t4 = t3 * t;
|
|
|
|
// angles
|
|
l1 =
|
|
modulo (218.3164477 + 481267.88123421 * t - 0.0015786 * t2 +
|
|
t3 / 538841.0 - t4 / 65194000.0, 360.0) * D2R;
|
|
d =
|
|
modulo (297.8501921 + 445267.1114034 * t - 0.0018819 * t2 +
|
|
t3 / 545868.0 - t4 / 113065000.0, 360.0) * D2R;
|
|
m =
|
|
modulo (357.5291092 + 35999.0502909 * t - 0.0001536 * t2 +
|
|
t3 / 24490000.0, 360.0) * D2R;
|
|
m1 =
|
|
modulo (134.9633964 + 477198.8675055 * t + 0.0087417 * t2 + t3 / 69699.0 -
|
|
t4 / 14712000.0, 360.0) * D2R;
|
|
f =
|
|
modulo (93.2720950 + 483202.0175233 * t - 0.0036539 * t2 -
|
|
t3 / 3526000.0 + t4 / 86331000.0, 360.0) * D2R;
|
|
a1 = modulo (119.75 + 131.849 * t, 360.0) * D2R;
|
|
a2 = modulo (53.09 + 479264.290 * t, 360.0) * D2R;
|
|
a3 = modulo (313.45 + 481266.484 * t, 360.0) * D2R;
|
|
e = 1.0 - 0.002516 * t - 0.0000074 * t2;
|
|
|
|
// Compute sums
|
|
for (i = 0, suml = sumb = sumr = 0.0; i < 60; i++)
|
|
{
|
|
// Arguments
|
|
arglr = clr[i].nd * d + clr[i].nm * m + clr[i].nm1 * m1 + clr[i].nf * f;
|
|
argb = cb[i].nd * d + cb[i].nm * m + cb[i].nm1 * m1 + cb[i].nf * f;
|
|
|
|
// E multiplication factor
|
|
if (abs (clr[i].nm) == 1)
|
|
ef = e;
|
|
else if (abs (clr[i].nm) == 2)
|
|
ef = e * e;
|
|
else
|
|
ef = 1.0;
|
|
|
|
// Sums
|
|
suml += clr[i].sa * sin (arglr) * ef;
|
|
sumr += clr[i].ca * cos (arglr) * ef;
|
|
|
|
// E multiplication factor
|
|
if (abs (cb[i].nm) == 1)
|
|
ef = e;
|
|
else if (abs (cb[i].nm) == 2)
|
|
ef = e * e;
|
|
else
|
|
ef = 1.0;
|
|
|
|
// Sums
|
|
sumb += cb[i].sa * sin (argb) * ef;
|
|
}
|
|
|
|
// Additives
|
|
suml += 3958 * sin (a1) + 1962 * sin (l1 - f) + 318 * sin (a2);
|
|
sumb +=
|
|
-2235 * sin (l1) + 382 * sin (a3) + 175 * sin (a1 - f) + 175 * sin (a1 +
|
|
f) +
|
|
127 * sin (l1 - m1) - 115 * sin (l1 + m1);
|
|
|
|
// Ecliptic longitude, latitude and distance
|
|
l = modulo (l1 * R2D + suml / 1000000.0, 360.0);
|
|
b = sumb / 1000000.0;
|
|
r = 385000.56 + sumr / 1000.0;
|
|
|
|
// Equatorial
|
|
ecliptical2equatorial (l, b, ra, de);
|
|
|
|
// Position
|
|
pos->x = r * cos (*de * D2R) * cos (*ra * D2R);
|
|
pos->y = r * cos (*de * D2R) * sin (*ra * D2R);
|
|
pos->z = r * sin (*de * D2R);
|
|
|
|
return;
|
|
}
|
|
|
|
// Convert ecliptical into equatorial coordinates
|
|
void
|
|
ecliptical2equatorial (double l, double b, double *ra, double *de)
|
|
{
|
|
double eps = 23.4392911;
|
|
|
|
*ra =
|
|
modulo (atan2
|
|
(sin (l * D2R) * cos (eps * D2R) -
|
|
tan (b * D2R) * sin (eps * D2R), cos (l * D2R)) * R2D, 360.0);
|
|
*de =
|
|
asin (sin (b * D2R) * cos (eps * D2R) +
|
|
cos (b * D2R) * sin (eps * D2R) * sin (l * D2R)) * R2D;
|
|
|
|
return;
|
|
}
|