00001
00020 #include "mfcpch.h"
00021 #include <stdio.h>
00022 #include <math.h>
00023 #include "errcode.h"
00024 #include "linlsq.h"
00025
00026 #ifndef __UNIX__
00027 #define M_PI 3.14159265359
00028 #endif
00029
00030 const ERRCODE EMPTY_LLSQ = "Can't delete from an empty LLSQ";
00031
00032 #define EXTERN
00033
00036 EXTERN double_VAR (pdlsq_posdir_ratio, 4e-6, "Mult of dir to cf pos");
00037 EXTERN double_VAR (pdlsq_threshold_angleavg, 0.1666666,
00038 "Frac of pi for simple fit");
00044 void LLSQ::clear() {
00045 n = 0;
00046 sigx = 0;
00047 sigy = 0;
00048 sigxx = 0;
00049 sigxy = 0;
00050 sigyy = 0;
00051 }
00052
00053
00057 void LLSQ::add(
00058 double x,
00059 double y
00060 ) {
00061 n++;
00062 sigx += x;
00063 sigy += y;
00064 sigxx += x * x;
00065 sigxy += x * y;
00066 sigyy += y * y;
00067 }
00068
00069
00073 void LLSQ::remove(
00074 double x,
00075 double y
00076 ) {
00077 if (n <= 0)
00078
00079 EMPTY_LLSQ.error ("LLSQ::remove", ABORT, NULL);
00080 n--;
00081 sigx -= x;
00082 sigy -= y;
00083 sigxx -= x * x;
00084 sigxy -= x * y;
00085 sigyy -= y * y;
00086 }
00087
00088
00094 double LLSQ::m() {
00095 if (n > 1)
00096 return (sigxy - sigx * sigy / n) / (sigxx - sigx * sigx / n);
00097 else
00098 return 0;
00099 }
00100
00101
00107 double LLSQ::c(
00108 double m
00109 ) {
00110 if (n > 0)
00111 return (sigy - m * sigx) / n;
00112 else
00113 return 0;
00114 }
00115
00116
00122 double LLSQ::rms(
00123 double m,
00124 double c
00125 ) {
00126 double error;
00127
00128 if (n > 0) {
00129 error =
00130 sigyy + m * (m * sigxx + 2 * (c * sigx - sigxy)) + c * (n * c -
00131 2 * sigy);
00132 if (error >= 0)
00133 error = sqrt (error / n);
00134 else
00135 error = 0;
00136 }
00137 else
00138 error = 0;
00139 return error;
00140 }
00141
00142
00148 double LLSQ::spearman() {
00149 double error;
00150
00151 if (n > 1) {
00152 error = (sigxx - sigx * sigx / n) * (sigyy - sigy * sigy / n);
00153 if (error > 0) {
00154 error = (sigxy - sigx * sigy / n) / sqrt (error);
00155 }
00156 else
00157 error = 1;
00158 }
00159 else
00160 error = 1;
00161 return error;
00162 }
00163
00164
00169 float PDLSQ::fit(
00170 DIR128 &ang,
00171 float &sin_ang,
00172 float &cos_ang,
00173 float &r) {
00174 double a, b;
00175 double angle;
00176 double avg_angle;
00177 double error;
00178 double sinx, cosx;
00179
00180 if (pos.n > 0) {
00181 a = pos.sigxy - pos.sigx * pos.sigy / pos.n
00182 + pdlsq_posdir_ratio * dir.sigxy;
00183 b =
00184 pos.sigxx - pos.sigyy + (pos.sigy * pos.sigy -
00185 pos.sigx * pos.sigx) / pos.n +
00186 pdlsq_posdir_ratio * (dir.sigxx - dir.sigyy);
00187 if (dir.sigy != 0 || dir.sigx != 0)
00188 avg_angle = atan2 (dir.sigy, dir.sigx);
00189 else
00190 avg_angle = 0;
00191 if ((a != 0 || b != 0) && pos.n > 1)
00192 angle = atan2 (2 * a, b) / 2;
00193 else
00194 angle = avg_angle;
00195 error = avg_angle - angle;
00196 if (error > M_PI / 2) {
00197 error -= M_PI;
00198 angle += M_PI;
00199 }
00200 if (error < -M_PI / 2) {
00201 error += M_PI;
00202 angle -= M_PI;
00203 }
00204 if (error > M_PI * pdlsq_threshold_angleavg
00205 || error < -M_PI * pdlsq_threshold_angleavg)
00206 angle = avg_angle;
00207
00208 ang = (INT16) (angle * MODULUS / (2 * M_PI));
00209 sinx = sin (angle);
00210 cosx = cos (angle);
00211 r = (sinx * pos.sigx - cosx * pos.sigy) / pos.n;
00212
00213
00214
00215 error = dir.sigxx * sinx * sinx + dir.sigyy * cosx * cosx
00216 - 2 * dir.sigxy * sinx * cosx;
00217 error *= pdlsq_posdir_ratio;
00218 error += sinx * sinx * pos.sigxx + cosx * cosx * pos.sigyy
00219 - 2 * sinx * cosx * pos.sigxy
00220 - 2 * r * (sinx * pos.sigx - cosx * pos.sigy) + r * r * pos.n;
00221 if (error >= 0)
00222
00223 error = sqrt (error / pos.n);
00224 else
00225 error = 0;
00226 sin_ang = sinx;
00227 cos_ang = cosx;
00228 }
00229 else {
00230 sin_ang = 0.0f;
00231 cos_ang = 0.0f;
00232 ang = 0;
00233 error = 0;
00234 }
00235 return error;
00236 }