tesseract  4.0.0-1-g2a2b
QSPLINE Class Reference

#include <quspline.h>

Public Member Functions

 QSPLINE ()
 
 QSPLINE (const QSPLINE &src)
 
 QSPLINE (int32_t count, int32_t *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)
 
bool 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 32 of file quspline.h.

Constructor & Destructor Documentation

◆ QSPLINE() [1/4]

QSPLINE::QSPLINE ( )
inline

Definition at line 44 of file quspline.h.

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

◆ QSPLINE() [2/4]

QSPLINE::QSPLINE ( const QSPLINE src)

Definition at line 137 of file quspline.cpp.

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

◆ QSPLINE() [3/4]

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

Definition at line 39 of file quspline.cpp.

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

◆ ~QSPLINE()

QSPLINE::~QSPLINE ( )

Definition at line 152 of file quspline.cpp.

152  {
153  delete[] xcoords;
154  delete[] quadratics;
155 }

◆ QSPLINE() [4/4]

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

Definition at line 68 of file quspline.cpp.

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

Member Function Documentation

◆ extrapolate()

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

Definition at line 291 of file quspline.cpp.

295  {
296  int segment; /*current segment of spline */
297  int dest_segment; //dest index
298  int32_t* xstarts; //new boundaries
299  QUAD_COEFFS *quads; //new ones
300  int increment; //in size
301 
302  increment = xmin < xcoords[0] ? 1 : 0;
303  if (xmax > xcoords[segments])
304  increment++;
305  if (increment == 0)
306  return;
307  xstarts = new int32_t[segments + 1 + increment];
308  quads = new QUAD_COEFFS[segments + increment];
309  if (xmin < xcoords[0]) {
310  xstarts[0] = xmin;
311  quads[0].a = 0;
312  quads[0].b = gradient;
313  quads[0].c = y (xcoords[0]) - quads[0].b * xcoords[0];
314  dest_segment = 1;
315  }
316  else
317  dest_segment = 0;
318  for (segment = 0; segment < segments; segment++) {
319  xstarts[dest_segment] = xcoords[segment];
320  quads[dest_segment] = quadratics[segment];
321  dest_segment++;
322  }
323  xstarts[dest_segment] = xcoords[segment];
324  if (xmax > xcoords[segments]) {
325  quads[dest_segment].a = 0;
326  quads[dest_segment].b = gradient;
327  quads[dest_segment].c = y (xcoords[segments])
328  - quads[dest_segment].b * xcoords[segments];
329  dest_segment++;
330  xstarts[dest_segment] = xmax + 1;
331  }
332  segments = dest_segment;
333  delete[] xcoords;
334  delete[] quadratics;
335  xcoords = xstarts;
336  quadratics = quads;
337 }
double a
Definition: quadratc.h:57
float c
Definition: quadratc.h:59
double y(double x) const
Definition: quspline.cpp:209
float b
Definition: quadratc.h:58

◆ move()

void QSPLINE::move ( ICOORD  vec)

Definition at line 251 of file quspline.cpp.

253  {
254  int32_t segment; //index of segment
255  int16_t x_shift = vec.x ();
256 
257  for (segment = 0; segment < segments; segment++) {
258  xcoords[segment] += x_shift;
259  quadratics[segment].move (vec);
260  }
261  xcoords[segment] += x_shift;
262 }
int16_t x() const
access function
Definition: points.h:53
void move(ICOORD vec)
Definition: quadratc.h:43

◆ operator=()

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

Definition at line 164 of file quspline.cpp.

165  {
166  delete[] xcoords;
167  delete[] quadratics;
168 
169  segments = source.segments;
170  xcoords = new int32_t[segments + 1];
171  quadratics = new QUAD_COEFFS[segments];
172  memmove (xcoords, source.xcoords, (segments + 1) * sizeof (int32_t));
173  memmove (quadratics, source.quadratics, segments * sizeof (QUAD_COEFFS));
174  return *this;
175 }

◆ overlap()

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

Definition at line 272 of file quspline.cpp.

275  {
276  int leftlimit = xcoords[1]; /*common left limit */
277  int rightlimit = xcoords[segments - 1]; /*common right limit */
278  /*or too non-overlap */
279  return !(spline2->segments < 3 || spline2->xcoords[1] > leftlimit + fraction * (rightlimit - leftlimit) ||
280  spline2->xcoords[spline2->segments - 1] < rightlimit - fraction * (rightlimit - leftlimit));
281 }

◆ plot() [1/2]

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

Definition at line 347 of file quspline.cpp.

350  {
351  int32_t segment; //index of segment
352  int16_t step; //index of poly piece
353  double increment; //x increment
354  double x; //x coord
355 
356  window->Pen(colour);
357  for (segment = 0; segment < segments; segment++) {
358  increment =
359  (double) (xcoords[segment + 1] -
360  xcoords[segment]) / QSPLINE_PRECISION;
361  x = xcoords[segment];
362  for (step = 0; step <= QSPLINE_PRECISION; step++) {
363  if (segment == 0 && step == 0)
364  window->SetCursor(x, quadratics[segment].y (x));
365  else
366  window->DrawTo(x, quadratics[segment].y (x));
367  x += increment;
368  }
369  }
370 }
#define QSPLINE_PRECISION
Definition: quspline.cpp:31
void DrawTo(int x, int y)
Definition: scrollview.cpp:527
void SetCursor(int x, int y)
Definition: scrollview.cpp:521
double y(double x) const
Definition: quspline.cpp:209
double step(double x1, double x2)
Definition: quspline.cpp:184
void Pen(Color color)
Definition: scrollview.cpp:722

◆ plot() [2/2]

void QSPLINE::plot ( Pix *  pix) const

Definition at line 373 of file quspline.cpp.

373  {
374  if (pix == nullptr) {
375  return;
376  }
377 
378  int32_t segment; // Index of segment
379  int16_t step; // Index of poly piece
380  double increment; // x increment
381  double x; // x coord
382  double height = static_cast<double>(pixGetHeight(pix));
383  Pta* points = ptaCreate(QSPLINE_PRECISION * segments);
384  const int kLineWidth = 5;
385 
386  for (segment = 0; segment < segments; segment++) {
387  increment = static_cast<double>((xcoords[segment + 1] -
388  xcoords[segment])) / QSPLINE_PRECISION;
389  x = xcoords[segment];
390  for (step = 0; step <= QSPLINE_PRECISION; step++) {
391  double y = height - quadratics[segment].y(x);
392  ptaAddPt(points, x, y);
393  x += increment;
394  }
395  }
396 
397  switch (pixGetDepth(pix)) {
398  case 1:
399  pixRenderPolyline(pix, points, kLineWidth, L_SET_PIXELS, 1);
400  break;
401  case 32:
402  pixRenderPolylineArb(pix, points, kLineWidth, 255, 0, 0, 1);
403  break;
404  default:
405  pixRenderPolyline(pix, points, kLineWidth, L_CLEAR_PIXELS, 1);
406  break;
407  }
408  ptaDestroy(&points);
409 }
#define QSPLINE_PRECISION
Definition: quspline.cpp:31
double y(double x) const
Definition: quspline.cpp:209
double step(double x1, double x2)
Definition: quspline.cpp:184
float y(float x) const
Definition: quadratc.h:38

◆ step()

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

Definition at line 184 of file quspline.cpp.

186  {
187  int index1, index2; //indices of coords
188  double total; /*total steps */
189 
190  index1 = spline_index (x1);
191  index2 = spline_index (x2);
192  total = 0;
193  while (index1 < index2) {
194  total +=
195  (double) quadratics[index1 + 1].y ((float) xcoords[index1 + 1]);
196  total -= (double) quadratics[index1].y ((float) xcoords[index1 + 1]);
197  index1++; /*next segment */
198  }
199  return total; /*total steps */
200 }
double y(double x) const
Definition: quspline.cpp:209

◆ y()

double QSPLINE::y ( double  x) const

Definition at line 209 of file quspline.cpp.

211  {
212  int32_t index; //segment index
213 
214  index = spline_index (x);
215  return quadratics[index].y (x);//in correct segment
216 }
float y(float x) const
Definition: quadratc.h:38

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 895 of file tordmain.cpp.

897  {
898  TBOX blob_box; //bounding box
899  C_BLOB *blob; //current blob
900  WERD *word; //current word
901  int32_t blob_count; //no of blobs
902  int32_t src_index; //source segment
903  int32_t dest_index; //destination segment
904  float ydiff; //baseline error
905  float x_centre; //centre of blob
906  //words of row
907  WERD_IT word_it = row->word_list ();
908  C_BLOB_IT blob_it; //blob iterator
909 
910  blob_count = 0;
911  for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) {
912  word = word_it.data (); //current word
913  //get total blobs
914  blob_count += word->cblob_list ()->length ();
915  }
916  if (blob_count == 0)
917  return;
918  // spline segments
919  std::vector<int32_t> xstarts(blob_count + row->baseline.segments + 1);
920  // spline coeffs
921  std::vector<double> coeffs((blob_count + row->baseline.segments) * 3);
922 
923  src_index = 0;
924  dest_index = 0;
925  xstarts[0] = row->baseline.xcoords[0];
926  for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) {
927  word = word_it.data (); //current word
928  //blobs in word
929  blob_it.set_to_list (word->cblob_list ());
930  for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
931  blob_it.forward ()) {
932  blob = blob_it.data ();
933  blob_box = blob->bounding_box ();
934  x_centre = (blob_box.left () + blob_box.right ()) / 2.0;
935  ydiff = blob_box.bottom () - row->base_line (x_centre);
936  if (ydiff < 0)
937  ydiff = -ydiff / row->x_height ();
938  else
939  ydiff = ydiff / row->x_height ();
940  if (ydiff < blshift_maxshift
941  && blob_box.height () / row->x_height () > blshift_xfraction) {
942  if (xstarts[dest_index] >= x_centre)
943  xstarts[dest_index] = blob_box.left ();
944  coeffs[dest_index * 3] = 0;
945  coeffs[dest_index * 3 + 1] = 0;
946  coeffs[dest_index * 3 + 2] = blob_box.bottom ();
947  //shift it
948  dest_index++;
949  xstarts[dest_index] = blob_box.right () + 1;
950  }
951  else {
952  if (xstarts[dest_index] <= x_centre) {
953  while (row->baseline.xcoords[src_index + 1] <= x_centre
954  && src_index < row->baseline.segments - 1) {
955  if (row->baseline.xcoords[src_index + 1] >
956  xstarts[dest_index]) {
957  coeffs[dest_index * 3] =
958  row->baseline.quadratics[src_index].a;
959  coeffs[dest_index * 3 + 1] =
960  row->baseline.quadratics[src_index].b;
961  coeffs[dest_index * 3 + 2] =
962  row->baseline.quadratics[src_index].c;
963  dest_index++;
964  xstarts[dest_index] =
965  row->baseline.xcoords[src_index + 1];
966  }
967  src_index++;
968  }
969  coeffs[dest_index * 3] =
970  row->baseline.quadratics[src_index].a;
971  coeffs[dest_index * 3 + 1] =
972  row->baseline.quadratics[src_index].b;
973  coeffs[dest_index * 3 + 2] =
974  row->baseline.quadratics[src_index].c;
975  dest_index++;
976  xstarts[dest_index] = row->baseline.xcoords[src_index + 1];
977  }
978  }
979  }
980  }
981  while (src_index < row->baseline.segments
982  && row->baseline.xcoords[src_index + 1] <= xstarts[dest_index])
983  src_index++;
984  while (src_index < row->baseline.segments) {
985  coeffs[dest_index * 3] = row->baseline.quadratics[src_index].a;
986  coeffs[dest_index * 3 + 1] = row->baseline.quadratics[src_index].b;
987  coeffs[dest_index * 3 + 2] = row->baseline.quadratics[src_index].c;
988  dest_index++;
989  src_index++;
990  xstarts[dest_index] = row->baseline.xcoords[src_index];
991  }
992  //turn to spline
993  row->baseline = QSPLINE(dest_index, &xstarts[0], &coeffs[0]);
994 }
double a
Definition: quadratc.h:57
float base_line(float xpos) const
Definition: ocrrow.h:59
Definition: rect.h:34
WERD_LIST * word_list()
Definition: ocrrow.h:55
float c
Definition: quadratc.h:59
float b
Definition: quadratc.h:58
int16_t left() const
Definition: rect.h:72
float x_height() const
Definition: ocrrow.h:64
Definition: werd.h:59
C_BLOB_LIST * cblob_list()
Definition: werd.h:98
TBOX bounding_box() const
Definition: stepblob.cpp:255
int16_t right() const
Definition: rect.h:79
int16_t bottom() const
Definition: rect.h:65
int16_t height() const
Definition: rect.h:108
QSPLINE()
Definition: quspline.h:44

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