📄 scat.c
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <draw.h>#include <event.h>#include "sky.h"#include "strings.c"enum{ NNGC=7840, /* number of NGC numbers [1..NNGC] */ NIC = 5386, /* number of IC numbers */ NNGCrec=NNGC+NIC, /* number of records in the NGC catalog (including IC's, starting at NNGC */ NMrec=122, /* number of M records */ NM=110, /* number of M numbers */ NAbell=2712, /* number of records in the Abell catalog */ NName=1000, /* number of prose names; estimated maximum (read from editable text file) */ NBayer=1517, /* number of bayer entries */ NSAO=258998, /* number of SAO stars */ MAXcon=1932, /* maximum number of patches in a constellation */ Ncon=88, /* number of constellations */ Npatch=92053, /* highest patch number */};char ngctype[NNGCrec];Mindexrec mindex[NMrec];Namerec name[NName];Bayerec bayer[NBayer];long con[MAXcon];ushort conindex[Ncon+1];long patchaddr[Npatch+1];Record *rec;Record *orec;Record *cur;char *dir=DIR;int saodb;int ngcdb;int abelldb;int ngctypedb;int mindexdb;int namedb;int bayerdb;int condb;int conindexdb;int patchdb;char parsed[3];long nrec;long nreca;long norec;long noreca;Biobuf bin;Biobuf bout;main(int argc, char *argv[]){ char *line; Binit(&bin, 0, OREAD); Binit(&bout, 1, OWRITE); if(argc != 1) dir = argv[1]; astro("", 1); while(line = Brdline(&bin, '\n')){ line[Blinelen(&bin)-1] = 0; lookup(line, 1); Bflush(&bout); } if(display != nil){ closedisplay(display); /* automatic refresh of rio window is triggered by mouse */ close(open("/dev/mouse", OREAD)); } return 0;}voidreset(void){ nrec = 0; cur = rec;}voidgrow(void){ nrec++; if(nreca < nrec){ nreca = nrec+50; rec = realloc(rec, nreca*sizeof(Record)); if(rec == 0){ fprint(2, "scat: realloc fails\n"); exits("realloc"); } } cur = rec+nrec-1;}voidcopy(void){ if(noreca < nreca){ noreca = nreca; orec = realloc(orec, nreca*sizeof(Record)); if(orec == 0){ fprint(2, "scat: realloc fails\n"); exits("realloc"); } } memmove(orec, rec, nrec*sizeof(Record)); norec = nrec;}inteopen(char *s){ char buf[128]; int f; sprint(buf, "%s/%s.scat", dir, s); f = open(buf, 0); if(f<0){ fprint(2, "scat: can't open %s\n", buf); exits("open"); } return f;}voidEread(int f, char *name, void *addr, long n){ if(read(f, addr, n) != n){ /* BUG! */ fprint(2, "scat: read error on %s\n", name); exits("read"); }}char*skipbl(char *s){ while(*s!=0 && (*s==' ' || *s=='\t')) s++; return s;}char*skipstr(char *s, char *t){ while(*s && *s==*t) s++, t++; return skipbl(s);}/* produce little-endian long at address l */longLong(long *l){ uchar *p; p = (uchar*)l; return (long)p[0]|((long)p[1]<<8)|((long)p[2]<<16)|((long)p[3]<<24);}/* produce little-endian long at address l */intShort(short *s){ uchar *p; p = (uchar*)s; return p[0]|(p[1]<<8);}voidnameopen(void){ Biobuf b; int i; char *l, *p; if(namedb == 0){ namedb = eopen("name"); Binit(&b, namedb, OREAD); for(i=0; i<NName; i++){ l = Brdline(&b, '\n'); if(l == 0) break; p = strchr(l, '\t'); if(p == 0){ Badformat: Bprint(&bout, "warning: name.scat bad format; line %d\n", i+1); break; } *p++ = 0; strcpy(name[i].name, l); if(strncmp(p, "ngc", 3) == 0) name[i].ngc = atoi(p+3); else if(strncmp(p, "ic", 2) == 0) name[i].ngc = atoi(p+2)+NNGC; else if(strncmp(p, "sao", 3) == 0) name[i].sao = atoi(p+3); else if(strncmp(p, "abell", 5) == 0) name[i].abell = atoi(p+5); else goto Badformat; } if(i == NName) Bprint(&bout, "warning: too many names in name.scat (max %d); extra ignored\n", NName); close(namedb); bayerdb = eopen("bayer"); Eread(bayerdb, "bayer", bayer, sizeof bayer); close(bayerdb); for(i=0; i<NBayer; i++) bayer[i].sao = Long(&bayer[i].sao); }}voidsaoopen(void){ if(saodb == 0){ nameopen(); saodb = eopen("sao"); }}voidngcopen(void){ if(ngcdb == 0){ nameopen(); ngcdb = eopen("ngc2000"); ngctypedb = eopen("ngc2000type"); Eread(ngctypedb, "ngctype", ngctype, sizeof ngctype); close(ngctypedb); }}voidabellopen(void){ /* nothing extra to do with abell: it's directly indexed by number */ if(abelldb == 0) abelldb = eopen("abell");}voidpatchopen(void){ Biobuf *b; long l, m; char buf[100]; if(patchdb == 0){ patchdb = eopen("patch"); sprint(buf, "%s/patchindex.scat", dir); b = Bopen(buf, OREAD); if(b == 0){ fprint(2, "can't open %s\n", buf); exits("open"); } for(m=0,l=0; l<=Npatch; l++) patchaddr[l] = m += Bgetc(b)*4; Bterm(b); }}voidmopen(void){ int i; if(mindexdb == 0){ mindexdb = eopen("mindex"); Eread(mindexdb, "mindex", mindex, sizeof mindex); close(mindexdb); for(i=0; i<NMrec; i++) mindex[i].ngc = Short(&mindex[i].ngc); }}voidconstelopen(void){ int i; if(condb == 0){ condb = eopen("con"); conindexdb = eopen("conindex"); Eread(conindexdb, "conindex", conindex, sizeof conindex); close(conindexdb); for(i=0; i<Ncon+1; i++) conindex[i] = Short((short*)&conindex[i]); }}voidlowercase(char *s){ for(; *s; s++) if('A'<=*s && *s<='Z') *s += 'a'-'A';}intloadngc(long index){ static int failed; long j; ngcopen(); j = (index-1)*sizeof(NGCrec); grow(); cur->type = NGC; cur->index = index; seek(ngcdb, j, 0); /* special case: NGC data may not be available */ if(read(ngcdb, &cur->ngc, sizeof(NGCrec)) != sizeof(NGCrec)){ if(!failed){ fprint(2, "scat: NGC database not available\n"); failed++; } cur->type = NONGC; cur->ngc.ngc = 0; cur->ngc.ra = 0; cur->ngc.dec = 0; cur->ngc.diam = 0; cur->ngc.mag = 0; return 0; } cur->ngc.ngc = Short(&cur->ngc.ngc); cur->ngc.ra = Long(&cur->ngc.ra); cur->ngc.dec = Long(&cur->ngc.dec); cur->ngc.diam = Long(&cur->ngc.diam); cur->ngc.mag = Short(&cur->ngc.mag); return 1;}intloadabell(long index){ long j; abellopen(); j = index-1; grow(); cur->type = Abell; cur->index = index; seek(abelldb, j*sizeof(Abellrec), 0); Eread(abelldb, "abell", &cur->abell, sizeof(Abellrec)); cur->abell.abell = Short(&cur->abell.abell); if(cur->abell.abell != index){ fprint(2, "bad format in abell catalog\n"); exits("abell"); } cur->abell.ra = Long(&cur->abell.ra); cur->abell.dec = Long(&cur->abell.dec); cur->abell.glat = Long(&cur->abell.glat); cur->abell.glong = Long(&cur->abell.glong); cur->abell.rad = Long(&cur->abell.rad); cur->abell.mag10 = Short(&cur->abell.mag10); cur->abell.pop = Short(&cur->abell.pop); cur->abell.dist = Short(&cur->abell.dist); return 1;}intloadsao(int index){ if(index<=0 || index>NSAO) return 0; saoopen(); grow(); cur->type = SAO; cur->index = index; seek(saodb, (index-1)*sizeof(SAOrec), 0); Eread(saodb, "sao", &cur->sao, sizeof(SAOrec)); cur->sao.ra = Long(&cur->sao.ra); cur->sao.dec = Long(&cur->sao.dec); cur->sao.dra = Long(&cur->sao.dra); cur->sao.ddec = Long(&cur->sao.ddec); cur->sao.mag = Short(&cur->sao.mag); cur->sao.mpg = Short(&cur->sao.mpg); cur->sao.hd = Long(&cur->sao.hd); return 1;}intloadplanet(int index, Record *r){ if(index<0 || index>NPlanet || planet[index].name[0]=='\0') return 0; grow(); cur->type = Planet; cur->index = index; /* check whether to take new or existing record */ if(r == nil) memmove(&cur->planet, &planet[index], sizeof(Planetrec)); else memmove(&cur->planet, &r->planet, sizeof(Planetrec)); return 1;}intloadpatch(long index){ int i; patchopen(); if(index<=0 || index>Npatch) return 0; grow(); cur->type = Patch; cur->index = index; seek(patchdb, patchaddr[index-1], 0); cur->patch.nkey = (patchaddr[index]-patchaddr[index-1])/4; Eread(patchdb, "patch", cur->patch.key, cur->patch.nkey*4); for(i=0; i<cur->patch.nkey; i++) cur->patch.key[i] = Long(&cur->patch.key[i]); return 1;}intloadtype(int t){ int i; ngcopen(); for(i=0; i<NNGCrec; i++) if(t == (ngctype[i])){ grow(); cur->type = NGCN; cur->index = i+1; } return 1;}voidflatten(void){ int i, j, notflat; Record *or; long key; loop: copy(); reset(); notflat = 0; for(i=0,or=orec; i<norec; i++,or++){ switch(or->type){ default: fprint(2, "bad type %d in flatten\n", or->type); break; case NONGC: break; case Planet: case Abell: case NGC: case SAO: grow(); memmove(cur, or, sizeof(Record)); break; case NGCN: if(loadngc(or->index)) notflat = 1; break; case NamedSAO: loadsao(or->index); notflat = 1; break; case NamedNGC: if(loadngc(or->index)) notflat = 1; break; case NamedAbell: loadabell(or->index); notflat = 1; break; case PatchC: loadpatch(or->index); notflat = 1; break; case Patch: for(j=1; j<or->patch.nkey; j++){ key = or->patch.key[j]; if((key&0x3F) == SAO) loadsao((key>>8)&0xFFFFFF); else if((key&0x3F) == Abell) loadabell((key>>8)&0xFFFFFF); else loadngc((key>>16)&0xFFFF); } break; } } if(notflat) goto loop;}intism(int index){ int i; for(i=0; i<NMrec; i++) if(mindex[i].ngc == index) return 1; return 0;}char*alpha(char *s, char *t){ int n; n = strlen(t); if(strncmp(s, t, n)==0 && (s[n]<'a' || 'z'<s[n])) return skipbl(s+n); return 0; }char*text(char *s, char *t){ int n; n = strlen(t); if(strncmp(s, t, n)==0 && (s[n]==0 || s[n]==' ' || s[n]=='\t')) return skipbl(s+n); return 0; }intcull(char *s, int keep, int dobbox){ int i, j, nobj, keepthis; Record *or; char *t; int dogrtr, doless, dom, dosao, dongc, doabell; int mgrtr, mless; char obj[100]; memset(obj, 0, sizeof(obj)); nobj = 0; dogrtr = 0; doless = 0; dom = 0; dongc = 0; dosao = 0; doabell = 0; mgrtr = mless= 0; if(dobbox) goto Cull; for(;;){ if(s[0] == '>'){ dogrtr = 1; mgrtr = 10 * strtod(s+1, &t); if(mgrtr==0 && t==s+1){ fprint(2, "bad magnitude\n"); return 0; } s = skipbl(t); continue; } if(s[0] == '<'){ doless = 1; mless = 10 * strtod(s+1, &t); if(mless==0 && t==s+1){ fprint(2, "bad magnitude\n"); return 0; } s = skipbl(t); continue; } if(t = text(s, "m")){ dom = 1; s = t; continue; } if(t = text(s, "sao")){ dosao = 1; s = t; continue; } if(t = text(s, "ngc")){ dongc = 1; s = t; continue; } if(t = text(s, "abell")){ doabell = 1; s = t; continue; } for(i=0; names[i].name; i++) if(t = alpha(s, names[i].name)){ if(nobj > 100){ fprint(2, "too many object types\n"); return 0; } obj[nobj++] = names[i].type; s = t; goto Continue; } break; Continue:; } if(*s){ fprint(2, "syntax error in object list\n"); return 0; } Cull: flatten(); copy(); reset(); if(dom) mopen(); if(dosao) saoopen(); if(dongc || nobj) ngcopen(); if(doabell) abellopen(); for(i=0,or=orec; i<norec; i++,or++){ keepthis = !keep; if(dobbox && inbbox(or->ngc.ra, or->ngc.dec)) keepthis = keep; if(doless && or->ngc.mag <= mless) keepthis = keep; if(dogrtr && or->ngc.mag >= mgrtr) keepthis = keep; if(dom && (or->type==NGC && ism(or->ngc.ngc))) keepthis = keep; if(dongc && or->type==NGC) keepthis = keep; if(doabell && or->type==Abell) keepthis = keep; if(dosao && or->type==SAO) keepthis = keep; for(j=0; j<nobj; j++) if(or->type==NGC && or->ngc.type==obj[j]) keepthis = keep; if(keepthis){ grow(); memmove(cur, or, sizeof(Record)); } } return 1;}intcompar(void *va, void *vb){ Record *a=va, *b=vb; if(a->type == b->type) return a->index - b->index; return a->type - b->type;}voidsort(void){ int i; Record *r, *s; if(nrec == 0) return; qsort(rec, nrec, sizeof(Record), compar); r = rec+1; s = rec; for(i=1; i<nrec; i++,r++){ /* may have multiple instances of a planet in the scene */ if(r->type==s->type && r->index==s->index && r->type!=Planet) continue; memmove(++s, r, sizeof(Record)); } nrec = (s+1)-rec;}char greekbuf[128];char*togreek(char *s){ char *t; int i, n; Rune r; t = greekbuf; while(*s){ for(i=1; i<=24; i++){ n = strlen(greek[i]); if(strncmp(s, greek[i], n)==0 && (s[n]==' ' || s[n]=='\t')){ s += n; t += runetochar(t, &greeklet[i]); goto Cont; } } n = chartorune(&r, s); for(i=0; i<n; i++) *t++ = *s++; Cont:; } *t = 0; return greekbuf;}char*fromgreek(char *s){ char *t; int i, n; Rune r; t = greekbuf; while(*s){ n = chartorune(&r, s); for(i=1; i<=24; i++){ if(r == greeklet[i]){ strcpy(t, greek[i]); t += strlen(greek[i]); s += n; goto Cont; } } for(i=0; i<n; i++) *t++ = *s++; Cont:; } *t = 0; return greekbuf;}#ifdef OLD/* * Old version */intcoords(int deg){ int i; int x, y; Record *or; long dec, ra, ndec, nra; int rdeg; flatten(); copy(); reset(); deg *= 2; for(i=0,or=orec; i<norec; i++,or++){ if(or->type == Planet) /* must keep it here */ loadplanet(or->index, or); dec = or->ngc.dec/MILLIARCSEC; ra = or->ngc.ra/MILLIARCSEC; rdeg = deg/cos((dec*PI)/180); for(y=-deg; y<=+deg; y++){ ndec = dec*2+y; if(ndec/2>=90 || ndec/2<=-90) continue; /* fp errors hurt here, so we round 1' to the pole */ if(ndec >= 0) ndec = ndec*500*60*60 + 60000; else ndec = ndec*500*60*60 - 60000; for(x=-rdeg; x<=+rdeg; x++){ nra = ra*2+x; if(nra/2 < 0) nra += 360*2; if(nra/2 >= 360) nra -= 360*2; /* fp errors hurt here, so we round up 1' */ nra = nra/2*MILLIARCSEC + 60000; loadpatch(patcha(angle(nra), angle(ndec))); } } } sort(); return 1;}#endif/* * New version attempts to match the boundaries of the plot better. */intcoords(int deg){ int i; int x, y, xx; Record *or; long min, circle; double factor; flatten(); circle = 360*MILLIARCSEC; deg *= MILLIARCSEC; /* find center */ folded = 0; bbox(0, 0, 0); /* now expand */ factor = cos(angle((decmax+decmin)/2)); if(factor < .2) factor = .2; factor = floor(1/factor); folded = 0; bbox(factor*deg, deg, 1); Bprint(&bout, "%s to ", hms(angle(ramin))); Bprint(&bout, "%s\n", hms(angle(ramax))); Bprint(&bout, "%s to ", dms(angle(decmin))); Bprint(&bout, "%s\n", dms(angle(decmax))); copy(); reset(); for(i=0,or=orec; i<norec; i++,or++) if(or->type == Planet) /* must keep it here */ loadplanet(or->index, or); min = ramin;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -