wordrec/seam.cpp

Go to the documentation of this file.
00001 
00020 /*----------------------------------------------------------------------
00021               I n c l u d e s
00022 ----------------------------------------------------------------------*/
00023 #include "seam.h"
00024 #include "callcpp.h"
00025 #include "structures.h"
00026 #include "makechop.h"
00027 
00028 #ifdef __UNIX__
00029 #include <assert.h>
00030 #endif
00031 
00032 /*----------------------------------------------------------------------
00033               V a r i a b l e s
00034 ----------------------------------------------------------------------*/
00035 #define NUM_STARTING_SEAMS  20
00036 
00038 #define SEAMBLOCK 100
00039 
00042 makestructure (newseam, free_seam, printseam, SEAM,
00043 freeseam, SEAMBLOCK, "SEAM", seamcount);
00046 /*----------------------------------------------------------------------
00047         Public Function Code
00048 ----------------------------------------------------------------------*/
00049 /* ================== */
00056 bool point_in_split(SPLIT *split, EDGEPT *point1, EDGEPT *point2) { 
00057   return ((split) ?
00058     ((exact_point (split->point1, point1) ||
00059     exact_point (split->point1, point2) ||
00060     exact_point (split->point2, point1) ||
00061     exact_point (split->point2, point2)) ? TRUE : FALSE) : FALSE);
00062 }
00063 
00064 
00065 /* ================== */
00072 bool point_in_seam(SEAM *seam, SPLIT *split) { 
00073   return (point_in_split (seam->split1, split->point1, split->point2) ||
00074     point_in_split (seam->split2, split->point1, split->point2) ||
00075     point_in_split (seam->split3, split->point1, split->point2));
00076 }
00077 
00078 
00079 /* ================== */
00083 SEAMS add_seam(SEAMS seam_list, SEAM *seam) {
00084   return (array_push (seam_list, seam));
00085 }
00086 
00087 
00088 /* ================== */
00095 void combine_seams(SEAM *dest_seam, SEAM *source_seam) {
00096   dest_seam->priority += source_seam->priority;
00097   dest_seam->location += source_seam->location;
00098   dest_seam->location /= 2;
00099 
00100   if (source_seam->split1) {
00101     if (!dest_seam->split1)
00102       dest_seam->split1 = source_seam->split1;
00103     else if (!dest_seam->split2)
00104       dest_seam->split2 = source_seam->split1;
00105     else if (!dest_seam->split3)
00106       dest_seam->split3 = source_seam->split1;
00107     else
00108       cprintf ("combine_seam: Seam is too crowded, can't be combined !\n");
00109   }
00110   if (source_seam->split2) {
00111     if (!dest_seam->split2)
00112       dest_seam->split2 = source_seam->split2;
00113     else if (!dest_seam->split3)
00114       dest_seam->split3 = source_seam->split2;
00115     else
00116       cprintf ("combine_seam: Seam is too crowded, can't be combined !\n");
00117   }
00118   if (source_seam->split3) {
00119     if (!dest_seam->split3)
00120       dest_seam->split3 = source_seam->split3;
00121     else
00122       cprintf ("combine_seam: Seam is too crowded, can't be combined !\n");
00123   }
00124   free_seam(source_seam);
00125 }
00126 
00127 
00128 /* ================== */
00132 void delete_seam(void *arg) {  //SEAM  *seam)
00133   SEAM *seam = (SEAM *) arg;
00134 
00135   if (seam) {
00136     if (seam->split1)
00137       delete_split (seam->split1);
00138     if (seam->split2)
00139       delete_split (seam->split2);
00140     if (seam->split3)
00141       delete_split (seam->split3);
00142     free_seam(seam);
00143   }
00144 }
00145 
00146 
00147 /* ================== */
00153 void free_seam_list(SEAMS seam_list) {
00154   int x;
00155 
00156   array_loop (seam_list, x) delete_seam (array_value (seam_list, x));
00157   array_free(seam_list);
00158 }
00159 
00160 
00161 /* ================== */
00165 bool test_insert_seam(SEAMS seam_list,
00166                       int index,
00167                       TBLOB *left_blob,
00168                       TBLOB *first_blob) {
00169   SEAM *test_seam;
00170   TBLOB *blob;
00171   int test_index;
00172   int list_length;
00173 
00174   list_length = array_count (seam_list);
00175   for (test_index = 0, blob = first_blob->next;
00176   test_index < index; test_index++, blob = blob->next) {
00177     test_seam = (SEAM *) array_value (seam_list, test_index);
00178     if (test_index + test_seam->widthp < index &&
00179         test_seam->widthp + test_index == index - 1 &&
00180         account_splits_right(test_seam, blob) < 0)
00181       return false;
00182   }
00183   for (test_index = index, blob = left_blob->next;
00184   test_index < list_length; test_index++, blob = blob->next) {
00185     test_seam = (SEAM *) array_value (seam_list, test_index);
00186     if (test_index - test_seam->widthn >= index &&
00187         test_index - test_seam->widthn == index &&
00188         account_splits_left(test_seam, first_blob, blob) < 0)
00189       return false;
00190   }
00191   return true;
00192 }
00193 
00200 SEAMS insert_seam(SEAMS seam_list,
00201                   int index,
00202                   SEAM *seam,
00203                   TBLOB *left_blob,
00204                   TBLOB *first_blob) {
00205   SEAM *test_seam;
00206   TBLOB *blob;
00207   int test_index;
00208   int list_length;
00209 
00210   list_length = array_count (seam_list);
00211   for (test_index = 0, blob = first_blob->next;
00212   test_index < index; test_index++, blob = blob->next) {
00213     test_seam = (SEAM *) array_value (seam_list, test_index);
00214     if (test_index + test_seam->widthp >= index) {
00215       test_seam->widthp++;       /*got in the way */
00216     }
00217     else if (test_seam->widthp + test_index == index - 1) {
00218       test_seam->widthp = account_splits_right(test_seam, blob);
00219       if (test_seam->widthp < 0) {
00220         cprintf ("Failed to find any right blob for a split!\n");
00221         print_seam("New dud seam", seam);
00222         print_seam("Failed seam", test_seam);
00223       }
00224     }
00225   }
00226   for (test_index = index, blob = left_blob->next;
00227   test_index < list_length; test_index++, blob = blob->next) {
00228     test_seam = (SEAM *) array_value (seam_list, test_index);
00229     if (test_index - test_seam->widthn < index) {
00230       test_seam->widthn++;       /*got in the way */
00231     }
00232     else if (test_index - test_seam->widthn == index) {
00233       test_seam->widthn = account_splits_left(test_seam, first_blob, blob);
00234       if (test_seam->widthn < 0) {
00235         cprintf ("Failed to find any left blob for a split!\n");
00236         print_seam("New dud seam", seam);
00237         print_seam("Failed seam", test_seam);
00238       }
00239     }
00240   }
00241   return (array_insert (seam_list, index, seam));
00242 }
00243 
00244 
00245 /* ================== */
00250 int account_splits_right(SEAM *seam, TBLOB *blob) {
00251   INT8 found_em[3];
00252   INT8 width;
00253 
00254   found_em[0] = seam->split1 == NULL;
00255   found_em[1] = seam->split2 == NULL;
00256   found_em[2] = seam->split3 == NULL;
00257   if (found_em[0] && found_em[1] && found_em[2])
00258     return 0;
00259   width = 0;
00260   do {
00261     if (!found_em[0])
00262       found_em[0] = find_split_in_blob (seam->split1, blob);
00263     if (!found_em[1])
00264       found_em[1] = find_split_in_blob (seam->split2, blob);
00265     if (!found_em[2])
00266       found_em[2] = find_split_in_blob (seam->split3, blob);
00267     if (found_em[0] && found_em[1] && found_em[2]) {
00268       return width;
00269     }
00270     width++;
00271     blob = blob->next;
00272   }
00273   while (blob != NULL);
00274   return -1;
00275 }
00276 
00277 
00278 /* ================== */
00283 int account_splits_left(SEAM *seam, TBLOB *blob, TBLOB *end_blob) {
00284   static INT32 depth = 0;
00285   static INT8 width;
00286   static INT8 found_em[3];
00287 
00288   if (blob != end_blob) {
00289     depth++;
00290     account_splits_left (seam, blob->next, end_blob);
00291     depth--;
00292   }
00293   else {
00294     found_em[0] = seam->split1 == NULL;
00295     found_em[1] = seam->split2 == NULL;
00296     found_em[2] = seam->split3 == NULL;
00297     width = 0;
00298   }
00299   if (!found_em[0])
00300     found_em[0] = find_split_in_blob (seam->split1, blob);
00301   if (!found_em[1])
00302     found_em[1] = find_split_in_blob (seam->split2, blob);
00303   if (!found_em[2])
00304     found_em[2] = find_split_in_blob (seam->split3, blob);
00305   if (!found_em[0] || !found_em[1] || !found_em[2]) {
00306     width++;
00307     if (depth == 0) {
00308       width = -1;
00309     }
00310   }
00311   return width;
00312 }
00313 
00314 
00315 /* ================== */
00319 bool find_split_in_blob(SPLIT *split, TBLOB *blob) {
00320   TESSLINE *outline;
00321 
00322 #if 0
00323   for (outline = blob->outlines; outline != NULL; outline = outline->next)
00324     if (is_split_outline (outline, split))
00325       return TRUE;
00326   return FALSE;
00327 #endif
00328   for (outline = blob->outlines; outline != NULL; outline = outline->next)
00329     if (point_in_outline(split->point1, outline))
00330       break;
00331   if (outline == NULL)
00332     return FALSE;
00333   for (outline = blob->outlines; outline != NULL; outline = outline->next)
00334     if (point_in_outline(split->point2, outline))
00335       return TRUE;
00336   return FALSE;
00337 }
00338 
00339 
00340 /* ================== */
00347 SEAM *join_two_seams(SEAM *seam1, SEAM *seam2) { 
00348   SEAM *result = NULL;
00349   SEAM *temp;
00350 
00351   assert(seam1 &&seam2);
00352 
00353   if ((seam1->split3 == NULL && seam2->split2 == NULL ||
00354     seam1->split2 == NULL && seam2->split3 == NULL ||
00355     seam1->split1 == NULL ||
00356   seam2->split1 == NULL) && (!shared_split_points (seam1, seam2))) {
00357     clone_seam(result, seam1);
00358     clone_seam(temp, seam2);
00359     combine_seams(result, temp);
00360   }
00361   return (result);
00362 }
00363 
00364 
00365 /* ================== */
00372 SEAM *new_seam(PRIORITY priority,
00373                int x_location,
00374                SPLIT *split1,
00375                SPLIT *split2,
00376                SPLIT *split3) {
00377   SEAM *seam;
00378 
00379   seam = newseam ();
00380 
00381   seam->priority = priority;
00382   seam->location = x_location;
00383   seam->widthp = 0;
00384   seam->widthn = 0;
00385   seam->split1 = split1;
00386   seam->split2 = split2;
00387   seam->split3 = split3;
00388 
00389   return (seam);
00390 }
00391 
00392 
00393 /* ================== */
00397 SEAMS new_seam_list() {
00398   return (array_new (NUM_STARTING_SEAMS));
00399 }
00400 
00401 
00402 /* ================== */
00408 void print_seam(const char *label, SEAM *seam) {
00409   if (seam) {
00410     cprintf(label);
00411     cprintf (" %6.2f @ %5d, p=%d, n=%d ",
00412       seam->priority, seam->location, seam->widthp, seam->widthn);
00413 
00414     print_split (seam->split1);
00415 
00416     if (seam->split2) {
00417       cprintf (",   ");
00418       print_split (seam->split2);
00419 
00420       if (seam->split3) {
00421         cprintf (",   ");
00422         print_split (seam->split3);
00423       }
00424     }
00425     cprintf ("\n");
00426   }
00427 }
00428 
00429 
00430 /* ================== */
00436 void print_seams(const char *label, SEAMS seams) {
00437   int x;
00438   char number[CHARS_PER_LINE];
00439 
00440   if (seams) {
00441     cprintf ("%s\n", label);
00442     array_loop(seams, x) {
00443       sprintf (number, "%2d:   ", x);
00444       print_seam (number, (SEAM *) array_value (seams, x));
00445     }
00446     cprintf ("\n");
00447   }
00448 }
00449 
00450 
00451 /* ================== */
00459 int shared_split_points(SEAM *seam1, SEAM *seam2) {
00460   if (seam1 == NULL || seam2 == NULL)
00461     return (FALSE);
00462 
00463   if (seam2->split1 == NULL)
00464     return (FALSE);
00465   if (point_in_seam (seam1, seam2->split1))
00466     return (TRUE);
00467 
00468   if (seam2->split2 == NULL)
00469     return (FALSE);
00470   if (point_in_seam (seam1, seam2->split2))
00471     return (TRUE);
00472 
00473   if (seam2->split3 == NULL)
00474     return (FALSE);
00475   if (point_in_seam (seam1, seam2->split3))
00476     return (TRUE);
00477 
00478   return (FALSE);
00479 }

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