tesseract  4.00.00dev
tesseract::TabVector Class Reference

#include <tabvector.h>

Inheritance diagram for tesseract::TabVector:
ELIST2_LINK

Public Member Functions

 TabVector ()
 
 ~TabVector ()
 
 TabVector (const TabVector &src, TabAlignment alignment, const ICOORD &vertical_skew, BLOBNBOX *blob)
 
TabVectorShallowCopy () const
 
const ICOORDstartpt () const
 
const ICOORDendpt () const
 
int extended_ymax () const
 
int extended_ymin () const
 
int sort_key () const
 
int mean_width () const
 
void set_top_constraints (TabConstraint_LIST *constraints)
 
void set_bottom_constraints (TabConstraint_LIST *constraints)
 
TabVector_CLIST * partners ()
 
void set_startpt (const ICOORD &start)
 
void set_endpt (const ICOORD &end)
 
bool intersects_other_lines () const
 
void set_intersects_other_lines (bool value)
 
int XAtY (int y) const
 
int VOverlap (const TabVector &other) const
 
int VOverlap (int top_y, int bottom_y) const
 
int ExtendedOverlap (int top_y, int bottom_y) const
 
bool IsLeftTab () const
 
bool IsRightTab () const
 
bool IsSeparator () const
 
bool IsCenterTab () const
 
bool IsRagged () const
 
bool IsLeftOf (const TabVector &other) const
 
bool Partnerless ()
 
int BoxCount ()
 
void Freeze ()
 
void XYFlip ()
 
void ReflectInYAxis ()
 
void ExtendToBox (BLOBNBOX *blob)
 
void SetYStart (int start_y)
 
void SetYEnd (int end_y)
 
void Rotate (const FCOORD &rotation)
 
void SetupConstraints ()
 
void SetupPartnerConstraints ()
 
void SetupPartnerConstraints (TabVector *partner)
 
void ApplyConstraints ()
 
bool SimilarTo (const ICOORD &vertical, const TabVector &other, BlobGrid *grid) const
 
void MergeWith (const ICOORD &vertical, TabVector *other)
 
void AddPartner (TabVector *partner)
 
bool IsAPartner (const TabVector *other)
 
void Print (const char *prefix)
 
void Debug (const char *prefix)
 
void Display (ScrollView *tab_win)
 
void FitAndEvaluateIfNeeded (const ICOORD &vertical, TabFind *finder)
 
void Evaluate (const ICOORD &vertical, TabFind *finder)
 
bool Fit (ICOORD vertical, bool force_parallel)
 
TabVectorVerticalTextlinePartner ()
 
TabVectorGetSinglePartner ()
 
- Public Member Functions inherited from ELIST2_LINK
 ELIST2_LINK ()
 
 ELIST2_LINK (const ELIST2_LINK &)
 
void operator= (const ELIST2_LINK &)
 

Static Public Member Functions

static TabVectorFitVector (TabAlignment alignment, ICOORD vertical, int extended_start_y, int extended_end_y, BLOBNBOX_CLIST *good_points, int *vertical_x, int *vertical_y)
 
static int SortKey (const ICOORD &vertical, int x, int y)
 
static int XAtY (const ICOORD &vertical, int sort_key, int y)
 
static int SortVectorsByKey (const void *v1, const void *v2)
 
static void MergeSimilarTabVectors (const ICOORD &vertical, TabVector_LIST *vectors, BlobGrid *grid)
 

Detailed Description

Definition at line 111 of file tabvector.h.

Constructor & Destructor Documentation

◆ TabVector() [1/2]

tesseract::TabVector::TabVector ( )
inline

Definition at line 113 of file tabvector.h.

113  {
114  // TODO(rays) fix this in elst.h line 1076, where it should use the
115  // copy constructor instead of operator=.
116  }

◆ ~TabVector()

tesseract::TabVector::~TabVector ( )

Definition at line 170 of file tabvector.cpp.

170  {
171 }

◆ TabVector() [2/2]

tesseract::TabVector::TabVector ( const TabVector src,
TabAlignment  alignment,
const ICOORD vertical_skew,
BLOBNBOX blob 
)

Definition at line 204 of file tabvector.cpp.

206  : extended_ymin_(src.extended_ymin_), extended_ymax_(src.extended_ymax_),
207  sort_key_(0), percent_score_(0), mean_width_(0),
208  needs_refit_(true), needs_evaluation_(true), intersects_other_lines_(false),
209  alignment_(alignment),
210  top_constraints_(NULL), bottom_constraints_(NULL) {
211  BLOBNBOX_C_IT it(&boxes_);
212  it.add_to_end(blob);
213  TBOX box = blob->bounding_box();
214  if (IsLeftTab()) {
215  startpt_ = box.botleft();
216  endpt_ = box.topleft();
217  } else {
218  startpt_ = box.botright();
219  endpt_ = box.topright();
220  }
221  sort_key_ = SortKey(vertical_skew,
222  (startpt_.x() + endpt_.x()) / 2,
223  (startpt_.y() + endpt_.y()) / 2);
224  if (textord_debug_tabfind > 3)
225  Print("Constructed a new tab vector:");
226 }
inT16 x() const
access function
Definition: points.h:52
int textord_debug_tabfind
Definition: alignedblob.cpp:27
inT16 y() const
access_function
Definition: points.h:56
ICOORD topleft() const
Definition: rect.h:96
const ICOORD & topright() const
Definition: rect.h:100
Definition: rect.h:30
bool IsLeftTab() const
Definition: tabvector.h:213
ICOORD botright() const
Definition: rect.h:92
void Print(const char *prefix)
Definition: tabvector.cpp:525
const ICOORD & botleft() const
Definition: rect.h:88
const TBOX & bounding_box() const
Definition: blobbox.h:215
static int SortKey(const ICOORD &vertical, int x, int y)
Definition: tabvector.h:280

Member Function Documentation

◆ AddPartner()

void tesseract::TabVector::AddPartner ( TabVector partner)

Definition at line 492 of file tabvector.cpp.

492  {
493  if (IsSeparator() || partner->IsSeparator())
494  return;
495  TabVector_C_IT it(&partners_);
496  if (!it.empty()) {
497  it.move_to_last();
498  if (it.data() == partner)
499  return;
500  }
501  it.add_after_then_move(partner);
502 }
bool IsSeparator() const
Definition: tabvector.h:221

◆ ApplyConstraints()

void tesseract::TabVector::ApplyConstraints ( )

Definition at line 353 of file tabvector.cpp.

353  {
354  if (top_constraints_ != NULL)
355  TabConstraint::ApplyConstraints(top_constraints_);
356  if (bottom_constraints_ != NULL)
357  TabConstraint::ApplyConstraints(bottom_constraints_);
358 }
static void ApplyConstraints(TabConstraint_LIST *constraints)
Definition: tabvector.cpp:119

◆ BoxCount()

int tesseract::TabVector::BoxCount ( )
inline

Definition at line 245 of file tabvector.h.

245  {
246  return boxes_.length();
247  }

◆ Debug()

void tesseract::TabVector::Debug ( const char *  prefix)

Definition at line 535 of file tabvector.cpp.

535  {
536  Print(prefix);
537  BLOBNBOX_C_IT it(&boxes_);
538  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
539  BLOBNBOX* bbox = it.data();
540  const TBOX& box = bbox->bounding_box();
541  tprintf("Box at (%d,%d)->(%d,%d)\n",
542  box.left(), box.bottom(), box.right(), box.top());
543  }
544 }
#define tprintf(...)
Definition: tprintf.h:31
inT16 left() const
Definition: rect.h:68
inT16 top() const
Definition: rect.h:54
Definition: rect.h:30
inT16 right() const
Definition: rect.h:75
inT16 bottom() const
Definition: rect.h:61
void Print(const char *prefix)
Definition: tabvector.cpp:525
const TBOX & bounding_box() const
Definition: blobbox.h:215

◆ Display()

void tesseract::TabVector::Display ( ScrollView tab_win)

Definition at line 547 of file tabvector.cpp.

547  {
548 #ifndef GRAPHICS_DISABLED
550  tab_win->Pen(ScrollView::BLUE);
551  else if (alignment_ == TA_LEFT_ALIGNED)
552  tab_win->Pen(ScrollView::LIME_GREEN);
553  else if (alignment_ == TA_LEFT_RAGGED)
554  tab_win->Pen(ScrollView::DARK_GREEN);
555  else if (alignment_ == TA_RIGHT_ALIGNED)
556  tab_win->Pen(ScrollView::PINK);
557  else if (alignment_ == TA_RIGHT_RAGGED)
558  tab_win->Pen(ScrollView::CORAL);
559  else
560  tab_win->Pen(ScrollView::WHITE);
561  tab_win->Line(startpt_.x(), startpt_.y(), endpt_.x(), endpt_.y());
562  tab_win->Pen(ScrollView::GREY);
563  tab_win->Line(startpt_.x(), startpt_.y(), startpt_.x(), extended_ymin_);
564  tab_win->Line(endpt_.x(), extended_ymax_, endpt_.x(), endpt_.y());
565  char score_buf[64];
566  snprintf(score_buf, sizeof(score_buf), "%d", percent_score_);
567  tab_win->TextAttributes("Times", 50, false, false, false);
568  tab_win->Text(startpt_.x(), startpt_.y(), score_buf);
569 #endif
570 }
void Line(int x1, int y1, int x2, int y2)
Definition: scrollview.cpp:538
bool textord_debug_printable
Definition: alignedblob.cpp:33
inT16 x() const
access function
Definition: points.h:52
inT16 y() const
access_function
Definition: points.h:56
void Text(int x, int y, const char *mystring)
Definition: scrollview.cpp:658
void Pen(Color color)
Definition: scrollview.cpp:726
void TextAttributes(const char *font, int pixel_size, bool bold, bool italic, bool underlined)
Definition: scrollview.cpp:641

◆ endpt()

const ICOORD& tesseract::TabVector::endpt ( ) const
inline

Definition at line 149 of file tabvector.h.

149  {
150  return endpt_;
151  }

◆ Evaluate()

void tesseract::TabVector::Evaluate ( const ICOORD vertical,
TabFind finder 
)

Definition at line 587 of file tabvector.cpp.

587  {
588  bool debug = false;
589  needs_evaluation_ = false;
590  int length = endpt_.y() - startpt_.y();
591  if (length == 0 || boxes_.empty()) {
592  percent_score_ = 0;
593  Print("Zero length in evaluate");
594  return;
595  }
596  // Compute the mean box height.
597  BLOBNBOX_C_IT it(&boxes_);
598  int mean_height = 0;
599  int height_count = 0;
600  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
601  BLOBNBOX* bbox = it.data();
602  const TBOX& box = bbox->bounding_box();
603  int height = box.height();
604  mean_height += height;
605  ++height_count;
606  }
607  if (height_count > 0) mean_height /= height_count;
608  int max_gutter = kGutterMultiple * mean_height;
609  if (IsRagged()) {
610  // Ragged edges face a tougher test in that the gap must always be within
611  // the height of the blob.
612  max_gutter = kGutterToNeighbourRatio * mean_height;
613  }
614 
615  STATS gutters(0, max_gutter + 1);
616  // Evaluate the boxes for their goodness, calculating the coverage as we go.
617  // Remove boxes that are not good and shorten the list to the first and
618  // last good boxes.
619  int num_deleted_boxes = 0;
620  bool text_on_image = false;
621  int good_length = 0;
622  const TBOX* prev_good_box = NULL;
623  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
624  BLOBNBOX* bbox = it.data();
625  const TBOX& box = bbox->bounding_box();
626  int mid_y = (box.top() + box.bottom()) / 2;
627  if (TabFind::WithinTestRegion(2, XAtY(box.bottom()), box.bottom())) {
628  if (!debug) {
629  tprintf("After already deleting %d boxes, ", num_deleted_boxes);
630  Print("Starting evaluation");
631  }
632  debug = true;
633  }
634  // A good box is one where the nearest neighbour on the inside is closer
635  // than half the distance to the nearest neighbour on the outside
636  // (of the putative column).
637  bool left = IsLeftTab();
638  int tab_x = XAtY(mid_y);
639  int gutter_width;
640  int neighbour_gap;
641  finder->GutterWidthAndNeighbourGap(tab_x, mean_height, max_gutter, left,
642  bbox, &gutter_width, &neighbour_gap);
643  if (debug) {
644  tprintf("Box (%d,%d)->(%d,%d) has gutter %d, ndist %d\n",
645  box.left(), box.bottom(), box.right(), box.top(),
646  gutter_width, neighbour_gap);
647  }
648  // Now we can make the test.
649  if (neighbour_gap * kGutterToNeighbourRatio <= gutter_width) {
650  // A good box contributes its height to the good_length.
651  good_length += box.top() - box.bottom();
652  gutters.add(gutter_width, 1);
653  // Two good boxes together contribute the gap between them
654  // to the good_length as well, as long as the gap is not
655  // too big.
656  if (prev_good_box != NULL) {
657  int vertical_gap = box.bottom() - prev_good_box->top();
658  double size1 = sqrt(static_cast<double>(prev_good_box->area()));
659  double size2 = sqrt(static_cast<double>(box.area()));
660  if (vertical_gap < kMaxFillinMultiple * MIN(size1, size2))
661  good_length += vertical_gap;
662  if (debug) {
663  tprintf("Box and prev good, gap=%d, target %g, goodlength=%d\n",
664  vertical_gap, kMaxFillinMultiple * MIN(size1, size2),
665  good_length);
666  }
667  } else {
668  // Adjust the start to the first good box.
669  SetYStart(box.bottom());
670  }
671  prev_good_box = &box;
672  if (bbox->flow() == BTFT_TEXT_ON_IMAGE)
673  text_on_image = true;
674  } else {
675  // Get rid of boxes that are not good.
676  if (debug) {
677  tprintf("Bad Box (%d,%d)->(%d,%d) with gutter %d, ndist %d\n",
678  box.left(), box.bottom(), box.right(), box.top(),
679  gutter_width, neighbour_gap);
680  }
681  it.extract();
682  ++num_deleted_boxes;
683  }
684  }
685  if (debug) {
686  Print("Evaluating:");
687  }
688  // If there are any good boxes, do it again, except this time get rid of
689  // boxes that have a gutter that is a small fraction of the mean gutter.
690  // This filters out ends that run into a coincidental gap in the text.
691  int search_top = endpt_.y();
692  int search_bottom = startpt_.y();
693  int median_gutter = IntCastRounded(gutters.median());
694  if (gutters.get_total() > 0) {
695  prev_good_box = NULL;
696  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
697  BLOBNBOX* bbox = it.data();
698  const TBOX& box = bbox->bounding_box();
699  int mid_y = (box.top() + box.bottom()) / 2;
700  // A good box is one where the gutter width is at least some constant
701  // fraction of the mean gutter width.
702  bool left = IsLeftTab();
703  int tab_x = XAtY(mid_y);
704  int max_gutter = kGutterMultiple * mean_height;
705  if (IsRagged()) {
706  // Ragged edges face a tougher test in that the gap must always be
707  // within the height of the blob.
708  max_gutter = kGutterToNeighbourRatio * mean_height;
709  }
710  int gutter_width;
711  int neighbour_gap;
712  finder->GutterWidthAndNeighbourGap(tab_x, mean_height, max_gutter, left,
713  bbox, &gutter_width, &neighbour_gap);
714  // Now we can make the test.
715  if (gutter_width >= median_gutter * kMinGutterFraction) {
716  if (prev_good_box == NULL) {
717  // Adjust the start to the first good box.
718  SetYStart(box.bottom());
719  search_bottom = box.top();
720  }
721  prev_good_box = &box;
722  search_top = box.bottom();
723  } else {
724  // Get rid of boxes that are not good.
725  if (debug) {
726  tprintf("Bad Box (%d,%d)->(%d,%d) with gutter %d, mean gutter %d\n",
727  box.left(), box.bottom(), box.right(), box.top(),
728  gutter_width, median_gutter);
729  }
730  it.extract();
731  ++num_deleted_boxes;
732  }
733  }
734  }
735  // If there has been a good box, adjust the end.
736  if (prev_good_box != NULL) {
737  SetYEnd(prev_good_box->top());
738  // Compute the percentage of the vector that is occupied by good boxes.
739  int length = endpt_.y() - startpt_.y();
740  percent_score_ = 100 * good_length / length;
741  if (num_deleted_boxes > 0) {
742  needs_refit_ = true;
743  FitAndEvaluateIfNeeded(vertical, finder);
744  if (boxes_.empty())
745  return;
746  }
747  // Test the gutter over the whole vector, instead of just at the boxes.
748  int required_shift;
749  if (search_bottom > search_top) {
750  search_bottom = startpt_.y();
751  search_top = endpt_.y();
752  }
753  double min_gutter_width = kLineCountReciprocal / boxes_.length();
754  min_gutter_width += IsRagged() ? kMinRaggedGutter : kMinAlignedGutter;
755  min_gutter_width *= mean_height;
756  int max_gutter_width = IntCastRounded(min_gutter_width) + 1;
757  if (median_gutter > max_gutter_width)
758  max_gutter_width = median_gutter;
759  int gutter_width = finder->GutterWidth(search_bottom, search_top, *this,
760  text_on_image, max_gutter_width,
761  &required_shift);
762  if (gutter_width < min_gutter_width) {
763  if (debug) {
764  tprintf("Rejecting bad tab Vector with %d gutter vs %g min\n",
765  gutter_width, min_gutter_width);
766  }
767  boxes_.shallow_clear();
768  percent_score_ = 0;
769  } else if (debug) {
770  tprintf("Final gutter %d, vs limit of %g, required shift = %d\n",
771  gutter_width, min_gutter_width, required_shift);
772  }
773  } else {
774  // There are no good boxes left, so score is 0.
775  percent_score_ = 0;
776  }
777 
778  if (debug) {
779  Print("Evaluation complete:");
780  }
781 }
const double kLineCountReciprocal
Definition: tabvector.cpp:51
const int kMaxFillinMultiple
Definition: tabvector.cpp:47
inT32 area() const
Definition: rect.h:118
bool IsRagged() const
Definition: tabvector.h:229
#define tprintf(...)
Definition: tprintf.h:31
const double kMinGutterFraction
Definition: tabvector.cpp:49
int IntCastRounded(double x)
Definition: helpers.h:179
inT16 left() const
Definition: rect.h:68
inT16 y() const
access_function
Definition: points.h:56
const double kMinAlignedGutter
Definition: tabvector.cpp:53
void SetYStart(int start_y)
Definition: tabvector.cpp:270
static bool WithinTestRegion(int detail_level, int x, int y)
inT16 top() const
Definition: rect.h:54
const double kMinRaggedGutter
Definition: tabvector.cpp:55
void FitAndEvaluateIfNeeded(const ICOORD &vertical, TabFind *finder)
Definition: tabvector.cpp:573
Definition: rect.h:30
bool IsLeftTab() const
Definition: tabvector.h:213
const int kGutterToNeighbourRatio
Definition: tabvector.cpp:40
#define MIN(x, y)
Definition: ndminx.h:28
int XAtY(int y) const
Definition: tabvector.h:189
inT16 height() const
Definition: rect.h:104
inT16 right() const
Definition: rect.h:75
Definition: statistc.h:33
inT16 bottom() const
Definition: rect.h:61
void Print(const char *prefix)
Definition: tabvector.cpp:525
void SetYEnd(int end_y)
Definition: tabvector.cpp:275
const int kGutterMultiple
Definition: tabvector.cpp:38
const TBOX & bounding_box() const
Definition: blobbox.h:215
BlobTextFlowType flow() const
Definition: blobbox.h:280

◆ extended_ymax()

int tesseract::TabVector::extended_ymax ( ) const
inline

Definition at line 152 of file tabvector.h.

152  {
153  return extended_ymax_;
154  }

◆ extended_ymin()

int tesseract::TabVector::extended_ymin ( ) const
inline

Definition at line 155 of file tabvector.h.

155  {
156  return extended_ymin_;
157  }

◆ ExtendedOverlap()

int tesseract::TabVector::ExtendedOverlap ( int  top_y,
int  bottom_y 
) const
inline

Definition at line 208 of file tabvector.h.

208  {
209  return MIN(top_y, extended_ymax_) - MAX(bottom_y, extended_ymin_);
210  }
#define MAX(x, y)
Definition: ndminx.h:24
#define MIN(x, y)
Definition: ndminx.h:28

◆ ExtendToBox()

void tesseract::TabVector::ExtendToBox ( BLOBNBOX blob)

Definition at line 246 of file tabvector.cpp.

246  {
247  TBOX new_box = new_blob->bounding_box();
248  BLOBNBOX_C_IT it(&boxes_);
249  if (!it.empty()) {
250  BLOBNBOX* blob = it.data();
251  TBOX box = blob->bounding_box();
252  while (!it.at_last() && box.top() <= new_box.top()) {
253  if (blob == new_blob)
254  return; // We have it already.
255  it.forward();
256  blob = it.data();
257  box = blob->bounding_box();
258  }
259  if (box.top() >= new_box.top()) {
260  it.add_before_stay_put(new_blob);
261  needs_refit_ = true;
262  return;
263  }
264  }
265  needs_refit_ = true;
266  it.add_after_stay_put(new_blob);
267 }
inT16 top() const
Definition: rect.h:54
Definition: rect.h:30
const TBOX & bounding_box() const
Definition: blobbox.h:215

◆ Fit()

bool tesseract::TabVector::Fit ( ICOORD  vertical,
bool  force_parallel 
)

Definition at line 788 of file tabvector.cpp.

788  {
789  needs_refit_ = false;
790  if (boxes_.empty()) {
791  // Don't refit something with no boxes, as that only happens
792  // in Evaluate, and we don't want to end up with a zero vector.
793  if (!force_parallel)
794  return false;
795  // If we are forcing parallel, then we just need to set the sort_key_.
796  ICOORD midpt = startpt_;
797  midpt += endpt_;
798  midpt /= 2;
799  sort_key_ = SortKey(vertical, midpt.x(), midpt.y());
800  return startpt_.y() != endpt_.y();
801  }
802  if (!force_parallel && !IsRagged()) {
803  // Use a fitted line as the vertical.
804  DetLineFit linepoints;
805  BLOBNBOX_C_IT it(&boxes_);
806  // Fit a line to all the boxes in the list.
807  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
808  BLOBNBOX* bbox = it.data();
809  const TBOX& box = bbox->bounding_box();
810  int x1 = IsRightTab() ? box.right() : box.left();
811  ICOORD boxpt(x1, box.bottom());
812  linepoints.Add(boxpt);
813  if (it.at_last()) {
814  ICOORD top_pt(x1, box.top());
815  linepoints.Add(top_pt);
816  }
817  }
818  linepoints.Fit(&startpt_, &endpt_);
819  if (startpt_.y() != endpt_.y()) {
820  vertical = endpt_;
821  vertical -= startpt_;
822  }
823  }
824  int start_y = startpt_.y();
825  int end_y = endpt_.y();
826  sort_key_ = IsLeftTab() ? MAX_INT32 : -MAX_INT32;
827  BLOBNBOX_C_IT it(&boxes_);
828  // Choose a line parallel to the vertical such that all boxes are on the
829  // correct side of it.
830  mean_width_ = 0;
831  int width_count = 0;
832  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
833  BLOBNBOX* bbox = it.data();
834  const TBOX& box = bbox->bounding_box();
835  mean_width_ += box.width();
836  ++width_count;
837  int x1 = IsRightTab() ? box.right() : box.left();
838  // Test both the bottom and the top, as one will be more extreme, depending
839  // on the direction of skew.
840  int bottom_y = box.bottom();
841  int top_y = box.top();
842  int key = SortKey(vertical, x1, bottom_y);
843  if (IsLeftTab() == (key < sort_key_)) {
844  sort_key_ = key;
845  startpt_ = ICOORD(x1, bottom_y);
846  }
847  key = SortKey(vertical, x1, top_y);
848  if (IsLeftTab() == (key < sort_key_)) {
849  sort_key_ = key;
850  startpt_ = ICOORD(x1, top_y);
851  }
852  if (it.at_first())
853  start_y = bottom_y;
854  if (it.at_last())
855  end_y = top_y;
856  }
857  if (width_count > 0) {
858  mean_width_ = (mean_width_ + width_count - 1) / width_count;
859  }
860  endpt_ = startpt_ + vertical;
861  needs_evaluation_ = true;
862  if (start_y != end_y) {
863  // Set the ends of the vector to fully include the first and last blobs.
864  startpt_.set_x(XAtY(vertical, sort_key_, start_y));
865  startpt_.set_y(start_y);
866  endpt_.set_x(XAtY(vertical, sort_key_, end_y));
867  endpt_.set_y(end_y);
868  return true;
869  }
870  return false;
871 }
#define MAX_INT32
Definition: host.h:62
void set_x(inT16 xin)
rewrite function
Definition: points.h:61
bool IsRagged() const
Definition: tabvector.h:229
inT16 x() const
access function
Definition: points.h:52
inT16 left() const
Definition: rect.h:68
inT16 y() const
access_function
Definition: points.h:56
inT16 top() const
Definition: rect.h:54
Definition: rect.h:30
bool IsLeftTab() const
Definition: tabvector.h:213
int XAtY(int y) const
Definition: tabvector.h:189
inT16 right() const
Definition: rect.h:75
inT16 width() const
Definition: rect.h:111
inT16 bottom() const
Definition: rect.h:61
const TBOX & bounding_box() const
Definition: blobbox.h:215
static int SortKey(const ICOORD &vertical, int x, int y)
Definition: tabvector.h:280
bool IsRightTab() const
Definition: tabvector.h:217
void set_y(inT16 yin)
rewrite function
Definition: points.h:65
integer coordinate
Definition: points.h:30

◆ FitAndEvaluateIfNeeded()

void tesseract::TabVector::FitAndEvaluateIfNeeded ( const ICOORD vertical,
TabFind finder 
)

Definition at line 573 of file tabvector.cpp.

574  {
575  if (needs_refit_)
576  Fit(vertical, true);
577  if (needs_evaluation_)
578  Evaluate(vertical, finder);
579 }
bool Fit(ICOORD vertical, bool force_parallel)
Definition: tabvector.cpp:788
void Evaluate(const ICOORD &vertical, TabFind *finder)
Definition: tabvector.cpp:587

◆ FitVector()

TabVector * tesseract::TabVector::FitVector ( TabAlignment  alignment,
ICOORD  vertical,
int  extended_start_y,
int  extended_end_y,
BLOBNBOX_CLIST *  good_points,
int vertical_x,
int vertical_y 
)
static

Definition at line 182 of file tabvector.cpp.

185  {
186  TabVector* vector = new TabVector(extended_start_y, extended_end_y,
187  alignment, good_points);
188  if (!vector->Fit(vertical, false)) {
189  delete vector;
190  return NULL;
191  }
192  if (!vector->IsRagged()) {
193  vertical = vector->endpt_ - vector->startpt_;
194  int weight = vector->BoxCount();
195  *vertical_x += vertical.x() * weight;
196  *vertical_y += vertical.y() * weight;
197  }
198  return vector;
199 }
inT16 x() const
access function
Definition: points.h:52
inT16 y() const
access_function
Definition: points.h:56

◆ Freeze()

void tesseract::TabVector::Freeze ( )
inline

Definition at line 250 of file tabvector.h.

250  {
251  boxes_.shallow_clear();
252  }

◆ GetSinglePartner()

TabVector * tesseract::TabVector::GetSinglePartner ( )

Definition at line 874 of file tabvector.cpp.

874  {
875  if (!partners_.singleton())
876  return NULL;
877  TabVector_C_IT partner_it(&partners_);
878  TabVector* partner = partner_it.data();
879  return partner;
880 }

◆ intersects_other_lines()

bool tesseract::TabVector::intersects_other_lines ( ) const
inline

Definition at line 179 of file tabvector.h.

179  {
180  return intersects_other_lines_;
181  }

◆ IsAPartner()

bool tesseract::TabVector::IsAPartner ( const TabVector other)

Definition at line 505 of file tabvector.cpp.

505  {
506  TabVector_C_IT it(&partners_);
507  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
508  if (it.data() == other)
509  return true;
510  }
511  return false;
512 }

◆ IsCenterTab()

bool tesseract::TabVector::IsCenterTab ( ) const
inline

Definition at line 225 of file tabvector.h.

225  {
226  return alignment_ == TA_CENTER_JUSTIFIED;
227  }

◆ IsLeftOf()

bool tesseract::TabVector::IsLeftOf ( const TabVector other) const
inline

Definition at line 235 of file tabvector.h.

235  {
236  return sort_key_ < other.sort_key_;
237  }

◆ IsLeftTab()

bool tesseract::TabVector::IsLeftTab ( ) const
inline

Definition at line 213 of file tabvector.h.

213  {
214  return alignment_ == TA_LEFT_ALIGNED || alignment_ == TA_LEFT_RAGGED;
215  }

◆ IsRagged()

bool tesseract::TabVector::IsRagged ( ) const
inline

Definition at line 229 of file tabvector.h.

229  {
230  return alignment_ == TA_LEFT_RAGGED || alignment_ == TA_RIGHT_RAGGED;
231  }

◆ IsRightTab()

bool tesseract::TabVector::IsRightTab ( ) const
inline

Definition at line 217 of file tabvector.h.

217  {
218  return alignment_ == TA_RIGHT_ALIGNED || alignment_ == TA_RIGHT_RAGGED;
219  }

◆ IsSeparator()

bool tesseract::TabVector::IsSeparator ( ) const
inline

Definition at line 221 of file tabvector.h.

221  {
222  return alignment_ == TA_SEPARATOR;
223  }

◆ mean_width()

int tesseract::TabVector::mean_width ( ) const
inline

Definition at line 161 of file tabvector.h.

161  {
162  return mean_width_;
163  }

◆ MergeSimilarTabVectors()

void tesseract::TabVector::MergeSimilarTabVectors ( const ICOORD vertical,
TabVector_LIST *  vectors,
BlobGrid grid 
)
static

Definition at line 361 of file tabvector.cpp.

363  {
364  TabVector_IT it1(vectors);
365  for (it1.mark_cycle_pt(); !it1.cycled_list(); it1.forward()) {
366  TabVector* v1 = it1.data();
367  TabVector_IT it2(it1);
368  for (it2.forward(); !it2.at_first(); it2.forward()) {
369  TabVector* v2 = it2.data();
370  if (v2->SimilarTo(vertical, *v1, grid)) {
371  // Merge into the forward one, in case the combined vector now
372  // overlaps one in between.
373  if (textord_debug_tabfind) {
374  v2->Print("Merging");
375  v1->Print("by deleting");
376  }
377  v2->MergeWith(vertical, it1.extract());
378  if (textord_debug_tabfind) {
379  v2->Print("Producing");
380  }
381  ICOORD merged_vector = v2->endpt();
382  merged_vector -= v2->startpt();
383  if (textord_debug_tabfind && abs(merged_vector.x()) > 100) {
384  v2->Print("Garbage result of merge?");
385  }
386  break;
387  }
388  }
389  }
390 }
inT16 x() const
access function
Definition: points.h:52
int textord_debug_tabfind
Definition: alignedblob.cpp:27
integer coordinate
Definition: points.h:30

◆ MergeWith()

void tesseract::TabVector::MergeWith ( const ICOORD vertical,
TabVector other 
)

Definition at line 458 of file tabvector.cpp.

458  {
459  extended_ymin_ = MIN(extended_ymin_, other->extended_ymin_);
460  extended_ymax_ = MAX(extended_ymax_, other->extended_ymax_);
461  if (other->IsRagged()) {
462  alignment_ = other->alignment_;
463  }
464  // Merge sort the two lists of boxes.
465  BLOBNBOX_C_IT it1(&boxes_);
466  BLOBNBOX_C_IT it2(&other->boxes_);
467  while (!it2.empty()) {
468  BLOBNBOX* bbox2 = it2.extract();
469  it2.forward();
470  TBOX box2 = bbox2->bounding_box();
471  BLOBNBOX* bbox1 = it1.data();
472  TBOX box1 = bbox1->bounding_box();
473  while (box1.bottom() < box2.bottom() && !it1.at_last()) {
474  it1.forward();
475  bbox1 = it1.data();
476  box1 = bbox1->bounding_box();
477  }
478  if (box1.bottom() < box2.bottom()) {
479  it1.add_to_end(bbox2);
480  } else if (bbox1 != bbox2) {
481  it1.add_before_stay_put(bbox2);
482  }
483  }
484  Fit(vertical, true);
485  other->Delete(this);
486 }
bool Fit(ICOORD vertical, bool force_parallel)
Definition: tabvector.cpp:788
#define MAX(x, y)
Definition: ndminx.h:24
Definition: rect.h:30
#define MIN(x, y)
Definition: ndminx.h:28
inT16 bottom() const
Definition: rect.h:61
const TBOX & bounding_box() const
Definition: blobbox.h:215

◆ Partnerless()

bool tesseract::TabVector::Partnerless ( )
inline

Definition at line 240 of file tabvector.h.

240  {
241  return partners_.empty();
242  }

◆ partners()

TabVector_CLIST* tesseract::TabVector::partners ( )
inline

Definition at line 170 of file tabvector.h.

170  {
171  return &partners_;
172  }

◆ Print()

void tesseract::TabVector::Print ( const char *  prefix)

Definition at line 525 of file tabvector.cpp.

525  {
526  tprintf(
527  "%s %s (%d,%d)->(%d,%d) w=%d s=%d, sort key=%d, boxes=%d,"
528  " partners=%d\n",
529  prefix, kAlignmentNames[alignment_], startpt_.x(), startpt_.y(),
530  endpt_.x(), endpt_.y(), mean_width_, percent_score_, sort_key_,
531  boxes_.length(), partners_.length());
532 }
inT16 x() const
access function
Definition: points.h:52
#define tprintf(...)
Definition: tprintf.h:31
inT16 y() const
access_function
Definition: points.h:56
const char * kAlignmentNames[]
Definition: tabvector.cpp:515

◆ ReflectInYAxis()

void tesseract::TabVector::ReflectInYAxis ( )
inline

Definition at line 265 of file tabvector.h.

265  {
266  startpt_.set_x(-startpt_.x());
267  endpt_.set_x(-endpt_.x());
268  sort_key_ = -sort_key_;
269  if (alignment_ == TA_LEFT_ALIGNED)
270  alignment_ = TA_RIGHT_ALIGNED;
271  else if (alignment_ == TA_RIGHT_ALIGNED)
272  alignment_ = TA_LEFT_ALIGNED;
273  if (alignment_ == TA_LEFT_RAGGED)
274  alignment_ = TA_RIGHT_RAGGED;
275  else if (alignment_ == TA_RIGHT_RAGGED)
276  alignment_ = TA_LEFT_RAGGED;
277  }
void set_x(inT16 xin)
rewrite function
Definition: points.h:61
inT16 x() const
access function
Definition: points.h:52

◆ Rotate()

void tesseract::TabVector::Rotate ( const FCOORD rotation)

Definition at line 281 of file tabvector.cpp.

281  {
282  startpt_.rotate(rotation);
283  endpt_.rotate(rotation);
284  int dx = endpt_.x() - startpt_.x();
285  int dy = endpt_.y() - startpt_.y();
286  if ((dy < 0 && abs(dy) > abs(dx)) || (dx < 0 && abs(dx) > abs(dy))) {
287  // Need to flip start/end.
288  ICOORD tmp = startpt_;
289  startpt_ = endpt_;
290  endpt_ = tmp;
291  }
292 }
void rotate(const FCOORD &vec)
Definition: ipoints.h:241
inT16 x() const
access function
Definition: points.h:52
inT16 y() const
access_function
Definition: points.h:56
integer coordinate
Definition: points.h:30

◆ set_bottom_constraints()

void tesseract::TabVector::set_bottom_constraints ( TabConstraint_LIST *  constraints)
inline

Definition at line 167 of file tabvector.h.

167  {
168  bottom_constraints_ = constraints;
169  }

◆ set_endpt()

void tesseract::TabVector::set_endpt ( const ICOORD end)
inline

Definition at line 176 of file tabvector.h.

176  {
177  endpt_ = end;
178  }

◆ set_intersects_other_lines()

void tesseract::TabVector::set_intersects_other_lines ( bool  value)
inline

Definition at line 182 of file tabvector.h.

182  {
183  intersects_other_lines_ = value;
184  }

◆ set_startpt()

void tesseract::TabVector::set_startpt ( const ICOORD start)
inline

Definition at line 173 of file tabvector.h.

173  {
174  startpt_ = start;
175  }

◆ set_top_constraints()

void tesseract::TabVector::set_top_constraints ( TabConstraint_LIST *  constraints)
inline

Definition at line 164 of file tabvector.h.

164  {
165  top_constraints_ = constraints;
166  }

◆ SetupConstraints()

void tesseract::TabVector::SetupConstraints ( )

Definition at line 296 of file tabvector.cpp.

296  {
297  TabConstraint::CreateConstraint(this, false);
299 }
static void CreateConstraint(TabVector *vector, bool is_top)
Definition: tabvector.cpp:66

◆ SetupPartnerConstraints() [1/2]

void tesseract::TabVector::SetupPartnerConstraints ( )

Definition at line 302 of file tabvector.cpp.

302  {
303  // With the first and last partner, we want a common bottom and top,
304  // respectively, and for each change of partner, we want a common
305  // top of first with bottom of next.
306  TabVector_C_IT it(&partners_);
307  TabVector* prev_partner = NULL;
308  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
309  TabVector* partner = it.data();
310  if (partner->top_constraints_ == NULL ||
311  partner->bottom_constraints_ == NULL) {
312  partner->Print("Impossible: has no constraints");
313  Print("This vector has it as a partner");
314  continue;
315  }
316  if (prev_partner == NULL) {
317  // This is the first partner, so common bottom.
318  if (TabConstraint::CompatibleConstraints(bottom_constraints_,
319  partner->bottom_constraints_))
320  TabConstraint::MergeConstraints(bottom_constraints_,
321  partner->bottom_constraints_);
322  } else {
323  // We need prev top to be common with partner bottom.
324  if (TabConstraint::CompatibleConstraints(prev_partner->top_constraints_,
325  partner->bottom_constraints_))
326  TabConstraint::MergeConstraints(prev_partner->top_constraints_,
327  partner->bottom_constraints_);
328  }
329  prev_partner = partner;
330  if (it.at_last()) {
331  // This is the last partner, so common top.
332  if (TabConstraint::CompatibleConstraints(top_constraints_,
333  partner->top_constraints_))
334  TabConstraint::MergeConstraints(top_constraints_,
335  partner->top_constraints_);
336  }
337  }
338 }
static bool CompatibleConstraints(TabConstraint_LIST *list1, TabConstraint_LIST *list2)
Definition: tabvector.cpp:78
static void MergeConstraints(TabConstraint_LIST *list1, TabConstraint_LIST *list2)
Definition: tabvector.cpp:95
void Print(const char *prefix)
Definition: tabvector.cpp:525

◆ SetupPartnerConstraints() [2/2]

void tesseract::TabVector::SetupPartnerConstraints ( TabVector partner)

Definition at line 341 of file tabvector.cpp.

341  {
342  if (TabConstraint::CompatibleConstraints(bottom_constraints_,
343  partner->bottom_constraints_))
344  TabConstraint::MergeConstraints(bottom_constraints_,
345  partner->bottom_constraints_);
346  if (TabConstraint::CompatibleConstraints(top_constraints_,
347  partner->top_constraints_))
348  TabConstraint::MergeConstraints(top_constraints_,
349  partner->top_constraints_);
350 }
static bool CompatibleConstraints(TabConstraint_LIST *list1, TabConstraint_LIST *list2)
Definition: tabvector.cpp:78
static void MergeConstraints(TabConstraint_LIST *list1, TabConstraint_LIST *list2)
Definition: tabvector.cpp:95

◆ SetYEnd()

void tesseract::TabVector::SetYEnd ( int  end_y)

Definition at line 275 of file tabvector.cpp.

275  {
276  endpt_.set_x(XAtY(end_y));
277  endpt_.set_y(end_y);
278 }
void set_x(inT16 xin)
rewrite function
Definition: points.h:61
int XAtY(int y) const
Definition: tabvector.h:189
void set_y(inT16 yin)
rewrite function
Definition: points.h:65

◆ SetYStart()

void tesseract::TabVector::SetYStart ( int  start_y)

Definition at line 270 of file tabvector.cpp.

270  {
271  startpt_.set_x(XAtY(start_y));
272  startpt_.set_y(start_y);
273 }
void set_x(inT16 xin)
rewrite function
Definition: points.h:61
int XAtY(int y) const
Definition: tabvector.h:189
void set_y(inT16 yin)
rewrite function
Definition: points.h:65

◆ ShallowCopy()

TabVector * tesseract::TabVector::ShallowCopy ( ) const

Definition at line 233 of file tabvector.cpp.

233  {
234  TabVector* copy = new TabVector();
235  copy->startpt_ = startpt_;
236  copy->endpt_ = endpt_;
237  copy->alignment_ = alignment_;
238  copy->extended_ymax_ = extended_ymax_;
239  copy->extended_ymin_ = extended_ymin_;
240  copy->intersects_other_lines_ = intersects_other_lines_;
241  return copy;
242 }

◆ SimilarTo()

bool tesseract::TabVector::SimilarTo ( const ICOORD vertical,
const TabVector other,
BlobGrid grid 
) const

Definition at line 394 of file tabvector.cpp.

395  {
396  if ((IsRightTab() && other.IsRightTab()) ||
397  (IsLeftTab() && other.IsLeftTab())) {
398  // If they don't overlap, at least in extensions, then there is no chance.
399  if (ExtendedOverlap(other.extended_ymax_, other.extended_ymin_) < 0)
400  return false;
401  // A fast approximation to the scale factor of the sort_key_.
402  int v_scale = abs(vertical.y());
403  if (v_scale == 0)
404  v_scale = 1;
405  // If they are close enough, then OK.
406  if (sort_key_ + kSimilarVectorDist * v_scale >= other.sort_key_ &&
407  sort_key_ - kSimilarVectorDist * v_scale <= other.sort_key_)
408  return true;
409  // Ragged tabs get a bigger threshold.
410  if (!IsRagged() || !other.IsRagged() ||
411  sort_key_ + kSimilarRaggedDist * v_scale < other.sort_key_ ||
412  sort_key_ - kSimilarRaggedDist * v_scale > other.sort_key_)
413  return false;
414  if (grid == NULL) {
415  // There is nothing else to test!
416  return true;
417  }
418  // If there is nothing in the rectangle between the vector that is going to
419  // move, and the place it is moving to, then they can be merged.
420  // Setup a vertical search for any blob.
421  const TabVector* mover = (IsRightTab() &&
422  sort_key_ < other.sort_key_) ? this : &other;
423  int top_y = mover->endpt_.y();
424  int bottom_y = mover->startpt_.y();
425  int left = MIN(mover->XAtY(top_y), mover->XAtY(bottom_y));
426  int right = MAX(mover->XAtY(top_y), mover->XAtY(bottom_y));
427  int shift = abs(sort_key_ - other.sort_key_) / v_scale;
428  if (IsRightTab()) {
429  right += shift;
430  } else {
431  left -= shift;
432  }
433 
434  GridSearch<BLOBNBOX, BLOBNBOX_CLIST, BLOBNBOX_C_IT> vsearch(grid);
435  vsearch.StartVerticalSearch(left, right, top_y);
436  BLOBNBOX* blob;
437  while ((blob = vsearch.NextVerticalSearch(true)) != NULL) {
438  const TBOX& box = blob->bounding_box();
439  if (box.top() > bottom_y)
440  return true; // Nothing found.
441  if (box.bottom() < top_y)
442  continue; // Doesn't overlap.
443  int left_at_box = XAtY(box.bottom());
444  int right_at_box = left_at_box;
445  if (IsRightTab())
446  right_at_box += shift;
447  else
448  left_at_box -= shift;
449  if (MIN(right_at_box, box.right()) > MAX(left_at_box, box.left()))
450  return false;
451  }
452  return true; // Nothing found.
453  }
454  return false;
455 }
bool IsRagged() const
Definition: tabvector.h:229
int ExtendedOverlap(int top_y, int bottom_y) const
Definition: tabvector.h:208
const int kSimilarVectorDist
Definition: tabvector.cpp:42
inT16 left() const
Definition: rect.h:68
inT16 y() const
access_function
Definition: points.h:56
inT16 top() const
Definition: rect.h:54
#define MAX(x, y)
Definition: ndminx.h:24
Definition: rect.h:30
bool IsLeftTab() const
Definition: tabvector.h:213
#define MIN(x, y)
Definition: ndminx.h:28
int XAtY(int y) const
Definition: tabvector.h:189
inT16 right() const
Definition: rect.h:75
inT16 bottom() const
Definition: rect.h:61
const TBOX & bounding_box() const
Definition: blobbox.h:215
bool IsRightTab() const
Definition: tabvector.h:217
const int kSimilarRaggedDist
Definition: tabvector.cpp:45

◆ sort_key()

int tesseract::TabVector::sort_key ( ) const
inline

Definition at line 158 of file tabvector.h.

158  {
159  return sort_key_;
160  }

◆ SortKey()

static int tesseract::TabVector::SortKey ( const ICOORD vertical,
int  x,
int  y 
)
inlinestatic

Definition at line 280 of file tabvector.h.

280  {
281  ICOORD pt(x, y);
282  return pt * vertical;
283  }
integer coordinate
Definition: points.h:30

◆ SortVectorsByKey()

static int tesseract::TabVector::SortVectorsByKey ( const void *  v1,
const void *  v2 
)
inlinestatic

Definition at line 294 of file tabvector.h.

294  {
295  const TabVector* tv1 = *static_cast<const TabVector* const *>(v1);
296  const TabVector* tv2 = *static_cast<const TabVector* const *>(v2);
297  return tv1->sort_key_ - tv2->sort_key_;
298  }

◆ startpt()

const ICOORD& tesseract::TabVector::startpt ( ) const
inline

Definition at line 146 of file tabvector.h.

146  {
147  return startpt_;
148  }

◆ VerticalTextlinePartner()

TabVector * tesseract::TabVector::VerticalTextlinePartner ( )

Definition at line 884 of file tabvector.cpp.

884  {
885  if (!partners_.singleton())
886  return NULL;
887  TabVector_C_IT partner_it(&partners_);
888  TabVector* partner = partner_it.data();
889  BLOBNBOX_C_IT box_it1(&boxes_);
890  BLOBNBOX_C_IT box_it2(&partner->boxes_);
891  // Count how many boxes are also in the other list.
892  // At the same time, gather the mean width and median vertical gap.
893  if (textord_debug_tabfind > 1) {
894  Print("Testing for vertical text");
895  partner->Print(" partner");
896  }
897  int num_matched = 0;
898  int num_unmatched = 0;
899  int total_widths = 0;
900  int width = startpt().x() - partner->startpt().x();
901  if (width < 0)
902  width = -width;
903  STATS gaps(0, width * 2);
904  BLOBNBOX* prev_bbox = NULL;
905  box_it2.mark_cycle_pt();
906  for (box_it1.mark_cycle_pt(); !box_it1.cycled_list(); box_it1.forward()) {
907  BLOBNBOX* bbox = box_it1.data();
908  TBOX box = bbox->bounding_box();
909  if (prev_bbox != NULL) {
910  gaps.add(box.bottom() - prev_bbox->bounding_box().top(), 1);
911  }
912  while (!box_it2.cycled_list() && box_it2.data() != bbox &&
913  box_it2.data()->bounding_box().bottom() < box.bottom()) {
914  box_it2.forward();
915  }
916  if (!box_it2.cycled_list() && box_it2.data() == bbox &&
917  bbox->region_type() >= BRT_UNKNOWN &&
918  (prev_bbox == NULL || prev_bbox->region_type() >= BRT_UNKNOWN))
919  ++num_matched;
920  else
921  ++num_unmatched;
922  total_widths += box.width();
923  prev_bbox = bbox;
924  }
925  if (num_unmatched + num_matched == 0) return NULL;
926  double avg_width = total_widths * 1.0 / (num_unmatched + num_matched);
927  double max_gap = textord_tabvector_vertical_gap_fraction * avg_width;
928  int min_box_match = static_cast<int>((num_matched + num_unmatched) *
930  bool is_vertical = (gaps.get_total() > 0 &&
931  num_matched >= min_box_match &&
932  gaps.median() <= max_gap);
933  if (textord_debug_tabfind > 1) {
934  tprintf("gaps=%d, matched=%d, unmatched=%d, min_match=%d "
935  "median gap=%.2f, width=%.2f max_gap=%.2f Vertical=%s\n",
936  gaps.get_total(), num_matched, num_unmatched, min_box_match,
937  gaps.median(), avg_width, max_gap, is_vertical?"Yes":"No");
938  }
939  return (is_vertical) ? partner : NULL;
940 }
inT16 x() const
access function
Definition: points.h:52
#define tprintf(...)
Definition: tprintf.h:31
double textord_tabvector_vertical_box_ratio
Definition: tabvector.cpp:61
BlobRegionType region_type() const
Definition: blobbox.h:268
const ICOORD & startpt() const
Definition: tabvector.h:146
int textord_debug_tabfind
Definition: alignedblob.cpp:27
inT16 top() const
Definition: rect.h:54
Definition: rect.h:30
inT16 width() const
Definition: rect.h:111
Definition: statistc.h:33
inT16 bottom() const
Definition: rect.h:61
void Print(const char *prefix)
Definition: tabvector.cpp:525
double textord_tabvector_vertical_gap_fraction
Definition: tabvector.cpp:58
const TBOX & bounding_box() const
Definition: blobbox.h:215

◆ VOverlap() [1/2]

int tesseract::TabVector::VOverlap ( const TabVector other) const
inline

Definition at line 199 of file tabvector.h.

199  {
200  return MIN(other.endpt_.y(), endpt_.y()) -
201  MAX(other.startpt_.y(), startpt_.y());
202  }
inT16 y() const
access_function
Definition: points.h:56
#define MAX(x, y)
Definition: ndminx.h:24
#define MIN(x, y)
Definition: ndminx.h:28

◆ VOverlap() [2/2]

int tesseract::TabVector::VOverlap ( int  top_y,
int  bottom_y 
) const
inline

Definition at line 204 of file tabvector.h.

204  {
205  return MIN(top_y, endpt_.y()) - MAX(bottom_y, startpt_.y());
206  }
inT16 y() const
access_function
Definition: points.h:56
#define MAX(x, y)
Definition: ndminx.h:24
#define MIN(x, y)
Definition: ndminx.h:28

◆ XAtY() [1/2]

int tesseract::TabVector::XAtY ( int  y) const
inline

Definition at line 189 of file tabvector.h.

189  {
190  int height = endpt_.y() - startpt_.y();
191  if (height != 0)
192  return (y - startpt_.y()) * (endpt_.x() - startpt_.x()) / height +
193  startpt_.x();
194  else
195  return startpt_.x();
196  }
inT16 x() const
access function
Definition: points.h:52
inT16 y() const
access_function
Definition: points.h:56

◆ XAtY() [2/2]

static int tesseract::TabVector::XAtY ( const ICOORD vertical,
int  sort_key,
int  y 
)
inlinestatic

Definition at line 286 of file tabvector.h.

286  {
287  if (vertical.y() != 0)
288  return (vertical.x() * y + sort_key) / vertical.y();
289  else
290  return sort_key;
291  }
inT16 x() const
access function
Definition: points.h:52
int sort_key() const
Definition: tabvector.h:158
inT16 y() const
access_function
Definition: points.h:56

◆ XYFlip()

void tesseract::TabVector::XYFlip ( )
inline

Definition at line 255 of file tabvector.h.

255  {
256  int x = startpt_.y();
257  startpt_.set_y(startpt_.x());
258  startpt_.set_x(x);
259  x = endpt_.y();
260  endpt_.set_y(endpt_.x());
261  endpt_.set_x(x);
262  }
void set_x(inT16 xin)
rewrite function
Definition: points.h:61
inT16 x() const
access function
Definition: points.h:52
inT16 y() const
access_function
Definition: points.h:56
void set_y(inT16 yin)
rewrite function
Definition: points.h:65

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