75 int b0a1xb0b1, b0b1xb0a0;
76 int a1b1xa1a0, a1a0xa1b0;
78 TPOINT b0a1, b0a0, a1b1, b0b1, a1a0;
91 b0a1xb0b1 =
CROSS(b0a1, b0b1);
92 b0b1xb0a0 =
CROSS(b0b1, b0a0);
93 a1b1xa1a0 =
CROSS(a1b1, a1a0);
96 a1a0xa1b0 = -
CROSS(a1a0, b0a1);
98 return ((b0a1xb0b1 > 0 && b0b1xb0a0 > 0) ||
99 (b0a1xb0b1 < 0 && b0b1xb0a0 < 0)) &&
100 ((a1b1xa1a0 > 0 && a1a0xa1b0 > 0) || (a1b1xa1a0 < 0 && a1a0xa1b0 < 0));
106 result->
loop = outline;
119 }
while (pt != outline);
132 if (src.
loop != NULL) {
137 newpt =
new EDGEPT(*srcpt);
138 if (prevpt == NULL) {
141 newpt->
prev = prevpt;
142 prevpt->
next = newpt;
146 }
while (srcpt != src.
loop);
161 this_edge = next_edge;
162 }
while (this_edge !=
loop);
172 }
while (pt !=
loop);
180 int tmp =
static_cast<int>(floor(pt->
pos.
x * rot.
x() -
181 pt->
pos.
y * rot.
y() + 0.5));
182 pt->
pos.
y =
static_cast<int>(floor(pt->
pos.
y * rot.
x() +
183 pt->
pos.
x * rot.
y() + 0.5));
186 }
while (pt !=
loop);
194 pt->
pos.
x += vec.
x();
195 pt->
pos.
y += vec.
y();
197 }
while (pt !=
loop);
205 pt->
pos.
x =
static_cast<int>(floor(pt->
pos.
x * factor + 0.5));
206 pt->
pos.
y =
static_cast<int>(floor(pt->
pos.
y * factor + 0.5));
208 }
while (pt !=
loop);
219 }
while (pt !=
loop);
236 if (this_edge->
pos.
x < minx)
237 minx = this_edge->
pos.
x;
238 if (this_edge->
pos.
y < miny)
239 miny = this_edge->
pos.
y;
240 if (this_edge->
pos.
x > maxx)
241 maxx = this_edge->
pos.
x;
242 if (this_edge->
pos.
y > maxy)
243 maxy = this_edge->
pos.
y;
245 this_edge = this_edge->
next;
246 }
while (this_edge !=
loop);
260 int* min_xp,
int* max_xp)
const {
266 int product =
CROSS(this_edge->
pos, vec);
269 this_edge = this_edge->
next;
270 }
while (this_edge !=
loop);
277 #ifndef GRAPHICS_DISABLED 281 window->
Pen(child_color);
293 }
while (pt !=
loop);
295 #endif // GRAPHICS_DISABLED 319 static TESSLINE** ApproximateOutlineList(
bool allow_detailed_fx,
320 C_OUTLINE_LIST* outlines,
323 C_OUTLINE_IT ol_it(outlines);
324 for (ol_it.mark_cycle_pt(); !ol_it.cycled_list(); ol_it.forward()) {
330 tail = &tessline->
next;
332 if (!outline->
child()->empty()) {
333 tail = ApproximateOutlineList(allow_detailed_fx, outline->
child(),
true,
346 ApproximateOutlineList(allow_detailed_fx, src->
out_list(),
false,
354 blob->denorm_ = src.denorm_;
364 TBLOB* rotated_blob = NULL;
367 if (denorm_.
block() != NULL &&
370 int x_middle = (box.
left() + box.
right()) / 2;
371 int y_middle = (box.
top() + box.
bottom()) / 2;
372 rotated_blob =
new TBLOB(*
this);
377 (rotation.
y() > 0 ? x_middle - box.
left() : box.
right() - x_middle);
378 rotated_blob->
Normalize(NULL, &rotation, &denorm_, x_middle, y_middle,
379 1.0f, 1.0f, 0.0f, target_y,
390 srcline = srcline->
next) {
395 prev_outline->
next = new_outline;
396 prev_outline = new_outline;
398 denorm_ = src.denorm_;
415 const DENORM* predecessor,
416 float x_origin,
float y_origin,
417 float x_scale,
float y_scale,
418 float final_xshift,
float final_yshift,
419 bool inverse, Pix* pix) {
421 x_scale, y_scale, final_xshift, final_yshift);
432 for (
TESSLINE* outline =
outlines; outline != NULL; outline = outline->next) {
433 outline->Normalize(denorm_);
442 for (
TESSLINE* outline =
outlines; outline != NULL; outline = outline->next) {
443 outline->Rotate(rotation);
449 for (
TESSLINE* outline =
outlines; outline != NULL; outline = outline->next) {
456 for (
TESSLINE* outline =
outlines; outline != NULL; outline = outline->next) {
457 outline->Scale(factor);
463 for (
TESSLINE* outline =
outlines; outline != NULL; outline = outline->next) {
464 outline->ComputeBoundingBox();
471 for (
TESSLINE* outline =
outlines; outline != NULL; outline = outline->next)
484 return TBOX(0, 0, 0, 0);
487 for (outline = outline->
next; outline != NULL; outline = outline->
next) {
496 for (
TESSLINE* outline =
outlines; outline != NULL; outline = outline->next) {
498 for (
TESSLINE* other_outline = outline->next; other_outline != NULL;
499 last_outline = other_outline, other_outline = other_outline->
next) {
500 if (outline->SameBox(*other_outline)) {
501 last_outline->
next = other_outline->
next;
503 other_outline->
loop = NULL;
504 delete other_outline;
505 other_outline = last_outline;
507 outline->is_hole =
false;
523 #ifndef GRAPHICS_DISABLED 526 for (
TESSLINE* outline =
outlines; outline != NULL; outline = outline->next)
527 outline->
plot(window, color, child_color);
529 #endif // GRAPHICS_DISABLED 540 CollectEdges(box, NULL, &accumulator, NULL, NULL);
545 if (x2nd < 1.0) x2nd = 1.0;
546 if (y2nd < 1.0) y2nd = 1.0;
547 second_moments->
set_x(x2nd);
548 second_moments->
set_y(y2nd);
549 return accumulator.
count();
556 *precise_box =
TBOX();
557 CollectEdges(box, precise_box, NULL, NULL, NULL);
575 y_coords->init_to_size(box.
width(), empty);
576 CollectEdges(box, NULL, NULL, x_coords, y_coords);
578 for (
int i = 0; i < x_coords->size(); ++i)
579 (*x_coords)[i].sort();
580 for (
int i = 0; i < y_coords->size(); ++i)
581 (*y_coords)[i].sort();
586 static void SegmentLLSQ(
const FCOORD& pt1,
const FCOORD& pt2,
594 if (xstart == xend && ystart == yend)
return;
595 double weight = step.length() / (xend - xstart + yend - ystart);
597 for (
int x = xstart; x < xend; ++x) {
598 double y = pt1.
y() + step.y() * (x + 0.5 - pt1.
x()) / step.x();
599 accumulator->
add(x + 0.5, y, weight);
602 for (
int y = ystart; y < yend; ++y) {
603 double x = pt1.
x() + step.x() * (y + 0.5 - pt1.
y()) / step.y();
604 accumulator->
add(x, y + 0.5, weight);
613 static void SegmentCoords(
const FCOORD& pt1,
const FCOORD& pt2,
614 int x_limit,
int y_limit,
621 for (
int x = start; x < end; ++x) {
622 int y =
IntCastRounded(pt1.
y() + step.y() * (x + 0.5 - pt1.
x()) / step.x());
623 (*y_coords)[x].push_back(y);
627 for (
int y = start; y < end; ++y) {
628 int x =
IntCastRounded(pt1.
x() + step.x() * (y + 0.5 - pt1.
y()) / step.y());
629 (*x_coords)[y].push_back(x);
671 static void CollectEdgesOfRun(
const EDGEPT* startpt,
const EDGEPT* lastpt,
678 int x_limit = box.
width() - 1;
679 int y_limit = box.
height() - 1;
680 if (outline != NULL) {
695 if (end_index <= start_index)
696 end_index += step_length;
708 prev_normed -= origin;
709 for (
int index = start_index; index < end_index; ++index) {
710 ICOORD step = outline->
step(index % step_length);
720 index % step_length);
723 pos_normed -= origin;
725 if (bounding_box != NULL) {
726 SegmentBBox(pos_normed, prev_normed, bounding_box);
728 if (accumulator != NULL) {
729 SegmentLLSQ(pos_normed, prev_normed, accumulator);
731 if (x_coords != NULL && y_coords != NULL) {
732 SegmentCoords(pos_normed, prev_normed, x_limit, y_limit,
735 prev_normed = pos_normed;
742 const EDGEPT* pt = startpt;
747 if (bounding_box != NULL) {
748 SegmentBBox(next_pos, pos, bounding_box);
750 if (accumulator != NULL) {
751 SegmentLLSQ(next_pos, pos, accumulator);
753 if (x_coords != NULL && y_coords != NULL) {
754 SegmentCoords(next_pos, pos, x_limit, y_limit, x_coords, y_coords);
756 }
while ((pt = pt->
next) != endpt);
765 void TBLOB::CollectEdges(
const TBOX& box,
772 EDGEPT* loop_pt = ol->FindBestStartPt();
774 if (pt == NULL)
continue;
780 last_pt = last_pt->
next;
781 }
while (last_pt != loop_pt && !last_pt->
IsHidden() &&
783 last_pt = last_pt->
prev;
784 CollectEdgesOfRun(pt, last_pt, denorm_, box,
787 }
while ((pt = pt->
next) != loop_pt);
797 for (b_it.mark_cycle_pt(); !b_it.cycled_list(); b_it.forward()) {
798 C_BLOB* blob = b_it.data();
808 bool inverse,
float x_height,
float baseline_shift,
810 const TBOX* norm_box,
813 if (norm_box != NULL) word_box = *norm_box;
814 float word_middle = (word_box.
left() + word_box.
right()) / 2.0f;
815 float input_y_offset = 0.0f;
819 word_middle = word_box.
left();
820 input_y_offset = word_box.
bottom();
821 final_y_offset = 0.0f;
825 input_y_offset = row->
base_line(word_middle) + baseline_shift;
830 float mid_x = (blob_box.
left() + blob_box.
right()) / 2.0f;
832 float blob_scale = scale;
836 scale, scale * 1.5f);
847 blob_scale, 0.0f, final_y_offset, inverse, pix);
849 if (word_denorm != NULL) {
851 input_y_offset, scale, scale,
852 0.0f, final_y_offset);
862 for (
int b = 0; b < src.
blobs.
size(); ++b) {
877 blobs[b]->ComputeBoundingBoxes();
895 for (
int i = start + 1; i < end && i <
blobs.
size(); ++i) {
898 if (outline == NULL) {
900 outline =
blobs[start]->outlines;
902 while (outline->
next != NULL)
903 outline = outline->
next;
912 for (
int i = start + 1; i < end && start + 1 <
blobs.
size(); ++i) {
917 #ifndef GRAPHICS_DISABLED 925 #endif // GRAPHICS_DISABLED 941 outline1 = outline1->
next) {
942 if (outline1->is_hole)
945 static_cast<inT16>((outline1->topleft.x + outline1->botright.x) / 2),
946 static_cast<inT16>((outline1->topleft.y + outline1->botright.y) / 2));
947 int mid_prod1 =
CROSS(mid_pt1, vertical);
948 int min_prod1, max_prod1;
949 outline1->MinMaxCrossProduct(vertical, &min_prod1, &max_prod1);
950 for (
TESSLINE* outline2 = outline1->
next; outline2 != NULL;
951 outline2 = outline2->
next) {
952 if (outline2->is_hole)
955 static_cast<inT16>((outline2->topleft.x + outline2->botright.x) / 2),
956 static_cast<inT16>((outline2->topleft.y + outline2->botright.y) / 2));
957 int mid_prod2 =
CROSS(mid_pt2, vertical);
958 int min_prod2, max_prod2;
959 outline2->MinMaxCrossProduct(vertical, &min_prod2, &max_prod2);
960 int mid_gap = abs(mid_prod2 - mid_prod1);
961 int overlap =
MIN(max_prod1, max_prod2) -
MAX(min_prod1, min_prod2);
962 if (mid_gap - overlap / 4 > max_gap) {
963 max_gap = mid_gap - overlap / 4;
965 *location += mid_pt2;
972 return max_gap > vertical.
y;
992 int location_prod =
CROSS(location, vertical);
994 while (outline != NULL) {
998 int mid_prod =
CROSS(mid_pt, vertical);
999 if (mid_prod < location_prod) {
1002 outline1->
next = outline;
1009 outline2->
next = outline;
1014 outline = outline->
next;
1018 outline1->
next = NULL;
1020 outline2->
next = NULL;
void DrawTo(int x, int y)
void MinMaxCrossProduct(const TPOINT vec, int *min_xp, int *max_xp) const
void CopyFrom(const TBLOB &src)
void GetEdgeCoords(const TBOX &box, GenericVector< GenericVector< int > > *x_coords, GenericVector< GenericVector< int > > *y_coords) const
void UpdateRange(const T1 &x, T2 *lower_bound, T2 *upper_bound)
double y_variance() const
const int kBlnBaselineOffset
int IntCastRounded(double x)
GenericVector< TBLOB * > blobs
void set_inverse(bool value)
static TESSLINE * BuildFromOutlineList(EDGEPT *outline)
float base_line(float xpos) const
void Normalize(const BLOCK *block, const FCOORD *rotation, const DENORM *predecessor, float x_origin, float y_origin, float x_scale, float y_scale, float final_xshift, float final_yshift, bool inverse, Pix *pix)
void SetCursor(int x, int y)
ICOORD position_at_index(int index) const
void plot(ScrollView *window, ScrollView::Color color, ScrollView::Color child_color)
void Move(const ICOORD vec)
void BLNormalize(const BLOCK *block, const ROW *row, Pix *pix, bool inverse, float x_height, float baseline_shift, bool numeric_mode, tesseract::OcrEngineMode hint, const TBOX *norm_box, DENORM *word_denorm)
void EliminateDuplicateOutlines()
void NormTransform(const DENORM *first_norm, const TPOINT &pt, TPOINT *transformed) const
ICOORD step(int index) const
void SetupNormalization(const BLOCK *block, const FCOORD *rotation, const DENORM *predecessor, float x_origin, float y_origin, float x_scale, float y_scale, float final_xshift, float final_yshift)
static ScrollView::Color NextColor(ScrollView::Color colour)
void Normalize(const DENORM &denorm)
void divide_blobs(TBLOB *blob, TBLOB *other_blob, bool italic_blob, const TPOINT &location)
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
C_OUTLINE_LIST * out_list()
void add(double x, double y)
TBOX bounding_box() const
void MergeBlobs(int start, int end)
void set_x(float xin)
rewrite function
const TPOINT kDivisibleVerticalItalic(1, 5)
void move(const ICOORD vec)
void plot(ScrollView *window)
void Move(const ICOORD vec)
BOOL8 flag(WERD_FLAGS mask) const
const BLOCK * block() const
void plot(ScrollView *window, ScrollView::Color color, ScrollView::Color child_color)
void LocalNormTransform(const TPOINT &pt, TPOINT *transformed) const
inT16 x() const
access function
double x_variance() const
TBOX bounding_box() const
void set_y(float yin)
rewrite function
void LocalNormBlob(TBLOB *blob) const
TBOX bounding_box() const
TBLOB * ClassifyNormalizeIfNeeded() const
void delete_data_pointers()
int edge_strength_at_index(int index) const
void ComputeBoundingBoxes()
void GetPreciseBoundingBox(TBOX *precise_box) const
void plot(ScrollView *window, ScrollView::Color colour) const
bool divisible_blob(TBLOB *blob, bool italic_blob, TPOINT *location)
void CopyFrom(const TESSLINE &src)
void CorrectBlobOrder(TBLOB *next)
void Rotate(const FCOORD rotation)
const TPOINT kDivisibleVerticalUpright(0, 1)
static TBLOB * PolygonalCopy(bool allow_detailed_fx, C_BLOB *src)
void ComputeBoundingBoxes()
FCOORD classify_rotation() const
void ComputeBoundingBox()
int ComputeMoments(FCOORD *center, FCOORD *second_moments) const
EDGEPT * FindBestStartPt() const
TESSLINE * ApproximateOutline(bool allow_detailed_fx, C_OUTLINE *c_outline)
void CopyFrom(const TWERD &src)
FCOORD mean_point() const
C_BLOB_LIST * cblob_list()
void init_to_size(int size, T t)
FCOORD sub_pixel_pos_at_index(const ICOORD &pos, int index) const
static TBLOB * ShallowCopy(const TBLOB &src)
const DENORM * RootDenorm() const
static bool IsCrossed(const TPOINT &a0, const TPOINT &a1, const TPOINT &b0, const TPOINT &b1)
static TWERD * PolygonalCopy(bool allow_detailed_fx, WERD *src)
const ICOORD & botleft() const
void Rotate(const FCOORD rotation)
inT16 y() const
access_function