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