00001
00020
00021
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
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
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) {
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++;
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++;
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 }