tesseract  3.03
/usr/local/google/home/jbreiden/tesseract-ocr-read-only/ccstruct/split.cpp
Go to the documentation of this file.
00001 /* -*-C-*-
00002  ********************************************************************************
00003  *
00004  * File:        split.c  (Formerly split.c)
00005  * Description:
00006  * Author:       Mark Seaman, OCR Technology
00007  * Created:      Fri Oct 16 14:37:00 1987
00008  * Modified:     Fri May 17 16:27:49 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               I n c l u d e s
00027 ----------------------------------------------------------------------*/
00028 #include "split.h"
00029 #include "coutln.h"
00030 #include "tprintf.h"
00031 
00032 #ifdef __UNIX__
00033 #include <assert.h>
00034 #endif
00035 
00036 /*----------------------------------------------------------------------
00037               V a r i a b l e s
00038 ----------------------------------------------------------------------*/
00039 BOOL_VAR(wordrec_display_splits, 0, "Display splits");
00040 
00041 /*----------------------------------------------------------------------
00042               F u n c t i o n s
00043 ----------------------------------------------------------------------*/
00044 
00045 /**********************************************************************
00046  * delete_split
00047  *
00048  * Remove this split from existence.
00049  **********************************************************************/
00050 void delete_split(SPLIT *split) { 
00051   if (split) {
00052     delete split;
00053   }
00054 }
00055 
00056 
00057 /**********************************************************************
00058  * make_edgept
00059  *
00060  * Create an EDGEPT and hook it into an existing list of edge points.
00061  **********************************************************************/
00062 EDGEPT *make_edgept(int x, int y, EDGEPT *next, EDGEPT *prev) {
00063   EDGEPT *this_edgept;
00064   /* Create point */
00065   this_edgept = new EDGEPT;
00066   this_edgept->pos.x = x;
00067   this_edgept->pos.y = y;
00068   // Now deal with the src_outline steps.
00069   C_OUTLINE* prev_ol = prev->src_outline;
00070   if (prev_ol != NULL && prev->next == next) {
00071     // Compute the fraction of the segment that is being cut.
00072     FCOORD segment_vec(next->pos.x - prev->pos.x, next->pos.y - prev->pos.y);
00073     FCOORD target_vec(x - prev->pos.x, y - prev->pos.y);
00074     double cut_fraction = target_vec.length() / segment_vec.length();
00075     // Get the start and end at the step level.
00076     ICOORD step_start = prev_ol->position_at_index(prev->start_step);
00077     int end_step = prev->start_step + prev->step_count;
00078     int step_length = prev_ol->pathlength();
00079     ICOORD step_end = prev_ol->position_at_index(end_step % step_length);
00080     ICOORD step_vec = step_end - step_start;
00081     double target_length = step_vec.length() * cut_fraction;
00082     // Find the point on the segment that gives the length nearest to target.
00083     int best_step = prev->start_step;
00084     ICOORD total_step(0, 0);
00085     double best_dist = target_length;
00086     for (int s = prev->start_step; s < end_step; ++s) {
00087       total_step += prev_ol->step(s % step_length);
00088       double dist = fabs(target_length - total_step.length());
00089       if (dist < best_dist) {
00090         best_dist = dist;
00091         best_step = s + 1;
00092       }
00093     }
00094     // The new point is an intermediate point.
00095     this_edgept->src_outline = prev_ol;
00096     this_edgept->step_count = end_step - best_step;
00097     this_edgept->start_step = best_step % step_length;
00098     prev->step_count = best_step - prev->start_step;
00099   } else {
00100     // The new point is poly only.
00101     this_edgept->src_outline = NULL;
00102     this_edgept->step_count = 0;
00103     this_edgept->start_step = 0;
00104   }
00105   /* Hook it up */
00106   this_edgept->next = next;
00107   this_edgept->prev = prev;
00108   prev->next = this_edgept;
00109   next->prev = this_edgept;
00110   /* Set up vec entries */
00111   this_edgept->vec.x = this_edgept->next->pos.x - x;
00112   this_edgept->vec.y = this_edgept->next->pos.y - y;
00113   this_edgept->prev->vec.x = x - this_edgept->prev->pos.x;
00114   this_edgept->prev->vec.y = y - this_edgept->prev->pos.y;
00115   return this_edgept;
00116 }
00117 
00118 /**********************************************************************
00119  * remove_edgept
00120  *
00121  * Remove a given EDGEPT from its list and delete it.
00122  **********************************************************************/
00123 void remove_edgept(EDGEPT *point) {
00124   EDGEPT *prev = point->prev;
00125   EDGEPT *next = point->next;
00126   // Add point's steps onto prev's steps if they are from the same outline.
00127   if (prev->src_outline == point->src_outline && prev->src_outline != NULL) {
00128     prev->step_count += point->step_count;
00129   }
00130   prev->next = next;
00131   next->prev = prev;
00132   prev->vec.x = next->pos.x - prev->pos.x;
00133   prev->vec.y = next->pos.y - prev->pos.y;
00134   delete point;
00135 }
00136 
00137 /**********************************************************************
00138  * new_split
00139  *
00140  * Create a new split record and initialize it.  Put it on the display
00141  * list.
00142  **********************************************************************/
00143 SPLIT *new_split(EDGEPT *point1, EDGEPT *point2) { 
00144   SPLIT *s = new SPLIT;
00145   s->point1 = point1;
00146   s->point2 = point2;
00147   return (s);
00148 }
00149 
00150 
00151 /**********************************************************************
00152  * print_split
00153  *
00154  * Print a list of splits.  Show the coordinates of both points in
00155  * each split.
00156  **********************************************************************/
00157 void print_split(SPLIT *split) { 
00158   if (split) {
00159     tprintf("(%d,%d)--(%d,%d)",
00160             split->point1->pos.x, split->point1->pos.y,
00161             split->point2->pos.x, split->point2->pos.y);
00162   }
00163 }
00164 
00165 
00166 /**********************************************************************
00167  * split_outline
00168  *
00169  * Split between these two edge points.
00170  **********************************************************************/
00171 void split_outline(EDGEPT *join_point1, EDGEPT *join_point2) { 
00172   assert(join_point1 != join_point2);
00173 
00174   EDGEPT* temp2 = join_point2->next;
00175   EDGEPT* temp1 = join_point1->next;
00176   /* Create two new points */
00177   EDGEPT* new_point1 = make_edgept(join_point1->pos.x, join_point1->pos.y,
00178                                    temp1, join_point2);
00179   EDGEPT* new_point2 = make_edgept(join_point2->pos.x, join_point2->pos.y,
00180                                    temp2, join_point1);
00181   // Join_point1 and 2 are now cross-over points, so they must have NULL
00182   // src_outlines and give their src_outline information their new
00183   // replacements.
00184   new_point1->src_outline = join_point1->src_outline;
00185   new_point1->start_step = join_point1->start_step;
00186   new_point1->step_count = join_point1->step_count;
00187   new_point2->src_outline = join_point2->src_outline;
00188   new_point2->start_step = join_point2->start_step;
00189   new_point2->step_count = join_point2->step_count;
00190   join_point1->src_outline = NULL;
00191   join_point1->start_step = 0;
00192   join_point1->step_count = 0;
00193   join_point2->src_outline = NULL;
00194   join_point2->start_step = 0;
00195   join_point2->step_count = 0;
00196   join_point1->MarkChop();
00197   join_point2->MarkChop();
00198 }
00199 
00200 
00201 /**********************************************************************
00202  * unsplit_outlines
00203  *
00204  * Remove the split that was put between these two points.
00205  **********************************************************************/
00206 void unsplit_outlines(EDGEPT *p1, EDGEPT *p2) { 
00207   EDGEPT *tmp1 = p1->next;
00208   EDGEPT *tmp2 = p2->next;
00209 
00210   assert (p1 != p2);
00211 
00212   tmp1->next->prev = p2;
00213   tmp2->next->prev = p1;
00214 
00215   // tmp2 is coincident with p1. p1 takes tmp2's place as tmp2 is deleted.
00216   p1->next = tmp2->next;
00217   p1->src_outline = tmp2->src_outline;
00218   p1->start_step = tmp2->start_step;
00219   p1->step_count = tmp2->step_count;
00220   // Likewise p2 takes tmp1's place.
00221   p2->next = tmp1->next;
00222   p2->src_outline = tmp1->src_outline;
00223   p2->start_step = tmp1->start_step;
00224   p2->step_count = tmp1->step_count;
00225   p1->UnmarkChop();
00226   p2->UnmarkChop();
00227 
00228   delete tmp1;
00229   delete tmp2;
00230 
00231   p1->vec.x = p1->next->pos.x - p1->pos.x;
00232   p1->vec.y = p1->next->pos.y - p1->pos.y;
00233 
00234   p2->vec.x = p2->next->pos.x - p2->pos.x;
00235   p2->vec.y = p2->next->pos.y - p2->pos.y;
00236 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines