wordrec/chop.cpp

Go to the documentation of this file.
00001 
00021 /*----------------------------------------------------------------------
00022               I n c l u d e s
00023 ----------------------------------------------------------------------*/
00024 #include "chop.h"
00025 #include "debug.h"
00026 #include "outlines.h"
00027 #include "olutil.h"
00028 #include "tordvars.h"
00029 #include "callcpp.h"
00030 #include "plotedges.h"
00031 #include "const.h"
00032 
00033 #include <math.h>
00034 
00035 /*----------------------------------------------------------------------
00036               V a r i a b l e s
00037 ----------------------------------------------------------------------*/
00038 
00041 make_int_var (chop_debug, 0, make_chop_debug,
00042 3, 1, set_chop_debug, "Chop debug");
00043 make_int_var (chop_enable, 1, make_chop_enable,
00044 3, 2, set_chop_enable, "Chop enable");
00045 make_toggle_var (vertical_creep, 0, make_vertical_creep,
00046 3, 4, set_vertical_creep, "Vertical creep");
00047 make_int_var (split_length, 10000, make_split_length,
00048 3, 5, set_split_length, "Split Length");
00049 make_int_var (same_distance, 2, make_same_distance,
00050 3, 6, set_same_distance, "Same distance");
00051 make_int_var (min_outline_points, 6, make_min_points,
00052 3, 9, set_min_points, "Min Number of Points on Outline");
00053 make_int_var (inside_angle, -50, make_inside_angle,
00054 3, 12, set_inside_angle, "Min Inside Angle Bend");
00055 make_int_var (min_outline_area, 2000, make_outline_area,
00056 3, 13, set_outline_area, "Min Outline Area");
00059 /*----------------------------------------------------------------------
00060               V a r i a b l e s (moved from gradechop)
00061 ----------------------------------------------------------------------*/
00064 make_float_var (split_dist_knob, 0.5, make_split_dist,
00065 3, 17, set_split_dist, "Split length adjustment");
00066 make_float_var (overlap_knob, 0.9, make_overlap_knob,
00067 3, 18, set_overlap_knob, "Split overlap adjustment");
00068 make_float_var (center_knob, 0.15, make_center_knob,
00069 3, 19, set_center_knob, "Split center adjustment");
00070 make_float_var (sharpness_knob, 0.06, make_sharpness_knob,
00071 3, 20, set_sharpness_knob, "Split sharpness adjustment");
00072 make_float_var (width_change_knob, 5.0, make_width_change,
00073 3, 21, set_width_change_knob, "Width change adjustment");
00074 make_float_var (ok_split, 100.0, make_ok_split,
00075 3, 14, set_ok_split, "OK split limit");
00076 make_float_var (good_split, 50.0, make_good_split,
00077 3, 15, set_good_split, "Good split limit");
00078 make_int_var (x_y_weight, 3, make_x_y_weight,
00079 3, 16, set_x_y_weight, "X / Y  length weight");
00082 /*----------------------------------------------------------------------
00083               M a c r o s
00084 ----------------------------------------------------------------------*/
00085 /* ================== */
00092 #define length_product(p1,p2)                                      \
00093 (sqrt ((((float) (p1).x * (p1).x + (float) (p1).y * (p1).y) *    \
00094          ((float) (p2).x * (p2).x + (float) (p2).y * (p2).y))))
00095 
00096 /*----------------------------------------------------------------------
00097               F u n c t i o n s
00098 ----------------------------------------------------------------------*/
00099 /* ================== */
00106 PRIORITY point_priority(EDGEPT *point) {
00107   return ((PRIORITY) point_bend_angle (point));
00108 }
00109 
00110 
00111 /* ================== */
00115 void add_point_to_list(POINT_GROUP point_list, EDGEPT *point) {
00116   HEAPENTRY data;
00117 
00118   if (SizeOfHeap (point_list) < MAX_NUM_POINTS - 2) {
00119     data.Data = (char *) point;
00120     data.Key = point_priority (point);
00121     HeapStore(point_list, &data);
00122   }
00123 
00124 #ifndef GRAPHICS_DISABLED
00125   if (chop_debug)
00126     mark_outline(point);
00127 #endif
00128 }
00129 
00130 
00131 /* ================== */
00136 int angle_change(EDGEPT *point1, EDGEPT *point2, EDGEPT *point3) {
00137   VECTOR vector1;
00138   VECTOR vector2;
00139 
00140   int angle;
00141   float length;
00142 
00143   /* Compute angle */
00144   vector1.x = point2->pos.x - point1->pos.x;
00145   vector1.y = point2->pos.y - point1->pos.y;
00146   vector2.x = point3->pos.x - point2->pos.x;
00147   vector2.y = point3->pos.y - point2->pos.y;
00148   /* Use cross product */
00149   length = length_product (vector1, vector2);
00150   if ((int) length == 0)
00151     return (0);
00152   angle = (int) (asin (CROSS (vector1, vector2) / length) / PI * 180.0);
00153 
00154   /* Use dot product */
00155   if (SCALAR (vector1, vector2) < 0)
00156     angle = 180 - angle;
00157   /* Adjust angle */
00158   if (angle > 180)
00159     angle -= 360;
00160   if (angle <= -180)
00161     angle += 360;
00162   return (angle);
00163 }
00164 
00165 
00166 /* ================== */
00170 void init_chop() {
00171   make_same_distance();
00172   make_vertical_creep();
00173   make_x_y_weight();
00174   make_chop_enable();
00175   make_chop_debug();
00176   make_split_dist();
00177   make_overlap_knob();
00178   make_sharpness_knob();
00179   make_width_change();
00180   make_good_split();
00181   make_ok_split();
00182   make_center_knob();
00183   make_split_length();
00184   make_min_points();
00185   make_inside_angle();
00186   make_outline_area();
00187 }
00188 
00189 
00190 /* ================== */
00195 int is_little_chunk(EDGEPT *point1, EDGEPT *point2) {
00196   EDGEPT *p = point1;            /* Iterator */
00197   int counter = 0;
00198 
00199   do {
00200                                  /* Go from P1 to P2 */
00201     if (is_same_edgept (point2, p)) {
00202       if (is_small_area (point1, point2))
00203         return (TRUE);
00204       else
00205         break;
00206     }
00207     p = p->next;
00208   }
00209   while ((p != point1) && (counter++ < min_outline_points));
00210   /* Go from P2 to P1 */
00211   p = point2;
00212   counter = 0;
00213   do {
00214     if (is_same_edgept (point1, p)) {
00215       return (is_small_area (point2, point1));
00216     }
00217     p = p->next;
00218   }
00219   while ((p != point2) && (counter++ < min_outline_points));
00220 
00221   return (FALSE);
00222 }
00223 
00224 
00225 /* ================== */
00229 int is_small_area(EDGEPT *point1, EDGEPT *point2) {
00230   EDGEPT *p = point1->next;      /* Iterator */
00231   int area = 0;
00232   TPOINT origin;
00233 
00234   do {
00235                                  /* Go from P1 to P2 */
00236     origin.x = p->pos.x - point1->pos.x;
00237     origin.y = p->pos.y - point1->pos.y;
00238     area += CROSS (origin, p->vec);
00239     p = p->next;
00240   }
00241   while (!is_same_edgept (point2, p));
00242 
00243   return (area < min_outline_area);
00244 }
00245 
00246 
00247 /* ================== */
00253 EDGEPT *pick_close_point(EDGEPT *critical_point,
00254                          EDGEPT *vertical_point,
00255                          int *best_dist) {
00256   EDGEPT *best_point = NULL;
00257   int this_distance;
00258   int found_better;
00259 
00260   do {
00261     found_better = FALSE;
00262 
00263     this_distance = edgept_dist (critical_point, vertical_point);
00264     if (this_distance <= *best_dist) {
00265 
00266       if (!(same_point (critical_point->pos, vertical_point->pos) ||
00267         same_point (critical_point->pos, vertical_point->next->pos)
00268         || best_point != NULL
00269         && same_point (best_point->pos, vertical_point->pos) ||
00270       is_exterior_point (critical_point, vertical_point))) {
00271         *best_dist = this_distance;
00272         best_point = vertical_point;
00273         if (vertical_creep)
00274           found_better = TRUE;
00275       }
00276     }
00277     vertical_point = vertical_point->next;
00278   }
00279   while (found_better == TRUE);
00280 
00281   return (best_point);
00282 }
00283 
00284 
00285 /* ================== */
00292 void prioritize_points(TESSLINE *outline, POINT_GROUP points) {
00293   EDGEPT *this_point;
00294   EDGEPT *local_min = NULL;
00295   EDGEPT *local_max = NULL;
00296 
00297   this_point = outline->loop;
00298   local_min = this_point;
00299   local_max = this_point;
00300   do {
00301     if (debug_5)
00302       cprintf ("(%3d,%3d)  min=%3d, max=%3d, dir=%2d, ang=%2.0f\n",
00303         this_point->pos.x, this_point->pos.y,
00304         (local_min ? local_min->pos.y : 999),
00305       (local_max ? local_max->pos.y : 999),
00306       direction (this_point), point_priority (this_point));
00307 
00308     if (this_point->vec.y < 0) {
00309                                  /* Look for minima */
00310       if (local_max != NULL)
00311         new_max_point(local_max, points);
00312       else if (is_inside_angle (this_point))
00313         add_point_to_list(points, this_point);
00314       local_max = NULL;
00315       local_min = this_point->next;
00316     }
00317     else if (this_point->vec.y > 0) {
00318                                  /* Look for maxima */
00319       if (local_min != NULL)
00320         new_min_point(local_min, points);
00321       else if (is_inside_angle (this_point))
00322         add_point_to_list(points, this_point);
00323       local_min = NULL;
00324       local_max = this_point->next;
00325     }
00326     else {
00327       /* Flat area */
00328       if (local_max != NULL) {
00329         if (local_max->prev->vec.y != 0) {
00330           new_max_point(local_max, points);
00331         }
00332         local_max = this_point->next;
00333         local_min = NULL;
00334       }
00335       else {
00336         if (local_min->prev->vec.y != 0) {
00337           new_min_point(local_min, points);
00338         }
00339         local_min = this_point->next;
00340         local_max = NULL;
00341       }
00342     }
00343 
00344                                  /* Next point */
00345     this_point = this_point->next;
00346   }
00347   while (this_point != outline->loop);
00348 }
00349 
00350 
00351 /* ================== */
00358 void new_min_point(EDGEPT *local_min, POINT_GROUP points) {
00359   INT16 dir;
00360 
00361   dir = direction (local_min);
00362 
00363   if (dir < 0) {
00364     add_point_to_list(points, local_min);
00365     return;
00366   }
00367 
00368   if (dir == 0 && point_priority (local_min) < 0) {
00369     add_point_to_list(points, local_min);
00370     return;
00371   }
00372 }
00373 
00374 
00375 /* ================== */
00382 void new_max_point(EDGEPT *local_max, POINT_GROUP points) {
00383   INT16 dir;
00384 
00385   dir = direction (local_max);
00386 
00387   if (dir > 0) {
00388     add_point_to_list(points, local_max);
00389     return;
00390   }
00391 
00392   if (dir == 0 && point_priority (local_max) < 0) {
00393     add_point_to_list(points, local_max);
00394     return;
00395   }
00396 }
00397 
00398 
00399 /* ================== */
00418 void vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point,
00419                                EDGEPT** best_point) {
00420   EDGEPT *p;                     /* Iterator */
00421   EDGEPT *this_edgept;           /* Iterator */
00422   int x = split_point->pos.x;    /* X value of vertical */
00423   int best_dist = LARGE_DISTANCE;/* Best point found */
00424 
00425   if (*best_point != NULL)
00426     best_dist = edgept_dist(split_point, *best_point);
00427 
00428   p = target_point;
00429   /* Look at each edge point */
00430   do {
00431     if ((((p->pos.x <= x) && (x <= p->next->pos.x)) ||
00432       ((p->next->pos.x <= x) && (x <= p->pos.x))) &&
00433       !same_point (split_point->pos, p->pos) &&
00434       !same_point (split_point->pos, p->next->pos)
00435     && (*best_point == NULL || !same_point ((*best_point)->pos, p->pos))) {
00436 
00437       this_edgept = near_point (split_point, p, p->next);
00438 
00439       if (*best_point == NULL)
00440         best_dist = edgept_dist (split_point, this_edgept);
00441 
00442       this_edgept =
00443         pick_close_point(split_point, this_edgept, &best_dist);
00444       if (this_edgept)
00445         *best_point = this_edgept;
00446     }
00447 
00448     p = p->next;
00449   }
00450   while (p != target_point);
00451 }

Generated on Wed Feb 28 19:49:13 2007 for Tesseract by  doxygen 1.5.1