21 #ifndef TESSERACT_TEXTORD_BBGRID_H__ 22 #define TESSERACT_TEXTORD_BBGRID_H__ 30 #include "allheaders.h" 43 ICOORD bleft,
int* left,
int* bottom);
46 ICOORD bleft,
int* left,
int* bottom);
48 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
class GridSearch;
79 void GridCoords(
int x,
int y,
int* grid_x,
int* grid_y)
const;
114 void Rotate(
const FCOORD& rotation);
118 IntGrid* NeighbourhoodSum()
const;
131 bool RectMostlyOverThreshold(
const TBOX& rect,
int threshold)
const;
134 bool AnyZeroInRect(
const TBOX& rect)
const;
138 Pix* ThresholdToPix(
int threshold)
const;
158 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
class BBGrid 174 void ClearGridData(
void (*free_method)(BBC*));
181 void InsertBBox(
bool h_spread,
bool v_spread, BBC* bbox);
192 void InsertPixPtBBox(
int left,
int bottom, Pix* pix, BBC* bbox);
197 void RemoveBBox(BBC* bbox);
200 bool RectangleEmpty(
const TBOX& rect);
207 ScrollView* MakeWindow(
int x,
int y,
const char* window_name);
215 void AssertNoDuplicates();
218 virtual void HandleClick(
int x,
int y);
229 return reinterpret_cast<size_t>(ptr) /
sizeof(T);
235 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
class GridSearch {
238 : grid_(grid), unique_mode_(false),
239 previous_return_(
NULL), next_return_(
NULL) {
266 TBOX box = previous_return_->bounding_box();
267 int x_center = (box.
left()+box.
right())/2;
268 int y_center = (box.
top()+box.
bottom())/2;
270 grid_->GridCoords(x_center, y_center, &grid_x, &grid_y);
271 return (x_ == grid_x) && (y_ == grid_y);
291 void StartFullSearch();
293 BBC* NextFullSearch();
297 void StartRadSearch(
int x,
int y,
int max_radius);
300 BBC* NextRadSearch();
310 void StartSideSearch(
int x,
int ymin,
int ymax);
314 BBC* NextSideSearch(
bool right_to_left);
318 void StartVerticalSearch(
int xmin,
int xmax,
int y);
322 BBC* NextVerticalSearch(
bool top_to_bottom);
326 void StartRectSearch(
const TBOX& rect);
328 BBC* NextRectSearch();
334 void RepositionIterator();
338 void CommonStart(
int x,
int y);
362 BBC* previous_return_;
367 unordered_set<BBC*, PtrHash<BBC> > returns_;
374 const BBC* p1 = *
reinterpret_cast<const BBC*
const *
>(void1);
375 const BBC* p2 = *
reinterpret_cast<const BBC*
const *
>(void2);
376 int result = p1->bounding_box().left() - p2->bounding_box().left();
379 result = p1->bounding_box().right() - p2->bounding_box().right();
382 result = p1->bounding_box().bottom() - p2->bounding_box().bottom();
385 return p1->bounding_box().top() - p2->bounding_box().top();
392 const BBC* p1 = *
reinterpret_cast<const BBC*
const *
>(void1);
393 const BBC* p2 = *
reinterpret_cast<const BBC*
const *
>(void2);
394 int result = p2->bounding_box().right() - p1->bounding_box().right();
397 result = p2->bounding_box().left() - p1->bounding_box().left();
400 result = p1->bounding_box().bottom() - p2->bounding_box().bottom();
403 return p1->bounding_box().top() - p2->bounding_box().top();
410 const BBC* p1 = *
reinterpret_cast<const BBC*
const *
>(void1);
411 const BBC* p2 = *
reinterpret_cast<const BBC*
const *
>(void2);
412 int result = p1->bounding_box().bottom() - p2->bounding_box().bottom();
415 result = p1->bounding_box().top() - p2->bounding_box().top();
418 result = p1->bounding_box().left() - p2->bounding_box().left();
421 return p1->bounding_box().right() - p2->bounding_box().right();
427 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
431 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
435 Init(gridsize, bleft, tright);
438 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
446 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
457 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
460 grid_[i].shallow_clear();
466 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
468 void (*free_method)(BBC*)) {
474 BBC_C_IT it(&bb_list);
476 it.add_after_then_move(bb);
478 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
479 free_method(it.data());
488 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
491 TBOX box = bbox->bounding_box();
492 int start_x, start_y, end_x, end_y;
500 for (
int y = start_y; y <= end_y; ++y, grid_index +=
gridwidth_) {
501 for (
int x = start_x; x <= end_x; ++x) {
502 grid_[grid_index + x].add_sorted(SortByBoxLeft<BBC>,
true, bbox);
516 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
518 Pix* pix, BBC* bbox) {
519 int width = pixGetWidth(pix);
520 int height = pixGetHeight(pix);
521 for (
int y = 0; y < height; ++y) {
522 l_uint32* data = pixGetData(pix) + y * pixGetWpl(pix);
523 for (
int x = 0; x < width; ++x) {
524 if (GET_DATA_BIT(data, x)) {
526 add_sorted(SortByBoxLeft<BBC>,
true, bbox);
535 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
537 TBOX box = bbox->bounding_box();
538 int start_x, start_y, end_x, end_y;
542 for (
int y = start_y; y <= end_y; ++y, grid_index +=
gridwidth_) {
543 for (
int x = start_x; x <= end_x; ++x) {
544 BBC_C_IT it(&
grid_[grid_index + x]);
545 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
546 if (it.data() == bbox)
554 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
563 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
582 grid_->HandleClick(sv_event->
x, sv_event->
y);
591 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
593 int x,
int y,
const char* window_name) {
595 #ifndef GRAPHICS_DISABLED 615 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
617 #ifndef GRAPHICS_DISABLED 626 TBOX box = bbox->bounding_box();
627 int left_x = box.
left();
628 int right_x = box.
right();
629 int top_y = box.
top();
630 int bottom_y = box.
bottom();
632 tab_win->
Pen(box_color);
633 tab_win->
Rectangle(left_x, bottom_y, right_x, top_y);
640 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
645 for (BBC_C_IT it(&
grid_[i]); !it.at_last(); it.forward()) {
646 BBC* ptr = it.data();
649 for (it2.forward(); !it2.at_first(); it2.forward()) {
657 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
659 tprintf(
"Click at (%d, %d)\n", x, y);
667 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
671 CommonStart(
grid_->bleft_.x(),
grid_->tright_.y());
677 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
682 while (it_.cycled_list()) {
684 if (x_ >=
grid_->gridwidth_) {
693 TBOX box = previous_return_->bounding_box();
695 }
while (x != x_ || y != y_);
696 return previous_return_;
700 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
706 max_radius_ = max_radius;
715 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
718 while (it_.cycled_list()) {
720 if (rad_index_ >= radius_) {
725 if (radius_ > max_radius_)
731 offset *= radius_ - rad_index_;
733 x_ = x_origin_ + offset.
x();
734 y_ = y_origin_ + offset.
y();
740 }
while (unique_mode_ && returns_.find(previous_return_) != returns_.end());
742 returns_.insert(previous_return_);
743 return previous_return_;
748 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
750 int ymin,
int ymax) {
755 radius_ = ((ymax - ymin) * 2 +
grid_->gridsize_ - 1) /
grid_->gridsize_;
757 CommonStart(x, ymax);
763 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
766 while (it_.cycled_list()) {
768 if (rad_index_ > radius_) {
774 if (x_ < 0 || x_ >=
grid_->gridwidth_)
777 y_ = y_origin_ - rad_index_;
782 }
while (unique_mode_ && returns_.find(previous_return_) != returns_.end());
784 returns_.insert(previous_return_);
785 return previous_return_;
790 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
796 radius_ = (xmax - xmin +
grid_->gridsize_ - 1) /
grid_->gridsize_;
798 CommonStart(xmin, y);
804 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
806 bool top_to_bottom) {
808 while (it_.cycled_list()) {
810 if (rad_index_ > radius_) {
816 if (y_ < 0 || y_ >=
grid_->gridheight_)
819 x_ = x_origin_ + rad_index_;
824 }
while (unique_mode_ && returns_.find(previous_return_) != returns_.end());
826 returns_.insert(previous_return_);
827 return previous_return_;
832 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
838 CommonStart(rect.
left(), rect.
top());
840 &max_radius_, &y_origin_);
844 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
847 while (it_.cycled_list()) {
849 if (x_ > max_radius_) {
858 }
while (!rect_.overlap(previous_return_->bounding_box()) ||
859 (unique_mode_ && returns_.find(previous_return_) != returns_.end()));
861 returns_.insert(previous_return_);
862 return previous_return_;
868 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
870 if (previous_return_ !=
NULL) {
874 BBC* prev_data =
NULL;
875 BBC* new_previous_return =
NULL;
877 for (it_.mark_cycle_pt(); !it_.cycled_list();) {
878 if (it_.data() == previous_return_) {
879 new_previous_return = prev_data;
882 next_return_ = it_.cycled_list() ?
NULL : it_.data();
884 prev_data = it_.data();
888 grid_->RemoveBBox(previous_return_);
889 previous_return_ = new_previous_return;
890 RepositionIterator();
894 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
906 if (!it_.empty() && it_.data() == next_return_) {
910 for (it_.mark_cycle_pt(); !it_.cycled_list(); it_.forward()) {
911 if (it_.data() == previous_return_ ||
912 it_.data_relative(1) == next_return_) {
918 previous_return_ =
NULL;
923 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
925 grid_->GridCoords(x, y, &x_origin_, &y_origin_);
929 previous_return_ =
NULL;
930 next_return_ = it_.empty() ?
NULL : it_.data();
935 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
937 previous_return_ = it_.data();
939 next_return_ = it_.cycled_list() ?
NULL : it_.data();
940 return previous_return_;
944 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
946 previous_return_ =
NULL;
953 template<
class BBC,
class BBC_CLIST,
class BBC_C_IT>
955 it_= &(
grid_->grid_[y_ *
grid_->gridwidth_ + x_]);
961 #endif // TESSERACT_TEXTORD_BBGRID_H__ size_t operator()(const T *ptr) const
void RepositionIterator()
bool ReturnedSeedElement() const
BBC * NextVerticalSearch(bool top_to_bottom)
ScrollView * MakeWindow(int x, int y, const char *window_name)
bool RectangleEmpty(const TBOX &rect)
void InsertBBox(bool h_spread, bool v_spread, BBC *bbox)
void DisplayBoxes(ScrollView *window)
void StartVerticalSearch(int xmin, int xmax, int y)
void Rectangle(int x1, int y1, int x2, int y2)
BBC * NextSideSearch(bool right_to_left)
void Init(int gridsize, const ICOORD &bleft, const ICOORD &tright)
LIST search(LIST list, void *key, int_compare is_equal)
int SortByBoxLeft(const void *void1, const void *void2)
static ICOORD chain_step(int chaindir)
int GridCellValue(int grid_x, int grid_y) const
int SortByBoxBottom(const void *void1, const void *void2)
void InsertPixPtBBox(int left, int bottom, Pix *pix, BBC *bbox)
void StartRadSearch(int x, int y, int max_radius)
IntGrid * CountCellElements()
Pix * TraceBlockOnReducedPix(BLOCK *block, int gridsize, ICOORD bleft, int *left, int *bottom)
void SetUniqueMode(bool mode)
Pix * TraceOutlineOnReducedPix(C_OUTLINE *outline, int gridsize, ICOORD bleft, int *left, int *bottom)
inT16 x() const
access function
GridSearch(BBGrid< BBC, BBC_CLIST, BBC_C_IT > *grid)
void AddEventHandler(SVEventHandler *listener)
Add an Event Listener to this ScrollView Window.
void ClearGridData(void(*free_method)(BBC *))
void SetGridCell(int grid_x, int grid_y, int value)
const ICOORD & bleft() const
void RemoveBBox(BBC *bbox)
int SortRightToLeft(const void *void1, const void *void2)
const ICOORD & tright() const
virtual void HandleClick(int x, int y)
void StartRectSearch(const TBOX &rect)
void Init(int gridsize, const ICOORD &bleft, const ICOORD &tright)
void Notify(const SVEvent *sv_event)
void ClipGridCoords(int *x, int *y) const
inT16 y() const
access_function
void StartSideSearch(int x, int ymin, int ymax)
void GridCoords(int x, int y, int *grid_x, int *grid_y) const
void AssertNoDuplicates()