Tesseract
3.02
|
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 }