tesseract  4.00.00dev
QSPLINE Class Reference

#include <quspline.h>

Public Member Functions

 QSPLINE ()
 
 QSPLINE (const QSPLINE &src)
 
 QSPLINE (inT32 count, inT32 *xstarts, double *coeffs)
 
 ~QSPLINE ()
 
 QSPLINE (int xstarts[], int segcount, int xcoords[], int ycoords[], int blobcount, int degree)
 
double step (double x1, double x2)
 
double y (double x) const
 
void move (ICOORD vec)
 
BOOL8 overlap (QSPLINE *spline2, double fraction)
 
void extrapolate (double gradient, int left, int right)
 
void plot (ScrollView *window, ScrollView::Color colour) const
 
void plot (Pix *pix) const
 
QSPLINEoperator= (const QSPLINE &source)
 

Friends

void make_first_baseline (TBOX *, int, int *, int *, QSPLINE *, QSPLINE *, float)
 
void make_holed_baseline (TBOX *, int, QSPLINE *, QSPLINE *, float)
 
void tweak_row_baseline (ROW *, double, double)
 

Detailed Description

Definition at line 31 of file quspline.h.

Constructor & Destructor Documentation

◆ QSPLINE() [1/4]

QSPLINE::QSPLINE ( )
inline

Definition at line 43 of file quspline.h.

43  { //empty constructor
44  segments = 0;
45  xcoords = NULL; //everything empty
46  quadratics = NULL;
47  }

◆ QSPLINE() [2/4]

QSPLINE::QSPLINE ( const QSPLINE src)

Definition at line 136 of file quspline.cpp.

137  {
138  segments = 0;
139  xcoords = NULL;
140  quadratics = NULL;
141  *this = src;
142 }

◆ QSPLINE() [3/4]

QSPLINE::QSPLINE ( inT32  count,
inT32 xstarts,
double *  coeffs 
)

Definition at line 38 of file quspline.cpp.

42  {
43  inT32 index; //segment index
44 
45  //get memory
46  xcoords = (inT32 *) alloc_mem ((count + 1) * sizeof (inT32));
47  quadratics = (QUAD_COEFFS *) alloc_mem (count * sizeof (QUAD_COEFFS));
48  segments = count;
49  for (index = 0; index < segments; index++) {
50  //copy them
51  xcoords[index] = xstarts[index];
52  quadratics[index] = QUAD_COEFFS (coeffs[index * 3],
53  coeffs[index * 3 + 1],
54  coeffs[index * 3 + 2]);
55  }
56  //right edge
57  xcoords[index] = xstarts[index];
58 }
int32_t inT32
Definition: host.h:38
void * alloc_mem(inT32 count)
Definition: memry.cpp:39
int count(LIST var_list)
Definition: oldlist.cpp:103

◆ ~QSPLINE()

QSPLINE::~QSPLINE ( )

Definition at line 151 of file quspline.cpp.

152  {
153  if (xcoords != NULL) {
154  free_mem(xcoords);
155  xcoords = NULL;
156  }
157  if (quadratics != NULL) {
158  free_mem(quadratics);
159  quadratics = NULL;
160  }
161 }
void free_mem(void *oldchunk)
Definition: memry.cpp:47

◆ QSPLINE() [4/4]

QSPLINE::QSPLINE ( int  xstarts[],
int  segcount,
int  xcoords[],
int  ycoords[],
int  blobcount,
int  degree 
)

Definition at line 67 of file quspline.cpp.

73  {
74  int pointindex; /*no along text line */
75  int segment; /*segment no */
76  inT32 *ptcounts; //no in each segment
77  QLSQ qlsq; /*accumulator */
78 
79  segments = segcount;
80  xcoords = (inT32 *) alloc_mem ((segcount + 1) * sizeof (inT32));
81  ptcounts = (inT32 *) alloc_mem ((segcount + 1) * sizeof (inT32));
82  quadratics = (QUAD_COEFFS *) alloc_mem (segcount * sizeof (QUAD_COEFFS));
83  memmove (xcoords, xstarts, (segcount + 1) * sizeof (inT32));
84  ptcounts[0] = 0; /*none in any yet */
85  for (segment = 0, pointindex = 0; pointindex < pointcount; pointindex++) {
86  while (segment < segcount && xpts[pointindex] >= xstarts[segment]) {
87  segment++; /*try next segment */
88  /*cumulative counts */
89  ptcounts[segment] = ptcounts[segment - 1];
90  }
91  ptcounts[segment]++; /*no in previous partition */
92  }
93  while (segment < segcount) {
94  segment++;
95  /*zero the rest */
96  ptcounts[segment] = ptcounts[segment - 1];
97  }
98 
99  for (segment = 0; segment < segcount; segment++) {
100  qlsq.clear ();
101  /*first blob */
102  pointindex = ptcounts[segment];
103  if (pointindex > 0
104  && xpts[pointindex] != xpts[pointindex - 1]
105  && xpts[pointindex] != xstarts[segment])
106  qlsq.add (xstarts[segment],
107  ypts[pointindex - 1]
108  + (ypts[pointindex] - ypts[pointindex - 1])
109  * (xstarts[segment] - xpts[pointindex - 1])
110  / (xpts[pointindex] - xpts[pointindex - 1]));
111  for (; pointindex < ptcounts[segment + 1]; pointindex++) {
112  qlsq.add (xpts[pointindex], ypts[pointindex]);
113  }
114  if (pointindex > 0 && pointindex < pointcount
115  && xpts[pointindex] != xstarts[segment + 1])
116  qlsq.add (xstarts[segment + 1],
117  ypts[pointindex - 1]
118  + (ypts[pointindex] - ypts[pointindex - 1])
119  * (xstarts[segment + 1] - xpts[pointindex - 1])
120  / (xpts[pointindex] - xpts[pointindex - 1]));
121  qlsq.fit (degree);
122  quadratics[segment].a = qlsq.get_a ();
123  quadratics[segment].b = qlsq.get_b ();
124  quadratics[segment].c = qlsq.get_c ();
125  }
126  free_mem(ptcounts);
127 }
double get_c()
Definition: quadlsq.h:51
void free_mem(void *oldchunk)
Definition: memry.cpp:47
double get_b()
Definition: quadlsq.h:48
int32_t inT32
Definition: host.h:38
void add(double x, double y)
Definition: quadlsq.cpp:56
Definition: quadlsq.h:25
void fit(int degree)
Definition: quadlsq.cpp:100
void * alloc_mem(inT32 count)
Definition: memry.cpp:39
double a
Definition: quadratc.h:58
float c
Definition: quadratc.h:60
float b
Definition: quadratc.h:59
void clear()
Definition: quadlsq.cpp:34
double get_a()
Definition: quadlsq.h:45

Member Function Documentation

◆ extrapolate()

void QSPLINE::extrapolate ( double  gradient,
int  left,
int  right 
)

Definition at line 306 of file quspline.cpp.

310  {
311  int segment; /*current segment of spline */
312  int dest_segment; //dest index
313  int *xstarts; //new boundaries
314  QUAD_COEFFS *quads; //new ones
315  int increment; //in size
316 
317  increment = xmin < xcoords[0] ? 1 : 0;
318  if (xmax > xcoords[segments])
319  increment++;
320  if (increment == 0)
321  return;
322  xstarts = (int *) alloc_mem ((segments + 1 + increment) * sizeof (int));
323  quads =
324  (QUAD_COEFFS *) alloc_mem ((segments + increment) * sizeof (QUAD_COEFFS));
325  if (xmin < xcoords[0]) {
326  xstarts[0] = xmin;
327  quads[0].a = 0;
328  quads[0].b = gradient;
329  quads[0].c = y (xcoords[0]) - quads[0].b * xcoords[0];
330  dest_segment = 1;
331  }
332  else
333  dest_segment = 0;
334  for (segment = 0; segment < segments; segment++) {
335  xstarts[dest_segment] = xcoords[segment];
336  quads[dest_segment] = quadratics[segment];
337  dest_segment++;
338  }
339  xstarts[dest_segment] = xcoords[segment];
340  if (xmax > xcoords[segments]) {
341  quads[dest_segment].a = 0;
342  quads[dest_segment].b = gradient;
343  quads[dest_segment].c = y (xcoords[segments])
344  - quads[dest_segment].b * xcoords[segments];
345  dest_segment++;
346  xstarts[dest_segment] = xmax + 1;
347  }
348  segments = dest_segment;
349  free_mem(xcoords);
350  free_mem(quadratics);
351  xcoords = (inT32 *) xstarts;
352  quadratics = quads;
353 }
void free_mem(void *oldchunk)
Definition: memry.cpp:47
int32_t inT32
Definition: host.h:38
double y(double x) const
Definition: quspline.cpp:217
void * alloc_mem(inT32 count)
Definition: memry.cpp:39
double a
Definition: quadratc.h:58
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
float c
Definition: quadratc.h:60
float b
Definition: quadratc.h:59

◆ move()

void QSPLINE::move ( ICOORD  vec)

Definition at line 259 of file quspline.cpp.

261  {
262  inT32 segment; //index of segment
263  inT16 x_shift = vec.x ();
264 
265  for (segment = 0; segment < segments; segment++) {
266  xcoords[segment] += x_shift;
267  quadratics[segment].move (vec);
268  }
269  xcoords[segment] += x_shift;
270 }
int32_t inT32
Definition: host.h:38
inT16 x() const
access function
Definition: points.h:52
void move(ICOORD vec)
Definition: quadratc.h:44
int16_t inT16
Definition: host.h:36

◆ operator=()

QSPLINE & QSPLINE::operator= ( const QSPLINE source)

Definition at line 170 of file quspline.cpp.

171  {
172  if (xcoords != NULL)
173  free_mem(xcoords);
174  if (quadratics != NULL)
175  free_mem(quadratics);
176 
177  segments = source.segments;
178  xcoords = (inT32 *) alloc_mem ((segments + 1) * sizeof (inT32));
179  quadratics = (QUAD_COEFFS *) alloc_mem (segments * sizeof (QUAD_COEFFS));
180  memmove (xcoords, source.xcoords, (segments + 1) * sizeof (inT32));
181  memmove (quadratics, source.quadratics, segments * sizeof (QUAD_COEFFS));
182  return *this;
183 }
void free_mem(void *oldchunk)
Definition: memry.cpp:47
int32_t inT32
Definition: host.h:38
void * alloc_mem(inT32 count)
Definition: memry.cpp:39

◆ overlap()

BOOL8 QSPLINE::overlap ( QSPLINE spline2,
double  fraction 
)

Definition at line 280 of file quspline.cpp.

283  {
284  int leftlimit; /*common left limit */
285  int rightlimit; /*common right limit */
286 
287  leftlimit = xcoords[1];
288  rightlimit = xcoords[segments - 1];
289  /*or too non-overlap */
290  if (spline2->segments < 3 || spline2->xcoords[1] > leftlimit + fraction * (rightlimit - leftlimit)
291  || spline2->xcoords[spline2->segments - 1] < rightlimit
292  - fraction * (rightlimit - leftlimit))
293  return FALSE;
294  else
295  return TRUE;
296 }
#define TRUE
Definition: capi.h:45
#define FALSE
Definition: capi.h:46

◆ plot() [1/2]

void QSPLINE::plot ( ScrollView window,
ScrollView::Color  colour 
) const

Definition at line 363 of file quspline.cpp.

366  {
367  inT32 segment; //index of segment
368  inT16 step; //index of poly piece
369  double increment; //x increment
370  double x; //x coord
371 
372  window->Pen(colour);
373  for (segment = 0; segment < segments; segment++) {
374  increment =
375  (double) (xcoords[segment + 1] -
376  xcoords[segment]) / QSPLINE_PRECISION;
377  x = xcoords[segment];
378  for (step = 0; step <= QSPLINE_PRECISION; step++) {
379  if (segment == 0 && step == 0)
380  window->SetCursor(x, quadratics[segment].y (x));
381  else
382  window->DrawTo(x, quadratics[segment].y (x));
383  x += increment;
384  }
385  }
386 }
#define QSPLINE_PRECISION
Definition: quspline.cpp:30
int32_t inT32
Definition: host.h:38
int16_t inT16
Definition: host.h:36
void SetCursor(int x, int y)
Definition: scrollview.cpp:525
double y(double x) const
Definition: quspline.cpp:217
double step(double x1, double x2)
Definition: quspline.cpp:192
void Pen(Color color)
Definition: scrollview.cpp:726
void DrawTo(int x, int y)
Definition: scrollview.cpp:531

◆ plot() [2/2]

void QSPLINE::plot ( Pix *  pix) const

Definition at line 389 of file quspline.cpp.

389  {
390  if (pix == NULL) {
391  return;
392  }
393 
394  inT32 segment; // Index of segment
395  inT16 step; // Index of poly piece
396  double increment; // x increment
397  double x; // x coord
398  double height = static_cast<double>(pixGetHeight(pix));
399  Pta* points = ptaCreate(QSPLINE_PRECISION * segments);
400  const int kLineWidth = 5;
401 
402  for (segment = 0; segment < segments; segment++) {
403  increment = static_cast<double>((xcoords[segment + 1] -
404  xcoords[segment])) / QSPLINE_PRECISION;
405  x = xcoords[segment];
406  for (step = 0; step <= QSPLINE_PRECISION; step++) {
407  double y = height - quadratics[segment].y(x);
408  ptaAddPt(points, x, y);
409  x += increment;
410  }
411  }
412 
413  switch (pixGetDepth(pix)) {
414  case 1:
415  pixRenderPolyline(pix, points, kLineWidth, L_SET_PIXELS, 1);
416  break;
417  case 32:
418  pixRenderPolylineArb(pix, points, kLineWidth, 255, 0, 0, 1);
419  break;
420  default:
421  pixRenderPolyline(pix, points, kLineWidth, L_CLEAR_PIXELS, 1);
422  break;
423  }
424  ptaDestroy(&points);
425 }
#define QSPLINE_PRECISION
Definition: quspline.cpp:30
int32_t inT32
Definition: host.h:38
int16_t inT16
Definition: host.h:36
double y(double x) const
Definition: quspline.cpp:217
double step(double x1, double x2)
Definition: quspline.cpp:192
float y(float x) const
Definition: quadratc.h:39

◆ step()

double QSPLINE::step ( double  x1,
double  x2 
)

Definition at line 192 of file quspline.cpp.

194  {
195  int index1, index2; //indices of coords
196  double total; /*total steps */
197 
198  index1 = spline_index (x1);
199  index2 = spline_index (x2);
200  total = 0;
201  while (index1 < index2) {
202  total +=
203  (double) quadratics[index1 + 1].y ((float) xcoords[index1 + 1]);
204  total -= (double) quadratics[index1].y ((float) xcoords[index1 + 1]);
205  index1++; /*next segment */
206  }
207  return total; /*total steps */
208 }
double y(double x) const
Definition: quspline.cpp:217

◆ y()

double QSPLINE::y ( double  x) const

Definition at line 217 of file quspline.cpp.

219  {
220  inT32 index; //segment index
221 
222  index = spline_index (x);
223  return quadratics[index].y (x);//in correct segment
224 }
int32_t inT32
Definition: host.h:38
float y(float x) const
Definition: quadratc.h:39

Friends And Related Function Documentation

◆ make_first_baseline

void make_first_baseline ( TBOX ,
int  ,
int ,
int ,
QSPLINE ,
QSPLINE ,
float   
)
friend

◆ make_holed_baseline

void make_holed_baseline ( TBOX ,
int  ,
QSPLINE ,
QSPLINE ,
float   
)
friend

◆ tweak_row_baseline

void tweak_row_baseline ( ROW ,
double  ,
double   
)
friend

Definition at line 885 of file tordmain.cpp.

887  {
888  TBOX blob_box; //bounding box
889  C_BLOB *blob; //current blob
890  WERD *word; //current word
891  inT32 blob_count; //no of blobs
892  inT32 src_index; //source segment
893  inT32 dest_index; //destination segment
894  inT32 *xstarts; //spline segments
895  double *coeffs; //spline coeffs
896  float ydiff; //baseline error
897  float x_centre; //centre of blob
898  //words of row
899  WERD_IT word_it = row->word_list ();
900  C_BLOB_IT blob_it; //blob iterator
901 
902  blob_count = 0;
903  for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) {
904  word = word_it.data (); //current word
905  //get total blobs
906  blob_count += word->cblob_list ()->length ();
907  }
908  if (blob_count == 0)
909  return;
910  xstarts =
911  (inT32 *) alloc_mem ((blob_count + row->baseline.segments + 1) *
912  sizeof (inT32));
913  coeffs =
914  (double *) alloc_mem ((blob_count + row->baseline.segments) * 3 *
915  sizeof (double));
916 
917  src_index = 0;
918  dest_index = 0;
919  xstarts[0] = row->baseline.xcoords[0];
920  for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) {
921  word = word_it.data (); //current word
922  //blobs in word
923  blob_it.set_to_list (word->cblob_list ());
924  for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
925  blob_it.forward ()) {
926  blob = blob_it.data ();
927  blob_box = blob->bounding_box ();
928  x_centre = (blob_box.left () + blob_box.right ()) / 2.0;
929  ydiff = blob_box.bottom () - row->base_line (x_centre);
930  if (ydiff < 0)
931  ydiff = -ydiff / row->x_height ();
932  else
933  ydiff = ydiff / row->x_height ();
934  if (ydiff < blshift_maxshift
935  && blob_box.height () / row->x_height () > blshift_xfraction) {
936  if (xstarts[dest_index] >= x_centre)
937  xstarts[dest_index] = blob_box.left ();
938  coeffs[dest_index * 3] = 0;
939  coeffs[dest_index * 3 + 1] = 0;
940  coeffs[dest_index * 3 + 2] = blob_box.bottom ();
941  //shift it
942  dest_index++;
943  xstarts[dest_index] = blob_box.right () + 1;
944  }
945  else {
946  if (xstarts[dest_index] <= x_centre) {
947  while (row->baseline.xcoords[src_index + 1] <= x_centre
948  && src_index < row->baseline.segments - 1) {
949  if (row->baseline.xcoords[src_index + 1] >
950  xstarts[dest_index]) {
951  coeffs[dest_index * 3] =
952  row->baseline.quadratics[src_index].a;
953  coeffs[dest_index * 3 + 1] =
954  row->baseline.quadratics[src_index].b;
955  coeffs[dest_index * 3 + 2] =
956  row->baseline.quadratics[src_index].c;
957  dest_index++;
958  xstarts[dest_index] =
959  row->baseline.xcoords[src_index + 1];
960  }
961  src_index++;
962  }
963  coeffs[dest_index * 3] =
964  row->baseline.quadratics[src_index].a;
965  coeffs[dest_index * 3 + 1] =
966  row->baseline.quadratics[src_index].b;
967  coeffs[dest_index * 3 + 2] =
968  row->baseline.quadratics[src_index].c;
969  dest_index++;
970  xstarts[dest_index] = row->baseline.xcoords[src_index + 1];
971  }
972  }
973  }
974  }
975  while (src_index < row->baseline.segments
976  && row->baseline.xcoords[src_index + 1] <= xstarts[dest_index])
977  src_index++;
978  while (src_index < row->baseline.segments) {
979  coeffs[dest_index * 3] = row->baseline.quadratics[src_index].a;
980  coeffs[dest_index * 3 + 1] = row->baseline.quadratics[src_index].b;
981  coeffs[dest_index * 3 + 2] = row->baseline.quadratics[src_index].c;
982  dest_index++;
983  src_index++;
984  xstarts[dest_index] = row->baseline.xcoords[src_index];
985  }
986  //turn to spline
987  row->baseline = QSPLINE (dest_index, xstarts, coeffs);
988  free_mem(xstarts);
989  free_mem(coeffs);
990 }
void free_mem(void *oldchunk)
Definition: memry.cpp:47
int32_t inT32
Definition: host.h:38
QSPLINE()
Definition: quspline.h:43
WERD_LIST * word_list()
Definition: ocrrow.h:52
float x_height() const
Definition: ocrrow.h:61
inT16 left() const
Definition: rect.h:68
void * alloc_mem(inT32 count)
Definition: memry.cpp:39
double a
Definition: quadratc.h:58
Definition: rect.h:30
TBOX bounding_box() const
Definition: stepblob.cpp:250
C_BLOB_LIST * cblob_list()
Definition: werd.h:100
inT16 height() const
Definition: rect.h:104
float c
Definition: quadratc.h:60
inT16 right() const
Definition: rect.h:75
inT16 bottom() const
Definition: rect.h:61
float base_line(float xpos) const
Definition: ocrrow.h:56
Definition: werd.h:60
float b
Definition: quadratc.h:59

The documentation for this class was generated from the following files: