Tesseract  3.02
tesseract-ocr/ccstruct/rect.cpp
Go to the documentation of this file.
00001 /**********************************************************************
00002  * File:        rect.c  (Formerly box.c)
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 #include          "mfcpch.h"     // precompiled headers
00021 #include          "rect.h"
00022 
00023 // Include automatically generated configuration file if running autoconf.
00024 #ifdef HAVE_CONFIG_H
00025 #include "config_auto.h"
00026 #endif
00027 
00028 /**********************************************************************
00029  * TBOX::TBOX()  Constructor from 2 ICOORDS
00030  *
00031  **********************************************************************/
00032 
00033 TBOX::TBOX(                   //construtor
00034          const ICOORD pt1,  //one corner
00035          const ICOORD pt2   //the other corner
00036         ) {
00037   if (pt1.x () <= pt2.x ()) {
00038     if (pt1.y () <= pt2.y ()) {
00039       bot_left = pt1;
00040       top_right = pt2;
00041     }
00042     else {
00043       bot_left = ICOORD (pt1.x (), pt2.y ());
00044       top_right = ICOORD (pt2.x (), pt1.y ());
00045     }
00046   }
00047   else {
00048     if (pt1.y () <= pt2.y ()) {
00049       bot_left = ICOORD (pt2.x (), pt1.y ());
00050       top_right = ICOORD (pt1.x (), pt2.y ());
00051     }
00052     else {
00053       bot_left = pt2;
00054       top_right = pt1;
00055     }
00056   }
00057 }
00058 
00059 /**********************************************************************
00060  * TBOX::TBOX()  Constructor from 4 integer values.
00061  *  Note: It is caller's responsibility to provide values in the right
00062  *        order.
00063  **********************************************************************/
00064 
00065 TBOX::TBOX(                    //constructor
00066     inT16 left, inT16 bottom, inT16 right, inT16 top)
00067     : bot_left(left, bottom), top_right(right, top) {
00068 }
00069 
00070 // rotate_large constructs the containing bounding box of all 4
00071 // corners after rotating them. It therefore guarantees that all
00072 // original content is contained within, but also slightly enlarges the box.
00073 void TBOX::rotate_large(const FCOORD& vec) {
00074   ICOORD top_left(bot_left.x(), top_right.y());
00075   ICOORD bottom_right(top_right.x(), bot_left.y());
00076   top_left.rotate(vec);
00077   bottom_right.rotate(vec);
00078   rotate(vec);
00079   TBOX box2(top_left, bottom_right);
00080   *this += box2;
00081 }
00082 
00083 /**********************************************************************
00084  * TBOX::intersection()  Build the largest box contained in both boxes
00085  *
00086  **********************************************************************/
00087 
00088 TBOX TBOX::intersection(  //shared area box
00089                       const TBOX &box) const {
00090   inT16 left;
00091   inT16 bottom;
00092   inT16 right;
00093   inT16 top;
00094   if (overlap (box)) {
00095     if (box.bot_left.x () > bot_left.x ())
00096       left = box.bot_left.x ();
00097     else
00098       left = bot_left.x ();
00099 
00100     if (box.top_right.x () < top_right.x ())
00101       right = box.top_right.x ();
00102     else
00103       right = top_right.x ();
00104 
00105     if (box.bot_left.y () > bot_left.y ())
00106       bottom = box.bot_left.y ();
00107     else
00108       bottom = bot_left.y ();
00109 
00110     if (box.top_right.y () < top_right.y ())
00111       top = box.top_right.y ();
00112     else
00113       top = top_right.y ();
00114   }
00115   else {
00116     left = MAX_INT16;
00117     bottom = MAX_INT16;
00118     top = -MAX_INT16;
00119     right = -MAX_INT16;
00120   }
00121   return TBOX (left, bottom, right, top);
00122 }
00123 
00124 
00125 /**********************************************************************
00126  * TBOX::bounding_union()  Build the smallest box containing both boxes
00127  *
00128  **********************************************************************/
00129 
00130 TBOX TBOX::bounding_union(  //box enclosing both
00131                         const TBOX &box) const {
00132   ICOORD bl;                     //bottom left
00133   ICOORD tr;                     //top right
00134 
00135   if (box.bot_left.x () < bot_left.x ())
00136     bl.set_x (box.bot_left.x ());
00137   else
00138     bl.set_x (bot_left.x ());
00139 
00140   if (box.top_right.x () > top_right.x ())
00141     tr.set_x (box.top_right.x ());
00142   else
00143     tr.set_x (top_right.x ());
00144 
00145   if (box.bot_left.y () < bot_left.y ())
00146     bl.set_y (box.bot_left.y ());
00147   else
00148     bl.set_y (bot_left.y ());
00149 
00150   if (box.top_right.y () > top_right.y ())
00151     tr.set_y (box.top_right.y ());
00152   else
00153     tr.set_y (top_right.y ());
00154   return TBOX (bl, tr);
00155 }
00156 
00157 
00158 /**********************************************************************
00159  * TBOX::plot()  Paint a box using specified settings
00160  *
00161  **********************************************************************/
00162 
00163 #ifndef GRAPHICS_DISABLED
00164 void TBOX::plot(                      //paint box
00165                ScrollView* fd,       //where to paint
00166                ScrollView::Color fill_colour,   //colour for inside
00167                ScrollView::Color border_colour  //colour for border
00168               ) const {
00169   fd->Brush(fill_colour);
00170   fd->Pen(border_colour);
00171   plot(fd);
00172 }
00173 #endif
00174 
00175 // Writes to the given file. Returns false in case of error.
00176 bool TBOX::Serialize(FILE* fp) const {
00177   if (!bot_left.Serialize(fp)) return false;
00178   if (!top_right.Serialize(fp)) return false;
00179   return true;
00180 }
00181 // Reads from the given file. Returns false in case of error.
00182 // If swap is true, assumes a big/little-endian swap is needed.
00183 bool TBOX::DeSerialize(bool swap, FILE* fp) {
00184   if (!bot_left.DeSerialize(swap, fp)) return false;
00185   if (!top_right.DeSerialize(swap, fp)) return false;
00186   return true;
00187 }
00188 
00189 /**********************************************************************
00190  * operator+=
00191  *
00192  * Extend one box to include the other  (In place union)
00193  **********************************************************************/
00194 
00195 DLLSYM TBOX &
00196 operator+= (                     //bounding bounding bx
00197 TBOX & op1,                       //operands
00198 const TBOX & op2) {
00199   if (op2.bot_left.x () < op1.bot_left.x ())
00200     op1.bot_left.set_x (op2.bot_left.x ());
00201 
00202   if (op2.top_right.x () > op1.top_right.x ())
00203     op1.top_right.set_x (op2.top_right.x ());
00204 
00205   if (op2.bot_left.y () < op1.bot_left.y ())
00206     op1.bot_left.set_y (op2.bot_left.y ());
00207 
00208   if (op2.top_right.y () > op1.top_right.y ())
00209     op1.top_right.set_y (op2.top_right.y ());
00210 
00211   return op1;
00212 }
00213 
00214 
00215 /**********************************************************************
00216  * operator&=
00217  *
00218  * Reduce one box to intersection with the other  (In place intersection)
00219  **********************************************************************/
00220 
00221 TBOX& operator&=(TBOX& op1, const TBOX& op2) {
00222   if (op1.overlap (op2)) {
00223     if (op2.bot_left.x () > op1.bot_left.x ())
00224       op1.bot_left.set_x (op2.bot_left.x ());
00225 
00226     if (op2.top_right.x () < op1.top_right.x ())
00227       op1.top_right.set_x (op2.top_right.x ());
00228 
00229     if (op2.bot_left.y () > op1.bot_left.y ())
00230       op1.bot_left.set_y (op2.bot_left.y ());
00231 
00232     if (op2.top_right.y () < op1.top_right.y ())
00233       op1.top_right.set_y (op2.top_right.y ());
00234   }
00235   else {
00236     op1.bot_left.set_x (MAX_INT16);
00237     op1.bot_left.set_y (MAX_INT16);
00238     op1.top_right.set_x (-MAX_INT16);
00239     op1.top_right.set_y (-MAX_INT16);
00240   }
00241   return op1;
00242 }
00243 
00244 bool TBOX::x_almost_equal(const TBOX &box, int tolerance) const {
00245   return (abs(left() - box.left()) <= tolerance &&
00246            abs(right() - box.right()) <= tolerance);
00247 }
00248 
00249 bool TBOX::almost_equal(const TBOX &box, int tolerance) const {
00250   return (abs(left() - box.left()) <= tolerance &&
00251           abs(right() - box.right()) <= tolerance &&
00252           abs(top() - box.top()) <= tolerance &&
00253           abs(bottom() - box.bottom()) <= tolerance);
00254 }