00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "cell.hh"
00012
00013
00014 template<class n_option>
00015 voronoicell_base<n_option>::voronoicell_base() :
00016 current_vertices(init_vertices), current_vertex_order(init_vertex_order),
00017 current_delete_size(init_delete_size), current_delete2_size(init_delete2_size),
00018 ed(new int*[current_vertices]), nu(new int[current_vertices]),
00019 pts(new fpoint[3*current_vertices]), mem(new int[current_vertex_order]),
00020 mec(new int[current_vertex_order]), mep(new int*[current_vertex_order]),
00021 ds(new int[current_delete_size]), ds2(new int[current_delete2_size]), neighbor(this) {
00022 int i;
00023 sure.p=pts;
00024 for(i=0;i<3;i++) {
00025 mem[i]=init_n_vertices;mec[i]=0;
00026 mep[i]=new int[init_n_vertices*(2*i+1)];
00027 }
00028 mem[3]=init_3_vertices;mec[3]=0;
00029 mep[3]=new int[init_3_vertices*7];
00030 for(i=4;i<current_vertex_order;i++) {
00031 mem[i]=init_n_vertices;mec[i]=0;
00032 mep[i]=new int[init_n_vertices*(2*i+1)];
00033 }
00034 }
00035
00036
00037 template<class n_option>
00038 voronoicell_base<n_option>::~voronoicell_base() {
00039 delete [] ds;
00040 delete [] ds2;
00041 for(int i=0;i<current_vertex_order;i++) if(mem[i]>0) delete [] mep[i];
00042 delete [] mem;
00043 delete [] mec;
00044 delete [] mep;
00045 delete [] ed;
00046 delete [] nu;
00047 delete [] pts;
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 template<class n_option>
00062 void voronoicell_base<n_option>::add_memory(int i) {
00063 int s=2*i+1;
00064 if(mem[i]==0) {
00065 neighbor.allocate(i,init_n_vertices);
00066 mep[i]=new int[init_n_vertices*s];
00067 mem[i]=init_n_vertices;
00068 #if VOROPP_VERBOSE >=2
00069 cerr << "Order " << i << " vertex memory created " << endl;
00070 #endif
00071 } else {
00072 int j=0,k,*l;
00073 mem[i]*=2;
00074 if(mem[i]>max_n_vertices) voropp_fatal_error("Point memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
00075 #if VOROPP_VERBOSE >=2
00076 cerr << "Order " << i << " vertex memory scaled up to " << mem[i] << endl;
00077 #endif
00078 l=new int[s*mem[i]];
00079 int m=0;
00080 neighbor.allocate_aux1(i);
00081 while(j<s*mec[i]) {
00082 k=mep[i][j+2*i];
00083 if(k>=0) {
00084 ed[k]=l+j;
00085 neighbor.set_to_aux1_offset(k,m);
00086 } else {
00087 int o;
00088 for(o=0;o<stack2;o++) {
00089 if(ed[ds2[o]]==mep[i]+j) {
00090 ed[ds2[o]]=l+j;
00091 neighbor.set_to_aux1_offset(ds2[o],m);
00092 break;
00093 }
00094 }
00095 if(o==stack2) voropp_fatal_error("Couldn't relocate dangling pointer",VOROPP_INTERNAL_ERROR);
00096 #if VOROPP_VERBOSE >=3
00097 cerr << "Relocated dangling pointer" << endl;
00098 #endif
00099 }
00100 for(k=0;k<s;k++,j++) l[j]=mep[i][j];
00101 for(k=0;k<i;k++,m++) neighbor.copy_to_aux1(i,m);
00102 }
00103 delete [] mep[i];
00104 mep[i]=l;
00105 neighbor.switch_to_aux1(i);
00106 }
00107 }
00108
00109
00110
00111
00112
00113
00114 template<class n_option>
00115 void voronoicell_base<n_option>::add_memory_vertices() {
00116 int i=2*current_vertices,j,**pp,*pnu;
00117 if(i>max_vertices) voropp_fatal_error("Vertex memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
00118 #if VOROPP_VERBOSE >=2
00119 cerr << "Vertex memory scaled up to " << i << endl;
00120 #endif
00121 fpoint *ppts;
00122 pp=new int*[i];
00123 for(j=0;j<current_vertices;j++) pp[j]=ed[j];
00124 delete [] ed;ed=pp;
00125 neighbor.add_memory_vertices(i);
00126 pnu=new int[i];
00127 for(j=0;j<current_vertices;j++) pnu[j]=nu[j];
00128 delete [] nu;nu=pnu;
00129 ppts=new fpoint[3*i];
00130 for(j=0;j<3*current_vertices;j++) ppts[j]=pts[j];
00131 delete [] pts;sure.p=pts=ppts;
00132 current_vertices=i;
00133 }
00134
00135
00136
00137
00138
00139
00140 template<class n_option>
00141 void voronoicell_base<n_option>::add_memory_vorder() {
00142 int i=2*current_vertex_order,j,*p1,**p2;
00143 if(i>max_vertex_order) voropp_fatal_error("Vertex order memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
00144 #if VOROPP_VERBOSE >=2
00145 cerr << "Vertex order memory scaled up to " << i << endl;
00146 #endif
00147 p1=new int[i];
00148 for(j=0;j<current_vertex_order;j++) p1[j]=mem[j];while(j<i) p1[j++]=0;
00149 delete [] mem;mem=p1;
00150 p2=new int*[i];
00151 for(j=0;j<current_vertex_order;j++) p2[j]=mep[j];
00152 delete [] mep;mep=p2;
00153 p1=new int[i];
00154 for(j=0;j<current_vertex_order;j++) p1[j]=mec[j];while(j<i) p1[j++]=0;
00155 delete [] mec;mec=p1;
00156 neighbor.add_memory_vorder(i);
00157 current_vertex_order=i;
00158 }
00159
00160
00161
00162
00163 template<class n_option>
00164 void voronoicell_base<n_option>::add_memory_ds() {
00165 int i=2*current_delete_size,j,*pds;
00166 if(i>max_delete_size) voropp_fatal_error("Delete stack 1 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
00167 #if VOROPP_VERBOSE >=2
00168 cerr << "Delete stack 1 memory scaled up to " << i << endl;
00169 #endif
00170 pds=new int[i];
00171 for(j=0;j<current_delete_size;j++) pds[j]=ds[j];
00172 delete [] ds;ds=pds;
00173 current_delete_size=i;
00174 }
00175
00176
00177
00178
00179 template<class n_option>
00180 void voronoicell_base<n_option>::add_memory_ds2() {
00181 int i=2*current_delete2_size,j,*pds2;
00182 if(i>max_delete2_size) voropp_fatal_error("Delete stack 2 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
00183 #if VOROPP_VERBOSE >=2
00184 cerr << "Delete stack 2 memory scaled up to " << i << endl;
00185 #endif
00186 pds2=new int[i];
00187 for(j=0;j<current_delete2_size;j++) pds2[j]=ds2[j];
00188 delete [] ds2;ds2=pds2;
00189 current_delete2_size=i;
00190 }
00191
00192
00193
00194
00195
00196 template<class n_option>
00197 void voronoicell_base<n_option>::init(fpoint xmin,fpoint xmax,fpoint ymin,fpoint ymax,fpoint zmin,fpoint zmax) {
00198 for(int i=0;i<current_vertex_order;i++) mec[i]=0;up=0;
00199 mec[3]=p=8;xmin*=2;xmax*=2;ymin*=2;ymax*=2;zmin*=2;zmax*=2;
00200 pts[0]=xmin;pts[1]=ymin;pts[2]=zmin;
00201 pts[3]=xmax;pts[4]=ymin;pts[5]=zmin;
00202 pts[6]=xmin;pts[7]=ymax;pts[8]=zmin;
00203 pts[9]=xmax;pts[10]=ymax;pts[11]=zmin;
00204 pts[12]=xmin;pts[13]=ymin;pts[14]=zmax;
00205 pts[15]=xmax;pts[16]=ymin;pts[17]=zmax;
00206 pts[18]=xmin;pts[19]=ymax;pts[20]=zmax;
00207 pts[21]=xmax;pts[22]=ymax;pts[23]=zmax;
00208 int *q=mep[3];
00209 q[0]=1;q[1]=4;q[2]=2;q[3]=2;q[4]=1;q[5]=0;q[6]=0;
00210 q[7]=3;q[8]=5;q[9]=0;q[10]=2;q[11]=1;q[12]=0;q[13]=1;
00211 q[14]=0;q[15]=6;q[16]=3;q[17]=2;q[18]=1;q[19]=0;q[20]=2;
00212 q[21]=2;q[22]=7;q[23]=1;q[24]=2;q[25]=1;q[26]=0;q[27]=3;
00213 q[28]=6;q[29]=0;q[30]=5;q[31]=2;q[32]=1;q[33]=0;q[34]=4;
00214 q[35]=4;q[36]=1;q[37]=7;q[38]=2;q[39]=1;q[40]=0;q[41]=5;
00215 q[42]=7;q[43]=2;q[44]=4;q[45]=2;q[46]=1;q[47]=0;q[48]=6;
00216 q[49]=5;q[50]=3;q[51]=6;q[52]=2;q[53]=1;q[54]=0;q[55]=7;
00217 ed[0]=q;ed[1]=q+7;ed[2]=q+14;ed[3]=q+21;
00218 ed[4]=q+28;ed[5]=q+35;ed[6]=q+42;ed[7]=q+49;
00219 neighbor.init();
00220 nu[0]=nu[1]=nu[2]=nu[3]=nu[4]=nu[5]=nu[6]=nu[7]=3;
00221 }
00222
00223
00224
00225
00226
00227 template<class n_option>
00228 inline void voronoicell_base<n_option>::init_octahedron(fpoint l) {
00229 for(int i=0;i<current_vertex_order;i++) mec[i]=0;up=0;
00230 mec[4]=p=6;l*=2;
00231 pts[0]=-l;pts[1]=0;pts[2]=0;
00232 pts[3]=l;pts[4]=0;pts[5]=0;
00233 pts[6]=0;pts[7]=-l;pts[8]=0;
00234 pts[9]=0;pts[10]=l;pts[11]=0;
00235 pts[12]=0;pts[13]=0;pts[14]=-l;
00236 pts[15]=0;pts[16]=0;pts[17]=l;
00237 int *q=mep[4];
00238 q[0]=2;q[1]=5;q[2]=3;q[3]=4;q[4]=0;q[5]=0;q[6]=0;q[7]=0;q[8]=0;
00239 q[9]=2;q[10]=4;q[11]=3;q[12]=5;q[13]=2;q[14]=2;q[15]=2;q[16]=2;q[17]=1;
00240 q[18]=0;q[19]=4;q[20]=1;q[21]=5;q[22]=0;q[23]=3;q[24]=0;q[25]=1;q[26]=2;
00241 q[27]=0;q[28]=5;q[29]=1;q[30]=4;q[31]=2;q[32]=3;q[33]=2;q[34]=1;q[35]=3;
00242 q[36]=0;q[37]=3;q[38]=1;q[39]=2;q[40]=3;q[41]=3;q[42]=1;q[43]=1;q[44]=4;
00243 q[45]=0;q[46]=2;q[47]=1;q[48]=3;q[49]=1;q[50]=3;q[51]=3;q[52]=1;q[53]=5;
00244 ed[0]=q;ed[1]=q+9;ed[2]=q+18;ed[3]=q+27;ed[4]=q+36;ed[5]=q+45;
00245 neighbor.init_octahedron();
00246 nu[0]=nu[1]=nu[2]=nu[3]=nu[4]=nu[5]=4;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255 template<class n_option>
00256 inline void voronoicell_base<n_option>::init_tetrahedron(fpoint x0,fpoint y0,fpoint z0,fpoint x1,fpoint y1,fpoint z1,fpoint x2,fpoint y2,fpoint z2,fpoint x3,fpoint y3,fpoint z3) {
00257 for(int i=0;i<current_vertex_order;i++) mec[i]=0;up=0;
00258 mec[3]=p=4;
00259 pts[0]=x0*2;pts[1]=y0*2;pts[2]=z0*2;
00260 pts[3]=x1*2;pts[4]=y1*2;pts[5]=z1*2;
00261 pts[6]=x2*2;pts[7]=y2*2;pts[8]=z2*2;
00262 pts[9]=x3*2;pts[10]=y3*2;pts[11]=z3*2;
00263 int *q=mep[3];
00264 q[0]=1;q[1]=3;q[2]=2;q[3]=0;q[4]=0;q[5]=0;q[6]=0;
00265 q[7]=0;q[8]=2;q[9]=3;q[10]=0;q[11]=2;q[12]=1;q[13]=1;
00266 q[14]=0;q[15]=3;q[16]=1;q[17]=2;q[18]=2;q[19]=1;q[20]=2;
00267 q[21]=0;q[22]=1;q[23]=2;q[24]=1;q[25]=2;q[26]=1;q[27]=3;
00268 ed[0]=q;ed[1]=q+7;ed[2]=q+14;ed[3]=q+21;
00269 neighbor.init_tetrahedron();
00270 nu[0]=nu[1]=nu[2]=nu[3]=3;
00271 }
00272
00273
00274
00275
00276
00277 template<class n_option>
00278 inline void voronoicell_base<n_option>::init_test(int n) {
00279 for(int i=0;i<current_vertex_order;i++) mec[i]=0;up=p=0;
00280 switch(n) {
00281 case 0:
00282
00283
00284
00285 add_vertex(1,-2,-1,3,1,5);
00286 add_vertex(0,-1,1,5,0,2);
00287 add_vertex(0,1,0,1,3,6,4);
00288 add_vertex(1,4,-1,4,6,2,0);
00289 add_vertex(-1,4,-1,3,5,2,6);
00290 add_vertex(-1,-2,-1,4,0,1);
00291 add_vertex(0,3,0,4,2,3);
00292 break;
00293 case 1:
00294
00295
00296
00297 add_vertex(-2,2,-1,3,4,1);
00298 add_vertex(2,2,-1,0,5,2);
00299 add_vertex(2,-2,-1,1,6,3);
00300 add_vertex(-2,-2,-1,2,7,0);
00301 add_vertex(-1,1,0,0,7,5);
00302 add_vertex(1,1,1,1,4,6);
00303 add_vertex(1,-1,1,7,2,5);
00304 add_vertex(-1,-1,1,4,3,6);
00305 break;
00306 case 2:
00307
00308
00309
00310
00311 add_vertex(1,-2,-1,1,3,4);
00312 add_vertex(-1,-2,-1,2,0,4,5);
00313 add_vertex(-1,2,-1,1,6,3);
00314 add_vertex(1,2,-1,2,6,5,0);
00315 add_vertex(0,-1,1,5,1,0);
00316 add_vertex(0,0,0,1,4,3,6);
00317 add_vertex(0,1,1,2,5,3);
00318 break;
00319 case 3:
00320
00321
00322
00323 add_vertex(-1,-1,-1,4,3,1);
00324 add_vertex(1,-1,-1,0,2,5);
00325 add_vertex(1,1,-1,6,1,3);
00326 add_vertex(-1,1,-1,2,0,7);
00327 add_vertex(-1,-1,1,7,0,5,8);
00328 add_vertex(1,-1,1,4,1,6,8);
00329 add_vertex(1,1,1,5,2,7,8);
00330 add_vertex(-1,1,1,6,3,4,8);
00331 add_vertex(0,0,2,7,4,5,6);
00332 break;
00333 case 4:
00334
00335
00336
00337
00338
00339
00340 add_vertex(1,-3,-1,5,6,1);
00341 add_vertex(-1,-3,-1,0,6,2);
00342 add_vertex(-3,0,-1,1,7,8,3);
00343 add_vertex(-1,3,-1,2,9,4);
00344 add_vertex(1,3,-1,3,9,5);
00345 add_vertex(3,0,-1,4,8,7,0);
00346 add_vertex(0,-2,1,7,1,0);
00347 add_vertex(0,-1,0,8,2,6,5);
00348 add_vertex(0,1,0,9,2,7,5);
00349 add_vertex(0,2,1,3,8,4);
00350 break;
00351 case 5:
00352
00353
00354
00355
00356 add_vertex(-1,-3,-1,7,1,8,12);
00357 add_vertex(1,-3,-1,2,12,8,0);
00358 add_vertex(3,-1,-1,3,9,13,1);
00359 add_vertex(3,1,-1,4,13,9,2);
00360 add_vertex(1,3,-1,5,10,14,3);
00361 add_vertex(-1,3,-1,6,14,10,4);
00362 add_vertex(-3,1,-1,7,11,15,5);
00363 add_vertex(-3,-1,-1,0,15,11,6);
00364 add_vertex(0,-2,1,0,1,12);
00365 add_vertex(2,0,1,2,3,13);
00366 add_vertex(0,2,1,14,4,5);
00367 add_vertex(-2,0,1,7,15,6);
00368 add_vertex(0,-1,0.5,0,8,1,16);
00369 add_vertex(1,0,0.5,2,9,3,16);
00370 add_vertex(0,1,0.5,4,10,5,16);
00371 add_vertex(-1,0,0.5,6,11,7,16);
00372 add_vertex(0,0,0,15,12,13,14);
00373 break;
00374 case 6:
00375
00376
00377
00378
00379 add_vertex(-1,-3,-1,7,1,8,12);
00380 add_vertex(1,-3,-1,2,12,8,0);
00381 add_vertex(3,-1,-1,3,9,13,1);
00382 add_vertex(3,1,-1,4,13,9,2);
00383 add_vertex(1,3,-1,5,10,14,3);
00384 add_vertex(-1,3,-1,6,14,10,4);
00385 add_vertex(-3,1,-1,7,11,15,5);
00386 add_vertex(-3,-1,-1,0,15,11,6);
00387 add_vertex(0,-2,1,0,1,12);
00388 add_vertex(2,0,1,2,3,13);
00389 add_vertex(0,2,1,14,4,5);
00390 add_vertex(-2,0,1,7,15,6);
00391 add_vertex(0,-1,0,0,8,1,16);
00392 add_vertex(1,0,0,2,9,3,16);
00393 add_vertex(0,1,0,4,10,5,16);
00394 add_vertex(-1,0,0,6,11,7,16);
00395 add_vertex(0,0,0,15,12,13,14);
00396 break;
00397 case 7:
00398
00399
00400
00401 add_vertex(2,-3,-1,3,4,1);
00402 add_vertex(-2,-3,-1,0,4,2);
00403 add_vertex(-2,3,-1,1,7,3);
00404 add_vertex(2,3,-1,2,6,0);
00405 add_vertex(0,-2,0,0,5,1);
00406 add_vertex(0,1,0,4,6,7);
00407 add_vertex(1,2,1,7,5,3);
00408 add_vertex(-1,2,1,5,6,2);
00409 break;
00410 case 8:
00411
00412
00413 add_vertex(3,-2,-1,2,3,1);
00414 add_vertex(-3,-2,-1,0,4,2);
00415 add_vertex(0,4,-1,1,5,0);
00416 add_vertex(1.5,-1,0,7,0,6);
00417 add_vertex(-1.5,-1,0,1,7,8);
00418 add_vertex(0,2,0,8,6,2);
00419 add_vertex(0.75,0.5,0,9,3,5);
00420 add_vertex(0,-1,0,4,3,9);
00421 add_vertex(-0.75,0.5,0,4,9,5);
00422 add_vertex(0,0,1,8,7,6);
00423 break;
00424 case 9:
00425
00426
00427 add_vertex(0,0,0,3,1,2);
00428 add_vertex(1,0,1,3,2,0);
00429 add_vertex(1,1,0,3,0,1);
00430 add_vertex(2,0,0,6,4,2,1,0);
00431 add_vertex(3,1,0,3,6,8,5);
00432 add_vertex(3,2,0,4);
00433 add_vertex(4,0,0,4,3,7,8);
00434 add_vertex(5,0,0,6);
00435 add_vertex(4,1,0,6,4);
00436 }
00437
00438 construct_relations();
00439 neighbor.label_facets();
00440 }
00441
00442
00443
00444
00445 template<class n_option>
00446 void voronoicell_base<n_option>::add_vertex(fpoint x,fpoint y,fpoint z,int a) {
00447 pts[3*p]=x;pts[3*p+1]=y;pts[3*p+2]=z;nu[p]=1;
00448 if(mem[1]==mec[1]) add_memory(1);
00449 neighbor.set_pointer(p,1);
00450 int *q=mep[1]+3*mec[1]++;ed[p]=q;
00451 q[0]=a;q[2]=p++;
00452 }
00453
00454
00455
00456
00457 template<class n_option>
00458 void voronoicell_base<n_option>::add_vertex(fpoint x,fpoint y,fpoint z,int a,int b) {
00459 pts[3*p]=x;pts[3*p+1]=y;pts[3*p+2]=z;nu[p]=2;
00460 if(mem[2]==mec[2]) add_memory(2);
00461 neighbor.set_pointer(p,2);
00462 int *q=mep[2]+5*mec[2]++;ed[p]=q;
00463 q[0]=a;q[1]=b;q[4]=p++;
00464 }
00465
00466
00467
00468
00469 template<class n_option>
00470 void voronoicell_base<n_option>::add_vertex(fpoint x,fpoint y,fpoint z,int a,int b,int c) {
00471 pts[3*p]=x;pts[3*p+1]=y;pts[3*p+2]=z;nu[p]=3;
00472 if(mem[3]==mec[3]) add_memory(3);
00473 neighbor.set_pointer(p,3);
00474 int *q=mep[3]+7*mec[3]++;ed[p]=q;
00475 q[0]=a;q[1]=b;q[2]=c;q[6]=p++;
00476 }
00477
00478
00479
00480
00481 template<class n_option>
00482 void voronoicell_base<n_option>::add_vertex(fpoint x,fpoint y,fpoint z,int a,int b,int c,int d) {
00483 pts[3*p]=x;pts[3*p+1]=y;pts[3*p+2]=z;nu[p]=4;
00484 if(mem[4]==mec[4]) add_memory(4);
00485 neighbor.set_pointer(p,4);
00486 int *q=mep[4]+9*mec[4]++;ed[p]=q;
00487 q[0]=a;q[1]=b;q[2]=c;q[3]=d;q[8]=p++;
00488 }
00489
00490
00491
00492
00493 template<class n_option>
00494 void voronoicell_base<n_option>::add_vertex(fpoint x,fpoint y,fpoint z,int a,int b,int c,int d,int e) {
00495 pts[3*p]=x;pts[3*p+1]=y;pts[3*p+2]=z;nu[p]=5;
00496 if(mem[5]==mec[5]) add_memory(5);
00497 neighbor.set_pointer(p,5);
00498 int *q=mep[5]+11*mec[5]++;ed[p]=q;
00499 q[0]=a;q[1]=b;q[2]=c;q[3]=d;q[4]=e;q[10]=p++;
00500 }
00501
00502
00503
00504
00505 template<class n_option>
00506 void voronoicell_base<n_option>::check_relations() {
00507 int i,j;
00508 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) if(ed[ed[i][j]][ed[i][nu[i]+j]]!=i)
00509 cout << "Relational error at point " << i << ", edge " << j << "." << endl;
00510 }
00511
00512
00513
00514
00515
00516
00517 template<class n_option>
00518 void voronoicell_base<n_option>::check_duplicates() {
00519 int i,j,k;
00520 for(i=0;i<p;i++) for(j=1;j<nu[i];j++) for(k=0;k<j;k++) if(ed[i][j]==ed[i][k])
00521 cout << "Duplicate edges: (" << i << "," << j << ") and (" << i << "," << k << ") [" << ed[i][j] << "]" << endl;
00522 }
00523
00524
00525 template<class n_option>
00526 void voronoicell_base<n_option>::construct_relations() {
00527 int i,j,k,l;
00528 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) {
00529 k=ed[i][j];
00530 l=0;
00531 while(ed[k][l]!=i) {
00532 l++;
00533 if(l==nu[k]) voropp_fatal_error("Relation table construction failed",VOROPP_INTERNAL_ERROR);
00534 }
00535 ed[i][nu[i]+j]=l;
00536 }
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546 template<class n_option>
00547 bool voronoicell_base<n_option>::nplane(fpoint x,fpoint y,fpoint z,fpoint rsq,int p_id) {
00548 int count=0,i,j,k,lp=up,cp,qp,rp,stack=0;stack2=0;
00549 int us=0,ls=0,qs,iqs,cs,uw,qw,lw;
00550 int *edp,*edd;
00551 fpoint u,l,r,q;bool complicated_setup=false,new_double_edge=false,double_edge=false;
00552
00553
00554 sure.init(x,y,z,rsq);
00555
00556
00557
00558 uw=sure.test(up,u);
00559
00560
00561
00562
00563 try {
00564 if(uw==1) {
00565
00566
00567 us=0;
00568 do {
00569 lp=ed[up][us];
00570 lw=sure.test(lp,l);
00571 if(l<u) break;
00572 us++;
00573 } while (us<nu[up]);
00574
00575 if(us==nu[up]) {
00576 return false;
00577 }
00578
00579 ls=ed[up][nu[up]+us];
00580 while(lw==1) {
00581 if(++count>=p) throw true;
00582 u=l;up=lp;
00583 for(us=0;us<ls;us++) {
00584 lp=ed[up][us];
00585 lw=sure.test(lp,l);
00586 if(l<u) break;
00587 }
00588 if(us==ls) {
00589 us++;
00590 while(us<nu[up]) {
00591 lp=ed[up][us];
00592 lw=sure.test(lp,l);
00593 if(l<u) break;
00594 us++;
00595 }
00596 if(us==nu[up]) {
00597 return false;
00598 }
00599 }
00600 ls=ed[up][nu[up]+us];
00601 }
00602
00603
00604
00605
00606 if(lw==0) {
00607 up=lp;
00608 complicated_setup=true;
00609 } else complicated_setup=false;
00610 } else if(uw==-1) {
00611 us=0;
00612 do {
00613 qp=ed[up][us];
00614 qw=sure.test(qp,q);
00615 if(u<q) break;
00616 us++;
00617 } while (us<nu[up]);
00618 if(us==nu[up]) return true;
00619
00620 while(qw==-1) {
00621 qs=ed[up][nu[up]+us];
00622 if(++count>=p) throw true;
00623 u=q;up=qp;
00624 for(us=0;us<qs;us++) {
00625 qp=ed[up][us];
00626 qw=sure.test(qp,q);
00627 if(u<q) break;
00628 }
00629 if(us==qs) {
00630 us++;
00631 while(us<nu[up]) {
00632 qp=ed[up][us];
00633 qw=sure.test(qp,q);
00634 if(u<q) break;
00635 us++;
00636 }
00637 if(us==nu[up]) return true;
00638 }
00639 }
00640 if(qw==1) {
00641 lp=up;ls=us;l=u;
00642 up=qp;us=ed[lp][nu[lp]+ls];u=q;
00643 complicated_setup=false;
00644 } else {
00645 up=qp;
00646 complicated_setup=true;
00647 }
00648 } else {
00649
00650
00651
00652
00653 complicated_setup=true;
00654 }
00655 }
00656 catch(bool except) {
00657
00658
00659
00660
00661 #if VOROPP_VERBOSE >=1
00662 cerr << "Bailed out of convex calculation\n";
00663 #endif
00664 qw=1;lw=0;
00665 for(qp=0;qp<p;qp++) {
00666 qw=sure.test(qp,q);
00667 if(qw==1) {
00668
00669
00670
00671 for(us=0;us<nu[qp];us++) {
00672 lp=ed[qp][us];
00673 if(lp<qp) {
00674 lw=sure.test(lp,l);
00675 if(lw!=1) break;
00676 }
00677 }
00678 if(us<nu[qp]) {
00679 up=qp;
00680 if(lw==0) {
00681 complicated_setup=true;
00682 } else {
00683 complicated_setup=false;
00684 u=q;
00685 ls=ed[up][nu[up]+us];
00686 }
00687 break;
00688 }
00689 } else if(qw==-1) {
00690
00691
00692
00693 for(ls=0;ls<nu[qp];ls++) {
00694 up=ed[qp][ls];
00695 if(up<qp) {
00696 uw=sure.test(up,u);
00697 if(uw!=-1) break;
00698 }
00699 }
00700 if(ls<nu[qp]) {
00701 if(uw==0) {
00702 up=qp;
00703 complicated_setup=true;
00704 } else {
00705 complicated_setup=false;
00706 lp=qp;l=q;
00707 us=ed[lp][nu[lp]+ls];
00708 }
00709 break;
00710 }
00711 } else {
00712
00713
00714
00715 up=qp;
00716 complicated_setup=true;
00717 break;
00718 }
00719 }
00720 if(qp==p) return qw==-1?true:false;
00721 }
00722
00723
00724
00725
00726 if(p==current_vertices) add_memory_vertices();
00727
00728 if(complicated_setup) {
00729
00730
00731
00732 pts[3*p]=pts[3*up];
00733 pts[3*p+1]=pts[3*up+1];
00734 pts[3*p+2]=pts[3*up+2];
00735
00736
00737
00738
00739 i=0;
00740 lp=ed[up][0];
00741 lw=sure.test(lp,l);
00742 if(lw!=-1) {
00743
00744
00745
00746
00747 rp=lw;
00748 do {
00749 i++;
00750
00751
00752
00753
00754
00755 if(i==nu[up]) return false;
00756 lp=ed[up][i];
00757 lw=sure.test(lp,l);
00758 } while (lw!=-1);
00759 j=i+1;
00760
00761
00762
00763
00764 while(j<nu[up]) {
00765 lp=ed[up][j];
00766 lw=sure.test(lp,l);
00767 if(lw!=-1) break;
00768 j++;
00769 }
00770
00771
00772
00773
00774
00775
00776
00777
00778 if(j==nu[up]&&i==1&&rp==0) {
00779 nu[p]=nu[up];
00780 double_edge=true;
00781 } else nu[p]=j-i+2;
00782 k=1;
00783
00784
00785
00786 while (nu[p]>=current_vertex_order) add_memory_vorder();
00787 if(mec[nu[p]]==mem[nu[p]]) add_memory(nu[p]);
00788 neighbor.set_pointer(p,nu[p]);
00789 ed[p]=mep[nu[p]]+(2*nu[p]+1)*mec[nu[p]]++;
00790 ed[p][2*nu[p]]=p;
00791
00792
00793
00794
00795 us=cycle_down(i,up);
00796 while(i<j) {
00797 qp=ed[up][i];
00798 qs=ed[up][nu[up]+i];
00799 neighbor.copy(p,k,up,i);
00800 ed[p][k]=qp;
00801 ed[p][nu[p]+k]=qs;
00802 ed[qp][qs]=p;
00803 ed[qp][nu[qp]+qs]=k;
00804 ed[up][i]=-1;
00805 i++;k++;
00806 }
00807 qs=i==nu[up]?0:i;
00808 } else {
00809
00810
00811
00812
00813 i=nu[up]-1;
00814 lp=ed[up][i];
00815 lw=sure.test(lp,l);
00816 while(lw==-1) {
00817 i--;
00818
00819
00820
00821
00822 if(i==0) return true;
00823 lp=ed[up][i];
00824 lw=sure.test(lp,l);
00825 }
00826
00827
00828 j=1;
00829 qp=ed[up][j];
00830 qw=sure.test(qp,q);
00831 while(qw==-1) {
00832 j++;
00833 qp=ed[up][j];
00834 qw=sure.test(qp,l);
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00844 if(i==j&&qw==0) {
00845 double_edge=true;
00846 nu[p]=nu[up];
00847 } else {
00848 nu[p]=nu[up]-i+j+1;
00849 }
00850
00851
00852
00853 k=1;
00854 while(nu[p]>=current_vertex_order) add_memory_vorder();
00855 if(mec[nu[p]]==mem[nu[p]]) add_memory(nu[p]);
00856
00857
00858
00859
00860 neighbor.set_pointer(p,nu[p]);
00861 ed[p]=mep[nu[p]]+(2*nu[p]+1)*mec[nu[p]]++;
00862 ed[p][2*nu[p]]=p;
00863 us=i++;
00864 while(i<nu[up]) {
00865 qp=ed[up][i];
00866 qs=ed[up][nu[up]+i];
00867 neighbor.copy(p,k,up,i);
00868 ed[p][k]=qp;
00869 ed[p][nu[p]+k]=qs;
00870 ed[qp][qs]=p;
00871 ed[qp][nu[qp]+qs]=k;
00872 ed[up][i]=-1;
00873 i++;k++;
00874 }
00875 i=0;
00876 while(i<j) {
00877 qp=ed[up][i];
00878 qs=ed[up][nu[up]+i];
00879 neighbor.copy(p,k,up,i);
00880 ed[p][k]=qp;
00881 ed[p][nu[p]+k]=qs;
00882 ed[qp][qs]=p;
00883 ed[qp][nu[qp]+qs]=k;
00884 ed[up][i]=-1;
00885 i++;k++;
00886 }
00887 qs=j;
00888 }
00889 if(!double_edge) {
00890 neighbor.copy(p,k,up,qs);
00891 neighbor.set(p,0,p_id);
00892 } else neighbor.copy(p,0,up,qs);
00893
00894
00895 if(stack2==current_delete2_size) add_memory_ds2();
00896 ds2[stack2++]=up;
00897
00898
00899
00900
00901
00902 cs=k;
00903 qp=up;q=u;
00904 i=ed[up][us];
00905 us=ed[up][nu[up]+us];
00906 up=i;
00907 ed[qp][2*nu[qp]]=-p;
00908
00909 } else {
00910
00911
00912
00913
00914
00915 if(stack==current_delete_size) add_memory_ds();
00916 ds[stack++]=up;
00917 r=1/(u-l);
00918 pts[3*p]=(pts[3*lp]*u-pts[3*up]*l)*r;
00919 pts[3*p+1]=(pts[3*lp+1]*u-pts[3*up+1]*l)*r;
00920 pts[3*p+2]=(pts[3*lp+2]*u-pts[3*up+2]*l)*r;
00921
00922
00923
00924 nu[p]=3;
00925 if(mec[3]==mem[3]) add_memory(3);
00926 neighbor.set_pointer(p,3);
00927 neighbor.set(p,0,p_id);
00928 neighbor.copy(p,1,up,us);
00929 neighbor.copy(p,2,lp,ls);
00930 ed[p]=mep[3]+7*mec[3]++;
00931 ed[p][6]=p;
00932 ed[up][us]=-1;
00933 ed[lp][ls]=p;
00934 ed[lp][nu[lp]+ls]=1;
00935 ed[p][1]=lp;
00936 ed[p][nu[p]+1]=ls;
00937 cs=2;
00938
00939
00940 qs=cycle_up(us,up);
00941 qp=up;q=u;
00942 }
00943
00944
00945
00946 cp=p;rp=p;p++;
00947 while(qp!=up||qs!=us) {
00948
00949
00950
00951
00952 lp=ed[qp][qs];
00953 lw=sure.test(lp,l);
00954
00955 if(lw==1) {
00956
00957
00958
00959 if(stack==current_delete_size) add_memory_ds();
00960 qs=cycle_up(ed[qp][nu[qp]+qs],lp);
00961 qp=lp;
00962 q=l;
00963 ds[stack++]=qp;
00964
00965 } else if(lw==-1) {
00966
00967
00968
00969
00970
00971
00972 if(p==current_vertices) add_memory_vertices();
00973 r=1/(q-l);
00974 pts[3*p]=(pts[3*lp]*q-pts[3*qp]*l)*r;
00975 pts[3*p+1]=(pts[3*lp+1]*q-pts[3*qp+1]*l)*r;
00976 pts[3*p+2]=(pts[3*lp+2]*q-pts[3*qp+2]*l)*r;
00977 nu[p]=3;
00978 if(mec[3]==mem[3]) add_memory(3);
00979 ls=ed[qp][qs+nu[qp]];
00980 neighbor.set_pointer(p,3);
00981 neighbor.set(p,0,p_id);
00982 neighbor.copy(p,1,qp,qs);
00983 neighbor.copy(p,2,lp,ls);
00984 ed[p]=mep[3]+7*mec[3]++;
00985 ed[p][6]=p;
00986 ed[lp][ls]=p;
00987 ed[lp][nu[lp]+ls]=1;
00988 ed[p][1]=lp;
00989 ed[p][0]=cp;
00990 ed[p][nu[p]+1]=ls;
00991 ed[p][nu[p]]=cs;
00992 ed[cp][cs]=p;
00993 ed[cp][nu[cp]+cs]=0;
00994 ed[qp][qs]=-1;
00995 qs=cycle_up(qs,qp);
00996 cp=p++;
00997 cs=2;
00998 } else {
00999
01000
01001
01002
01003
01004 if(p==current_vertices) add_memory_vertices();
01005
01006
01007
01008 k=double_edge?0:1;
01009 qs=ed[qp][nu[qp]+qs];
01010 qp=lp;
01011 iqs=qs;
01012
01013
01014
01015 do {
01016 k++;
01017 qs=cycle_up(qs,qp);
01018 lp=ed[qp][qs];
01019 lw=sure.test(lp,l);
01020 } while (lw==-1);
01021
01022
01023
01024
01025
01026
01027
01028 j=-ed[qp][2*nu[qp]];
01029 if(qp==up&&qs==us) {
01030
01031
01032
01033
01034 new_double_edge=false;
01035 if(j>0) k+=nu[j];
01036 } else {
01037 if(j>0) {
01038
01039
01040
01041
01042 k+=nu[j];
01043
01044
01045
01046
01047
01048
01049 if(lw==0) {
01050
01051
01052
01053 i=-ed[lp][2*nu[lp]];
01054 if(i>0) {
01055
01056
01057
01058 if(ed[i][nu[i]-1]==j) {
01059 new_double_edge=true;
01060 k-=1;
01061 } else new_double_edge=false;
01062 } else {
01063
01064
01065
01066
01067
01068
01069
01070 if(j==rp&&lp==up&&ed[qp][nu[qp]+qs]==us) {
01071 new_double_edge=true;
01072 k-=1;
01073 } else new_double_edge=false;
01074 }
01075 } else new_double_edge=false;
01076 } else {
01077
01078
01079
01080
01081 if(lw==0) {
01082
01083
01084
01085
01086
01087
01088 i=-ed[lp][2*nu[lp]];
01089 if(i==cp) {
01090 new_double_edge=true;
01091 k-=1;
01092 } else new_double_edge=false;
01093 } else new_double_edge=false;
01094 }
01095 }
01096
01097
01098
01099
01100 while(k>=current_vertex_order) add_memory_vorder();
01101 if(mec[k]==mem[k]) add_memory(k);
01102
01103
01104
01105 if(j>0) {
01106
01107
01108
01109
01110 if(nu[j]!=k) {
01111
01112
01113 neighbor.set_aux1(k);
01114 edp=mep[k]+(2*k+1)*mec[k]++;
01115 i=0;
01116 while(i<nu[j]) {
01117 neighbor.copy_aux1(j,i);
01118 edp[i]=ed[j][i];
01119 edp[k+i]=ed[j][nu[j]+i];
01120 i++;
01121 }
01122 edp[2*k]=j;
01123
01124
01125
01126
01127 edd=mep[nu[j]]+(2*nu[j]+1)*--mec[nu[j]];
01128 if(edd!=ed[j]) {
01129 for(lw=0;lw<=2*nu[j];lw++) ed[j][lw]=edd[lw];
01130 neighbor.set_aux2_copy(j,nu[j]);
01131 neighbor.copy_pointer(edd[2*nu[j]],j);
01132 ed[edd[2*nu[j]]]=ed[j];
01133 }
01134 neighbor.set_to_aux1(j);
01135 ed[j]=edp;
01136 } else i=nu[j];
01137 } else {
01138
01139
01140 neighbor.set_pointer(p,k);
01141 ed[p]=mep[k]+(2*k+1)*mec[k]++;
01142 ed[p][2*k]=p;
01143 if(stack2==current_delete2_size) add_memory_ds2();
01144 ds2[stack2++]=qp;
01145 pts[3*p]=pts[3*qp];
01146 pts[3*p+1]=pts[3*qp+1];
01147 pts[3*p+2]=pts[3*qp+2];
01148 ed[qp][2*nu[qp]]=-p;
01149 j=p++;
01150 i=0;
01151 }
01152 nu[j]=k;
01153
01154
01155
01156
01157 if(!double_edge) {
01158 ed[j][i]=cp;
01159 ed[j][nu[j]+i]=cs;
01160 neighbor.set(j,i,p_id);
01161 ed[cp][cs]=j;
01162 ed[cp][nu[cp]+cs]=i;
01163 i++;
01164 }
01165
01166
01167
01168 qs=iqs;
01169 while(i<(new_double_edge?k:k-1)) {
01170 qs=cycle_up(qs,qp);
01171 lp=ed[qp][qs];ls=ed[qp][nu[qp]+qs];
01172 neighbor.copy(j,i,qp,qs);
01173 ed[j][i]=lp;
01174 ed[j][nu[j]+i]=ls;
01175 ed[lp][ls]=j;
01176 ed[lp][nu[lp]+ls]=i;
01177 ed[qp][qs]=-1;
01178 i++;
01179 }
01180 qs=cycle_up(qs,qp);
01181 cs=i;
01182 cp=j;
01183 neighbor.copy(j,new_double_edge?0:cs,qp,qs);
01184
01185
01186
01187 double_edge=new_double_edge;
01188 }
01189 }
01190
01191
01192 ed[cp][cs]=rp;
01193 ed[rp][0]=cp;
01194 ed[cp][nu[cp]+cs]=0;
01195 ed[rp][nu[rp]+0]=cs;
01196
01197
01198 i=0;
01199 while(i<stack) {
01200 j=ds[i];
01201 if(ed[j][nu[j]]!=-1) {
01202 ed[j][nu[j]]=-1;
01203 i++;
01204 } else ds[i]=ds[--stack];
01205 }
01206
01207
01208
01209 for(i=0;i<stack2;i++) {
01210 j=ds2[i];
01211 ed[j][2*nu[j]]=j;
01212 if(ed[j][nu[j]]!=-1) {
01213 ed[j][nu[j]]=-1;
01214 if(stack==current_delete_size) add_memory_ds();
01215 ds[stack++]=j;
01216 }
01217 }
01218
01219
01220 for(i=0;i<stack;i++) {
01221 cp=ds[i];
01222 for(j=0;j<nu[cp];j++) {
01223 qp=ed[cp][j];
01224 if(qp!=-1) {
01225 if(ed[qp][nu[qp]]!=-1) {
01226 if(stack==current_delete_size) add_memory_ds();
01227 ds[stack++]=qp;
01228 ed[qp][nu[qp]]=-1;
01229 }
01230 }
01231 }
01232 }
01233 up=0;
01234
01235
01236 while(stack>0) {
01237 while(ed[--p][nu[p]]==-1) {
01238 j=nu[p];
01239 mec[j]--;
01240 for(i=0;i<=2*j;i++) ed[p][i]=(mep[j]+(2*j+1)*mec[j])[i];
01241 neighbor.set_aux2_copy(p,j);
01242 neighbor.copy_pointer(ed[p][2*j],p);
01243 ed[ed[p][2*j]]=ed[p];
01244 }
01245 up=ds[--stack];
01246 if(up<p) {
01247
01248
01249 pts[3*up]=pts[3*p];
01250 pts[3*up+1]=pts[3*p+1];
01251 pts[3*up+2]=pts[3*p+2];
01252
01253
01254 j=nu[up];
01255 mec[j]--;
01256 for(i=0;i<=2*j;i++) ed[up][i]=(mep[j]+(2*j+1)*mec[j])[i];
01257 neighbor.set_aux2_copy(up,j);
01258 neighbor.copy_pointer(ed[up][2*j],up);
01259 neighbor.copy_pointer(up,p);
01260 ed[ed[up][2*j]]=ed[up];
01261
01262
01263 ed[up]=ed[p];
01264 nu[up]=nu[p];
01265 for(i=0;i<nu[up];i++) {
01266 if(ed[up][i]==-1)
01267 voropp_fatal_error("Dangling edge found",VOROPP_INTERNAL_ERROR);
01268 ed[ed[up][i]][ed[up][nu[up]+i]]=up;
01269 }
01270 ed[up][2*nu[up]]=up;
01271 } else up=p++;
01272 }
01273
01274
01275 if(mec[0]>0) voropp_fatal_error("Zero order vertex formed",VOROPP_INTERNAL_ERROR);
01276
01277
01278 return collapse_order2();
01279 }
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 template<class n_option>
01292 inline bool voronoicell_base<n_option>::collapse_order2() {
01293 if(!collapse_order1()) return false;
01294 int a,b,i,j,k,l;
01295 while(mec[2]>0) {
01296
01297
01298 i=--mec[2];
01299 j=mep[2][5*i];k=mep[2][5*i+1];
01300 if(j==k) {
01301 #if VOROPP_VERBOSE >=1
01302 cerr << "Order two vertex joins itself" << endl;
01303 #endif
01304 return false;
01305 }
01306
01307
01308 for(l=0;l<nu[j];l++) {
01309 if(ed[j][l]==k) break;
01310 }
01311
01312
01313
01314
01315 a=mep[2][5*i+2];b=mep[2][5*i+3];i=mep[2][5*i+4];
01316 if(l==nu[j]) {
01317 ed[j][a]=k;
01318 ed[k][b]=j;
01319 ed[j][nu[j]+a]=b;
01320 ed[k][nu[k]+b]=a;
01321 } else {
01322 if(!delete_connection(j,a,false)) return false;
01323 if(!delete_connection(k,b,true)) return false;
01324 }
01325
01326
01327 --p;
01328 if(up==i) up=0;
01329 if(p!=i) {
01330 if(up==p) up=i;
01331 pts[3*i]=pts[3*p];
01332 pts[3*i+1]=pts[3*p+1];
01333 pts[3*i+2]=pts[3*p+2];
01334 for(k=0;k<nu[p];k++) ed[ed[p][k]][ed[p][nu[p]+k]]=i;
01335 neighbor.copy_pointer(i,p);
01336 ed[i]=ed[p];
01337 nu[i]=nu[p];
01338 ed[i][2*nu[i]]=i;
01339 }
01340
01341
01342 if(!collapse_order1()) return false;
01343 }
01344 return true;
01345 }
01346
01347
01348
01349
01350
01351
01352 template<class n_option>
01353 inline bool voronoicell_base<n_option>::collapse_order1() {
01354 int i,j,k;
01355 while(mec[1]>0) {
01356 up=0;
01357 #if VOROPP_VERBOSE >=1
01358 cerr << "Order one collapse" << endl;
01359 #endif
01360 i=--mec[1];
01361 j=mep[1][3*i];k=mep[1][3*i+1];
01362 i=mep[1][3*i+2];
01363 if(!delete_connection(j,k,false)) return false;
01364 --p;
01365 if(up==i) up=0;
01366 if(p!=i) {
01367 if(up==p) up=i;
01368 pts[3*i]=pts[3*p];
01369 pts[3*i+1]=pts[3*p+1];
01370 pts[3*i+2]=pts[3*p+2];
01371 for(k=0;k<nu[p];k++) ed[ed[p][k]][ed[p][nu[p]+k]]=i;
01372 neighbor.copy_pointer(i,p);
01373 ed[i]=ed[p];
01374 nu[i]=nu[p];
01375 ed[i][2*nu[i]]=i;
01376 }
01377 }
01378 return true;
01379 }
01380
01381
01382
01383
01384
01385
01386
01387 template<class n_option>
01388 inline bool voronoicell_base<n_option>::delete_connection(int j,int k,bool hand) {
01389 int q=hand?k:cycle_up(k,j);
01390 int i=nu[j]-1,l,*edp,*edd,m;
01391 if(i<1) {
01392 cout << "Zero order vertex formed" << endl;
01393 return false;
01394 }
01395 if(mec[i]==mem[i]) add_memory(i);
01396 neighbor.set_aux1(i);
01397 for(l=0;l<q;l++) neighbor.copy_aux1(j,l);
01398 while(l<i) {
01399 neighbor.copy_aux1_shift(j,l);
01400 l++;
01401 }
01402 edp=mep[i]+(2*i+1)*mec[i]++;
01403 edp[2*i]=j;
01404 for(l=0;l<k;l++) {
01405 edp[l]=ed[j][l];
01406 edp[l+i]=ed[j][l+nu[j]];
01407 }
01408 while(l<i) {
01409 m=ed[j][l+1];
01410 edp[l]=m;
01411 k=ed[j][l+nu[j]+1];
01412 edp[l+i]=k;
01413 ed[m][nu[m]+k]--;
01414 l++;
01415 }
01416
01417 edd=mep[nu[j]]+(2*nu[j]+1)*--mec[nu[j]];
01418 for(l=0;l<=2*nu[j];l++) ed[j][l]=edd[l];
01419 neighbor.set_aux2_copy(j,nu[j]);
01420 neighbor.set_to_aux2(edd[2*nu[j]]);
01421 neighbor.set_to_aux1(j);
01422 ed[edd[2*nu[j]]]=edd;
01423 ed[j]=edp;
01424 nu[j]=i;
01425 return true;
01426 }
01427
01428
01429
01430
01431
01432
01433
01434 template<class n_option>
01435 inline bool voronoicell_base<n_option>::plane(fpoint x,fpoint y,fpoint z) {
01436 fpoint rsq=x*x+y*y+z*z;
01437 return nplane(x,y,z,rsq,0);
01438 }
01439
01440
01441
01442
01443
01444
01445 template<class n_option>
01446 inline bool voronoicell_base<n_option>::plane(fpoint x,fpoint y,fpoint z,fpoint rsq) {
01447 return nplane(x,y,z,rsq,0);
01448 }
01449
01450
01451
01452
01453
01454
01455 template<class n_option>
01456 inline bool voronoicell_base<n_option>::nplane(fpoint x,fpoint y,fpoint z,int p_id) {
01457 fpoint rsq=x*x+y*y+z*z;
01458 return nplane(x,y,z,rsq,p_id);
01459 }
01460
01461
01462
01463
01464
01465
01466 template<class n_option>
01467 inline int voronoicell_base<n_option>::cycle_up(int a,int p) {
01468 return a==nu[p]-1?0:a+1;
01469 }
01470
01471
01472
01473
01474
01475
01476 template<class n_option>
01477 inline int voronoicell_base<n_option>::cycle_down(int a,int p) {
01478 return a==0?nu[p]-1:a-1;
01479 }
01480
01481
01482
01483
01484
01485 template<class n_option>
01486 fpoint voronoicell_base<n_option>::volume() {
01487 const fpoint fe=1/48.0;
01488 fpoint vol=0;
01489 int i,j,k,l,m,n;
01490 fpoint ux,uy,uz,vx,vy,vz,wx,wy,wz;
01491 for(i=1;i<p;i++) {
01492 ux=pts[0]-pts[3*i];
01493 uy=pts[1]-pts[3*i+1];
01494 uz=pts[2]-pts[3*i+2];
01495 for(j=0;j<nu[i];j++) {
01496 k=ed[i][j];
01497 if(k>=0) {
01498 ed[i][j]=-1-k;
01499 l=cycle_up(ed[i][nu[i]+j],k);
01500 vx=pts[3*k]-pts[0];
01501 vy=pts[3*k+1]-pts[1];
01502 vz=pts[3*k+2]-pts[2];
01503 m=ed[k][l];ed[k][l]=-1-m;
01504 while(m!=i) {
01505 n=cycle_up(ed[k][nu[k]+l],m);
01506 wx=pts[3*m]-pts[0];
01507 wy=pts[3*m+1]-pts[1];
01508 wz=pts[3*m+2]-pts[2];
01509 vol+=ux*vy*wz+uy*vz*wx+uz*vx*wy-uz*vy*wx-uy*vx*wz-ux*vz*wy;
01510 k=m;l=n;vx=wx;vy=wy;vz=wz;
01511 m=ed[k][l];ed[k][l]=-1-m;
01512 }
01513 }
01514 }
01515 }
01516 reset_edges();
01517 return vol*fe;
01518 }
01519
01520
01521
01522
01523 template<class n_option>
01524 void voronoicell_base<n_option>::output_face_areas(ostream &os) {
01525 bool later=false;
01526 fpoint area;
01527 int i,j,k,l,m,n;
01528 fpoint ux,uy,uz,vx,vy,vz,wx,wy,wz;
01529 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
01530 k=ed[i][j];
01531 if(k>=0) {
01532 area=0;
01533 ed[i][j]=-1-k;
01534 l=cycle_up(ed[i][nu[i]+j],k);
01535 m=ed[k][l];ed[k][l]=-1-m;
01536 while(m!=i) {
01537 n=cycle_up(ed[k][nu[k]+l],m);
01538 ux=pts[3*k]-pts[3*i];
01539 uy=pts[3*k+1]-pts[3*i+1];
01540 uz=pts[3*k+2]-pts[3*i+2];
01541 vx=pts[3*m]-pts[3*i];
01542 vy=pts[3*m+1]-pts[3*i+1];
01543 vz=pts[3*m+2]-pts[3*i+2];
01544 wx=uy*vz-uz*vy;
01545 wy=uz*vx-ux*vz;
01546 wz=ux*vy-uy*vx;
01547 area+=sqrt(wx*wx+wy*wy+wz*wz);
01548 k=m;l=n;
01549 m=ed[k][l];ed[k][l]=-1-m;
01550 }
01551 if(later) os << " ";else later=true;
01552 os << 0.125*area;
01553 }
01554 }
01555 reset_edges();
01556 }
01557
01558
01559
01560
01561 template<class n_option>
01562 fpoint voronoicell_base<n_option>::surface_area() {
01563 fpoint area=0;
01564 int i,j,k,l,m,n;
01565 fpoint ux,uy,uz,vx,vy,vz,wx,wy,wz;
01566 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
01567 k=ed[i][j];
01568 if(k>=0) {
01569 ed[i][j]=-1-k;
01570 l=cycle_up(ed[i][nu[i]+j],k);
01571 m=ed[k][l];ed[k][l]=-1-m;
01572 while(m!=i) {
01573 n=cycle_up(ed[k][nu[k]+l],m);
01574 ux=pts[3*k]-pts[3*i];
01575 uy=pts[3*k+1]-pts[3*i+1];
01576 uz=pts[3*k+2]-pts[3*i+2];
01577 vx=pts[3*m]-pts[3*i];
01578 vy=pts[3*m+1]-pts[3*i+1];
01579 vz=pts[3*m+2]-pts[3*i+2];
01580 wx=uy*vz-uz*vy;
01581 wy=uz*vx-ux*vz;
01582 wz=ux*vy-uy*vx;
01583 area+=sqrt(wx*wx+wy*wy+wz*wz);
01584 k=m;l=n;
01585 m=ed[k][l];ed[k][l]=-1-m;
01586 }
01587 }
01588 }
01589 reset_edges();
01590 return 0.125*area;
01591 }
01592
01593
01594
01595
01596
01597
01598 template<class n_option>
01599 void voronoicell_base<n_option>::centroid(fpoint &cx,fpoint &cy,fpoint &cz) {
01600 fpoint tvol,vol=0;cx=cy=cz=0;
01601 int i,j,k,l,m,n;
01602 fpoint ux,uy,uz,vx,vy,vz,wx,wy,wz;
01603 for(i=1;i<p;i++) {
01604 ux=pts[0]-pts[3*i];
01605 uy=pts[1]-pts[3*i+1];
01606 uz=pts[2]-pts[3*i+2];
01607 for(j=0;j<nu[i];j++) {
01608 k=ed[i][j];
01609 if(k>=0) {
01610 ed[i][j]=-1-k;
01611 l=cycle_up(ed[i][nu[i]+j],k);
01612 vx=pts[3*k]-pts[0];
01613 vy=pts[3*k+1]-pts[1];
01614 vz=pts[3*k+2]-pts[2];
01615 m=ed[k][l];ed[k][l]=-1-m;
01616 while(m!=i) {
01617 n=cycle_up(ed[k][nu[k]+l],m);
01618 wx=pts[3*m]-pts[0];
01619 wy=pts[3*m+1]-pts[1];
01620 wz=pts[3*m+2]-pts[2];
01621 tvol=ux*vy*wz+uy*vz*wx+uz*vx*wy-uz*vy*wx-uy*vx*wz-ux*vz*wy;
01622 vol+=tvol;
01623 cx+=(wx+vx-ux)*tvol;
01624 cy+=(wy+vy-uy)*tvol;
01625 cz+=(wz+vz-uz)*tvol;
01626 k=m;l=n;vx=wx;vy=wy;vz=wz;
01627 m=ed[k][l];ed[k][l]=-1-m;
01628 }
01629 }
01630 }
01631 }
01632 reset_edges();
01633 if(vol>tolerance_sq) {
01634 vol=0.125/vol;
01635 cx=cx*vol+0.5*pts[0];
01636 cy=cy*vol+0.5*pts[1];
01637 cz=cz*vol+0.5*pts[2];
01638 } else cx=cy=cz=0;
01639 }
01640
01641
01642
01643
01644
01645 template<class n_option>
01646 fpoint voronoicell_base<n_option>::max_radius_squared() {
01647 int i;fpoint r,s;
01648 r=pts[0]*pts[0]+pts[1]*pts[1]+pts[2]*pts[2];
01649 for(i=3;i<3*p;i+=3) {
01650 s=pts[i]*pts[i]+pts[i+1]*pts[i+1]+pts[i+2]*pts[i+2];
01651 if(s>r) r=s;
01652 }
01653 return r;
01654 }
01655
01656
01657
01658 template<class n_option>
01659 fpoint voronoicell_base<n_option>::total_edge_distance() {
01660 int i,j,k;
01661 fpoint dis=0,dx,dy,dz;
01662 for(i=0;i<p-1;i++) for(j=0;j<nu[i];j++) {
01663 k=ed[i][j];
01664 if(k>i) {
01665 dx=pts[3*k]-pts[3*i];
01666 dy=pts[3*k+1]-pts[3*i+1];
01667 dz=pts[3*k+2]-pts[3*i+2];
01668 dis+=sqrt(dx*dx+dy*dy+dz*dz);
01669 }
01670 }
01671 return 0.5*dis;
01672 }
01673
01674
01675
01676
01677
01678
01679 template<class n_option>
01680 void voronoicell_base<n_option>::draw_pov(ostream &os,fpoint x,fpoint y,fpoint z) {
01681 int i,j,k;fpoint ux,uy,uz;
01682 for(i=0;i<p;i++) {
01683 ux=x+0.5*pts[3*i];uy=y+0.5*pts[3*i+1];uz=z+0.5*pts[3*i+2];
01684 os << "sphere{<" << ux << "," << uy << "," << uz << ">,r}\n";
01685 for(j=0;j<nu[i];j++) {
01686 k=ed[i][j];
01687 if(k<i) os << "cylinder{<" << ux << "," << uy << "," << uz << ">,<" << x+0.5*pts[3*k] << "," << y+0.5*pts[3*k+1] << "," << z+0.5*pts[3*k+2] << ">,r}\n";
01688 }
01689 }
01690 }
01691
01692
01693
01694
01695
01696
01697 template<class n_option>
01698 inline void voronoicell_base<n_option>::draw_pov(const char *filename,fpoint x,fpoint y,fpoint z) {
01699 ofstream os;
01700 os.open(filename,ofstream::out|ofstream::trunc);
01701 draw_pov(os,x,y,z);
01702 os.close();
01703 }
01704
01705
01706
01707
01708
01709 template<class n_option>
01710 inline void voronoicell_base<n_option>::draw_pov(fpoint x,fpoint y,fpoint z) {
01711 draw_pov(cout,x,y,z);
01712 }
01713
01714
01715
01716
01717
01718 template<class n_option>
01719 void voronoicell_base<n_option>::draw_gnuplot(ostream &os,fpoint x,fpoint y,fpoint z) {
01720 int i,j,k;fpoint ux,uy,uz;
01721 for(i=0;i<p;i++) {
01722 ux=x+0.5*pts[3*i];uy=y+0.5*pts[3*i+1];uz=z+0.5*pts[3*i+2];
01723 for(j=0;j<nu[i];j++) {
01724 k=ed[i][j];
01725 if(ed[i][j]<i) os << ux << " " << uy << " " << uz << "\n" << x+0.5*pts[3*k] << " " << y+0.5*pts[3*k+1] << " " << z+0.5*pts[3*k+2] << "\n\n\n";
01726 }
01727 }
01728 }
01729
01730
01731
01732
01733
01734
01735 template<class n_option>
01736 inline void voronoicell_base<n_option>::draw_gnuplot(const char *filename,fpoint x,fpoint y,fpoint z) {
01737 ofstream os;
01738 os.open(filename,ofstream::out|ofstream::trunc);
01739 draw_gnuplot(os,x,y,z);
01740 os.close();
01741 }
01742
01743
01744
01745
01746
01747 template<class n_option>
01748 inline void voronoicell_base<n_option>::draw_gnuplot(fpoint x,fpoint y,fpoint z) {
01749 draw_gnuplot(cout,x,y,z);
01750 }
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761 template<class n_option>
01762 inline void voronoicell_base<n_option>::draw_pov_mesh(ostream &os,fpoint x,fpoint y,fpoint z) {
01763 int i,j,k,l,m,n;
01764 os << "mesh2 {\nvertex_vectors {\n" << p << ",\n";
01765 for(i=0;i<p;i++) {
01766 os << "<" << x+0.5*pts[3*i] << "," << y+0.5*pts[3*i+1] << "," << z+0.5*pts[3*i+2] << ">,\n";
01767 }
01768 os << "}\nface_indices {\n" << 2*(p-2) << ",\n";
01769 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
01770 k=ed[i][j];
01771 if(k>=0) {
01772 ed[i][j]=-1-k;
01773 l=cycle_up(ed[i][nu[i]+j],k);
01774 m=ed[k][l];ed[k][l]=-1-m;
01775 while(m!=i) {
01776 n=cycle_up(ed[k][nu[k]+l],m);
01777 os << "<" << i << "," << k << "," << m << ">\n";
01778 k=m;l=n;
01779 m=ed[k][l];ed[k][l]=-1-m;
01780 }
01781 }
01782 }
01783 reset_edges();
01784 os << "}\ninside_vector <0,0,1>\n}\n";
01785 }
01786
01787
01788
01789
01790
01791
01792
01793 template<class n_option>
01794 inline void voronoicell_base<n_option>::reset_edges() {
01795 int i,j;
01796 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) {
01797 if(ed[i][j]>=0) voropp_fatal_error("Edge reset routine found a previously untested edge",VOROPP_INTERNAL_ERROR);
01798 ed[i][j]=-1-ed[i][j];
01799 }
01800 }
01801
01802
01803
01804
01805
01806
01807 template<class n_option>
01808 inline void voronoicell_base<n_option>::draw_pov_mesh(const char *filename,fpoint x,fpoint y,fpoint z) {
01809 ofstream os;
01810 os.open(filename,ofstream::out|ofstream::trunc);
01811 draw_pov_mesh(os,x,y,z);
01812 os.close();
01813 }
01814
01815
01816
01817
01818
01819 template<class n_option>
01820 inline void voronoicell_base<n_option>::draw_pov_mesh(fpoint x,fpoint y,fpoint z) {
01821 draw_pov_mesh(cout,x,y,z);
01822 }
01823
01824
01825
01826 template<class n_option>
01827 inline void voronoicell_base<n_option>::perturb(fpoint r) {
01828 for(int i=0;i<3*p;i++) pts[i]+=(2*fpoint(rand())/RAND_MAX-1)*r;
01829 }
01830
01831
01832 suretest::suretest() : current_marginal(init_marginal) {
01833 sn=new int[2*current_marginal];
01834 }
01835
01836
01837 suretest::~suretest() {
01838 delete [] sn;
01839 }
01840
01841
01842
01843
01844
01845 inline void suretest::init(fpoint x,fpoint y,fpoint z,fpoint rsq) {
01846 sc=0;px=x;py=y;pz=z;prsq=rsq;
01847 }
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859 inline int suretest::test(int n,fpoint &ans) {
01860 ans=px*p[3*n]+py*p[3*n+1]+pz*p[3*n+2]-prsq;
01861 if(ans<-tolerance2) {
01862 return -1;
01863 } else if(ans>tolerance2) {
01864 return 1;
01865 }
01866 return check_marginal(n,ans);
01867 }
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881 int suretest::check_marginal(int n,fpoint &ans) {
01882 int i;
01883 for(i=0;i<sc;i+=2) if(sn[i]==n) return sn[i+1];
01884 if(sc==2*current_marginal) {
01885 i=2*current_marginal;
01886 if(i>max_marginal) voropp_fatal_error("Marginal case buffer allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
01887 #if VOROPP_VERBOSE >=2
01888 cerr << "Marginal cases buffer scaled up to " << i << endl;
01889 #endif
01890 int *psn=new int[2*i];
01891 for(int j=0;j<2*current_marginal;j++) psn[j]=sn[j];
01892 delete [] sn;sn=psn;
01893 }
01894 sn[sc++]=n;
01895 sn[sc++]=ans>tolerance?1:(ans<-tolerance?-1:0);
01896 return sn[sc-1];
01897 }
01898
01899
01900
01901 template<class n_option>
01902 void voronoicell_base<n_option>::print_edges() {
01903 int j;
01904 for(int i=0;i<p;i++) {
01905 cout << i << " " << nu[i] << " ";
01906 for(j=0;j<nu[i];j++) cout << " " << ed[i][j];
01907 cout << " ";
01908 while(j<2*nu[i]) cout << " " << ed[i][j++];
01909 cout << " " << ed[i][j];
01910 neighbor.print_edges(i);
01911 cout << " " << pts[3*i] << " " << pts[3*i+1] << " " << pts[3*i+2];
01912 cout << " " << ed[i];
01913 if(ed[i]>=mep[nu[i]]+mec[nu[i]]*(2*nu[i]+1)) cout << " Memory error";
01914 cout << endl;
01915 }
01916 }
01917
01918
01919
01920
01921
01922 template<class n_option>
01923 void voronoicell_base<n_option>::output_normals(ostream &os) {
01924 int i,j,k;bool later=false;
01925 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) {
01926 k=ed[i][j];
01927 if(k>=0) {
01928 if(later) os << " ";
01929 else later=true;
01930 output_normals_search(os,i,j,k);
01931 }
01932 }
01933 reset_edges();
01934 }
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947 template<class n_option>
01948 inline void voronoicell_base<n_option>::output_normals_search(ostream &os,int i,int j,int k) {
01949 ed[i][j]=-1-k;
01950 int l=cycle_up(ed[i][nu[i]+j],k),m;
01951 fpoint ux,uy,uz,vx,vy,vz,wx,wy,wz,wmag;
01952 do {
01953 m=ed[k][l];ed[k][l]=-1-m;
01954 ux=pts[3*m]-pts[3*k];
01955 uy=pts[3*m+1]-pts[3*k+1];
01956 uz=pts[3*m+2]-pts[3*k+2];
01957
01958
01959 if(ux*ux+uy*uy+uz*uz>tolerance_sq) {
01960 while(m!=i) {
01961 l=cycle_up(ed[k][nu[k]+l],m);
01962 k=m;m=ed[k][l];ed[k][l]=-1-m;
01963 vx=pts[3*m]-pts[3*k];
01964 vy=pts[3*m+1]-pts[3*k+1];
01965 vz=pts[3*m+2]-pts[3*k+2];
01966
01967
01968
01969 wx=uz*vy-uy*vz;
01970 wy=ux*vz-uz*vx;
01971 wz=uy*vx-ux*vy;
01972 wmag=wx*wx+wy*wy+wz*wz;
01973
01974
01975
01976 if(wmag>tolerance_sq) {
01977
01978
01979 wmag=1/sqrt(wmag);
01980 os << "(" << wx*wmag << "," << wy*wmag << "," << wz*wmag << ")";
01981
01982
01983
01984 while(m!=i) {
01985 l=cycle_up(ed[k][nu[k]+l],m);
01986 k=m;m=ed[k][l];ed[k][l]=-1-m;
01987 }
01988 return;
01989 }
01990 }
01991 os << "(0,0,0)";
01992 return;
01993 }
01994 l=cycle_up(ed[k][nu[k]+l],m);
01995 k=m;
01996 } while (k!=i);
01997 os << "(0,0,0)";
01998 }
01999
02000
02001
02002
02003 template<class n_option>
02004 int voronoicell_base<n_option>::number_of_faces() {
02005 int i,j,k,l,m,s=0;
02006 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) {
02007 k=ed[i][j];
02008 if(k>=0) {
02009 s++;
02010 ed[i][j]=-1-k;
02011 l=cycle_up(ed[i][nu[i]+j],k);
02012 do {
02013 m=ed[k][l];
02014 ed[k][l]=-1-m;
02015 l=cycle_up(ed[k][nu[k]+l],m);
02016 k=m;
02017 } while (k!=i);
02018
02019 }
02020 }
02021 reset_edges();
02022 return s;
02023 }
02024
02025
02026
02027 template<class n_option>
02028 void voronoicell_base<n_option>::output_vertex_orders(ostream &os) {
02029 if(p==0) return;
02030 os << nu[0];
02031 for(int i=1;i<p;i++) os << " " << nu[i];
02032 }
02033
02034
02035
02036
02037 template<class n_option>
02038 void voronoicell_base<n_option>::output_vertices(ostream &os) {
02039 if(p==0) return;
02040 os << "(" << pts[0]*0.5 << "," << pts[1]*0.5 << "," << pts[2]*0.5 << ")";
02041 for(int i=3;i<3*p;i+=3) os << " (" << pts[i]*0.5 << "," << pts[i+1]*0.5 << "," << pts[i+2]*0.5 << ")";
02042 }
02043
02044
02045
02046
02047
02048
02049
02050 template<class n_option>
02051 void voronoicell_base<n_option>::output_vertices(ostream &os,fpoint x,fpoint y,fpoint z) {
02052 if(p==0) return;
02053 os << "(" << x+pts[0]*0.5 << "," << y+pts[1]*0.5 << "," << z+pts[2]*0.5 << ")";
02054 for(int i=3;i<3*p;i+=3) os << " (" << x+pts[i]*0.5 << "," << y+pts[i+1]*0.5 << "," << z+pts[i+2]*0.5 << ")";
02055 }
02056
02057
02058
02059 template<class n_option>
02060 void voronoicell_base<n_option>::output_face_perimeters(ostream &os) {
02061 int i,j,k,l,m;bool later=false;
02062 fpoint dx,dy,dz,perim;
02063 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) {
02064 k=ed[i][j];
02065 if(k>=0) {
02066 dx=pts[3*k]-pts[3*i];
02067 dy=pts[3*k+1]-pts[3*i+1];
02068 dz=pts[3*k+2]-pts[3*i+2];
02069 perim=sqrt(dx*dx+dy*dy+dz*dz);
02070 ed[i][j]=-1-k;
02071 l=cycle_up(ed[i][nu[i]+j],k);
02072 do {
02073 m=ed[k][l];
02074 dx=pts[3*m]-pts[3*k];
02075 dy=pts[3*m+1]-pts[3*k+1];
02076 dz=pts[3*m+2]-pts[3*k+2];
02077 perim+=sqrt(dx*dx+dy*dy+dz*dz);
02078 ed[k][l]=-1-m;
02079 l=cycle_up(ed[k][nu[k]+l],m);
02080 k=m;
02081 } while (k!=i);
02082 if(later) os << " ";else later=true;
02083 os << 0.5*perim;
02084 }
02085 }
02086 reset_edges();
02087 }
02088
02089
02090
02091
02092 template<class n_option>
02093 void voronoicell_base<n_option>::output_face_vertices(ostream &os) {
02094 int i,j,k,l,m;bool later=false;
02095 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) {
02096 k=ed[i][j];
02097 if(k>=0) {
02098 if(later) os << " ";else later=true;
02099 os << "(" << i;
02100 ed[i][j]=-1-k;
02101 l=cycle_up(ed[i][nu[i]+j],k);
02102 do {
02103 os << "," << k;
02104 m=ed[k][l];
02105 ed[k][l]=-1-m;
02106 l=cycle_up(ed[k][nu[k]+l],m);
02107 k=m;
02108 } while (k!=i);
02109 os << ")";
02110 }
02111 }
02112 reset_edges();
02113 }
02114
02115
02116
02117 template<class n_option>
02118 void voronoicell_base<n_option>::output_face_orders(ostream &os) {
02119 int i,j,k,l,m,q;bool later=false;
02120 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) {
02121 k=ed[i][j];
02122 if(k>=0) {
02123 q=1;
02124 ed[i][j]=-1-k;
02125 l=cycle_up(ed[i][nu[i]+j],k);
02126 do {
02127 q++;
02128 m=ed[k][l];
02129 ed[k][l]=-1-m;
02130 l=cycle_up(ed[k][nu[k]+l],m);
02131 k=m;
02132 } while (k!=i);
02133 if(later) os << " ";else later=true;
02134 os << q;
02135 }
02136 }
02137 reset_edges();
02138 }
02139
02140
02141
02142
02143 template<class n_option>
02144 void voronoicell_base<n_option>::output_face_freq_table(ostream &os) {
02145 int *stat,*pstat,current_facet_size=init_facet_size,newc,maxf=0;
02146 stat=new int[current_facet_size];
02147 int i,j,k,l,m,q;
02148 for(i=0;i<current_facet_size;i++) stat[i]=0;
02149 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) {
02150 k=ed[i][j];
02151 if(k>=0) {
02152 q=1;
02153 ed[i][j]=-1-k;
02154 l=cycle_up(ed[i][nu[i]+j],k);
02155 do {
02156 q++;
02157 m=ed[k][l];
02158 ed[k][l]=-1-m;
02159 l=cycle_up(ed[k][nu[k]+l],m);
02160 k=m;
02161 } while (k!=i);
02162 if(q>=current_facet_size) {
02163 newc=current_facet_size*2;
02164 pstat=new int[newc];
02165 for(k=0;k<current_facet_size;k++) pstat[k]=stat[k];
02166 while(k<newc) pstat[k]=0;
02167 delete [] stat;
02168 current_facet_size=newc;
02169 stat=pstat;
02170 }
02171 stat[q]++;
02172 if(q>maxf) maxf=q;
02173 }
02174 }
02175 reset_edges();
02176 os << "(0," << stat[0] << ")";
02177 for(i=1;i<=maxf;i++) os << " (" << i << "," << stat[i] << ")";
02178 delete [] stat;
02179 }
02180
02181
02182
02183
02184 template<class n_option>
02185 void voronoicell_base<n_option>::label_facets() {
02186 neighbor.label_facets();
02187 }
02188
02189
02190
02191
02192
02193
02194
02195 template<class n_option>
02196 void voronoicell_base<n_option>::output_neighbors(ostream &os,bool later) {
02197 neighbor.neighbors(os,later);
02198 }
02199
02200
02201
02202
02203
02204
02205 template<class n_option>
02206 void voronoicell_base<n_option>::check_facets() {
02207 neighbor.check_facets();
02208 }
02209
02210
02211
02212
02213
02214
02215
02216 template<class n_option>
02217 bool voronoicell_base<n_option>::plane_intersects(fpoint x,fpoint y,fpoint z,fpoint rsq) {
02218 fpoint g=x*pts[3*up]+y*pts[3*up+1]+z*pts[3*up+2];
02219 if(g<rsq) return plane_intersects_track(x,y,z,rsq,g);
02220 return true;
02221 }
02222
02223
02224
02225
02226
02227
02228
02229
02230 template<class n_option>
02231 bool voronoicell_base<n_option>::plane_intersects_guess(fpoint x,fpoint y,fpoint z,fpoint rsq) {
02232 up=0;
02233 fpoint g=x*pts[3*up]+y*pts[3*up+1]+z*pts[3*up+2];
02234 if(g<rsq) {
02235 int ca=1,cc=p>>3,mp=1;
02236 fpoint m;
02237 while(ca<cc) {
02238 m=x*pts[3*mp]+y*pts[3*mp+1]+z*pts[3*mp+2];
02239 if(m>g) {
02240 if(m>rsq) return true;
02241 g=m;up=mp;
02242 }
02243 ca+=mp++;
02244 }
02245 return plane_intersects_track(x,y,z,rsq,g);
02246 }
02247 return true;
02248 }
02249
02250
02251
02252
02253
02254
02255
02256
02257 template<class n_option>
02258 inline bool voronoicell_base<n_option>::plane_intersects_track(fpoint x,fpoint y,fpoint z,fpoint rsq,fpoint g) {
02259 int count=0,ls,us,tp;
02260 fpoint t;
02261
02262 for(us=0;us<nu[up];us++) {
02263 tp=ed[up][us];
02264 t=x*pts[3*tp]+y*pts[3*tp+1]+z*pts[3*tp+2];
02265 if(t>g) {
02266 ls=ed[up][nu[up]+us];
02267 up=tp;
02268 while (t<rsq) {
02269 if(++count>=p) {
02270 #if VOROPP_VERBOSE >=1
02271 cerr << "Bailed out of convex calculation" << endl;
02272 #endif
02273 for(tp=0;tp<p;tp++) if(x*pts[3*tp]+y*pts[3*tp+1]+z*pts[3*tp+2]>rsq) return true;
02274 return false;
02275 }
02276
02277
02278
02279
02280 for(us=0;us<ls;us++) {
02281 tp=ed[up][us];
02282 g=x*pts[3*tp]+y*pts[3*tp+1]+z*pts[3*tp+2];
02283 if(g>t) break;
02284 }
02285 if(us==ls) {
02286 us++;
02287 while(us<nu[up]) {
02288 tp=ed[up][us];
02289 g=x*pts[3*tp]+y*pts[3*tp+1]+z*pts[3*tp+2];
02290 if(g>t) break;
02291 us++;
02292 }
02293 if(us==nu[up]) return false;
02294 }
02295 ls=ed[up][nu[up]+us];up=tp;t=g;
02296 }
02297 return true;
02298 }
02299 }
02300 return false;
02301 }
02302
02303
02304
02305 template<class n_option>
02306 int voronoicell_base<n_option>::number_of_edges() {
02307 int i,edges=0;
02308 for(i=0;i<p;i++) edges+=nu[i];
02309 return edges>>1;
02310 }
02311
02312
02313
02314
02315
02316 neighbor_track::neighbor_track(voronoicell_base<neighbor_track> *ivc) : vc(ivc) {
02317 int i;
02318 mne=new int*[vc->current_vertex_order];
02319 ne=new int*[vc->current_vertices];
02320 for(i=0;i<3;i++) mne[i]=new int[init_n_vertices*i];
02321 mne[3]=new int[init_3_vertices*3];
02322 for(i=4;i<vc->current_vertex_order;i++) mne[i]=new int[init_n_vertices*i];
02323 }
02324
02325
02326
02327 neighbor_track::~neighbor_track() {
02328 for(int i=0;i<vc->current_vertex_order;i++) if(vc->mem[i]>0) delete [] mne[i];
02329 delete [] mne;
02330 delete [] ne;
02331 }
02332
02333
02334
02335
02336 inline void neighbor_track::allocate(int i,int m) {
02337 mne[i]=new int[m*i];
02338 }
02339
02340
02341
02342 inline void neighbor_track::add_memory_vertices(int i) {
02343 int **pp;
02344 pp=new int*[i];
02345 for(int j=0;j<vc->current_vertices;j++) pp[j]=ne[j];
02346 delete [] ne;ne=pp;
02347 }
02348
02349
02350
02351
02352 inline void neighbor_track::add_memory_vorder(int i) {
02353 int **p2;
02354 p2=new int*[i];
02355 for(int j=0;j<vc->current_vertex_order;j++) p2[j]=mne[j];
02356 delete [] mne;mne=p2;
02357 }
02358
02359
02360
02361 inline void neighbor_track::init() {
02362 int *q;
02363 q=mne[3];
02364 q[0]=-5;q[1]=-3;q[2]=-1;
02365 q[3]=-5;q[4]=-2;q[5]=-3;
02366 q[6]=-5;q[7]=-1;q[8]=-4;
02367 q[9]=-5;q[10]=-4;q[11]=-2;
02368 q[12]=-6;q[13]=-1;q[14]=-3;
02369 q[15]=-6;q[16]=-3;q[17]=-2;
02370 q[18]=-6;q[19]=-4;q[20]=-1;
02371 q[21]=-6;q[22]=-2;q[23]=-4;
02372 ne[0]=q;ne[1]=q+3;ne[2]=q+6;ne[3]=q+9;
02373 ne[4]=q+12;ne[5]=q+15;ne[6]=q+18;ne[7]=q+21;
02374 }
02375
02376
02377
02378 inline void neighbor_track::init_octahedron() {
02379 int *q;
02380 q=mne[4];
02381 q[0]=-5;q[1]=-6;q[2]=-7;q[3]=-8;
02382 q[4]=-1;q[5]=-2;q[6]=-3;q[7]=-4;
02383 q[8]=-6;q[9]=-5;q[10]=-2;q[11]=-1;
02384 q[12]=-8;q[13]=-7;q[14]=-4;q[15]=-3;
02385 q[16]=-5;q[17]=-8;q[18]=-3;q[19]=-2;
02386 q[20]=-7;q[21]=-6;q[22]=-1;q[23]=-4;
02387 ne[0]=q;ne[1]=q+4;ne[2]=q+8;ne[3]=q+12;ne[4]=q+16;ne[5]=q+20;
02388 }
02389
02390
02391
02392 inline void neighbor_track::init_tetrahedron() {
02393 int *q;
02394 q=mne[3];
02395 q[0]=-4;q[1]=-3;q[2]=-2;
02396 q[3]=-3;q[4]=-4;q[5]=-1;
02397 q[6]=-4;q[7]=-2;q[8]=-1;
02398 q[9]=-2;q[10]=-3;q[11]=-1;
02399 ne[0]=q;ne[1]=q+3;ne[2]=q+6;ne[3]=q+9;
02400 }
02401
02402
02403
02404
02405 inline void neighbor_track::set_pointer(int p,int n) {
02406 ne[p]=mne[n]+n*vc->mec[n];
02407 }
02408
02409
02410 inline void neighbor_track::copy(int a,int b,int c,int d) {
02411 ne[a][b]=ne[c][d];
02412 }
02413
02414
02415 inline void neighbor_track::set(int a,int b,int c) {
02416 ne[a][b]=c;
02417 }
02418
02419
02420
02421 inline void neighbor_track::set_aux1(int k) {
02422 paux1=mne[k]+k*vc->mec[k];
02423 }
02424
02425
02426 inline void neighbor_track::copy_aux1(int a,int b) {
02427 paux1[b]=ne[a][b];
02428 }
02429
02430
02431
02432 inline void neighbor_track::copy_aux1_shift(int a,int b) {
02433 paux1[b]=ne[a][b+1];
02434 }
02435
02436
02437
02438 inline void neighbor_track::set_aux2_copy(int a,int b) {
02439 paux2=mne[b]+b*vc->mec[b];
02440 for(int i=0;i<b;i++) ne[a][i]=paux2[i];
02441 }
02442
02443
02444 inline void neighbor_track::copy_pointer(int a,int b) {
02445 ne[a]=ne[b];
02446 }
02447
02448
02449 inline void neighbor_track::set_to_aux1(int j) {
02450 ne[j]=paux1;
02451 }
02452
02453
02454 inline void neighbor_track::set_to_aux2(int j) {
02455 ne[j]=paux2;
02456 }
02457
02458
02459 inline void neighbor_track::print_edges(int i) {
02460 cout << " (";
02461 for(int j=0;j<vc->nu[i];j++) {
02462 cout << ne[i][j] << (j==vc->nu[i]-1?")":",");
02463 }
02464 }
02465
02466
02467 inline void neighbor_track::allocate_aux1(int i) {
02468 paux1=new int[i*vc->mem[i]];
02469 }
02470
02471
02472
02473 inline void neighbor_track::switch_to_aux1(int i) {
02474 delete [] mne[i];
02475 mne[i]=paux1;
02476 }
02477
02478
02479 inline void neighbor_track::copy_to_aux1(int i,int m) {
02480 paux1[m]=mne[i][m];
02481 }
02482
02483
02484 inline void neighbor_track::set_to_aux1_offset(int k,int m) {
02485 ne[k]=paux1+m;
02486 }
02487
02488
02489
02490 void neighbor_track::check_facets() {
02491 int **edp,*nup;edp=vc->ed;nup=vc->nu;
02492 int i,j,k,l,m,q;
02493 for(i=0;i<vc->p;i++) for(j=0;j<nup[i];j++) {
02494 k=edp[i][j];
02495 if(k>=0) {
02496 edp[i][j]=-1-k;
02497 q=ne[i][j];
02498 l=vc->cycle_up(edp[i][nup[i]+j],k);
02499 do {
02500 m=edp[k][l];
02501 edp[k][l]=-1-m;
02502 if(ne[k][l]!=q) cerr << "Facet error at (" << k << "," << l << ")=" << ne[k][l] << ", started from (" << i << "," << j << ")=" << q << endl;
02503 l=vc->cycle_up(edp[k][nup[k]+l],m);
02504 k=m;
02505 } while (k!=i);
02506 }
02507 }
02508 vc->reset_edges();
02509 }
02510
02511
02512
02513
02514
02515 void neighbor_track::neighbors(ostream &os,bool later) {
02516 int **edp=vc->ed,*nup=vc->nu;
02517 int i,j,k,l,m;
02518 for(i=0;i<vc->p;i++) for(j=0;j<nup[i];j++) {
02519 k=edp[i][j];
02520 if(k>=0) {
02521 if(later) os << " ";else later=true;
02522 os << ne[i][j];
02523 edp[i][j]=-1-k;
02524 l=vc->cycle_up(edp[i][nup[i]+j],k);
02525 do {
02526 m=edp[k][l];
02527 edp[k][l]=-1-m;
02528 l=vc->cycle_up(edp[k][nup[k]+l],m);
02529 k=m;
02530 } while (k!=i);
02531 }
02532 }
02533 vc->reset_edges();
02534 }
02535
02536
02537 void neighbor_track::label_facets() {
02538 int **edp,*nup;edp=vc->ed;nup=vc->nu;
02539 int i,j,k,l,m,q=1;
02540 for(i=0;i<vc->p;i++) for(j=0;j<nup[i];j++) {
02541 k=edp[i][j];
02542 if(k>=0) {
02543 edp[i][j]=-1-k;
02544 ne[i][j]=q;
02545 l=vc->cycle_up(edp[i][nup[i]+j],k);
02546 do {
02547 m=edp[k][l];
02548 edp[k][l]=-1-m;
02549 ne[k][l]=q;
02550 l=vc->cycle_up(edp[k][nup[k]+l],m);
02551 k=m;
02552 } while (k!=i);
02553 q++;
02554 }
02555 }
02556 vc->reset_edges();
02557 }