tesseract v5.3.3.20231005
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
28namespace tesseract {
29
30/**********************************************************************
31 * TBOX::TBOX() Constructor from 2 ICOORDS
32 *
33 **********************************************************************/
34
35TBOX::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
62bool 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.
69void 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
84TBOX 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
128TBOX 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
165void 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.
177void 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.
187bool 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.
198bool 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
214TBOX &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
242TBOX &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
268bool TBOX::x_almost_equal(const TBOX &box, int tolerance) const {
269 return (abs(left() - box.left()) <= tolerance && abs(right() - box.right()) <= tolerance);
270}
271
272bool 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
ICOORD & operator+=(ICOORD &op1, const ICOORD &op2)
Definition: points.h:372
TBOX & operator&=(TBOX &op1, const TBOX &op2)
Definition: rect.cpp:242
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:710
void Brush(Color color)
Definition: scrollview.cpp:716