|
|
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.