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