tesseract
3.03
|
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 }