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