Tesseract  3.02
tesseract-ocr/ccstruct/quadlsq.cpp
Go to the documentation of this file.
00001 /**********************************************************************
00002  * File:        quadlsq.cpp  (Formerly qlsq.c)
00003  * Description: Code for least squares approximation of quadratics.
00004  * Author:              Ray Smith
00005  * Created:             Wed Oct  6 15:14:23 BST 1993
00006  *
00007  * (C) Copyright 1993, Hewlett-Packard Ltd.
00008  ** Licensed under the Apache License, Version 2.0 (the "License");
00009  ** you may not use this file except in compliance with the License.
00010  ** You may obtain a copy of the License at
00011  ** http://www.apache.org/licenses/LICENSE-2.0
00012  ** Unless required by applicable law or agreed to in writing, software
00013  ** distributed under the License is distributed on an "AS IS" BASIS,
00014  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  ** See the License for the specific language governing permissions and
00016  ** limitations under the License.
00017  *
00018  **********************************************************************/
00019 
00020 #include "mfcpch.h"
00021 #include          <stdio.h>
00022 #include          <math.h>
00023 #include          "errcode.h"
00024 #include          "quadlsq.h"
00025 
00026 const ERRCODE EMPTY_QLSQ = "Can't delete from an empty QLSQ";
00027 
00028 #define EXTERN
00029 
00030 /**********************************************************************
00031  * QLSQ::clear
00032  *
00033  * Function to initialize a QLSQ.
00034  **********************************************************************/
00035 
00036 void QLSQ::clear() {  //initialize
00037   a = 0;
00038   b = 0;
00039   c = 0;
00040   n = 0;                         //no elements
00041   sigx = 0;                      //update accumulators
00042   sigy = 0;
00043   sigxx = 0;
00044   sigxy = 0;
00045   sigyy = 0;
00046   sigxxx = 0;
00047   sigxxy = 0;
00048   sigxxxx = 0;
00049 }
00050 
00051 
00052 /**********************************************************************
00053  * QLSQ::add
00054  *
00055  * Add an element to the accumulator.
00056  **********************************************************************/
00057 
00058 void QLSQ::add(           //add an element
00059                double x,  //xcoord
00060                double y   //ycoord
00061               ) {
00062   n++;                           //count elements
00063   sigx += x;                     //update accumulators
00064   sigy += y;
00065   sigxx += x * x;
00066   sigxy += x * y;
00067   sigyy += y * y;
00068   sigxxx += (long double) x *x * x;
00069   sigxxy += (long double) x *x * y;
00070   sigxxxx += (long double) x *x * x * x;
00071 }
00072 
00073 
00074 /**********************************************************************
00075  * QLSQ::remove
00076  *
00077  * Delete an element from the acculuator.
00078  **********************************************************************/
00079 
00080 void QLSQ::remove(           //delete an element
00081                   double x,  //xcoord
00082                   double y   //ycoord
00083                  ) {
00084   if (n <= 0)
00085                                  //illegal
00086     EMPTY_QLSQ.error ("QLSQ::remove", ABORT, NULL);
00087   n--;                           //count elements
00088   sigx -= x;                     //update accumulators
00089   sigy -= y;
00090   sigxx -= x * x;
00091   sigxy -= x * y;
00092   sigyy -= y * y;
00093   sigxxx -= (long double) x *x * x;
00094   sigxxy -= (long double) x *x * y;
00095   sigxxxx -= (long double) x *x * x * x;
00096 }
00097 
00098 
00099 /**********************************************************************
00100  * QLSQ::fit
00101  *
00102  * Fit the given degree of polynomial and store the result.
00103  **********************************************************************/
00104 
00105 void QLSQ::fit(            //fit polynomial
00106                int degree  //degree to fit
00107               ) {
00108   long double cubetemp;          //intermediates
00109   long double squaretemp;
00110   long double top96, bottom96;   /*accurate top & bottom */
00111 
00112   if (n >= 4 && degree >= 2) {
00113     cubetemp = sigxxx * n - (long double) sigxx *sigx;
00114 
00115     top96 =
00116       cubetemp * ((long double) sigxy * n - (long double) sigx * sigy);
00117 
00118     squaretemp = (long double) sigxx *n - (long double) sigx *sigx;
00119 
00120     top96 += squaretemp * ((long double) sigxx * sigy - sigxxy * n);
00121 
00122     bottom96 = cubetemp * cubetemp;
00123 
00124     bottom96 -= squaretemp * (sigxxxx * n - (long double) sigxx * sigxx);
00125 
00126     a = top96 / bottom96;
00127 
00128     top96 = ((long double) sigxx * sigx - sigxxx * n) * a
00129       + (long double) sigxy *n - (long double) sigx *sigy;
00130     bottom96 = (long double) sigxx *n - (long double) sigx *sigx;
00131     b = top96 / bottom96;
00132 
00133     c = (sigy - a * sigxx - b * sigx) / n;
00134   }
00135   else if (n == 0 || degree < 0) {
00136     a = b = c = 0;
00137   }
00138   else {
00139     a = 0;
00140     if (n > 1 && degree > 0) {
00141       b = (sigxy * n - sigx * sigy) / (sigxx * n - sigx * sigx);
00142     }
00143     else
00144       b = 0;
00145     c = (sigy - b * sigx) / n;
00146   }
00147 }