00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020
00021 #ifndef TESSERACT_TEXTORD_BBGRID_H__
00022 #define TESSERACT_TEXTORD_BBGRID_H__
00023
00024 #include "clst.h"
00025 #include "coutln.h"
00026 #include "rect.h"
00027 #include "scrollview.h"
00028
00029
00030
00031 #ifdef HAVE_CONFIG_H
00032 #include "config_auto.h"
00033 #endif
00034
00035 #include "allheaders.h"
00036
00037 class BLOCK;
00038
00039 namespace tesseract {
00040
00041
00042
00043
00044
00045
00046
00047 Pix* TraceOutlineOnReducedPix(C_OUTLINE* outline, int gridsize,
00048 ICOORD bleft, int* left, int* bottom);
00049
00050 Pix* TraceBlockOnReducedPix(BLOCK* block, int gridsize,
00051 ICOORD bleft, int* left, int* bottom);
00052
00053 template<class BBC, class BBC_CLIST, class BBC_C_IT> class GridSearch;
00054
00055
00056
00057 class GridBase {
00058 public:
00059 GridBase();
00060 GridBase(int gridsize, const ICOORD& bleft, const ICOORD& tright);
00061 virtual ~GridBase();
00062
00063
00064
00065 void Init(int gridsize, const ICOORD& bleft, const ICOORD& tright);
00066
00067
00068 int gridsize() const {
00069 return gridsize_;
00070 }
00071 int gridwidth() const {
00072 return gridwidth_;
00073 }
00074 int gridheight() const {
00075 return gridheight_;
00076 }
00077 const ICOORD& bleft() const {
00078 return bleft_;
00079 }
00080 const ICOORD& tright() const {
00081 return tright_;
00082 }
00083
00084 void GridCoords(int x, int y, int* grid_x, int* grid_y) const;
00085
00086
00087 void ClipGridCoords(int* x, int* y) const;
00088
00089 protected:
00090
00091 int gridsize_;
00092 int gridwidth_;
00093 int gridheight_;
00094 int gridbuckets_;
00095 ICOORD bleft_;
00096 ICOORD tright_;
00097
00098 private:
00099 };
00100
00101
00102 class IntGrid : public GridBase {
00103 public:
00104 IntGrid();
00105 IntGrid(int gridsize, const ICOORD& bleft, const ICOORD& tright);
00106 virtual ~IntGrid();
00107
00108
00109
00110 void Init(int gridsize, const ICOORD& bleft, const ICOORD& tright);
00111
00112
00113 void Clear();
00114
00115
00116
00117
00118
00119 void Rotate(const FCOORD& rotation);
00120
00121
00122
00123 IntGrid* NeighbourhoodSum() const;
00124
00125 int GridCellValue(int grid_x, int grid_y) const {
00126 ClipGridCoords(&grid_x, &grid_y);
00127 return grid_[grid_y * gridwidth_ + grid_x];
00128 }
00129 void SetGridCell(int grid_x, int grid_y, int value) {
00130 ASSERT_HOST(grid_x >= 0 && grid_x < gridwidth());
00131 ASSERT_HOST(grid_y >= 0 && grid_y < gridheight());
00132 grid_[grid_y * gridwidth_ + grid_x] = value;
00133 }
00134
00135
00136 bool RectMostlyOverThreshold(const TBOX& rect, int threshold) const;
00137
00138
00139 bool AnyZeroInRect(const TBOX& rect) const;
00140
00141
00142
00143 Pix* ThresholdToPix(int threshold) const;
00144
00145 private:
00146 int* grid_;
00147 };
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 template<class BBC, class BBC_CLIST, class BBC_C_IT> class BBGrid
00164 : public GridBase {
00165 friend class GridSearch<BBC, BBC_CLIST, BBC_C_IT>;
00166 public:
00167 BBGrid();
00168 BBGrid(int gridsize, const ICOORD& bleft, const ICOORD& tright);
00169 virtual ~BBGrid();
00170
00171
00172
00173 void Init(int gridsize, const ICOORD& bleft, const ICOORD& tright);
00174
00175
00176 void Clear();
00177
00178
00179 void ClearGridData(void (*free_method)(BBC*));
00180
00181
00182
00183
00184
00185
00186 void InsertBBox(bool h_spread, bool v_spread, BBC* bbox);
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 void InsertPixPtBBox(int left, int bottom, Pix* pix, BBC* bbox);
00198
00199
00200
00201
00202 void RemoveBBox(BBC* bbox);
00203
00204
00205 bool RectangleEmpty(const TBOX& rect);
00206
00207
00208
00209 IntGrid* CountCellElements();
00210
00211
00212 ScrollView* MakeWindow(int x, int y, const char* window_name);
00213
00214
00215
00216
00217 void DisplayBoxes(ScrollView* window);
00218
00219
00220 void AssertNoDuplicates();
00221
00222
00223 virtual void HandleClick(int x, int y);
00224
00225 protected:
00226 BBC_CLIST* grid_;
00227
00228 private:
00229 };
00230
00231
00232 template<class BBC, class BBC_CLIST, class BBC_C_IT> class GridSearch {
00233 public:
00234 GridSearch(BBGrid<BBC, BBC_CLIST, BBC_C_IT>* grid)
00235 : grid_(grid), unique_mode_(false),
00236 previous_return_(NULL), next_return_(NULL) {
00237 }
00238
00239
00240 int GridX() const {
00241 return x_;
00242 }
00243 int GridY() const {
00244 return y_;
00245 }
00246
00247
00248
00249
00250
00251 void SetUniqueMode(bool mode) {
00252 unique_mode_ = mode;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262 bool ReturnedSeedElement() const {
00263 TBOX box = previous_return_->bounding_box();
00264 int x_center = (box.left()+box.right())/2;
00265 int y_center = (box.top()+box.bottom())/2;
00266 int grid_x, grid_y;
00267 grid_->GridCoords(x_center, y_center, &grid_x, &grid_y);
00268 return (x_ == grid_x) && (y_ == grid_y);
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 void StartFullSearch();
00289
00290 BBC* NextFullSearch();
00291
00292
00293
00294 void StartRadSearch(int x, int y, int max_radius);
00295
00296
00297 BBC* NextRadSearch();
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 void StartSideSearch(int x, int ymin, int ymax);
00308
00309
00310
00311 BBC* NextSideSearch(bool right_to_left);
00312
00313
00314
00315 void StartVerticalSearch(int xmin, int xmax, int y);
00316
00317
00318
00319 BBC* NextVerticalSearch(bool top_to_bottom);
00320
00321
00322
00323 void StartRectSearch(const TBOX& rect);
00324
00325 BBC* NextRectSearch();
00326
00327
00328
00329
00330 void RemoveBBox();
00331 void RepositionIterator();
00332
00333 private:
00334
00335 void CommonStart(int x, int y);
00336
00337 BBC* CommonNext();
00338
00339 BBC* CommonEnd();
00340
00341
00342 void SetIterator();
00343
00344 private:
00345
00346 BBGrid<BBC, BBC_CLIST, BBC_C_IT>* grid_;
00347
00348
00349 int x_origin_;
00350 int y_origin_;
00351 int max_radius_;
00352 int radius_;
00353 int rad_index_;
00354 int rad_dir_;
00355 TBOX rect_;
00356 int x_;
00357 int y_;
00358 bool unique_mode_;
00359 BBC* previous_return_;
00360 BBC* next_return_;
00361
00362 BBC_C_IT it_;
00363
00364 BBC_CLIST returns_;
00365 };
00366
00367
00368 template<class BBC>
00369 int SortByBoxLeft(const void* void1, const void* void2) {
00370
00371 const BBC* p1 = *reinterpret_cast<const BBC* const *>(void1);
00372 const BBC* p2 = *reinterpret_cast<const BBC* const *>(void2);
00373 int result = p1->bounding_box().left() - p2->bounding_box().left();
00374 if (result != 0)
00375 return result;
00376 result = p1->bounding_box().right() - p2->bounding_box().right();
00377 if (result != 0)
00378 return result;
00379 result = p1->bounding_box().bottom() - p2->bounding_box().bottom();
00380 if (result != 0)
00381 return result;
00382 return p1->bounding_box().top() - p2->bounding_box().top();
00383 }
00384
00385
00386 template<class BBC>
00387 int SortRightToLeft(const void* void1, const void* void2) {
00388
00389 const BBC* p1 = *reinterpret_cast<const BBC* const *>(void1);
00390 const BBC* p2 = *reinterpret_cast<const BBC* const *>(void2);
00391 int result = p2->bounding_box().right() - p1->bounding_box().right();
00392 if (result != 0)
00393 return result;
00394 result = p2->bounding_box().left() - p1->bounding_box().left();
00395 if (result != 0)
00396 return result;
00397 result = p1->bounding_box().bottom() - p2->bounding_box().bottom();
00398 if (result != 0)
00399 return result;
00400 return p1->bounding_box().top() - p2->bounding_box().top();
00401 }
00402
00403
00404 template<class BBC>
00405 int SortByBoxBottom(const void* void1, const void* void2) {
00406
00407 const BBC* p1 = *reinterpret_cast<const BBC* const *>(void1);
00408 const BBC* p2 = *reinterpret_cast<const BBC* const *>(void2);
00409 int result = p1->bounding_box().bottom() - p2->bounding_box().bottom();
00410 if (result != 0)
00411 return result;
00412 result = p1->bounding_box().top() - p2->bounding_box().top();
00413 if (result != 0)
00414 return result;
00415 result = p1->bounding_box().left() - p2->bounding_box().left();
00416 if (result != 0)
00417 return result;
00418 return p1->bounding_box().right() - p2->bounding_box().right();
00419 }
00420
00422
00424 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00425 BBGrid<BBC, BBC_CLIST, BBC_C_IT>::BBGrid() : grid_(NULL) {
00426 }
00427
00428 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00429 BBGrid<BBC, BBC_CLIST, BBC_C_IT>::BBGrid(
00430 int gridsize, const ICOORD& bleft, const ICOORD& tright)
00431 : grid_(NULL) {
00432 Init(gridsize, bleft, tright);
00433 }
00434
00435 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00436 BBGrid<BBC, BBC_CLIST, BBC_C_IT>::~BBGrid() {
00437 if (grid_ != NULL)
00438 delete [] grid_;
00439 }
00440
00441
00442
00443 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00444 void BBGrid<BBC, BBC_CLIST, BBC_C_IT>::Init(int gridsize,
00445 const ICOORD& bleft,
00446 const ICOORD& tright) {
00447 GridBase::Init(gridsize, bleft, tright);
00448 if (grid_ != NULL)
00449 delete [] grid_;
00450 grid_ = new BBC_CLIST[gridbuckets_];
00451 }
00452
00453
00454 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00455 void BBGrid<BBC, BBC_CLIST, BBC_C_IT>::Clear() {
00456 for (int i = 0; i < gridbuckets_; ++i) {
00457 grid_[i].shallow_clear();
00458 }
00459 }
00460
00461
00462
00463 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00464 void BBGrid<BBC, BBC_CLIST, BBC_C_IT>::ClearGridData(
00465 void (*free_method)(BBC*)) {
00466 if (grid_ == NULL) return;
00467 GridSearch<BBC, BBC_CLIST, BBC_C_IT> search(this);
00468 search.StartFullSearch();
00469 BBC* bb;
00470 BBC_CLIST bb_list;
00471 BBC_C_IT it(&bb_list);
00472 while ((bb = search.NextFullSearch()) != NULL) {
00473 it.add_after_then_move(bb);
00474 }
00475 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
00476 free_method(it.data());
00477 }
00478 }
00479
00480
00481
00482
00483
00484
00485 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00486 void BBGrid<BBC, BBC_CLIST, BBC_C_IT>::InsertBBox(bool h_spread, bool v_spread,
00487 BBC* bbox) {
00488 TBOX box = bbox->bounding_box();
00489 int start_x, start_y, end_x, end_y;
00490 GridCoords(box.left(), box.bottom(), &start_x, &start_y);
00491 GridCoords(box.right(), box.top(), &end_x, &end_y);
00492 if (!h_spread)
00493 end_x = start_x;
00494 if (!v_spread)
00495 end_y = start_y;
00496 int grid_index = start_y * gridwidth_;
00497 for (int y = start_y; y <= end_y; ++y, grid_index += gridwidth_) {
00498 for (int x = start_x; x <= end_x; ++x) {
00499 grid_[grid_index + x].add_sorted(SortByBoxLeft<BBC>, true, bbox);
00500 }
00501 }
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00514 void BBGrid<BBC, BBC_CLIST, BBC_C_IT>::InsertPixPtBBox(int left, int bottom,
00515 Pix* pix, BBC* bbox) {
00516 int width = pixGetWidth(pix);
00517 int height = pixGetHeight(pix);
00518 for (int y = 0; y < height; ++y) {
00519 l_uint32* data = pixGetData(pix) + y * pixGetWpl(pix);
00520 for (int x = 0; x < width; ++x) {
00521 if (GET_DATA_BIT(data, x)) {
00522 grid_[(bottom + y) * gridwidth_ + x + left].
00523 add_sorted(SortByBoxLeft<BBC>, true, bbox);
00524 }
00525 }
00526 }
00527 }
00528
00529
00530
00531
00532 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00533 void BBGrid<BBC, BBC_CLIST, BBC_C_IT>::RemoveBBox(BBC* bbox) {
00534 TBOX box = bbox->bounding_box();
00535 int start_x, start_y, end_x, end_y;
00536 GridCoords(box.left(), box.bottom(), &start_x, &start_y);
00537 GridCoords(box.right(), box.top(), &end_x, &end_y);
00538 int grid_index = start_y * gridwidth_;
00539 for (int y = start_y; y <= end_y; ++y, grid_index += gridwidth_) {
00540 for (int x = start_x; x <= end_x; ++x) {
00541 BBC_C_IT it(&grid_[grid_index + x]);
00542 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
00543 if (it.data() == bbox)
00544 it.extract();
00545 }
00546 }
00547 }
00548 }
00549
00550
00551 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00552 bool BBGrid<BBC, BBC_CLIST, BBC_C_IT>::RectangleEmpty(const TBOX& rect) {
00553 GridSearch<BBC, BBC_CLIST, BBC_C_IT> rsearch(this);
00554 rsearch.StartRectSearch(rect);
00555 return rsearch.NextRectSearch() == NULL;
00556 }
00557
00558
00559
00560 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00561 IntGrid* BBGrid<BBC, BBC_CLIST, BBC_C_IT>::CountCellElements() {
00562 IntGrid* intgrid = new IntGrid(gridsize(), bleft(), tright());
00563 for (int y = 0; y < gridheight(); ++y) {
00564 for (int x = 0; x < gridwidth(); ++x) {
00565 int cell_count = grid_[y * gridwidth() + x].length();
00566 intgrid->SetGridCell(x, y, cell_count);
00567 }
00568 }
00569 return intgrid;
00570 }
00571
00572
00573 template<class G> class TabEventHandler : public SVEventHandler {
00574 public:
00575 explicit TabEventHandler(G* grid) : grid_(grid) {
00576 }
00577 void Notify(const SVEvent* sv_event) {
00578 if (sv_event->type == SVET_CLICK) {
00579 grid_->HandleClick(sv_event->x, sv_event->y);
00580 }
00581 }
00582 private:
00583 G* grid_;
00584 };
00585
00586
00587
00588 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00589 ScrollView* BBGrid<BBC, BBC_CLIST, BBC_C_IT>::MakeWindow(
00590 int x, int y, const char* window_name) {
00591 ScrollView* tab_win = NULL;
00592 #ifndef GRAPHICS_DISABLED
00593 tab_win = new ScrollView(window_name, x, y,
00594 tright_.x() - bleft_.x(),
00595 tright_.y() - bleft_.y(),
00596 tright_.x() - bleft_.x(),
00597 tright_.y() - bleft_.y(),
00598 true);
00599 TabEventHandler<BBGrid<BBC, BBC_CLIST, BBC_C_IT> >* handler =
00600 new TabEventHandler<BBGrid<BBC, BBC_CLIST, BBC_C_IT> >(this);
00601 tab_win->AddEventHandler(handler);
00602 tab_win->Pen(ScrollView::GREY);
00603 tab_win->Rectangle(0, 0, tright_.x() - bleft_.x(), tright_.y() - bleft_.y());
00604 #endif
00605 return tab_win;
00606 }
00607
00608
00609
00610
00611
00612 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00613 void BBGrid<BBC, BBC_CLIST, BBC_C_IT>::DisplayBoxes(ScrollView* tab_win) {
00614 #ifndef GRAPHICS_DISABLED
00615 tab_win->Pen(ScrollView::BLUE);
00616 tab_win->Brush(ScrollView::NONE);
00617
00618
00619 GridSearch<BBC, BBC_CLIST, BBC_C_IT> gsearch(this);
00620 gsearch.StartFullSearch();
00621 BBC* bbox;
00622 while ((bbox = gsearch.NextFullSearch()) != NULL) {
00623 TBOX box = bbox->bounding_box();
00624 int left_x = box.left();
00625 int right_x = box.right();
00626 int top_y = box.top();
00627 int bottom_y = box.bottom();
00628 ScrollView::Color box_color = bbox->BoxColor();
00629 tab_win->Pen(box_color);
00630 tab_win->Rectangle(left_x, bottom_y, right_x, top_y);
00631 }
00632 tab_win->Update();
00633 #endif
00634 }
00635
00636
00637 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00638 void BBGrid<BBC, BBC_CLIST, BBC_C_IT>::AssertNoDuplicates() {
00639
00640 for (int i = gridwidth_ * gridheight_ - 1; i >= 0; --i) {
00641
00642 for (BBC_C_IT it(&grid_[i]); !it.at_last(); it.forward()) {
00643 BBC* ptr = it.data();
00644 BBC_C_IT it2(it);
00645
00646 for (it2.forward(); !it2.at_first(); it2.forward()) {
00647 ASSERT_HOST(it2.data() != ptr);
00648 }
00649 }
00650 }
00651 }
00652
00653
00654 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00655 void BBGrid<BBC, BBC_CLIST, BBC_C_IT>::HandleClick(int x, int y) {
00656 tprintf("Click at (%d, %d)\n", x, y);
00657 }
00658
00660
00662
00663
00664 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00665 void GridSearch<BBC, BBC_CLIST, BBC_C_IT>::StartFullSearch() {
00666
00667
00668 CommonStart(grid_->bleft_.x(), grid_->tright_.y());
00669 }
00670
00671
00672
00673
00674 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00675 BBC* GridSearch<BBC, BBC_CLIST, BBC_C_IT>::NextFullSearch() {
00676 int x;
00677 int y;
00678 do {
00679 while (it_.cycled_list()) {
00680 ++x_;
00681 if (x_ >= grid_->gridwidth_) {
00682 --y_;
00683 if (y_ < 0)
00684 return CommonEnd();
00685 x_ = 0;
00686 }
00687 SetIterator();
00688 }
00689 CommonNext();
00690 TBOX box = previous_return_->bounding_box();
00691 grid_->GridCoords(box.left(), box.bottom(), &x, &y);
00692 } while (x != x_ || y != y_);
00693 return previous_return_;
00694 }
00695
00696
00697 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00698 void GridSearch<BBC, BBC_CLIST, BBC_C_IT>::StartRadSearch(int x, int y,
00699 int max_radius) {
00700
00701
00702
00703 max_radius_ = max_radius;
00704 radius_ = 0;
00705 rad_index_ = 0;
00706 rad_dir_ = 3;
00707 CommonStart(x, y);
00708 }
00709
00710
00711
00712 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00713 BBC* GridSearch<BBC, BBC_CLIST, BBC_C_IT>::NextRadSearch() {
00714 do {
00715 while (it_.cycled_list()) {
00716 ++rad_index_;
00717 if (rad_index_ >= radius_) {
00718 ++rad_dir_;
00719 rad_index_ = 0;
00720 if (rad_dir_ >= 4) {
00721 ++radius_;
00722 if (radius_ > max_radius_)
00723 return CommonEnd();
00724 rad_dir_ = 0;
00725 }
00726 }
00727 ICOORD offset = C_OUTLINE::chain_step(rad_dir_);
00728 offset *= radius_ - rad_index_;
00729 offset += C_OUTLINE::chain_step(rad_dir_ + 1) * rad_index_;
00730 x_ = x_origin_ + offset.x();
00731 y_ = y_origin_ + offset.y();
00732 if (x_ >= 0 && x_ < grid_->gridwidth_ &&
00733 y_ >= 0 && y_ < grid_->gridheight_)
00734 SetIterator();
00735 }
00736 CommonNext();
00737 } while (unique_mode_ &&
00738 !returns_.add_sorted(SortByBoxLeft<BBC>, true, previous_return_));
00739 return previous_return_;
00740 }
00741
00742
00743
00744 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00745 void GridSearch<BBC, BBC_CLIST, BBC_C_IT>::StartSideSearch(int x,
00746 int ymin, int ymax) {
00747
00748
00749
00750
00751 radius_ = ((ymax - ymin) * 2 + grid_->gridsize_ - 1) / grid_->gridsize_;
00752 rad_index_ = 0;
00753 CommonStart(x, ymax);
00754 }
00755
00756
00757
00758
00759 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00760 BBC* GridSearch<BBC, BBC_CLIST, BBC_C_IT>::NextSideSearch(bool right_to_left) {
00761 do {
00762 while (it_.cycled_list()) {
00763 ++rad_index_;
00764 if (rad_index_ > radius_) {
00765 if (right_to_left)
00766 --x_;
00767 else
00768 ++x_;
00769 rad_index_ = 0;
00770 if (x_ < 0 || x_ >= grid_->gridwidth_)
00771 return CommonEnd();
00772 }
00773 y_ = y_origin_ - rad_index_;
00774 if (y_ >= 0 && y_ < grid_->gridheight_)
00775 SetIterator();
00776 }
00777 CommonNext();
00778 } while (unique_mode_ &&
00779 !returns_.add_sorted(SortByBoxLeft<BBC>, true, previous_return_));
00780 return previous_return_;
00781 }
00782
00783
00784
00785 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00786 void GridSearch<BBC, BBC_CLIST, BBC_C_IT>::StartVerticalSearch(int xmin,
00787 int xmax,
00788 int y) {
00789
00790
00791 radius_ = (xmax - xmin + grid_->gridsize_ - 1) / grid_->gridsize_;
00792 rad_index_ = 0;
00793 CommonStart(xmin, y);
00794 }
00795
00796
00797
00798
00799 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00800 BBC* GridSearch<BBC, BBC_CLIST, BBC_C_IT>::NextVerticalSearch(
00801 bool top_to_bottom) {
00802 do {
00803 while (it_.cycled_list()) {
00804 ++rad_index_;
00805 if (rad_index_ > radius_) {
00806 if (top_to_bottom)
00807 --y_;
00808 else
00809 ++y_;
00810 rad_index_ = 0;
00811 if (y_ < 0 || y_ >= grid_->gridheight_)
00812 return CommonEnd();
00813 }
00814 x_ = x_origin_ + rad_index_;
00815 if (x_ >= 0 && x_ < grid_->gridwidth_)
00816 SetIterator();
00817 }
00818 CommonNext();
00819 } while (unique_mode_ &&
00820 !returns_.add_sorted(SortByBoxLeft<BBC>, true, previous_return_));
00821 return previous_return_;
00822 }
00823
00824
00825
00826 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00827 void GridSearch<BBC, BBC_CLIST, BBC_C_IT>::StartRectSearch(const TBOX& rect) {
00828
00829
00830
00831 rect_ = rect;
00832 CommonStart(rect.left(), rect.top());
00833 grid_->GridCoords(rect.right(), rect.bottom(),
00834 &max_radius_, &y_origin_);
00835 }
00836
00837
00838 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00839 BBC* GridSearch<BBC, BBC_CLIST, BBC_C_IT>::NextRectSearch() {
00840 do {
00841 while (it_.cycled_list()) {
00842 ++x_;
00843 if (x_ > max_radius_) {
00844 --y_;
00845 x_ = x_origin_;
00846 if (y_ < y_origin_)
00847 return CommonEnd();
00848 }
00849 SetIterator();
00850 }
00851 CommonNext();
00852 } while (!rect_.overlap(previous_return_->bounding_box()) ||
00853 (unique_mode_ &&
00854 !returns_.add_sorted(SortByBoxLeft<BBC>, true, previous_return_)));
00855 return previous_return_;
00856 }
00857
00858
00859
00860
00861 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00862 void GridSearch<BBC, BBC_CLIST, BBC_C_IT>::RemoveBBox() {
00863 if (previous_return_ != NULL) {
00864
00865
00866
00867 BBC* prev_data = NULL;
00868 BBC* new_previous_return = NULL;
00869 it_.move_to_first();
00870 for (it_.mark_cycle_pt(); !it_.cycled_list();) {
00871 if (it_.data() == previous_return_) {
00872 new_previous_return = prev_data;
00873 it_.extract();
00874 it_.forward();
00875 next_return_ = it_.cycled_list() ? NULL : it_.data();
00876 } else {
00877 prev_data = it_.data();
00878 it_.forward();
00879 }
00880 }
00881 grid_->RemoveBBox(previous_return_);
00882 previous_return_ = new_previous_return;
00883 RepositionIterator();
00884 }
00885 }
00886
00887 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00888 void GridSearch<BBC, BBC_CLIST, BBC_C_IT>::RepositionIterator() {
00889
00890
00891 returns_.shallow_clear();
00892
00893
00894
00895 it_.move_to_first();
00896
00897
00898
00899 if (!it_.empty() && it_.data() == next_return_) {
00900 it_.mark_cycle_pt();
00901 return;
00902 }
00903 for (it_.mark_cycle_pt(); !it_.cycled_list(); it_.forward()) {
00904 if (it_.data() == previous_return_ ||
00905 it_.data_relative(1) == next_return_) {
00906 CommonNext();
00907 return;
00908 }
00909 }
00910
00911 previous_return_ = NULL;
00912 next_return_ = NULL;
00913 }
00914
00915
00916 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00917 void GridSearch<BBC, BBC_CLIST, BBC_C_IT>::CommonStart(int x, int y) {
00918 grid_->GridCoords(x, y, &x_origin_, &y_origin_);
00919 x_ = x_origin_;
00920 y_ = y_origin_;
00921 SetIterator();
00922 previous_return_ = NULL;
00923 next_return_ = it_.empty() ? NULL : it_.data();
00924 returns_.shallow_clear();
00925 }
00926
00927
00928 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00929 BBC* GridSearch<BBC, BBC_CLIST, BBC_C_IT>::CommonNext() {
00930 previous_return_ = it_.data();
00931 it_.forward();
00932 next_return_ = it_.cycled_list() ? NULL : it_.data();
00933 return previous_return_;
00934 }
00935
00936
00937 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00938 BBC* GridSearch<BBC, BBC_CLIST, BBC_C_IT>::CommonEnd() {
00939 previous_return_ = NULL;
00940 next_return_ = NULL;
00941 return NULL;
00942 }
00943
00944
00945
00946 template<class BBC, class BBC_CLIST, class BBC_C_IT>
00947 void GridSearch<BBC, BBC_CLIST, BBC_C_IT>::SetIterator() {
00948 it_= &(grid_->grid_[y_ * grid_->gridwidth_ + x_]);
00949 it_.mark_cycle_pt();
00950 }
00951
00952 }
00953
00954 #endif // TESSERACT_TEXTORD_BBGRID_H__