00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef RECT_H
00021 #define RECT_H
00022
00023 #include <math.h>
00024 #include "points.h"
00025 #include "ndminx.h"
00026 #include "tprintf.h"
00027 #include "scrollview.h"
00028
00029 class DLLSYM TBOX {
00030 public:
00031 TBOX ():
00032 bot_left (MAX_INT16, MAX_INT16), top_right (-MAX_INT16, -MAX_INT16) {
00033 }
00034
00035 TBOX(
00036 const ICOORD pt1,
00037 const ICOORD pt2);
00038
00039 TBOX(
00040 inT16 left, inT16 bottom, inT16 right, inT16 top);
00041
00042 TBOX(
00043 const FCOORD pt);
00044
00045 bool null_box() const {
00046 return ((left () >= right ()) || (top () <= bottom ()));
00047 }
00048
00049 inT16 top() const {
00050 return top_right.y ();
00051 }
00052 void set_top(int y) {
00053 top_right.set_y(y);
00054 }
00055
00056 inT16 bottom() const {
00057 return bot_left.y ();
00058 }
00059 void set_bottom(int y) {
00060 bot_left.set_y(y);
00061 }
00062
00063 inT16 left() const {
00064 return bot_left.x ();
00065 }
00066 void set_left(int x) {
00067 bot_left.set_x(x);
00068 }
00069
00070 inT16 right() const {
00071 return top_right.x ();
00072 }
00073 void set_right(int x) {
00074 top_right.set_x(x);
00075 }
00076
00077 const ICOORD &botleft() const {
00078 return bot_left;
00079 }
00080
00081 ICOORD botright() const {
00082 return ICOORD (top_right.x (), bot_left.y ());
00083 }
00084
00085 ICOORD topleft() const {
00086 return ICOORD (bot_left.x (), top_right.y ());
00087 }
00088
00089 const ICOORD &topright() const {
00090 return top_right;
00091 }
00092
00093 inT16 height() const {
00094 if (!null_box ())
00095 return top_right.y () - bot_left.y ();
00096 else
00097 return 0;
00098 }
00099
00100 inT16 width() const {
00101 if (!null_box ())
00102 return top_right.x () - bot_left.x ();
00103 else
00104 return 0;
00105 }
00106
00107 inT32 area() const {
00108 if (!null_box ())
00109 return width () * height ();
00110 else
00111 return 0;
00112 }
00113
00114 void move_bottom_edge(
00115 const inT16 y) {
00116 bot_left += ICOORD (0, y);
00117 }
00118
00119 void move_left_edge(
00120 const inT16 x) {
00121 bot_left += ICOORD (x, 0);
00122 }
00123
00124 void move_right_edge(
00125 const inT16 x) {
00126 top_right += ICOORD (x, 0);
00127 }
00128
00129 void move_top_edge(
00130 const inT16 y) {
00131 top_right += ICOORD (0, y);
00132 }
00133
00134 void move(
00135 const ICOORD vec) {
00136 bot_left += vec;
00137 top_right += vec;
00138 }
00139
00140 void move(
00141 const FCOORD vec) {
00142 bot_left.set_x ((inT16) floor (bot_left.x () + vec.x ()));
00143
00144 bot_left.set_y ((inT16) floor (bot_left.y () + vec.y ()));
00145
00146 top_right.set_x ((inT16) ceil (top_right.x () + vec.x ()));
00147
00148 top_right.set_y ((inT16) ceil (top_right.y () + vec.y ()));
00149
00150 }
00151
00152 void scale(
00153 const float f) {
00154 bot_left.set_x ((inT16) floor (bot_left.x () * f));
00155 bot_left.set_y ((inT16) floor (bot_left.y () * f));
00156 top_right.set_x ((inT16) ceil (top_right.x () * f));
00157 top_right.set_y ((inT16) ceil (top_right.y () * f));
00158 }
00159 void scale(
00160 const FCOORD vec) {
00161 bot_left.set_x ((inT16) floor (bot_left.x () * vec.x ()));
00162 bot_left.set_y ((inT16) floor (bot_left.y () * vec.y ()));
00163 top_right.set_x ((inT16) ceil (top_right.x () * vec.x ()));
00164 top_right.set_y ((inT16) ceil (top_right.y () * vec.y ()));
00165 }
00166
00167
00168
00169
00170 void rotate(const FCOORD& vec) {
00171 bot_left.rotate (vec);
00172 top_right.rotate (vec);
00173 *this = TBOX (bot_left, top_right);
00174 }
00175
00176
00177
00178 void rotate_large(const FCOORD& vec);
00179
00180 bool contains(
00181 const FCOORD pt) const;
00182
00183 bool contains(
00184 const TBOX &box) const;
00185
00186 bool overlap(
00187 const TBOX &box) const;
00188
00189 bool major_overlap(
00190 const TBOX &box) const;
00191
00192
00193 bool x_overlap(const TBOX &box) const;
00194
00195
00196
00197 bool major_x_overlap(const TBOX &box) const;
00198
00199
00200 bool y_overlap(const TBOX &box) const;
00201
00202
00203
00204 bool major_y_overlap(const TBOX &box) const;
00205
00206
00207 double overlap_fraction(const TBOX &box) const;
00208
00209 TBOX intersection(
00210 const TBOX &box) const;
00211
00212 TBOX bounding_union(
00213 const TBOX &box) const;
00214
00215 void print() const {
00216 tprintf("Bounding box=(%d,%d)->(%d,%d)\n",
00217 left(), bottom(), right(), top());
00218 }
00219
00220 #ifndef GRAPHICS_DISABLED
00221 void plot(
00222 ScrollView* fd) const {
00223 fd->Rectangle(bot_left.x (), bot_left.y (), top_right.x (),
00224 top_right.y ());
00225 }
00226
00227 void plot(
00228 ScrollView* fd,
00229 ScrollView::Color fill_colour,
00230 ScrollView::Color border_colour) const;
00231 #endif
00232
00233 friend DLLSYM TBOX & operator+= (TBOX &, const TBOX &);
00234
00235 friend DLLSYM TBOX & operator-= (TBOX &, const TBOX &);
00236
00237
00238 void serialise_asc(
00239 FILE *f);
00240 void de_serialise_asc(
00241 FILE *f);
00242
00243 private:
00244 ICOORD bot_left;
00245 ICOORD top_right;
00246 };
00247
00248
00249
00250
00251
00252
00253 inline TBOX::TBOX(
00254 const FCOORD pt
00255 ) {
00256 bot_left = ICOORD ((inT16) floor (pt.x ()), (inT16) floor (pt.y ()));
00257 top_right = ICOORD ((inT16) ceil (pt.x ()), (inT16) ceil (pt.y ()));
00258 }
00259
00260
00261
00262
00263
00264
00265
00266 inline bool TBOX::contains(const FCOORD pt) const {
00267 return ((pt.x () >= bot_left.x ()) &&
00268 (pt.x () <= top_right.x ()) &&
00269 (pt.y () >= bot_left.y ()) && (pt.y () <= top_right.y ()));
00270 }
00271
00272
00273
00274
00275
00276
00277
00278 inline bool TBOX::contains(const TBOX &box) const {
00279 return (contains (box.bot_left) && contains (box.top_right));
00280 }
00281
00282
00283
00284
00285
00286
00287
00288 inline bool TBOX::overlap(
00289 const TBOX &box) const {
00290 return ((box.bot_left.x () <= top_right.x ()) &&
00291 (box.top_right.x () >= bot_left.x ()) &&
00292 (box.bot_left.y () <= top_right.y ()) &&
00293 (box.top_right.y () >= bot_left.y ()));
00294 }
00295
00296
00297
00298
00299
00300
00301 inline bool TBOX::major_overlap(
00302 const TBOX &box) const {
00303 int overlap = MIN(box.top_right.x(), top_right.x());
00304 overlap -= MAX(box.bot_left.x(), bot_left.x());
00305 overlap += overlap;
00306 if (overlap < MIN(box.width(), width()))
00307 return false;
00308 overlap = MIN(box.top_right.y(), top_right.y());
00309 overlap -= MAX(box.bot_left.y(), bot_left.y());
00310 overlap += overlap;
00311 if (overlap < MIN(box.height(), height()))
00312 return false;
00313 return true;
00314 }
00315
00316
00317
00318
00319
00320
00321 inline double TBOX::overlap_fraction(const TBOX &box) const {
00322 double fraction = 0.0;
00323 if (this->area()) {
00324 fraction = this->intersection(box).area() * 1.0 / this->area();
00325 }
00326 return fraction;
00327 }
00328
00329
00330
00331
00332
00333
00334 inline bool TBOX::x_overlap(const TBOX &box) const {
00335 return ((box.bot_left.x() <= top_right.x()) &&
00336 (box.top_right.x() >= bot_left.x()));
00337 }
00338
00339
00340
00341
00342
00343
00344
00345 inline bool TBOX::major_x_overlap(const TBOX &box) const {
00346 inT16 overlap = box.width();
00347 if (this->left() > box.left()) {
00348 overlap -= this->left() - box.left();
00349 }
00350 if (this->right() < box.right()) {
00351 overlap -= box.right() - this->right();
00352 }
00353 return (overlap >= box.width() / 2 || overlap >= this->width() / 2);
00354 }
00355
00356
00357
00358
00359
00360
00361 inline bool TBOX::y_overlap(const TBOX &box) const {
00362 return ((box.bot_left.y() <= top_right.y()) &&
00363 (box.top_right.y() >= bot_left.y()));
00364 }
00365
00366
00367
00368
00369
00370
00371
00372 inline bool TBOX::major_y_overlap(const TBOX &box) const {
00373 inT16 overlap = box.height();
00374 if (this->bottom() > box.bottom()) {
00375 overlap -= this->bottom() - box.bottom();
00376 }
00377 if (this->top() < box.top()) {
00378 overlap -= box.top() - this->top();
00379 }
00380 return (overlap >= box.height() / 2 || overlap >= this->height() / 2);
00381 }
00382 #endif