Tesseract  3.02
QSPLINE Class Reference

#include <quspline.h>

List of all members.

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
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 30 of file quspline.h.


Constructor & Destructor Documentation

QSPLINE::QSPLINE ( ) [inline]

Definition at line 42 of file quspline.h.

              {  //empty constructor
      segments = 0;
      xcoords = NULL;            //everything empty
      quadratics = NULL;
    }
QSPLINE::QSPLINE ( const QSPLINE src)

Definition at line 136 of file quspline.cpp.

                                     {
  segments = 0;
  xcoords = NULL;
  quadratics = NULL;
  *this = src;
}
QSPLINE::QSPLINE ( inT32  count,
inT32 xstarts,
double *  coeffs 
)

Definition at line 38 of file quspline.cpp.

                  {
  inT32 index;                   //segment index

                                 //get memory
  xcoords = (inT32 *) alloc_mem ((count + 1) * sizeof (inT32));
  quadratics = (QUAD_COEFFS *) alloc_mem (count * sizeof (QUAD_COEFFS));
  segments = count;
  for (index = 0; index < segments; index++) {
                                 //copy them
    xcoords[index] = xstarts[index];
    quadratics[index] = QUAD_COEFFS (coeffs[index * 3],
      coeffs[index * 3 + 1],
      coeffs[index * 3 + 2]);
  }
                                 //right edge
  xcoords[index] = xstarts[index];
}
QSPLINE::~QSPLINE ( )

Definition at line 151 of file quspline.cpp.

  {
  if (xcoords != NULL) {
    free_mem(xcoords);
    xcoords = NULL;
  }
  if (quadratics != NULL) {
    free_mem(quadratics);
    quadratics = NULL;
  }
}
QSPLINE::QSPLINE ( int  xstarts[],
int  segcount,
int  xcoords[],
int  ycoords[],
int  blobcount,
int  degree 
)

Definition at line 67 of file quspline.cpp.

  {
  register int pointindex;       /*no along text line */
  register int segment;          /*segment no */
  inT32 *ptcounts;               //no in each segment
  QLSQ qlsq;                     /*accumulator */

  segments = segcount;
  xcoords = (inT32 *) alloc_mem ((segcount + 1) * sizeof (inT32));
  ptcounts = (inT32 *) alloc_mem ((segcount + 1) * sizeof (inT32));
  quadratics = (QUAD_COEFFS *) alloc_mem (segcount * sizeof (QUAD_COEFFS));
  memmove (xcoords, xstarts, (segcount + 1) * sizeof (inT32));
  ptcounts[0] = 0;               /*none in any yet */
  for (segment = 0, pointindex = 0; pointindex < pointcount; pointindex++) {
    while (segment < segcount && xpts[pointindex] >= xstarts[segment]) {
      segment++;                 /*try next segment */
                                 /*cumulative counts */
      ptcounts[segment] = ptcounts[segment - 1];
    }
    ptcounts[segment]++;         /*no in previous partition */
  }
  while (segment < segcount) {
    segment++;
                                 /*zero the rest */
    ptcounts[segment] = ptcounts[segment - 1];
  }

  for (segment = 0; segment < segcount; segment++) {
    qlsq.clear ();
                                 /*first blob */
    pointindex = ptcounts[segment];
    if (pointindex > 0
      && xpts[pointindex] != xpts[pointindex - 1]
      && xpts[pointindex] != xstarts[segment])
      qlsq.add (xstarts[segment],
        ypts[pointindex - 1]
        + (ypts[pointindex] - ypts[pointindex - 1])
        * (xstarts[segment] - xpts[pointindex - 1])
        / (xpts[pointindex] - xpts[pointindex - 1]));
    for (; pointindex < ptcounts[segment + 1]; pointindex++) {
      qlsq.add (xpts[pointindex], ypts[pointindex]);
    }
    if (pointindex > 0 && pointindex < pointcount
      && xpts[pointindex] != xstarts[segment + 1])
      qlsq.add (xstarts[segment + 1],
        ypts[pointindex - 1]
        + (ypts[pointindex] - ypts[pointindex - 1])
        * (xstarts[segment + 1] - xpts[pointindex - 1])
        / (xpts[pointindex] - xpts[pointindex - 1]));
    qlsq.fit (degree);
    quadratics[segment].a = qlsq.get_a ();
    quadratics[segment].b = qlsq.get_b ();
    quadratics[segment].c = qlsq.get_c ();
  }
  free_mem(ptcounts);
}

Member Function Documentation

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

Definition at line 306 of file quspline.cpp.

                           {
  register int segment;          /*current segment of spline */
  int dest_segment;              //dest index
  int *xstarts;                  //new boundaries
  QUAD_COEFFS *quads;            //new ones
  int increment;                 //in size

  increment = xmin < xcoords[0] ? 1 : 0;
  if (xmax > xcoords[segments])
    increment++;
  if (increment == 0)
    return;
  xstarts = (int *) alloc_mem ((segments + 1 + increment) * sizeof (int));
  quads =
    (QUAD_COEFFS *) alloc_mem ((segments + increment) * sizeof (QUAD_COEFFS));
  if (xmin < xcoords[0]) {
    xstarts[0] = xmin;
    quads[0].a = 0;
    quads[0].b = gradient;
    quads[0].c = y (xcoords[0]) - quads[0].b * xcoords[0];
    dest_segment = 1;
  }
  else
    dest_segment = 0;
  for (segment = 0; segment < segments; segment++) {
    xstarts[dest_segment] = xcoords[segment];
    quads[dest_segment] = quadratics[segment];
    dest_segment++;
  }
  xstarts[dest_segment] = xcoords[segment];
  if (xmax > xcoords[segments]) {
    quads[dest_segment].a = 0;
    quads[dest_segment].b = gradient;
    quads[dest_segment].c = y (xcoords[segments])
      - quads[dest_segment].b * xcoords[segments];
    dest_segment++;
    xstarts[dest_segment] = xmax + 1;
  }
  segments = dest_segment;
  free_mem(xcoords);
  free_mem(quadratics);
  xcoords = (inT32 *) xstarts;
  quadratics = quads;
}
void QSPLINE::move ( ICOORD  vec)

Definition at line 259 of file quspline.cpp.

                    {
  inT32 segment;                 //index of segment
  inT16 x_shift = vec.x ();

  for (segment = 0; segment < segments; segment++) {
    xcoords[segment] += x_shift;
    quadratics[segment].move (vec);
  }
  xcoords[segment] += x_shift;
}
QSPLINE & QSPLINE::operator= ( const QSPLINE source)

Definition at line 170 of file quspline.cpp.

                        {
  if (xcoords != NULL)
    free_mem(xcoords);
  if (quadratics != NULL)
    free_mem(quadratics);

  segments = source.segments;
  xcoords = (inT32 *) alloc_mem ((segments + 1) * sizeof (inT32));
  quadratics = (QUAD_COEFFS *) alloc_mem (segments * sizeof (QUAD_COEFFS));
  memmove (xcoords, source.xcoords, (segments + 1) * sizeof (inT32));
  memmove (quadratics, source.quadratics, segments * sizeof (QUAD_COEFFS));
  return *this;
}
BOOL8 QSPLINE::overlap ( QSPLINE spline2,
double  fraction 
)

Definition at line 280 of file quspline.cpp.

                        {
  int leftlimit;                 /*common left limit */
  int rightlimit;                /*common right limit */

  leftlimit = xcoords[1];
  rightlimit = xcoords[segments - 1];
                                 /*or too non-overlap */
  if (spline2->segments < 3 || spline2->xcoords[1] > leftlimit + fraction * (rightlimit - leftlimit)
    || spline2->xcoords[spline2->segments - 1] < rightlimit
    - fraction * (rightlimit - leftlimit))
    return FALSE;
  else
    return TRUE;
}
void QSPLINE::plot ( ScrollView window,
ScrollView::Color  colour 
) const

Definition at line 363 of file quspline.cpp.

                          {
  inT32 segment;                 //index of segment
  inT16 step;                    //index of poly piece
  double increment;              //x increment
  double x;                      //x coord

  window->Pen(colour);
  for (segment = 0; segment < segments; segment++) {
    increment =
      (double) (xcoords[segment + 1] -
      xcoords[segment]) / QSPLINE_PRECISION;
    x = xcoords[segment];
    for (step = 0; step <= QSPLINE_PRECISION; step++) {
      if (segment == 0 && step == 0)
        window->SetCursor(x, quadratics[segment].y (x));
      else
        window->DrawTo(x, quadratics[segment].y (x));
      x += increment;
    }
  }
}
double QSPLINE::step ( double  x1,
double  x2 
)

Definition at line 192 of file quspline.cpp.

                                {
  int index1, index2;            //indices of coords
  double total;                  /*total steps */

  index1 = spline_index (x1);
  index2 = spline_index (x2);
  total = 0;
  while (index1 < index2) {
    total +=
      (double) quadratics[index1 + 1].y ((float) xcoords[index1 + 1]);
    total -= (double) quadratics[index1].y ((float) xcoords[index1 + 1]);
    index1++;                    /*next segment */
  }
  return total;                  /*total steps */
}
double QSPLINE::y ( double  x) const

Definition at line 217 of file quspline.cpp.

                         {
  inT32 index;                   //segment index

  index = spline_index (x);
  return quadratics[index].y (x);//in correct segment
}

Friends And Related Function Documentation

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

Definition at line 680 of file tordmain.cpp.

                                                  {
  TBOX blob_box;                 //bounding box
  C_BLOB *blob;                  //current blob
  WERD *word;                    //current word
  inT32 blob_count;              //no of blobs
  inT32 src_index;               //source segment
  inT32 dest_index;              //destination segment
  inT32 *xstarts;                //spline segments
  double *coeffs;                //spline coeffs
  float ydiff;                   //baseline error
  float x_centre;                //centre of blob
                                 //words of row
  WERD_IT word_it = row->word_list ();
  C_BLOB_IT blob_it;             //blob iterator

  blob_count = 0;
  for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) {
    word = word_it.data ();      //current word
                                 //get total blobs
    blob_count += word->cblob_list ()->length ();
  }
  if (blob_count == 0)
    return;
  xstarts =
    (inT32 *) alloc_mem ((blob_count + row->baseline.segments + 1) *
    sizeof (inT32));
  coeffs =
    (double *) alloc_mem ((blob_count + row->baseline.segments) * 3 *
    sizeof (double));

  src_index = 0;
  dest_index = 0;
  xstarts[0] = row->baseline.xcoords[0];
  for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) {
    word = word_it.data ();      //current word
                                 //blobs in word
    blob_it.set_to_list (word->cblob_list ());
    for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
    blob_it.forward ()) {
      blob = blob_it.data ();
      blob_box = blob->bounding_box ();
      x_centre = (blob_box.left () + blob_box.right ()) / 2.0;
      ydiff = blob_box.bottom () - row->base_line (x_centre);
      if (ydiff < 0)
        ydiff = -ydiff / row->x_height ();
      else
        ydiff = ydiff / row->x_height ();
      if (ydiff < blshift_maxshift
        && blob_box.height () / row->x_height () > blshift_xfraction) {
        if (xstarts[dest_index] >= x_centre)
          xstarts[dest_index] = blob_box.left ();
        coeffs[dest_index * 3] = 0;
        coeffs[dest_index * 3 + 1] = 0;
        coeffs[dest_index * 3 + 2] = blob_box.bottom ();
        //shift it
        dest_index++;
        xstarts[dest_index] = blob_box.right () + 1;
      }
      else {
        if (xstarts[dest_index] <= x_centre) {
          while (row->baseline.xcoords[src_index + 1] <= x_centre
          && src_index < row->baseline.segments - 1) {
            if (row->baseline.xcoords[src_index + 1] >
            xstarts[dest_index]) {
              coeffs[dest_index * 3] =
                row->baseline.quadratics[src_index].a;
              coeffs[dest_index * 3 + 1] =
                row->baseline.quadratics[src_index].b;
              coeffs[dest_index * 3 + 2] =
                row->baseline.quadratics[src_index].c;
              dest_index++;
              xstarts[dest_index] =
                row->baseline.xcoords[src_index + 1];
            }
            src_index++;
          }
          coeffs[dest_index * 3] =
            row->baseline.quadratics[src_index].a;
          coeffs[dest_index * 3 + 1] =
            row->baseline.quadratics[src_index].b;
          coeffs[dest_index * 3 + 2] =
            row->baseline.quadratics[src_index].c;
          dest_index++;
          xstarts[dest_index] = row->baseline.xcoords[src_index + 1];
        }
      }
    }
  }
  while (src_index < row->baseline.segments
    && row->baseline.xcoords[src_index + 1] <= xstarts[dest_index])
    src_index++;
  while (src_index < row->baseline.segments) {
    coeffs[dest_index * 3] = row->baseline.quadratics[src_index].a;
    coeffs[dest_index * 3 + 1] = row->baseline.quadratics[src_index].b;
    coeffs[dest_index * 3 + 2] = row->baseline.quadratics[src_index].c;
    dest_index++;
    src_index++;
    xstarts[dest_index] = row->baseline.xcoords[src_index];
  }
                                 //turn to spline
  row->baseline = QSPLINE (dest_index, xstarts, coeffs);
  free_mem(xstarts);
  free_mem(coeffs);
}

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