00001
00002
00003
00004
00005
00006
00007 #include "cell.hh"
00008 #include "container.hh"
00009
00010
00011
00012
00013
00014
00015 template<class r_option>
00016 container_base<r_option>::container_base(fpoint xa,fpoint xb,fpoint ya,fpoint yb,fpoint za,fpoint zb,
00017 int xn,int yn,int zn,bool xper,bool yper,bool zper,int memi)
00018 : ax(xa),bx(xb),ay(ya),by(yb),az(za),bz(zb),
00019 xsp(xn/(xb-xa)),ysp(yn/(yb-ya)),zsp(zn/(zb-za)),
00020 nx(xn),ny(yn),nz(zn),nxy(xn*yn),nxyz(xn*yn*zn),
00021 hx(xper?2*xn+1:xn),hy(yper?2*yn+1:yn),hz(zper?2*zn+1:zn),hxy(hx*hy),hxyz(hx*hy*hz),
00022 xperiodic(xper),yperiodic(yper),zperiodic(zper),
00023 mv(0),wall_number(0),current_wall_size(init_wall_size),
00024 radius(this),sz(radius.mem_size) {
00025 int l;
00026 co=new int[nxyz];
00027 for(l=0;l<nxyz;l++) co[l]=0;
00028 mem=new int[nxyz];
00029 for(l=0;l<nxyz;l++) mem[l]=memi;
00030 id=new int*[nxyz];
00031 for(l=0;l<nxyz;l++) id[l]=new int[memi];
00032 p=new fpoint*[nxyz];
00033 for(l=0;l<nxyz;l++) p[l]=new fpoint[sz*memi];
00034 mask=new unsigned int[hxyz];
00035 for(l=0;l<hxyz;l++) mask[l]=0;
00036 s_size=3*(hxy+hz*(hx+hy));if(s_size<18) s_size=18;
00037 sl=new int[s_size];
00038 walls=new wall*[current_wall_size];
00039 mrad=new fpoint[hgridsq*seq_length];
00040 initialize_radii();
00041 }
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 template<class r_option>
00053 void container_base<r_option>::initialize_radii() {
00054 const unsigned int b1=1<<21,b2=1<<22,b3=1<<24,b4=1<<25,b5=1<<27,b6=1<<28;
00055 const fpoint xstep=(bx-ax)/nx/fgrid;
00056 const fpoint ystep=(by-ay)/ny/fgrid;
00057 const fpoint zstep=(bz-az)/nz/fgrid;
00058 int i,j,k,lx,ly,lz,l=0,q;
00059 unsigned int *e=const_cast<unsigned int*> (wl);
00060 fpoint xlo,ylo,zlo,xhi,yhi,zhi,minr;fpoint *radp=mrad;
00061 unsigned int f,qq;
00062 for(zlo=0,zhi=zstep,lz=0;lz<hgrid;zlo=zhi,zhi+=zstep,lz++) {
00063 for(ylo=0,yhi=ystep,ly=0;ly<hgrid;ylo=yhi,yhi+=ystep,ly++) {
00064 for(xlo=0,xhi=xstep,lx=0;lx<hgrid;xlo=xhi,xhi+=xstep,l++,lx++) {
00065 minr=large_number;
00066 for(q=e[0]+1;q<seq_length;q++) {
00067 f=e[q];
00068 i=(f&127)-64;
00069 j=(f>>7&127)-64;
00070 k=(f>>14&127)-64;qq=f>>21;
00071 if((f&b2)==b2) {
00072 compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i-1,j,k);
00073 if((f&b1)==0) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i+1,j,k);
00074 } else if((f&b1)==b1) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i+1,j,k);
00075 if((f&b4)==b4) {
00076 compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j-1,k);
00077 if((f&b3)==0) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j+1,k);
00078 } else if((f&b3)==b3) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j+1,k);
00079 if((f&b6)==b6) {
00080 compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j,k-1);
00081 if((f&b5)==0) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j,k+1);
00082 } else if((f&b5)==b5) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j,k+1);
00083 }
00084 q--;
00085 while(q>0) {
00086 radp[q]=minr;
00087 f=e[q];
00088 i=(f&127)-64;
00089 j=(f>>7&127)-64;
00090 k=(f>>14&127)-64;
00091 compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j,k);
00092 q--;
00093 }
00094 radp[0]=minr;
00095 e+=seq_length;
00096 radp+=seq_length;
00097 }
00098 }
00099 }
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 template<class r_option>
00113 inline void container_base<r_option>::compute_minimum(fpoint &minr,fpoint &xlo,fpoint &xhi,fpoint &ylo,fpoint &yhi,fpoint &zlo,fpoint &zhi,int ti,int tj,int tk) {
00114 const fpoint boxx=(bx-ax)/nx,boxy=(by-ay)/ny,boxz=(bz-az)/nz;
00115 fpoint radsq,temp;
00116 if(ti>0) {temp=boxx*ti-xhi;radsq=temp*temp;}
00117 else if(ti<0) {temp=xlo-boxx*(1+ti);radsq=temp*temp;}
00118 else radsq=0;
00119
00120 if(tj>0) {temp=boxy*tj-yhi;radsq+=temp*temp;}
00121 else if(tj<0) {temp=ylo-boxy*(1+tj);radsq+=temp*temp;}
00122
00123 if(tk>0) {temp=boxz*tk-zhi;radsq+=temp*temp;}
00124 else if(tk<0) {temp=zlo-boxz*(1+tk);radsq+=temp*temp;}
00125
00126 if(radsq<minr) minr=radsq;
00127 }
00128
00129
00130 template<class r_option>
00131 container_base<r_option>::~container_base() {
00132 int l;
00133 for(l=0;l<nxyz;l++) delete [] p[l];
00134 for(l=0;l<nxyz;l++) delete [] id[l];
00135 delete [] p;
00136 delete [] id;
00137 delete [] mem;
00138 delete [] co;
00139 delete [] mask;
00140 delete [] sl;
00141 delete [] walls;
00142 delete [] mrad;
00143 }
00144
00145
00146 template<class r_option>
00147 void container_base<r_option>::draw_particles(ostream &os) {
00148 int c,l,i;
00149 for(l=0;l<nxyz;l++) {
00150 for(c=0;c<co[l];c++) {
00151 os << id[l][c];
00152 for(i=sz*c;i<sz*(c+1);i++) os << " " << p[l][i];
00153 os << "\n";
00154 }
00155 }
00156 }
00157
00158
00159
00160 template<class r_option>
00161 void container_base<r_option>::draw_particles() {
00162 draw_particles(cin);
00163 }
00164
00165
00166
00167
00168 template<class r_option>
00169 void container_base<r_option>::draw_particles(const char *filename) {
00170 ofstream os;
00171 os.open(filename,ofstream::out|ofstream::trunc);
00172 draw_particles(os);
00173 os.close();
00174 }
00175
00176
00177 template<class r_option>
00178 void container_base<r_option>::draw_particles_pov(ostream &os) {
00179 int l,c;
00180 for(l=0;l<nxyz;l++) {
00181 for(c=0;c<co[l];c++) {
00182 os << "// id " << id[l][c] << "\n";
00183 os << "sphere{<" << p[l][sz*c] << "," << p[l][sz*c+1] << ","
00184 << p[l][sz*c+2] << ">,";
00185 radius.rad(os,l,c);
00186 os << "}\n";
00187 }
00188 }
00189 }
00190
00191
00192
00193 template<class r_option>
00194 void container_base<r_option>::draw_particles_pov() {
00195 draw_particles_pov(cin);
00196 }
00197
00198
00199
00200
00201 template<class r_option>
00202 void container_base<r_option>::draw_particles_pov(const char *filename) {
00203 ofstream os;
00204 os.open(filename,ofstream::out|ofstream::trunc);
00205 draw_particles_pov(os);
00206 os.close();
00207 }
00208
00209
00210 template<class r_option>
00211 void container_base<r_option>::put(int n,fpoint x,fpoint y,fpoint z) {
00212 if(x>ax&&y>ay&&z>az) {
00213 int i,j,k;
00214 i=int((x-ax)*xsp);j=int((y-ay)*ysp);k=int((z-az)*zsp);
00215 if(i<nx&&j<ny&&k<nz) {
00216 i+=nx*j+nxy*k;
00217 if(co[i]==mem[i]) add_particle_memory(i);
00218 p[i][sz*co[i]]=x;p[i][sz*co[i]+1]=y;p[i][sz*co[i]+2]=z;
00219 radius.store_radius(i,co[i],0.5);
00220 id[i][co[i]++]=n;
00221 }
00222 }
00223 }
00224
00225
00226
00227
00228
00229 template<class r_option>
00230 void container_base<r_option>::put(int n,fpoint x,fpoint y,fpoint z,fpoint r) {
00231 if(x>ax&&y>ay&&z>az) {
00232 int i,j,k;
00233 i=int((x-ax)*xsp);j=int((y-ay)*ysp);k=int((z-az)*zsp);
00234 if(i<nx&&j<ny&&k<nz) {
00235 i+=nx*j+nxy*k;
00236 if(co[i]==mem[i]) add_particle_memory(i);
00237 p[i][sz*co[i]]=x;p[i][sz*co[i]+1]=y;p[i][sz*co[i]+2]=z;
00238 radius.store_radius(i,co[i],r);
00239 id[i][co[i]++]=n;
00240 }
00241 }
00242 }
00243
00244
00245 template<class r_option>
00246 void container_base<r_option>::add_particle_memory(int i) {
00247 int *idp;fpoint *pp;
00248 int l,nmem=2*mem[i];
00249 #if VOROPP_VERBOSE >=3
00250 cerr << "Particle memory in region " << i << " scaled up to " << nmem << endl;
00251 #endif
00252 if(nmem>max_particle_memory) throw fatal_error("Absolute maximum memory allocation exceeded");
00253 idp=new int[nmem];
00254 for(l=0;l<co[i];l++) idp[l]=id[i][l];
00255 pp=new fpoint[sz*nmem];
00256 for(l=0;l<sz*co[i];l++) pp[l]=p[i][l];
00257 mem[i]=nmem;
00258 delete [] id[i];id[i]=idp;
00259 delete [] p[i];p[i]=pp;
00260 }
00261
00262
00263 template<class r_option>
00264 inline void container_base<r_option>::add_list_memory() {
00265 int i,j=0,*ps;
00266 ps=new int[s_size*2];
00267 #if VOROPP_VERBOSE >=2
00268 cerr << "List memory scaled up to " << s_size*2 << endl;
00269 #endif
00270 if(s_start<=s_end) {
00271 for(i=s_start;i<s_end;i++) ps[j++]=sl[i];
00272 } else {
00273 for(i=s_start;i<s_size;i++) ps[j++]=sl[i];
00274 for(i=0;i<s_end;i++) ps[j++]=sl[i];
00275 }
00276 s_size*=2;
00277 s_start=0;s_end=j;
00278 delete [] sl;sl=ps;
00279 }
00280
00281
00282 template<class r_option>
00283 void container_base<r_option>::import(istream &is) {
00284 radius.import(is);
00285 }
00286
00287
00288
00289 template<class r_option>
00290 inline void container_base<r_option>::import() {
00291 import(cin);
00292 }
00293
00294
00295
00296
00297 template<class r_option>
00298 inline void container_base<r_option>::import(const char *filename) {
00299 ifstream is;
00300 is.open(filename,ifstream::in);
00301 import(is);
00302 is.close();
00303 }
00304
00305
00306 template<class r_option>
00307 void container_base<r_option>::region_count() {
00308 int i,j,k,ijk=0;
00309 for(k=0;k<nz;k++) {
00310 for(j=0;j<ny;j++) {
00311 for(i=0;i<nx;i++) cout << "Region (" << i << "," << j << "," << k << "): " << co[ijk++] << " particles" << endl;
00312 }
00313 }
00314 }
00315
00316
00317 template<class r_option>
00318 void container_base<r_option>::clear() {
00319 for(int ijk=0;ijk<nxyz;ijk++) co[ijk]=0;
00320 radius.clear_max();
00321 }
00322
00323
00324
00325
00326 template<class r_option>
00327 void container_base<r_option>::draw_cells_gnuplot(const char *filename,fpoint xmin,fpoint xmax,fpoint ymin,fpoint ymax,fpoint zmin,fpoint zmax) {
00328 fpoint x,y,z,px,py,pz;
00329 voropp_loop l1(this);
00330 int q,s;
00331 voronoicell c;
00332 ofstream os;
00333 os.open(filename,ofstream::out|ofstream::trunc);
00334 s=l1.init(xmin,xmax,ymin,ymax,zmin,zmax,px,py,pz);
00335 do {
00336 for(q=0;q<co[s];q++) {
00337 x=p[s][sz*q]+px;y=p[s][sz*q+1]+py;z=p[s][sz*q+2]+pz;
00338 if(x>xmin&&x<xmax&&y>ymin&&y<ymax&&z>zmin&&z<zmax) {
00339 if (compute_cell(c,l1.ip,l1.jp,l1.kp,s,q,x,y,z)) c.draw_gnuplot(os,x,y,z);
00340 }
00341 }
00342 } while((s=l1.inc(px,py,pz))!=-1);
00343 os.close();
00344 }
00345
00346
00347
00348 template<class r_option>
00349 void container_base<r_option>::draw_cells_gnuplot(const char *filename) {
00350 draw_cells_gnuplot(filename,ax,bx,ay,by,az,bz);
00351 }
00352
00353
00354
00355
00356 template<class r_option>
00357 void container_base<r_option>::draw_cells_pov(const char *filename,fpoint xmin,fpoint xmax,fpoint ymin,fpoint ymax,fpoint zmin,fpoint zmax) {
00358 fpoint x,y,z,px,py,pz;
00359 voropp_loop l1(this);
00360 int q,s;
00361 voronoicell c;
00362 ofstream os;
00363 os.open(filename,ofstream::out|ofstream::trunc);
00364 s=l1.init(xmin,xmax,ymin,ymax,zmin,zmax,px,py,pz);
00365 do {
00366 for(q=0;q<co[s];q++) {
00367 os << "// cell " << id[s][q] << "\n";
00368 x=p[s][sz*q]+px;y=p[s][sz*q+1]+py;z=p[s][sz*q+2]+pz;
00369 if(x>xmin&&x<xmax&&y>ymin&&y<ymax&&z>zmin&&z<zmax) {
00370 if (compute_cell(c,l1.ip,l1.jp,l1.kp,s,q,x,y,z)) c.draw_pov(os,x,y,z);
00371 }
00372 }
00373 } while((s=l1.inc(px,py,pz))!=-1);
00374 os.close();
00375 }
00376
00377
00378
00379 template<class r_option>
00380 void container_base<r_option>::draw_cells_pov(const char *filename) {
00381 draw_cells_pov(filename,ax,bx,ay,by,az,bz);
00382 }
00383
00384
00385
00386
00387
00388 template<class r_option>
00389 void container_base<r_option>::compute_all_cells() {
00390 voronoicell c;
00391 int i,j,k,ijk=0,q;
00392 for(k=0;k<nz;k++) for(j=0;j<ny;j++) for(i=0;i<nx;i++,ijk++) {
00393 for(q=0;q<co[ijk];q++) compute_cell(c,i,j,k,ijk,q);
00394 }
00395 }
00396
00397
00398
00399
00400 template<class r_option>
00401 void container_base<r_option>::store_cell_volumes(fpoint *bb) {
00402 voronoicell c;
00403 int i,j,k,ijk=0,q;
00404 for(k=0;k<nz;k++) for(j=0;j<ny;j++) for(i=0;i<nx;i++,ijk++) {
00405 for(q=0;q<co[ijk];q++) {
00406 if (compute_cell(c,i,j,k,ijk,q)) {
00407 bb[id[ijk][q]]=c.volume();
00408 } else {
00409 bb[id[ijk][q]]=0;
00410 }
00411 }
00412 }
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422 template<class r_option>
00423 fpoint container_base<r_option>::packing_fraction(fpoint *bb,fpoint cx,fpoint cy,fpoint cz,fpoint r) {
00424 voropp_loop l1(this);
00425 fpoint px,py,pz,x,y,z,rsq=r*r,pvol=0,vvol=0;
00426 int q,s;
00427 s=l1.init(cx,cy,cz,r,px,py,pz);
00428 do {
00429 for(q=0;q<co[s];q++) {
00430 x=p[s][sz*q]+px-cx;
00431 y=p[s][sz*q+1]+py-cy;
00432 z=p[s][sz*q+2]+pz-cz;
00433 if (x*x+y*y+z*z<rsq) {
00434 pvol+=radius.volume(s,q);
00435 vvol+=bb[id[s][q]];
00436 }
00437 }
00438 } while((s=l1.inc(px,py,pz))!=-1);
00439 return vvol>tolerance?pvol/vvol*4.1887902047863909846168578443726:0;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449 template<class r_option>
00450 fpoint container_base<r_option>::packing_fraction(fpoint *bb,fpoint xmin,fpoint xmax,fpoint ymin,fpoint ymax,fpoint zmin,fpoint zmax) {
00451 voropp_loop l1(this);
00452 fpoint x,y,z,px,py,pz,pvol=0,vvol=0;
00453 int q,s;
00454 s=l1.init(xmin,xmax,ymin,ymax,zmin,zmax,px,py,pz);
00455 do {
00456 for(q=0;q<co[s];q++) {
00457 x=p[s][sz*q]+px;
00458 y=p[s][sz*q+1]+py;
00459 z=p[s][sz*q+2]+pz;
00460 if(x>xmin&&x<xmax&&y>ymin&&y<ymax&&z>zmin&&z<zmax) {
00461 pvol+=radius.volume(s,q);
00462 vvol+=bb[id[s][q]];
00463 }
00464 }
00465 } while((s=l1.inc(px,py,pz))!=-1);
00466 return vvol>tolerance?pvol/vvol*4.1887902047863909846168578443726:0;
00467 }
00468
00469
00470
00471 template<class r_option>
00472 fpoint container_base<r_option>::sum_cell_volumes() {
00473 voronoicell c;
00474 int i,j,k,ijk=0,q;fpoint vol=0;
00475 for(k=0;k<nz;k++) for(j=0;j<ny;j++) for(i=0;i<nx;i++,ijk++) {
00476 for(q=0;q<co[ijk];q++) if (compute_cell(c,i,j,k,ijk,q)) vol+=c.volume();
00477 }
00478 return vol;
00479 }
00480
00481
00482
00483 template<class r_option>
00484 inline void container_base<r_option>::count_all_faces(ostream &os) {
00485 voronoicell c;
00486 fpoint x,y,z;
00487 int i,j,k,ijk=0,q;
00488 for(k=0;k<nz;k++) for(j=0;j<ny;j++) for(i=0;i<nx;i++,ijk++) {
00489 for(q=0;q<co[ijk];q++) {
00490 x=p[ijk][sz*q];y=p[ijk][sz*q+1];z=p[ijk][sz*q+2];
00491 os << id[ijk][q] << " " << x << " " << y << " " << z;
00492 radius.print(os,ijk,q);
00493 if (compute_cell(c,i,j,k,ijk,q,x,y,z)) {
00494 os << " " << c.number_of_faces() << "\n";
00495 } else os << " 0\n";
00496 }
00497 }
00498 }
00499
00500
00501
00502 template<class r_option>
00503 void container_base<r_option>::count_all_faces() {
00504 count_all_faces(cout);
00505 }
00506
00507
00508
00509
00510 template<class r_option>
00511 void container_base<r_option>::count_all_faces(const char* filename) {
00512 ofstream os;
00513 os.open(filename,ofstream::out|ofstream::trunc);
00514 count_all_faces(os);
00515 os.close();
00516 }
00517
00518
00519
00520 template<class r_option>
00521 template<class n_option>
00522 inline void container_base<r_option>::print_all(ostream &os,voronoicell_base<n_option> &c) {
00523 fpoint x,y,z;
00524 int i,j,k,ijk=0,q;
00525 for(k=0;k<nz;k++) for(j=0;j<ny;j++) for(i=0;i<nx;i++,ijk++) {
00526 for(q=0;q<co[ijk];q++) {
00527 x=p[ijk][sz*q];y=p[ijk][sz*q+1];z=p[ijk][sz*q+2];
00528 os << id[ijk][q] << " " << x << " " << y << " " << z;
00529 radius.print(os,ijk,q);
00530 if (compute_cell(c,i,j,k,ijk,q,x,y,z)) {
00531 os << " " << c.volume();
00532 c.neighbors(os);
00533 os << "\n";
00534 } else os << " 0\n";
00535 }
00536 }
00537 }
00538
00539
00540
00541 template<class r_option>
00542 void container_base<r_option>::print_all(ostream &os) {
00543 voronoicell c;
00544 print_all(os,c);
00545 }
00546
00547
00548 template<class r_option>
00549 void container_base<r_option>::print_all() {
00550 voronoicell c;
00551 print_all(cout,c);
00552 }
00553
00554
00555
00556
00557 template<class r_option>
00558 inline void container_base<r_option>::print_all(const char* filename) {
00559 voronoicell c;
00560 ofstream os;
00561 os.open(filename,ofstream::out|ofstream::trunc);
00562 print_all(os,c);
00563 os.close();
00564 }
00565
00566
00567
00568
00569 template<class r_option>
00570 void container_base<r_option>::print_all_neighbor(ostream &os) {
00571 voronoicell_neighbor c;
00572 print_all(os,c);
00573 }
00574
00575
00576
00577 template<class r_option>
00578 void container_base<r_option>::print_all_neighbor() {
00579 voronoicell_neighbor c;
00580 print_all(cout,c);
00581 }
00582
00583
00584
00585
00586 template<class r_option>
00587 inline void container_base<r_option>::print_all_neighbor(const char* filename) {
00588 voronoicell_neighbor c;
00589 ofstream os;
00590 os.open(filename,ofstream::out|ofstream::trunc);
00591 print_all(os,c);
00592 os.close();
00593 }
00594
00595
00596
00597
00598
00599
00600 template<class r_option>
00601 template<class n_option>
00602 inline bool container_base<r_option>::initialize_voronoicell(voronoicell_base<n_option> &c,fpoint x,fpoint y,fpoint z) {
00603 fpoint x1,x2,y1,y2,z1,z2;
00604 if(xperiodic) x1=-(x2=0.5*(bx-ax));else {x1=ax-x;x2=bx-x;}
00605 if(yperiodic) y1=-(y2=0.5*(by-ay));else {y1=ay-y;y2=by-y;}
00606 if(zperiodic) z1=-(z2=0.5*(bz-az));else {z1=az-z;z2=bz-z;}
00607 c.init(x1,x2,y1,y2,z1,z2);
00608 for(int j=0;j<wall_number;j++) {
00609 if (!(walls[j]->cut_cell(c,x,y,z))) return false;
00610 }
00611 return true;
00612 }
00613
00614
00615
00616
00617
00618
00619 template<class r_option>
00620 bool container_base<r_option>::point_inside(fpoint x,fpoint y,fpoint z) {
00621 if(x<ax||x>bx||y<ay||y>by||z<az||z>bz) return false;
00622 return point_inside_walls(x,y,z);
00623 }
00624
00625
00626
00627
00628
00629
00630
00631 template<class r_option>
00632 bool container_base<r_option>::point_inside_walls(fpoint x,fpoint y,fpoint z) {
00633 for(int j=0;j<wall_number;j++) if(!walls[j]->point_inside(x,y,z)) return false;
00634 return true;
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 template<class r_option>
00652 template<class n_option>
00653 bool container_base<r_option>::compute_cell_sphere(voronoicell_base<n_option> &c,int i,int j,int k,int ijk,int s,fpoint x,fpoint y,fpoint z) {
00654
00655
00656
00657 const fpoint length_scale=1;
00658 fpoint x1,y1,z1,qx,qy,qz,lr=0,lrs=0,ur,urs,rs;
00659 int q,t;
00660 voropp_loop l(this);
00661 if (!initialize_voronoicell(c,x,y,z)) return false;
00662
00663
00664
00665
00666 radius.init(ijk,s);
00667 while(radius.cutoff(lrs)<c.maxradsq()) {
00668 ur=lr+0.5*length_scale;urs=ur*ur;
00669 t=l.init(x,y,z,ur,qx,qy,qz);
00670 do {
00671 for(q=0;q<co[t];q++) {
00672 x1=p[t][sz*q]+qx-x;y1=p[t][sz*q+1]+qy-y;z1=p[t][sz*q+2]+qz-z;
00673 rs=x1*x1+y1*y1+z1*z1;
00674 if(lrs-tolerance<rs&&rs<urs&&(q!=s||ijk!=t)) {
00675 if (!c.nplane(x1,y1,z1,radius.scale(rs,t,q),id[t][q])) return false;
00676 }
00677 }
00678 } while((t=l.inc(qx,qy,qz))!=-1);
00679 lr=ur;lrs=urs;
00680 }
00681 return true;
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 template<class r_option>
00693 template<class n_option>
00694 inline bool container_base<r_option>::compute_cell_sphere(voronoicell_base<n_option> &c,int i,int j,int k,int ijk,int s) {
00695 fpoint x=p[ijk][sz*s],y=p[ijk][sz*s+1],z=p[ijk][sz*s+2];
00696 return compute_cell_sphere(c,i,j,k,ijk,s,x,y,z);
00697 }
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 template<class r_option>
00709 template<class n_option>
00710 inline bool container_base<r_option>::compute_cell(voronoicell_base<n_option> &c,int i,int j,int k,int ijk,int s) {
00711 fpoint x=p[ijk][sz*s],y=p[ijk][sz*s+1],z=p[ijk][sz*s+2];
00712 return compute_cell(c,i,j,k,ijk,s,x,y,z);
00713 }
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739 template<class r_option>
00740 template<class n_option>
00741 bool container_base<r_option>::compute_cell(voronoicell_base<n_option> &c,int i,int j,int k,int ijk,int s,fpoint x,fpoint y,fpoint z) {
00742 const fpoint boxx=(bx-ax)/nx,boxy=(by-ay)/ny,boxz=(bz-az)/nz;
00743 fpoint x1,y1,z1,qx=0,qy=0,qz=0;
00744 fpoint xlo,ylo,zlo,xhi,yhi,zhi,rs;
00745 int ci,cj,ck,di,dj,dk,dijk,ei,ej,ek,eijk,si,sj,sk,sijk;
00746 fpoint gxs,gys,gzs,*radp;
00747 int f,g,l;unsigned int q,*e;
00748 const unsigned int b1=1<<21,b2=1<<22,b3=1<<24,b4=1<<25,b5=1<<27,b6=1<<28;
00749
00750 radius.init(ijk,s);
00751
00752
00753 if (!initialize_voronoicell(c,x,y,z)) return false;
00754 fpoint crs,mrs;
00755
00756 int next_count=3,list_index=0,list_size=8;
00757 int count_list[]={7,11,15,19,26,35,45,59};
00758
00759
00760 for(l=0;l<s;l++) {
00761 x1=p[ijk][sz*l]-x;
00762 y1=p[ijk][sz*l+1]-y;
00763 z1=p[ijk][sz*l+2]-z;
00764 rs=radius.scale(x1*x1+y1*y1+z1*z1,ijk,l);
00765 if (!c.nplane(x1,y1,z1,rs,id[ijk][l])) return false;
00766 }
00767 l++;
00768 while(l<co[ijk]) {
00769 x1=p[ijk][sz*l]-x;
00770 y1=p[ijk][sz*l+1]-y;
00771 z1=p[ijk][sz*l+2]-z;
00772 rs=radius.scale(x1*x1+y1*y1+z1*z1,ijk,l);
00773 if (!c.nplane(x1,y1,z1,rs,id[ijk][l])) return false;
00774 l++;
00775 }
00776
00777
00778
00779
00780 mrs=c.maxradsq();
00781
00782
00783
00784
00785
00786 unsigned int m1,m2;
00787 fpoint fx=x-ax-boxx*i,fy=y-ay-boxy*j,fz=z-az-boxz*k;
00788 si=int(fx*xsp*fgrid);sj=int(fy*ysp*fgrid);sk=int(fz*zsp*fgrid);
00789
00790
00791
00792
00793
00794
00795
00796
00797 if(si>=hgrid) {
00798 gxs=fx;
00799 m1=127+(3<<21);si=fgrid-1-si;m2=1+(1<<21);
00800 } else {m1=m2=0;gxs=boxx-fx;}
00801 if(sj>=hgrid) {
00802 gys=fy;
00803 m1|=(127<<7)+(3<<24);sj=fgrid-1-sj;m2|=(1<<7)+(1<<24);
00804 } else gys=boxy-fy;
00805 if(sk>=hgrid) {
00806 gzs=fz;
00807 m1|=(127<<14)+(3<<27);sk=fgrid-1-sk;m2|=(1<<14)+(1<<27);
00808 } else gzs=boxz-fz;
00809 gxs*=gxs;gys*=gys;gzs*=gzs;
00810
00811
00812
00813
00814 if(si<0) si=0;if(sj<0) sj=0;if(sk<0) sk=0;
00815
00816
00817
00818 sijk=si+hgrid*(sj+hgrid*sk);
00819 radp=mrad+sijk*seq_length;
00820 e=(const_cast<unsigned int*> (wl))+sijk*seq_length;
00821
00822
00823
00824 f=e[0];g=0;
00825 do {
00826
00827
00828
00829 if(g==next_count) {
00830 mrs=c.maxradsq();
00831 if(list_index!=list_size) next_count=count_list[list_index++];
00832 }
00833
00834
00835
00836 if(mrs<radius.cutoff(radp[g])) return true;
00837 g++;
00838
00839
00840
00841
00842 q=e[g];q^=m1;q+=m2;
00843 di=q&127;di-=64;
00844 dj=(q>>7)&127;dj-=64;
00845 dk=(q>>14)&127;dk-=64;
00846
00847
00848 if(xperiodic) {if(di<-nx) continue;else if(di>nx) continue;}
00849 else {if(di<-i) continue;else if(di>=nx-i) continue;}
00850 if(yperiodic) {if(dj<-ny) continue;else if(dj>ny) continue;}
00851 else {if(dj<-j) continue;else if(dj>=ny-j) continue;}
00852 if(zperiodic) {if(dk<-nz) continue;else if(dk>nz) continue;}
00853 else {if(dk<-k) continue;else if(dk>=nz-k) continue;}
00854
00855
00856
00857
00858
00859
00860 if(compute_min_max_radius(di,dj,dk,fx,fy,fz,gxs,gys,gzs,crs,mrs)) continue;
00861
00862
00863
00864 di+=i;dj+=j;dk+=k;
00865 if(xperiodic) {if(di<0) {qx=ax-bx;di+=nx;} else if(di>=nx) {qx=bx-ax;di-=nx;} else qx=0;}
00866 if(yperiodic) {if(dj<0) {qy=ay-by;dj+=ny;} else if(dj>=ny) {qy=by-ay;dj-=ny;} else qy=0;}
00867 if(zperiodic) {if(dk<0) {qz=az-bz;dk+=nz;} else if(dk>=nz) {qz=bz-az;dk-=nz;} else qz=0;}
00868 dijk=di+nx*(dj+ny*dk);
00869
00870
00871
00872
00873
00874 if(mrs>radius.cutoff(crs)) {
00875 for(l=0;l<co[dijk];l++) {
00876 x1=p[dijk][sz*l]+qx-x;
00877 y1=p[dijk][sz*l+1]+qy-y;
00878 z1=p[dijk][sz*l+2]+qz-z;
00879 rs=radius.scale(x1*x1+y1*y1+z1*z1,dijk,l);
00880 if (!c.nplane(x1,y1,z1,rs,id[dijk][l])) return false;
00881 }
00882 } else {
00883 for(l=0;l<co[dijk];l++) {
00884 x1=p[dijk][sz*l]+qx-x;
00885 y1=p[dijk][sz*l+1]+qy-y;
00886 z1=p[dijk][sz*l+2]+qz-z;
00887 rs=radius.scale(x1*x1+y1*y1+z1*z1,dijk,l);
00888 if(rs<mrs) {
00889 if (!c.nplane(x1,y1,z1,rs,id[dijk][l])) return false;
00890 }
00891 }
00892 }
00893 } while(g<f);
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903 ci=xperiodic?nx:i;
00904 cj=yperiodic?ny:j;
00905 ck=zperiodic?nz:k;
00906
00907
00908
00909 mv++;
00910 if(mv==0) {
00911 for(l=0;l<hxyz;l++) mask[l]=0;
00912 mv=1;
00913 }
00914
00915
00916 s_start=s_end=0;
00917
00918 while(g<seq_length-1) {
00919
00920
00921
00922 if(g==next_count) {
00923 mrs=c.maxradsq();
00924 if(list_index!=list_size) next_count=count_list[list_index++];
00925 }
00926
00927
00928
00929 if(mrs<radius.cutoff(radp[g])) return true;
00930 g++;
00931
00932
00933
00934
00935 q=e[g];q^=m1;q+=m2;
00936 di=q&127;di-=64;
00937 dj=(q>>7)&127;dj-=64;
00938 dk=(q>>14)&127;dk-=64;
00939
00940
00941
00942
00943 ei=ci+di;
00944 ej=cj+dj;
00945 ek=ck+dk;
00946 if(ei<0) continue;else if(ei>=hx) continue;
00947 if(ej<0) continue;else if(ej>=hy) continue;
00948 if(ek<0) continue;else if(ek>=hz) continue;
00949 eijk=ei+hx*(ej+hy*ek);
00950 mask[eijk]=mv;
00951
00952
00953
00954
00955
00956
00957 if(compute_min_max_radius(di,dj,dk,fx,fy,fz,gxs,gys,gzs,crs,mrs)) continue;
00958
00959
00960
00961 di+=i;dj+=j;dk+=k;
00962 if(xperiodic) {if(di<0) {qx=ax-bx;di+=nx;} else if(di>=nx) {qx=bx-ax;di-=nx;} else qx=0;}
00963 if(yperiodic) {if(dj<0) {qy=ay-by;dj+=ny;} else if(dj>=ny) {qy=by-ay;dj-=ny;} else qy=0;}
00964 if(zperiodic) {if(dk<0) {qz=az-bz;dk+=nz;} else if(dk>=nz) {qz=bz-az;dk-=nz;} else qz=0;}
00965 dijk=di+nx*(dj+ny*dk);
00966
00967
00968
00969
00970
00971 if(mrs>radius.cutoff(crs)) {
00972 for(l=0;l<co[dijk];l++) {
00973 x1=p[dijk][sz*l]+qx-x;
00974 y1=p[dijk][sz*l+1]+qy-y;
00975 z1=p[dijk][sz*l+2]+qz-z;
00976 rs=radius.scale(x1*x1+y1*y1+z1*z1,dijk,l);
00977 if (!c.nplane(x1,y1,z1,rs,id[dijk][l])) return false;
00978 }
00979 } else {
00980 for(l=0;l<co[dijk];l++) {
00981 x1=p[dijk][sz*l]+qx-x;
00982 y1=p[dijk][sz*l+1]+qy-y;
00983 z1=p[dijk][sz*l+2]+qz-z;
00984 rs=radius.scale(x1*x1+y1*y1+z1*z1,dijk,l);
00985 if(rs<mrs) {
00986 if(!c.nplane(x1,y1,z1,rs,id[dijk][l])) return false;
00987 }
00988 }
00989 }
00990
00991
00992
00993 if(s_end+18>s_size) add_list_memory();
00994
00995
00996
00997
00998 if((q&b2)==b2) {
00999 if(ei>0) if(mask[eijk-1]!=mv) {mask[eijk-1]=mv;sl[s_end++]=ei-1;sl[s_end++]=ej;sl[s_end++]=ek;}
01000 if((q&b1)==0) if(ei<hx-1) if(mask[eijk+1]!=mv) {mask[eijk+1]=mv;sl[s_end++]=ei+1;sl[s_end++]=ej;sl[s_end++]=ek;}
01001 } else if((q&b1)==b1) {if(ei<hx-1) if(mask[eijk+1]!=mv) {mask[eijk+1]=mv;sl[s_end++]=ei+1;sl[s_end++]=ej;sl[s_end++]=ek;}}
01002 if((q&b4)==b4) {if(ej>0) if(mask[eijk-hx]!=mv) {mask[eijk-hx]=mv;sl[s_end++]=ei;sl[s_end++]=ej-1;sl[s_end++]=ek;}
01003 if((q&b3)==0) if(ej<hy-1) if(mask[eijk+hx]!=mv) {mask[eijk+hx]=mv;sl[s_end++]=ei;sl[s_end++]=ej+1;sl[s_end++]=ek;}
01004 } else if((q&b3)==b3) {if(ej<hy-1) if(mask[eijk+hx]!=mv) {mask[eijk+hx]=mv;sl[s_end++]=ei;sl[s_end++]=ej+1;sl[s_end++]=ek;}}
01005 if((q&b6)==b6) {if(ek>0) if(mask[eijk-hxy]!=mv) {mask[eijk-hxy]=mv;sl[s_end++]=ei;sl[s_end++]=ej;sl[s_end++]=ek-1;}
01006 if((q&b5)==0) if(ek<hz-1) if(mask[eijk+hxy]!=mv) {mask[eijk+hxy]=mv;sl[s_end++]=ei;sl[s_end++]=ej;sl[s_end++]=ek+1;}
01007 } else if((q&b5)==b5) if(ek<hz-1) if(mask[eijk+hxy]!=mv) {mask[eijk+hxy]=mv;sl[s_end++]=ei;sl[s_end++]=ej;sl[s_end++]=ek+1;}
01008 }
01009
01010
01011 if(mrs<radius.cutoff(radp[g])) return true;
01012
01013
01014
01015 fx+=boxx*ci;fy+=boxy*cj;fz+=boxz*ck;
01016
01017
01018
01019
01020 while(s_start!=s_end) {
01021
01022
01023 if(s_start==s_size) s_start=0;
01024
01025
01026
01027 di=sl[s_start++];dj=sl[s_start++];dk=sl[s_start++];
01028 xlo=di*boxx-fx;xhi=xlo+boxx;
01029 ylo=dj*boxy-fy;yhi=ylo+boxy;
01030 zlo=dk*boxz-fz;zhi=zlo+boxz;
01031
01032
01033
01034 if(di>ci) {
01035 if(dj>cj) {
01036 if(dk>ck) {
01037 if(corner_test(c,xlo,ylo,zlo,xhi,yhi,zhi)) continue;
01038 } else if(dk<ck) {
01039 if(corner_test(c,xlo,ylo,zhi,xhi,yhi,zlo)) continue;
01040 } else {
01041 if(edge_z_test(c,xlo,ylo,zlo,xhi,yhi,zhi)) continue;
01042 }
01043 } else if(dj<cj) {
01044 if(dk>ck) {
01045 if(corner_test(c,xlo,yhi,zlo,xhi,ylo,zhi)) continue;
01046 } else if(dk<ck) {
01047 if(corner_test(c,xlo,yhi,zhi,xhi,ylo,zlo)) continue;
01048 } else {
01049 if(edge_z_test(c,xlo,yhi,zlo,xhi,ylo,zhi)) continue;
01050 }
01051 } else {
01052 if(dk>ck) {
01053 if(edge_y_test(c,xlo,ylo,zlo,xhi,yhi,zhi)) continue;
01054 } else if(dk<ck) {
01055 if(edge_y_test(c,xlo,ylo,zhi,xhi,yhi,zlo)) continue;
01056 } else {
01057 if(face_x_test(c,xlo,ylo,zlo,yhi,zhi)) continue;
01058 }
01059 }
01060 } else if(di<ci) {
01061 if(dj>cj) {
01062 if(dk>ck) {
01063 if(corner_test(c,xhi,ylo,zlo,xlo,yhi,zhi)) continue;
01064 } else if(dk<ck) {
01065 if(corner_test(c,xhi,ylo,zhi,xlo,yhi,zlo)) continue;
01066 } else {
01067 if(edge_z_test(c,xhi,ylo,zlo,xlo,yhi,zhi)) continue;
01068 }
01069 } else if(dj<cj) {
01070 if(dk>ck) {
01071 if(corner_test(c,xhi,yhi,zlo,xlo,ylo,zhi)) continue;
01072 } else if(dk<ck) {
01073 if(corner_test(c,xhi,yhi,zhi,xlo,ylo,zlo)) continue;
01074 } else {
01075 if(edge_z_test(c,xhi,yhi,zlo,xlo,ylo,zhi)) continue;
01076 }
01077 } else {
01078 if(dk>ck) {
01079 if(edge_y_test(c,xhi,ylo,zlo,xlo,yhi,zhi)) continue;
01080 } else if(dk<ck) {
01081 if(edge_y_test(c,xhi,ylo,zhi,xlo,yhi,zlo)) continue;
01082 } else {
01083 if(face_x_test(c,xhi,ylo,zlo,yhi,zhi)) continue;
01084 }
01085 }
01086 } else {
01087 if(dj>cj) {
01088 if(dk>ck) {
01089 if(edge_x_test(c,xlo,ylo,zlo,xhi,yhi,zhi)) continue;
01090 } else if(dk<ck) {
01091 if(edge_x_test(c,xlo,ylo,zhi,xhi,yhi,zlo)) continue;
01092 } else {
01093 if(face_y_test(c,xlo,ylo,zlo,xhi,zhi)) continue;
01094 }
01095 } else if(dj<cj) {
01096 if(dk>ck) {
01097 if(edge_x_test(c,xlo,yhi,zlo,xhi,ylo,zhi)) continue;
01098 } else if(dk<ck) {
01099 if(edge_x_test(c,xlo,yhi,zhi,xhi,ylo,zlo)) continue;
01100 } else {
01101 if(face_y_test(c,xlo,yhi,zlo,xhi,zhi)) continue;
01102 }
01103 } else {
01104 if(dk>ck) {
01105 if(face_z_test(c,xlo,ylo,zlo,xhi,yhi)) continue;
01106 } else if(dk<ck) {
01107 if(face_z_test(c,xlo,ylo,zhi,xhi,yhi)) continue;
01108 } else {
01109 cout << "Can't happen ... happened\n";
01110 }
01111 }
01112 }
01113
01114
01115
01116 if(xperiodic) {ei=i+di-nx;if(ei<0) {qx=ax-bx;ei+=nx;} else if(ei>=nx) {qx=bx-ax;ei-=nx;} else qx=0;} else ei=di;
01117 if(yperiodic) {ej=j+dj-ny;if(ej<0) {qy=ay-by;ej+=ny;} else if(ej>=ny) {qy=by-ay;ej-=ny;} else qy=0;} else ej=dj;
01118 if(zperiodic) {ek=k+dk-nz;if(ek<0) {qz=az-bz;ek+=nz;} else if(ek>=nz) {qz=bz-az;ek-=nz;} else qz=0;} else ek=dk;
01119 eijk=ei+nx*(ej+ny*ek);
01120
01121
01122
01123
01124 for(l=0;l<co[eijk];l++) {
01125 x1=p[eijk][sz*l]+qx-x;
01126 y1=p[eijk][sz*l+1]+qy-y;
01127 z1=p[eijk][sz*l+2]+qz-z;
01128 rs=radius.scale(x1*x1+y1*y1+z1*z1,eijk,l);
01129 if (!c.nplane(x1,y1,z1,rs,id[eijk][l])) return false;
01130 }
01131
01132
01133 if((s_start<=s_end?s_size-s_end+s_start:s_end-s_start)<18) add_list_memory();
01134
01135
01136
01137 dijk=di+hx*(dj+hy*dk);
01138 if(di>0) if(mask[dijk-1]!=mv) {if(s_end==s_size) s_end=0;mask[dijk-1]=mv;sl[s_end++]=di-1;sl[s_end++]=dj;sl[s_end++]=dk;}
01139 if(dj>0) if(mask[dijk-hx]!=mv) {if(s_end==s_size) s_end=0;mask[dijk-hx]=mv;sl[s_end++]=di;sl[s_end++]=dj-1;sl[s_end++]=dk;}
01140 if(dk>0) if(mask[dijk-hxy]!=mv) {if(s_end==s_size) s_end=0;mask[dijk-hxy]=mv;sl[s_end++]=di;sl[s_end++]=dj;sl[s_end++]=dk-1;}
01141 if(di<hx-1) if(mask[dijk+1]!=mv) {if(s_end==s_size) s_end=0;mask[dijk+1]=mv;sl[s_end++]=di+1;sl[s_end++]=dj;sl[s_end++]=dk;}
01142 if(dj<hy-1) if(mask[dijk+hx]!=mv) {if(s_end==s_size) s_end=0;mask[dijk+hx]=mv;sl[s_end++]=di;sl[s_end++]=dj+1;sl[s_end++]=dk;}
01143 if(dk<hz-1) if(mask[dijk+hxy]!=mv) {if(s_end==s_size) s_end=0;mask[dijk+hxy]=mv;sl[s_end++]=di;sl[s_end++]=dj;sl[s_end++]=dk+1;}
01144 }
01145
01146 return true;
01147 }
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 template<class r_option>
01159 template<class n_option>
01160 inline bool container_base<r_option>::corner_test(voronoicell_base<n_option> &c,fpoint xl,fpoint yl,fpoint zl,fpoint xh,fpoint yh,fpoint zh) {
01161 if(c.plane_intersects_guess(xh,yl,zl,radius.cutoff(xl*xh+yl*yl+zl*zl))) return false;
01162 if(c.plane_intersects(xh,yh,zl,radius.cutoff(xl*xh+yl*yh+zl*zl))) return false;
01163 if(c.plane_intersects(xl,yh,zl,radius.cutoff(xl*xl+yl*yh+zl*zl))) return false;
01164 if(c.plane_intersects(xl,yh,zh,radius.cutoff(xl*xl+yl*yh+zl*zh))) return false;
01165 if(c.plane_intersects(xl,yl,zh,radius.cutoff(xl*xl+yl*yl+zl*zh))) return false;
01166 if(c.plane_intersects(xh,yl,zh,radius.cutoff(xl*xh+yl*yl+zl*zh))) return false;
01167 return true;
01168 }
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 template<class r_option>
01182 template<class n_option>
01183 inline bool container_base<r_option>::edge_x_test(voronoicell_base<n_option> &c,fpoint x0,fpoint yl,fpoint zl,fpoint x1,fpoint yh,fpoint zh) {
01184 if(c.plane_intersects_guess(x0,yl,zh,radius.cutoff(yl*yl+zl*zh))) return false;
01185 if(c.plane_intersects(x1,yl,zh,radius.cutoff(yl*yl+zl*zh))) return false;
01186 if(c.plane_intersects(x1,yl,zl,radius.cutoff(yl*yl+zl*zl))) return false;
01187 if(c.plane_intersects(x0,yl,zl,radius.cutoff(yl*yl+zl*zl))) return false;
01188 if(c.plane_intersects(x0,yh,zl,radius.cutoff(yl*yh+zl*zl))) return false;
01189 if(c.plane_intersects(x1,yh,zl,radius.cutoff(yl*yh+zl*zl))) return false;
01190 return true;
01191 }
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 template<class r_option>
01205 template<class n_option>
01206 inline bool container_base<r_option>::edge_y_test(voronoicell_base<n_option> &c,fpoint xl,fpoint y0,fpoint zl,fpoint xh,fpoint y1,fpoint zh) {
01207 if(c.plane_intersects_guess(xl,y0,zh,radius.cutoff(xl*xl+zl*zh))) return false;
01208 if(c.plane_intersects(xl,y1,zh,radius.cutoff(xl*xl+zl*zh))) return false;
01209 if(c.plane_intersects(xl,y1,zl,radius.cutoff(xl*xl+zl*zl))) return false;
01210 if(c.plane_intersects(xl,y0,zl,radius.cutoff(xl*xl+zl*zl))) return false;
01211 if(c.plane_intersects(xh,y0,zl,radius.cutoff(xl*xh+zl*zl))) return false;
01212 if(c.plane_intersects(xh,y1,zl,radius.cutoff(xl*xh+zl*zl))) return false;
01213 return true;
01214 }
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227 template<class r_option>
01228 template<class n_option>
01229 inline bool container_base<r_option>::edge_z_test(voronoicell_base<n_option> &c,fpoint xl,fpoint yl,fpoint z0,fpoint xh,fpoint yh,fpoint z1) {
01230 if(c.plane_intersects_guess(xl,yh,z0,radius.cutoff(xl*xl+yl*yh))) return false;
01231 if(c.plane_intersects(xl,yh,z1,radius.cutoff(xl*xl+yl*yh))) return false;
01232 if(c.plane_intersects(xl,yl,z1,radius.cutoff(xl*xl+yl*yl))) return false;
01233 if(c.plane_intersects(xl,yl,z0,radius.cutoff(xl*xl+yl*yl))) return false;
01234 if(c.plane_intersects(xh,yl,z0,radius.cutoff(xl*xh+yl*yl))) return false;
01235 if(c.plane_intersects(xh,yl,z1,radius.cutoff(xl*xh+yl*yl))) return false;
01236 return true;
01237 }
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247 template<class r_option>
01248 template<class n_option>
01249 inline bool container_base<r_option>::face_x_test(voronoicell_base<n_option> &c,fpoint xl,fpoint y0,fpoint z0,fpoint y1,fpoint z1) {
01250 if(c.plane_intersects_guess(xl,y0,z0,radius.cutoff(xl*xl))) return false;
01251 if(c.plane_intersects(xl,y0,z1,radius.cutoff(xl*xl))) return false;
01252 if(c.plane_intersects(xl,y1,z1,radius.cutoff(xl*xl))) return false;
01253 if(c.plane_intersects(xl,y1,z0,radius.cutoff(xl*xl))) return false;
01254 return true;
01255 }
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265 template<class r_option>
01266 template<class n_option>
01267 inline bool container_base<r_option>::face_y_test(voronoicell_base<n_option> &c,fpoint x0,fpoint yl,fpoint z0,fpoint x1,fpoint z1) {
01268 if(c.plane_intersects_guess(x0,yl,z0,radius.cutoff(yl*yl))) return false;
01269 if(c.plane_intersects(x0,yl,z1,radius.cutoff(yl*yl))) return false;
01270 if(c.plane_intersects(x1,yl,z1,radius.cutoff(yl*yl))) return false;
01271 if(c.plane_intersects(x1,yl,z0,radius.cutoff(yl*yl))) return false;
01272 return true;
01273 }
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283 template<class r_option>
01284 template<class n_option>
01285 inline bool container_base<r_option>::face_z_test(voronoicell_base<n_option> &c,fpoint x0,fpoint y0,fpoint zl,fpoint x1,fpoint y1) {
01286 if(c.plane_intersects_guess(x0,y0,zl,radius.cutoff(zl*zl))) return false;
01287 if(c.plane_intersects(x0,y1,zl,radius.cutoff(zl*zl))) return false;
01288 if(c.plane_intersects(x1,y1,zl,radius.cutoff(zl*zl))) return false;
01289 if(c.plane_intersects(x1,y0,zl,radius.cutoff(zl*zl))) return false;
01290 return true;
01291 }
01292
01293
01294
01295 template<class r_option>
01296 voropp_loop::voropp_loop(container_base<r_option> *q) : sx(q->bx-q->ax), sy(q->by-q->ay), sz(q->bz-q->az),
01297 xsp(q->xsp),ysp(q->ysp),zsp(q->zsp),
01298 ax(q->ax),ay(q->ay),az(q->az),
01299 nx(q->nx),ny(q->ny),nz(q->nz),nxy(q->nxy),nxyz(q->nxyz),
01300 xperiodic(q->xperiodic),yperiodic(q->yperiodic),zperiodic(q->zperiodic) {}
01301
01302
01303
01304
01305 inline int voropp_loop::init(fpoint vx,fpoint vy,fpoint vz,fpoint r,fpoint &px,fpoint &py,fpoint &pz) {
01306 ai=step_int((vx-ax-r)*xsp);
01307 bi=step_int((vx-ax+r)*xsp);
01308 if(!xperiodic) {
01309 if(ai<0) {ai=0;if(bi<0) bi=0;}
01310 if(bi>=nx) {bi=nx-1;if(ai>=nx) ai=nx-1;}
01311 }
01312 aj=step_int((vy-ay-r)*ysp);
01313 bj=step_int((vy-ay+r)*ysp);
01314 if(!yperiodic) {
01315 if(aj<0) {aj=0;if(bj<0) bj=0;}
01316 if(bj>=ny) {bj=ny-1;if(aj>=ny) aj=ny-1;}
01317 }
01318 ak=step_int((vz-az-r)*zsp);
01319 bk=step_int((vz-az+r)*zsp);
01320 if(!zperiodic) {
01321 if(ak<0) {ak=0;if(bk<0) bk=0;}
01322 if(bk>=nz) {bk=nz-1;if(ak>=nz) ak=nz-1;}
01323 }
01324 i=ai;j=aj;k=ak;
01325 aip=ip=step_mod(i,nx);apx=px=step_div(i,nx)*sx;
01326 ajp=jp=step_mod(j,ny);apy=py=step_div(j,ny)*sy;
01327 akp=kp=step_mod(k,nz);apz=pz=step_div(k,nz)*sz;
01328 inc1=aip-step_mod(bi,nx);
01329 inc2=nx*(ny+ajp-step_mod(bj,ny))+inc1;
01330 inc1+=nx;
01331 s=aip+nx*(ajp+ny*akp);
01332 return s;
01333 }
01334
01335
01336
01337
01338
01339 inline int voropp_loop::init(fpoint xmin,fpoint xmax,fpoint ymin,fpoint ymax,fpoint zmin,fpoint zmax,fpoint &px,fpoint &py,fpoint &pz) {
01340 ai=step_int((xmin-ax)*xsp);
01341 bi=step_int((xmax-ax)*xsp);
01342 if(!xperiodic) {
01343 if(ai<0) {ai=0;if(bi<0) bi=0;}
01344 if(bi>=nx) {bi=nx-1;if(ai>=nx) ai=nx-1;}
01345 }
01346 aj=step_int((ymin-ay)*ysp);
01347 bj=step_int((ymax-ay)*ysp);
01348 if(!yperiodic) {
01349 if(aj<0) {aj=0;if(bj<0) bj=0;}
01350 if(bj>=ny) {bj=ny-1;if(aj>=ny) aj=ny-1;}
01351 }
01352 ak=step_int((zmin-az)*zsp);
01353 bk=step_int((zmax-az)*zsp);
01354 if(!zperiodic) {
01355 if(ak<0) {ak=0;if(bk<0) bk=0;}
01356 if(bk>=nz) {bk=nz-1;if(ak>=nz) ak=nz-1;}
01357 }
01358 i=ai;j=aj;k=ak;
01359 aip=ip=step_mod(i,nx);apx=px=step_div(i,nx)*sx;
01360 ajp=jp=step_mod(j,ny);apy=py=step_div(j,ny)*sy;
01361 akp=kp=step_mod(k,nz);apz=pz=step_div(k,nz)*sz;
01362 inc1=aip-step_mod(bi,nx);
01363 inc2=nx*(ny+ajp-step_mod(bj,ny))+inc1;
01364 inc1+=nx;
01365 s=aip+nx*(ajp+ny*akp);
01366 return s;
01367 }
01368
01369
01370
01371 inline int voropp_loop::inc(fpoint &px,fpoint &py,fpoint &pz) {
01372 if(i<bi) {
01373 i++;
01374 if(ip<nx-1) {ip++;s++;} else {ip=0;s+=1-nx;px+=sx;}
01375 return s;
01376 } else if(j<bj) {
01377 i=ai;ip=aip;px=apx;j++;
01378 if(jp<ny-1) {jp++;s+=inc1;} else {jp=0;s+=inc1-nxy;py+=sy;}
01379 return s;
01380 } else if(k<bk) {
01381 i=ai;ip=aip;j=aj;jp=ajp;px=apx;py=apy;k++;
01382 if(kp<nz-1) {kp++;s+=inc2;} else {kp=0;s+=inc2-nxyz;pz+=sz;}
01383 return s;
01384 } else return -1;
01385 }
01386
01387
01388
01389
01390 inline int voropp_loop::step_int(fpoint a) {
01391 return a<0?int(a)-1:int(a);
01392 }
01393
01394
01395 inline int voropp_loop::step_mod(int a,int b) {
01396 return a>=0?a%b:b-1-(b-1-a)%b;
01397 }
01398
01399
01400 inline int voropp_loop::step_div(int a,int b) {
01401 return a>=0?a/b:-1+(a+1)/b;
01402 }
01403
01404
01405
01406 template<class r_option>
01407 void container_base<r_option>::add_wall(wall& w) {
01408 if(wall_number==current_wall_size) {
01409 current_wall_size*=2;
01410 if(current_wall_size>max_wall_size) throw fatal_error("Wall memory allocation exceeded absolute maximum");
01411 wall **pwall;
01412 pwall=new wall*[current_wall_size];
01413 for(int i=0;i<wall_number;i++) pwall[i]=walls[i];
01414 delete [] walls;walls=pwall;
01415 }
01416 walls[wall_number++]=&w;
01417 }
01418
01419
01420
01421
01422
01423 inline void radius_poly::store_radius(int i,int j,fpoint r) {
01424 cc->p[i][4*j+3]=r;
01425 if(r>max_radius) max_radius=r;
01426 }
01427
01428
01429 inline void radius_poly::clear_max() {
01430 max_radius=0;
01431 }
01432
01433
01434
01435
01436 inline void radius_mono::import(istream &is) {
01437 int n;fpoint x,y,z;
01438 is >> n >> x >> y >> z;
01439 while(!is.eof()) {
01440 cc->put(n,x,y,z);
01441 is >> n >> x >> y >> z;
01442 }
01443 }
01444
01445
01446
01447
01448 inline void radius_poly::import(istream &is) {
01449 int n;fpoint x,y,z,r;
01450 is >> n >> x >> y >> z >> r;
01451 while(!is.eof()) {
01452 cc->put(n,x,y,z,r);
01453 is >> n >> x >> y >> z >> r;
01454 }
01455 }
01456
01457
01458
01459
01460
01461
01462 inline void radius_poly::init(int ijk,int s) {
01463 crad=cc->p[ijk][4*s+3];
01464 mul=1+(crad*crad-max_radius*max_radius)/((max_radius+crad)*(max_radius+crad));
01465 crad*=crad;
01466 }
01467
01468
01469
01470
01471
01472
01473
01474 inline fpoint radius_poly::cutoff(fpoint lrs) {
01475 return mul*lrs;
01476 }
01477
01478
01479
01480
01481
01482
01483 inline fpoint radius_mono::cutoff(fpoint lrs) {
01484 return lrs;
01485 }
01486
01487
01488
01489
01490
01491 inline void radius_mono::rad(ostream &os,int l,int c) {
01492 os << "s";
01493 }
01494
01495
01496
01497
01498
01499 inline void radius_poly::rad(ostream &os,int l,int c) {
01500 os << cc->p[l][4*c+3];
01501 }
01502
01503
01504
01505
01506
01507
01508
01509
01510 inline fpoint radius_mono::volume(int ijk,int s) {
01511 return 0.125;
01512 }
01513
01514
01515
01516
01517
01518 inline fpoint radius_poly::volume(int ijk,int s) {
01519 fpoint a=cc->p[ijk][4*s+3];
01520 return a*a*a;
01521 }
01522
01523
01524
01525
01526
01527
01528
01529 inline fpoint radius_poly::scale(fpoint rs,int t,int q) {
01530 return rs+crad-cc->p[t][4*q+3]*cc->p[t][4*q+3];
01531 }
01532
01533
01534
01535
01536
01537
01538 inline fpoint radius_mono::scale(fpoint rs,int t,int q) {
01539 return rs;
01540 }
01541
01542
01543
01544
01545
01546 inline void radius_poly::print(ostream &os,int ijk,int q) {
01547 os << " " << cc->p[ijk][4*q+3];
01548 }
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563 template<class r_option>
01564 inline bool container_base<r_option>::compute_min_max_radius(int di,int dj,int dk,fpoint fx,fpoint fy,fpoint fz,fpoint gxs,fpoint gys,fpoint gzs,fpoint &crs,fpoint mrs) {
01565 fpoint xlo,ylo,zlo;
01566 const fpoint boxx=(bx-ax)/nx,boxy=(by-ay)/ny,boxz=(bz-az)/nz;
01567 const fpoint bxsq=boxx*boxx+boxy*boxy+boxz*boxz;
01568 if(di>0) {
01569 xlo=di*boxx-fx;
01570 crs=xlo*xlo;
01571 if(dj>0) {
01572 ylo=dj*boxy-fy;
01573 crs+=ylo*ylo;
01574 if(dk>0) {
01575 zlo=dk*boxz-fz;
01576 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01577 crs+=bxsq+2*(boxx*xlo+boxy*ylo+boxz*zlo);
01578 } else if(dk<0) {
01579 zlo=(dk+1)*boxz-fz;
01580 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01581 crs+=bxsq+2*(boxx*xlo+boxy*ylo-boxz*zlo);
01582 } else {
01583 if(radius.cutoff(crs)>mrs) return true;
01584 crs+=boxx*(2*xlo+boxx)+boxy*(2*ylo+boxy)+gzs;
01585 }
01586 } else if(dj<0) {
01587 ylo=(dj+1)*boxy-fy;
01588 crs+=ylo*ylo;
01589 if(dk>0) {
01590 zlo=dk*boxz-fz;
01591 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01592 crs+=bxsq+2*(boxx*xlo-boxy*ylo+boxz*zlo);
01593 } else if(dk<0) {
01594 zlo=(dk+1)*boxz-fz;
01595 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01596 crs+=bxsq+2*(boxx*xlo-boxy*ylo-boxz*zlo);
01597 } else {
01598 if(radius.cutoff(crs)>mrs) return true;
01599 crs+=boxx*(2*xlo+boxx)+boxy*(-2*ylo+boxy)+gzs;
01600 }
01601 } else {
01602 if(dk>0) {
01603 zlo=dk*boxz-fz;
01604 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01605 crs+=boxz*(2*zlo+boxz);
01606 } else if(dk<0) {
01607 zlo=(dk+1)*boxz-fz;
01608 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01609 crs+=boxz*(-2*zlo+boxz);
01610 } else {
01611 if(radius.cutoff(crs)>mrs) return true;
01612 crs+=gzs;
01613 }
01614 crs+=gys+boxx*(2*xlo+boxx);
01615 }
01616 } else if(di<0) {
01617 xlo=(di+1)*boxx-fx;
01618 crs=xlo*xlo;
01619 if(dj>0) {
01620 ylo=dj*boxy-fy;
01621 crs+=ylo*ylo;
01622 if(dk>0) {
01623 zlo=dk*boxz-fz;
01624 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01625 crs+=bxsq+2*(-boxx*xlo+boxy*ylo+boxz*zlo);
01626 } else if(dk<0) {
01627 zlo=(dk+1)*boxz-fz;
01628 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01629 crs+=bxsq+2*(-boxx*xlo+boxy*ylo-boxz*zlo);
01630 } else {
01631 if(radius.cutoff(crs)>mrs) return true;
01632 crs+=boxx*(-2*xlo+boxx)+boxy*(2*ylo+boxy)+gzs;
01633 }
01634 } else if(dj<0) {
01635 ylo=(dj+1)*boxy-fy;
01636 crs+=ylo*ylo;
01637 if(dk>0) {
01638 zlo=dk*boxz-fz;
01639 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01640 crs+=bxsq+2*(-boxx*xlo-boxy*ylo+boxz*zlo);
01641 } else if(dk<0) {
01642 zlo=(dk+1)*boxz-fz;
01643 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01644 crs+=bxsq+2*(-boxx*xlo-boxy*ylo-boxz*zlo);
01645 } else {
01646 if(radius.cutoff(crs)>mrs) return true;
01647 crs+=boxx*(-2*xlo+boxx)+boxy*(-2*ylo+boxy)+gzs;
01648 }
01649 } else {
01650 if(dk>0) {
01651 zlo=dk*boxz-fz;
01652 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01653 crs+=boxz*(2*zlo+boxz);
01654 } else if(dk<0) {
01655 zlo=(dk+1)*boxz-fz;
01656 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01657 crs+=boxz*(-2*zlo+boxz);
01658 } else {
01659 if(radius.cutoff(crs)>mrs) return true;
01660 crs+=gzs;
01661 }
01662 crs+=gys+boxx*(-2*xlo+boxx);
01663 }
01664 } else {
01665 if(dj>0) {
01666 ylo=dj*boxy-fy;
01667 crs=ylo*ylo;
01668 if(dk>0) {
01669 zlo=dk*boxz-fz;
01670 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01671 crs+=boxz*(2*zlo+boxz);
01672 } else if(dk<0) {
01673 zlo=(dk+1)*boxz-fz;
01674 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01675 crs+=boxz*(-2*zlo+boxz);
01676 } else {
01677 if(radius.cutoff(crs)>mrs) return true;
01678 crs+=gzs;
01679 }
01680 crs+=boxy*(2*ylo+boxy);
01681 } else if(dj<0) {
01682 ylo=(dj+1)*boxy-fy;
01683 crs=ylo*ylo;
01684 if(dk>0) {
01685 zlo=dk*boxz-fz;
01686 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01687 crs+=boxz*(2*zlo+boxz);
01688 } else if(dk<0) {
01689 zlo=(dk+1)*boxz-fz;
01690 crs+=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01691 crs+=boxz*(-2*zlo+boxz);
01692 } else {
01693 if(radius.cutoff(crs)>mrs) return true;
01694 crs+=gzs;
01695 }
01696 crs+=boxy*(-2*ylo+boxy);
01697 } else {
01698 if(dk>0) {
01699 zlo=dk*boxz-fz;crs=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01700 crs+=boxz*(2*zlo+boxz);
01701 } else if(dk<0) {
01702 zlo=(dk+1)*boxz-fz;crs=zlo*zlo;if(radius.cutoff(crs)>mrs) return true;
01703 crs+=boxz*(-2*zlo+boxz);
01704 } else {
01705 crs=0;
01706 cout << "Can't happen ... happened\n";
01707 }
01708 crs+=gys;
01709 }
01710 crs+=gxs;
01711 }
01712 return false;
01713 }
01714
01715 #include "worklist.cc"