• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**********************************************************************
2  * File:        rect.h  (Formerly box.h)
3  * Description: Bounding box class definition.
4  * Author:					Phil Cheatle
5  * Created:					Wed Oct 16 15:18:45 BST 1991
6  *
7  * (C) Copyright 1991, Hewlett-Packard Ltd.
8  ** Licensed under the Apache License, Version 2.0 (the "License");
9  ** you may not use this file except in compliance with the License.
10  ** You may obtain a copy of the License at
11  ** http://www.apache.org/licenses/LICENSE-2.0
12  ** Unless required by applicable law or agreed to in writing, software
13  ** distributed under the License is distributed on an "AS IS" BASIS,
14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  ** See the License for the specific language governing permissions and
16  ** limitations under the License.
17  *
18  **********************************************************************/
19 
20 #ifndef           RECT_H
21 #define           RECT_H
22 
23 #include          <math.h>
24 #include          "points.h"
25 #include          "ndminx.h"
26 #include          "tprintf.h"
27 #include	"scrollview.h"
28 
29 class DLLSYM TBOX  {  // bounding box
30   public:
TBOX()31     TBOX ():       // empty constructor making a null box
32     bot_left (MAX_INT16, MAX_INT16), top_right (-MAX_INT16, -MAX_INT16) {
33     }
34 
35     TBOX(                    //constructor
36         const ICOORD pt1,   //one corner
37         const ICOORD pt2);  //the other corner
38 
39     TBOX(                    // constructor
40         inT16 left, inT16 bottom, inT16 right, inT16 top);
41 
42     TBOX(  //box around FCOORD
43         const FCOORD pt);
44 
null_box()45     bool null_box() const {  // Is box null
46       return ((left () >= right ()) || (top () <= bottom ()));
47     }
48 
top()49     inT16 top() const {  // coord of top
50       return top_right.y ();
51     }
set_top(int y)52     void set_top(int y) {
53       top_right.set_y(y);
54     }
55 
bottom()56     inT16 bottom() const {  // coord of bottom
57       return bot_left.y ();
58     }
set_bottom(int y)59     void set_bottom(int y) {
60       bot_left.set_y(y);
61     }
62 
left()63     inT16 left() const {  // coord of left
64       return bot_left.x ();
65     }
set_left(int x)66     void set_left(int x) {
67       bot_left.set_x(x);
68     }
69 
right()70     inT16 right() const {  // coord of right
71       return top_right.x ();
72     }
set_right(int x)73     void set_right(int x) {
74       top_right.set_x(x);
75     }
76 
botleft()77     const ICOORD &botleft() const {  // access function
78       return bot_left;
79     }
80 
botright()81     ICOORD botright() const {  // ~ access function
82       return ICOORD (top_right.x (), bot_left.y ());
83     }
84 
topleft()85     ICOORD topleft() const {  // ~ access function
86       return ICOORD (bot_left.x (), top_right.y ());
87     }
88 
topright()89     const ICOORD &topright() const {  // access function
90       return top_right;
91     }
92 
height()93     inT16 height() const {  //how high is it?
94       if (!null_box ())
95         return top_right.y () - bot_left.y ();
96       else
97         return 0;
98     }
99 
width()100     inT16 width() const {  //how high is it?
101       if (!null_box ())
102         return top_right.x () - bot_left.x ();
103       else
104         return 0;
105     }
106 
area()107     inT32 area() const {  //what is the area?
108       if (!null_box ())
109         return width () * height ();
110       else
111         return 0;
112     }
113 
move_bottom_edge(const inT16 y)114     void move_bottom_edge(                  // move one edge
115                           const inT16 y) {  // by +/- y
116       bot_left += ICOORD (0, y);
117     }
118 
move_left_edge(const inT16 x)119     void move_left_edge(                  // move one edge
120                         const inT16 x) {  // by +/- x
121       bot_left += ICOORD (x, 0);
122     }
123 
move_right_edge(const inT16 x)124     void move_right_edge(                  // move one edge
125                          const inT16 x) {  // by +/- x
126       top_right += ICOORD (x, 0);
127     }
128 
move_top_edge(const inT16 y)129     void move_top_edge(                  // move one edge
130                        const inT16 y) {  // by +/- y
131       top_right += ICOORD (0, y);
132     }
133 
move(const ICOORD vec)134     void move(                     // move box
135               const ICOORD vec) {  // by vector
136       bot_left += vec;
137       top_right += vec;
138     }
139 
move(const FCOORD vec)140     void move(                     // move box
141               const FCOORD vec) {  // by float vector
142       bot_left.set_x ((inT16) floor (bot_left.x () + vec.x ()));
143       //round left
144       bot_left.set_y ((inT16) floor (bot_left.y () + vec.y ()));
145       //round down
146       top_right.set_x ((inT16) ceil (top_right.x () + vec.x ()));
147       //round right
148       top_right.set_y ((inT16) ceil (top_right.y () + vec.y ()));
149       //round up
150     }
151 
scale(const float f)152     void scale(                  // scale box
153                const float f) {  // by multiplier
154       bot_left.set_x ((inT16) floor (bot_left.x () * f));  // round left
155       bot_left.set_y ((inT16) floor (bot_left.y () * f));  // round down
156       top_right.set_x ((inT16) ceil (top_right.x () * f));  // round right
157       top_right.set_y ((inT16) ceil (top_right.y () * f));  // round up
158     }
scale(const FCOORD vec)159     void scale(                     // scale box
160                const FCOORD vec) {  // by float vector
161       bot_left.set_x ((inT16) floor (bot_left.x () * vec.x ()));
162       bot_left.set_y ((inT16) floor (bot_left.y () * vec.y ()));
163       top_right.set_x ((inT16) ceil (top_right.x () * vec.x ()));
164       top_right.set_y ((inT16) ceil (top_right.y () * vec.y ()));
165     }
166 
167     // rotate doesn't enlarge the box - it just rotates the bottom-left
168     // and top-right corners. Use rotate_large if you want to guarantee
169     // that all content is contained within the rotated box.
rotate(const FCOORD & vec)170     void rotate(const FCOORD& vec) {  // by vector
171       bot_left.rotate (vec);
172       top_right.rotate (vec);
173       *this = TBOX (bot_left, top_right);
174     }
175     // rotate_large constructs the containing bounding box of all 4
176     // corners after rotating them. It therefore guarantees that all
177     // original content is contained within, but also slightly enlarges the box.
178     void rotate_large(const FCOORD& vec);
179 
180     bool contains(  // is pt inside box
181                    const FCOORD pt) const;
182 
183     bool contains(  // is box inside box
184                    const TBOX &box) const;
185 
186     bool overlap(  // do boxes overlap
187                   const TBOX &box) const;
188 
189     bool major_overlap(  // do boxes overlap more than half
190                    const TBOX &box) const;
191 
192     // Do boxes overlap on x axis.
193     bool x_overlap(const TBOX &box) const;
194 
195     // Do boxes overlap on x axis by more than
196     // half of the width of the narrower box.
197     bool major_x_overlap(const TBOX &box) const;
198 
199     // Do boxes overlap on y axis.
200     bool y_overlap(const TBOX &box) const;
201 
202     // Do boxes overlap on y axis by more than
203     // half of the height of the shorter box.
204     bool major_y_overlap(const TBOX &box) const;
205 
206     // fraction of current box's area covered by other
207     double overlap_fraction(const TBOX &box) const;
208 
209     TBOX intersection(  //shared area box
210                      const TBOX &box) const;
211 
212     TBOX bounding_union(  //box enclosing both
213                        const TBOX &box) const;
214 
print()215     void print() const {  // print
216       tprintf ("Bounding box=(%d,%d)->(%d,%d)\n",
217         left (), bottom (), right (), top ());
218     }
219 
220 #ifndef GRAPHICS_DISABLED
plot(ScrollView * fd)221     void plot(                    //use current settings
222               ScrollView* fd) const {  //where to paint
223       fd->Rectangle(bot_left.x (), bot_left.y (), top_right.x (),
224         top_right.y ());
225     }
226 
227     void plot(                              //paint box
228               ScrollView* fd,                    //where to paint
229               ScrollView::Color fill_colour,           //colour for inside
230               ScrollView::Color border_colour) const;  //colour for border
231 #endif
232 
233     friend DLLSYM TBOX & operator+= (TBOX &, const TBOX &);
234     //in place union
235     friend DLLSYM TBOX & operator-= (TBOX &, const TBOX &);
236     //in place intrsection
237 
238     void serialise_asc(  //convert to ascii
239                        FILE *f);
240     void de_serialise_asc(  //convert from ascii
241                           FILE *f);
242 
243   private:
244     ICOORD bot_left;             //bottom left corner
245     ICOORD top_right;            //top right corner
246 };
247 
248 /**********************************************************************
249  * TBOX::TBOX()  Constructor from 1 FCOORD
250  *
251  **********************************************************************/
252 
TBOX(const FCOORD pt)253 inline TBOX::TBOX(                 //construtor
254                 const FCOORD pt  //floating centre
255                ) {
256   bot_left = ICOORD ((inT16) floor (pt.x ()), (inT16) floor (pt.y ()));
257   top_right = ICOORD ((inT16) ceil (pt.x ()), (inT16) ceil (pt.y ()));
258 }
259 
260 
261 /**********************************************************************
262  * TBOX::contains()  Is point within box
263  *
264  **********************************************************************/
265 
contains(const FCOORD pt)266 inline bool TBOX::contains(const FCOORD pt) const {
267   return ((pt.x () >= bot_left.x ()) &&
268     (pt.x () <= top_right.x ()) &&
269     (pt.y () >= bot_left.y ()) && (pt.y () <= top_right.y ()));
270 }
271 
272 
273 /**********************************************************************
274  * TBOX::contains()  Is box within box
275  *
276  **********************************************************************/
277 
contains(const TBOX & box)278 inline bool TBOX::contains(const TBOX &box) const {
279   return (contains (box.bot_left) && contains (box.top_right));
280 }
281 
282 
283 /**********************************************************************
284  * TBOX::overlap()  Do two boxes overlap?
285  *
286  **********************************************************************/
287 
overlap(const TBOX & box)288 inline bool TBOX::overlap(  // do boxes overlap
289                           const TBOX &box) const {
290   return ((box.bot_left.x () <= top_right.x ()) &&
291     (box.top_right.x () >= bot_left.x ()) &&
292     (box.bot_left.y () <= top_right.y ()) &&
293     (box.top_right.y () >= bot_left.y ()));
294 }
295 
296 /**********************************************************************
297  * TBOX::major_overlap()  Do two boxes overlap by at least half of the smallest?
298  *
299  **********************************************************************/
300 
major_overlap(const TBOX & box)301 inline bool TBOX::major_overlap(  // Do boxes overlap more that half.
302                                 const TBOX &box) const {
303   int overlap = MIN(box.top_right.x(), top_right.x());
304   overlap -= MAX(box.bot_left.x(), bot_left.x());
305   overlap += overlap;
306   if (overlap < MIN(box.width(), width()))
307     return false;
308   overlap = MIN(box.top_right.y(), top_right.y());
309   overlap -= MAX(box.bot_left.y(), bot_left.y());
310   overlap += overlap;
311   if (overlap < MIN(box.height(), height()))
312     return false;
313   return true;
314 }
315 
316 /**********************************************************************
317  * TBOX::overlap_fraction()  Fraction of area covered by the other box
318  *
319  **********************************************************************/
320 
overlap_fraction(const TBOX & box)321 inline double TBOX::overlap_fraction(const TBOX &box) const {
322   double fraction = 0.0;
323   if (this->area()) {
324     fraction = this->intersection(box).area() * 1.0 / this->area();
325   }
326   return fraction;
327 }
328 
329 /**********************************************************************
330  * TBOX::x_overlap()  Do two boxes overlap on x-axis
331  *
332  **********************************************************************/
333 
x_overlap(const TBOX & box)334 inline bool TBOX::x_overlap(const TBOX &box) const {
335   return ((box.bot_left.x() <= top_right.x()) &&
336     (box.top_right.x() >= bot_left.x()));
337 }
338 
339 /**********************************************************************
340  * TBOX::major_x_overlap()  Do two boxes overlap by more than half the
341  *                          width of the narrower box on the x-axis
342  *
343  **********************************************************************/
344 
major_x_overlap(const TBOX & box)345 inline bool TBOX::major_x_overlap(const TBOX &box) const {
346   inT16 overlap = box.width();
347   if (this->left() > box.left()) {
348     overlap -= this->left() - box.left();
349   }
350   if (this->right() < box.right()) {
351     overlap -= box.right() - this->right();
352   }
353   return (overlap >= box.width() / 2 || overlap >= this->width() / 2);
354 }
355 
356 /**********************************************************************
357  * TBOX::y_overlap()  Do two boxes overlap on y-axis
358  *
359  **********************************************************************/
360 
y_overlap(const TBOX & box)361 inline bool TBOX::y_overlap(const TBOX &box) const {
362   return ((box.bot_left.y() <= top_right.y()) &&
363     (box.top_right.y() >= bot_left.y()));
364 }
365 
366 /**********************************************************************
367  * TBOX::major_y_overlap()  Do two boxes overlap by more than half the
368  *                          height of the shorter box on the y-axis
369  *
370  **********************************************************************/
371 
major_y_overlap(const TBOX & box)372 inline bool TBOX::major_y_overlap(const TBOX &box) const {
373   inT16 overlap = box.height();
374   if (this->bottom() > box.bottom()) {
375     overlap -= this->bottom() - box.bottom();
376   }
377   if (this->top() < box.top()) {
378     overlap -= box.top() - this->top();
379   }
380   return (overlap >= box.height() / 2 || overlap >= this->height() / 2);
381 }
382 #endif
383