tesseract  4.0.0-1-g2a2b
chop.cpp
Go to the documentation of this file.
1 /* -*-C-*-
2  ******************************************************************************
3  *
4  * File: chop.cpp (Formerly chop.c)
5  * Description:
6  * Author: Mark Seaman, OCR Technology
7  * Created: Fri Oct 16 14:37:00 1987
8  * Modified: Tue Jul 30 16:41:11 1991 (Mark Seaman) marks@hpgrlt
9  * Language: C
10  * Package: N/A
11  * Status: Reusable Software Component
12  *
13  * (c) Copyright 1987, Hewlett-Packard Company.
14  ** Licensed under the Apache License, Version 2.0 (the "License");
15  ** you may not use this file except in compliance with the License.
16  ** You may obtain a copy of the License at
17  ** http://www.apache.org/licenses/LICENSE-2.0
18  ** Unless required by applicable law or agreed to in writing, software
19  ** distributed under the License is distributed on an "AS IS" BASIS,
20  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  ** See the License for the specific language governing permissions and
22  ** limitations under the License.
23  *
24  *****************************************************************************/
25 
26 /*----------------------------------------------------------------------
27  I n c l u d e s
28 ----------------------------------------------------------------------*/
29 
30 #include "chop.h"
31 #include "outlines.h"
32 #include "callcpp.h"
33 #include "plotedges.h"
34 #include "wordrec.h"
35 
36 #include <cmath>
37 
38 // Include automatically generated configuration file if running autoconf.
39 #ifdef HAVE_CONFIG_H
40 #include "config_auto.h"
41 #endif
42 
43 namespace tesseract {
44 /*----------------------------------------------------------------------
45  F u n c t i o n s
46 ----------------------------------------------------------------------*/
54  return (PRIORITY)angle_change(point->prev, point, point->next);
55 }
56 
57 
63 void Wordrec::add_point_to_list(PointHeap* point_heap, EDGEPT *point) {
64  if (point_heap->size() < MAX_NUM_POINTS - 2) {
65  PointPair pair(point_priority(point), point);
66  point_heap->Push(&pair);
67  }
68 
69 #ifndef GRAPHICS_DISABLED
70  if (chop_debug > 2)
71  mark_outline(point);
72 #endif
73 }
74 
75 // Returns true if the edgept supplied as input is an inside angle. This
76 // is determined by the angular change of the vectors from point to point.
78  return angle_change(pt->prev, pt, pt->next) < chop_inside_angle;
79 }
80 
87 int Wordrec::angle_change(EDGEPT *point1, EDGEPT *point2, EDGEPT *point3) {
88  VECTOR vector1;
89  VECTOR vector2;
90 
91  int angle;
92 
93  /* Compute angle */
94  vector1.x = point2->pos.x - point1->pos.x;
95  vector1.y = point2->pos.y - point1->pos.y;
96  vector2.x = point3->pos.x - point2->pos.x;
97  vector2.y = point3->pos.y - point2->pos.y;
98  /* Use cross product */
99  float length = std::sqrt(static_cast<float>(LENGTH(vector1)) * LENGTH(vector2));
100  if ((int) length == 0)
101  return (0);
102  angle = static_cast<int>(floor(asin(CROSS (vector1, vector2) /
103  length) / M_PI * 180.0 + 0.5));
104 
105  /* Use dot product */
106  if (SCALAR (vector1, vector2) < 0)
107  angle = 180 - angle;
108  /* Adjust angle */
109  if (angle > 180)
110  angle -= 360;
111  if (angle <= -180)
112  angle += 360;
113  return (angle);
114 }
115 
123  EDGEPT *vertical_point,
124  int *best_dist) {
125  EDGEPT *best_point = nullptr;
126  int this_distance;
127  int found_better;
128 
129  do {
130  found_better = FALSE;
131 
132  this_distance = edgept_dist (critical_point, vertical_point);
133  if (this_distance <= *best_dist) {
134 
135  if (!(same_point (critical_point->pos, vertical_point->pos) ||
136  same_point (critical_point->pos, vertical_point->next->pos) ||
137  (best_point && same_point (best_point->pos, vertical_point->pos)) ||
138  is_exterior_point (critical_point, vertical_point))) {
139  *best_dist = this_distance;
140  best_point = vertical_point;
142  found_better = TRUE;
143  }
144  }
145  vertical_point = vertical_point->next;
146  }
147  while (found_better == TRUE);
148 
149  return (best_point);
150 }
151 
152 
161  EDGEPT *this_point;
162  EDGEPT *local_min = nullptr;
163  EDGEPT *local_max = nullptr;
164 
165  this_point = outline->loop;
166  local_min = this_point;
167  local_max = this_point;
168  do {
169  if (this_point->vec.y < 0) {
170  /* Look for minima */
171  if (local_max != nullptr)
172  new_max_point(local_max, points);
173  else if (is_inside_angle (this_point))
174  add_point_to_list(points, this_point);
175  local_max = nullptr;
176  local_min = this_point->next;
177  }
178  else if (this_point->vec.y > 0) {
179  /* Look for maxima */
180  if (local_min != nullptr)
181  new_min_point(local_min, points);
182  else if (is_inside_angle (this_point))
183  add_point_to_list(points, this_point);
184  local_min = nullptr;
185  local_max = this_point->next;
186  }
187  else {
188  /* Flat area */
189  if (local_max != nullptr) {
190  if (local_max->prev->vec.y != 0) {
191  new_max_point(local_max, points);
192  }
193  local_max = this_point->next;
194  local_min = nullptr;
195  }
196  else {
197  if (local_min->prev->vec.y != 0) {
198  new_min_point(local_min, points);
199  }
200  local_min = this_point->next;
201  local_max = nullptr;
202  }
203  }
204 
205  /* Next point */
206  this_point = this_point->next;
207  }
208  while (this_point != outline->loop);
209 }
210 
211 
219 void Wordrec::new_min_point(EDGEPT *local_min, PointHeap* points) {
220  int16_t dir;
221 
222  dir = direction (local_min);
223 
224  if (dir < 0) {
225  add_point_to_list(points, local_min);
226  return;
227  }
228 
229  if (dir == 0 && point_priority (local_min) < 0) {
230  add_point_to_list(points, local_min);
231  return;
232  }
233 }
234 
235 
243 void Wordrec::new_max_point(EDGEPT *local_max, PointHeap* points) {
244  int16_t dir;
245 
246  dir = direction (local_max);
247 
248  if (dir > 0) {
249  add_point_to_list(points, local_max);
250  return;
251  }
252 
253  if (dir == 0 && point_priority (local_max) < 0) {
254  add_point_to_list(points, local_max);
255  return;
256  }
257 }
258 
259 
272 void Wordrec::vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point,
273  EDGEPT** best_point,
274  EDGEPT_CLIST *new_points) {
275  EDGEPT *p; /* Iterator */
276  EDGEPT *this_edgept; /* Iterator */
277  EDGEPT_C_IT new_point_it(new_points);
278  int x = split_point->pos.x; /* X value of vertical */
279  int best_dist = LARGE_DISTANCE;/* Best point found */
280 
281  if (*best_point != nullptr)
282  best_dist = edgept_dist(split_point, *best_point);
283 
284  p = target_point;
285  /* Look at each edge point */
286  do {
287  if (((p->pos.x <= x && x <= p->next->pos.x) ||
288  (p->next->pos.x <= x && x <= p->pos.x)) &&
289  !same_point(split_point->pos, p->pos) &&
290  !same_point(split_point->pos, p->next->pos) &&
291  !p->IsChopPt() &&
292  (*best_point == nullptr || !same_point((*best_point)->pos, p->pos))) {
293 
294  if (near_point(split_point, p, p->next, &this_edgept)) {
295  new_point_it.add_before_then_move(this_edgept);
296  }
297 
298  if (*best_point == nullptr)
299  best_dist = edgept_dist (split_point, this_edgept);
300 
301  this_edgept =
302  pick_close_point(split_point, this_edgept, &best_dist);
303  if (this_edgept)
304  *best_point = this_edgept;
305  }
306 
307  p = p->next;
308  }
309  while (p != target_point);
310 }
311 
312 } // namespace tesseract
#define TRUE
Definition: capi.h:51
void add_point_to_list(PointHeap *point_heap, EDGEPT *point)
Definition: chop.cpp:63
TPOINT pos
Definition: blobs.h:170
#define MAX_NUM_POINTS
Definition: chop.h:39
#define edgept_dist(p1, p2)
Definition: outlines.h:88
#define CROSS(a, b)
Definition: vecfuncs.h:52
int direction(EDGEPT *point)
Definition: vecfuncs.cpp:43
#define SCALAR(a, b)
Definition: vecfuncs.h:61
#define LENGTH(a)
Definition: vecfuncs.h:70
bool near_point(EDGEPT *point, EDGEPT *line_pt_0, EDGEPT *line_pt_1, EDGEPT **near_pt)
Definition: outlines.cpp:45
PRIORITY point_priority(EDGEPT *point)
Definition: chop.cpp:53
EDGEPT * loop
Definition: blobs.h:264
bool chop_vertical_creep
Definition: wordrec.h:210
#define FALSE
Definition: capi.h:52
VECTOR vec
Definition: blobs.h:171
Definition: blobs.h:83
EDGEPT * prev
Definition: blobs.h:177
void Push(Pair *entry)
Definition: genericheap.h:95
EDGEPT * pick_close_point(EDGEPT *critical_point, EDGEPT *vertical_point, int *best_dist)
Definition: chop.cpp:122
void mark_outline(EDGEPT *edgept)
Definition: plotedges.cpp:92
void prioritize_points(TESSLINE *outline, PointHeap *points)
Definition: chop.cpp:160
int16_t x
Definition: blobs.h:78
float PRIORITY
Definition: seam.h:42
#define LARGE_DISTANCE
Definition: outlines.h:37
void vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point, EDGEPT **best_point, EDGEPT_CLIST *new_points)
Definition: chop.cpp:272
bool IsChopPt() const
Definition: blobs.h:166
void new_min_point(EDGEPT *local_min, PointHeap *points)
Definition: chop.cpp:219
Definition: blobs.h:57
#define same_point(p1, p2)
Definition: outlines.h:50
int16_t y
Definition: blobs.h:79
EDGEPT * next
Definition: blobs.h:176
#define is_exterior_point(edge, point)
Definition: outlines.h:98
int angle_change(EDGEPT *point1, EDGEPT *point2, EDGEPT *point3)
Definition: chop.cpp:87
void new_max_point(EDGEPT *local_max, PointHeap *points)
Definition: chop.cpp:243
bool is_inside_angle(EDGEPT *pt)
Definition: chop.cpp:77