|
|
1.1 ! root 1: /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */ ! 2: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */ ! 3: /* The copyright notice does not imply actual or intended publication. */ ! 4: /* AUTHORS: */ ! 5: /* H. S. Baird - ATT-BL MH - first versions */ ! 6: /* T. J. Thompson - ATT-BL HO - improvements */ ! 7: ! 8: /* Coord.c - function bodies for basic Coordinate geometry. ! 9: See Coord.h for associated defines, typedefs, etc. ! 10: */ ! 11: ! 12: #include <stdio.h> ! 13: #include <math.h> ! 14: #include <string.h> ! 15: #define ATAN_INCL 1 ! 16: #include "CPU.h" ! 17: #include "boole.h" ! 18: #include "Units.h" ! 19: #include "Coord.h" ! 20: ! 21: /* Added by Tim Thompson ... */ ! 22: int Readvax = 0; ! 23: ! 24: VOID ! 25: setreadvax() ! 26: { ! 27: char *getenv(); ! 28: char *p = getenv("READVAX"); ! 29: /* any non-null value of READVAX will set it */ ! 30: if ( p!=NULL && strlen(p)>0 ) ! 31: Readvax = 1; ! 32: } ! 33: ! 34: /* ... */ ! 35: ! 36: /* Convert a real value, a units specification, and a resolution ! 37: into a value in scanner coordinates. */ ! 38: int vto_scoor(v,u,r) ! 39: double v; /* value in special units */ ! 40: char u; /* units: one of UNITS (see ric.h) */ ! 41: int r; /* resolution in pixels/inch */ ! 42: { int c; ! 43: switch(u) { ! 44: case 'i': /* inches */ ! 45: c = (int)(v*r + 0.5); ! 46: break; ! 47: case 'c': /* cm */ ! 48: c = (int)((v*r/2.54) + 0.5); ! 49: break; ! 50: case 'p': /* points */ ! 51: c = (int)((v*INCHES_PER_POINT*r) + 0.5); ! 52: break; ! 53: case 'P': /* picas */ ! 54: c = (int)((v*12.0*INCHES_PER_POINT*r) + 0.5); ! 55: break; ! 56: case 's': /* scanner pixel (Scoor) */ ! 57: case 'u': /* basic unit */ ! 58: c = (int)(v + 0.5); ! 59: break; ! 60: default: ! 61: c = (int)(v + 0.5); ! 62: break; ! 63: }; ! 64: return(c); ! 65: } ! 66: ! 67: /* Return pointer to empty Sp from malloc space */ ! 68: Sp *alloc_sp() ! 69: { Sp *spp; ! 70: if((spp=(Sp *)malloc(sizeof(Sp)))==NULL) ! 71: abort("alloc_sp: can't"); ! 72: *spp = zero_Sp; ! 73: return(spp); ! 74: } ! 75: ! 76: /* Free Sp from malloc space */ ! 77: free_sp(spp) ! 78: Sp *spp; ! 79: { free(spp); ! 80: } ! 81: ! 82: Sp *ato_sp(s) ! 83: char *s; ! 84: { char *d; ! 85: static Sp p; ! 86: char *p_x,*p_y; ! 87: #define SP_DELIM "(), " ! 88: d = strdup(s); ! 89: p_x = strtok(d,SP_DELIM); ! 90: p_y = strtok((char *)0,SP_DELIM); ! 91: if(p_x==NULL||p_y==NULL) ! 92: {free(d); return(NULL);}; ! 93: p.x = atoi(p_x); ! 94: p.y = atoi(p_y); ! 95: free(d); ! 96: return(&p); ! 97: } ! 98: ! 99: char *sp_toa(sp) ! 100: Sp *sp; ! 101: #define sp_toa_distinct (5) ! 102: { static char s[sp_toa_distinct][40]; ! 103: static int sp_toa_cur = -1; ! 104: sp_toa_cur = (sp_toa_cur+1)%sp_toa_distinct; ! 105: sprintf(s[sp_toa_cur],"(%d,%d)",sp->x,sp->y); ! 106: return(s[sp_toa_cur]); ! 107: } ! 108: ! 109: /* Read a list of Sp's (in ascii) from file *fp, into set *spsp */ ! 110: frda_sps(fp,spsp) ! 111: FILE *fp; ! 112: Sps *spsp; ! 113: #define MAX_SPS_LINE (80) ! 114: { Sp *spp,**bb; ! 115: long seek; ! 116: char line[MAX_SPS_LINE+1]; ! 117: *spsp = empty_Sps; ! 118: seek = ftell(fp); ! 119: /* count all points quickly, in advance */ ! 120: while(!feof(fp)) { ! 121: line[0] = '\0'; ! 122: fgets(line,MAX_SPS_LINE,fp); ! 123: if(strlen(line)>0) { ! 124: spsp->mny++; ! 125: }; ! 126: }; ! 127: if((spsp->pa=(Sp **)malloc((spsp->mny+1)*sizeof(Sp *)))==NULL) ! 128: abort("frda_sps: can't alloc spsp->pa[%d]",spsp->mny+1); ! 129: /* next, reread points */ ! 130: fseek(fp,(long)seek,0); ! 131: bb=spsp->pa; ! 132: while(!feof(fp)) { ! 133: line[0] = '\0'; ! 134: fgets(line,MAX_SPS_LINE,fp); ! 135: if(strlen(line)>0) { ! 136: *(spp = alloc_sp()) = *ato_sp(line); ! 137: *(bb++) = spp; ! 138: }; ! 139: }; ! 140: *bb = NULL; ! 141: } ! 142: ! 143: err_sps(p) ! 144: Sps *p; ! 145: { int i; ! 146: Sp **s; ! 147: fprintf(stderr,"Sps: %d points: ",p->mny); ! 148: if(p->mny>0) for(s=p->pa; (*s)!=NULL; s++) { ! 149: fprintf(stderr,"%s ",sp_toa(*s)); ! 150: }; ! 151: fprintf(stderr,"\n"); ! 152: } ! 153: ! 154: Sp *append_sp_sps(sp,sps) ! 155: Sp *sp; ! 156: Sps *sps; ! 157: { if(sps->mny>0) { ! 158: if((sps->pa=(Sp **)realloc(sps->pa,(sps->mny+2)*sizeof(Sp *)))==NULL) ! 159: abort("append_sp_sps: can't realloc sps->pa[%d]",sps->mny+2); ! 160: } ! 161: else { sps->mny=0; ! 162: if((sps->pa=(Sp **)malloc((sps->mny+2)*sizeof(Sp *)))==NULL) ! 163: abort("append_sp_sps: can't alloc sps->pa[%d]",sps->mny+2); ! 164: }; ! 165: sps->pa[sps->mny++] = sp; ! 166: sps->pa[sps->mny] = NULL; ! 167: } ! 168: ! 169: /* Return pointer to local static Sps which holds a duplicate of the ! 170: given Sps (all contents are freshly malloc'ed) */ ! 171: Sps *dup_sps(old) ! 172: Sps *old; ! 173: { static Sps new; ! 174: Sp **o,**n; ! 175: if(old->mny>0) { ! 176: new.mny = old->mny; ! 177: if((new.pa=(Sp **)malloc((new.mny+1)*sizeof(Sp *)))==NULL) ! 178: abort("dup_sps: can't alloc new.pa[%d]",new.mny+1); ! 179: for(o=old->pa,n=new.pa; *o!=NULL; o++,n++) { ! 180: *(*n = alloc_sp()) = **o; ! 181: }; ! 182: *n = NULL; ! 183: } ! 184: else new = empty_Sps; ! 185: return(&new); ! 186: } ! 187: ! 188: free_sps(p) ! 189: Sps *p; ! 190: { if(p->pa!=NULL) free(p->pa); ! 191: *p = empty_Sps; ! 192: } ! 193: ! 194: Sp *append_sp_spa(sp,spa) ! 195: Sp *sp; ! 196: Spa *spa; ! 197: { if(spa->mny>0) { ! 198: if((spa->a=(Sp *)realloc(spa->a,(spa->mny+1)*sizeof(Sp)))==NULL) ! 199: abort("append_sp_spa: can't alloc spa->a[%d]",spa->mny+1); ! 200: } ! 201: else { spa->mny=0; ! 202: if((spa->a=(Sp *)malloc((spa->mny+1)*sizeof(Sp)))==NULL) ! 203: abort("append_sp_spa: can't alloc spa->a[%d]",spa->mny+1); ! 204: }; ! 205: spa->a[spa->mny++] = *sp; ! 206: } ! 207: ! 208: err_spa(p) ! 209: Spa *p; ! 210: { int i; ! 211: Sp *sp; ! 212: fprintf(stderr,"Spa: %d points: ",p->mny); ! 213: for(i=0,sp=p->a;i<p->mny;i++,sp++) { ! 214: fprintf(stderr,"%s ",sp_toa(sp)); ! 215: }; ! 216: fprintf(stderr,"\n"); ! 217: } ! 218: ! 219: free_spa(p) ! 220: Spa *p; ! 221: { if(p->a!=NULL) free(p->a); ! 222: *p = empty_Spa; ! 223: } ! 224: ! 225: /* Rotate the Scanner point `(x,y') about origin `*orp' by angle `ang', ! 226: and return pointer to the result. This is slow, but no matter. */ ! 227: Sp *rotate_Sp(ang,orp,x,y) ! 228: double ang; ! 229: Sp *orp; ! 230: int x,y; ! 231: { static Sp res; ! 232: Sp of; ! 233: of.x = x - orp->x; of.y = y - orp->y; ! 234: res.x = (short)(((cos(ang)*of.x - sin(ang)*of.y)) + orp->x + 0.5); ! 235: res.y = (short)(((sin(ang)*of.x + cos(ang)*of.y)) + orp->y + 0.5); ! 236: return(&res); ! 237: } ! 238: ! 239: /* Horizontally shear the Scanner point `(x,y') about origin `*orp' by shear ! 240: angle `ang', and return pointer to the result. `Ang' is close to 90 degrees. ! 241: This is slow, but no matter. */ ! 242: Sp *hshear_Sp(ang,orp,x,y) ! 243: double ang; ! 244: Sp *orp; ! 245: int x,y; ! 246: { static Sp res; ! 247: Scoor of_y,tr_x; ! 248: res.x = (short)(orp->x - (y - orp->y)*tan(ang-(90.0*DtoR)) + 0.5); ! 249: res.y = orp->y; ! 250: return(&res); ! 251: } ! 252: ! 253: /* Return pointer to initialized Edge from malloc space */ ! 254: Edge *alloc_edge() ! 255: { Edge *ep; ! 256: if((ep=(Edge *)malloc(sizeof(Edge)))==NULL) ! 257: abort("alloc_edge: can't"); ! 258: *ep = empty_Edge; ! 259: return(ep); ! 260: } ! 261: ! 262: /* Free Edge from malloc space */ ! 263: free_edge(ep) ! 264: Edge *ep; ! 265: { free(ep); ! 266: } ! 267: ! 268: char *edge_toa(ep) ! 269: Edge *ep; ! 270: { static char s[40]; ! 271: strcpy(s,sp_toa(&(ep->a))); ! 272: strcat(s,"-"); ! 273: strcat(s,sp_toa(&(ep->b))); ! 274: return(s); ! 275: } ! 276: ! 277: Edge *ato_edge(s) ! 278: char *s; ! 279: { char *d; ! 280: static Edge e; ! 281: char *a_x,*a_y,*b_x,*b_y; ! 282: #define EDGE_DELIM "(),- " ! 283: d = strdup(s); ! 284: a_x = strtok(d,EDGE_DELIM); ! 285: a_y = strtok((char *)0,EDGE_DELIM); ! 286: b_x = strtok((char *)0,EDGE_DELIM); ! 287: b_y = strtok((char *)0,EDGE_DELIM); ! 288: if(a_x==NULL||a_y==NULL||b_x==NULL||b_y==NULL) ! 289: {free(d); return(NULL);}; ! 290: e.a.x = atoi(a_x); ! 291: e.a.y = atoi(a_y); ! 292: e.b.x = atoi(b_x); ! 293: e.b.y = atoi(b_y); ! 294: free(d); ! 295: return(&e); ! 296: } ! 297: ! 298: /* Return pointer to empty Bbx from malloc space */ ! 299: Bbx *alloc_bbx() ! 300: { Bbx *bxp; ! 301: if((bxp=(Bbx *)malloc(sizeof(Bbx)))==NULL) ! 302: abort("alloc_bbx: can't"); ! 303: *bxp = empty_Bbx; ! 304: return(bxp); ! 305: } ! 306: ! 307: /* Free Bbx from malloc space */ ! 308: free_bbx(bxp) ! 309: Bbx *bxp; ! 310: { free(bxp); ! 311: } ! 312: ! 313: char *bbx_toa(bxp) ! 314: Bbx *bxp; ! 315: { static char s[40]; ! 316: strcpy(s,sp_toa(&(bxp->a))); ! 317: strcat(s,sp_toa(&(bxp->b))); ! 318: return(s); ! 319: } ! 320: ! 321: Bbx *ato_bbx(s) ! 322: char *s; ! 323: { char *d; ! 324: static Bbx bx; ! 325: char *a_x,*a_y,*b_x,*b_y; ! 326: #define BBX_DELIM "(), " ! 327: d = strdup(s); ! 328: a_x = strtok(d,BBX_DELIM); ! 329: a_y = strtok((char *)0,BBX_DELIM); ! 330: b_x = strtok((char *)0,BBX_DELIM); ! 331: b_y = strtok((char *)0,BBX_DELIM); ! 332: if(a_x==NULL||a_y==NULL||b_x==NULL||b_y==NULL) ! 333: {free(d); return(NULL);}; ! 334: bx.a.x = atoi(a_x); ! 335: bx.a.y = atoi(a_y); ! 336: bx.b.x = atoi(b_x); ! 337: bx.b.y = atoi(b_y); ! 338: free(d); ! 339: return(&bx); ! 340: } ! 341: ! 342: Bbx *expand_bbx(bxp,X) ! 343: Bbx *bxp; ! 344: int X; /* expansion code */ ! 345: { static Bbx xbx; ! 346: xbx = *bxp; ! 347: switch(X) { ! 348: case -3: ! 349: xbx.a.x += 2; ! 350: xbx.a.y += 2; ! 351: xbx.b.x -= 1; ! 352: xbx.b.y -= 1; ! 353: break; ! 354: case -2: ! 355: xbx.a.x += 1; ! 356: xbx.a.y += 1; ! 357: xbx.b.x -= 1; ! 358: xbx.b.y -= 1; ! 359: break; ! 360: case -1: ! 361: xbx.a.x += 1; ! 362: xbx.a.y += 1; ! 363: break; ! 364: case 0: ! 365: break; ! 366: case 1: ! 367: xbx.b.x += 1; ! 368: xbx.b.y += 1; ! 369: break; ! 370: case 2: ! 371: xbx.a.x -= 1; ! 372: xbx.a.y -= 1; ! 373: xbx.b.x += 1; ! 374: xbx.b.y += 1; ! 375: break; ! 376: case 3: ! 377: xbx.a.x -= 1; ! 378: xbx.a.y -= 1; ! 379: xbx.b.x += 2; ! 380: xbx.b.y += 2; ! 381: break; ! 382: default: ! 383: break; ! 384: }; ! 385: return(&xbx); ! 386: } ! 387: ! 388: /* Predicate: Is most of Bbx 1 inside Bbx 2? ``Most'' is defined ! 389: as more than half of the first Bbx's area inside BBx 2.*/ ! 390: boolean bbx_inside_most(b1,b2) ! 391: Bbx *b1,*b2; ! 392: { struct { /* overlap between blob box and selection box */ ! 393: Bbx bx; /* Bbx of intersection */ ! 394: Sp sd; /* side-lengths of overlap box, >=0 */ ! 395: long area; /* area is square pixels, >=0 */ ! 396: } ov; ! 397: if(!bbx_inside_any(b1,b2)) return(F); ! 398: else if(bbx_inside_all(b1,b2)) return(T); ! 399: else { /* compute overlap box */ ! 400: ov.bx.a.x = ((b1)->a.x>(b2)->a.x)? (b1)->a.x: (b2)->a.x; ! 401: ov.bx.a.y = ((b1)->a.y>(b2)->a.y)? (b1)->a.y: (b2)->a.y; ! 402: ov.bx.b.x = ((b1)->b.x<(b2)->b.x)? (b1)->b.x: (b2)->b.x; ! 403: ov.bx.b.y = ((b1)->b.y<(b2)->b.y)? (b1)->b.y: (b2)->b.y; ! 404: ov.sd.x = bbx_wid(&ov.bx); if(ov.sd.x<0) ov.sd.x=0; ! 405: ov.sd.y = bbx_hgt(&ov.bx); if(ov.sd.y<0) ov.sd.y=0; ! 406: ov.area = ov.sd.x*ov.sd.y; ! 407: return( (ov.area>0) && ( 2*ov.area > bbx_area(b1) ) ); ! 408: }; ! 409: } ! 410: ! 411: Bbx *translate_bbx(bxp,off) ! 412: Bbx *bxp; ! 413: Sp off; ! 414: { static Bbx res; ! 415: res.a.x = bxp->a.x + off.x; ! 416: res.a.y = bxp->a.y + off.y; ! 417: res.b.x = bxp->b.x + off.x; ! 418: res.b.y = bxp->b.y + off.y; ! 419: return(&res); ! 420: } ! 421: ! 422: /* Free Bbxs (but not the contents) */ ! 423: free_bbxs(bxsp) ! 424: Bbxs *bxsp; ! 425: { Bbx **b; ! 426: if(bxsp->mny>0) { ! 427: if(bxsp->pa!=NULL) free(bxsp->pa); ! 428: }; ! 429: *bxsp = empty_Bbxs; ! 430: } ! 431: ! 432: /* Free Bbxs (and the individually-malloc'ed contents) */ ! 433: free_bbxs_etc(bxsp) ! 434: Bbxs *bxsp; ! 435: { Bbx **b; ! 436: if(bxsp->mny>0) { ! 437: for(b=bxsp->pa; (*b)!=NULL; b++) free(*b); ! 438: if(bxsp->pa!=NULL) free(bxsp->pa); ! 439: }; ! 440: *bxsp = empty_Bbxs; ! 441: } ! 442: ! 443: /* Return pointer to local static Bbxs which holds a duplicate of the ! 444: given Bbxs (all contents are freshly malloc'ed) */ ! 445: Bbxs *dup_bbxs(old) ! 446: Bbxs *old; ! 447: { static Bbxs new; ! 448: Bbx **o,**n; ! 449: if(old->mny>0) { ! 450: new.mny = old->mny; ! 451: new.alloc = old->alloc; ! 452: new.incr = old->incr; ! 453: if((new.pa=(Bbx **)malloc((new.alloc)*sizeof(Bbx *)))==NULL) ! 454: abort("dup_bbxs: can't alloc new.pa[%d]",new.alloc); ! 455: for(o=old->pa,n=new.pa; *o!=NULL; o++,n++) { ! 456: *(*n = alloc_bbx()) = **o; ! 457: }; ! 458: *n = NULL; ! 459: } ! 460: else new = empty_Bbxs; ! 461: return(&new); ! 462: } ! 463: ! 464: Bbx *append_bbx(bxp,bxsp) ! 465: Bbx *bxp; ! 466: Bbxs *bxsp; ! 467: { if(bxsp->mny>0) { ! 468: if((bxsp->mny+2)>bxsp->alloc) { ! 469: bxsp->alloc += bxsp->incr; ! 470: if( ( bxsp->pa = ! 471: (Bbx **)realloc(bxsp->pa,bxsp->alloc*sizeof(Bbx *)) ) ! 472: ==NULL ) ! 473: abort("append_bbx: can't alloc bxsp->pa[%d]",bxsp->alloc); ! 474: }; ! 475: } ! 476: else { bxsp->mny=0; ! 477: if(bxsp->pa!=NULL) free(bxsp->pa); ! 478: bxsp->alloc=0; ! 479: while((bxsp->mny+2)>bxsp->alloc) bxsp->alloc += bxsp->incr; ! 480: if((bxsp->pa=(Bbx **)malloc(bxsp->alloc*sizeof(Bbx *)))==NULL) ! 481: abort("append_bbx: can't alloc bxsp->a[%d]",bxsp->alloc); ! 482: }; ! 483: bxsp->pa[bxsp->mny++] = bxp; ! 484: bxsp->pa[bxsp->mny] = NULL; ! 485: } ! 486: ! 487: frda_bbxs(fp,bxsp) ! 488: FILE *fp; ! 489: Bbxs *bxsp; ! 490: #define MAX_BBX_LINE (80) ! 491: { Bbx *bxp,**bb; ! 492: long seek; ! 493: char line[MAX_BBX_LINE+1]; ! 494: *bxsp = empty_Bbxs; ! 495: seek = ftell(fp); ! 496: /* count all boxes quickly, in advance */ ! 497: while(!feof(fp)) { ! 498: line[0] = '\0'; ! 499: fgets(line,MAX_BBX_LINE,fp); ! 500: if(strlen(line)>0) { ! 501: bxsp->mny++; ! 502: }; ! 503: }; ! 504: if((bxsp->pa=(Bbx **)malloc((bxsp->mny+1)*sizeof(Bbx *)))==NULL) ! 505: abort("frda_bbxs: can't alloc bxsp->pa[%d]",bxsp->mny+1); ! 506: bxsp->alloc = bxsp->mny+1; ! 507: /* next, reread boxes */ ! 508: fseek(fp,(long)seek,0); ! 509: bb=bxsp->pa; ! 510: while(!feof(fp)) { ! 511: line[0] = '\0'; ! 512: fgets(line,MAX_BBX_LINE,fp); ! 513: if(strlen(line)>0) { ! 514: *(bxp = alloc_bbx()) = *ato_bbx(line); ! 515: *(bb++) = bxp; ! 516: }; ! 517: }; ! 518: *bb = NULL; ! 519: } ! 520: ! 521: fwra_bbxs(fp,bxsp) ! 522: FILE *fp; ! 523: Bbxs *bxsp; ! 524: { Bbx **b; ! 525: if(bxsp->mny>0) for(b=bxsp->pa; *b!=NULL; b++) { ! 526: fputs(bbx_toa(*b),fp); ! 527: fputs("\n",fp); ! 528: }; ! 529: fflush(fp); ! 530: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.