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