tesseract 3.04.01

wordrec/chop.cpp

Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines