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