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