Tesseract 3.02

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
stepblob.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 * File: stepblob.cpp (Formerly cblob.c)
3 * Description: Code for C_BLOB class.
4 * Author: Ray Smith
5 * Created: Tue Oct 08 10:41:13 BST 1991
6 *
7 * (C) Copyright 1991, Hewlett-Packard Ltd.
8 ** Licensed under the Apache License, Version 2.0 (the "License");
9 ** you may not use this file except in compliance with the License.
10 ** You may obtain a copy of the License at
11 ** http://www.apache.org/licenses/LICENSE-2.0
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 *
18 **********************************************************************/
19
20 #include "mfcpch.h"
21 #include "stepblob.h"
22 #include "allheaders.h"
23
24 // Include automatically generated configuration file if running autoconf.
25 #ifdef HAVE_CONFIG_H
26 #include "config_auto.h"
27 #endif
28
29 ELISTIZE (C_BLOB)
30 /**********************************************************************
31 * position_outline
32 *
33 * Position the outline in the given list at the relevant place
34 * according to its nesting.
35 **********************************************************************/
36 static void position_outline( //put in place
37 C_OUTLINE *outline, //thing to place
38 C_OUTLINE_LIST *destlist //desstination list
39 ) {
40 C_OUTLINE *dest_outline; //outline from dest list
41 C_OUTLINE_IT it = destlist; //iterator
42 //iterator on children
43 C_OUTLINE_IT child_it = outline->child ();
44
45 if (!it.empty ()) {
46 do {
47 dest_outline = it.data (); //get destination
48 //encloses dest
49 if (*dest_outline < *outline) {
50 //take off list
51 dest_outline = it.extract ();
52 //put this in place
53 it.add_after_then_move (outline);
54 //make it a child
55 child_it.add_to_end (dest_outline);
56 while (!it.at_last ()) {
57 it.forward (); //do rest of list
58 //check for other children
59 dest_outline = it.data ();
60 if (*dest_outline < *outline) {
61 //take off list
62 dest_outline = it.extract ();
63 child_it.add_to_end (dest_outline);
64 //make it a child
65 if (it.empty ())
66 break;
67 }
68 }
69 return; //finished
70 }
71 //enclosed by dest
72 else if (*outline < *dest_outline) {
73 position_outline (outline, dest_outline->child ());
74 //place in child list
75 return; //finished
76 }
77 it.forward ();
78 }
79 while (!it.at_first ());
80 }
81 it.add_to_end (outline); //at outer level
82 }
83
84
85 /**********************************************************************
86 * plot_outline_list
87 *
88 * Draw a list of outlines in the given colour and their children
89 * in the child colour.
90 **********************************************************************/
91
92 #ifndef GRAPHICS_DISABLED
93 static void plot_outline_list( //draw outlines
94 C_OUTLINE_LIST *list, //outline to draw
95 ScrollView* window, //window to draw in
96 ScrollView::Color colour, //colour to use
97 ScrollView::Color child_colour //colour of children
98 ) {
99 C_OUTLINE *outline; //current outline
100 C_OUTLINE_IT it = list; //iterator
101
102 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
103 outline = it.data ();
104 //draw it
105 outline->plot (window, colour);
106 if (!outline->child ()->empty ())
107 plot_outline_list (outline->child (), window,
108 child_colour, child_colour);
109 }
110 }
111 #endif
112
113
114 /**********************************************************************
115 * reverse_outline_list
116 *
117 * Reverse a list of outlines and their children.
118 **********************************************************************/
119
120 static void reverse_outline_list( //reverse outlines
121 C_OUTLINE_LIST *list //outline to reverse
122 ) {
123 C_OUTLINE *outline; //current outline
124 C_OUTLINE_IT it = list; //iterator
125
126 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
127 outline = it.data ();
128 outline->reverse (); //reverse it
129 if (!outline->child ()->empty ())
130 reverse_outline_list (outline->child ());
131 }
132 }
133
134
135 /**********************************************************************
136 * C_BLOB::C_BLOB
137 *
138 * Constructor to build a C_BLOB from a list of C_OUTLINEs.
139 * The C_OUTLINEs are not copied so the source list is emptied.
140 * The C_OUTLINEs are nested correctly in the blob.
141 **********************************************************************/
142
143 C_BLOB::C_BLOB( //constructor
144 C_OUTLINE_LIST *outline_list //in random order
145 ) {
146 C_OUTLINE *outline; //current outline
147 C_OUTLINE_IT it = outline_list;//iterator
148
149 while (!it.empty ()) { //grab the list
150 outline = it.extract (); //get off the list
151 //put it in place
152 position_outline(outline, &outlines);
153 if (!it.empty ())
154 it.forward ();
155 }
156 it.set_to_list (&outlines);
157 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
158 outline = it.data ();
159 if (outline->turn_direction () < 0) {
160 outline->reverse ();
161 reverse_outline_list (outline->child ());
162 outline->set_flag (COUT_INVERSE, TRUE);
163 }
164 else {
165 outline->set_flag (COUT_INVERSE, FALSE);
166 }
167 }
168 }
169
170 // Simpler constructor to build a blob from a single outline that has
171 // already been fully initialized.
172 C_BLOB::C_BLOB(C_OUTLINE* outline) {
173 C_OUTLINE_IT it(&outlines);
174 it.add_to_end(outline);
175 }
176
177
178 // Build and return a fake blob containing a single fake outline with no
179 // steps.
180 C_BLOB* C_BLOB::FakeBlob(const TBOX& box) {
181 C_OUTLINE_LIST outlines;
182 C_OUTLINE::FakeOutline(box, &outlines);
183 return new C_BLOB(&outlines);
184 }
185
186 /**********************************************************************
187 * C_BLOB::bounding_box
188 *
189 * Return the bounding box of the blob.
190 **********************************************************************/
191
192 TBOX C_BLOB::bounding_box() { //bounding box
193 C_OUTLINE *outline; //current outline
194 C_OUTLINE_IT it = &outlines; //outlines of blob
195 TBOX box; //bounding box
196
197 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
198 outline = it.data ();
199 box += outline->bounding_box ();
200 }
201 return box;
202 }
203
204
205 /**********************************************************************
206 * C_BLOB::area
207 *
208 * Return the area of the blob.
209 **********************************************************************/
210
211 inT32 C_BLOB::area() { //area
212 C_OUTLINE *outline; //current outline
213 C_OUTLINE_IT it = &outlines; //outlines of blob
214 inT32 total; //total area
215
216 total = 0;
217 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
218 outline = it.data ();
219 total += outline->area ();
220 }
221 return total;
222 }
223
224 /**********************************************************************
225 * C_BLOB::perimeter
226 *
227 * Return the perimeter of the top and 2nd level outlines.
228 **********************************************************************/
229
230 inT32 C_BLOB::perimeter() {
231 C_OUTLINE *outline; // current outline
232 C_OUTLINE_IT it = &outlines; // outlines of blob
233 inT32 total; // total perimeter
234
235 total = 0;
236 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
237 outline = it.data();
238 total += outline->perimeter();
239 }
240 return total;
241 }
242
243
244 /**********************************************************************
245 * C_BLOB::outer_area
246 *
247 * Return the area of the blob.
248 **********************************************************************/
249
250 inT32 C_BLOB::outer_area() { //area
251 C_OUTLINE *outline; //current outline
252 C_OUTLINE_IT it = &outlines; //outlines of blob
253 inT32 total; //total area
254
255 total = 0;
256 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
257 outline = it.data ();
258 total += outline->outer_area ();
259 }
260 return total;
261 }
262
263
264 /**********************************************************************
265 * C_BLOB::count_transitions
266 *
267 * Return the total x and y maxes and mins in the blob.
268 * Chlid outlines are not counted.
269 **********************************************************************/
270
271 inT32 C_BLOB::count_transitions( //area
272 inT32 threshold //on size
273 ) {
274 C_OUTLINE *outline; //current outline
275 C_OUTLINE_IT it = &outlines; //outlines of blob
276 inT32 total; //total area
277
278 total = 0;
279 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
280 outline = it.data ();
281 total += outline->count_transitions (threshold);
282 }
283 return total;
284 }
285
286
287 /**********************************************************************
288 * C_BLOB::move
289 *
290 * Move C_BLOB by vector
291 **********************************************************************/
292
293 void C_BLOB::move( // reposition blob
294 const ICOORD vec // by vector
295 ) {
296 C_OUTLINE_IT it(&outlines); // iterator
297
298 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
299 it.data ()->move (vec); // move each outline
300 }
301
302 // Static helper for C_BLOB::rotate to allow recursion of child outlines.
303 void RotateOutlineList(const FCOORD& rotation, C_OUTLINE_LIST* outlines) {
304 C_OUTLINE_LIST new_outlines;
305 C_OUTLINE_IT src_it(outlines);
306 C_OUTLINE_IT dest_it(&new_outlines);
307 while (!src_it.empty()) {
308 C_OUTLINE* old_outline = src_it.extract();
309 src_it.forward();
310 C_OUTLINE* new_outline = new C_OUTLINE(old_outline, rotation);
311 if (!old_outline->child()->empty()) {
312 RotateOutlineList(rotation, old_outline->child());
313 C_OUTLINE_IT child_it(new_outline->child());
314 child_it.add_list_after(old_outline->child());
315 }
316 delete old_outline;
317 dest_it.add_to_end(new_outline);
318 }
319 src_it.add_list_after(&new_outlines);
320 }
321
322 /**********************************************************************
323 * C_BLOB::rotate
324 *
325 * Rotate C_BLOB by rotation.
326 * Warning! has to rebuild all the C_OUTLINEs.
327 **********************************************************************/
328 void C_BLOB::rotate(const FCOORD& rotation) {
329 RotateOutlineList(rotation, &outlines);
330 }
331
332 static void render_outline_list(C_OUTLINE_LIST *list,
333 int left, int top, Pix* pix) {
334 C_OUTLINE_IT it(list);
335 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
336 C_OUTLINE* outline = it.data();
337 outline->render(left, top, pix);
338 if (!outline->child()->empty())
339 render_outline_list(outline->child(), left, top, pix);
340 }
341 }
342
343 static void render_outline_list_outline(C_OUTLINE_LIST *list,
344 int left, int top, Pix* pix) {
345 C_OUTLINE_IT it(list);
346 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
347 C_OUTLINE* outline = it.data();
348 outline->render_outline(left, top, pix);
349 }
350 }
351
352 // Returns a Pix rendering of the blob. pixDestroy after use.
353 Pix* C_BLOB::render() {
354 TBOX box = bounding_box();
355 Pix* pix = pixCreate(box.width(), box.height(), 1);
356 render_outline_list(&outlines, box.left(), box.top(), pix);
357 return pix;
358 }
359
360 // Returns a Pix rendering of the outline of the blob. (no fill).
361 // pixDestroy after use.
362 Pix* C_BLOB::render_outline() {
363 TBOX box = bounding_box();
364 Pix* pix = pixCreate(box.width(), box.height(), 1);
365 render_outline_list_outline(&outlines, box.left(), box.top(), pix);
366 return pix;
367 }
368
369 /**********************************************************************
370 * C_BLOB::plot
371 *
372 * Draw the C_BLOB in the given colour.
373 **********************************************************************/
374
375 #ifndef GRAPHICS_DISABLED
376 void C_BLOB::plot( //draw it
377 ScrollView* window, //window to draw in
378 ScrollView::Color blob_colour, //main colour
379 ScrollView::Color child_colour //for holes
380 ) {
381 plot_outline_list(&outlines, window, blob_colour, child_colour);
382 }
383 #endif