00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00019
00020 #ifndef TESSERACT_TEXTORD_TABVECTOR_H__
00021 #define TESSERACT_TEXTORD_TABVECTOR_H__
00022
00023 #include "clst.h"
00024 #include "elst.h"
00025 #include "elst2.h"
00026 #include "rect.h"
00027 #include "bbgrid.h"
00028
00029 #undef TA_CENTER
00030
00031 class BLOBNBOX;
00032 class ScrollView;
00033
00034 CLISTIZEH(BLOBNBOX)
00035
00036 namespace tesseract {
00037
00038
00039
00040 enum TabAlignment {
00041 TA_LEFT_ALIGNED,
00042 TA_LEFT_RAGGED,
00043 TA_CENTER,
00044 TA_RIGHT_ALIGNED,
00045 TA_RIGHT_RAGGED,
00046 TA_SEPARATOR,
00047 TA_COUNT
00048 };
00049
00050
00051
00052 class TabFind;
00053 class TabVector;
00054 class TabConstraint;
00055 typedef BBGrid<BLOBNBOX, BLOBNBOX_CLIST, BLOBNBOX_C_IT> BlobGrid;
00056
00057 ELIST2IZEH(TabVector)
00058 CLISTIZEH(TabVector)
00059 ELISTIZEH(TabConstraint)
00060
00061
00062
00063
00064
00065
00066
00067 class TabConstraint : public ELIST_LINK {
00068 public:
00069 TabConstraint() {
00070
00071
00072
00073 }
00074
00075
00076 static void CreateConstraint(TabVector* vector, bool is_top);
00077
00078
00079 static bool CompatibleConstraints(TabConstraint_LIST* list1,
00080 TabConstraint_LIST* list2);
00081
00082
00083
00084 static void MergeConstraints(TabConstraint_LIST* list1,
00085 TabConstraint_LIST* list2);
00086
00087
00088
00089 static void ApplyConstraints(TabConstraint_LIST* constraints);
00090
00091 private:
00092 TabConstraint(TabVector* vector, bool is_top);
00093
00094
00095 static void GetConstraints(TabConstraint_LIST* constraints,
00096 int* y_min, int* y_max);
00097
00098
00099 TabVector* vector_;
00100
00101 bool is_top_;
00102
00103 int y_min_;
00104 int y_max_;
00105 };
00106
00107
00108
00109 class TabVector : public ELIST2_LINK {
00110 public:
00111 TabVector() {
00112
00113
00114 }
00115 ~TabVector();
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 static TabVector* FitVector(TabAlignment alignment, ICOORD vertical,
00126 int extended_start_y, int extended_end_y,
00127 BLOBNBOX_CLIST* good_points,
00128 int* vertical_x, int* vertical_y);
00129
00130
00131
00132
00133 TabVector(const TabVector& src, TabAlignment alignment,
00134 const ICOORD& vertical_skew, BLOBNBOX* blob);
00135
00136
00137 const ICOORD& startpt() const {
00138 return startpt_;
00139 }
00140 const ICOORD& endpt() const {
00141 return endpt_;
00142 }
00143 int extended_ymax() const {
00144 return extended_ymax_;
00145 }
00146 int extended_ymin() const {
00147 return extended_ymin_;
00148 }
00149 int sort_key() const {
00150 return sort_key_;
00151 }
00152 void set_top_constraints(TabConstraint_LIST* constraints) {
00153 top_constraints_ = constraints;
00154 }
00155 void set_bottom_constraints(TabConstraint_LIST* constraints) {
00156 bottom_constraints_ = constraints;
00157 }
00158 TabVector_CLIST* partners() {
00159 return &partners_;
00160 }
00161
00162
00163
00164
00165 int XAtY(int y) const {
00166 int height = endpt_.y() - startpt_.y();
00167 if (height != 0)
00168 return (y - startpt_.y()) * (endpt_.x() - startpt_.x()) / height +
00169 startpt_.x();
00170 else
00171 return startpt_.x();
00172 }
00173
00174
00175 int VOverlap(const TabVector& other) const {
00176 return MIN(other.endpt_.y(), endpt_.y()) -
00177 MAX(other.startpt_.y(), startpt_.y());
00178 }
00179
00180 int VOverlap(int top_y, int bottom_y) const {
00181 return MIN(top_y, endpt_.y()) - MAX(bottom_y, startpt_.y());
00182 }
00183
00184 int ExtendedOverlap(int top_y, int bottom_y) const {
00185 return MIN(top_y, extended_ymax_) - MAX(bottom_y, extended_ymin_);
00186 }
00187
00188
00189 bool IsLeftTab() const {
00190 return alignment_ == TA_LEFT_ALIGNED || alignment_ == TA_LEFT_RAGGED;
00191 }
00192
00193 bool IsRightTab() const {
00194 return alignment_ == TA_RIGHT_ALIGNED || alignment_ == TA_RIGHT_RAGGED;
00195 }
00196
00197 bool IsSeparator() const {
00198 return alignment_ == TA_SEPARATOR;
00199 }
00200
00201 bool IsRagged() const {
00202 return alignment_ == TA_LEFT_RAGGED || alignment_ == TA_RIGHT_RAGGED;
00203 }
00204
00205
00206
00207 bool IsLeftOf(const TabVector& other) const {
00208 return sort_key_ < other.sort_key_;
00209 }
00210
00211
00212 bool Partnerless() {
00213 return partners_.empty();
00214 }
00215
00216
00217 int BoxCount() {
00218 return boxes_.length();
00219 }
00220
00221
00222 void Freeze() {
00223 boxes_.shallow_clear();
00224 }
00225
00226
00227 void XYFlip() {
00228 int x = startpt_.y();
00229 startpt_.set_y(startpt_.x());
00230 startpt_.set_x(x);
00231 x = endpt_.y();
00232 endpt_.set_y(endpt_.x());
00233 endpt_.set_x(x);
00234 }
00235
00236
00237 static int SortKey(const ICOORD& vertical, int x, int y) {
00238 ICOORD pt(x, y);
00239 return pt * vertical;
00240 }
00241
00242
00243 static int XAtY(const ICOORD& vertical, int sort_key, int y) {
00244 if (vertical.y() != 0)
00245 return (vertical.x() * y + sort_key) / vertical.y();
00246 else
00247 return sort_key;
00248 }
00249
00250
00251 static int SortVectorsByKey(const void* v1, const void* v2) {
00252 const TabVector* tv1 = *reinterpret_cast<const TabVector* const *>(v1);
00253 const TabVector* tv2 = *reinterpret_cast<const TabVector* const *>(v2);
00254 return tv1->sort_key_ - tv2->sort_key_;
00255 }
00256
00257
00258
00259
00260
00261 void ExtendToBox(BLOBNBOX* blob);
00262
00263
00264 void SetYStart(int start_y);
00265
00266 void SetYEnd(int end_y);
00267
00268
00269 void Rotate(const FCOORD& rotation);
00270
00271
00272
00273 void SetupConstraints();
00274
00275
00276 void SetupPartnerConstraints();
00277
00278
00279 void SetupPartnerConstraints(TabVector* partner);
00280
00281
00282 void ApplyConstraints();
00283
00284
00285 static void MergeSimilarTabVectors(const ICOORD& vertical,
00286 TabVector_LIST* vectors, BlobGrid* grid);
00287
00288
00289
00290 bool SimilarTo(const ICOORD& vertical,
00291 const TabVector& other, BlobGrid* grid) const;
00292
00293
00294 void MergeWith(const ICOORD& vertical, TabVector* other);
00295
00296
00297
00298
00299
00300 void AddPartner(TabVector* partner);
00301
00302
00303 bool IsAPartner(const TabVector* other);
00304
00305
00306 void Print(const char* prefix);
00307
00308
00309 void Debug(const char* prefix);
00310
00311
00312 void Display(ScrollView* tab_win);
00313
00314
00315 void FitAndEvaluateIfNeeded(const ICOORD& vertical, TabFind* finder);
00316
00317
00318
00319
00320
00321
00322
00323 void Evaluate(const ICOORD& vertical, TabFind* finder);
00324
00325
00326
00327 bool Fit(ICOORD vertical, bool force_parallel);
00328
00329
00330
00331 TabVector* VerticalTextlinePartner();
00332
00333 private:
00334
00335
00336 TabVector(int extended_ymin, int extended_ymax,
00337 TabAlignment alignment, BLOBNBOX_CLIST* boxes);
00338
00339
00340
00341
00342 void Delete(TabVector* replacement);
00343
00344 private:
00345
00346 ICOORD startpt_;
00347
00348 ICOORD endpt_;
00349
00350 int extended_ymin_;
00351
00352 int extended_ymax_;
00353
00354 int sort_key_;
00355
00356 int percent_score_;
00357
00358 bool needs_refit_;
00359
00360 bool needs_evaluation_;
00361
00362 TabAlignment alignment_;
00363
00364 BLOBNBOX_CLIST boxes_;
00365
00366 TabVector_CLIST partners_;
00367
00368
00369 TabConstraint_LIST* top_constraints_;
00370 TabConstraint_LIST* bottom_constraints_;
00371 };
00372
00373 }
00374
00375 #endif // TESSERACT_TEXTORD_TABVECTOR_H__
00376
00377