|
|
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: /* Coord.h - defines, typedefs, Inits, empties, and function declarations
7: for basic Coordinate geometry data items.
8: See Coord.c for associated functions.
9: */
10:
11: /* Round signed floating-pt no. F:
12: (a) ROUND - to nearest integer;
13: (b) ROUND_UP - up to next int;
14: (c) ROUND_DN - down to prior int.
15: Evaluates the argument exactly once. */
16: static double _round,_round_up,_round_dn;
17: #define ROUND(F) ((int)(((_round=(F))>=0.0)? _round+0.5: _round-0.5))
18: #define ROUND_UP(F) ((int)(((_round_up=(F))>=0.0)? _round_up+0.999999: _round_up))
19: #define ROUND_DN(F) ((int)(((_round_dn=(F))>=0.0)? _round_dn: _round_dn-0.999999))
20:
21: /* The basic unit is the scanner pixel, located in the X,Y plane. As in many
22: graphics coordinate systems, X increases left-to-right, while Y increases
23: top-down. Pixel coordinates are usually integer values. The physical extent
24: of integer coordinate `x' along the real X-axis is the half-open interval
25: [x,x+1), and similarly for Y. The actual digitizing resolution (e.g.
26: pixels/inch) represented can vary from document to document, and is almost
27: always known to the algorithms. X & Y resolution can be different, though
28: for simplicity of discussion we will usually assume that they are equal,
29: i.e. that pixels are square. Thus pixel (x,y) may be thought of as the region
30: [x,x+1)X[y,y+1) in the real plane.
31: Half-pixel resolution is also supported, with its own data types for
32: clarity. However, to avoid distracting struggles with the type system, they
33: are for the most part #defined to be identical to ordinary coordinates. The
34: principle effect is that the limits of scanner coordinates have been halved
35: to allow for safe use of half-pixels everywhere. (This still permits images
36: 80 inches square at 400 pixels/inch, assuming `short' is at least 16-bit 2's
37: complement.)
38: Half-pixel coordinates can also be used to describe boundaries of regions,
39: as a set of ideal point locations at the corners and edge midpoints of pixels.
40: The half-pixel data type is used; boundary points are identified by flags
41: in the Bdy "boundary" structure, and may be displayed differently. */
42:
43: #define Scoor short /* Scanner pixel coordinate value */
44: #define Hcoor Scoor /* Half-pixel coordinate value */
45: #define Bcoor Hcoor /* Half-pixel boundary coordinate value */
46:
47: /* Each Scoor value `v' is associated of course with two Hcoor values `a' < `b'.
48: Conventionally, the physical extent of the `a' half-coordinate is the real
49: interval [v,v+0.5), and `b' is [v+0.5,v+1). */
50: #define StoHa(S) ((S)*2)
51: #define StoHb(S) ((S)*2+1)
52: #define HtoS(H) ((H)/2)
53:
54: /* The 3 half-pixel boundary points of a pixel coordinate `C' are: */
55: #define StoBa(S) (StoHa((S))) /* minimum of interval */
56: #define StoBb(S) (StoHb((S))) /* midpoint of interval */
57: #define StoBc(S) (StoHa((S)+1)) /* maximum of interval */
58:
59: #define Scoor_MIN (SHRT_MIN/2) /* minimum possible value */
60: #define Scoor_MAX (SHRT_MAX/2) /* maximum possible value */
61:
62: #define Hcoor_MIN (SHRT_MIN) /* minimum possible value */
63: #define Hcoor_MAX (SHRT_MAX) /* maximum possible value */
64:
65: #define fwri_Scoor(F,V) fwri_int2((F),(V))
66: #define frdi_Scoor(F) frdi_int2(F)
67:
68: #define fwri_Hcoor(F,V) fwri_int2((F),(V))
69: #define frdi_Hcoor(F) frdi_int2(F)
70:
71: #define fwri_Bcoor(F,V) fwri_int2((F),(V))
72: #define frdi_Bcoor(F) frdi_int2(F)
73:
74: typedef struct Sp { /* point: pixel address */
75: Scoor x; /* increases left-to-right: Scoor_MIN is left of image */
76: Scoor y; /* increases down: Scoor_MIN is top of image */
77: } Sp;
78: #define Hp Sp /* Half-pixel point */
79:
80: #define Init_Zero_Sp {0,0}
81: #define Init_Min_Sp {Scoor_MIN,Scoor_MIN}
82: #define Init_Max_Sp {Scoor_MAX,Scoor_MAX}
83:
84: #if MAIN
85: Sp zero_Sp = Init_Zero_Sp;
86: #else
87: extern Sp zero_Sp;
88: #endif
89:
90: #define fwri_Sp(F,P) { fwri_Scoor((F),(P)->x); fwri_Scoor((F),(P)->y); }
91: #define frdi_Sp(F,P) (feof(F)? 0: ( \
92: (P)->x=frdi_Scoor(F), \
93: (P)->y=frdi_Scoor(F), \
94: (ferror(F)? -errno: 1) ) )
95:
96: /* Is Sp *p1 exactly equal to Sp *p2? */
97: #define sp_eq(p1,p2) ( \
98: ((p1)->x == (p2)->x) \
99: && ((p1)->y == (p2)->y) \
100: )
101:
102: typedef struct Sps { /* Set of Points */
103: int mny; /* no. points (mny==0 ==> pa==NULL) */
104: Sp **pa; /* NULL-terminated Sp *pa[mny+1] (malloc space)*/
105: } Sps;
106:
107: #define Init_Sps {0,NULL}
108: #if MAIN
109: Sps empty_Sps = Init_Sps;
110: #else
111: extern Sps empty_Sps;
112: #endif
113:
114: typedef struct Spa { /* array of Points */
115: int mny; /* no. points in array */
116: Sp *a; /* Sp a[mny] (malloc space)*/
117: } Spa;
118: /** #define Pointa Spa **/ /* OBSOLESCENT */
119:
120: #define Init_Spa {0,NULL}
121: #if MAIN
122: Spa empty_Spa = Init_Spa;
123: #else
124: extern Spa empty_Spa;
125: #endif
126:
127: /* An edge is an ordered pair of vertices. */
128: typedef struct Edge {
129: Sp a,b; /* endpoints */
130: } Edge;
131:
132: #define Init_Edge {Init_Zero_Sp,Init_Zero_Sp}
133: #if MAIN
134: Edge empty_Edge = Init_Edge;
135: #else
136: extern Edge empty_Edge;
137: #endif
138:
139: #define fwri_Edge(F,P) { fwri_Sp((F),&((P)->a)); fwri_Sp((F),&((P)->b)); }
140: #define frdi_Edge(F,P) ( feof(F)? 0: ( \
141: frdi_Sp(F,&((P)->a)), \
142: frdi_Sp(F,&((P)->b)), \
143: (ferror(F)? -errno: 1) ) )
144:
145: /* A bounding box is a rectangle */
146: typedef struct { /* bounding box: inclusive of boundary values */
147: Sp a; /* top-left corner */
148: Sp b; /* bottom-right corner */
149: } Bbx;
150:
151: typedef struct DSp { /* point: pixel address */
152: double x; /* increases down the page, MinScoor at top */
153: double y; /* increases across the page, MinScoor at left */
154: } DSp;
155:
156: #define Init_Bbx {Init_Max_Sp,Init_Min_Sp}
157: #define Init_Max_Bbx {Init_Min_Sp,Init_Max_Sp}
158: #if MAIN
159: Bbx empty_Bbx = Init_Bbx;
160: Bbx max_Bbx = Init_Max_Bbx;
161: #else
162: extern Bbx empty_Bbx;
163: extern Bbx max_Bbx;
164: #endif
165:
166: #define fwri_Bbx(F,P) { fwri_Sp((F),&((P)->a)); fwri_Sp((F),&((P)->b)); }
167: #define frdi_Bbx(F,P) ( feof(F)? 0: ( \
168: frdi_Sp(F,&((P)->a)), \
169: frdi_Sp(F,&((P)->b)), \
170: (ferror(F)? -errno: 1) ) )
171:
172: /* OBSOLESCENT: */
173: #if MAIN
174: Bbx null_Bbx = {Init_Max_Sp,Init_Min_Sp};
175: #else
176: extern Bbx null_Bbx;
177: #endif
178:
179: /* height, width, area of Bbx in pixels */
180: #define bbx_hgt(bxp) ((bxp)->b.y-(bxp)->a.y+1)
181: #define bbx_wid(bxp) ((bxp)->b.x-(bxp)->a.x+1)
182: #define bbx_area(bxp) (bbx_hgt((bxp))*bbx_wid((bxp)))
183:
184: /* Is Bbx *b1 exactly equal to Bbx *b2? */
185: #define bbx_eq(b1,b2) ( \
186: ((b1)->a.x == (b2)->a.x) \
187: && ((b1)->a.y == (b2)->a.y) \
188: && ((b1)->b.x == (b2)->b.x) \
189: && ((b1)->b.y == (b2)->b.y) \
190: )
191:
192: /* Is Bbx *b1 wholly inside Bbx *b2? */
193: #define bbx_inside_all(b1,b2) ( \
194: ((b1)->a.x >= (b2)->a.x) \
195: && ((b1)->a.y >= (b2)->a.y) \
196: && ((b1)->b.x <= (b2)->b.x) \
197: && ((b1)->b.y <= (b2)->b.y) \
198: )
199:
200: /* Is any of Bbx *b1 inside Bbx *b2? */
201: #define bbx_inside_any(b1,b2) ( \
202: ((b1)->a.x <= (b2)->b.x) \
203: && ((b1)->a.y <= (b2)->b.y) \
204: && ((b1)->b.x >= (b2)->a.x) \
205: && ((b1)->b.y >= (b2)->a.y) \
206: )
207:
208: typedef struct Bbxs { /* A set of Bbxs */
209: int mny; /* if mny==0, then pa==NULL */
210: Bbx **pa; /* NULL-terminated array (in malloc space) of `mny+1'
211: pointers to Bbxs (in malloc space) */
212: int alloc; /* no. slots in pa[] actually allocated (>=mny+1) */
213: int incr; /* no. slots in pa[] to reallocate at a time */
214: } Bbxs;
215:
216: #define Init_Bbxs {0,NULL,0,512}
217: #if MAIN
218: Bbxs empty_Bbxs = Init_Bbxs;
219: #else
220: extern Bbxs empty_Bbxs;
221: #endif
222:
223: Sp *alloc_sp();
224: free_sp();
225: char *sp_toa(); /* Sp to ascii printable string */
226: Sp *ato_sp(); /* Sp from ascii printable string */
227: frda_sps();
228: Sps *dup_sps();
229: Sp *append_sp_sps();
230: Sp *append_sp_spa();
231: Sp *rotate_Sp(); /* rotate Sp about given fixed-point */
232: Sp *hshear_Sp(); /* horiz-shear Sp about given fixed-point */
233: Edge *alloc_edge();
234: free_edge();
235: char *edge_toa(); /* Edge to ascii printable string */
236: Edge *ato_edge(); /* Edge from ascii printable string */
237: Bbx *alloc_bbx();
238: Bbx *append_bbx();
239: Bbxs *dup_bbxs();
240: char *bbx_toa(); /* Bbx to ascii printable string */
241: Bbx *ato_bbx(); /* Bbx from ascii printable string */
242: Bbx *translate_bbx();
243: boolean bbx_inside_most(); /* Is Bbx 1 mostly inside Bbx 2? */
244: Bbx *expand_bbx();
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.