tesseract  5.0.0
rect.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * File: rect.cpp (Formerly box.c)
3  * Description: Bounding box class definition.
4  * Author: Phil Cheatle
5  *
6  * (C) Copyright 1991, Hewlett-Packard Ltd.
7  ** Licensed under the Apache License, Version 2.0 (the "License");
8  ** you may not use this file except in compliance with the License.
9  ** You may obtain a copy of the License at
10  ** http://www.apache.org/licenses/LICENSE-2.0
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  *
17  **********************************************************************/
18 
19 // Include automatically generated configuration file if running autoconf.
20 #ifdef HAVE_CONFIG_H
21 # include "config_auto.h"
22 #endif
23 
24 #include "rect.h"
25 
26 #include "serialis.h" // for TFile
27 
28 namespace tesseract {
29 
30 /**********************************************************************
31  * TBOX::TBOX() Constructor from 2 ICOORDS
32  *
33  **********************************************************************/
34 
35 TBOX::TBOX( // constructor
36  const ICOORD pt1, // one corner
37  const ICOORD pt2 // the other corner
38 ) {
39  if (pt1.x() <= pt2.x()) {
40  if (pt1.y() <= pt2.y()) {
41  bot_left = pt1;
42  top_right = pt2;
43  } else {
44  bot_left = ICOORD(pt1.x(), pt2.y());
45  top_right = ICOORD(pt2.x(), pt1.y());
46  }
47  } else {
48  if (pt1.y() <= pt2.y()) {
49  bot_left = ICOORD(pt2.x(), pt1.y());
50  top_right = ICOORD(pt1.x(), pt2.y());
51  } else {
52  bot_left = pt2;
53  top_right = pt1;
54  }
55  }
56 }
57 
59  return bot_left.DeSerialize(f) && top_right.DeSerialize(f);
60 }
61 
62 bool TBOX::Serialize(TFile *f) const {
63  return bot_left.Serialize(f) && top_right.Serialize(f);
64 }
65 
66 // rotate_large constructs the containing bounding box of all 4
67 // corners after rotating them. It therefore guarantees that all
68 // original content is contained within, but also slightly enlarges the box.
69 void TBOX::rotate_large(const FCOORD &vec) {
70  ICOORD top_left(bot_left.x(), top_right.y());
71  ICOORD bottom_right(top_right.x(), bot_left.y());
72  top_left.rotate(vec);
73  bottom_right.rotate(vec);
74  rotate(vec);
75  TBOX box2(top_left, bottom_right);
76  *this += box2;
77 }
78 
79 /**********************************************************************
80  * TBOX::intersection() Build the largest box contained in both boxes
81  *
82  **********************************************************************/
83 
84 TBOX TBOX::intersection( // shared area box
85  const TBOX &box) const {
90  if (overlap(box)) {
91  if (box.bot_left.x() > bot_left.x()) {
92  left = box.bot_left.x();
93  } else {
94  left = bot_left.x();
95  }
96 
97  if (box.top_right.x() < top_right.x()) {
98  right = box.top_right.x();
99  } else {
100  right = top_right.x();
101  }
102 
103  if (box.bot_left.y() > bot_left.y()) {
104  bottom = box.bot_left.y();
105  } else {
106  bottom = bot_left.y();
107  }
108 
109  if (box.top_right.y() < top_right.y()) {
110  top = box.top_right.y();
111  } else {
112  top = top_right.y();
113  }
114  } else {
115  left = INT16_MAX;
116  bottom = INT16_MAX;
117  top = -INT16_MAX;
118  right = -INT16_MAX;
119  }
120  return TBOX(left, bottom, right, top);
121 }
122 
123 /**********************************************************************
124  * TBOX::bounding_union() Build the smallest box containing both boxes
125  *
126  **********************************************************************/
127 
128 TBOX TBOX::bounding_union( // box enclosing both
129  const TBOX &box) const {
130  ICOORD bl; // bottom left
131  ICOORD tr; // top right
132 
133  if (box.bot_left.x() < bot_left.x()) {
134  bl.set_x(box.bot_left.x());
135  } else {
136  bl.set_x(bot_left.x());
137  }
138 
139  if (box.top_right.x() > top_right.x()) {
140  tr.set_x(box.top_right.x());
141  } else {
142  tr.set_x(top_right.x());
143  }
144 
145  if (box.bot_left.y() < bot_left.y()) {
146  bl.set_y(box.bot_left.y());
147  } else {
148  bl.set_y(bot_left.y());
149  }
150 
151  if (box.top_right.y() > top_right.y()) {
152  tr.set_y(box.top_right.y());
153  } else {
154  tr.set_y(top_right.y());
155  }
156  return TBOX(bl, tr);
157 }
158 
159 /**********************************************************************
160  * TBOX::plot() Paint a box using specified settings
161  *
162  **********************************************************************/
163 
164 #ifndef GRAPHICS_DISABLED
165 void TBOX::plot( // paint box
166  ScrollView *fd, // where to paint
167  ScrollView::Color fill_colour, // colour for inside
168  ScrollView::Color border_colour // colour for border
169  ) const {
170  fd->Brush(fill_colour);
171  fd->Pen(border_colour);
172  plot(fd);
173 }
174 #endif
175 
176 // Appends the bounding box as (%d,%d)->(%d,%d) to a string.
177 void TBOX::print_to_str(std::string &str) const {
178  // "(%d,%d)->(%d,%d)", left(), bottom(), right(), top()
179  str += "(" + std::to_string(left());
180  str += "," + std::to_string(bottom());
181  str += ")->(" + std::to_string(right());
182  str += "," + std::to_string(top());
183  str += ')';
184 }
185 
186 // Writes to the given file. Returns false in case of error.
187 bool TBOX::Serialize(FILE *fp) const {
188  if (!bot_left.Serialize(fp)) {
189  return false;
190  }
191  if (!top_right.Serialize(fp)) {
192  return false;
193  }
194  return true;
195 }
196 // Reads from the given file. Returns false in case of error.
197 // If swap is true, assumes a big/little-endian swap is needed.
198 bool TBOX::DeSerialize(bool swap, FILE *fp) {
199  if (!bot_left.DeSerialize(swap, fp)) {
200  return false;
201  }
202  if (!top_right.DeSerialize(swap, fp)) {
203  return false;
204  }
205  return true;
206 }
207 
208 /**********************************************************************
209  * operator+=
210  *
211  * Extend one box to include the other (In place union)
212  **********************************************************************/
213 
214 TBOX &operator+=( // bounding bounding bx
215  TBOX &op1, // operands
216  const TBOX &op2) {
217  if (op2.bot_left.x() < op1.bot_left.x()) {
218  op1.bot_left.set_x(op2.bot_left.x());
219  }
220 
221  if (op2.top_right.x() > op1.top_right.x()) {
222  op1.top_right.set_x(op2.top_right.x());
223  }
224 
225  if (op2.bot_left.y() < op1.bot_left.y()) {
226  op1.bot_left.set_y(op2.bot_left.y());
227  }
228 
229  if (op2.top_right.y() > op1.top_right.y()) {
230  op1.top_right.set_y(op2.top_right.y());
231  }
232 
233  return op1;
234 }
235 
236 /**********************************************************************
237  * operator&=
238  *
239  * Reduce one box to intersection with the other (In place intersection)
240  **********************************************************************/
241 
242 TBOX &operator&=(TBOX &op1, const TBOX &op2) {
243  if (op1.overlap(op2)) {
244  if (op2.bot_left.x() > op1.bot_left.x()) {
245  op1.bot_left.set_x(op2.bot_left.x());
246  }
247 
248  if (op2.top_right.x() < op1.top_right.x()) {
249  op1.top_right.set_x(op2.top_right.x());
250  }
251 
252  if (op2.bot_left.y() > op1.bot_left.y()) {
253  op1.bot_left.set_y(op2.bot_left.y());
254  }
255 
256  if (op2.top_right.y() < op1.top_right.y()) {
257  op1.top_right.set_y(op2.top_right.y());
258  }
259  } else {
260  op1.bot_left.set_x(INT16_MAX);
261  op1.bot_left.set_y(INT16_MAX);
262  op1.top_right.set_x(-INT16_MAX);
263  op1.top_right.set_y(-INT16_MAX);
264  }
265  return op1;
266 }
267 
268 bool TBOX::x_almost_equal(const TBOX &box, int tolerance) const {
269  return (abs(left() - box.left()) <= tolerance && abs(right() - box.right()) <= tolerance);
270 }
271 
272 bool TBOX::almost_equal(const TBOX &box, int tolerance) const {
273  return (abs(left() - box.left()) <= tolerance && abs(right() - box.right()) <= tolerance &&
274  abs(top() - box.top()) <= tolerance && abs(bottom() - box.bottom()) <= tolerance);
275 }
276 
277 } // namespace tesseract
TBOX & operator&=(TBOX &op1, const TBOX &op2)
Definition: rect.cpp:242
ICOORD & operator+=(ICOORD &op1, const ICOORD &op2)
Definition: points.h:372
int16_t TDimension
Definition: tesstypes.h:32
integer coordinate
Definition: points.h:36
void rotate(const FCOORD &vec)
Definition: points.h:511
void set_x(TDimension xin)
rewrite function
Definition: points.h:67
TDimension y() const
access_function
Definition: points.h:62
bool DeSerialize(TFile *f)
Definition: points.cpp:43
void set_y(TDimension yin)
rewrite function
Definition: points.h:71
TDimension x() const
access function
Definition: points.h:58
bool Serialize(TFile *f) const
Definition: points.cpp:47
TDimension left() const
Definition: rect.h:82
void print_to_str(std::string &str) const
Definition: rect.cpp:177
bool x_almost_equal(const TBOX &box, int tolerance) const
Definition: rect.cpp:268
bool almost_equal(const TBOX &box, int tolerance) const
Definition: rect.cpp:272
bool Serialize(FILE *fp) const
Definition: rect.cpp:187
bool DeSerialize(bool swap, FILE *fp)
Definition: rect.cpp:198
void rotate(const FCOORD &vec)
Definition: rect.h:210
TDimension top() const
Definition: rect.h:68
TBOX bounding_union(const TBOX &box) const
Definition: rect.cpp:128
TBOX intersection(const TBOX &box) const
Definition: rect.cpp:84
void rotate_large(const FCOORD &vec)
Definition: rect.cpp:69
TDimension right() const
Definition: rect.h:89
bool overlap(const TBOX &box) const
Definition: rect.h:363
TDimension bottom() const
Definition: rect.h:75
void plot(ScrollView *fd) const
Definition: rect.h:296
void Pen(Color color)
Definition: scrollview.cpp:723
void Brush(Color color)
Definition: scrollview.cpp:729