#include <quspline.h>
Definition at line 35 of file quspline.h.
QSPLINE::QSPLINE | ( | ) | [inline] |
Definition at line 47 of file quspline.h.
References NULL, quadratics, segments, and xcoords.
00047 { //empty constructor 00048 segments = 0; 00049 xcoords = NULL; //everything empty 00050 quadratics = NULL; 00051 }
QSPLINE::QSPLINE | ( | const QSPLINE & | src | ) |
Constructor to build a QSPLINE from another.
Definition at line 122 of file quspline.cpp.
References NULL, quadratics, segments, and xcoords.
00123 { 00124 segments = 0; 00125 xcoords = NULL; 00126 quadratics = NULL; 00127 *this = src; 00128 }
Constructor to build a QSPLINE given the components used in the old code.
Definition at line 30 of file quspline.cpp.
References alloc_mem(), quadratics, segments, and xcoords.
00034 { 00035 INT32 index; //segment index 00036 00037 //get memory 00038 xcoords = (INT32 *) alloc_mem ((count + 1) * sizeof (INT32)); 00039 quadratics = (QUAD_COEFFS *) alloc_mem (count * sizeof (QUAD_COEFFS)); 00040 segments = count; 00041 for (index = 0; index < segments; index++) { 00042 //copy them 00043 xcoords[index] = xstarts[index]; 00044 quadratics[index] = QUAD_COEFFS (coeffs[index * 3], 00045 coeffs[index * 3 + 1], 00046 coeffs[index * 3 + 2]); 00047 } 00048 //right edge 00049 xcoords[index] = xstarts[index]; 00050 }
QSPLINE::~QSPLINE | ( | ) |
Destroy a QSPLINE.
Definition at line 134 of file quspline.cpp.
References free_mem(), NULL, quadratics, and xcoords.
00135 { 00136 if (xcoords != NULL) { 00137 free_mem(xcoords); 00138 xcoords = NULL; 00139 } 00140 if (quadratics != NULL) { 00141 free_mem(quadratics); 00142 quadratics = NULL; 00143 } 00144 }
QSPLINE::QSPLINE | ( | int | xstarts[], | |
int | segcount, | |||
int | xcoords[], | |||
int | ycoords[], | |||
int | blobcount, | |||
int | degree | |||
) |
Constructor to build a QSPLINE by appproximation of points.
Definition at line 56 of file quspline.cpp.
References QUAD_COEFFS::a, QLSQ::add(), alloc_mem(), QUAD_COEFFS::b, QUAD_COEFFS::c, QLSQ::clear(), QLSQ::fit(), free_mem(), QLSQ::get_a(), QLSQ::get_b(), QLSQ::get_c(), quadratics, segments, and xcoords.
00062 { 00063 register int pointindex; /*no along text line */ 00064 register int segment; /*segment no */ 00065 INT32 *ptcounts; //no in each segment 00066 QLSQ qlsq; /*accumulator */ 00067 00068 segments = segcount; 00069 xcoords = (INT32 *) alloc_mem ((segcount + 1) * sizeof (INT32)); 00070 ptcounts = (INT32 *) alloc_mem ((segcount + 1) * sizeof (INT32)); 00071 quadratics = (QUAD_COEFFS *) alloc_mem (segcount * sizeof (QUAD_COEFFS)); 00072 memmove (xcoords, xstarts, (segcount + 1) * sizeof (INT32)); 00073 ptcounts[0] = 0; /*none in any yet */ 00074 for (segment = 0, pointindex = 0; pointindex < pointcount; pointindex++) { 00075 while (segment < segcount && xpts[pointindex] >= xstarts[segment]) { 00076 segment++; /*try next segment */ 00077 /*cumulative counts */ 00078 ptcounts[segment] = ptcounts[segment - 1]; 00079 } 00080 ptcounts[segment]++; /*no in previous partition */ 00081 } 00082 while (segment < segcount) { 00083 segment++; 00084 /*zero the rest */ 00085 ptcounts[segment] = ptcounts[segment - 1]; 00086 } 00087 00088 for (segment = 0; segment < segcount; segment++) { 00089 qlsq.clear (); 00090 /*first blob */ 00091 pointindex = ptcounts[segment]; 00092 if (pointindex > 0 00093 && xpts[pointindex] != xpts[pointindex - 1] 00094 && xpts[pointindex] != xstarts[segment]) 00095 qlsq.add (xstarts[segment], 00096 ypts[pointindex - 1] 00097 + (ypts[pointindex] - ypts[pointindex - 1]) 00098 * (xstarts[segment] - xpts[pointindex - 1]) 00099 / (xpts[pointindex] - xpts[pointindex - 1])); 00100 for (; pointindex < ptcounts[segment + 1]; pointindex++) { 00101 qlsq.add (xpts[pointindex], ypts[pointindex]); 00102 } 00103 if (pointindex > 0 && pointindex < pointcount 00104 && xpts[pointindex] != xstarts[segment + 1]) 00105 qlsq.add (xstarts[segment + 1], 00106 ypts[pointindex - 1] 00107 + (ypts[pointindex] - ypts[pointindex - 1]) 00108 * (xstarts[segment + 1] - xpts[pointindex - 1]) 00109 / (xpts[pointindex] - xpts[pointindex - 1])); 00110 qlsq.fit (degree); 00111 quadratics[segment].a = qlsq.get_a (); 00112 quadratics[segment].b = qlsq.get_b (); 00113 quadratics[segment].c = qlsq.get_c (); 00114 } 00115 free_mem(ptcounts); 00116 }
void QSPLINE::de_dump | ( | FILE * | f | ) | [inline] |
Definition at line 97 of file quspline.h.
References de_serialise_bytes(), quadratics, segments, and xcoords.
Referenced by ROW::de_dump().
00098 { 00099 xcoords = (INT32 *) de_serialise_bytes (f, 00100 (segments + 1) * sizeof (INT32)); 00101 quadratics = (QUAD_COEFFS *) de_serialise_bytes (f, 00102 segments * 00103 sizeof (QUAD_COEFFS)); 00104 }
void QSPLINE::dump | ( | FILE * | f | ) | [inline] |
Definition at line 91 of file quspline.h.
References quadratics, segments, serialise_bytes(), and xcoords.
Referenced by ROW::dump().
00092 { 00093 serialise_bytes (f, (void *) xcoords, (segments + 1) * sizeof (INT32)); 00094 serialise_bytes (f, (void *) quadratics, segments * sizeof (QUAD_COEFFS)); 00095 }
void QSPLINE::extrapolate | ( | double | gradient, | |
int | left, | |||
int | right | |||
) |
Extrapolates the spline linearly using the same gradient as the quadratic has at either end.
Definition at line 268 of file quspline.cpp.
References QUAD_COEFFS::a, alloc_mem(), QUAD_COEFFS::b, QUAD_COEFFS::c, free_mem(), quadratics, segments, xcoords, and y().
Referenced by find_textlines().
00272 { 00273 register int segment; /*current segment of spline */ 00274 int dest_segment; //dest index 00275 int *xstarts; //new boundaries 00276 QUAD_COEFFS *quads; //new ones 00277 int increment; //in size 00278 00279 increment = xmin < xcoords[0] ? 1 : 0; 00280 if (xmax > xcoords[segments]) 00281 increment++; 00282 if (increment == 0) 00283 return; 00284 xstarts = (int *) alloc_mem ((segments + 1 + increment) * sizeof (int)); 00285 quads = 00286 (QUAD_COEFFS *) alloc_mem ((segments + increment) * sizeof (QUAD_COEFFS)); 00287 if (xmin < xcoords[0]) { 00288 xstarts[0] = xmin; 00289 quads[0].a = 0; 00290 quads[0].b = gradient; 00291 quads[0].c = y (xcoords[0]) - quads[0].b * xcoords[0]; 00292 dest_segment = 1; 00293 } 00294 else 00295 dest_segment = 0; 00296 for (segment = 0; segment < segments; segment++) { 00297 xstarts[dest_segment] = xcoords[segment]; 00298 quads[dest_segment] = quadratics[segment]; 00299 dest_segment++; 00300 } 00301 xstarts[dest_segment] = xcoords[segment]; 00302 if (xmax > xcoords[segments]) { 00303 quads[dest_segment].a = 0; 00304 quads[dest_segment].b = gradient; 00305 quads[dest_segment].c = y (xcoords[segments]) 00306 - quads[dest_segment].b * xcoords[segments]; 00307 dest_segment++; 00308 xstarts[dest_segment] = xmax + 1; 00309 } 00310 segments = dest_segment; 00311 free_mem(xcoords); 00312 free_mem(quadratics); 00313 xcoords = (INT32 *) xstarts; 00314 quadratics = quads; 00315 }
QSPLINE::make_serialise | ( | QSPLINE | ) |
void QSPLINE::move | ( | ICOORD | vec | ) |
Reposition spline by vector.
Definition at line 227 of file quspline.cpp.
References QUAD_COEFFS::move(), quadratics, segments, and xcoords.
Referenced by ROW::move().
00229 { 00230 INT32 segment; //index of segment 00231 INT16 x_shift = vec.x (); 00232 00233 for (segment = 0; segment < segments; segment++) { 00234 xcoords[segment] += x_shift; 00235 quadratics[segment].move (vec); 00236 } 00237 xcoords[segment] += x_shift; 00238 }
Return TRUE if spline2 overlaps this by no more than fraction less than the bounds of this.
Definition at line 245 of file quspline.cpp.
References FALSE, segments, TRUE, and xcoords.
Referenced by correlate_neighbours().
00248 { 00249 int leftlimit; /*common left limit */ 00250 int rightlimit; /*common right limit */ 00251 00252 leftlimit = xcoords[1]; 00253 rightlimit = xcoords[segments - 1]; 00254 /*or too non-overlap */ 00255 if (spline2->segments < 3 || spline2->xcoords[1] > leftlimit + fraction * (rightlimit - leftlimit) 00256 || spline2->xcoords[spline2->segments - 1] < rightlimit 00257 - fraction * (rightlimit - leftlimit)) 00258 return FALSE; 00259 else 00260 return TRUE; 00261 }
Draw the QSPLINE in the given colour.
Definition at line 322 of file quspline.cpp.
References draw2d, line_color_index, move2d, QSPLINE_PRECISION, quadratics, segments, step(), xcoords, and y().
Referenced by find_textlines(), and ROW::plot_baseline().
00325 { 00326 INT32 segment; //index of segment 00327 INT16 step; //index of poly piece 00328 double increment; //x increment 00329 double x; //x coord 00330 00331 line_color_index(window, colour); 00332 for (segment = 0; segment < segments; segment++) { 00333 increment = 00334 (double) (xcoords[segment + 1] - 00335 xcoords[segment]) / QSPLINE_PRECISION; 00336 x = xcoords[segment]; 00337 for (step = 0; step <= QSPLINE_PRECISION; step++) { 00338 if (segment == 0 && step == 0) 00339 move2d (window, x, quadratics[segment].y (x)); 00340 else 00341 draw2d (window, x, quadratics[segment].y (x)); 00342 x += increment; 00343 } 00344 } 00345 }
void QSPLINE::prep_serialise | ( | ) | [inline] |
INT32 QSPLINE::spline_index | ( | double | x | ) | const [private] |
Return the index to the largest xcoord not greater than x.
Definition at line 204 of file quspline.cpp.
References segments, and xcoords.
Referenced by step(), and y().
00206 { 00207 INT32 index; //segment index 00208 INT32 bottom; //bottom of range 00209 INT32 top; //top of range 00210 00211 bottom = 0; 00212 top = segments; 00213 while (top - bottom > 1) { 00214 index = (top + bottom) / 2; //centre of range 00215 if (x >= xcoords[index]) 00216 bottom = index; //new min 00217 else 00218 top = index; //new max 00219 } 00220 return bottom; 00221 }
double QSPLINE::step | ( | double | x1, | |
double | x2 | |||
) |
Return the total of the step functions between the given coords.
Definition at line 169 of file quspline.cpp.
References quadratics, spline_index(), xcoords, and y().
Referenced by get_ydiffs(), and plot().
00171 { 00172 int index1, index2; //indices of coords 00173 double total; /*total steps */ 00174 00175 index1 = spline_index (x1); 00176 index2 = spline_index (x2); 00177 total = 0; 00178 while (index1 < index2) { 00179 total += 00180 (double) quadratics[index1 + 1].y ((float) xcoords[index1 + 1]); 00181 total -= (double) quadratics[index1].y ((float) xcoords[index1 + 1]); 00182 index1++; /*next segment */ 00183 } 00184 return total; /*total steps */ 00185 }
double QSPLINE::y | ( | double | x | ) | const |
Return the y value at the given x value.
Definition at line 191 of file quspline.cpp.
References quadratics, spline_index(), and QUAD_COEFFS::y().
Referenced by ROW::base_line(), compute_row_xheight(), extrapolate(), find_lesser_parts(), get_ydiffs(), make_first_baseline(), make_holed_baseline(), most_overlapping_row(), plot(), reduced_box_for_blob(), step(), suspected_punct_blob(), and try_doc_fixed().
00193 { 00194 INT32 index; //segment index 00195 00196 index = spline_index (x); 00197 return quadratics[index].y (x);//in correct segment 00198 }
void tweak_row_baseline | ( | ROW * | ) | [friend] |
Remove empties.
Shift baseline to fit the blobs more accurately where they are close enough.
Definition at line 886 of file tordmain.cpp.
00888 { 00889 BOX blob_box; //bounding box 00890 C_BLOB *blob; //current blob 00891 WERD *word; //current word 00892 INT32 blob_count; //no of blobs 00893 INT32 src_index; //source segment 00894 INT32 dest_index; //destination segment 00895 INT32 *xstarts; //spline segments 00896 double *coeffs; //spline coeffs 00897 float ydiff; //baseline error 00898 float x_centre; //centre of blob 00899 //words of row 00900 WERD_IT word_it = row->word_list (); 00901 C_BLOB_IT blob_it; //blob iterator 00902 00903 blob_count = 0; 00904 for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) { 00905 word = word_it.data (); //current word 00906 //get total blobs 00907 blob_count += word->cblob_list ()->length (); 00908 } 00909 if (blob_count == 0) 00910 return; 00911 xstarts = 00912 (INT32 *) alloc_mem ((blob_count + row->baseline.segments + 1) * 00913 sizeof (INT32)); 00914 coeffs = 00915 (double *) alloc_mem ((blob_count + row->baseline.segments) * 3 * 00916 sizeof (double)); 00917 00918 src_index = 0; 00919 dest_index = 0; 00920 xstarts[0] = row->baseline.xcoords[0]; 00921 for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) { 00922 word = word_it.data (); //current word 00923 //blobs in word 00924 blob_it.set_to_list (word->cblob_list ()); 00925 for (blob_it.mark_cycle_pt (); !blob_it.cycled_list (); 00926 blob_it.forward ()) { 00927 blob = blob_it.data (); 00928 blob_box = blob->bounding_box (); 00929 x_centre = (blob_box.left () + blob_box.right ()) / 2.0; 00930 ydiff = blob_box.bottom () - row->base_line (x_centre); 00931 if (ydiff < 0) 00932 ydiff = -ydiff / row->x_height (); 00933 else 00934 ydiff = ydiff / row->x_height (); 00935 if (ydiff < textord_blshift_maxshift 00936 && blob_box.height () / row->x_height () > 00937 textord_blshift_xfraction) { 00938 if (xstarts[dest_index] >= x_centre) 00939 xstarts[dest_index] = blob_box.left (); 00940 coeffs[dest_index * 3] = 0; 00941 coeffs[dest_index * 3 + 1] = 0; 00942 coeffs[dest_index * 3 + 2] = blob_box.bottom (); 00943 //shift it 00944 dest_index++; 00945 xstarts[dest_index] = blob_box.right () + 1; 00946 } 00947 else { 00948 if (xstarts[dest_index] <= x_centre) { 00949 while (row->baseline.xcoords[src_index + 1] <= x_centre 00950 && src_index < row->baseline.segments - 1) { 00951 if (row->baseline.xcoords[src_index + 1] > 00952 xstarts[dest_index]) { 00953 coeffs[dest_index * 3] = 00954 row->baseline.quadratics[src_index].a; 00955 coeffs[dest_index * 3 + 1] = 00956 row->baseline.quadratics[src_index].b; 00957 coeffs[dest_index * 3 + 2] = 00958 row->baseline.quadratics[src_index].c; 00959 dest_index++; 00960 xstarts[dest_index] = 00961 row->baseline.xcoords[src_index + 1]; 00962 } 00963 src_index++; 00964 } 00965 coeffs[dest_index * 3] = 00966 row->baseline.quadratics[src_index].a; 00967 coeffs[dest_index * 3 + 1] = 00968 row->baseline.quadratics[src_index].b; 00969 coeffs[dest_index * 3 + 2] = 00970 row->baseline.quadratics[src_index].c; 00971 dest_index++; 00972 xstarts[dest_index] = row->baseline.xcoords[src_index + 1]; 00973 } 00974 } 00975 } 00976 } 00977 while (src_index < row->baseline.segments 00978 && row->baseline.xcoords[src_index + 1] <= xstarts[dest_index]) 00979 src_index++; 00980 while (src_index < row->baseline.segments) { 00981 coeffs[dest_index * 3] = row->baseline.quadratics[src_index].a; 00982 coeffs[dest_index * 3 + 1] = row->baseline.quadratics[src_index].b; 00983 coeffs[dest_index * 3 + 2] = row->baseline.quadratics[src_index].c; 00984 dest_index++; 00985 src_index++; 00986 xstarts[dest_index] = row->baseline.xcoords[src_index]; 00987 } 00988 //turn to spline 00989 row->baseline = QSPLINE (dest_index, xstarts, coeffs); 00990 free_mem(xstarts); 00991 free_mem(coeffs); 00992 }
QUAD_COEFFS* QSPLINE::quadratics [private] |
Definition at line 116 of file quspline.h.
Referenced by de_dump(), dump(), extrapolate(), move(), plot(), QSPLINE(), step(), tweak_row_baseline(), y(), and ~QSPLINE().
INT32 QSPLINE::segments [private] |
Definition at line 114 of file quspline.h.
Referenced by de_dump(), dump(), extrapolate(), make_first_baseline(), make_holed_baseline(), move(), overlap(), plot(), QSPLINE(), spline_index(), and tweak_row_baseline().
INT32* QSPLINE::xcoords [private] |
Definition at line 115 of file quspline.h.
Referenced by de_dump(), dump(), extrapolate(), make_first_baseline(), make_holed_baseline(), move(), overlap(), plot(), QSPLINE(), spline_index(), step(), tweak_row_baseline(), and ~QSPLINE().