1 /*
2
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 */
19 // Rect.C Rectangle-handling routines.
20 // Rex E. Bradford (REX)
21 //
22 // This module implements a bunch of rectangle-manipulation
23 // routines. Rectangles are defined such that the upper-left
24 // point is inside the rectangle, and the lower-right point is
25 // outside.
26 //
27 // Thus, if the rect.ul.x == rect.lr.x OR rect.ul.y == rect.lr.y,
28 // the rectangle is empty.
29 //
30 // Also, a rect's width = rect.lr.x - rect.ul.x,
31 // and its height = rect.lr.y - rect.ul.y.
32 /*
33 * $Header: n:/project/lib/src/dstruct/RCS/rect.c 1.3 1994/04/05 04:04:13 dc Exp $
34 * $log$
35 */
36 #include <stdbool.h>
37 #include "rect.h"
38
39 // --------------------------------------------------------
40 //
41 // RectTestSect() tests if two rectangles intersect.
42 //
43 // pr1 = ptr to 1st rectangle
44 // pr2 = ptr to 2nd rectangle
45 //
46 // returns: TRUE if rectangles intersect, FALSE if disjoint.
47
RectTestSect(LGRect * pr1,LGRect * pr2)48 int RectTestSect(LGRect *pr1, LGRect *pr2)
49 {
50 return(RECT_TEST_SECT(pr1,pr2));
51 }
52
53 // --------------------------------------------------------
54 //
55 // RectSect() finds intersection of two rects.
56 //
57 // pr1 = ptr to 1st rectangle
58 // pr2 = ptr to 2nd rectangle
59 // prsect = ptr to rectangle, filled with intersection of the
60 // two rects (caution: if no intersection, this rect is undefined!)
61 //
62 // returns: TRUE IF rectangles intersect, FALSE if disjoint (in this
63 // case, *prsect is undefined)
64
RectSect(LGRect * pr1,LGRect * pr2,LGRect * prsect)65 int RectSect(LGRect *pr1, LGRect *pr2, LGRect *prsect)
66 {
67 if (!RECT_TEST_SECT(pr1, pr2))
68 return(false);
69
70 prsect->ul.x = pr1->ul.x > pr2->ul.x ? pr1->ul.x : pr2->ul.x;
71 prsect->lr.x = pr1->lr.x < pr2->lr.x ? pr1->lr.x : pr2->lr.x;
72 prsect->ul.y = pr1->ul.y > pr2->ul.y ? pr1->ul.y : pr2->ul.y;
73 prsect->lr.y = pr1->lr.y < pr2->lr.y ? pr1->lr.y : pr2->lr.y;
74
75 return(true);
76 }
77
78 // ---------------------------------------------------------
79 //
80 // RectUnion() finds union of two rects.
81 //
82 // pr1 = ptr to 1st rectangle
83 // pr2 = ptr to 2nd rectangle
84 // prunion = ptr to rectangle, filled with union of the two rects
85
RectUnion(LGRect * pr1,LGRect * pr2,LGRect * prunion)86 void RectUnion(LGRect *pr1, LGRect *pr2, LGRect *prunion)
87 {
88 RECT_UNION(pr1, pr2, prunion);
89 }
90
91 // ---------------------------------------------------------
92 //
93 // RectEncloses() tests whether first rect fully encloses second.
94 //
95 // pr1 = ptr to 1st rectangle
96 // pr2 = ptr to 2nd rectangle
97 //
98 // returns: TRUE if *pr1 encloses *pr2, FALSE otherwise
99
RectEncloses(LGRect * pr1,LGRect * pr2)100 int RectEncloses(LGRect *pr1, LGRect *pr2)
101 {
102 return(RECT_ENCLOSES(pr1, pr2));
103 }
104
105 // ---------------------------------------------------------
106 //
107 // RectTestPt() tests whether point is inside rect.
108 //
109 // prect = ptr to rectangle
110 // pt = point to be tested
111 //
112 // returns: TRUE if point is within rectangle, FALSE if outside
113
RectTestPt(LGRect * prect,LGPoint pt)114 int RectTestPt(LGRect *prect, LGPoint pt)
115 {
116 return(RECT_TEST_PT(prect, pt));
117 }
118
119 // ---------------------------------------------------------
120 //
121 // RectMove() moves a rectangle by a delta.
122 //
123 // pr = ptr to rectangle
124 // delta = point to move rectangle by
125
RectMove(LGRect * pr,LGPoint delta)126 void RectMove(LGRect *pr, LGPoint delta)
127 {
128 RECT_MOVE(pr, delta);
129 }
130
131 // ---------------------------------------------------------
132 //
133 // RectOffsettedRect() creates a rectangle, offsetted from another.
134 //
135 // pr = ptr to original rect
136 // delta = pt to offset by
137 // proff = rectangle to fill in with offsetted rect
138
RectOffsettedRect(LGRect * pr,LGPoint delta,LGRect * proff)139 void RectOffsettedRect(LGRect *pr, LGPoint delta, LGRect *proff)
140 {
141 RECT_OFFSETTED_RECT(pr, delta, proff);
142 }
143
144 // ---------------------------------------------------------
145 //
146 // RectClipCode() calculates 4-bit clipcode for pt vs. rect.
147 //
148 // prect = ptr to rectangle
149 // pt = point to be tested
150 //
151 // Returns: a 4-bit clipcode, bits set as follows:
152 //
153 // 000x: set to 1 if pt.x < rect.ul.x
154 // 00x0: set to 1 if pt.x >= rect.lr.x
155 // 0x00: set to 1 if pt.y < rect.ul.y
156 // x000: set to 1 if pt.y >= rect.lr.y
157 //
158 // thus set to 0 if point is inside rect, although a cheaper test can be
159 // done (via RectTestPt()).
160
RectClipCode(LGRect * prect,LGPoint pt)161 int RectClipCode(LGRect *prect, LGPoint pt)
162 {
163 short flag;
164
165 flag = 0;
166 if (pt.x < prect->ul.x)
167 flag = 1;
168 if (pt.x >= prect->lr.x)
169 flag |= 2;
170 if (pt.y < prect->ul.y)
171 flag |= 4;
172 if (pt.y >= prect->lr.y)
173 flag |= 8;
174
175 return(flag);
176 }
177
178 // ---------------------------------------------------------
MakePoint(short x,short y)179 LGPoint MakePoint(short x, short y)
180 {
181 LGPoint pt;
182
183 pt.x = x;
184 pt.y = y;
185 return (pt);
186 }
187