tesseract  3.03
/usr/local/google/home/jbreiden/tesseract-ocr-read-only/ccstruct/rect.h
Go to the documentation of this file.
00001 /**********************************************************************
00002  * File:        rect.h  (Formerly box.h)
00003  * Description: Bounding box class definition.
00004  * Author:                                      Phil Cheatle
00005  * Created:                                     Wed Oct 16 15:18:45 BST 1991
00006  *
00007  * (C) Copyright 1991, Hewlett-Packard Ltd.
00008  ** Licensed under the Apache License, Version 2.0 (the "License");
00009  ** you may not use this file except in compliance with the License.
00010  ** You may obtain a copy of the License at
00011  ** http://www.apache.org/licenses/LICENSE-2.0
00012  ** Unless required by applicable law or agreed to in writing, software
00013  ** distributed under the License is distributed on an "AS IS" BASIS,
00014  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  ** See the License for the specific language governing permissions and
00016  ** limitations under the License.
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 "scrollview.h"
00027 #include "strngs.h"
00028 #include "tprintf.h"
00029 
00030 class DLLSYM TBOX  {  // bounding box
00031   public:
00032     TBOX ():       // empty constructor making a null box
00033     bot_left (MAX_INT16, MAX_INT16), top_right (-MAX_INT16, -MAX_INT16) {
00034     }
00035 
00036     TBOX(          // constructor
00037         const ICOORD pt1,   // one corner
00038         const ICOORD pt2);  // the other corner
00039 
00040     TBOX(                    // constructor
00041         inT16 left, inT16 bottom, inT16 right, inT16 top);
00042 
00043     TBOX(  // box around FCOORD
00044         const FCOORD pt);
00045 
00046     bool null_box() const {  // Is box null
00047       return ((left () >= right ()) || (top () <= bottom ()));
00048     }
00049 
00050     bool operator==(const TBOX& other) const {
00051       return bot_left == other.bot_left && top_right == other.top_right;
00052     }
00053 
00054     inT16 top() const {  // coord of top
00055       return top_right.y ();
00056     }
00057     void set_top(int y) {
00058       top_right.set_y(y);
00059     }
00060 
00061     inT16 bottom() const {  // coord of bottom
00062       return bot_left.y ();
00063     }
00064     void set_bottom(int y) {
00065       bot_left.set_y(y);
00066     }
00067 
00068     inT16 left() const {  // coord of left
00069       return bot_left.x ();
00070     }
00071     void set_left(int x) {
00072       bot_left.set_x(x);
00073     }
00074 
00075     inT16 right() const {  // coord of right
00076       return top_right.x ();
00077     }
00078     void set_right(int x) {
00079       top_right.set_x(x);
00080     }
00081 
00082     const ICOORD &botleft() const {  // access function
00083       return bot_left;
00084     }
00085 
00086     ICOORD botright() const {  // ~ access function
00087       return ICOORD (top_right.x (), bot_left.y ());
00088     }
00089 
00090     ICOORD topleft() const {  // ~ access function
00091       return ICOORD (bot_left.x (), top_right.y ());
00092     }
00093 
00094     const ICOORD &topright() const {  // access function
00095       return top_right;
00096     }
00097 
00098     inT16 height() const {  // how high is it?
00099       if (!null_box ())
00100         return top_right.y () - bot_left.y ();
00101       else
00102         return 0;
00103     }
00104 
00105     inT16 width() const {  // how high is it?
00106       if (!null_box ())
00107         return top_right.x () - bot_left.x ();
00108       else
00109         return 0;
00110     }
00111 
00112     inT32 area() const {  // what is the area?
00113       if (!null_box ())
00114         return width () * height ();
00115       else
00116         return 0;
00117     }
00118 
00119     // Pads the box on either side by the supplied x,y pad amounts.
00120     // NO checks for exceeding any bounds like 0 or an image size.
00121     void pad(int xpad, int ypad) {
00122       ICOORD pad(xpad, ypad);
00123       bot_left -= pad;
00124       top_right += pad;
00125     }
00126 
00127     void move_bottom_edge(                  // move one edge
00128                           const inT16 y) {  // by +/- y
00129       bot_left += ICOORD (0, y);
00130     }
00131 
00132     void move_left_edge(                  // move one edge
00133                         const inT16 x) {  // by +/- x
00134       bot_left += ICOORD (x, 0);
00135     }
00136 
00137     void move_right_edge(                  // move one edge
00138                          const inT16 x) {  // by +/- x
00139       top_right += ICOORD (x, 0);
00140     }
00141 
00142     void move_top_edge(                  // move one edge
00143                        const inT16 y) {  // by +/- y
00144       top_right += ICOORD (0, y);
00145     }
00146 
00147     void move(                     // move box
00148               const ICOORD vec) {  // by vector
00149       bot_left += vec;
00150       top_right += vec;
00151     }
00152 
00153     void move(                     // move box
00154               const FCOORD vec) {  // by float vector
00155       bot_left.set_x ((inT16) floor (bot_left.x () + vec.x ()));
00156       // round left
00157       bot_left.set_y ((inT16) floor (bot_left.y () + vec.y ()));
00158       // round down
00159       top_right.set_x ((inT16) ceil (top_right.x () + vec.x ()));
00160       // round right
00161       top_right.set_y ((inT16) ceil (top_right.y () + vec.y ()));
00162       // round up
00163     }
00164 
00165     void scale(                  // scale box
00166                const float f) {  // by multiplier
00167       bot_left.set_x ((inT16) floor (bot_left.x () * f));  // round left
00168       bot_left.set_y ((inT16) floor (bot_left.y () * f));  // round down
00169       top_right.set_x ((inT16) ceil (top_right.x () * f));  // round right
00170       top_right.set_y ((inT16) ceil (top_right.y () * f));  // round up
00171     }
00172     void scale(                     // scale box
00173                const FCOORD vec) {  // by float vector
00174       bot_left.set_x ((inT16) floor (bot_left.x () * vec.x ()));
00175       bot_left.set_y ((inT16) floor (bot_left.y () * vec.y ()));
00176       top_right.set_x ((inT16) ceil (top_right.x () * vec.x ()));
00177       top_right.set_y ((inT16) ceil (top_right.y () * vec.y ()));
00178     }
00179 
00180     // rotate doesn't enlarge the box - it just rotates the bottom-left
00181     // and top-right corners. Use rotate_large if you want to guarantee
00182     // that all content is contained within the rotated box.
00183     void rotate(const FCOORD& vec) {  // by vector
00184       bot_left.rotate (vec);
00185       top_right.rotate (vec);
00186       *this = TBOX (bot_left, top_right);
00187     }
00188     // rotate_large constructs the containing bounding box of all 4
00189     // corners after rotating them. It therefore guarantees that all
00190     // original content is contained within, but also slightly enlarges the box.
00191     void rotate_large(const FCOORD& vec);
00192 
00193     bool contains(  // is pt inside box
00194                    const FCOORD pt) const;
00195 
00196     bool contains(  // is box inside box
00197                    const TBOX &box) const;
00198 
00199     bool overlap(  // do boxes overlap
00200                   const TBOX &box) const;
00201 
00202     bool major_overlap(  // do boxes overlap more than half
00203                         const TBOX &box) const;
00204 
00205     // Do boxes overlap on x axis.
00206     bool x_overlap(const TBOX &box) const;
00207 
00208     // Return the horizontal gap between the boxes. If the boxes
00209     // overlap horizontally then the return value is negative, indicating
00210     // the amount of the overlap.
00211     int x_gap(const TBOX& box) const {
00212       return MAX(bot_left.x(), box.bot_left.x()) -
00213              MIN(top_right.x(), box.top_right.x());
00214     }
00215 
00216     // Return the vertical gap between the boxes. If the boxes
00217     // overlap vertically then the return value is negative, indicating
00218     // the amount of the overlap.
00219     int y_gap(const TBOX& box) const {
00220       return MAX(bot_left.y(), box.bot_left.y()) -
00221              MIN(top_right.y(), box.top_right.y());
00222     }
00223 
00224     // Do boxes overlap on x axis by more than
00225     // half of the width of the narrower box.
00226     bool major_x_overlap(const TBOX &box) const;
00227 
00228     // Do boxes overlap on y axis.
00229     bool y_overlap(const TBOX &box) const;
00230 
00231     // Do boxes overlap on y axis by more than
00232     // half of the height of the shorter box.
00233     bool major_y_overlap(const TBOX &box) const;
00234 
00235     // fraction of current box's area covered by other
00236     double overlap_fraction(const TBOX &box) const;
00237 
00238     // fraction of the current box's projected area covered by the other's
00239     double x_overlap_fraction(const TBOX& box) const;
00240 
00241     // fraction of the current box's projected area covered by the other's
00242     double y_overlap_fraction(const TBOX& box) const;
00243 
00244     // Returns true if the boxes are almost equal on x axis.
00245     bool x_almost_equal(const TBOX &box, int tolerance) const;
00246 
00247     // Returns true if the boxes are almost equal
00248     bool almost_equal(const TBOX &box, int tolerance) const;
00249 
00250     TBOX intersection(  // shared area box
00251                      const TBOX &box) const;
00252 
00253     TBOX bounding_union(  // box enclosing both
00254                        const TBOX &box) const;
00255 
00256     // Sets the box boundaries to the given coordinates.
00257     void set_to_given_coords(int x_min, int y_min, int x_max, int y_max) {
00258       bot_left.set_x(x_min);
00259       bot_left.set_y(y_min);
00260       top_right.set_x(x_max);
00261       top_right.set_y(y_max);
00262     }
00263 
00264     void print() const {  // print
00265       tprintf("Bounding box=(%d,%d)->(%d,%d)\n",
00266               left(), bottom(), right(), top());
00267     }
00268     // Appends the bounding box as (%d,%d)->(%d,%d) to a STRING.
00269     void print_to_str(STRING *str) const;
00270 
00271 #ifndef GRAPHICS_DISABLED
00272     void plot(                    // use current settings
00273               ScrollView* fd) const {  // where to paint
00274       fd->Rectangle(bot_left.x (), bot_left.y (), top_right.x (),
00275         top_right.y ());
00276     }
00277 
00278     void plot(                              // paint box
00279               ScrollView* fd,                    // where to paint
00280               ScrollView::Color fill_colour,           // colour for inside
00281               ScrollView::Color border_colour) const;  // colour for border
00282 #endif
00283     // Writes to the given file. Returns false in case of error.
00284     bool Serialize(FILE* fp) const;
00285     // Reads from the given file. Returns false in case of error.
00286     // If swap is true, assumes a big/little-endian swap is needed.
00287     bool DeSerialize(bool swap, FILE* fp);
00288 
00289     friend TBOX& operator+=(TBOX&, const TBOX&);
00290     // in place union
00291     friend TBOX& operator&=(TBOX&, const TBOX&);
00292     // in place intersection
00293 
00294   private:
00295     ICOORD bot_left;             // bottom left corner
00296     ICOORD top_right;            // top right corner
00297 };
00298 
00299 /**********************************************************************
00300  * TBOX::TBOX()  Constructor from 1 FCOORD
00301  *
00302  **********************************************************************/
00303 
00304 inline TBOX::TBOX(               // construtor
00305                 const FCOORD pt  // floating centre
00306                ) {
00307   bot_left = ICOORD ((inT16) floor (pt.x ()), (inT16) floor (pt.y ()));
00308   top_right = ICOORD ((inT16) ceil (pt.x ()), (inT16) ceil (pt.y ()));
00309 }
00310 
00311 
00312 /**********************************************************************
00313  * TBOX::contains()  Is point within box
00314  *
00315  **********************************************************************/
00316 
00317 inline bool TBOX::contains(const FCOORD pt) const {
00318   return ((pt.x () >= bot_left.x ()) &&
00319     (pt.x () <= top_right.x ()) &&
00320     (pt.y () >= bot_left.y ()) && (pt.y () <= top_right.y ()));
00321 }
00322 
00323 
00324 /**********************************************************************
00325  * TBOX::contains()  Is box within box
00326  *
00327  **********************************************************************/
00328 
00329 inline bool TBOX::contains(const TBOX &box) const {
00330   return (contains (box.bot_left) && contains (box.top_right));
00331 }
00332 
00333 
00334 /**********************************************************************
00335  * TBOX::overlap()  Do two boxes overlap?
00336  *
00337  **********************************************************************/
00338 
00339 inline bool TBOX::overlap(  // do boxes overlap
00340                           const TBOX &box) const {
00341   return ((box.bot_left.x () <= top_right.x ()) &&
00342     (box.top_right.x () >= bot_left.x ()) &&
00343     (box.bot_left.y () <= top_right.y ()) &&
00344     (box.top_right.y () >= bot_left.y ()));
00345 }
00346 
00347 /**********************************************************************
00348  * TBOX::major_overlap()  Do two boxes overlap by at least half of the smallest?
00349  *
00350  **********************************************************************/
00351 
00352 inline bool TBOX::major_overlap(  // Do boxes overlap more that half.
00353                                 const TBOX &box) const {
00354   int overlap = MIN(box.top_right.x(), top_right.x());
00355   overlap -= MAX(box.bot_left.x(), bot_left.x());
00356   overlap += overlap;
00357   if (overlap < MIN(box.width(), width()))
00358     return false;
00359   overlap = MIN(box.top_right.y(), top_right.y());
00360   overlap -= MAX(box.bot_left.y(), bot_left.y());
00361   overlap += overlap;
00362   if (overlap < MIN(box.height(), height()))
00363     return false;
00364   return true;
00365 }
00366 
00367 /**********************************************************************
00368  * TBOX::overlap_fraction()  Fraction of area covered by the other box
00369  *
00370  **********************************************************************/
00371 
00372 inline double TBOX::overlap_fraction(const TBOX &box) const {
00373   double fraction = 0.0;
00374   if (this->area()) {
00375     fraction = this->intersection(box).area() * 1.0 / this->area();
00376   }
00377   return fraction;
00378 }
00379 
00380 /**********************************************************************
00381  * TBOX::x_overlap()  Do two boxes overlap on x-axis
00382  *
00383  **********************************************************************/
00384 
00385 inline bool TBOX::x_overlap(const TBOX &box) const {
00386   return ((box.bot_left.x() <= top_right.x()) &&
00387     (box.top_right.x() >= bot_left.x()));
00388 }
00389 
00390 /**********************************************************************
00391  * TBOX::major_x_overlap()  Do two boxes overlap by more than half the
00392  *                          width of the narrower box on the x-axis
00393  *
00394  **********************************************************************/
00395 
00396 inline bool TBOX::major_x_overlap(const TBOX &box) const {
00397   inT16 overlap = box.width();
00398   if (this->left() > box.left()) {
00399     overlap -= this->left() - box.left();
00400   }
00401   if (this->right() < box.right()) {
00402     overlap -= box.right() - this->right();
00403   }
00404   return (overlap >= box.width() / 2 || overlap >= this->width() / 2);
00405 }
00406 
00407 /**********************************************************************
00408  * TBOX::y_overlap()  Do two boxes overlap on y-axis
00409  *
00410  **********************************************************************/
00411 
00412 inline bool TBOX::y_overlap(const TBOX &box) const {
00413   return ((box.bot_left.y() <= top_right.y()) &&
00414     (box.top_right.y() >= bot_left.y()));
00415 }
00416 
00417 /**********************************************************************
00418  * TBOX::major_y_overlap()  Do two boxes overlap by more than half the
00419  *                          height of the shorter box on the y-axis
00420  *
00421  **********************************************************************/
00422 
00423 inline bool TBOX::major_y_overlap(const TBOX &box) const {
00424   inT16 overlap = box.height();
00425   if (this->bottom() > box.bottom()) {
00426     overlap -= this->bottom() - box.bottom();
00427   }
00428   if (this->top() < box.top()) {
00429     overlap -= box.top() - this->top();
00430   }
00431   return (overlap >= box.height() / 2 || overlap >= this->height() / 2);
00432 }
00433 
00434 /**********************************************************************
00435  * TBOX::x_overlap_fraction() Calculates the horizontal overlap of the
00436  *                            given boxes as a fraction of this boxes
00437  *                            width.
00438  *
00439  **********************************************************************/
00440 
00441 inline double TBOX::x_overlap_fraction(const TBOX& other) const {
00442   int low = MAX(left(), other.left());
00443   int high = MIN(right(), other.right());
00444   int width = right() - left();
00445   if (width == 0) {
00446     int x = left();
00447     if (other.left() <= x && x <= other.right())
00448       return 1.0;
00449     else
00450       return 0.0;
00451   } else {
00452     return MAX(0, static_cast<double>(high - low) / width);
00453   }
00454 }
00455 
00456 /**********************************************************************
00457  * TBOX::y_overlap_fraction() Calculates the vertical overlap of the
00458  *                            given boxes as a fraction of this boxes
00459  *                            height.
00460  *
00461  **********************************************************************/
00462 
00463 inline double TBOX::y_overlap_fraction(const TBOX& other) const {
00464   int low = MAX(bottom(), other.bottom());
00465   int high = MIN(top(), other.top());
00466   int height = top() - bottom();
00467   if (height == 0) {
00468     int y = bottom();
00469     if (other.bottom() <= y && y <= other.top())
00470       return 1.0;
00471     else
00472       return 0.0;
00473   } else {
00474     return MAX(0, static_cast<double>(high - low) / height);
00475   }
00476 }
00477 
00478 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines