Annotation of researchv10no/cmd/map/export/map.c, revision 1.1.1.1

1.1       root        1: #include "map.h"
                      2: 
                      3: #define NVERT 20       /* max number of vertices in a -v polygon */
                      4: #define HALFWIDTH 8192 /* output scaled to fit in -HALFWIDTH,HALFWIDTH */
                      5: #define LONGLINES (HALFWIDTH*4)        /* permissible segment lengths */
                      6: #define SHORTLINES (HALFWIDTH/8)
                      7: #define SCALERATIO 10  /* of abs to rel data (see map(5)) */
                      8: #define RESOL 2.       /* coarsest resolution for tracing grid (degrees) */
                      9: #define TWO_THRD 0.66666666666666667
                     10: 
                     11: int normproj(double, double, double *, double *);
                     12: int posproj(double, double, double *, double *);
                     13: int picut(struct place *, struct place *, double *);
                     14: double reduce(double);
                     15: short getshort(FILE *);
                     16: char *mapindex(char *);
                     17: proj projection;
                     18: 
                     19: 
                     20: static char *mapdir = "/usr/dict";     /* default map directory */
                     21: struct file {
                     22:        char *name;
                     23:        char *color;
                     24:        char *style;
                     25: };
                     26: static struct file dfltfile = {
                     27:        "world", BLACK, SOLID   /* default map */
                     28: };
                     29: static struct file *file = &dfltfile;  /* list of map files */
                     30: static int nfile = 1;                  /* length of list */
                     31: static char *currcolor = BLACK;                /* current color */
                     32: static char *gridcolor = BLACK;
                     33: static char *bordcolor = BLACK;
                     34: 
                     35: extern struct index index[];
                     36: int halfwidth = HALFWIDTH;
                     37: 
                     38: static int (*cut)(struct place *, struct place *, double *);
                     39: static int (*limb)(double*, double*, double);
                     40: static void dolimb(void);
                     41: static int onlimb;
                     42: static int poles;
                     43: static double orientation[3] = { 90., 0., 0. };        /* -o option */
                     44: static oriented;       /* nonzero if -o option occurred */
                     45: static upright;                /* 1 if orientation[0]==90, -1 if -90, else 0*/
                     46: static int delta = 1;  /* -d setting */
                     47: static double limits[4] = {    /* -l parameters */
                     48:        -90., 90., -180., 180.
                     49: };
                     50: static double klimits[4] = {   /* -k parameters */
                     51:        -90., 90., -180., 180.
                     52: };
                     53: static int limcase;
                     54: static double rlimits[4];      /* limits expressed in radians */
                     55: static double lolat, hilat, lolon, hilon;
                     56: static double window[4] = {    /* option -w */
                     57:        -90., 90., -180., 180.
                     58: };
                     59: static windowed;       /* nozero if option -w */
                     60: static struct vert { double x, y; } v[NVERT+2];        /*clipping polygon*/
                     61: static struct edge { double a, b, c; } e[NVERT]; /* coeffs for linear inequality */
                     62: static int nvert;      /* number of vertices in clipping polygon */
                     63: 
                     64: static double rwindow[4];      /* window, expressed in radians */
                     65: static double params[2];               /* projection params */
                     66: /* bounds on output values before scaling; found by coarse survey */
                     67: static double xmin = 100.;
                     68: static double xmax = -100.;
                     69: static double ymin = 100.;
                     70: static double ymax = -100.;
                     71: static double xcent, ycent;
                     72: static double xoff, yoff;
                     73: double xrange, yrange;
                     74: static int left = -HALFWIDTH;
                     75: static int right = HALFWIDTH;
                     76: static int bottom = -HALFWIDTH;
                     77: static int top = HALFWIDTH;
                     78: static int longlines = SHORTLINES; /* drop longer segments */
                     79: static int shortlines = SHORTLINES;
                     80: static int bflag = 1;  /* 0 for option -b */
                     81: static int s1flag = 0; /* 1 for option -s1 */
                     82: static int s2flag = 0; /* 1 for option -s2 */
                     83: static int rflag = 0;  /* 1 for option -r */
                     84: static int kflag = 0;  /* 1 if option -k occurred */
                     85: static int xflag = 0;  /* 1 if option -x occurred */
                     86:        int vflag = 1;  /* -1 if option -v occurred */
                     87: static double position[3];     /* option -p */
                     88: static double center[3] = {0., 0., 0.};        /* option -c */
                     89: static struct coord crot;              /* option -c */
                     90: static double grid[3] = { 10., 10., RESOL };   /* option -g */
                     91: static double dlat, dlon;      /* resolution for tracing grid in lat and lon */
                     92: static double scaling; /* to compute final integer output */
                     93: static struct file *track;     /* options -t and -u */
                     94: static int ntrack;             /* number of tracks present */
                     95: static char *symbolfile;       /* option -y */
                     96: 
                     97: void   clamp(double *px, double v);
                     98: void   clipinit(void);
                     99: double diddle(struct place *, double, double);
                    100: double diddle(struct place *, double, double);
                    101: void   dobounds(double, double, double, double, int);
                    102: void   dogrid(double, double, double, double);
                    103: int    duple(struct place *, double);
                    104: double fmax(double, double);
                    105: double fmin(double, double);
                    106: void   getdata(char *);
                    107: int    gridpt(double, double, int);
                    108: int    inpoly(double, double);
                    109: int    inwindow(struct place *);
                    110: void   pathnames(void);
                    111: int    pnorm(double);
                    112: void   radbds(double *w, double *rw);
                    113: void   revlon(struct place *, double);
                    114: void   satellite(struct file *);
                    115: int    seeable(double, double);
                    116: void   windlim(void);
                    117: void   realcut(void);
                    118: 
                    119: int
                    120: option(char *s) 
                    121: {
                    122: 
                    123:        if(s[0]=='-' && (s[1]<'0'||s[1]>'9'))
                    124:                return(s[1]!='.'&&s[1]!=0);
                    125:        else
                    126:                return(0);
                    127: }
                    128: 
                    129: void
                    130: conv(int k, struct coord *g)
                    131: {
                    132:        g->l = (0.0001/SCALERATIO)*k;
                    133:        sincos(g);
                    134: }
                    135: 
                    136: int
                    137: main(int argc, char *argv[])
                    138: {
                    139:        int i,k;
                    140:        char *s, *t, *style;
                    141:        double x, y;
                    142:        double lat, lon;
                    143:        double *wlim;
                    144:        double dd;
                    145:        if(sizeof(short)!=2)
                    146:                abort();        /* getshort() won't work */
                    147:        s = getenv("MAP");
                    148:        if(s)
                    149:                file[0].name = s;
                    150:        s = getenv("MAPDIR");
                    151:        if(s)
                    152:                mapdir = s;
                    153:        if(argc<=1) 
                    154:                error("usage: map projection params options");
                    155:        for(k=0;index[k].name;k++) {
                    156:                s = index[k].name;
                    157:                t = argv[1];
                    158:                while(*s == *t){
                    159:                        if(*s==0) goto found;
                    160:                        s++;
                    161:                        t++;
                    162:                }
                    163:        }
                    164:        fprintf(stderr,"projections:\n");
                    165:        for(i=0;index[i].name;i++)  {
                    166:                fprintf(stderr,"%s",index[i].name);
                    167:                for(k=0; k<index[i].npar; k++)
                    168:                        fprintf(stderr," p%d", k);
                    169:                fprintf(stderr,"\n");
                    170:        }
                    171:        exit(1);
                    172: found:
                    173:        argv += 2;
                    174:        argc -= 2;
                    175:        cut = index[k].cut;
                    176:        limb = index[k].limb;
                    177:        poles = index[k].poles;
                    178:        for(i=0;i<index[k].npar;i++) {
                    179:                if(i>=argc||option(argv[i])) {
                    180:                        fprintf(stderr,"%s needs %d params\n",index[k].name,index[k].npar);
                    181:                        exit(1);
                    182:                }
                    183:                params[i] = atof(argv[i]);
                    184:        }
                    185:        argv += i;
                    186:        argc -= i;
                    187:        while(argc>0&&option(argv[0])) {
                    188:                argc--;
                    189:                argv++;
                    190:                switch(argv[-1][1]) {
                    191:                case 'm':
                    192:                        if(file == &dfltfile) {
                    193:                                file = 0;
                    194:                                nfile = 0;
                    195:                        }
                    196:                        while(argc && !option(*argv)) {
                    197:                                file = realloc(file,(nfile+1)*sizeof(*file));
                    198:                                file[nfile].name = *argv;
                    199:                                file[nfile].color = currcolor;
                    200:                                file[nfile].style = SOLID;
                    201:                                nfile++;
                    202:                                argv++;
                    203:                                argc--;
                    204:                        }
                    205:                        break;
                    206:                case 'b':
                    207:                        bflag = 0;
                    208:                        for(nvert=0;nvert<NVERT&&argc>=2;nvert++) {
                    209:                                if(option(*argv))
                    210:                                        break;
                    211:                                v[nvert].x = atof(*argv++);
                    212:                                argc--;
                    213:                                if(option(*argv))
                    214:                                        break;
                    215:                                v[nvert].y = atof(*argv++);
                    216:                                argc--;
                    217:                        }
                    218:                        if(nvert>=NVERT)
                    219:                                error("too many clipping vertices");
                    220:                        break;
                    221:                case 'g':
                    222:                        gridcolor = currcolor;
                    223:                        for(i=0;i<3&&argc>i&&!option(argv[i]);i++)
                    224:                                grid[i] = atof(argv[i]);
                    225:                        switch(i) {
                    226:                        case 0:
                    227:                                grid[0] = grid[1] = 0.;
                    228:                                break;
                    229:                        case 1:
                    230:                                grid[1] = grid[0];
                    231:                        }
                    232:                        argc -= i;
                    233:                        argv += i;
                    234:                        break;
                    235:                case 't':
                    236:                        style = SOLID;
                    237:                        goto casetu;
                    238:                case 'u':
                    239:                        style = DOTDASH;
                    240:                casetu:
                    241:                        while(argc && !option(*argv)) {
                    242:                                track = realloc(track,(ntrack+1)*sizeof(*track));
                    243:                                track[ntrack].name = *argv;
                    244:                                track[ntrack].color = currcolor;
                    245:                                track[ntrack].style = style;
                    246:                                ntrack++;
                    247:                                argv++;
                    248:                                argc--;
                    249:                        }
                    250:                        break;
                    251:                case 'r':
                    252:                        rflag++;
                    253:                        break;
                    254:                case 's':
                    255:                        switch(argv[-1][2]) {
                    256:                        case '1':
                    257:                                s1flag++;
                    258:                                break;
                    259:                        case 0:         /* compatibility */
                    260:                        case '2':
                    261:                                s2flag++;
                    262:                        }
                    263:                        break;
                    264:                case 'o':
                    265:                        for(i=0;i<3&&i<argc&&!option(argv[i]);i++)
                    266:                                orientation[i] = atof(argv[i]);
                    267:                        oriented++;
                    268:                        argv += i;
                    269:                        argc -= i;
                    270:                        break;
                    271:                case 'l':
                    272:                        bordcolor = currcolor;
                    273:                        for(i=0;i<argc&&i<4&&!option(argv[i]);i++)
                    274:                                limits[i] = atof(argv[i]);
                    275:                        argv += i;
                    276:                        argc -= i;
                    277:                        break;
                    278:                case 'k':
                    279:                        kflag++;
                    280:                        for(i=0;i<argc&&i<4&&!option(argv[i]);i++)
                    281:                                klimits[i] = atof(argv[i]);
                    282:                        argv += i;
                    283:                        argc -= i;
                    284:                        break;
                    285:                case 'd':
                    286:                        if(argc>0&&!option(argv[0])) {
                    287:                                delta = atoi(argv[0]);
                    288:                                argv++;
                    289:                                argc--;
                    290:                        }
                    291:                        break;
                    292:                case 'w':
                    293:                        bordcolor = currcolor;
                    294:                        windowed++;
                    295:                        for(i=0;i<argc&&i<4&&!option(argv[i]);i++)
                    296:                                window[i] = atof(argv[i]);
                    297:                        argv += i;
                    298:                        argc -= i;
                    299:                        break;
                    300:                case 'c':
                    301:                        for(i=0;i<3&&argc>i&&!option(argv[i]);i++) 
                    302:                                center[i] = atof(argv[i]);
                    303:                        argc -= i;
                    304:                        argv += i;
                    305:                        break;
                    306:                case 'p':
                    307:                        for(i=0;i<3&&argc>i&&!option(argv[i]);i++)
                    308:                                position[i] = atof(argv[i]);
                    309:                        argc -= i;
                    310:                        argv += i;
                    311:                        if(i!=3||position[2]<=0) 
                    312:                                error("incomplete positioning");
                    313:                        break;
                    314:                case 'y':
                    315:                        if(argc>0&&!option(argv[0])) {
                    316:                                symbolfile = argv[0];
                    317:                                argc--;
                    318:                                argv++;
                    319:                        }
                    320:                        break;
                    321:                case 'v':
                    322:                        if(index[k].limb == 0)
                    323:                                error("-v does not apply here");
                    324:                        vflag = -1;
                    325:                        break;
                    326:                case 'x':
                    327:                        xflag = 1;
                    328:                        break;
                    329:                case 'C':
                    330:                        if(argc && !option(*argv)) {
                    331:                                currcolor = *argv;
                    332:                                argc--;
                    333:                                argv++;
                    334:                        }
                    335:                        break;
                    336:                }
                    337:        }
                    338:        if(argc>0)
                    339:                error("error in arguments");
                    340:        pathnames();
                    341:        clamp(&limits[0],-90.);
                    342:        clamp(&limits[1],90.);
                    343:        clamp(&klimits[0],-90.);
                    344:        clamp(&klimits[1],90.);
                    345:        clamp(&window[0],-90.);
                    346:        clamp(&window[1],90.);
                    347:        radbds(limits,rlimits);
                    348:        limcase = limits[2]<-180.?0:
                    349:                  limits[3]>180.?2:
                    350:                  1;
                    351:        if(
                    352:                window[0]>=window[1]||
                    353:                window[2]>=window[3]||
                    354:                window[0]>90.||
                    355:                window[1]<-90.||
                    356:                window[2]>180.||
                    357:                window[3]<-180.)
                    358:                error("unreasonable window");
                    359:        windlim();
                    360:        radbds(window,rwindow);
                    361:        upright = orientation[0]==90? 1: orientation[0]==-90? -1: 0;
                    362:        if(index[k].spheroid && !upright)
                    363:                error("can't tilt the spheroid");
                    364:        if(limits[2]>limits[3])
                    365:                limits[3] += 360;
                    366:        if(!oriented)
                    367:                orientation[2] = (limits[2]+limits[3])/2;
                    368:        orient(orientation[0],orientation[1],orientation[2]);
                    369:        projection = (*index[k].prog)(params[0],params[1]);
                    370:        if(projection == 0)
                    371:                error("unreasonable projection parameters");
                    372:        clipinit();
                    373:        grid[0] = fabs(grid[0]);
                    374:        grid[1] = fabs(grid[1]);
                    375:        if(!kflag)
                    376:                for(i=0;i<4;i++)
                    377:                        klimits[i] = limits[i];
                    378:        if(klimits[2]>klimits[3])
                    379:                klimits[3] += 360;
                    380:        lolat = limits[0];
                    381:        hilat = limits[1];
                    382:        lolon = limits[2];
                    383:        hilon = limits[3];
                    384:        if(lolon>=hilon||lolat>=hilat||lolat<-90.||hilat>90.)
                    385:                error("unreasonable limits");
                    386:        wlim = kflag? klimits: window;
                    387:        dlat = fmin(hilat-lolat,wlim[1]-wlim[0])/16;
                    388:        dlon = fmin(hilon-lolon,wlim[3]-wlim[2])/32;
                    389:        dd = fmax(dlat,dlon);
                    390:        while(grid[2]>fmin(dlat,dlon)/2)
                    391:                grid[2] /= 2;
                    392:        realcut();
                    393:        if(nvert<=0) {
                    394:                for(lat=klimits[0];lat<klimits[1]+dd-FUZZ;lat+=dd) {
                    395:                        if(lat>klimits[1])
                    396:                                lat = klimits[1];
                    397:                        for(lon=klimits[2];lon<klimits[3]+dd-FUZZ;lon+=dd) {
                    398:                                i = (kflag?posproj:normproj)
                    399:                                        (lat,lon+(lon<klimits[3]?FUZZ:-FUZZ),
                    400:                                   &x,&y);
                    401:                                if(i*vflag <= 0)
                    402:                                        continue;
                    403:                                if(x<xmin) xmin = x;
                    404:                                if(x>xmax) xmax = x;
                    405:                                if(y<ymin) ymin = y;
                    406:                                if(y>ymax) ymax = y;
                    407:                        }
                    408:                }
                    409:        } else {
                    410:                for(i=0; i<nvert; i++) {
                    411:                        x = v[i].x;
                    412:                        y = v[i].y;
                    413:                        if(x<xmin) xmin = x;
                    414:                        if(x>xmax) xmax = x;
                    415:                        if(y<ymin) ymin = y;
                    416:                        if(y>ymax) ymax = y;
                    417:                }
                    418:        }
                    419:        xrange = xmax - xmin;
                    420:        yrange = ymax - ymin;
                    421:        if(xrange<=0||yrange<=0)
                    422:                error("map seems to be empty");
                    423:        scaling = 2;    /*plotting area from -1 to 1*/
                    424:        if(position[2]!=0) {
                    425:                if(posproj(position[0]-.5,position[1],&xcent,&ycent)==0||
                    426:                   posproj(position[0]+.5,position[1],&x,&y)==0)
                    427:                        error("unreasonable position");
                    428:                scaling /= (position[2]*hypot(x-xcent,y-ycent));
                    429:                if(posproj(position[0],position[1],&xcent,&ycent)==0)
                    430:                        error("unreasonable position");
                    431:        } else {
                    432:                scaling /= (xrange>yrange?xrange:yrange);
                    433:                xcent = (xmin+xmax)/2;
                    434:                ycent = (ymin+ymax)/2;
                    435:        }
                    436:        xoff = center[0]/scaling;
                    437:        yoff = center[1]/scaling;
                    438:        crot.l = center[2]*RAD;
                    439:        sincos(&crot);
                    440:        scaling *= HALFWIDTH*0.9;
                    441:        if(symbolfile) 
                    442:                getsyms(symbolfile);
                    443:        if(!s2flag) {
                    444:                openpl();
                    445:                erase();
                    446:        }
                    447:        range(left,bottom,right,top);
                    448:        color(gridcolor);
                    449:        pen(DOTTED);
                    450:        if(grid[0]>0.)
                    451:                for(lat=ceil(lolat/grid[0])*grid[0];
                    452:                    lat<=hilat;lat+=grid[0]) 
                    453:                        dogrid(lat,lat,lolon,hilon);
                    454:        if(grid[1]>0.)
                    455:                for(lon=ceil(lolon/grid[1])*grid[1];
                    456:                    lon<=hilon;lon+=grid[1]) 
                    457:                        dogrid(lolat,hilat,lon,lon);
                    458:        color(bordcolor);
                    459:        pen(SOLID);
                    460:        if(bflag) {
                    461:                dolimb();
                    462:                dobounds(lolat,hilat,lolon,hilon,0);
                    463:                dobounds(window[0],window[1],window[2],window[3],1);
                    464:        }
                    465:        lolat = floor(limits[0]/10)*10;
                    466:        hilat = ceil(limits[1]/10)*10;
                    467:        lolon = floor(limits[2]/10)*10;
                    468:        hilon = ceil(limits[3]/10)*10;
                    469:        if(lolon>hilon)
                    470:                hilon += 360.;
                    471:        /*do tracks first so as not to lose the standard input*/
                    472:        for(i=0;i<ntrack;i++) {
                    473:                longlines = LONGLINES;
                    474:                satellite(&track[i]);
                    475:                longlines = shortlines;
                    476:        }
                    477:        for(i=0;i<nfile;i++) {
                    478:                pen(file[i].style);
                    479:                color(file[i].color);
                    480:                getdata(file[i].name);
                    481:        }
                    482:        move(right,bottom);
                    483:        if(!s1flag)
                    484:                closepl();
                    485:        return 0;
                    486: }
                    487: 
                    488: /* Out of perverseness (really to recover from a dubious,
                    489:    but documented, convention) the returns from projection
                    490:    functions (-1 unplottable, 0 wrong sheet, 1 good) are
                    491:    recoded into -1 wrong sheet, 0 unplottable, 1 good. */
                    492: 
                    493: int
                    494: fixproj(struct place *g, double *x, double *y)
                    495: {
                    496:        int i = (*projection)(g,x,y);
                    497:        return i<0? 0: i==0? -1: 1;
                    498: }
                    499: 
                    500: int
                    501: normproj(double lat, double lon, double *x, double *y)
                    502: {
                    503:        int i;
                    504:        struct place geog;
                    505:        latlon(lat,lon,&geog);
                    506: /*
                    507:        printp(&geog);
                    508: */
                    509:        normalize(&geog);
                    510:        if(!inwindow(&geog))
                    511:                return(-1);
                    512:        i = fixproj(&geog,x,y);
                    513:        if(rflag) 
                    514:                *x = -*x;
                    515: /*
                    516:        printp(&geog);
                    517:        fprintf(stderr,"%d %.3f %.3f\n",i,*x,*y);
                    518: */
                    519:        return(i);
                    520: }
                    521: 
                    522: int
                    523: posproj(double lat, double lon, double *x, double *y)
                    524: {
                    525:        int i;
                    526:        struct place geog;
                    527:        latlon(lat,lon,&geog);
                    528:        normalize(&geog);
                    529:        i = fixproj(&geog,x,y);
                    530:        if(rflag) 
                    531:                *x = -*x;
                    532:        return(i);
                    533: }
                    534: 
                    535: int
                    536: inwindow(struct place *geog)
                    537: {
                    538:        if(geog->nlat.l<rwindow[0]-FUZZ||
                    539:           geog->nlat.l>rwindow[1]+FUZZ||
                    540:           geog->wlon.l<rwindow[2]-FUZZ||
                    541:           geog->wlon.l>rwindow[3]+FUZZ)
                    542:                return(0);
                    543:        else return(1);
                    544: }
                    545: 
                    546: int
                    547: inlimits(struct place *g)
                    548: {
                    549:        if(rlimits[0]-FUZZ>g->nlat.l||
                    550:           rlimits[1]+FUZZ<g->nlat.l)
                    551:                return(0);
                    552:        switch(limcase) {
                    553:        case 0:
                    554:                if(rlimits[2]+TWOPI-FUZZ>g->wlon.l&&
                    555:                   rlimits[3]+FUZZ<g->wlon.l)
                    556:                        return(0);
                    557:                break;
                    558:        case 1:
                    559:                if(rlimits[2]-FUZZ>g->wlon.l||
                    560:                   rlimits[3]+FUZZ<g->wlon.l)
                    561:                        return(0);
                    562:                break;
                    563:        case 2:
                    564:                if(rlimits[2]>g->wlon.l&&
                    565:                   rlimits[3]-TWOPI+FUZZ<g->wlon.l)
                    566:                        return(0);
                    567:                break;
                    568:        }
                    569:        return(1);
                    570: }
                    571: 
                    572: 
                    573: long patch[18][36];
                    574: 
                    575: void
                    576: getdata(char *mapfile)
                    577: {
                    578:        char *indexfile;
                    579:        int kx,ky,c;
                    580:        int k;
                    581:        long b;
                    582:        long *p;
                    583:        int ip, jp;
                    584:        int n;
                    585:        struct place g;
                    586:        int i, j;
                    587:        double lat, lon;
                    588:        int conn;
                    589:        FILE *ifile, *xfile;
                    590: 
                    591:        indexfile = mapindex(mapfile);
                    592:        xfile = fopen(indexfile,"r");
                    593:        if(xfile==NULL)
                    594:                filerror("can't find map index", indexfile);
                    595:        free(indexfile);
                    596:        for(i=0,p=patch[0];i<18*36;i++,p++)
                    597:                *p = 1;
                    598:        while(!feof(xfile) && fscanf(xfile,"%d%d%ld",&i,&j,&b)==3)
                    599:                patch[i+9][j+18] = b;
                    600:        fclose(xfile);
                    601:        ifile = fopen(mapfile,"r");
                    602:        if(ifile==NULL)
                    603:                filerror("can't find map data", mapfile);
                    604:        for(lat=lolat;lat<hilat;lat+=10.)
                    605:                for(lon=lolon;lon<hilon;lon+=10.) {
                    606:                        if(!seeable(lat,lon))
                    607:                                continue;
                    608:                        i = pnorm(lat);
                    609:                        j = pnorm(lon);
                    610:                        if((b=patch[i+9][j+18])&1)
                    611:                                continue;
                    612:                        fseek(ifile,b,0);
                    613:                        while((ip=getc(ifile))>=0&&(jp=getc(ifile))>=0){
                    614:                                if(ip!=(i&0377)||jp!=(j&0377))
                    615:                                        break;
                    616:                                n = getshort(ifile);
                    617:                                conn = 0;
                    618:                                if(n > 0) {     /* absolute coordinates */
                    619:                                        for(k=0;k<n;k++){
                    620:                                                kx = SCALERATIO*getshort(ifile);
                    621:                                                ky = SCALERATIO*getshort(ifile);
                    622:                                                if (((k%delta) != 0) && (k != (n-1)))
                    623:                                                        continue;
                    624:                                                conv(kx,&g.nlat);
                    625:                                                conv(ky,&g.wlon);
                    626:                                                conn = plotpt(&g,conn);
                    627:                                        }
                    628:                                } else {        /* differential, scaled by SCALERATI0 */
                    629:                                        n = -n;
                    630:                                        kx = SCALERATIO*getshort(ifile);
                    631:                                        ky = SCALERATIO*getshort(ifile);
                    632:                                        for(k=0; k<n; k++) {
                    633:                                                c = getc(ifile);
                    634:                                                if(c&0200) c|= ~0177;
                    635:                                                kx += c;
                    636:                                                c = getc(ifile);
                    637:                                                if(c&0200) c|= ~0177;
                    638:                                                ky += c;
                    639:                                                if(k%delta!=0&&k!=n-1)
                    640:                                                        continue;
                    641:                                                conv(kx,&g.nlat);
                    642:                                                conv(ky,&g.wlon);
                    643:                                                conn = plotpt(&g,conn);
                    644:                                        }
                    645:                                }
                    646:                                if(k==1) {
                    647:                                        conv(kx,&g.nlat);
                    648:                                        conv(ky,&g.wlon);
                    649:                                        conn = plotpt(&g,conn);
                    650:                                }
                    651:                        }
                    652:                }
                    653:        fclose(ifile);
                    654: }
                    655: 
                    656: int
                    657: seeable(double lat0, double lon0)
                    658: {
                    659:        double x, y;
                    660:        double lat, lon;
                    661:        for(lat=lat0;lat<=lat0+10;lat+=2*grid[2])
                    662:                for(lon=lon0;lon<=lon0+10;lon+=2*grid[2])
                    663:                        if(normproj(lat,lon,&x,&y)*vflag>0)
                    664:                                return(1);
                    665:        return(0);
                    666: }
                    667: 
                    668: void
                    669: satellite(struct file *t)
                    670: {
                    671:        char sym[50];
                    672:        char lbl[50];
                    673:        double scale;
                    674:        register conn;
                    675:        double lat,lon;
                    676:        struct place place;
                    677:        static FILE *ifile = stdin;
                    678:        if(t->name[0]!='-'||t->name[1]!=0) {
                    679:                fclose(ifile);
                    680:                if((ifile=fopen(t->name,"r"))==NULL)
                    681:                        filerror("can't find track", t->name);
                    682:        }
                    683:        color(t->color);
                    684:        pen(t->style);
                    685:        for(;;) {
                    686:                conn = 0;
                    687:                while(!feof(ifile) && fscanf(ifile,"%lf%lf",&lat,&lon)==2){
                    688:                        latlon(lat,lon,&place);
                    689:                        if(fscanf(ifile,"%1s",lbl) == 1) {
                    690:                                if(strchr("+-.0123456789",*lbl)==0)
                    691:                                        break;
                    692:                                ungetc(*lbl,ifile);
                    693:                        }
                    694:                        conn = plotpt(&place,conn);
                    695:                }
                    696:                if(feof(ifile))
                    697:                        return;
                    698:                fscanf(ifile,"%[^\n]",lbl+1);
                    699:                switch(*lbl) {
                    700:                case '"':
                    701:                        if(plotpt(&place,conn))
                    702:                                text(lbl+1);
                    703:                        break;
                    704:                case ':':
                    705:                case '!':
                    706:                        if(sscanf(lbl+1,"%s %lf",sym,&scale) <= 1)
                    707:                                scale = 1;
                    708:                        if(plotpt(&place,conn?conn:-1)) {
                    709:                                int r = *lbl=='!'?0:rflag?-1:1;
                    710:                                if(putsym(&place,sym,scale,r) == 0)
                    711:                                        text(lbl);
                    712:                        }
                    713:                        break;
                    714:                default:
                    715:                        if(plotpt(&place,conn))
                    716:                                text(lbl);
                    717:                        break;
                    718:                }
                    719:        }
                    720: }
                    721: 
                    722: int
                    723: pnorm(double x)
                    724: {
                    725:        int i;
                    726:        i = x/10.;
                    727:        i %= 36;
                    728:        if(i>=18) return(i-36);
                    729:        if(i<-18) return(i+36);
                    730:        return(i);
                    731: }
                    732: 
                    733: void
                    734: error(char *s)
                    735: {
                    736:        fprintf(stderr,"map: \r\n%s\n",s);
                    737:        exit(1);
                    738: }
                    739: 
                    740: void
                    741: filerror(char *s, char *f)
                    742: {
                    743:        fprintf(stderr,"\r\n%s %s\n",s,f);
                    744:        exit(1);
                    745: }
                    746: 
                    747: char *
                    748: mapindex(char *s)
                    749: {
                    750:        char *t = malloc(strlen(s)+3);
                    751:        strcpy(t,s);
                    752:        strcat(t,".x");
                    753:        return t;
                    754: }
                    755: 
                    756: #define NOPT 32767
                    757: static ox = NOPT, oy = NOPT;
                    758: 
                    759: int
                    760: cpoint(int xi, int yi, int conn)
                    761: {
                    762:        int dx = abs(ox-xi);
                    763:        int dy = abs(oy-yi);
                    764:        if(!xflag && (xi<left||xi>=right || yi<bottom||yi>=top)) {
                    765:                ox = oy = NOPT;
                    766:                return 0;
                    767:        }
                    768:        if(conn == -1)          /* isolated plotting symbol */
                    769:                ;
                    770:        else if(!conn)
                    771:                move(xi,yi);
                    772:        else {
                    773:                if(dx+dy>longlines) {
                    774:                        ox = oy = NOPT; /* don't leap across cuts */
                    775:                        return 0;
                    776:                }
                    777:                if(dx || dy)
                    778:                        vec(xi,yi);
                    779:        }
                    780:        ox = xi, oy = yi;
                    781:        return dx+dy<=2? 2: 1;  /* 2=very near; see dogrid */
                    782: }
                    783: 
                    784: 
                    785: struct place oldg;
                    786: 
                    787: int
                    788: plotpt(struct place *g, int conn)
                    789: {
                    790:        int kx,ky;
                    791:        int ret;
                    792:        double cutlon;
                    793:        if(!inlimits(g)) {
                    794:                return(0);
                    795: }
                    796:        normalize(g);
                    797:        if(!inwindow(g)) {
                    798:                return(0);
                    799: }
                    800:        switch((*cut)(g,&oldg,&cutlon)) {
                    801:        case 2:
                    802:                if(conn) {
                    803:                        ret = duple(g,cutlon)|duple(g,cutlon);
                    804:                        oldg = *g;
                    805:                        return(ret);
                    806:                }
                    807:        case 0:
                    808:                conn = 0;
                    809:        default:        /* prevent diags about bad return value */
                    810:        case 1:
                    811:                oldg = *g;
                    812:                ret = doproj(g,&kx,&ky);
                    813:                if(ret==0 || !onlimb && ret*vflag<=0)
                    814:                        return(0);
                    815:                ret = cpoint(kx,ky,conn);
                    816:                return ret;
                    817:        }
                    818: }
                    819: 
                    820: int
                    821: doproj(struct place *g, int *kx, int *ky)
                    822: {
                    823:        int i;
                    824:        double x,y,x1,y1;
                    825: /*fprintf(stderr,"dopr1 %f %f \n",g->nlat.l,g->wlon.l);*/
                    826:        i = fixproj(g,&x,&y);
                    827:        if(i == 0)
                    828:                return(0);
                    829:        if(rflag)
                    830:                x = -x;
                    831: /*fprintf(stderr,"dopr2 %f %f\n",x,y);*/
                    832:        if(!inpoly(x,y)) {
                    833:                return 0;
                    834: }
                    835:        x1 = x - xcent;
                    836:        y1 = y - ycent;
                    837:        x = (x1*crot.c - y1*crot.s + xoff)*scaling;
                    838:        y = (x1*crot.s + y1*crot.c + yoff)*scaling;
                    839:        *kx = x + (x>0?.5:-.5);
                    840:        *ky = y + (y>0?.5:-.5);
                    841:        return(i);
                    842: }
                    843: 
                    844: int
                    845: duple(struct place *g, double cutlon)
                    846: {
                    847:        int kx,ky;
                    848:        int okx,oky;
                    849:        struct place ig;
                    850:        revlon(g,cutlon);
                    851:        revlon(&oldg,cutlon);
                    852:        ig = *g;
                    853:        invert(&ig);
                    854:        if(!inlimits(&ig))
                    855:                return(0);
                    856:        if(doproj(g,&kx,&ky)*vflag<=0 ||
                    857:           doproj(&oldg,&okx,&oky)*vflag<=0)
                    858:                return(0);
                    859:        cpoint(okx,oky,0);
                    860:        cpoint(kx,ky,1);
                    861:        return(1);
                    862: }
                    863: 
                    864: void
                    865: revlon(struct place *g, double cutlon)
                    866: {
                    867:        g->wlon.l = reduce(cutlon-reduce(g->wlon.l-cutlon));
                    868:        sincos(&g->wlon);
                    869: }
                    870: 
                    871: 
                    872: /*     recognize problems of cuts
                    873:  *     move a point across cut to side of its predecessor
                    874:  *     if its very close to the cut
                    875:  *     return(0) if cut interrupts the line
                    876:  *     return(1) if line is to be drawn normally
                    877:  *     return(2) if line is so close to cut as to
                    878:  *     be properly drawn on both sheets
                    879: */
                    880: 
                    881: int
                    882: picut(struct place *g, struct place *og, double *cutlon)
                    883: {
                    884:        *cutlon = PI;
                    885:        return(ckcut(g,og,PI));
                    886: }
                    887: 
                    888: int
                    889: nocut(struct place *g, struct place *og, double *cutlon)
                    890: {
                    891: #pragma        ref g
                    892: #pragma        ref og
                    893: #pragma        ref cutlon
                    894:        return(1);
                    895: }
                    896: 
                    897: int
                    898: ckcut(struct place *g1, struct place *g2, double lon)
                    899: {
                    900:        double d1, d2;
                    901:        double f1, f2;
                    902:        int kx,ky;
                    903:        d1 = reduce(g1->wlon.l -lon);
                    904:        d2 = reduce(g2->wlon.l -lon);
                    905:        if((f1=fabs(d1))<FUZZ)
                    906:                d1 = diddle(g1,lon,d2);
                    907:        if((f2=fabs(d2))<FUZZ) {
                    908:                d2 = diddle(g2,lon,d1);
                    909:                if(doproj(g2,&kx,&ky)*vflag>0)
                    910:                        cpoint(kx,ky,0);
                    911:        }
                    912:        if(f1<FUZZ&&f2<FUZZ)
                    913:                return(2);
                    914:        if(f1>PI*TWO_THRD||f2>PI*TWO_THRD)
                    915:                return(1);
                    916:        return(d1*d2>=0);
                    917: }
                    918: 
                    919: double
                    920: diddle(struct place *g, double lon, double d)
                    921: {
                    922:        double d1;
                    923:        d1 = FUZZ/2;
                    924:        if(d<0)
                    925:                d1 = -d1;
                    926:        g->wlon.l = reduce(lon+d1);
                    927:        sincos(&g->wlon);
                    928:        return(d1);
                    929: }
                    930: 
                    931: double
                    932: reduce(double lon)
                    933: {
                    934:        if(lon>PI)
                    935:                lon -= 2*PI;
                    936:        else if(lon<-PI)
                    937:                lon += 2*PI;
                    938:        return(lon);
                    939: }
                    940: 
                    941: 
                    942: double tetrapt = 35.26438968;  /* atan(1/sqrt(2)) */
                    943: 
                    944: void
                    945: dogrid(double lat0, double lat1, double lon0, double lon1)
                    946: {
                    947:        double slat,slon,tlat,tlon;
                    948:        register int conn, oconn;
                    949:        slat = tlat = slon = tlon = 0;
                    950:        if(lat1>lat0)
                    951:                slat = tlat = fmin(grid[2],dlat);
                    952:        else
                    953:                slon = tlon = fmin(grid[2],dlon);;
                    954:        conn = oconn = 0;
                    955:        while(lat0<=lat1&&lon0<=lon1) {
                    956:                conn = gridpt(lat0,lon0,conn);
                    957:                if(projection==Xguyou&&slat>0) {
                    958:                        if(lat0<-45&&lat0+slat>-45)
                    959:                                conn = gridpt(-45.,lon0,conn);
                    960:                        else if(lat0<45&&lat0+slat>45)
                    961:                                conn = gridpt(45.,lon0,conn);
                    962:                } else if(projection==Xtetra&&slat>0) {
                    963:                        if(lat0<-tetrapt&&lat0+slat>-tetrapt) {
                    964:                                gridpt(-tetrapt-.001,lon0,conn);
                    965:                                conn = gridpt(-tetrapt+.001,lon0,0);
                    966:                        }
                    967:                        else if(lat0<tetrapt&&lat0+slat>tetrapt) {
                    968:                                gridpt(tetrapt-.001,lon0,conn);
                    969:                                conn = gridpt(tetrapt+.001,lon0,0);
                    970:                        }
                    971:                }
                    972:                if(conn==0 && oconn!=0) {
                    973:                        if(slat+slon>.05) {
                    974:                                lat0 -= slat;   /* steps too big */
                    975:                                lon0 -= slon;   /* or near bdry */
                    976:                                slat /= 2;
                    977:                                slon /= 2;
                    978:                                conn = oconn = gridpt(lat0,lon0,conn);
                    979:                        } else
                    980:                                oconn = 0;
                    981:                } else {
                    982:                        if(conn==2) {
                    983:                                slat = tlat;
                    984:                                slon = tlon;
                    985:                                conn = 1;
                    986:                        }
                    987:                        oconn = conn;
                    988:                }
                    989:                lat0 += slat;
                    990:                lon0 += slon;
                    991:        }
                    992:        gridpt(lat1,lon1,conn);
                    993: }
                    994: 
                    995: static gridinv;                /* nonzero when doing window bounds */
                    996: 
                    997: int
                    998: gridpt(double lat, double lon, int conn)
                    999: {
                   1000:        struct place g;
                   1001: /*fprintf(stderr,"%f %f\n",lat,lon);*/
                   1002:        latlon(lat,lon,&g);
                   1003:        if(gridinv)
                   1004:                invert(&g);
                   1005:        return(plotpt(&g,conn));
                   1006: }
                   1007: 
                   1008: /* win=0 ordinary grid lines, win=1 window lines */
                   1009: 
                   1010: void
                   1011: dobounds(double lolat, double hilat, double lolon, double hilon, int win)
                   1012: {
                   1013:        gridinv = win;
                   1014:        if(lolat>-90 || win && (poles&1)!=0)
                   1015:                dogrid(lolat+FUZZ,lolat+FUZZ,lolon,hilon);
                   1016:        if(hilat<90 || win && (poles&2)!=0)
                   1017:                dogrid(hilat-FUZZ,hilat-FUZZ,lolon,hilon);
                   1018:        if(hilon-lolon<360 || win && cut==picut) {
                   1019:                dogrid(lolat,hilat,lolon+FUZZ,lolon+FUZZ);
                   1020:                dogrid(lolat,hilat,hilon-FUZZ,hilon-FUZZ);
                   1021:        }
                   1022:        gridinv = 0;
                   1023: }
                   1024: 
                   1025: static void
                   1026: dolimb(void)
                   1027: {
                   1028:        double lat, lon;
                   1029:        double res = fmin(dlat, dlon)/4;
                   1030:        int conn = 0;
                   1031:        int newconn;
                   1032:        if(limb == 0)
                   1033:                return;
                   1034:        onlimb = gridinv = 1;
                   1035:        for(;;) {
                   1036:                newconn = (*limb)(&lat, &lon, res);
                   1037:                if(newconn == -1)
                   1038:                        break;
                   1039:                conn = gridpt(lat, lon, conn*newconn);
                   1040:        }
                   1041:        onlimb = gridinv = 0;
                   1042: }
                   1043: 
                   1044: 
                   1045: void
                   1046: radbds(double *w, double *rw)
                   1047: {
                   1048:        int i;
                   1049:        for(i=0;i<4;i++)
                   1050:                rw[i] = w[i]*RAD;
                   1051:        rw[0] -= FUZZ;
                   1052:        rw[1] += FUZZ;
                   1053:        rw[2] -= FUZZ;
                   1054:        rw[3] += FUZZ;
                   1055: }
                   1056: 
                   1057: void
                   1058: windlim(void)
                   1059: {
                   1060:        double center = orientation[0];
                   1061:        double colat;
                   1062:        if(center>90)
                   1063:                center = 180 - center;
                   1064:        if(center<-90)
                   1065:                center = -180 - center;
                   1066:        if(fabs(center)>90)
                   1067:                error("unreasonable orientation");
                   1068:        colat = 90 - window[0];
                   1069:        if(center-colat>limits[0])
                   1070:                limits[0] = center - colat;
                   1071:        if(center+colat<limits[1])
                   1072:                limits[1] = center + colat;
                   1073: }
                   1074: 
                   1075: 
                   1076: short
                   1077: getshort(FILE *f)
                   1078: {
                   1079:        int c, r;
                   1080:        c = getc(f);
                   1081:        r = (c | getc(f)<<8);
                   1082:        if (r&0x8000)
                   1083:                r |= ~0xFFFF;   /* in case short > 16 bits */
                   1084:        return r;
                   1085: }
                   1086: 
                   1087: double
                   1088: fmin(double x, double y)
                   1089: {
                   1090:        return(x<y?x:y);
                   1091: }
                   1092: 
                   1093: double
                   1094: fmax(double x, double y)
                   1095: {
                   1096:        return(x>y?x:y);
                   1097: }
                   1098: 
                   1099: void
                   1100: clamp(double *px, double v)
                   1101: {
                   1102:        *px = (v<0?fmax:fmin)(*px,v);
                   1103: }
                   1104: 
                   1105: void
                   1106: pathnames(void)
                   1107: {
                   1108:        int i;
                   1109:        char *t, *indexfile, *name;
                   1110:        FILE *f, *fx;
                   1111:        for(i=0; i<nfile; i++) {
                   1112:                name = file[i].name;
                   1113:                if(*name=='/')
                   1114:                        continue;
                   1115:                indexfile = mapindex(name);
                   1116:                        /* ansi equiv of unix access() call */
                   1117:                f = fopen(name, "r");
                   1118:                fx = fopen(indexfile, "r");
                   1119:                if(f) fclose(f);
                   1120:                if(fx) fclose(fx);
                   1121:                free(indexfile);
                   1122:                if(f && fx)
                   1123:                        continue;
                   1124:                t = malloc(strlen(name)+strlen(mapdir)+2);
                   1125:                strcpy(t,mapdir);
                   1126:                strcat(t,"/");
                   1127:                strcat(t,name);
                   1128:                file[i].name = t;
                   1129:        }
                   1130: }
                   1131: 
                   1132: void
                   1133: clipinit(void)
                   1134: {
                   1135:        register i;
                   1136:        double s,t;
                   1137:        if(nvert<=0)
                   1138:                return;
                   1139:        for(i=0; i<nvert; i++) {        /*convert latlon to xy*/
                   1140:                if(normproj(v[i].x,v[i].y,&v[i].x,&v[i].y)==0)
                   1141:                        error("invisible clipping vertex");
                   1142:        }
                   1143:        if(nvert==2) {                  /*rectangle with diag specified*/
                   1144:                nvert = 4;
                   1145:                v[2] = v[1];
                   1146:                v[1].x=v[0].x, v[1].y=v[2].y, v[3].x=v[2].x, v[3].y=v[0].y;
                   1147:        }       
                   1148:        v[nvert] = v[0];
                   1149:        v[nvert+1] = v[1];
                   1150:        s = 0;
                   1151:        for(i=1; i<=nvert; i++) {       /*test for convexity*/
                   1152:                t = (v[i-1].x-v[i].x)*(v[i+1].y-v[i].y) -
                   1153:                    (v[i-1].y-v[i].y)*(v[i+1].x-v[i].x);
                   1154:                if(t<-FUZZ && s>=0) s = 1;
                   1155:                if(t>FUZZ && s<=0) s = -1;
                   1156:                if(-FUZZ<=t&&t<=FUZZ || t*s>0) {
                   1157:                        s = 0;
                   1158:                        break;
                   1159:                }
                   1160:        }
                   1161:        if(s==0)
                   1162:                error("improper clipping polygon");
                   1163:        for(i=0; i<nvert; i++) {        /*edge equation ax+by=c*/
                   1164:                e[i].a = s*(v[i+1].y - v[i].y);
                   1165:                e[i].b = s*(v[i].x - v[i+1].x);
                   1166:                e[i].c = s*(v[i].x*v[i+1].y - v[i].y*v[i+1].x);
                   1167:        }
                   1168: }
                   1169: 
                   1170: int
                   1171: inpoly(double x, double y)
                   1172: {
                   1173:        register i;
                   1174:        for(i=0; i<nvert; i++) {
                   1175:                register struct edge *ei = &e[i];
                   1176:                double val = x*ei->a + y*ei->b - ei->c;
                   1177:                if(val>10*FUZZ)
                   1178:                        return(0);
                   1179:        }
                   1180:        return 1;
                   1181: }
                   1182: 
                   1183: void
                   1184: realcut()
                   1185: {
                   1186:        struct place g;
                   1187:        double lat;
                   1188:        
                   1189:        if(cut != picut)        /* punt on unusual cuts */
                   1190:                return;
                   1191:        for(lat=window[0]; lat<=window[1]; lat+=grid[2]) {
                   1192:                g.wlon.l = PI;
                   1193:                sincos(&g.wlon);
                   1194:                g.nlat.l = lat*RAD;
                   1195:                sincos(&g.nlat);
                   1196:                if(!inwindow(&g)) {
                   1197:                        break;
                   1198: }
                   1199:                invert(&g);
                   1200:                if(inlimits(&g)) {
                   1201:                        return;
                   1202: }
                   1203:        }
                   1204:        longlines = shortlines = LONGLINES;
                   1205:        cut = nocut;            /* not necessary; small eff. gain */
                   1206: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.