|
tesseract 3.04.01
|
00001 /* -*-C-*- 00002 ******************************************************************************** 00003 * 00004 * File: chop.c (Formerly chop.c) 00005 * Description: 00006 * Author: Mark Seaman, OCR Technology 00007 * Created: Fri Oct 16 14:37:00 1987 00008 * Modified: Tue Jul 30 16:41:11 1991 (Mark Seaman) marks@hpgrlt 00009 * Language: C 00010 * Package: N/A 00011 * Status: Reusable Software Component 00012 * 00013 * (c) Copyright 1987, Hewlett-Packard Company. 00014 ** Licensed under the Apache License, Version 2.0 (the "License"); 00015 ** you may not use this file except in compliance with the License. 00016 ** You may obtain a copy of the License at 00017 ** http://www.apache.org/licenses/LICENSE-2.0 00018 ** Unless required by applicable law or agreed to in writing, software 00019 ** distributed under the License is distributed on an "AS IS" BASIS, 00020 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00021 ** See the License for the specific language governing permissions and 00022 ** limitations under the License. 00023 * 00024 *********************************************************************************/ 00025 00026 /*---------------------------------------------------------------------- 00027 I n c l u d e s 00028 ----------------------------------------------------------------------*/ 00029 00030 #include "chop.h" 00031 #include "outlines.h" 00032 #include "callcpp.h" 00033 #include "plotedges.h" 00034 #include "const.h" 00035 #include "wordrec.h" 00036 00037 #include <math.h> 00038 00039 // Include automatically generated configuration file if running autoconf. 00040 #ifdef HAVE_CONFIG_H 00041 #include "config_auto.h" 00042 #endif 00043 00044 namespace tesseract { 00045 /*---------------------------------------------------------------------- 00046 F u n c t i o n s 00047 ----------------------------------------------------------------------*/ 00054 PRIORITY Wordrec::point_priority(EDGEPT *point) { 00055 return (PRIORITY)angle_change(point->prev, point, point->next); 00056 } 00057 00058 00064 void Wordrec::add_point_to_list(PointHeap* point_heap, EDGEPT *point) { 00065 if (point_heap->size() < MAX_NUM_POINTS - 2) { 00066 PointPair pair(point_priority(point), point); 00067 point_heap->Push(&pair); 00068 } 00069 00070 #ifndef GRAPHICS_DISABLED 00071 if (chop_debug > 2) 00072 mark_outline(point); 00073 #endif 00074 } 00075 00076 // Returns true if the edgept supplied as input is an inside angle. This 00077 // is determined by the angular change of the vectors from point to point. 00078 bool Wordrec::is_inside_angle(EDGEPT *pt) { 00079 return angle_change(pt->prev, pt, pt->next) < chop_inside_angle; 00080 } 00081 00088 int Wordrec::angle_change(EDGEPT *point1, EDGEPT *point2, EDGEPT *point3) { 00089 VECTOR vector1; 00090 VECTOR vector2; 00091 00092 int angle; 00093 float length; 00094 00095 /* Compute angle */ 00096 vector1.x = point2->pos.x - point1->pos.x; 00097 vector1.y = point2->pos.y - point1->pos.y; 00098 vector2.x = point3->pos.x - point2->pos.x; 00099 vector2.y = point3->pos.y - point2->pos.y; 00100 /* Use cross product */ 00101 length = (float)sqrt((float)LENGTH(vector1) * LENGTH(vector2)); 00102 if ((int) length == 0) 00103 return (0); 00104 angle = static_cast<int>(floor(asin(CROSS (vector1, vector2) / 00105 length) / PI * 180.0 + 0.5)); 00106 00107 /* Use dot product */ 00108 if (SCALAR (vector1, vector2) < 0) 00109 angle = 180 - angle; 00110 /* Adjust angle */ 00111 if (angle > 180) 00112 angle -= 360; 00113 if (angle <= -180) 00114 angle += 360; 00115 return (angle); 00116 } 00117 00124 EDGEPT *Wordrec::pick_close_point(EDGEPT *critical_point, 00125 EDGEPT *vertical_point, 00126 int *best_dist) { 00127 EDGEPT *best_point = NULL; 00128 int this_distance; 00129 int found_better; 00130 00131 do { 00132 found_better = FALSE; 00133 00134 this_distance = edgept_dist (critical_point, vertical_point); 00135 if (this_distance <= *best_dist) { 00136 00137 if (!(same_point (critical_point->pos, vertical_point->pos) || 00138 same_point (critical_point->pos, vertical_point->next->pos) || 00139 (best_point && same_point (best_point->pos, vertical_point->pos)) || 00140 is_exterior_point (critical_point, vertical_point))) { 00141 *best_dist = this_distance; 00142 best_point = vertical_point; 00143 if (chop_vertical_creep) 00144 found_better = TRUE; 00145 } 00146 } 00147 vertical_point = vertical_point->next; 00148 } 00149 while (found_better == TRUE); 00150 00151 return (best_point); 00152 } 00153 00154 00162 void Wordrec::prioritize_points(TESSLINE *outline, PointHeap* points) { 00163 EDGEPT *this_point; 00164 EDGEPT *local_min = NULL; 00165 EDGEPT *local_max = NULL; 00166 00167 this_point = outline->loop; 00168 local_min = this_point; 00169 local_max = this_point; 00170 do { 00171 if (this_point->vec.y < 0) { 00172 /* Look for minima */ 00173 if (local_max != NULL) 00174 new_max_point(local_max, points); 00175 else if (is_inside_angle (this_point)) 00176 add_point_to_list(points, this_point); 00177 local_max = NULL; 00178 local_min = this_point->next; 00179 } 00180 else if (this_point->vec.y > 0) { 00181 /* Look for maxima */ 00182 if (local_min != NULL) 00183 new_min_point(local_min, points); 00184 else if (is_inside_angle (this_point)) 00185 add_point_to_list(points, this_point); 00186 local_min = NULL; 00187 local_max = this_point->next; 00188 } 00189 else { 00190 /* Flat area */ 00191 if (local_max != NULL) { 00192 if (local_max->prev->vec.y != 0) { 00193 new_max_point(local_max, points); 00194 } 00195 local_max = this_point->next; 00196 local_min = NULL; 00197 } 00198 else { 00199 if (local_min->prev->vec.y != 0) { 00200 new_min_point(local_min, points); 00201 } 00202 local_min = this_point->next; 00203 local_max = NULL; 00204 } 00205 } 00206 00207 /* Next point */ 00208 this_point = this_point->next; 00209 } 00210 while (this_point != outline->loop); 00211 } 00212 00213 00221 void Wordrec::new_min_point(EDGEPT *local_min, PointHeap* points) { 00222 inT16 dir; 00223 00224 dir = direction (local_min); 00225 00226 if (dir < 0) { 00227 add_point_to_list(points, local_min); 00228 return; 00229 } 00230 00231 if (dir == 0 && point_priority (local_min) < 0) { 00232 add_point_to_list(points, local_min); 00233 return; 00234 } 00235 } 00236 00237 00245 void Wordrec::new_max_point(EDGEPT *local_max, PointHeap* points) { 00246 inT16 dir; 00247 00248 dir = direction (local_max); 00249 00250 if (dir > 0) { 00251 add_point_to_list(points, local_max); 00252 return; 00253 } 00254 00255 if (dir == 0 && point_priority (local_max) < 0) { 00256 add_point_to_list(points, local_max); 00257 return; 00258 } 00259 } 00260 00261 00274 void Wordrec::vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point, 00275 EDGEPT** best_point, 00276 EDGEPT_CLIST *new_points) { 00277 EDGEPT *p; /* Iterator */ 00278 EDGEPT *this_edgept; /* Iterator */ 00279 EDGEPT_C_IT new_point_it(new_points); 00280 int x = split_point->pos.x; /* X value of vertical */ 00281 int best_dist = LARGE_DISTANCE;/* Best point found */ 00282 00283 if (*best_point != NULL) 00284 best_dist = edgept_dist(split_point, *best_point); 00285 00286 p = target_point; 00287 /* Look at each edge point */ 00288 do { 00289 if (((p->pos.x <= x && x <= p->next->pos.x) || 00290 (p->next->pos.x <= x && x <= p->pos.x)) && 00291 !same_point(split_point->pos, p->pos) && 00292 !same_point(split_point->pos, p->next->pos) && 00293 !p->IsChopPt() && 00294 (*best_point == NULL || !same_point((*best_point)->pos, p->pos))) { 00295 00296 if (near_point(split_point, p, p->next, &this_edgept)) { 00297 new_point_it.add_before_then_move(this_edgept); 00298 } 00299 00300 if (*best_point == NULL) 00301 best_dist = edgept_dist (split_point, this_edgept); 00302 00303 this_edgept = 00304 pick_close_point(split_point, this_edgept, &best_dist); 00305 if (this_edgept) 00306 *best_point = this_edgept; 00307 } 00308 00309 p = p->next; 00310 } 00311 while (p != target_point); 00312 } 00313 00314 } // namespace tesseract