fc_accum.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <models/shape/accumulators/fc_accum.h>
00025
00026 #include <cmath>
00027 #include <cstdio>
00028
00029 using namespace fawkes;
00030
00031 const float FittedCircle::TOO_SMALL_DELTA = 1.0e-3f;
00032
00033
00034
00035
00036
00037
00038 FittedCircle::FittedCircle(void)
00039 {
00040 reset();
00041 }
00042
00043
00044 FittedCircle::~FittedCircle(void)
00045 {
00046 }
00047
00048
00049 void
00050 FittedCircle::reset(void)
00051 {
00052 count = 0;
00053 for (int i=0; i<2; ++i)
00054 {
00055 circle_matrices[i].A00 = circle_matrices[i].A01 = circle_matrices[i].A02 = 0.0f;
00056 circle_matrices[i].A10 = circle_matrices[i].A11 = circle_matrices[i].A12 = 0.0f;
00057 circle_matrices[i].A20 = circle_matrices[i].A21 = circle_matrices[i].A22 = 0.0f;
00058 circle_matrices[i].b0 = circle_matrices[i].b1 = circle_matrices[i].b2 = 0.0f;
00059 }
00060 current_circle = 0;
00061 point_added = false;
00062 }
00063
00064
00065
00066
00067
00068 float
00069 FittedCircle::addPoint(const point_t& pt)
00070 {
00071 int next_circle = 1 - current_circle;
00072 point_added = true;
00073
00074 circle_matrices[next_circle].A00 += 4 * pt.x * pt.x;
00075 circle_matrices[next_circle].A01 += 4 * pt.x * pt.y;
00076 circle_matrices[next_circle].A02 += 2 * pt.x;
00077
00078 circle_matrices[next_circle].A10 += 4 * pt.y * pt.x;
00079 circle_matrices[next_circle].A11 += 4 * pt.y * pt.y;
00080 circle_matrices[next_circle].A12 += 2 * pt.y;
00081
00082 circle_matrices[next_circle].A20 += 2 * pt.x;
00083 circle_matrices[next_circle].A21 += 2 * pt.y;
00084 circle_matrices[next_circle].A22 += 1;
00085
00086 float r2 = pt.x * pt.x + pt.y * pt.y;
00087 circle_matrices[next_circle].b0 += 2 * r2 * pt.x;
00088 circle_matrices[next_circle].b1 += 2 * r2 * pt.y;
00089 circle_matrices[next_circle].b2 += r2;
00090
00091 float dist;
00092
00093 Circle* p = fitCircle(&circle_matrices[next_circle]);
00094 if (p)
00095 {
00096 float dx = p->center.x - pt.x;
00097 float dy = p->center.y - pt.y;
00098 float r = p->radius;
00099 dist = fabs(sqrt(dx*dx+dy*dy)-r);
00100 }
00101 else
00102 {
00103 dist = 0;
00104 }
00105
00106 return dist;
00107 }
00108
00109
00110
00111
00112
00113 void
00114 FittedCircle::removePoint(const point_t& pt)
00115 {
00116 int next_circle = 1 - current_circle;
00117 point_added = true;
00118
00119 circle_matrices[next_circle].A00 -= 4 * pt.x * pt.x;
00120 circle_matrices[next_circle].A01 -= 4 * pt.x * pt.y;
00121 circle_matrices[next_circle].A02 -= 2 * pt.x;
00122
00123 circle_matrices[next_circle].A10 -= 4 * pt.y * pt.x;
00124 circle_matrices[next_circle].A11 -= 4 * pt.y * pt.y;
00125 circle_matrices[next_circle].A12 -= 2 * pt.y;
00126
00127 circle_matrices[next_circle].A20 -= 2 * pt.x;
00128 circle_matrices[next_circle].A21 -= 2 * pt.y;
00129 circle_matrices[next_circle].A22 -= 1;
00130
00131 float r2 = pt.x * pt.x + pt.y * pt.y;
00132 circle_matrices[next_circle].b0 -= 2 * r2 * pt.x;
00133 circle_matrices[next_circle].b1 -= 2 * r2 * pt.y;
00134 circle_matrices[next_circle].b2 -= r2;
00135 }
00136
00137
00138
00139
00140
00141
00142
00143 float
00144 FittedCircle::distanceTo(const point_t& pt, bool current)
00145 {
00146 int id = current?current_circle:(1-current_circle);
00147 Circle* p = fitCircle(&circle_matrices[id]);
00148 if (p)
00149 {
00150 float dx = p->center.x - pt.x;
00151 float dy = p->center.y - pt.y;
00152 return fabs(sqrt(dx*dx+dy*dy)-p->radius);
00153 }
00154 else
00155 {
00156
00157 return 100000.0f;
00158 }
00159 }
00160
00161
00162
00163 void
00164 FittedCircle::commit(void)
00165 {
00166 if (point_added)
00167 {
00168 current_circle = 1 - current_circle;
00169 point_added = false;
00170 ++count;
00171 }
00172 }
00173
00174
00175
00176
00177 int
00178 FittedCircle::getCount(void) const
00179 {
00180 return count;
00181 }
00182
00183
00184
00185
00186
00187 Circle*
00188 FittedCircle::getCircle(void) const
00189 {
00190 return fitCircle(const_cast<circle_matrix*>(&circle_matrices[current_circle]));
00191 }
00192
00193
00194
00195
00196
00197
00198 Circle*
00199 FittedCircle::fitCircle(circle_matrix* p) const
00200 {
00201
00202 static Circle c;
00203 float delta = + p->A00 * p->A11 * p->A22 + p->A01 * p->A12 * p->A20 + p->A02 * p->A10 * p->A21
00204 - p->A00 * p->A12 * p->A21 - p->A01 * p->A10 * p->A22 - p->A02 * p->A11 * p->A20;
00205 if (delta > -TOO_SMALL_DELTA && delta < TOO_SMALL_DELTA)
00206 {
00207 printf("A=\n");
00208 printf("\t%f\t%f\t%f\n", p->A00, p->A01, p->A02);
00209 printf("\t%f\t%f\t%f\n", p->A10, p->A11, p->A12);
00210 printf("\t%f\t%f\t%f\n", p->A20, p->A21, p->A22);
00211 printf("b=\n");
00212 printf("\t%f\t%f\t%f\n", p->b0, p->b1, p->b2);
00213 printf("Delta too small: %e\n", delta);
00214 return NULL;
00215 }
00216 else
00217 {
00218 c.center.x = (float)( ( + p->b0 * p->A11 * p->A22 + p->A01 * p->A12 * p->b2 + p->A02 * p->b1 * p->A21
00219 - p->b0 * p->A12 * p->A21 - p->A01 * p->b1 * p->A22 - p->A02 * p->A11 * p->b2 ) / delta);
00220 c.center.y = (float)( ( + p->A00 * p->b1 * p->A22 + p->b0 * p->A12 * p->A20 + p->A02 * p->A10 * p->b2
00221 - p->A00 * p->A12 * p->b2 - p->b0 * p->A10 * p->A22 - p->A02 * p->b1 * p->A20 ) / delta);
00222 c.radius = (float)sqrt((+ p->A00 * p->A11 * p->b2 + p->A01 * p->b1 * p->A20 + p->b0 * p->A10 * p->A21
00223 - p->A00 * p->b1 * p->A21 - p->A01 * p->A10 * p->b2 - p->b0 * p->A11 * p->A20 ) / delta
00224 + c.center.x * c.center.x + c.center.y * c.center.y);
00225 c.count = count;
00226 return &c;
00227 }
00228 }
00229