159cc4ca5SDavid du Colombier #include <u.h>
259cc4ca5SDavid du Colombier #include <libc.h>
359cc4ca5SDavid du Colombier #include <bio.h>
459cc4ca5SDavid du Colombier #include <draw.h>
559cc4ca5SDavid du Colombier #include <event.h>
659cc4ca5SDavid du Colombier #include <ctype.h>
759cc4ca5SDavid du Colombier #include "map.h"
859cc4ca5SDavid du Colombier #undef RAD
959cc4ca5SDavid du Colombier #undef TWOPI
1059cc4ca5SDavid du Colombier #include "sky.h"
1159cc4ca5SDavid du Colombier
1259cc4ca5SDavid du Colombier /* convert to milliarcsec */
1359cc4ca5SDavid du Colombier static long c = MILLIARCSEC; /* 1 degree */
1459cc4ca5SDavid du Colombier static long m5 = 1250*60*60; /* 5 minutes of ra */
1559cc4ca5SDavid du Colombier
1659cc4ca5SDavid du Colombier DAngle ramin;
1759cc4ca5SDavid du Colombier DAngle ramax;
1859cc4ca5SDavid du Colombier DAngle decmin;
1959cc4ca5SDavid du Colombier DAngle decmax;
2059cc4ca5SDavid du Colombier int folded;
2159cc4ca5SDavid du Colombier
2259cc4ca5SDavid du Colombier Image *grey;
2359cc4ca5SDavid du Colombier Image *alphagrey;
2459cc4ca5SDavid du Colombier Image *green;
2559cc4ca5SDavid du Colombier Image *lightblue;
2659cc4ca5SDavid du Colombier Image *lightgrey;
2759cc4ca5SDavid du Colombier Image *ocstipple;
2859cc4ca5SDavid du Colombier Image *suncolor;
2959cc4ca5SDavid du Colombier Image *mooncolor;
3059cc4ca5SDavid du Colombier Image *shadowcolor;
3159cc4ca5SDavid du Colombier Image *mercurycolor;
3259cc4ca5SDavid du Colombier Image *venuscolor;
3359cc4ca5SDavid du Colombier Image *marscolor;
3459cc4ca5SDavid du Colombier Image *jupitercolor;
3559cc4ca5SDavid du Colombier Image *saturncolor;
3659cc4ca5SDavid du Colombier Image *uranuscolor;
3759cc4ca5SDavid du Colombier Image *neptunecolor;
3859cc4ca5SDavid du Colombier Image *plutocolor;
3959cc4ca5SDavid du Colombier Image *cometcolor;
4059cc4ca5SDavid du Colombier
4159cc4ca5SDavid du Colombier Planetrec *planet;
4259cc4ca5SDavid du Colombier
4359cc4ca5SDavid du Colombier long mapx0, mapy0;
4459cc4ca5SDavid du Colombier long mapra, mapdec;
4559cc4ca5SDavid du Colombier double mylat, mylon, mysid;
4659cc4ca5SDavid du Colombier double mapscale;
4759cc4ca5SDavid du Colombier double maps;
4859cc4ca5SDavid du Colombier int (*projection)(struct place*, double*, double*);
4959cc4ca5SDavid du Colombier
5059cc4ca5SDavid du Colombier char *fontname = "/lib/font/bit/lucida/unicode.6.font";
5159cc4ca5SDavid du Colombier
5259cc4ca5SDavid du Colombier /* types Coord and Loc correspond to types in map(3) thus:
5359cc4ca5SDavid du Colombier Coord == struct coord;
5459cc4ca5SDavid du Colombier Loc == struct place, except longitudes are measured
5559cc4ca5SDavid du Colombier positive east for Loc and west for struct place
5659cc4ca5SDavid du Colombier */
5759cc4ca5SDavid du Colombier
5859cc4ca5SDavid du Colombier typedef struct Xyz Xyz;
5959cc4ca5SDavid du Colombier typedef struct coord Coord;
6059cc4ca5SDavid du Colombier typedef struct Loc Loc;
6159cc4ca5SDavid du Colombier
6259cc4ca5SDavid du Colombier struct Xyz{
6359cc4ca5SDavid du Colombier double x,y,z;
6459cc4ca5SDavid du Colombier };
6559cc4ca5SDavid du Colombier
6659cc4ca5SDavid du Colombier struct Loc{
6759cc4ca5SDavid du Colombier Coord nlat, elon;
6859cc4ca5SDavid du Colombier };
6959cc4ca5SDavid du Colombier
7059cc4ca5SDavid du Colombier Xyz north = { 0, 0, 1 };
7159cc4ca5SDavid du Colombier
7259cc4ca5SDavid du Colombier int
plotopen(void)7359cc4ca5SDavid du Colombier plotopen(void)
7459cc4ca5SDavid du Colombier {
7559cc4ca5SDavid du Colombier if(display != nil)
7659cc4ca5SDavid du Colombier return 1;
7759cc4ca5SDavid du Colombier display = initdisplay(nil, nil, drawerror);
7859cc4ca5SDavid du Colombier if(display == nil){
7959cc4ca5SDavid du Colombier fprint(2, "initdisplay failed: %r\n");
8059cc4ca5SDavid du Colombier return -1;
8159cc4ca5SDavid du Colombier }
8259cc4ca5SDavid du Colombier grey = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 1, 0x777777FF);
8359cc4ca5SDavid du Colombier lightgrey = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 1, 0xAAAAAAFF);
8459cc4ca5SDavid du Colombier alphagrey = allocimage(display, Rect(0, 0, 2, 2), RGBA32, 1, 0x77777777);
8559cc4ca5SDavid du Colombier green = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 1, 0x00AA00FF);
8659cc4ca5SDavid du Colombier lightblue = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 1, 0x009EEEFF);
8759cc4ca5SDavid du Colombier ocstipple = allocimage(display, Rect(0, 0, 2, 2), CMAP8, 1, 0xAAAAAAFF);
8859cc4ca5SDavid du Colombier draw(ocstipple, Rect(0, 0, 1, 1), display->black, nil, ZP);
8959cc4ca5SDavid du Colombier draw(ocstipple, Rect(1, 1, 2, 2), display->black, nil, ZP);
9059cc4ca5SDavid du Colombier
9159cc4ca5SDavid du Colombier suncolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0xFFFF77FF);
9259cc4ca5SDavid du Colombier mooncolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0xAAAAAAFF);
9359cc4ca5SDavid du Colombier shadowcolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0x00000055);
9459cc4ca5SDavid du Colombier mercurycolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0xFFAAAAFF);
9559cc4ca5SDavid du Colombier venuscolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0xAAAAFFFF);
9659cc4ca5SDavid du Colombier marscolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0xFF5555FF);
9759cc4ca5SDavid du Colombier jupitercolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0xFFFFAAFF);
9859cc4ca5SDavid du Colombier saturncolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0xAAFFAAFF);
9959cc4ca5SDavid du Colombier uranuscolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0x77DDDDFF);
10059cc4ca5SDavid du Colombier neptunecolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0x77FF77FF);
10159cc4ca5SDavid du Colombier plutocolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0x7777FFFF);
10259cc4ca5SDavid du Colombier cometcolor = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, 0xAAAAFFFF);
10359cc4ca5SDavid du Colombier font = openfont(display, fontname);
10459cc4ca5SDavid du Colombier if(font == nil)
10559cc4ca5SDavid du Colombier fprint(2, "warning: no font %s: %r\n", fontname);
10659cc4ca5SDavid du Colombier return 1;
10759cc4ca5SDavid du Colombier }
10859cc4ca5SDavid du Colombier
10959cc4ca5SDavid du Colombier /*
11059cc4ca5SDavid du Colombier * Function heavens() for setting up observer-eye-view
11159cc4ca5SDavid du Colombier * sky charts, plus subsidiary functions.
11259cc4ca5SDavid du Colombier * Written by Doug McIlroy.
11359cc4ca5SDavid du Colombier */
11459cc4ca5SDavid du Colombier
11559cc4ca5SDavid du Colombier /* heavens(nlato, wlono, nlatc, wlonc) sets up a map(3)-style
11659cc4ca5SDavid du Colombier coordinate change (by calling orient()) and returns a
11759cc4ca5SDavid du Colombier projection function heavens for calculating a star map
11859cc4ca5SDavid du Colombier centered on nlatc,wlonc and rotated so it will appear
11959cc4ca5SDavid du Colombier upright as seen by a ground observer at nlato,wlono.
12059cc4ca5SDavid du Colombier all coordinates (north latitude and west longitude)
12159cc4ca5SDavid du Colombier are in degrees.
12259cc4ca5SDavid du Colombier */
12359cc4ca5SDavid du Colombier
12459cc4ca5SDavid du Colombier Coord
mkcoord(double degrees)12559cc4ca5SDavid du Colombier mkcoord(double degrees)
12659cc4ca5SDavid du Colombier {
12759cc4ca5SDavid du Colombier Coord c;
12859cc4ca5SDavid du Colombier
12959cc4ca5SDavid du Colombier c.l = degrees*PI/180;
13059cc4ca5SDavid du Colombier c.s = sin(c.l);
13159cc4ca5SDavid du Colombier c.c = cos(c.l);
13259cc4ca5SDavid du Colombier return c;
13359cc4ca5SDavid du Colombier }
13459cc4ca5SDavid du Colombier
13559cc4ca5SDavid du Colombier Xyz
ptov(struct place p)13659cc4ca5SDavid du Colombier ptov(struct place p)
13759cc4ca5SDavid du Colombier {
13859cc4ca5SDavid du Colombier Xyz v;
13959cc4ca5SDavid du Colombier
14059cc4ca5SDavid du Colombier v.z = p.nlat.s;
14159cc4ca5SDavid du Colombier v.x = p.nlat.c * p.wlon.c;
14259cc4ca5SDavid du Colombier v.y = -p.nlat.c * p.wlon.s;
14359cc4ca5SDavid du Colombier return v;
14459cc4ca5SDavid du Colombier }
14559cc4ca5SDavid du Colombier
14659cc4ca5SDavid du Colombier double
dot(Xyz a,Xyz b)14759cc4ca5SDavid du Colombier dot(Xyz a, Xyz b)
14859cc4ca5SDavid du Colombier {
14959cc4ca5SDavid du Colombier return a.x*b.x + a.y*b.y + a.z*b.z;
15059cc4ca5SDavid du Colombier }
15159cc4ca5SDavid du Colombier
15259cc4ca5SDavid du Colombier Xyz
cross(Xyz a,Xyz b)15359cc4ca5SDavid du Colombier cross(Xyz a, Xyz b)
15459cc4ca5SDavid du Colombier {
15559cc4ca5SDavid du Colombier Xyz v;
15659cc4ca5SDavid du Colombier
15759cc4ca5SDavid du Colombier v.x = a.y*b.z - a.z*b.y;
15859cc4ca5SDavid du Colombier v.y = a.z*b.x - a.x*b.z;
15959cc4ca5SDavid du Colombier v.z = a.x*b.y - a.y*b.x;
16059cc4ca5SDavid du Colombier return v;
16159cc4ca5SDavid du Colombier }
16259cc4ca5SDavid du Colombier
16359cc4ca5SDavid du Colombier double
len(Xyz a)16459cc4ca5SDavid du Colombier len(Xyz a)
16559cc4ca5SDavid du Colombier {
16659cc4ca5SDavid du Colombier return sqrt(dot(a, a));
16759cc4ca5SDavid du Colombier }
16859cc4ca5SDavid du Colombier
16959cc4ca5SDavid du Colombier /* An azimuth vector from a to b is a tangent to
17059cc4ca5SDavid du Colombier the sphere at a pointing along the (shorter)
17159cc4ca5SDavid du Colombier great-circle direction to b. It lies in the
17259cc4ca5SDavid du Colombier plane of the vectors a and b, is perpendicular
17359cc4ca5SDavid du Colombier to a, and has a positive compoent along b,
17459cc4ca5SDavid du Colombier provided a and b span a 2-space. Otherwise
17559cc4ca5SDavid du Colombier it is null. (aXb)Xa, where X denotes cross
17659cc4ca5SDavid du Colombier product, is such a vector. */
17759cc4ca5SDavid du Colombier
17859cc4ca5SDavid du Colombier Xyz
azvec(Xyz a,Xyz b)17959cc4ca5SDavid du Colombier azvec(Xyz a, Xyz b)
18059cc4ca5SDavid du Colombier {
18159cc4ca5SDavid du Colombier return cross(cross(a,b), a);
18259cc4ca5SDavid du Colombier }
18359cc4ca5SDavid du Colombier
18459cc4ca5SDavid du Colombier /* Find the azimuth of point b as seen
18559cc4ca5SDavid du Colombier from point a, given that a is distinct
18659cc4ca5SDavid du Colombier from either pole and from b */
18759cc4ca5SDavid du Colombier
18859cc4ca5SDavid du Colombier double
azimuth(Xyz a,Xyz b)18959cc4ca5SDavid du Colombier azimuth(Xyz a, Xyz b)
19059cc4ca5SDavid du Colombier {
19159cc4ca5SDavid du Colombier Xyz aton = azvec(a,north);
19259cc4ca5SDavid du Colombier Xyz atob = azvec(a,b);
19359cc4ca5SDavid du Colombier double lenaton = len(aton);
19459cc4ca5SDavid du Colombier double lenatob = len(atob);
19559cc4ca5SDavid du Colombier double az = acos(dot(aton,atob)/(lenaton*lenatob));
19659cc4ca5SDavid du Colombier
19759cc4ca5SDavid du Colombier if(dot(b,cross(north,a)) < 0)
19859cc4ca5SDavid du Colombier az = -az;
19959cc4ca5SDavid du Colombier return az;
20059cc4ca5SDavid du Colombier }
20159cc4ca5SDavid du Colombier
20259cc4ca5SDavid du Colombier /* Find the rotation (3rd argument of orient() in the
20359cc4ca5SDavid du Colombier map projection package) for the map described
20459cc4ca5SDavid du Colombier below. The return is radians; it must be converted
20559cc4ca5SDavid du Colombier to degrees for orient().
20659cc4ca5SDavid du Colombier */
20759cc4ca5SDavid du Colombier
20859cc4ca5SDavid du Colombier double
rot(struct place center,struct place zenith)20959cc4ca5SDavid du Colombier rot(struct place center, struct place zenith)
21059cc4ca5SDavid du Colombier {
21159cc4ca5SDavid du Colombier Xyz cen = ptov(center);
21259cc4ca5SDavid du Colombier Xyz zen = ptov(zenith);
21359cc4ca5SDavid du Colombier
21459cc4ca5SDavid du Colombier if(cen.z > 1-FUZZ) /* center at N pole */
21559cc4ca5SDavid du Colombier return PI + zenith.wlon.l;
21659cc4ca5SDavid du Colombier if(cen.z < FUZZ-1) /* at S pole */
21759cc4ca5SDavid du Colombier return -zenith.wlon.l;
21859cc4ca5SDavid du Colombier if(fabs(dot(cen,zen)) > 1-FUZZ) /* at zenith */
21959cc4ca5SDavid du Colombier return 0;
22059cc4ca5SDavid du Colombier return azimuth(cen, zen);
22159cc4ca5SDavid du Colombier }
22259cc4ca5SDavid du Colombier
22359cc4ca5SDavid du Colombier int (*
heavens(double zlatdeg,double zlondeg,double clatdeg,double clondeg)22459cc4ca5SDavid du Colombier heavens(double zlatdeg, double zlondeg, double clatdeg, double clondeg))(Loc*, double*, double*)
22559cc4ca5SDavid du Colombier {
22659cc4ca5SDavid du Colombier struct place center;
22759cc4ca5SDavid du Colombier struct place zenith;
22859cc4ca5SDavid du Colombier
22959cc4ca5SDavid du Colombier center.nlat = mkcoord(clatdeg);
23059cc4ca5SDavid du Colombier center.wlon = mkcoord(clondeg);
23159cc4ca5SDavid du Colombier zenith.nlat = mkcoord(zlatdeg);
23259cc4ca5SDavid du Colombier zenith.wlon = mkcoord(zlondeg);
23359cc4ca5SDavid du Colombier projection = stereographic();
23459cc4ca5SDavid du Colombier orient(clatdeg, clondeg, rot(center, zenith)*180/PI);
23559cc4ca5SDavid du Colombier return projection;
23659cc4ca5SDavid du Colombier }
23759cc4ca5SDavid du Colombier
23859cc4ca5SDavid du Colombier int
maptoxy(long ra,long dec,double * x,double * y)23959cc4ca5SDavid du Colombier maptoxy(long ra, long dec, double *x, double *y)
24059cc4ca5SDavid du Colombier {
24159cc4ca5SDavid du Colombier double lat, lon;
24259cc4ca5SDavid du Colombier struct place pl;
24359cc4ca5SDavid du Colombier
24459cc4ca5SDavid du Colombier lat = angle(dec);
24559cc4ca5SDavid du Colombier lon = angle(ra);
24659cc4ca5SDavid du Colombier pl.nlat.l = lat;
24759cc4ca5SDavid du Colombier pl.nlat.s = sin(lat);
24859cc4ca5SDavid du Colombier pl.nlat.c = cos(lat);
24959cc4ca5SDavid du Colombier pl.wlon.l = lon;
25059cc4ca5SDavid du Colombier pl.wlon.s = sin(lon);
25159cc4ca5SDavid du Colombier pl.wlon.c = cos(lon);
25259cc4ca5SDavid du Colombier normalize(&pl);
25359cc4ca5SDavid du Colombier return projection(&pl, x, y);
25459cc4ca5SDavid du Colombier }
25559cc4ca5SDavid du Colombier
25659cc4ca5SDavid du Colombier /* end of 'heavens' section */
25759cc4ca5SDavid du Colombier
25859cc4ca5SDavid du Colombier int
setmap(long ramin,long ramax,long decmin,long decmax,Rectangle r,int zenithup)25959cc4ca5SDavid du Colombier setmap(long ramin, long ramax, long decmin, long decmax, Rectangle r, int zenithup)
26059cc4ca5SDavid du Colombier {
26159cc4ca5SDavid du Colombier int c;
26259cc4ca5SDavid du Colombier double minx, maxx, miny, maxy;
26359cc4ca5SDavid du Colombier
26459cc4ca5SDavid du Colombier c = 1000*60*60;
26559cc4ca5SDavid du Colombier mapra = ramax/2+ramin/2;
26659cc4ca5SDavid du Colombier mapdec = decmax/2+decmin/2;
26759cc4ca5SDavid du Colombier
26859cc4ca5SDavid du Colombier if(zenithup)
26959cc4ca5SDavid du Colombier projection = heavens(mylat, mysid, (double)mapdec/c, (double)mapra/c);
27059cc4ca5SDavid du Colombier else{
27159cc4ca5SDavid du Colombier orient((double)mapdec/c, (double)mapra/c, 0.);
27259cc4ca5SDavid du Colombier projection = stereographic();
27359cc4ca5SDavid du Colombier }
27459cc4ca5SDavid du Colombier mapx0 = (r.max.x+r.min.x)/2;
27559cc4ca5SDavid du Colombier mapy0 = (r.max.y+r.min.y)/2;
27659cc4ca5SDavid du Colombier maps = ((double)Dy(r))/(double)(decmax-decmin);
27759cc4ca5SDavid du Colombier if(maptoxy(ramin, decmin, &minx, &miny) < 0)
27859cc4ca5SDavid du Colombier return -1;
27959cc4ca5SDavid du Colombier if(maptoxy(ramax, decmax, &maxx, &maxy) < 0)
28059cc4ca5SDavid du Colombier return -1;
28159cc4ca5SDavid du Colombier /*
28259cc4ca5SDavid du Colombier * It's tricky to get the scale right. This noble attempt scales
28359cc4ca5SDavid du Colombier * to fit the lengths of the sides of the rectangle.
28459cc4ca5SDavid du Colombier */
28559cc4ca5SDavid du Colombier mapscale = Dx(r)/(minx-maxx);
28659cc4ca5SDavid du Colombier if(mapscale > Dy(r)/(maxy-miny))
28759cc4ca5SDavid du Colombier mapscale = Dy(r)/(maxy-miny);
28859cc4ca5SDavid du Colombier /*
28959cc4ca5SDavid du Colombier * near the pole It's not a rectangle, though, so this scales
29059cc4ca5SDavid du Colombier * to fit the corners of the trapezoid (a triangle at the pole).
29159cc4ca5SDavid du Colombier */
29259cc4ca5SDavid du Colombier mapscale *= (cos(angle(mapdec))+1.)/2;
29359cc4ca5SDavid du Colombier if(maxy < miny){
29459cc4ca5SDavid du Colombier /* upside down, between zenith and pole */
29559cc4ca5SDavid du Colombier fprint(2, "reverse plot\n");
29659cc4ca5SDavid du Colombier mapscale = -mapscale;
29759cc4ca5SDavid du Colombier }
29859cc4ca5SDavid du Colombier return 1;
29959cc4ca5SDavid du Colombier }
30059cc4ca5SDavid du Colombier
30159cc4ca5SDavid du Colombier Point
map(long ra,long dec)30259cc4ca5SDavid du Colombier map(long ra, long dec)
30359cc4ca5SDavid du Colombier {
30459cc4ca5SDavid du Colombier double x, y;
30559cc4ca5SDavid du Colombier Point p;
30659cc4ca5SDavid du Colombier
30759cc4ca5SDavid du Colombier if(maptoxy(ra, dec, &x, &y) > 0){
30859cc4ca5SDavid du Colombier p.x = mapscale*x + mapx0;
30959cc4ca5SDavid du Colombier p.y = mapscale*-y + mapy0;
31059cc4ca5SDavid du Colombier }else{
31159cc4ca5SDavid du Colombier p.x = -100;
31259cc4ca5SDavid du Colombier p.y = -100;
31359cc4ca5SDavid du Colombier }
31459cc4ca5SDavid du Colombier return p;
31559cc4ca5SDavid du Colombier }
31659cc4ca5SDavid du Colombier
31759cc4ca5SDavid du Colombier int
dsize(int mag)31859cc4ca5SDavid du Colombier dsize(int mag) /* mag is 10*magnitude; return disc size */
31959cc4ca5SDavid du Colombier {
32059cc4ca5SDavid du Colombier double d;
32159cc4ca5SDavid du Colombier
32259cc4ca5SDavid du Colombier mag += 25; /* make mags all positive; sirius is -1.6m */
32359cc4ca5SDavid du Colombier d = (130-mag)/10;
32459cc4ca5SDavid du Colombier /* if plate scale is huge, adjust */
32559cc4ca5SDavid du Colombier if(maps < 100.0/MILLIARCSEC)
32659cc4ca5SDavid du Colombier d *= .71;
32759cc4ca5SDavid du Colombier if(maps < 50.0/MILLIARCSEC)
32859cc4ca5SDavid du Colombier d *= .71;
32959cc4ca5SDavid du Colombier return d;
33059cc4ca5SDavid du Colombier }
33159cc4ca5SDavid du Colombier
33259cc4ca5SDavid du Colombier void
drawname(Image * scr,Image * col,char * s,int ra,int dec)33359cc4ca5SDavid du Colombier drawname(Image *scr, Image *col, char *s, int ra, int dec)
33459cc4ca5SDavid du Colombier {
33559cc4ca5SDavid du Colombier Point p;
33659cc4ca5SDavid du Colombier
33759cc4ca5SDavid du Colombier if(font == nil)
33859cc4ca5SDavid du Colombier return;
33959cc4ca5SDavid du Colombier p = addpt(map(ra, dec), Pt(4, -1)); /* font has huge ascent */
34059cc4ca5SDavid du Colombier string(scr, p, col, ZP, font, s);
34159cc4ca5SDavid du Colombier }
34259cc4ca5SDavid du Colombier
34359cc4ca5SDavid du Colombier int
npixels(DAngle diam)34459cc4ca5SDavid du Colombier npixels(DAngle diam)
34559cc4ca5SDavid du Colombier {
34659cc4ca5SDavid du Colombier Point p0, p1;
34759cc4ca5SDavid du Colombier
34859cc4ca5SDavid du Colombier diam = DEG(angle(diam)*MILLIARCSEC); /* diam in milliarcsec */
34959cc4ca5SDavid du Colombier diam /= 2; /* radius */
35059cc4ca5SDavid du Colombier /* convert to plate scale */
35159cc4ca5SDavid du Colombier /* BUG: need +100 because we sometimes crash in library if we plot the exact center */
35259cc4ca5SDavid du Colombier p0 = map(mapra+100, mapdec);
35359cc4ca5SDavid du Colombier p1 = map(mapra+100+diam, mapdec);
35459cc4ca5SDavid du Colombier return hypot(p0.x-p1.x, p0.y-p1.y);
35559cc4ca5SDavid du Colombier }
35659cc4ca5SDavid du Colombier
35759cc4ca5SDavid du Colombier void
drawdisc(Image * scr,DAngle semidiam,int ring,Image * color,Point pt,char * s)35859cc4ca5SDavid du Colombier drawdisc(Image *scr, DAngle semidiam, int ring, Image *color, Point pt, char *s)
35959cc4ca5SDavid du Colombier {
36059cc4ca5SDavid du Colombier int d;
36159cc4ca5SDavid du Colombier
36259cc4ca5SDavid du Colombier d = npixels(semidiam*2);
36359cc4ca5SDavid du Colombier if(d < 5)
36459cc4ca5SDavid du Colombier d = 5;
36559cc4ca5SDavid du Colombier fillellipse(scr, pt, d, d, color, ZP);
36659cc4ca5SDavid du Colombier if(ring == 1)
36759cc4ca5SDavid du Colombier ellipse(scr, pt, 5*d/2, d/2, 0, color, ZP);
36859cc4ca5SDavid du Colombier if(ring == 2)
36959cc4ca5SDavid du Colombier ellipse(scr, pt, d, d, 0, grey, ZP);
37059cc4ca5SDavid du Colombier if(s){
37159cc4ca5SDavid du Colombier d = stringwidth(font, s);
37259cc4ca5SDavid du Colombier pt.x -= d/2;
37359cc4ca5SDavid du Colombier pt.y -= font->height/2 + 1;
37459cc4ca5SDavid du Colombier string(scr, pt, display->black, ZP, font, s);
37559cc4ca5SDavid du Colombier }
37659cc4ca5SDavid du Colombier }
37759cc4ca5SDavid du Colombier
37859cc4ca5SDavid du Colombier void
drawplanet(Image * scr,Planetrec * p,Point pt)37959cc4ca5SDavid du Colombier drawplanet(Image *scr, Planetrec *p, Point pt)
38059cc4ca5SDavid du Colombier {
38159cc4ca5SDavid du Colombier if(strcmp(p->name, "sun") == 0){
38259cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 0, suncolor, pt, nil);
38359cc4ca5SDavid du Colombier return;
38459cc4ca5SDavid du Colombier }
38559cc4ca5SDavid du Colombier if(strcmp(p->name, "moon") == 0){
38659cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 0, mooncolor, pt, nil);
38759cc4ca5SDavid du Colombier return;
38859cc4ca5SDavid du Colombier }
38959cc4ca5SDavid du Colombier if(strcmp(p->name, "shadow") == 0){
39059cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 2, shadowcolor, pt, nil);
39159cc4ca5SDavid du Colombier return;
39259cc4ca5SDavid du Colombier }
39359cc4ca5SDavid du Colombier if(strcmp(p->name, "mercury") == 0){
39459cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 0, mercurycolor, pt, "m");
39559cc4ca5SDavid du Colombier return;
39659cc4ca5SDavid du Colombier }
39759cc4ca5SDavid du Colombier if(strcmp(p->name, "venus") == 0){
39859cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 0, venuscolor, pt, "v");
39959cc4ca5SDavid du Colombier return;
40059cc4ca5SDavid du Colombier }
40159cc4ca5SDavid du Colombier if(strcmp(p->name, "mars") == 0){
40259cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 0, marscolor, pt, "M");
40359cc4ca5SDavid du Colombier return;
40459cc4ca5SDavid du Colombier }
40559cc4ca5SDavid du Colombier if(strcmp(p->name, "jupiter") == 0){
40659cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 0, jupitercolor, pt, "J");
40759cc4ca5SDavid du Colombier return;
40859cc4ca5SDavid du Colombier }
40959cc4ca5SDavid du Colombier if(strcmp(p->name, "saturn") == 0){
41059cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 1, saturncolor, pt, "S");
41159cc4ca5SDavid du Colombier
41259cc4ca5SDavid du Colombier return;
41359cc4ca5SDavid du Colombier }
41459cc4ca5SDavid du Colombier if(strcmp(p->name, "uranus") == 0){
41559cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 0, uranuscolor, pt, "U");
41659cc4ca5SDavid du Colombier
41759cc4ca5SDavid du Colombier return;
41859cc4ca5SDavid du Colombier }
41959cc4ca5SDavid du Colombier if(strcmp(p->name, "neptune") == 0){
42059cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 0, neptunecolor, pt, "N");
42159cc4ca5SDavid du Colombier
42259cc4ca5SDavid du Colombier return;
42359cc4ca5SDavid du Colombier }
42459cc4ca5SDavid du Colombier if(strcmp(p->name, "pluto") == 0){
42559cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 0, plutocolor, pt, "P");
42659cc4ca5SDavid du Colombier
42759cc4ca5SDavid du Colombier return;
42859cc4ca5SDavid du Colombier }
42959cc4ca5SDavid du Colombier if(strcmp(p->name, "comet") == 0){
43059cc4ca5SDavid du Colombier drawdisc(scr, p->semidiam, 0, cometcolor, pt, "C");
43159cc4ca5SDavid du Colombier return;
43259cc4ca5SDavid du Colombier }
43359cc4ca5SDavid du Colombier
43459cc4ca5SDavid du Colombier pt.x -= stringwidth(font, p->name)/2;
43559cc4ca5SDavid du Colombier pt.y -= font->height/2;
43659cc4ca5SDavid du Colombier string(scr, pt, grey, ZP, font, p->name);
43759cc4ca5SDavid du Colombier }
43859cc4ca5SDavid du Colombier
43959cc4ca5SDavid du Colombier void
tolast(char * name)44059cc4ca5SDavid du Colombier tolast(char *name)
44159cc4ca5SDavid du Colombier {
44259cc4ca5SDavid du Colombier int i, nlast;
44359cc4ca5SDavid du Colombier Record *r, rr;
44459cc4ca5SDavid du Colombier
44559cc4ca5SDavid du Colombier /* stop early to simplify inner loop adjustment */
44659cc4ca5SDavid du Colombier nlast = 0;
44759cc4ca5SDavid du Colombier for(i=0,r=rec; i<nrec-nlast; i++,r++)
44859cc4ca5SDavid du Colombier if(r->type == Planet)
44959cc4ca5SDavid du Colombier if(name==nil || strcmp(r->planet.name, name)==0){
45059cc4ca5SDavid du Colombier rr = *r;
45159cc4ca5SDavid du Colombier memmove(rec+i, rec+i+1, (nrec-i-1)*sizeof(Record));
45259cc4ca5SDavid du Colombier rec[nrec-1] = rr;
45359cc4ca5SDavid du Colombier --i;
45459cc4ca5SDavid du Colombier --r;
45559cc4ca5SDavid du Colombier nlast++;
45659cc4ca5SDavid du Colombier }
45759cc4ca5SDavid du Colombier }
45859cc4ca5SDavid du Colombier
45959cc4ca5SDavid du Colombier int
bbox(long extrara,long extradec,int quantize)46059cc4ca5SDavid du Colombier bbox(long extrara, long extradec, int quantize)
46159cc4ca5SDavid du Colombier {
46259cc4ca5SDavid du Colombier int i;
46359cc4ca5SDavid du Colombier Record *r;
46459cc4ca5SDavid du Colombier int ra, dec;
46559cc4ca5SDavid du Colombier int rah, ram, d1, d2;
46659cc4ca5SDavid du Colombier double r0;
46759cc4ca5SDavid du Colombier
46859cc4ca5SDavid du Colombier ramin = 0x7FFFFFFF;
46959cc4ca5SDavid du Colombier ramax = -0x7FFFFFFF;
47059cc4ca5SDavid du Colombier decmin = 0x7FFFFFFF;
47159cc4ca5SDavid du Colombier decmax = -0x7FFFFFFF;
47259cc4ca5SDavid du Colombier
47359cc4ca5SDavid du Colombier for(i=0,r=rec; i<nrec; i++,r++){
47459cc4ca5SDavid du Colombier if(r->type == Patch){
47559cc4ca5SDavid du Colombier radec(r->index, &rah, &ram, &dec);
47659cc4ca5SDavid du Colombier ra = 15*rah+ram/4;
47759cc4ca5SDavid du Colombier r0 = c/cos(dec*PI/180);
47859cc4ca5SDavid du Colombier ra *= c;
47959cc4ca5SDavid du Colombier dec *= c;
48059cc4ca5SDavid du Colombier if(dec == 0)
48159cc4ca5SDavid du Colombier d1 = c, d2 = c;
48259cc4ca5SDavid du Colombier else if(dec < 0)
48359cc4ca5SDavid du Colombier d1 = c, d2 = 0;
48459cc4ca5SDavid du Colombier else
48559cc4ca5SDavid du Colombier d1 = 0, d2 = c;
48659cc4ca5SDavid du Colombier }else if(r->type==SAO || r->type==NGC || r->type==Planet || r->type==Abell){
48759cc4ca5SDavid du Colombier ra = r->ngc.ra;
48859cc4ca5SDavid du Colombier dec = r->ngc.dec;
48959cc4ca5SDavid du Colombier d1 = 0, d2 = 0, r0 = 0;
49059cc4ca5SDavid du Colombier }else
49159cc4ca5SDavid du Colombier continue;
49259cc4ca5SDavid du Colombier if(dec+d2+extradec > decmax)
49359cc4ca5SDavid du Colombier decmax = dec+d2+extradec;
49459cc4ca5SDavid du Colombier if(dec-d1-extradec < decmin)
49559cc4ca5SDavid du Colombier decmin = dec-d1-extradec;
49659cc4ca5SDavid du Colombier if(folded){
49759cc4ca5SDavid du Colombier ra -= 180*c;
49859cc4ca5SDavid du Colombier if(ra < 0)
49959cc4ca5SDavid du Colombier ra += 360*c;
50059cc4ca5SDavid du Colombier }
50159cc4ca5SDavid du Colombier if(ra+r0+extrara > ramax)
50259cc4ca5SDavid du Colombier ramax = ra+r0+extrara;
50359cc4ca5SDavid du Colombier if(ra-extrara < ramin)
50459cc4ca5SDavid du Colombier ramin = ra-extrara;
50559cc4ca5SDavid du Colombier }
50659cc4ca5SDavid du Colombier
50759cc4ca5SDavid du Colombier if(decmax > 90*c)
50859cc4ca5SDavid du Colombier decmax = 90*c;
50959cc4ca5SDavid du Colombier if(decmin < -90*c)
51059cc4ca5SDavid du Colombier decmin = -90*c;
51159cc4ca5SDavid du Colombier if(ramin < 0)
51259cc4ca5SDavid du Colombier ramin += 360*c;
51359cc4ca5SDavid du Colombier if(ramax >= 360*c)
51459cc4ca5SDavid du Colombier ramax -= 360*c;
51559cc4ca5SDavid du Colombier
51659cc4ca5SDavid du Colombier if(quantize){
51759cc4ca5SDavid du Colombier /* quantize to degree boundaries */
51859cc4ca5SDavid du Colombier ramin -= ramin%m5;
51959cc4ca5SDavid du Colombier if(ramax%m5 != 0)
52059cc4ca5SDavid du Colombier ramax += m5-(ramax%m5);
52159cc4ca5SDavid du Colombier if(decmin > 0)
52259cc4ca5SDavid du Colombier decmin -= decmin%c;
52359cc4ca5SDavid du Colombier else
52459cc4ca5SDavid du Colombier decmin -= c - (-decmin)%c;
52559cc4ca5SDavid du Colombier if(decmax > 0){
52659cc4ca5SDavid du Colombier if(decmax%c != 0)
52759cc4ca5SDavid du Colombier decmax += c-(decmax%c);
52859cc4ca5SDavid du Colombier }else if(decmax < 0){
52959cc4ca5SDavid du Colombier if(decmax%c != 0)
53059cc4ca5SDavid du Colombier decmax += ((-decmax)%c);
53159cc4ca5SDavid du Colombier }
53259cc4ca5SDavid du Colombier }
53359cc4ca5SDavid du Colombier
53459cc4ca5SDavid du Colombier if(folded){
53559cc4ca5SDavid du Colombier if(ramax-ramin > 270*c){
53659cc4ca5SDavid du Colombier fprint(2, "ra range too wide %ld°\n", (ramax-ramin)/c);
53759cc4ca5SDavid du Colombier return -1;
53859cc4ca5SDavid du Colombier }
53959cc4ca5SDavid du Colombier }else if(ramax-ramin > 270*c){
54059cc4ca5SDavid du Colombier folded = 1;
54159cc4ca5SDavid du Colombier return bbox(0, 0, quantize);
54259cc4ca5SDavid du Colombier }
54359cc4ca5SDavid du Colombier
54459cc4ca5SDavid du Colombier return 1;
54559cc4ca5SDavid du Colombier }
54659cc4ca5SDavid du Colombier
54759cc4ca5SDavid du Colombier int
inbbox(DAngle ra,DAngle dec)54859cc4ca5SDavid du Colombier inbbox(DAngle ra, DAngle dec)
54959cc4ca5SDavid du Colombier {
55059cc4ca5SDavid du Colombier int min;
55159cc4ca5SDavid du Colombier
55259cc4ca5SDavid du Colombier if(dec < decmin)
55359cc4ca5SDavid du Colombier return 0;
55459cc4ca5SDavid du Colombier if(dec > decmax)
55559cc4ca5SDavid du Colombier return 0;
55659cc4ca5SDavid du Colombier min = ramin;
55759cc4ca5SDavid du Colombier if(ramin > ramax){ /* straddling 0h0m */
55859cc4ca5SDavid du Colombier min -= 360*c;
55959cc4ca5SDavid du Colombier if(ra > 180*c)
56059cc4ca5SDavid du Colombier ra -= 360*c;
56159cc4ca5SDavid du Colombier }
56259cc4ca5SDavid du Colombier if(ra < min)
56359cc4ca5SDavid du Colombier return 0;
56459cc4ca5SDavid du Colombier if(ra > ramax)
56559cc4ca5SDavid du Colombier return 0;
56659cc4ca5SDavid du Colombier return 1;
56759cc4ca5SDavid du Colombier }
56859cc4ca5SDavid du Colombier
56959cc4ca5SDavid du Colombier int
gridra(long mapdec)57059cc4ca5SDavid du Colombier gridra(long mapdec)
57159cc4ca5SDavid du Colombier {
57259cc4ca5SDavid du Colombier mapdec = abs(mapdec)+c/2;
57359cc4ca5SDavid du Colombier mapdec /= c;
57459cc4ca5SDavid du Colombier if(mapdec < 60)
57559cc4ca5SDavid du Colombier return m5;
57659cc4ca5SDavid du Colombier if(mapdec < 80)
57759cc4ca5SDavid du Colombier return 2*m5;
57859cc4ca5SDavid du Colombier if(mapdec < 85)
57959cc4ca5SDavid du Colombier return 4*m5;
58059cc4ca5SDavid du Colombier return 8*m5;
58159cc4ca5SDavid du Colombier }
58259cc4ca5SDavid du Colombier
58359cc4ca5SDavid du Colombier #define GREY (nogrey? display->white : grey)
58459cc4ca5SDavid du Colombier
58559cc4ca5SDavid du Colombier void
plot(char * flags)58659cc4ca5SDavid du Colombier plot(char *flags)
58759cc4ca5SDavid du Colombier {
58859cc4ca5SDavid du Colombier int i, j, k;
58959cc4ca5SDavid du Colombier char *t;
59059cc4ca5SDavid du Colombier long x, y;
59159cc4ca5SDavid du Colombier int ra, dec;
59259cc4ca5SDavid du Colombier int m;
59359cc4ca5SDavid du Colombier Point p, pts[10];
59459cc4ca5SDavid du Colombier Record *r;
59559cc4ca5SDavid du Colombier Rectangle rect, r1;
59659cc4ca5SDavid du Colombier int dx, dy, nogrid, textlevel, nogrey, zenithup;
59759cc4ca5SDavid du Colombier Image *scr;
59859cc4ca5SDavid du Colombier char *name, buf[32];
59959cc4ca5SDavid du Colombier double v;
60059cc4ca5SDavid du Colombier
60159cc4ca5SDavid du Colombier if(plotopen() < 0)
60259cc4ca5SDavid du Colombier return;
60359cc4ca5SDavid du Colombier nogrid = 0;
60459cc4ca5SDavid du Colombier nogrey = 0;
60559cc4ca5SDavid du Colombier textlevel = 1;
60659cc4ca5SDavid du Colombier dx = 512;
60759cc4ca5SDavid du Colombier dy = 512;
60859cc4ca5SDavid du Colombier zenithup = 0;
60959cc4ca5SDavid du Colombier for(;;){
61059cc4ca5SDavid du Colombier if(t = alpha(flags, "nogrid")){
61159cc4ca5SDavid du Colombier nogrid = 1;
61259cc4ca5SDavid du Colombier flags = t;
61359cc4ca5SDavid du Colombier continue;
61459cc4ca5SDavid du Colombier }
61559cc4ca5SDavid du Colombier if((t = alpha(flags, "zenith")) || (t = alpha(flags, "zenithup")) ){
61659cc4ca5SDavid du Colombier zenithup = 1;
61759cc4ca5SDavid du Colombier flags = t;
61859cc4ca5SDavid du Colombier continue;
61959cc4ca5SDavid du Colombier }
62059cc4ca5SDavid du Colombier if((t = alpha(flags, "notext")) || (t = alpha(flags, "nolabel")) ){
62159cc4ca5SDavid du Colombier textlevel = 0;
62259cc4ca5SDavid du Colombier flags = t;
62359cc4ca5SDavid du Colombier continue;
62459cc4ca5SDavid du Colombier }
62559cc4ca5SDavid du Colombier if((t = alpha(flags, "alltext")) || (t = alpha(flags, "alllabel")) ){
62659cc4ca5SDavid du Colombier textlevel = 2;
62759cc4ca5SDavid du Colombier flags = t;
62859cc4ca5SDavid du Colombier continue;
62959cc4ca5SDavid du Colombier }
63059cc4ca5SDavid du Colombier if(t = alpha(flags, "dx")){
63159cc4ca5SDavid du Colombier dx = strtol(t, &t, 0);
63259cc4ca5SDavid du Colombier if(dx < 100){
63359cc4ca5SDavid du Colombier fprint(2, "dx %d too small (min 100) in plot\n", dx);
63459cc4ca5SDavid du Colombier return;
63559cc4ca5SDavid du Colombier }
63659cc4ca5SDavid du Colombier flags = skipbl(t);
63759cc4ca5SDavid du Colombier continue;
63859cc4ca5SDavid du Colombier }
63959cc4ca5SDavid du Colombier if(t = alpha(flags, "dy")){
64059cc4ca5SDavid du Colombier dy = strtol(t, &t, 0);
64159cc4ca5SDavid du Colombier if(dy < 100){
64259cc4ca5SDavid du Colombier fprint(2, "dy %d too small (min 100) in plot\n", dy);
64359cc4ca5SDavid du Colombier return;
64459cc4ca5SDavid du Colombier }
64559cc4ca5SDavid du Colombier flags = skipbl(t);
64659cc4ca5SDavid du Colombier continue;
64759cc4ca5SDavid du Colombier }
64859cc4ca5SDavid du Colombier if((t = alpha(flags, "nogrey")) || (t = alpha(flags, "nogray"))){
64959cc4ca5SDavid du Colombier nogrey = 1;
65059cc4ca5SDavid du Colombier flags = skipbl(t);
65159cc4ca5SDavid du Colombier continue;
65259cc4ca5SDavid du Colombier }
65359cc4ca5SDavid du Colombier if(*flags){
65459cc4ca5SDavid du Colombier fprint(2, "syntax error in plot\n");
65559cc4ca5SDavid du Colombier return;
65659cc4ca5SDavid du Colombier }
65759cc4ca5SDavid du Colombier break;
65859cc4ca5SDavid du Colombier }
65959cc4ca5SDavid du Colombier flatten();
66059cc4ca5SDavid du Colombier folded = 0;
66159cc4ca5SDavid du Colombier
66259cc4ca5SDavid du Colombier if(bbox(0, 0, 1) < 0)
66359cc4ca5SDavid du Colombier return;
66459cc4ca5SDavid du Colombier if(ramax-ramin<100 || decmax-decmin<100){
66559cc4ca5SDavid du Colombier fprint(2, "plot too small\n");
66659cc4ca5SDavid du Colombier return;
66759cc4ca5SDavid du Colombier }
66859cc4ca5SDavid du Colombier
669*9a747e4fSDavid du Colombier scr = allocimage(display, Rect(0, 0, dx, dy), RGB24, 0, DBlack);
67059cc4ca5SDavid du Colombier if(scr == nil){
67159cc4ca5SDavid du Colombier fprint(2, "can't allocate image: %r\n");
67259cc4ca5SDavid du Colombier return;
67359cc4ca5SDavid du Colombier }
67459cc4ca5SDavid du Colombier rect = scr->r;
67559cc4ca5SDavid du Colombier rect.min.x += 16;
67659cc4ca5SDavid du Colombier rect = insetrect(rect, 40);
67759cc4ca5SDavid du Colombier if(setmap(ramin, ramax, decmin, decmax, rect, zenithup) < 0){
67859cc4ca5SDavid du Colombier fprint(2, "can't set up map coordinates\n");
67959cc4ca5SDavid du Colombier return;
68059cc4ca5SDavid du Colombier }
68159cc4ca5SDavid du Colombier if(!nogrid){
68259cc4ca5SDavid du Colombier for(x=ramin; ; ){
68359cc4ca5SDavid du Colombier for(j=0; j<nelem(pts); j++){
68459cc4ca5SDavid du Colombier /* use double to avoid overflow */
68559cc4ca5SDavid du Colombier v = (double)j / (double)(nelem(pts)-1);
68659cc4ca5SDavid du Colombier v = decmin + v*(decmax-decmin);
68759cc4ca5SDavid du Colombier pts[j] = map(x, v);
68859cc4ca5SDavid du Colombier }
68959cc4ca5SDavid du Colombier bezspline(scr, pts, nelem(pts), Endsquare, Endsquare, 0, GREY, ZP);
69059cc4ca5SDavid du Colombier ra = x;
69159cc4ca5SDavid du Colombier if(folded){
69259cc4ca5SDavid du Colombier ra -= 180*c;
69359cc4ca5SDavid du Colombier if(ra < 0)
69459cc4ca5SDavid du Colombier ra += 360*c;
69559cc4ca5SDavid du Colombier }
69659cc4ca5SDavid du Colombier p = pts[0];
69759cc4ca5SDavid du Colombier p.x -= stringwidth(font, hm5(angle(ra)))/2;
69859cc4ca5SDavid du Colombier string(scr, p, GREY, ZP, font, hm5(angle(ra)));
69959cc4ca5SDavid du Colombier p = pts[nelem(pts)-1];
70059cc4ca5SDavid du Colombier p.x -= stringwidth(font, hm5(angle(ra)))/2;
70159cc4ca5SDavid du Colombier p.y -= font->height;
70259cc4ca5SDavid du Colombier string(scr, p, GREY, ZP, font, hm5(angle(ra)));
70359cc4ca5SDavid du Colombier if(x == ramax)
70459cc4ca5SDavid du Colombier break;
70559cc4ca5SDavid du Colombier x += gridra(mapdec);
70659cc4ca5SDavid du Colombier if(x > ramax)
70759cc4ca5SDavid du Colombier x = ramax;
70859cc4ca5SDavid du Colombier }
70959cc4ca5SDavid du Colombier for(y=decmin; y<=decmax; y+=c){
71059cc4ca5SDavid du Colombier for(j=0; j<nelem(pts); j++){
71159cc4ca5SDavid du Colombier /* use double to avoid overflow */
71259cc4ca5SDavid du Colombier v = (double)j / (double)(nelem(pts)-1);
71359cc4ca5SDavid du Colombier v = ramin + v*(ramax-ramin);
71459cc4ca5SDavid du Colombier pts[j] = map(v, y);
71559cc4ca5SDavid du Colombier }
71659cc4ca5SDavid du Colombier bezspline(scr, pts, nelem(pts), Endsquare, Endsquare, 0, GREY, ZP);
71759cc4ca5SDavid du Colombier p = pts[0];
71859cc4ca5SDavid du Colombier p.x += 3;
71959cc4ca5SDavid du Colombier p.y -= font->height/2;
72059cc4ca5SDavid du Colombier string(scr, p, GREY, ZP, font, deg(angle(y)));
72159cc4ca5SDavid du Colombier p = pts[nelem(pts)-1];
72259cc4ca5SDavid du Colombier p.x -= 3+stringwidth(font, deg(angle(y)));
72359cc4ca5SDavid du Colombier p.y -= font->height/2;
72459cc4ca5SDavid du Colombier string(scr, p, GREY, ZP, font, deg(angle(y)));
72559cc4ca5SDavid du Colombier }
72659cc4ca5SDavid du Colombier }
72759cc4ca5SDavid du Colombier /* reorder to get planets in front of stars */
72859cc4ca5SDavid du Colombier tolast(nil);
72959cc4ca5SDavid du Colombier tolast("moon"); /* moon is in front of everything... */
73059cc4ca5SDavid du Colombier tolast("shadow"); /* ... except the shadow */
73159cc4ca5SDavid du Colombier
73259cc4ca5SDavid du Colombier for(i=0,r=rec; i<nrec; i++,r++){
73359cc4ca5SDavid du Colombier dec = r->ngc.dec;
73459cc4ca5SDavid du Colombier ra = r->ngc.ra;
73559cc4ca5SDavid du Colombier if(folded){
73659cc4ca5SDavid du Colombier ra -= 180*c;
73759cc4ca5SDavid du Colombier if(ra < 0)
73859cc4ca5SDavid du Colombier ra += 360*c;
73959cc4ca5SDavid du Colombier }
74059cc4ca5SDavid du Colombier if(textlevel){
74159cc4ca5SDavid du Colombier name = nameof(r);
74259cc4ca5SDavid du Colombier if(name==nil && textlevel>1 && r->type==SAO){
74359cc4ca5SDavid du Colombier snprint(buf, sizeof buf, "SAO%ld", r->index);
74459cc4ca5SDavid du Colombier name = buf;
74559cc4ca5SDavid du Colombier }
74659cc4ca5SDavid du Colombier if(name)
74759cc4ca5SDavid du Colombier drawname(scr, nogrey? display->white : alphagrey, name, ra, dec);
74859cc4ca5SDavid du Colombier }
74959cc4ca5SDavid du Colombier if(r->type == Planet){
75059cc4ca5SDavid du Colombier drawplanet(scr, &r->planet, map(ra, dec));
75159cc4ca5SDavid du Colombier continue;
75259cc4ca5SDavid du Colombier }
75359cc4ca5SDavid du Colombier if(r->type == SAO){
75459cc4ca5SDavid du Colombier m = r->sao.mag;
75559cc4ca5SDavid du Colombier if(m == UNKNOWNMAG)
75659cc4ca5SDavid du Colombier m = r->sao.mpg;
75759cc4ca5SDavid du Colombier if(m == UNKNOWNMAG)
75859cc4ca5SDavid du Colombier continue;
75959cc4ca5SDavid du Colombier m = dsize(m);
76059cc4ca5SDavid du Colombier if(m < 3)
76159cc4ca5SDavid du Colombier fillellipse(scr, map(ra, dec), m, m, nogrey? display->white : lightgrey, ZP);
76259cc4ca5SDavid du Colombier else{
76359cc4ca5SDavid du Colombier ellipse(scr, map(ra, dec), m+1, m+1, 0, display->black, ZP);
76459cc4ca5SDavid du Colombier fillellipse(scr, map(ra, dec), m, m, display->white, ZP);
76559cc4ca5SDavid du Colombier }
76659cc4ca5SDavid du Colombier continue;
76759cc4ca5SDavid du Colombier }
76859cc4ca5SDavid du Colombier if(r->type == Abell){
76959cc4ca5SDavid du Colombier ellipse(scr, addpt(map(ra, dec), Pt(-3, 2)), 2, 1, 0, lightblue, ZP);
77059cc4ca5SDavid du Colombier ellipse(scr, addpt(map(ra, dec), Pt(3, 2)), 2, 1, 0, lightblue, ZP);
77159cc4ca5SDavid du Colombier ellipse(scr, addpt(map(ra, dec), Pt(0, -2)), 1, 2, 0, lightblue, ZP);
77259cc4ca5SDavid du Colombier continue;
77359cc4ca5SDavid du Colombier }
77459cc4ca5SDavid du Colombier switch(r->ngc.type){
77559cc4ca5SDavid du Colombier case Galaxy:
77659cc4ca5SDavid du Colombier j = npixels(r->ngc.diam);
77759cc4ca5SDavid du Colombier if(j < 4)
77859cc4ca5SDavid du Colombier j = 4;
77959cc4ca5SDavid du Colombier if(j > 10)
78059cc4ca5SDavid du Colombier k = j/3;
78159cc4ca5SDavid du Colombier else
78259cc4ca5SDavid du Colombier k = j/2;
78359cc4ca5SDavid du Colombier ellipse(scr, map(ra, dec), j, k, 0, lightblue, ZP);
78459cc4ca5SDavid du Colombier break;
78559cc4ca5SDavid du Colombier
78659cc4ca5SDavid du Colombier case PlanetaryN:
78759cc4ca5SDavid du Colombier p = map(ra, dec);
78859cc4ca5SDavid du Colombier j = npixels(r->ngc.diam);
78959cc4ca5SDavid du Colombier if(j < 3)
79059cc4ca5SDavid du Colombier j = 3;
79159cc4ca5SDavid du Colombier ellipse(scr, p, j, j, 0, green, ZP);
79259cc4ca5SDavid du Colombier line(scr, Pt(p.x, p.y+j+1), Pt(p.x, p.y+j+4),
79359cc4ca5SDavid du Colombier Endsquare, Endsquare, 0, green, ZP);
79459cc4ca5SDavid du Colombier line(scr, Pt(p.x, p.y-(j+1)), Pt(p.x, p.y-(j+4)),
79559cc4ca5SDavid du Colombier Endsquare, Endsquare, 0, green, ZP);
79659cc4ca5SDavid du Colombier line(scr, Pt(p.x+j+1, p.y), Pt(p.x+j+4, p.y),
79759cc4ca5SDavid du Colombier Endsquare, Endsquare, 0, green, ZP);
79859cc4ca5SDavid du Colombier line(scr, Pt(p.x-(j+1), p.y), Pt(p.x-(j+4), p.y),
79959cc4ca5SDavid du Colombier Endsquare, Endsquare, 0, green, ZP);
80059cc4ca5SDavid du Colombier break;
80159cc4ca5SDavid du Colombier
80259cc4ca5SDavid du Colombier case DiffuseN:
80359cc4ca5SDavid du Colombier case NebularCl:
80459cc4ca5SDavid du Colombier p = map(ra, dec);
80559cc4ca5SDavid du Colombier j = npixels(r->ngc.diam);
80659cc4ca5SDavid du Colombier if(j < 4)
80759cc4ca5SDavid du Colombier j = 4;
80859cc4ca5SDavid du Colombier r1.min = Pt(p.x-j, p.y-j);
80959cc4ca5SDavid du Colombier r1.max = Pt(p.x+j, p.y+j);
81059cc4ca5SDavid du Colombier if(r->ngc.type != DiffuseN)
81159cc4ca5SDavid du Colombier draw(scr, r1, ocstipple, ocstipple, ZP);
81259cc4ca5SDavid du Colombier line(scr, Pt(p.x-j, p.y-j), Pt(p.x+j, p.y-j),
81359cc4ca5SDavid du Colombier Endsquare, Endsquare, 0, green, ZP);
81459cc4ca5SDavid du Colombier line(scr, Pt(p.x-j, p.y+j), Pt(p.x+j, p.y+j),
81559cc4ca5SDavid du Colombier Endsquare, Endsquare, 0, green, ZP);
81659cc4ca5SDavid du Colombier line(scr, Pt(p.x-j, p.y-j), Pt(p.x-j, p.y+j),
81759cc4ca5SDavid du Colombier Endsquare, Endsquare, 0, green, ZP);
81859cc4ca5SDavid du Colombier line(scr, Pt(p.x+j, p.y-j), Pt(p.x+j, p.y+j),
81959cc4ca5SDavid du Colombier Endsquare, Endsquare, 0, green, ZP);
82059cc4ca5SDavid du Colombier break;
82159cc4ca5SDavid du Colombier
82259cc4ca5SDavid du Colombier case OpenCl:
82359cc4ca5SDavid du Colombier p = map(ra, dec);
82459cc4ca5SDavid du Colombier j = npixels(r->ngc.diam);
82559cc4ca5SDavid du Colombier if(j < 4)
82659cc4ca5SDavid du Colombier j = 4;
82759cc4ca5SDavid du Colombier fillellipse(scr, p, j, j, ocstipple, ZP);
82859cc4ca5SDavid du Colombier break;
82959cc4ca5SDavid du Colombier
83059cc4ca5SDavid du Colombier case GlobularCl:
83159cc4ca5SDavid du Colombier j = npixels(r->ngc.diam);
83259cc4ca5SDavid du Colombier if(j < 4)
83359cc4ca5SDavid du Colombier j = 4;
83459cc4ca5SDavid du Colombier p = map(ra, dec);
83559cc4ca5SDavid du Colombier ellipse(scr, p, j, j, 0, lightgrey, ZP);
83659cc4ca5SDavid du Colombier line(scr, Pt(p.x-(j-1), p.y), Pt(p.x+j, p.y),
83759cc4ca5SDavid du Colombier Endsquare, Endsquare, 0, lightgrey, ZP);
83859cc4ca5SDavid du Colombier line(scr, Pt(p.x, p.y-(j-1)), Pt(p.x, p.y+j),
83959cc4ca5SDavid du Colombier Endsquare, Endsquare, 0, lightgrey, ZP);
84059cc4ca5SDavid du Colombier break;
84159cc4ca5SDavid du Colombier
84259cc4ca5SDavid du Colombier }
84359cc4ca5SDavid du Colombier }
84459cc4ca5SDavid du Colombier flushimage(display, 1);
84559cc4ca5SDavid du Colombier displayimage(scr);
84659cc4ca5SDavid du Colombier }
84759cc4ca5SDavid du Colombier
84859cc4ca5SDavid du Colombier int
runcommand(char * command,int p[2])84959cc4ca5SDavid du Colombier runcommand(char *command, int p[2])
85059cc4ca5SDavid du Colombier {
85159cc4ca5SDavid du Colombier switch(rfork(RFPROC|RFFDG|RFNOWAIT)){
85259cc4ca5SDavid du Colombier case -1:
85359cc4ca5SDavid du Colombier return -1;
85459cc4ca5SDavid du Colombier default:
85559cc4ca5SDavid du Colombier break;
85659cc4ca5SDavid du Colombier case 0:
85759cc4ca5SDavid du Colombier dup(p[1], 1);
85859cc4ca5SDavid du Colombier close(p[0]);
85959cc4ca5SDavid du Colombier close(p[1]);
86059cc4ca5SDavid du Colombier execl("/bin/rc", "rc", "-c", command, nil);
86159cc4ca5SDavid du Colombier fprint(2, "can't exec %s: %r", command);
86259cc4ca5SDavid du Colombier exits(nil);
86359cc4ca5SDavid du Colombier }
86459cc4ca5SDavid du Colombier return 1;
86559cc4ca5SDavid du Colombier }
86659cc4ca5SDavid du Colombier
86759cc4ca5SDavid du Colombier void
parseplanet(char * line,Planetrec * p)86859cc4ca5SDavid du Colombier parseplanet(char *line, Planetrec *p)
86959cc4ca5SDavid du Colombier {
87059cc4ca5SDavid du Colombier char *fld[6];
87159cc4ca5SDavid du Colombier int i, nfld;
87259cc4ca5SDavid du Colombier char *s;
87359cc4ca5SDavid du Colombier
87459cc4ca5SDavid du Colombier if(line[0] == '\0')
87559cc4ca5SDavid du Colombier return;
87659cc4ca5SDavid du Colombier line[10] = '\0'; /* terminate name */
87759cc4ca5SDavid du Colombier s = strrchr(line, ' ');
87859cc4ca5SDavid du Colombier if(s == nil)
87959cc4ca5SDavid du Colombier s = line;
88059cc4ca5SDavid du Colombier else
88159cc4ca5SDavid du Colombier s++;
88259cc4ca5SDavid du Colombier strcpy(p->name, s);
88359cc4ca5SDavid du Colombier for(i=0; s[i]!='\0'; i++)
88459cc4ca5SDavid du Colombier p->name[i] = tolower(s[i]);
88559cc4ca5SDavid du Colombier p->name[i] = '\0';
88659cc4ca5SDavid du Colombier nfld = getfields(line+11, fld, nelem(fld), 1, " ");
88759cc4ca5SDavid du Colombier p->ra = dangle(getra(fld[0]));
88859cc4ca5SDavid du Colombier p->dec = dangle(getra(fld[1]));
88959cc4ca5SDavid du Colombier p->az = atof(fld[2])*MILLIARCSEC;
89059cc4ca5SDavid du Colombier p->alt = atof(fld[3])*MILLIARCSEC;
89159cc4ca5SDavid du Colombier p->semidiam = atof(fld[4])*1000;
89259cc4ca5SDavid du Colombier if(nfld > 5)
89359cc4ca5SDavid du Colombier p->phase = atof(fld[5]);
89459cc4ca5SDavid du Colombier else
89559cc4ca5SDavid du Colombier p->phase = 0;
89659cc4ca5SDavid du Colombier }
89759cc4ca5SDavid du Colombier
89859cc4ca5SDavid du Colombier void
astro(char * flags,int initial)89959cc4ca5SDavid du Colombier astro(char *flags, int initial)
90059cc4ca5SDavid du Colombier {
90159cc4ca5SDavid du Colombier int p[2];
90259cc4ca5SDavid du Colombier int i, n, np;
90359cc4ca5SDavid du Colombier char cmd[256], buf[4096], *lines[20], *fld[10];
90459cc4ca5SDavid du Colombier
90559cc4ca5SDavid du Colombier snprint(cmd, sizeof cmd, "/bin/astro -p %s", flags);
90659cc4ca5SDavid du Colombier if(pipe(p) < 0){
90759cc4ca5SDavid du Colombier fprint(2, "can't pipe: %r\n");
90859cc4ca5SDavid du Colombier return;
90959cc4ca5SDavid du Colombier }
91059cc4ca5SDavid du Colombier if(runcommand(cmd, p) < 0){
91159cc4ca5SDavid du Colombier close(p[0]);
91259cc4ca5SDavid du Colombier close(p[1]);
91359cc4ca5SDavid du Colombier fprint(2, "can't run astro: %r");
91459cc4ca5SDavid du Colombier return;
91559cc4ca5SDavid du Colombier }
91659cc4ca5SDavid du Colombier close(p[1]);
91759cc4ca5SDavid du Colombier n = readn(p[0], buf, sizeof buf-1);
91859cc4ca5SDavid du Colombier if(n <= 0){
91959cc4ca5SDavid du Colombier fprint(2, "no data from astro\n");
92059cc4ca5SDavid du Colombier return;
92159cc4ca5SDavid du Colombier }
92259cc4ca5SDavid du Colombier if(!initial)
92359cc4ca5SDavid du Colombier Bwrite(&bout, buf, n);
92459cc4ca5SDavid du Colombier buf[n] = '\0';
92559cc4ca5SDavid du Colombier np = getfields(buf, lines, nelem(lines), 0, "\n");
92659cc4ca5SDavid du Colombier if(np <= 1){
92759cc4ca5SDavid du Colombier fprint(2, "astro: not enough output\n");
92859cc4ca5SDavid du Colombier return;
92959cc4ca5SDavid du Colombier }
93059cc4ca5SDavid du Colombier Bprint(&bout, "%s\n", lines[0]);
93159cc4ca5SDavid du Colombier Bflush(&bout);
93259cc4ca5SDavid du Colombier /* get latitude and longitude */
93359cc4ca5SDavid du Colombier if(getfields(lines[0], fld, nelem(fld), 1, " ") < 8)
93459cc4ca5SDavid du Colombier fprint(2, "astro: can't read longitude: too few fields\n");
93559cc4ca5SDavid du Colombier else{
93659cc4ca5SDavid du Colombier mysid = getra(fld[5])*180./PI;
93759cc4ca5SDavid du Colombier mylat = getra(fld[6])*180./PI;
93859cc4ca5SDavid du Colombier mylon = getra(fld[7])*180./PI;
93959cc4ca5SDavid du Colombier }
94059cc4ca5SDavid du Colombier /*
94159cc4ca5SDavid du Colombier * Each time we run astro, we generate a new planet list
94259cc4ca5SDavid du Colombier * so multiple appearances of a planet may exist as we plot
94359cc4ca5SDavid du Colombier * its motion over time.
94459cc4ca5SDavid du Colombier */
94559cc4ca5SDavid du Colombier planet = malloc(NPlanet*sizeof planet[0]);
94659cc4ca5SDavid du Colombier if(planet == nil){
94759cc4ca5SDavid du Colombier fprint(2, "astro: malloc failed: %r\n");
94859cc4ca5SDavid du Colombier exits("malloc");
94959cc4ca5SDavid du Colombier }
95059cc4ca5SDavid du Colombier memset(planet, 0, NPlanet*sizeof planet[0]);
95159cc4ca5SDavid du Colombier for(i=1; i<np; i++)
95259cc4ca5SDavid du Colombier parseplanet(lines[i], &planet[i-1]);
95359cc4ca5SDavid du Colombier }
954