Tesseract  3.02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
chop.cpp
Go to the documentation of this file.
1 /* -*-C-*-
2  ********************************************************************************
3  *
4  * File: chop.c (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 "olutil.h"
33 #include "callcpp.h"
34 #include "plotedges.h"
35 #include "const.h"
36 #include "wordrec.h"
37 
38 #include <math.h>
39 
40 // Include automatically generated configuration file if running autoconf.
41 #ifdef HAVE_CONFIG_H
42 #include "config_auto.h"
43 #endif
44 
45 namespace tesseract {
46 /*----------------------------------------------------------------------
47  F u n c t i o n s
48 ----------------------------------------------------------------------*/
56  return (PRIORITY)angle_change(point->prev, point, point->next);
57 }
58 
59 
65 void Wordrec::add_point_to_list(POINT_GROUP point_list, EDGEPT *point) {
66  HEAPENTRY data;
67 
68  if (SizeOfHeap (point_list) < MAX_NUM_POINTS - 2) {
69  data.Data = (char *) point;
70  data.Key = point_priority (point);
71  HeapStore(point_list, &data);
72  }
73 
74 #ifndef GRAPHICS_DISABLED
75  if (chop_debug > 2)
76  mark_outline(point);
77 #endif
78 }
79 
80 
87 int Wordrec::angle_change(EDGEPT *point1, EDGEPT *point2, EDGEPT *point3) {
88  VECTOR vector1;
89  VECTOR vector2;
90 
91  int angle;
92  float length;
93 
94  /* Compute angle */
95  vector1.x = point2->pos.x - point1->pos.x;
96  vector1.y = point2->pos.y - point1->pos.y;
97  vector2.x = point3->pos.x - point2->pos.x;
98  vector2.y = point3->pos.y - point2->pos.y;
99  /* Use cross product */
100  length = (float)sqrt((float)LENGTH(vector1) * LENGTH(vector2));
101  if ((int) length == 0)
102  return (0);
103  angle = static_cast<int>(floor(asin(CROSS (vector1, vector2) /
104  length) / PI * 180.0 + 0.5));
105 
106  /* Use dot product */
107  if (SCALAR (vector1, vector2) < 0)
108  angle = 180 - angle;
109  /* Adjust angle */
110  if (angle > 180)
111  angle -= 360;
112  if (angle <= -180)
113  angle += 360;
114  return (angle);
115 }
116 
123 int Wordrec::is_little_chunk(EDGEPT *point1, EDGEPT *point2) {
124  EDGEPT *p = point1; /* Iterator */
125  int counter = 0;
126 
127  do {
128  /* Go from P1 to P2 */
129  if (is_same_edgept (point2, p)) {
130  if (is_small_area (point1, point2))
131  return (TRUE);
132  else
133  break;
134  }
135  p = p->next;
136  }
137  while ((p != point1) && (counter++ < chop_min_outline_points));
138  /* Go from P2 to P1 */
139  p = point2;
140  counter = 0;
141  do {
142  if (is_same_edgept (point1, p)) {
143  return (is_small_area (point2, point1));
144  }
145  p = p->next;
146  }
147  while ((p != point2) && (counter++ < chop_min_outline_points));
148 
149  return (FALSE);
150 }
151 
152 
158 int Wordrec::is_small_area(EDGEPT *point1, EDGEPT *point2) {
159  EDGEPT *p = point1->next; /* Iterator */
160  int area = 0;
161  TPOINT origin;
162 
163  do {
164  /* Go from P1 to P2 */
165  origin.x = p->pos.x - point1->pos.x;
166  origin.y = p->pos.y - point1->pos.y;
167  area += CROSS (origin, p->vec);
168  p = p->next;
169  }
170  while (!is_same_edgept (point2, p));
171 
172  return (area < chop_min_outline_area);
173 }
174 
175 
183  EDGEPT *vertical_point,
184  int *best_dist) {
185  EDGEPT *best_point = NULL;
186  int this_distance;
187  int found_better;
188 
189  do {
190  found_better = FALSE;
191 
192  this_distance = edgept_dist (critical_point, vertical_point);
193  if (this_distance <= *best_dist) {
194 
195  if (!(same_point (critical_point->pos, vertical_point->pos) ||
196  same_point (critical_point->pos, vertical_point->next->pos) ||
197  (best_point && same_point (best_point->pos, vertical_point->pos)) ||
198  is_exterior_point (critical_point, vertical_point))) {
199  *best_dist = this_distance;
200  best_point = vertical_point;
202  found_better = TRUE;
203  }
204  }
205  vertical_point = vertical_point->next;
206  }
207  while (found_better == TRUE);
208 
209  return (best_point);
210 }
211 
212 
221  EDGEPT *this_point;
222  EDGEPT *local_min = NULL;
223  EDGEPT *local_max = NULL;
224 
225  this_point = outline->loop;
226  local_min = this_point;
227  local_max = this_point;
228  do {
229  if (this_point->vec.y < 0) {
230  /* Look for minima */
231  if (local_max != NULL)
232  new_max_point(local_max, points);
233  else if (is_inside_angle (this_point))
234  add_point_to_list(points, this_point);
235  local_max = NULL;
236  local_min = this_point->next;
237  }
238  else if (this_point->vec.y > 0) {
239  /* Look for maxima */
240  if (local_min != NULL)
241  new_min_point(local_min, points);
242  else if (is_inside_angle (this_point))
243  add_point_to_list(points, this_point);
244  local_min = NULL;
245  local_max = this_point->next;
246  }
247  else {
248  /* Flat area */
249  if (local_max != NULL) {
250  if (local_max->prev->vec.y != 0) {
251  new_max_point(local_max, points);
252  }
253  local_max = this_point->next;
254  local_min = NULL;
255  }
256  else {
257  if (local_min->prev->vec.y != 0) {
258  new_min_point(local_min, points);
259  }
260  local_min = this_point->next;
261  local_max = NULL;
262  }
263  }
264 
265  /* Next point */
266  this_point = this_point->next;
267  }
268  while (this_point != outline->loop);
269 }
270 
271 
279 void Wordrec::new_min_point(EDGEPT *local_min, POINT_GROUP points) {
280  inT16 dir;
281 
282  dir = direction (local_min);
283 
284  if (dir < 0) {
285  add_point_to_list(points, local_min);
286  return;
287  }
288 
289  if (dir == 0 && point_priority (local_min) < 0) {
290  add_point_to_list(points, local_min);
291  return;
292  }
293 }
294 
295 
303 void Wordrec::new_max_point(EDGEPT *local_max, POINT_GROUP points) {
304  inT16 dir;
305 
306  dir = direction (local_max);
307 
308  if (dir > 0) {
309  add_point_to_list(points, local_max);
310  return;
311  }
312 
313  if (dir == 0 && point_priority (local_max) < 0) {
314  add_point_to_list(points, local_max);
315  return;
316  }
317 }
318 
319 
332 void Wordrec::vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point,
333  EDGEPT** best_point,
334  EDGEPT_CLIST *new_points) {
335  EDGEPT *p; /* Iterator */
336  EDGEPT *this_edgept; /* Iterator */
337  EDGEPT_C_IT new_point_it(new_points);
338  int x = split_point->pos.x; /* X value of vertical */
339  int best_dist = LARGE_DISTANCE;/* Best point found */
340 
341  if (*best_point != NULL)
342  best_dist = edgept_dist(split_point, *best_point);
343 
344  p = target_point;
345  /* Look at each edge point */
346  do {
347  if ((((p->pos.x <= x) && (x <= p->next->pos.x)) ||
348  ((p->next->pos.x <= x) && (x <= p->pos.x))) &&
349  !same_point (split_point->pos, p->pos) &&
350  !same_point (split_point->pos, p->next->pos)
351  && (*best_point == NULL || !same_point ((*best_point)->pos, p->pos))) {
352 
353  if (near_point(split_point, p, p->next, &this_edgept)) {
354  new_point_it.add_before_then_move(this_edgept);
355  }
356 
357  if (*best_point == NULL)
358  best_dist = edgept_dist (split_point, this_edgept);
359 
360  this_edgept =
361  pick_close_point(split_point, this_edgept, &best_dist);
362  if (this_edgept)
363  *best_point = this_edgept;
364  }
365 
366  p = p->next;
367  }
368  while (p != target_point);
369 }
370 
371 } // namespace tesseract