Tesseract 3.02

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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 ----------------------------------------------------------------------*/
55 PRIORITY Wordrec::point_priority(EDGEPT *point) {
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
182 EDGEPT *Wordrec::pick_close_point(EDGEPT *critical_point,
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;
201 if (chop_vertical_creep)
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
220 void Wordrec::prioritize_points(TESSLINE *outline, POINT_GROUP points) {
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