00001 #include "stdalgorithm.hpp"
00002 #include "kube-gustavson-fft.hpp"
00003 #include <fstream>
00004 #include <iostream>
00005 #include <cmath>
00006
00007 using namespace std;
00008
00009 const int Parabelzentrum::order=5;
00010
00011
00012 Parabelzentrum::Parabelzentrum(const bildfloat& bild_, int pktmax_) :
00013 bild(bild_), pktmax(pktmax_), xmax(1), ymax(1), xmin(1), ymin(1) {
00014 reserve_2D(R, order, pktmax);
00015 f=new double[pktmax];
00016 koeff=new double[order];
00017 errors=new double[order];
00018 rel_errors=new double[order];
00019 pktzahl=0;
00020 x_estimate=0.0;
00021 y_estimate=0.0;
00022 }
00023
00024 Parabelzentrum::~Parabelzentrum() {
00025 delete_2D(R);
00026 delete[] f;
00027 delete[] koeff;
00028 delete[] errors;
00029 delete[] rel_errors;
00030 }
00031
00032 void Parabelzentrum::estimate(double x, double y) {
00033 if (pktzahl>0) STHROW("Error: Can set estimate only if there are no points");
00034 x_estimate=x;
00035 y_estimate=y;
00036 }
00037
00038 void Parabelzentrum::operator () (int x, int y) {
00039 if (pktzahl==pktmax) STHROW("Mist -- zuwenig Platz für die Punkte");
00040
00041
00042 f[pktzahl]=bild(y,x);
00043
00044
00045
00046
00047 double xn=x-x_estimate;
00048 double yn=y-y_estimate;
00049 R[pktzahl][0]=1.0;
00050 R[pktzahl][1]=xn;
00051 R[pktzahl][2]=yn;
00052 R[pktzahl][3]=xn*xn;
00053 R[pktzahl][4]=yn*yn;
00054 pktzahl++;
00055 xmax.put(xn);
00056 xmin.put(xn);
00057 ymax.put(yn);
00058 ymin.put(yn);
00059 }
00060
00061 void Parabelzentrum::clear() {
00062 pktzahl=0;
00063 xmax.clear();
00064 xmin.clear();
00065 ymax.clear();
00066 ymin.clear();
00067 x_cent=0.0;
00068 y_cent=0.0;
00069 x_estimate=0.0;
00070 y_estimate=0.0;
00071
00072 }
00073
00074 bool Parabelzentrum::fit() {
00075 x_cent=0; y_cent=0;
00076 for (int i=0; i<pktzahl; i++) {
00077 x_cent+=R[i][1];
00078 y_cent+=R[i][2];
00079 }
00080 x_cent/=pktzahl;
00081 y_cent/=pktzahl;
00082
00083
00084
00085 s_xcent=0; s_ycent=0;
00086 for (int i=0; i<pktzahl; i++) {
00087 s_xcent+=SQR(R[i][1]-x_cent);
00088 s_ycent+=SQR(R[i][2]-y_cent);
00089 }
00090 s_xcent/=pktzahl;
00091 s_ycent/=pktzahl;
00092
00093 if (pktzahl==0) {
00094 std::cerr<<"Fit ohne Punkte !"<<std::endl;
00095 return false;
00096 }
00097
00098 if (pktzahl < 2*order) {
00099 std::cerr<<"Sehr wenig Punkte !"<<std::endl;
00100 return true;
00101 }
00102
00103
00104 double *d=new double[order];
00105
00106
00107
00108 if(QR(pktzahl, order, R, d, f, 1e-10)) {
00109 std::cerr<<"Matrix singulär ????"<<std::endl;
00110
00111
00112 return false;
00113 }
00114
00115
00116 rdsolve(order, R, d, f, koeff);
00117 double x=-koeff[1]/(2*koeff[3]);
00118 double y=-koeff[2]/(2*koeff[4]);
00119
00120
00121 compute_errors(order, pktzahl, R, d, f, errors);
00122 for (int o=0; o<order; o++)
00123 rel_errors[o]=errors[o]/koeff[o];
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 if ((x>xmax()) || (x<xmin()) || (y>ymax()) || (y<ymin())) {
00134 std::cerr<<"Danebengeschossen !"<<std::endl;
00135 return true;
00136 }
00137
00138
00139 x_cent=x;
00140 y_cent=y;
00141
00142
00143
00144 s_xcent=x_cent*sqrt(SQR(rel_errors[1]) + SQR (rel_errors[3]));
00145 s_ycent=y_cent*sqrt(SQR(rel_errors[2]) + SQR (rel_errors[4]));
00146
00147 return true;
00148 delete[] d;
00149 }
00150
00151 bildcomplex::bildcomplex(const bildfloat &realvalue) :
00152 bildcomplex_base()
00153 { MAP(realvalue) {
00154 (*this)(y,x).re=realvalue(y,x);
00155 (*this)(y,x).im=0.0;
00156 }
00157 }
00158
00159 bildcomplex::bildcomplex(const bildfloat& real, const bildfloat& imag) :
00160 bildcomplex_base()
00161 { MAP(real) {
00162 (*this)(y,x).re=real(y,x);
00163 (*this)(y,x).im=imag(y,x);
00164 }
00165 }
00166
00167 void bildcomplex::decompose(bildfloat&real, bildfloat& imag)
00168 {
00169 MAP((*this)) {
00170 real(y,x)=(*this)(y,x).re;
00171 imag(y,x)=(*this)(y,x).im;
00172 }
00173
00174 }
00175
00176
00177 bildcomplex& bildcomplex::FFT_forward() {
00178 forward_fft2f(bild[0], SIZEY, SIZEX);
00179 return *this;
00180 }
00181
00182
00183 bildcomplex& bildcomplex::FFT_backward() {
00184 inverse_fft2f(bild[0], SIZEY, SIZEX);
00185 return *this;
00186 }
00187
00188 bildfloat& bildcomplex::norm(bildfloat &ret) {
00189 MAP (ret) {
00190 ret(y,x)=SQR((*this)(y,x).re)+SQR((*this)(y,x).im);
00191 }
00192 return ret;
00193 }
00194
00195 bildcomplex& bildcomplex::Hamming_window(float width, float xm, float ym) {
00196
00197 MAP((*this)) {
00198 float xs=x-xm;
00199 float ys=y-ym;
00200 if (SQR(xs)+SQR(ys) < SQR(width))
00201 (*this)(y,x)*=SQR(0.54+0.46*cos(M_PI*sqrt(SQR(xs)+SQR(ys))/width))*2.36961606240022;
00202 else
00203 (*this)(y,x)=0.0;
00204 }
00205 return *this;
00206 }
00207
00208 bildcomplex& bildcomplex::Hamming_unwindow(float width, float xm, float ym) {
00209
00210 MAP((*this)) {
00211 float xs=x-xm;
00212 float ys=y-ym;
00213 if (SQR(xs)+SQR(ys) < SQR(width))
00214 (*this)(y,x)/=SQR(0.54+0.46*cos(M_PI*sqrt(SQR(xs)+SQR(ys))/width))*2.36961606240022;
00215 else
00216 (*this)(y,x)=0.0;
00217 }
00218 return *this;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 bool pnpoly(int npol, float *xp, float *yp, float x, float y)
00250 {
00251 int i, j;
00252 bool c = false;
00253 for (i = 0, j = npol-1; i < npol; j = i++) {
00254 if ((((yp[i]<=y) && (y<yp[j])) ||
00255 ((yp[j]<=y) && (y<yp[i]))) &&
00256 (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
00257
00258 c = !c;
00259 }
00260 return c;
00261 }
00262
00263
00264
00265 Voronoischnitt::Voronoischnitt(bildfloat &bfl, float xmitte_, float ymitte_, const char *vorofile) :
00266 rb(bfl), xmitte(xmitte_), ymitte(ymitte_), r(0,0)
00267 {
00268 ifstream vf(vorofile);
00269 vector<Point> centerpoints;
00270 vector<cell> zellen;
00271 if (!vf) STHROW("Voronoidata "<<vorofile<<" not found");
00272
00273 while (vf) {
00274
00275 float x; float y; int anzahl;
00276 vf >>x; vf >>y; vf>>anzahl;
00277
00278 int cellindex=centerpoints.size();
00279 centerpoints.push_back(make_pair(x,y));
00280
00281
00282 zellen.resize(cellindex+1);
00283 for (int i=0; i<anzahl; i++) {
00284 vf >> x; vf >>y;
00285 zellen[cellindex].push_back(make_pair(x,y));
00286 }
00287 }
00288 vf.close();
00289
00290 if (zellen.size()<2) STHROW("Could not read Voronoi data "<<vorofile);
00291
00292 int ind=0;
00293 float mindist=SQR(centerpoints[0].first-xmitte)+SQR(centerpoints[0].second-ymitte);
00294 for (size_t i=1; i<centerpoints.size(); i++) {
00295 float dist=SQR(centerpoints[i].first-xmitte)+SQR(centerpoints[i].second-ymitte);
00296 if (dist<mindist) {
00297 mindist=dist;
00298 ind=i;
00299 }
00300 }
00301
00302 cerr<<ind<<endl;
00303 zelle=zellen[ind];
00304
00305 stddev=0;
00306
00307 npol=zelle.size()+1;
00308 xp=new float[npol];
00309 yp=new float[npol];
00310 for (int i=0; i<npol-1; i++) {
00311 xp[i]=zelle[i].first;
00312 yp[i]=zelle[i].second;
00313 }
00314 xp[npol-1]=xp[0];
00315 yp[npol-1]=yp[0];
00316
00317
00318 }
00319
00320 Voronoischnitt::~Voronoischnitt() {
00321 delete [] xp;
00322 delete [] yp;
00323 }
00324
00325 void Voronoischnitt::compute_schnitt(int nr) {
00326
00327 int anzahl=zelle.size();
00328 if (anzahl!=6) cerr<<"Warnung: Zelle hat nicht 6 Ecken, sondern "<<anzahl<<endl;
00329 int ind=0;
00330 maxdist=mindist=SQR(zelle[0].first-zelle[3].first)+SQR(zelle[0].second-zelle[3].second);
00331 for (int shift=1; shift < anzahl; shift++) {
00332 float aktdist=SQR(zelle[shift%anzahl].first-zelle[(shift+3)%anzahl].first)+
00333 SQR(zelle[shift%anzahl].second-zelle[(shift+3)%anzahl].second);
00334 if (aktdist>maxdist) {
00335 maxdist=aktdist;
00336 ind=shift;
00337 }
00338 if (aktdist<mindist) mindist=aktdist;
00339 }
00340
00341 mindist=sqrt(mindist);
00342 maxdist=sqrt(maxdist);
00343
00344 cerr<<".c create line "<<zelle[ind%anzahl].first<<" "<<zelle[ind%anzahl].second<<" "<<
00345 zelle[(ind+3)%anzahl].first<<" "<<zelle[(ind+3)%anzahl].second<<endl;
00346
00347
00348 vec2d M(xmitte, ymitte);
00349 vec2d P1(zelle[ind%anzahl].first, zelle[ind%anzahl].second);
00350 vec2d P2(zelle[(ind+3)%anzahl].first, zelle[(ind+3)%anzahl].second);
00351
00352 vec2d v1=P1-M;
00353 vec2d v2=P2-M;
00354
00355 r=v1/abs(v1)-v2/abs(v2);
00356
00357 int stepstart, stepend;
00358
00359
00360 cerr<<"Richtungsvektor "<<r.x<<", "<<r.y<<endl;
00361 if (abs(r.x) >abs(r.y)) {
00362 r/=r.x;
00363
00364 if (P1.x < P2.x) {
00365 stepstart=int(-abs(v1.x)); stepend=int(abs(v2.x));
00366 } else {
00367 stepstart=int(-abs(v2.x)); stepend=int(abs(v1.x));
00368 }
00369 } else {
00370 r/=r.y;
00371 if (P1.y < P2.y) {
00372 stepstart=int(-abs(v1.y)); stepend=int(abs(v2.y));
00373 } else {
00374 stepstart=int(-abs(v2.y)); stepend=int(abs(v1.y));
00375 }
00376 }
00377
00378
00379
00380 for (int step=stepstart; step<=stepend; step++) {
00381 int xpunkt= int(floor(r.x*step+M.x+0.5));
00382 int ypunkt= int(floor(r.y*step+M.y+0.5));
00383
00384
00385 vec2d distvec(xpunkt-xmitte, ypunkt-ymitte);
00386 double dist=abs(distvec);
00387 if (r*distvec < 0) dist*=-1;
00388
00389 cout<<nr<<"\t"<<dist<<"\t"<<rb(ypunkt, xpunkt)<<endl;
00390 }
00391 cout<<endl;
00392
00393 }
00394
00395 vec2d Voronoischnitt::direction() {
00396 return r;
00397 }
00398
00399
00400 float Voronoischnitt::boundary_average()
00401 {
00402 int anzahl=zelle.size();
00403 if (anzahl!=6) cerr<<"Warnung: Zelle hat nicht 6 Ecken, sondern "<<anzahl<<endl;
00404
00405 mean_avg avg(rb);
00406 for (int i=0; i<anzahl; i++) {
00407
00408
00409
00410 avg(int(floor(zelle[i].first+0.5)), int(floor(zelle[i].second+0.5)));
00411 }
00412
00413 double height=avg.sum/avg.pktzahl;
00414 stddev=sqrt((avg.sqrsum/avg.pktzahl) - SQR(height));
00415 cerr<<"Mittlere Höhe am Rand: "<<height<<" +/- "<<stddev<<endl;
00416 return avg.sum/avg.pktzahl;
00417 }
00418
00419
00420 bool Voronoischnitt::contains(float x, float y) {
00421 return pnpoly(npol, xp, yp, x, y);
00422 }
00423
00424