Tesseract  3.02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tesseract::ColPartitionSet Class Reference

#include <colpartitionset.h>

Inheritance diagram for tesseract::ColPartitionSet:
ELIST_LINK

Public Member Functions

 ColPartitionSet ()
 
 ColPartitionSet (ColPartition_LIST *partitions)
 
 ColPartitionSet (ColPartition *partition)
 
 ~ColPartitionSet ()
 
const TBOXbounding_box () const
 
bool Empty ()
 
int ColumnCount ()
 
ColPartitionGetColumnByIndex (int index)
 
ColPartitionColumnContaining (int x, int y)
 
void GetColumnBoxes (int y_bottom, int y_top, ColSegment_LIST *segments)
 
void RelinquishParts ()
 
void ImproveColumnCandidate (WidthCallback *cb, PartSetVector *src_sets)
 
void AddToColumnSetsIfUnique (PartSetVector *column_sets, WidthCallback *cb)
 
bool CompatibleColumns (bool debug, ColPartitionSet *other, WidthCallback *cb)
 
int UnmatchedWidth (ColPartitionSet *part_set)
 
bool LegalColumnCandidate ()
 
ColPartitionSetCopy (bool good_only)
 
void DisplayColumnEdges (int y_bottom, int y_top, ScrollView *win)
 
ColumnSpanningType SpanningType (int resolution, int left, int right, int y, int left_margin, int right_margin, int *first_col, int *last_col, int *first_spanned_col)
 
void ChangeWorkColumns (const ICOORD &bleft, const ICOORD &tright, int resolution, ColPartition_LIST *used_parts, WorkingPartSet_LIST *working_set)
 
void AccumulateColumnWidthsAndGaps (int *total_width, int *width_samples, int *total_gap, int *gap_samples)
 
void Print ()
 
- Public Member Functions inherited from ELIST_LINK
 ELIST_LINK ()
 
 ELIST_LINK (const ELIST_LINK &)
 
void operator= (const ELIST_LINK &)
 

Detailed Description

Definition at line 40 of file colpartitionset.h.

Constructor & Destructor Documentation

tesseract::ColPartitionSet::ColPartitionSet ( )
inline

Definition at line 42 of file colpartitionset.h.

42  {
43  }
tesseract::ColPartitionSet::ColPartitionSet ( ColPartition_LIST *  partitions)
explicit

Definition at line 33 of file colpartitionset.cpp.

33  {
34  ColPartition_IT it(&parts_);
35  it.add_list_after(partitions);
36  ComputeCoverage();
37 }
tesseract::ColPartitionSet::ColPartitionSet ( ColPartition partition)
explicit

Definition at line 39 of file colpartitionset.cpp.

39  {
40  ColPartition_IT it(&parts_);
41  it.add_after_then_move(part);
42  ComputeCoverage();
43 }
tesseract::ColPartitionSet::~ColPartitionSet ( )

Definition at line 45 of file colpartitionset.cpp.

45  {
46 }

Member Function Documentation

void tesseract::ColPartitionSet::AccumulateColumnWidthsAndGaps ( int *  total_width,
int *  width_samples,
int *  total_gap,
int *  gap_samples 
)

Definition at line 557 of file colpartitionset.cpp.

560  {
561  ColPartition_IT it(&parts_);
562  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
563  ColPartition* part = it.data();
564  *total_width += part->ColumnWidth();
565  ++*width_samples;
566  if (!it.at_last()) {
567  ColPartition* next_part = it.data_relative(1);
568  int gap = part->KeyWidth(part->right_key(), next_part->left_key());
569  *total_gap += gap;
570  ++*gap_samples;
571  }
572  }
573 }
void tesseract::ColPartitionSet::AddToColumnSetsIfUnique ( PartSetVector column_sets,
WidthCallback cb 
)

Definition at line 164 of file colpartitionset.cpp.

165  {
166  bool debug = TabFind::WithinTestRegion(2, bounding_box_.left(),
167  bounding_box_.bottom());
168  if (debug) {
169  tprintf("Considering new column candidate:\n");
170  Print();
171  }
172  if (!LegalColumnCandidate()) {
173  if (debug) {
174  tprintf("Not a legal column candidate:\n");
175  Print();
176  }
177  delete this;
178  return;
179  }
180  for (int i = 0; i < column_sets->size(); ++i) {
181  ColPartitionSet* columns = column_sets->get(i);
182  // In ordering the column set candidates, good_coverage_ is king,
183  // followed by good_column_count_ and then bad_coverage_.
184  bool better = good_coverage_ > columns->good_coverage_;
185  if (good_coverage_ == columns->good_coverage_) {
186  better = good_column_count_ > columns->good_column_count_;
187  if (good_column_count_ == columns->good_column_count_) {
188  better = bad_coverage_ > columns->bad_coverage_;
189  }
190  }
191  if (better) {
192  // The new one is better so add it.
193  if (debug)
194  tprintf("Good one\n");
195  column_sets->insert(this, i);
196  return;
197  }
198  if (columns->CompatibleColumns(false, this, cb)) {
199  if (debug)
200  tprintf("Duplicate\n");
201  delete this;
202  return; // It is not unique.
203  }
204  }
205  if (debug)
206  tprintf("Added to end\n");
207  column_sets->push_back(this);
208 }
inT16 left() const
Definition: rect.h:67
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:41
static bool WithinTestRegion(int detail_level, int x, int y)
inT16 bottom() const
Definition: rect.h:60
const TBOX& tesseract::ColPartitionSet::bounding_box ( ) const
inline

Definition at line 50 of file colpartitionset.h.

50  {
51  return bounding_box_;
52  }
void tesseract::ColPartitionSet::ChangeWorkColumns ( const ICOORD bleft,
const ICOORD tright,
int  resolution,
ColPartition_LIST *  used_parts,
WorkingPartSet_LIST *  working_set 
)

Definition at line 485 of file colpartitionset.cpp.

489  {
490  // Move the input list to a temporary location so we can delete its elements
491  // as we add them to the output working_set.
492  WorkingPartSet_LIST work_src;
493  WorkingPartSet_IT src_it(&work_src);
494  src_it.add_list_after(working_set_list);
495  src_it.move_to_first();
496  WorkingPartSet_IT dest_it(working_set_list);
497  // Completed blocks and to_blocks are accumulated and given to the first new
498  // one whenever we keep a column, or at the end.
499  BLOCK_LIST completed_blocks;
500  TO_BLOCK_LIST to_blocks;
501  WorkingPartSet* first_new_set = NULL;
502  WorkingPartSet* working_set = NULL;
503  ColPartition_IT col_it(&parts_);
504  for (col_it.mark_cycle_pt(); !col_it.cycled_list(); col_it.forward()) {
505  ColPartition* column = col_it.data();
506  // Any existing column to the left of column is completed.
507  while (!src_it.empty() &&
508  ((working_set = src_it.data())->column() == NULL ||
509  working_set->column()->right_key() <= column->left_key())) {
510  src_it.extract();
511  working_set->ExtractCompletedBlocks(bleft, tright, resolution,
512  used_parts, &completed_blocks,
513  &to_blocks);
514  delete working_set;
515  src_it.forward();
516  }
517  // Make a new between-column WorkingSet for before the current column.
518  working_set = new WorkingPartSet(NULL);
519  dest_it.add_after_then_move(working_set);
520  if (first_new_set == NULL)
521  first_new_set = working_set;
522  // A matching column gets to stay, and first_new_set gets all the
523  // completed_sets.
524  working_set = src_it.empty() ? NULL : src_it.data();
525  if (working_set != NULL &&
526  working_set->column()->MatchingColumns(*column)) {
527  working_set->set_column(column);
528  dest_it.add_after_then_move(src_it.extract());
529  src_it.forward();
530  first_new_set->InsertCompletedBlocks(&completed_blocks, &to_blocks);
531  first_new_set = NULL;
532  } else {
533  // Just make a new working set for the current column.
534  working_set = new WorkingPartSet(column);
535  dest_it.add_after_then_move(working_set);
536  }
537  }
538  // Complete any remaining src working sets.
539  while (!src_it.empty()) {
540  working_set = src_it.extract();
541  working_set->ExtractCompletedBlocks(bleft, tright, resolution,
542  used_parts, &completed_blocks,
543  &to_blocks);
544  delete working_set;
545  src_it.forward();
546  }
547  // Make a new between-column WorkingSet for after the last column.
548  working_set = new WorkingPartSet(NULL);
549  dest_it.add_after_then_move(working_set);
550  if (first_new_set == NULL)
551  first_new_set = working_set;
552  // The first_new_set now gets any accumulated completed_parts/blocks.
553  first_new_set->InsertCompletedBlocks(&completed_blocks, &to_blocks);
554 }
#define NULL
Definition: host.h:144
ColPartition * tesseract::ColPartitionSet::ColumnContaining ( int  x,
int  y 
)

Definition at line 59 of file colpartitionset.cpp.

59  {
60  ColPartition_IT it(&parts_);
61  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
62  ColPartition* part = it.data();
63  if (part->ColumnContains(x, y))
64  return part;
65  }
66  return NULL;
67 }
#define NULL
Definition: host.h:144
int tesseract::ColPartitionSet::ColumnCount ( )
inline

Definition at line 56 of file colpartitionset.h.

56  {
57  return parts_.length();
58  }
bool tesseract::ColPartitionSet::CompatibleColumns ( bool  debug,
ColPartitionSet other,
WidthCallback cb 
)

Definition at line 212 of file colpartitionset.cpp.

213  {
214  if (debug) {
215  tprintf("CompatibleColumns testing compatibility\n");
216  Print();
217  other->Print();
218  }
219  if (other->parts_.empty()) {
220  if (debug)
221  tprintf("CompatibleColumns true due to empty other\n");
222  return true;
223  }
224  ColPartition_IT it(&other->parts_);
225  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
226  ColPartition* part = it.data();
227  if (part->blob_type() < BRT_UNKNOWN) {
228  if (debug) {
229  tprintf("CompatibleColumns ignoring image partition\n");
230  part->Print();
231  }
232  continue; // Image partitions are irrelevant to column compatibility.
233  }
234  int y = part->MidY();
235  int left = part->bounding_box().left();
236  int right = part->bounding_box().right();
237  ColPartition* left_col = ColumnContaining(left, y);
238  ColPartition* right_col = ColumnContaining(right, y);
239  if (right_col == NULL || left_col == NULL) {
240  if (debug) {
241  tprintf("CompatibleColumns false due to partition edge outside\n");
242  part->Print();
243  }
244  return false; // A partition edge lies outside of all columns
245  }
246  if (right_col != left_col && cb->Run(right - left)) {
247  if (debug) {
248  tprintf("CompatibleColumns false due to good width in multiple cols\n");
249  part->Print();
250  }
251  return false; // Partition with a good width must be in a single column.
252  }
253 
254  ColPartition_IT it2= it;
255  while (!it2.at_last()) {
256  it2.forward();
257  ColPartition* next_part = it2.data();
258  if (!BLOBNBOX::IsTextType(next_part->blob_type()))
259  continue; // Non-text partitions are irrelevant.
260  int next_left = next_part->bounding_box().left();
261  if (next_left == right) {
262  break; // They share the same edge, so one must be a pull-out.
263  }
264  // Search to see if right and next_left fall within a single column.
265  ColPartition* next_left_col = ColumnContaining(next_left, y);
266  if (right_col == next_left_col) {
267  // There is a column break in this column.
268  // This can be due to a figure caption within a column, a pull-out
269  // block, or a simple broken textline that remains to be merged:
270  // all allowed, or a change in column layout: not allowed.
271  // If both partitions are of good width, then it is likely
272  // a change in column layout, otherwise probably an allowed situation.
273  if (part->good_width() && next_part->good_width()) {
274  if (debug) {
275  int next_right = next_part->bounding_box().right();
276  tprintf("CompatibleColumns false due to 2 parts of good width\n");
277  tprintf("part1 %d-%d, part2 %d-%d\n",
278  left, right, next_left, next_right);
279  right_col->Print();
280  }
281  return false;
282  }
283  }
284  break;
285  }
286  }
287  if (debug)
288  tprintf("CompatibleColumns true!\n");
289  return true;
290 }
ColPartition * ColumnContaining(int x, int y)
#define NULL
Definition: host.h:144
static bool IsTextType(BlobRegionType type)
Definition: blobbox.h:391
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:41
ColPartitionSet * tesseract::ColPartitionSet::Copy ( bool  good_only)

Definition at line 343 of file colpartitionset.cpp.

343  {
344  ColPartition_LIST copy_parts;
345  ColPartition_IT src_it(&parts_);
346  ColPartition_IT dest_it(&copy_parts);
347  for (src_it.mark_cycle_pt(); !src_it.cycled_list(); src_it.forward()) {
348  ColPartition* part = src_it.data();
349  if (BLOBNBOX::IsTextType(part->blob_type()) &&
350  (!good_only || part->good_width() || part->good_column()))
351  dest_it.add_after_then_move(part->ShallowCopy());
352  }
353  if (dest_it.empty())
354  return NULL;
355  return new ColPartitionSet(&copy_parts);
356 }
#define NULL
Definition: host.h:144
static bool IsTextType(BlobRegionType type)
Definition: blobbox.h:391
void tesseract::ColPartitionSet::DisplayColumnEdges ( int  y_bottom,
int  y_top,
ScrollView win 
)

Definition at line 375 of file colpartitionset.cpp.

376  {
377  #ifndef GRAPHICS_DISABLED
378  ColPartition_IT it(&parts_);
379  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
380  ColPartition* part = it.data();
381  win->Line(part->LeftAtY(y_top), y_top, part->LeftAtY(y_bottom), y_bottom);
382  win->Line(part->RightAtY(y_top), y_top, part->RightAtY(y_bottom), y_bottom);
383  }
384  #endif // GRAPHICS_DISABLED
385 }
void Line(int x1, int y1, int x2, int y2)
Definition: scrollview.cpp:533
bool tesseract::ColPartitionSet::Empty ( )
inline

Definition at line 53 of file colpartitionset.h.

53  {
54  return parts_.empty();
55  }
void tesseract::ColPartitionSet::GetColumnBoxes ( int  y_bottom,
int  y_top,
ColSegment_LIST *  segments 
)

Definition at line 359 of file colpartitionset.cpp.

360  {
361  ColPartition_IT it(&parts_);
362  ColSegment_IT col_it(segments);
363  col_it.move_to_last();
364  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
365  ColPartition* part = it.data();
366  ICOORD bot_left(part->LeftAtY(y_top), y_bottom);
367  ICOORD top_right(part->RightAtY(y_bottom), y_top);
368  ColSegment *col_seg = new ColSegment();
369  col_seg->InsertBox(TBOX(bot_left, top_right));
370  col_it.add_after_then_move(col_seg);
371  }
372 }
Definition: rect.h:29
integer coordinate
Definition: points.h:30
ColPartition * tesseract::ColPartitionSet::GetColumnByIndex ( int  index)

Definition at line 49 of file colpartitionset.cpp.

49  {
50  ColPartition_IT it(&parts_);
51  it.mark_cycle_pt();
52  for (int i = 0; i < index && !it.cycled_list(); ++i, it.forward());
53  if (it.cycled_list())
54  return NULL;
55  return it.data();
56 }
#define NULL
Definition: host.h:144
void tesseract::ColPartitionSet::ImproveColumnCandidate ( WidthCallback cb,
PartSetVector src_sets 
)

Definition at line 79 of file colpartitionset.cpp.

80  {
81  int set_size = src_sets->size();
82  // Iterate over the provided column sets, as each one may have something
83  // to improve this.
84  for (int i = 0; i < set_size; ++i) {
85  ColPartitionSet* column_set = src_sets->get(i);
86  if (column_set == NULL)
87  continue;
88  // Iterate over the parts in this and column_set, adding bigger or
89  // new parts in column_set to this.
90  ColPartition_IT part_it(&parts_);
91  ASSERT_HOST(!part_it.empty());
92  int prev_right = MIN_INT32;
93  part_it.mark_cycle_pt();
94  ColPartition_IT col_it(&column_set->parts_);
95  for (col_it.mark_cycle_pt(); !col_it.cycled_list(); col_it.forward()) {
96  ColPartition* col_part = col_it.data();
97  if (col_part->blob_type() < BRT_UNKNOWN)
98  continue; // Ignore image partitions.
99  int col_left = col_part->left_key();
100  int col_right = col_part->right_key();
101  // Sync-up part_it (in this) so it matches the col_part in column_set.
102  ColPartition* part = part_it.data();
103  while (!part_it.at_last() && part->right_key() < col_left) {
104  prev_right = part->right_key();
105  part_it.forward();
106  part = part_it.data();
107  }
108  int part_left = part->left_key();
109  int part_right = part->right_key();
110  if (part_right < col_left || col_right < part_left) {
111  // There is no overlap so this is a new partition.
112  AddPartition(col_part->ShallowCopy(), &part_it);
113  continue;
114  }
115  // Check the edges of col_part to see if they can improve part.
116  bool part_width_ok = cb->Run(part->KeyWidth(part_left, part_right));
117  if (col_left < part_left && col_left > prev_right) {
118  // The left edge of the column is better and it doesn't overlap,
119  // so we can potentially expand it.
120  int col_box_left = col_part->BoxLeftKey();
121  bool tab_width_ok = cb->Run(part->KeyWidth(col_left, part_right));
122  bool box_width_ok = cb->Run(part->KeyWidth(col_box_left, part_right));
123  if (tab_width_ok || (!part_width_ok )) {
124  // The tab is leaving the good column metric at least as good as
125  // it was before, so use the tab.
126  part->CopyLeftTab(*col_part, false);
127  part->SetColumnGoodness(cb);
128  } else if (col_box_left < part_left &&
129  (box_width_ok || !part_width_ok)) {
130  // The box is leaving the good column metric at least as good as
131  // it was before, so use the box.
132  part->CopyLeftTab(*col_part, true);
133  part->SetColumnGoodness(cb);
134  }
135  part_left = part->left_key();
136  }
137  if (col_right > part_right &&
138  (part_it.at_last() ||
139  part_it.data_relative(1)->left_key() > col_right)) {
140  // The right edge is better, so we can possibly expand it.
141  int col_box_right = col_part->BoxRightKey();
142  bool tab_width_ok = cb->Run(part->KeyWidth(part_left, col_right));
143  bool box_width_ok = cb->Run(part->KeyWidth(part_left, col_box_right));
144  if (tab_width_ok || (!part_width_ok )) {
145  // The tab is leaving the good column metric at least as good as
146  // it was before, so use the tab.
147  part->CopyRightTab(*col_part, false);
148  part->SetColumnGoodness(cb);
149  } else if (col_box_right > part_right &&
150  (box_width_ok || !part_width_ok)) {
151  // The box is leaving the good column metric at least as good as
152  // it was before, so use the box.
153  part->CopyRightTab(*col_part, true);
154  part->SetColumnGoodness(cb);
155  }
156  }
157  }
158  }
159  ComputeCoverage();
160 }
#define NULL
Definition: host.h:144
#define ASSERT_HOST(x)
Definition: errcode.h:84
#define MIN_INT32
Definition: host.h:128
bool tesseract::ColPartitionSet::LegalColumnCandidate ( )

Definition at line 320 of file colpartitionset.cpp.

320  {
321  ColPartition_IT it(&parts_);
322  if (it.empty())
323  return false;
324  bool any_text_parts = false;
325  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
326  ColPartition* part = it.data();
327  if (BLOBNBOX::IsTextType(part->blob_type())) {
328  if (!part->IsLegal())
329  return false; // Individual partition is illegal.
330  any_text_parts = true;
331  }
332  if (!it.at_last()) {
333  ColPartition* next_part = it.data_relative(1);
334  if (next_part->left_key() < part->right_key()) {
335  return false;
336  }
337  }
338  }
339  return any_text_parts;
340 }
static bool IsTextType(BlobRegionType type)
Definition: blobbox.h:391
void tesseract::ColPartitionSet::Print ( )

Definition at line 576 of file colpartitionset.cpp.

576  {
577  ColPartition_IT it(&parts_);
578  tprintf("Partition set of %d parts, %d good, coverage=%d+%d"
579  " (%d,%d)->(%d,%d)\n",
580  it.length(), good_column_count_, good_coverage_, bad_coverage_,
581  bounding_box_.left(), bounding_box_.bottom(),
582  bounding_box_.right(), bounding_box_.top());
583  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
584  ColPartition* part = it.data();
585  part->Print();
586  }
587 }
inT16 left() const
Definition: rect.h:67
inT16 right() const
Definition: rect.h:74
inT16 top() const
Definition: rect.h:53
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:41
inT16 bottom() const
Definition: rect.h:60
void tesseract::ColPartitionSet::RelinquishParts ( )

Definition at line 70 of file colpartitionset.cpp.

70  {
71  ColPartition_IT it(&parts_);
72  while (!it.empty()) {
73  it.extract();
74  it.forward();
75  }
76 }
ColumnSpanningType tesseract::ColPartitionSet::SpanningType ( int  resolution,
int  left,
int  right,
int  y,
int  left_margin,
int  right_margin,
int *  first_col,
int *  last_col,
int *  first_spanned_col 
)

Definition at line 394 of file colpartitionset.cpp.

400  {
401  *first_col = -1;
402  *last_col = -1;
403  *first_spanned_col = -1;
404  int margin_columns = 0;
405  ColPartition_IT it(&parts_);
406  int col_index = 1;
407  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward(), col_index += 2) {
408  ColPartition* part = it.data();
409  if (part->ColumnContains(left, y)) {
410  // In the default case, first_col is set, but columns_spanned remains
411  // zero, so first_col will get reset in the first column genuinely
412  // spanned, but we can tell the difference from a noise partition
413  // that touches no column.
414  *first_col = col_index;
415  if (part->ColumnContains(right, y)) {
416  // Both within a single column.
417  *last_col = col_index;
418  return CST_FLOWING;
419  }
420  if (left_margin <= part->LeftAtY(y)) {
421  // It completely spans this column.
422  *first_spanned_col = col_index;
423  margin_columns = 1;
424  }
425  } else if (part->ColumnContains(right, y)) {
426  if (*first_col < 0) {
427  // It started in-between.
428  *first_col = col_index - 1;
429  }
430  if (right_margin >= part->RightAtY(y)) {
431  // It completely spans this column.
432  if (margin_columns == 0)
433  *first_spanned_col = col_index;
434  ++margin_columns;
435  }
436  *last_col = col_index;
437  break;
438  } else if (left < part->LeftAtY(y) && right > part->RightAtY(y)) {
439  // Neither left nor right are contained within, so it spans this
440  // column.
441  if (*first_col < 0) {
442  // It started in between the previous column and the current column.
443  *first_col = col_index - 1;
444  }
445  if (margin_columns == 0)
446  *first_spanned_col = col_index;
447  *last_col = col_index;
448  } else if (right < part->LeftAtY(y)) {
449  // We have gone past the end.
450  *last_col = col_index - 1;
451  if (*first_col < 0) {
452  // It must lie completely between columns =>noise.
453  *first_col = col_index - 1;
454  }
455  break;
456  }
457  }
458  if (*first_col < 0)
459  *first_col = col_index - 1; // The last in-between.
460  if (*last_col < 0)
461  *last_col = col_index - 1; // The last in-between.
462  ASSERT_HOST(*first_col >= 0 && *last_col >= 0);
463  ASSERT_HOST(*first_col <= *last_col);
464  if (*first_col == *last_col && right - left < kMinColumnWidth * resolution) {
465  // Neither end was in a column, and it didn't span any, so it lies
466  // entirely between columns, therefore noise.
467  return CST_NOISE;
468  } else if (margin_columns <= 1) {
469  // An exception for headings that stick outside of single-column text.
470  if (margin_columns == 1 && parts_.singleton()) {
471  return CST_HEADING;
472  }
473  // It is a pullout, as left and right were not in the same column, but
474  // it doesn't go to the edge of its start and end.
475  return CST_PULLOUT;
476  }
477  // Its margins went to the edges of first and last columns => heading.
478  return CST_HEADING;
479 }
const int kMinColumnWidth
Definition: colfind.cpp:49
#define ASSERT_HOST(x)
Definition: errcode.h:84
int tesseract::ColPartitionSet::UnmatchedWidth ( ColPartitionSet part_set)

Definition at line 295 of file colpartitionset.cpp.

295  {
296  int total_width = 0;
297  ColPartition_IT it(&part_set->parts_);
298  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
299  ColPartition* part = it.data();
300  if (!BLOBNBOX::IsTextType(part->blob_type())) {
301  continue; // Non-text partitions are irrelevant to column compatibility.
302  }
303  int y = part->MidY();
304  BLOBNBOX_C_IT box_it(part->boxes());
305  for (box_it.mark_cycle_pt(); !box_it.cycled_list(); box_it.forward()) {
306  const TBOX& box = it.data()->bounding_box();
307  // Assume that the whole blob is outside any column iff its x-middle
308  // is outside.
309  int x = (box.left() + box.right()) / 2;
310  ColPartition* col = ColumnContaining(x, y);
311  if (col == NULL)
312  total_width += box.width();
313  }
314  }
315  return total_width;
316 }
ColPartition * ColumnContaining(int x, int y)
#define NULL
Definition: host.h:144
inT16 left() const
Definition: rect.h:67
inT16 width() const
Definition: rect.h:104
Definition: rect.h:29
inT16 right() const
Definition: rect.h:74
static bool IsTextType(BlobRegionType type)
Definition: blobbox.h:391

The documentation for this class was generated from the following files: