Bugfix in search_for_outside_edge routine.
[voro++.git] / branches / exact / src / cell.cc
blob9aff884fcc950f98f1d162ba1be7cbf4cdae2839
1 // Voro++, a 3D cell-based Voronoi library
2 //
3 // Author : Chris H. Rycroft (LBL / UC Berkeley)
4 // Email : chr@alum.mit.edu
5 // Date : August 30th 2011
7 /** \file cell.cc
8 * \brief Function implementations for the voronoicell and related classes. */
10 #include <cstring>
11 using namespace std;
13 #include "config.hh"
14 #include "common.hh"
15 #include "cell.hh"
17 namespace voro {
19 /** Constructs a Voronoi cell and sets up the initial memory. */
20 voronoicell_base::voronoicell_base() :
21 current_vertices(init_vertices), current_vertex_order(init_vertex_order),
22 current_delete_size(init_delete_size), current_delete2_size(init_delete2_size),
23 ed(new int*[current_vertices]), nu(new int[current_vertices]),
24 pts(new double[3*current_vertices]), ptsq(new mpq_class[3*current_vertices]),
25 synced(false), mem(new int[current_vertex_order]),
26 mec(new int[current_vertex_order]), mep(new int*[current_vertex_order]),
27 ds(new int[current_delete_size]), stacke(ds+current_delete_size),
28 ds2(new int[current_delete2_size]), stacke2(ds2+current_delete_size),
29 current_marginal(init_marginal), marg(new int[current_marginal]) {
30 int i;
31 for(i=0;i<3;i++) {
32 mem[i]=init_n_vertices;mec[i]=0;
33 mep[i]=new int[init_n_vertices*((i<<1)+1)];
35 mem[3]=init_3_vertices;mec[3]=0;
36 mep[3]=new int[init_3_vertices*7];
37 for(i=4;i<current_vertex_order;i++) {
38 mem[i]=init_n_vertices;mec[i]=0;
39 mep[i]=new int[init_n_vertices*((i<<1)+1)];
43 /** The voronoicell destructor deallocates all the dynamic memory. */
44 voronoicell_base::~voronoicell_base() {
45 for(int i=current_vertex_order-1;i>=0;i--) if(mem[i]>0) delete [] mep[i];
46 delete [] marg;
47 delete [] ds2;delete [] ds;
48 delete [] mep;delete [] mec;
49 delete [] mem;delete [] ptsq;delete [] pts;
50 delete [] nu;delete [] ed;
53 /** Ensures that enough memory is allocated prior to carrying out a copy.
54 * \param[in] vc a reference to the specialized version of the calling class.
55 * \param[in] vb a pointered to the class to be copied. */
56 template<class vc_class>
57 void voronoicell_base::check_memory_for_copy(vc_class &vc,voronoicell_base* vb) {
58 while(current_vertex_order<vb->current_vertex_order) add_memory_vorder(vc);
59 for(int i=0;i<current_vertex_order;i++) while(mem[i]<vb->mec[i]) add_memory(vc,i,ds2);
60 while(current_vertices<vb->p) add_memory_vertices(vc);
63 /** Copies the vertex and edge information from another class. The routine
64 * assumes that enough memory is available for the copy.
65 * \param[in] vb a pointer to the class to copy. */
66 void voronoicell_base::copy(voronoicell_base* vb) {
67 int i,j;
68 p=vb->p;up=0;
69 for(i=0;i<current_vertex_order;i++) {
70 mec[i]=vb->mec[i];
71 for(j=0;j<mec[i]*(2*i+1);j++) mep[i][j]=vb->mep[i][j];
72 for(j=0;j<mec[i]*(2*i+1);j+=2*i+1) ed[mep[i][j+2*i]]=mep[i]+j;
74 for(i=0;i<p;i++) nu[i]=vb->nu[i];
75 for(i=0;i<3*p;i++) ptsq[i]=vb->ptsq[i];
76 synced=false;
79 /** Copies the information from another voronoicell class into this
80 * class, extending memory allocation if necessary.
81 * \param[in] c the class to copy. */
82 void voronoicell_neighbor::operator=(voronoicell &c) {
83 voronoicell_base *vb=((voronoicell_base*) &c);
84 check_memory_for_copy(*this,vb);copy(vb);
85 int i,j;
86 for(i=0;i<c.current_vertex_order;i++) {
87 for(j=0;j<c.mec[i]*i;j++) mne[i][j]=0;
88 for(j=0;j<c.mec[i];j++) ne[c.mep[i][(2*i+1)*j+2*i]]=mne[i]+(j*i);
92 /** Copies the information from another voronoicell_neighbor class into this
93 * class, extending memory allocation if necessary.
94 * \param[in] c the class to copy. */
95 void voronoicell_neighbor::operator=(voronoicell_neighbor &c) {
96 voronoicell_base *vb=((voronoicell_base*) &c);
97 check_memory_for_copy(*this,vb);copy(vb);
98 int i,j;
99 for(i=0;i<c.current_vertex_order;i++) {
100 for(j=0;j<c.mec[i]*i;j++) mne[i][j]=c.mne[i][j];
101 for(j=0;j<c.mec[i];j++) ne[c.mep[i][(2*i+1)*j+2*i]]=mne[i]+(j*i);
105 /** Translates the vertices of the Voronoi cell by a given vector.
106 * \param[in] (x,y,z) the coordinates of the vector. */
107 void voronoicell_base::translate(double x,double y,double z) {
108 x*=2;y*=2;z*=2;
109 synced=false;
110 double *ptsp=pts;
111 while(ptsp<pts+3*p) {
112 *(ptsp++)=x;*(ptsp++)=y;*(ptsp++)=z;
116 /** Increases the memory storage for a particular vertex order, by increasing
117 * the size of the of the corresponding mep array. If the arrays already exist,
118 * their size is doubled; if they don't exist, then new ones of size
119 * init_n_vertices are allocated. The routine also ensures that the pointers in
120 * the ed array are updated, by making use of the back pointers. For the cases
121 * where the back pointer has been temporarily overwritten in the marginal
122 * vertex code, the auxiliary delete stack is scanned to find out how to update
123 * the ed value. If the template has been instantiated with the neighbor
124 * tracking turned on, then the routine also reallocates the corresponding mne
125 * array.
126 * \param[in] i the order of the vertex memory to be increased. */
127 template<class vc_class>
128 void voronoicell_base::add_memory(vc_class &vc,int i,int *stackp2) {
129 int s=(i<<1)+1;
130 if(mem[i]==0) {
131 vc.n_allocate(i,init_n_vertices);
132 mep[i]=new int[init_n_vertices*s];
133 mem[i]=init_n_vertices;
134 #if VOROPP_VERBOSE >=2
135 fprintf(stderr,"Order %d vertex memory created\n",i);
136 #endif
137 } else {
138 int j=0,k,*l;
139 mem[i]<<=1;
140 if(mem[i]>max_n_vertices) voro_fatal_error("Point memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
141 #if VOROPP_VERBOSE >=2
142 fprintf(stderr,"Order %d vertex memory scaled up to %d\n",i,mem[i]);
143 #endif
144 l=new int[s*mem[i]];
145 int m=0;
146 vc.n_allocate_aux1(i);
147 while(j<s*mec[i]) {
148 k=mep[i][j+(i<<1)];
149 if(k>=0) {
150 ed[k]=l+j;
151 vc.n_set_to_aux1_offset(k,m);
152 } else {
153 int *dsp;
154 for(dsp=ds2;dsp<stackp2;dsp++) {
155 if(ed[*dsp]==mep[i]+j) {
156 ed[*dsp]=l+j;
157 vc.n_set_to_aux1_offset(*dsp,m);
158 break;
161 if(dsp==stackp2) voro_fatal_error("Couldn't relocate dangling pointer",VOROPP_INTERNAL_ERROR);
162 #if VOROPP_VERBOSE >=3
163 fputs("Relocated dangling pointer",stderr);
164 #endif
166 for(k=0;k<s;k++,j++) l[j]=mep[i][j];
167 for(k=0;k<i;k++,m++) vc.n_copy_to_aux1(i,m);
169 delete [] mep[i];
170 mep[i]=l;
171 vc.n_switch_to_aux1(i);
175 /** Doubles the maximum number of vertices allowed, by reallocating the ed, nu,
176 * and pts arrays. If the allocation exceeds the absolute maximum set in
177 * max_vertices, then the routine exits with a fatal error. If the template has
178 * been instantiated with the neighbor tracking turned on, then the routine
179 * also reallocates the ne array. */
180 template<class vc_class>
181 void voronoicell_base::add_memory_vertices(vc_class &vc) {
182 int i=(current_vertices<<1),j,**pp,*pnu;
183 if(i>max_vertices) voro_fatal_error("Vertex memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
184 #if VOROPP_VERBOSE >=2
185 fprintf(stderr,"Vertex memory scaled up to %d\n",i);
186 #endif
187 pp=new int*[i];
188 for(j=0;j<current_vertices;j++) pp[j]=ed[j];
189 delete [] ed;ed=pp;
190 vc.n_add_memory_vertices(i);
191 pnu=new int[i];
192 for(j=0;j<current_vertices;j++) pnu[j]=nu[j];
193 delete [] nu;nu=pnu;
194 mpq_class *pptsq=new mpq_class[3*i];
195 for(j=0;j<3*current_vertices;j++) pptsq[j]=ptsq[j];
196 delete [] ptsq;ptsq=pptsq;
197 double *ppts=new double[3*i];
198 for(j=0;j<3*current_vertices;j++) ppts[j]=pts[j];
199 delete [] pts;pts=ppts;
200 current_vertices=i;
203 /** Doubles the maximum allowed vertex order, by reallocating mem, mep, and mec
204 * arrays. If the allocation exceeds the absolute maximum set in
205 * max_vertex_order, then the routine causes a fatal error. If the template has
206 * been instantiated with the neighbor tracking turned on, then the routine
207 * also reallocates the mne array. */
208 template<class vc_class>
209 void voronoicell_base::add_memory_vorder(vc_class &vc) {
210 int i=(current_vertex_order<<1),j,*p1,**p2;
211 if(i>max_vertex_order) voro_fatal_error("Vertex order memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
212 #if VOROPP_VERBOSE >=2
213 fprintf(stderr,"Vertex order memory scaled up to %d\n",i);
214 #endif
215 p1=new int[i];
216 for(j=0;j<current_vertex_order;j++) p1[j]=mem[j];while(j<i) p1[j++]=0;
217 delete [] mem;mem=p1;
218 p2=new int*[i];
219 for(j=0;j<current_vertex_order;j++) p2[j]=mep[j];
220 delete [] mep;mep=p2;
221 p1=new int[i];
222 for(j=0;j<current_vertex_order;j++) p1[j]=mec[j];while(j<i) p1[j++]=0;
223 delete [] mec;mec=p1;
224 vc.n_add_memory_vorder(i);
225 current_vertex_order=i;
228 /** Doubles the size allocation of the main delete stack. If the allocation
229 * exceeds the absolute maximum set in max_delete_size, then routine causes a
230 * fatal error. */
231 void voronoicell_base::add_memory_ds(int *&stackp) {
232 current_delete_size<<=1;
233 if(current_delete_size>max_delete_size) voro_fatal_error("Delete stack 1 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
234 #if VOROPP_VERBOSE >=2
235 fprintf(stderr,"Delete stack 1 memory scaled up to %d\n",current_delete_size);
236 #endif
237 int *dsn=new int[current_delete_size],*dsnp=dsn,*dsp=ds;
238 while(dsp<stackp) *(dsnp++)=*(dsp++);
239 delete [] ds;ds=dsn;stackp=dsnp;
240 stacke=ds+current_delete_size;
243 /** Doubles the size allocation of the auxiliary delete stack. If the
244 * allocation exceeds the absolute maximum set in max_delete2_size, then the
245 * routine causes a fatal error. */
246 void voronoicell_base::add_memory_ds2(int *&stackp2) {
247 current_delete2_size<<=1;
248 if(current_delete2_size>max_delete2_size) voro_fatal_error("Delete stack 2 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR);
249 #if VOROPP_VERBOSE >=2
250 fprintf(stderr,"Delete stack 2 memory scaled up to %d\n",current_delete2_size);
251 #endif
252 int *dsn=new int[current_delete2_size],*dsnp=dsn,*dsp=ds2;
253 while(dsp<stackp2) *(dsnp++)=*(dsp++);
254 delete [] ds2;ds2=dsn;stackp2=dsnp;
255 stacke2=ds2+current_delete2_size;
258 /** Initializes a Voronoi cell as a rectangular box with the given dimensions.
259 * \param[in] (xmin,xmax) the minimum and maximum x coordinates.
260 * \param[in] (ymin,ymax) the minimum and maximum y coordinates.
261 * \param[in] (zmin,zmax) the minimum and maximum z coordinates. */
262 void voronoicell_base::init_base(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax) {
263 for(int i=0;i<current_vertex_order;i++) mec[i]=0;up=0;
264 mec[3]=p=8;xmin*=2;xmax*=2;ymin*=2;ymax*=2;zmin*=2;zmax*=2;
265 *ptsq=xmin;ptsq[1]=ymin;ptsq[2]=zmin;
266 ptsq[3]=xmax;ptsq[4]=ymin;ptsq[5]=zmin;
267 ptsq[6]=xmin;ptsq[7]=ymax;ptsq[8]=zmin;
268 ptsq[9]=xmax;ptsq[10]=ymax;ptsq[11]=zmin;
269 ptsq[12]=xmin;ptsq[13]=ymin;ptsq[14]=zmax;
270 ptsq[15]=xmax;ptsq[16]=ymin;ptsq[17]=zmax;
271 ptsq[18]=xmin;ptsq[19]=ymax;ptsq[20]=zmax;
272 ptsq[21]=xmax;ptsq[22]=ymax;ptsq[23]=zmax;
273 int *q=mep[3];
274 *q=1;q[1]=4;q[2]=2;q[3]=2;q[4]=1;q[5]=0;q[6]=0;
275 q[7]=3;q[8]=5;q[9]=0;q[10]=2;q[11]=1;q[12]=0;q[13]=1;
276 q[14]=0;q[15]=6;q[16]=3;q[17]=2;q[18]=1;q[19]=0;q[20]=2;
277 q[21]=2;q[22]=7;q[23]=1;q[24]=2;q[25]=1;q[26]=0;q[27]=3;
278 q[28]=6;q[29]=0;q[30]=5;q[31]=2;q[32]=1;q[33]=0;q[34]=4;
279 q[35]=4;q[36]=1;q[37]=7;q[38]=2;q[39]=1;q[40]=0;q[41]=5;
280 q[42]=7;q[43]=2;q[44]=4;q[45]=2;q[46]=1;q[47]=0;q[48]=6;
281 q[49]=5;q[50]=3;q[51]=6;q[52]=2;q[53]=1;q[54]=0;q[55]=7;
282 *ed=q;ed[1]=q+7;ed[2]=q+14;ed[3]=q+21;
283 ed[4]=q+28;ed[5]=q+35;ed[6]=q+42;ed[7]=q+49;
284 *nu=nu[1]=nu[2]=nu[3]=nu[4]=nu[5]=nu[6]=nu[7]=3;
285 synced=false;
288 /** Initializes a Voronoi cell as a regular octahedron.
289 * \param[in] l The distance from the octahedron center to a vertex. Six
290 * vertices are initialized at (-l,0,0), (l,0,0), (0,-l,0),
291 * (0,l,0), (0,0,-l), and (0,0,l). */
292 void voronoicell_base::init_octahedron_base(double l) {
293 for(int i=0;i<current_vertex_order;i++) mec[i]=0;up=0;
294 mec[4]=p=6;l*=2;
295 *ptsq=-l;ptsq[1]=0;ptsq[2]=0;
296 ptsq[3]=l;ptsq[4]=0;ptsq[5]=0;
297 ptsq[6]=0;ptsq[7]=-l;ptsq[8]=0;
298 ptsq[9]=0;ptsq[10]=l;ptsq[11]=0;
299 ptsq[12]=0;ptsq[13]=0;ptsq[14]=-l;
300 ptsq[15]=0;ptsq[16]=0;ptsq[17]=l;
301 int *q=mep[4];
302 *q=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;
303 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;
304 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;
305 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;
306 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;
307 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;
308 *ed=q;ed[1]=q+9;ed[2]=q+18;ed[3]=q+27;ed[4]=q+36;ed[5]=q+45;
309 *nu=nu[1]=nu[2]=nu[3]=nu[4]=nu[5]=4;
310 synced=false;
313 /** Initializes a Voronoi cell as a tetrahedron. It assumes that the normal to
314 * the face for the first three vertices points inside.
315 * \param (x0,y0,z0) a position vector for the first vertex.
316 * \param (x1,y1,z1) a position vector for the second vertex.
317 * \param (x2,y2,z2) a position vector for the third vertex.
318 * \param (x3,y3,z3) a position vector for the fourth vertex. */
319 void voronoicell_base::init_tetrahedron_base(double x0,double y0,double z0,double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3) {
320 for(int i=0;i<current_vertex_order;i++) mec[i]=0;up=0;
321 mec[3]=p=4;
322 *ptsq=x0*2;ptsq[1]=y0*2;ptsq[2]=z0*2;
323 ptsq[3]=x1*2;ptsq[4]=y1*2;ptsq[5]=z1*2;
324 ptsq[6]=x2*2;ptsq[7]=y2*2;ptsq[8]=z2*2;
325 ptsq[9]=x3*2;ptsq[10]=y3*2;ptsq[11]=z3*2;
326 int *q=mep[3];
327 *q=1;q[1]=3;q[2]=2;q[3]=0;q[4]=0;q[5]=0;q[6]=0;
328 q[7]=0;q[8]=2;q[9]=3;q[10]=0;q[11]=2;q[12]=1;q[13]=1;
329 q[14]=0;q[15]=3;q[16]=1;q[17]=2;q[18]=2;q[19]=1;q[20]=2;
330 q[21]=0;q[22]=1;q[23]=2;q[24]=1;q[25]=2;q[26]=1;q[27]=3;
331 *ed=q;ed[1]=q+7;ed[2]=q+14;ed[3]=q+21;
332 *nu=nu[1]=nu[2]=nu[3]=3;
335 /** Checks that the relational table of the Voronoi cell is accurate, and
336 * prints out any errors. This algorithm is O(p), so running it every time the
337 * plane routine is called will result in a significant slowdown. */
338 void voronoicell_base::check_relations() {
339 int i,j;
340 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) if(ed[ed[i][j]][ed[i][nu[i]+j]]!=i)
341 printf("Relational error at point %d, edge %d.\n",i,j);
344 /** This routine checks for any two vertices that are connected by more than
345 * one edge. The plane algorithm is designed so that this should not happen, so
346 * any occurrences are most likely errors. Note that the routine is O(p), so
347 * running it every time the plane routine is called will result in a
348 * significant slowdown. */
349 void voronoicell_base::check_duplicates() {
350 int i,j,k;
351 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])
352 printf("Duplicate edges: (%d,%d) and (%d,%d) [%d]\n",i,j,i,k,ed[i][j]);
355 /** Constructs the relational table if the edges have been specified. */
356 void voronoicell_base::construct_relations() {
357 int i,j,k,l;
358 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) {
359 k=ed[i][j];
360 l=0;
361 while(ed[k][l]!=i) {
362 l++;
363 if(l==nu[k]) voro_fatal_error("Relation table construction failed",VOROPP_INTERNAL_ERROR);
365 ed[i][nu[i]+j]=l;
369 /** Cuts the Voronoi cell by a particle whose center is at a separation of
370 * (x,y,z) from the cell center. The value of rsq should be initially set to
371 * \f$x^2+y^2+z^2\f$.
372 * \param[in] vc a reference to the specialized version of the calling class.
373 * \param[in] (x,y,z) the normal vector to the plane.
374 * \param[in] rsq the distance along this vector of the plane.
375 * \param[in] p_id the plane ID (for neighbor tracking only).
376 * \return False if the plane cut deleted the cell entirely, true otherwise. */
377 template<class vc_class>
378 bool voronoicell_base::nplane(vc_class &vc,double x,double y,double z,double rsq,int p_id) {
379 int count=0,i,j,k,lp=up,cp,qp,rp,*stackp(ds),*stackp2(ds2),*dsp;
380 int us=0,ls=0,qs,iqs,cs,uw,qw,lw;
381 int *edp,*edd;
382 mpq_class u,l,r,q;bool complicated_setup=false,new_double_edge=false,double_edge=false;
384 // Initialize the safe testing routine
385 n_marg=0;px=x;py=y;pz=z;prsq=rsq;
387 // Test approximately sqrt(n)/4 points for their proximity to the plane
388 // and keep the one which is closest
389 uw=m_test(up,u);
391 // Starting from an initial guess, we now move from vertex to vertex,
392 // to try and find an edge which intersects the cutting plane,
393 // or a vertex which is on the plane
394 try {
395 if(uw==1) {
397 // The test point is inside the cutting plane.
398 us=0;
399 do {
400 lp=ed[up][us];
401 lw=m_test(lp,l);
402 if(l<u) break;
403 us++;
404 } while (us<nu[up]);
406 if(us==nu[up]) {
407 return false;
410 ls=ed[up][nu[up]+us];
411 while(lw==1) {
412 if(++count>=p) throw true;
413 u=l;up=lp;
414 for(us=0;us<ls;us++) {
415 lp=ed[up][us];
416 lw=m_test(lp,l);
417 if(l<u) break;
419 if(us==ls) {
420 us++;
421 while(us<nu[up]) {
422 lp=ed[up][us];
423 lw=m_test(lp,l);
424 if(l<u) break;
425 us++;
427 if(us==nu[up]) {
428 return false;
431 ls=ed[up][nu[up]+us];
434 // If the last point in the iteration is within the
435 // plane, we need to do the complicated setup
436 // routine. Otherwise, we use the regular iteration.
437 if(lw==0) {
438 up=lp;
439 complicated_setup=true;
440 } else complicated_setup=false;
441 } else if(uw==-1) {
442 us=0;
443 do {
444 qp=ed[up][us];
445 qw=m_test(qp,q);
446 if(u<q) break;
447 us++;
448 } while (us<nu[up]);
449 if(us==nu[up]) return true;
451 while(qw==-1) {
452 qs=ed[up][nu[up]+us];
453 if(++count>=p) throw true;
454 u=q;up=qp;
455 for(us=0;us<qs;us++) {
456 qp=ed[up][us];
457 qw=m_test(qp,q);
458 if(u<q) break;
460 if(us==qs) {
461 us++;
462 while(us<nu[up]) {
463 qp=ed[up][us];
464 qw=m_test(qp,q);
465 if(u<q) break;
466 us++;
468 if(us==nu[up]) return true;
471 if(qw==1) {
472 lp=up;ls=us;l=u;
473 up=qp;us=ed[lp][nu[lp]+ls];u=q;
474 complicated_setup=false;
475 } else {
476 up=qp;
477 complicated_setup=true;
479 } else {
481 // Our original test point was on the plane, so we
482 // automatically head for the complicated setup
483 // routine
484 complicated_setup=true;
487 catch(bool except) {
488 // This routine is a fall-back, in case floating point errors
489 // cause the usual search routine to fail. In the fall-back
490 // routine, we just test every edge to find one straddling
491 // the plane.
492 #if VOROPP_VERBOSE >=1
493 fputs("Bailed out of convex calculation\n",stderr);
494 #endif
495 qw=1;lw=0;
496 for(qp=0;qp<p;qp++) {
497 qw=m_test(qp,q);
498 if(qw==1) {
500 // The point is inside the cutting space. Now
501 // see if we can find a neighbor which isn't.
502 for(us=0;us<nu[qp];us++) {
503 lp=ed[qp][us];
504 if(lp<qp) {
505 lw=m_test(lp,l);
506 if(lw!=1) break;
509 if(us<nu[qp]) {
510 up=qp;
511 if(lw==0) {
512 complicated_setup=true;
513 } else {
514 complicated_setup=false;
515 u=q;
516 ls=ed[up][nu[up]+us];
518 break;
520 } else if(qw==-1) {
522 // The point is outside the cutting space. See
523 // if we can find a neighbor which isn't.
524 for(ls=0;ls<nu[qp];ls++) {
525 up=ed[qp][ls];
526 if(up<qp) {
527 uw=m_test(up,u);
528 if(uw!=-1) break;
531 if(ls<nu[qp]) {
532 if(uw==0) {
533 up=qp;
534 complicated_setup=true;
535 } else {
536 complicated_setup=false;
537 lp=qp;l=q;
538 us=ed[lp][nu[lp]+ls];
540 break;
542 } else {
544 // The point is in the plane, so we just
545 // proceed with the complicated setup routine
546 up=qp;
547 complicated_setup=true;
548 break;
551 if(qp==p) return qw==-1?true:false;
554 synced=false;
556 // We're about to add the first point of the new facet. In either
557 // routine, we have to add a point, so first check there's space for
558 // it.
559 if(p==current_vertices) add_memory_vertices(vc);
561 if(complicated_setup) {
563 // The search algorithm found a point which is on the cutting
564 // plane. We leave that point in place, and create a new one at
565 // the same location.
566 ptsq[3*p]=ptsq[3*up];
567 ptsq[3*p+1]=ptsq[3*up+1];
568 ptsq[3*p+2]=ptsq[3*up+2];
570 // Search for a collection of edges of the test vertex which
571 // are outside of the cutting space. Begin by testing the
572 // zeroth edge.
573 i=0;
574 lp=*ed[up];
575 lw=m_test(lp,l);
576 if(lw!=-1) {
578 // The first edge is either inside the cutting space,
579 // or lies within the cutting plane. Test the edges
580 // sequentially until we find one that is outside.
581 rp=lw;
582 do {
583 i++;
585 // If we reached the last edge with no luck
586 // then all of the vertices are inside
587 // or on the plane, so the cell is completely
588 // deleted
589 if(i==nu[up]) return false;
590 lp=ed[up][i];
591 lw=m_test(lp,l);
592 } while (lw!=-1);
593 j=i+1;
595 // We found an edge outside the cutting space. Keep
596 // moving through these edges until we find one that's
597 // inside or on the plane.
598 while(j<nu[up]) {
599 lp=ed[up][j];
600 lw=m_test(lp,l);
601 if(lw!=-1) break;
602 j++;
605 // Compute the number of edges for the new vertex. In
606 // general it will be the number of outside edges
607 // found, plus two. But we need to recognize the
608 // special case when all but one edge is outside, and
609 // the remaining one is on the plane. For that case we
610 // have to reduce the edge count by one to prevent
611 // doubling up.
612 if(j==nu[up]&&i==1&&rp==0) {
613 nu[p]=nu[up];
614 double_edge=true;
615 } else nu[p]=j-i+2;
616 k=1;
618 // Add memory for the new vertex if needed, and
619 // initialize
620 while (nu[p]>=current_vertex_order) add_memory_vorder(vc);
621 if(mec[nu[p]]==mem[nu[p]]) add_memory(vc,nu[p],stackp2);
622 vc.n_set_pointer(p,nu[p]);
623 ed[p]=mep[nu[p]]+((nu[p]<<1)+1)*mec[nu[p]]++;
624 ed[p][nu[p]<<1]=p;
626 // Copy the edges of the original vertex into the new
627 // one. Delete the edges of the original vertex, and
628 // update the relational table.
629 us=cycle_down(i,up);
630 while(i<j) {
631 qp=ed[up][i];
632 qs=ed[up][nu[up]+i];
633 vc.n_copy(p,k,up,i);
634 ed[p][k]=qp;
635 ed[p][nu[p]+k]=qs;
636 ed[qp][qs]=p;
637 ed[qp][nu[qp]+qs]=k;
638 ed[up][i]=-1;
639 i++;k++;
641 qs=i==nu[up]?0:i;
642 } else {
644 // In this case, the zeroth edge is outside the cutting
645 // plane. Begin by searching backwards from the last
646 // edge until we find an edge which isn't outside.
647 i=nu[up]-1;
648 lp=ed[up][i];
649 lw=m_test(lp,l);
650 while(lw==-1) {
651 i--;
653 // If i reaches zero, then we have a point in
654 // the plane all of whose edges are outside
655 // the cutting space, so we just exit
656 if(i==0) return true;
657 lp=ed[up][i];
658 lw=m_test(lp,l);
661 // Now search forwards from zero
662 j=1;
663 qp=ed[up][j];
664 qw=m_test(qp,q);
665 while(qw==-1) {
666 j++;
667 qp=ed[up][j];
668 qw=m_test(qp,l);
671 // Compute the number of edges for the new vertex. In
672 // general it will be the number of outside edges
673 // found, plus two. But we need to recognize the
674 // special case when all but one edge is outside, and
675 // the remaining one is on the plane. For that case we
676 // have to reduce the edge count by one to prevent
677 // doubling up.
678 if(i==j&&qw==0) {
679 double_edge=true;
680 nu[p]=nu[up];
681 } else {
682 nu[p]=nu[up]-i+j+1;
685 // Add memory to store the vertex if it doesn't exist
686 // already
687 k=1;
688 while(nu[p]>=current_vertex_order) add_memory_vorder(vc);
689 if(mec[nu[p]]==mem[nu[p]]) add_memory(vc,nu[p],stackp2);
691 // Copy the edges of the original vertex into the new
692 // one. Delete the edges of the original vertex, and
693 // update the relational table.
694 vc.n_set_pointer(p,nu[p]);
695 ed[p]=mep[nu[p]]+((nu[p]<<1)+1)*mec[nu[p]]++;
696 ed[p][nu[p]<<1]=p;
697 us=i++;
698 while(i<nu[up]) {
699 qp=ed[up][i];
700 qs=ed[up][nu[up]+i];
701 vc.n_copy(p,k,up,i);
702 ed[p][k]=qp;
703 ed[p][nu[p]+k]=qs;
704 ed[qp][qs]=p;
705 ed[qp][nu[qp]+qs]=k;
706 ed[up][i]=-1;
707 i++;k++;
709 i=0;
710 while(i<j) {
711 qp=ed[up][i];
712 qs=ed[up][nu[up]+i];
713 vc.n_copy(p,k,up,i);
714 ed[p][k]=qp;
715 ed[p][nu[p]+k]=qs;
716 ed[qp][qs]=p;
717 ed[qp][nu[qp]+qs]=k;
718 ed[up][i]=-1;
719 i++;k++;
721 qs=j;
723 if(!double_edge) {
724 vc.n_copy(p,k,up,qs);
725 vc.n_set(p,0,p_id);
726 } else vc.n_copy(p,0,up,qs);
728 // Add this point to the auxiliary delete stack
729 if(stackp2==stacke2) add_memory_ds2(stackp2);
730 *(stackp2++)=up;
732 // Look at the edges on either side of the group that was
733 // detected. We're going to commence facet computation by
734 // moving along one of them. We are going to end up coming back
735 // along the other one.
736 cs=k;
737 qp=up;q=u;
738 i=ed[up][us];
739 us=ed[up][nu[up]+us];
740 up=i;
741 ed[qp][nu[qp]<<1]=-p;
743 } else {
745 // The search algorithm found an intersected edge between the
746 // points lp and up. Create a new vertex between them which
747 // lies on the cutting plane. Since u and l differ by at least
748 // the tolerance, this division should never screw up.
749 if(stackp==stacke) add_memory_ds(stackp);
750 *(stackp++)=up;
751 r=u/(u-l);l=1-r;
752 ptsq[3*p]=ptsq[3*lp]*r+ptsq[3*up]*l;
753 ptsq[3*p+1]=ptsq[3*lp+1]*r+ptsq[3*up+1]*l;
754 ptsq[3*p+2]=ptsq[3*lp+2]*r+ptsq[3*up+2]*l;
756 // This point will always have three edges. Connect one of them
757 // to lp.
758 nu[p]=3;
759 if(mec[3]==mem[3]) add_memory(vc,3,stackp2);
760 vc.n_set_pointer(p,3);
761 vc.n_set(p,0,p_id);
762 vc.n_copy(p,1,up,us);
763 vc.n_copy(p,2,lp,ls);
764 ed[p]=mep[3]+7*mec[3]++;
765 ed[p][6]=p;
766 ed[up][us]=-1;
767 ed[lp][ls]=p;
768 ed[lp][nu[lp]+ls]=1;
769 ed[p][1]=lp;
770 ed[p][nu[p]+1]=ls;
771 cs=2;
773 // Set the direction to move in
774 qs=cycle_up(us,up);
775 qp=up;q=u;
778 // When the code reaches here, we have initialized the first point, and
779 // we have a direction for moving it to construct the rest of the facet
780 cp=p;rp=p;p++;
781 while(qp!=up||qs!=us) {
783 // We're currently tracing round an intersected facet. Keep
784 // moving around it until we find a point or edge which
785 // intersects the plane.
786 lp=ed[qp][qs];
787 lw=m_test(lp,l);
789 if(lw==1) {
791 // The point is still in the cutting space. Just add it
792 // to the delete stack and keep moving.
793 qs=cycle_up(ed[qp][nu[qp]+qs],lp);
794 qp=lp;
795 q=l;
796 if(stackp==stacke) add_memory_ds(stackp);
797 *(stackp++)=qp;
799 } else if(lw==-1) {
801 // The point is outside of the cutting space, so we've
802 // found an intersected edge. Introduce a regular point
803 // at the point of intersection. Connect it to the
804 // point we just tested. Also connect it to the previous
805 // new point in the facet we're constructing.
806 if(p==current_vertices) add_memory_vertices(vc);
807 r=q/(q-l);l=1-r;
808 ptsq[3*p]=ptsq[3*lp]*r+ptsq[3*qp]*l;
809 ptsq[3*p+1]=ptsq[3*lp+1]*r+ptsq[3*qp+1]*l;
810 ptsq[3*p+2]=ptsq[3*lp+2]*r+ptsq[3*qp+2]*l;
811 nu[p]=3;
812 if(mec[3]==mem[3]) add_memory(vc,3,stackp2);
813 ls=ed[qp][qs+nu[qp]];
814 vc.n_set_pointer(p,3);
815 vc.n_set(p,0,p_id);
816 vc.n_copy(p,1,qp,qs);
817 vc.n_copy(p,2,lp,ls);
818 ed[p]=mep[3]+7*mec[3]++;
819 *ed[p]=cp;
820 ed[p][1]=lp;
821 ed[p][3]=cs;
822 ed[p][4]=ls;
823 ed[p][6]=p;
824 ed[lp][ls]=p;
825 ed[lp][nu[lp]+ls]=1;
826 ed[cp][cs]=p;
827 ed[cp][nu[cp]+cs]=0;
828 ed[qp][qs]=-1;
829 qs=cycle_up(qs,qp);
830 cp=p++;
831 cs=2;
832 } else {
834 // We've found a point which is on the cutting plane.
835 // We're going to introduce a new point right here, but
836 // first we need to figure out the number of edges it
837 // has.
838 if(p==current_vertices) add_memory_vertices(vc);
840 // If the previous vertex detected a double edge, our
841 // new vertex will have one less edge.
842 k=double_edge?0:1;
843 qs=ed[qp][nu[qp]+qs];
844 qp=lp;
845 iqs=qs;
847 // Start testing the edges of the current point until
848 // we find one which isn't outside the cutting space
849 do {
850 k++;
851 qs=cycle_up(qs,qp);
852 lp=ed[qp][qs];
853 lw=m_test(lp,l);
854 } while (lw==-1);
856 // Now we need to find out whether this marginal vertex
857 // we are on has been visited before, because if that's
858 // the case, we need to add vertices to the existing
859 // new vertex, rather than creating a fresh one. We also
860 // need to figure out whether we're in a case where we
861 // might be creating a duplicate edge.
862 j=-ed[qp][nu[qp]<<1];
863 if(qp==up&&qs==us) {
865 // If we're heading into the final part of the
866 // new facet, then we never worry about the
867 // duplicate edge calculation.
868 new_double_edge=false;
869 if(j>0) k+=nu[j];
870 } else {
871 if(j>0) {
873 // This vertex was visited before, so
874 // count those vertices to the ones we
875 // already have.
876 k+=nu[j];
878 // The only time when we might make a
879 // duplicate edge is if the point we're
880 // going to move to next is also a
881 // marginal point, so test for that
882 // first.
883 if(lw==0) {
885 // Now see whether this marginal point
886 // has been visited before.
887 i=-ed[lp][nu[lp]<<1];
888 if(i>0) {
890 // Now see if the last edge of that other
891 // marginal point actually ends up here.
892 if(ed[i][nu[i]-1]==j) {
893 new_double_edge=true;
894 k-=1;
895 } else new_double_edge=false;
896 } else {
898 // That marginal point hasn't been visited
899 // before, so we probably don't have to worry
900 // about duplicate edges, except in the
901 // case when that's the way into the end
902 // of the facet, because that way always creates
903 // an edge.
904 if(j==rp&&lp==up&&ed[qp][nu[qp]+qs]==us) {
905 new_double_edge=true;
906 k-=1;
907 } else new_double_edge=false;
909 } else new_double_edge=false;
910 } else {
912 // The vertex hasn't been visited
913 // before, but let's see if it's
914 // marginal
915 if(lw==0) {
917 // If it is, we need to check
918 // for the case that it's a
919 // small branch, and that we're
920 // heading right back to where
921 // we came from
922 i=-ed[lp][nu[lp]<<1];
923 if(i==cp) {
924 new_double_edge=true;
925 k-=1;
926 } else new_double_edge=false;
927 } else new_double_edge=false;
931 // k now holds the number of edges of the new vertex
932 // we are forming. Add memory for it if it doesn't exist
933 // already.
934 while(k>=current_vertex_order) add_memory_vorder(vc);
935 if(mec[k]==mem[k]) add_memory(vc,k,stackp2);
937 // Now create a new vertex with order k, or augment
938 // the existing one
939 if(j>0) {
941 // If we're augmenting a vertex but we don't
942 // actually need any more edges, just skip this
943 // routine to avoid memory confusion
944 if(nu[j]!=k) {
945 // Allocate memory and copy the edges
946 // of the previous instance into it
947 vc.n_set_aux1(k);
948 edp=mep[k]+((k<<1)+1)*mec[k]++;
949 i=0;
950 while(i<nu[j]) {
951 vc.n_copy_aux1(j,i);
952 edp[i]=ed[j][i];
953 edp[k+i]=ed[j][nu[j]+i];
954 i++;
956 edp[k<<1]=j;
958 // Remove the previous instance with
959 // fewer vertices from the memory
960 // structure
961 edd=mep[nu[j]]+((nu[j]<<1)+1)*--mec[nu[j]];
962 if(edd!=ed[j]) {
963 for(lw=0;lw<=(nu[j]<<1);lw++) ed[j][lw]=edd[lw];
964 vc.n_set_aux2_copy(j,nu[j]);
965 vc.n_copy_pointer(edd[nu[j]<<1],j);
966 ed[edd[nu[j]<<1]]=ed[j];
968 vc.n_set_to_aux1(j);
969 ed[j]=edp;
970 } else i=nu[j];
971 } else {
973 // Allocate a new vertex of order k
974 vc.n_set_pointer(p,k);
975 ed[p]=mep[k]+((k<<1)+1)*mec[k]++;
976 ed[p][k<<1]=p;
977 if(stackp2==stacke2) add_memory_ds2(stackp2);
978 *(stackp2++)=qp;
979 ptsq[3*p]=ptsq[3*qp];
980 ptsq[3*p+1]=ptsq[3*qp+1];
981 ptsq[3*p+2]=ptsq[3*qp+2];
982 ed[qp][nu[qp]<<1]=-p;
983 j=p++;
984 i=0;
986 nu[j]=k;
988 // Unless the previous case was a double edge, connect
989 // the first available edge of the new vertex to the
990 // last one in the facet
991 if(!double_edge) {
992 ed[j][i]=cp;
993 ed[j][nu[j]+i]=cs;
994 vc.n_set(j,i,p_id);
995 ed[cp][cs]=j;
996 ed[cp][nu[cp]+cs]=i;
997 i++;
1000 // Copy in the edges of the underlying vertex,
1001 // and do one less if this was a double edge
1002 qs=iqs;
1003 while(i<(new_double_edge?k:k-1)) {
1004 qs=cycle_up(qs,qp);
1005 lp=ed[qp][qs];ls=ed[qp][nu[qp]+qs];
1006 vc.n_copy(j,i,qp,qs);
1007 ed[j][i]=lp;
1008 ed[j][nu[j]+i]=ls;
1009 ed[lp][ls]=j;
1010 ed[lp][nu[lp]+ls]=i;
1011 ed[qp][qs]=-1;
1012 i++;
1014 qs=cycle_up(qs,qp);
1015 cs=i;
1016 cp=j;
1017 vc.n_copy(j,new_double_edge?0:cs,qp,qs);
1019 // Update the double_edge flag, to pass it
1020 // to the next instance of this routine
1021 double_edge=new_double_edge;
1025 // Connect the final created vertex to the initial one
1026 ed[cp][cs]=rp;
1027 *ed[rp]=cp;
1028 ed[cp][nu[cp]+cs]=0;
1029 ed[rp][nu[rp]]=cs;
1031 // Delete points: first, remove any duplicates
1032 dsp=ds;
1033 while(dsp<stackp) {
1034 j=*dsp;
1035 if(ed[j][nu[j]]!=-1) {
1036 ed[j][nu[j]]=-1;
1037 dsp++;
1038 } else *dsp=*(--stackp);
1041 // Add the points in the auxiliary delete stack,
1042 // and reset their back pointers
1043 for(dsp=ds2;dsp<stackp2;dsp++) {
1044 j=*dsp;
1045 ed[j][nu[j]<<1]=j;
1046 if(ed[j][nu[j]]!=-1) {
1047 ed[j][nu[j]]=-1;
1048 if(stackp==stacke) add_memory_ds(stackp);
1049 *(stackp++)=j;
1053 // Scan connections and add in extras
1054 for(dsp=ds;dsp<stackp;dsp++) {
1055 cp=*dsp;
1056 for(edp=ed[cp];edp<ed[cp]+nu[cp];edp++) {
1057 qp=*edp;
1058 if(qp!=-1&&ed[qp][nu[qp]]!=-1) {
1059 if(stackp==stacke) {
1060 int dis=stackp-dsp;
1061 add_memory_ds(stackp);
1062 dsp=ds+dis;
1064 *(stackp++)=qp;
1065 ed[qp][nu[qp]]=-1;
1069 up=0;
1071 // Delete them from the array structure
1072 while(stackp>ds) {
1073 --p;
1074 while(ed[p][nu[p]]==-1) {
1075 j=nu[p];
1076 edp=ed[p];edd=(mep[j]+((j<<1)+1)*--mec[j]);
1077 while(edp<ed[p]+(j<<1)+1) *(edp++)=*(edd++);
1078 vc.n_set_aux2_copy(p,j);
1079 vc.n_copy_pointer(ed[p][(j<<1)],p);
1080 ed[ed[p][(j<<1)]]=ed[p];
1081 --p;
1083 up=*(--stackp);
1084 if(up<p) {
1086 // Vertex management
1087 ptsq[3*up]=ptsq[3*p];
1088 ptsq[3*up+1]=ptsq[3*p+1];
1089 ptsq[3*up+2]=ptsq[3*p+2];
1091 // Memory management
1092 j=nu[up];
1093 edp=ed[up];edd=(mep[j]+((j<<1)+1)*--mec[j]);
1094 while(edp<ed[up]+(j<<1)+1) *(edp++)=*(edd++);
1095 vc.n_set_aux2_copy(up,j);
1096 vc.n_copy_pointer(ed[up][j<<1],up);
1097 vc.n_copy_pointer(up,p);
1098 ed[ed[up][j<<1]]=ed[up];
1100 // Edge management
1101 ed[up]=ed[p];
1102 nu[up]=nu[p];
1103 for(i=0;i<nu[up];i++) ed[ed[up][i]][ed[up][nu[up]+i]]=up;
1104 ed[up][nu[up]<<1]=up;
1105 } else up=p++;
1108 // Check for any vertices of zero order
1109 if(*mec>0) voro_fatal_error("Zero order vertex formed",VOROPP_INTERNAL_ERROR);
1111 // Collapse any order 2 vertices and exit
1112 return collapse_order2(vc);
1115 /** During the creation of a new facet in the plane routine, it is possible
1116 * that some order two vertices may arise. This routine removes them.
1117 * Suppose an order two vertex joins c and d. If there's a edge between
1118 * c and d already, then the order two vertex is just removed; otherwise,
1119 * the order two vertex is removed and c and d are joined together directly.
1120 * It is possible this process will create order two or order one vertices,
1121 * and the routine is continually run until all of them are removed.
1122 * \return False if the vertex removal was unsuccessful, indicative of the cell
1123 * reducing to zero volume and disappearing; true if the vertex removal
1124 * was successful. */
1125 template<class vc_class>
1126 inline bool voronoicell_base::collapse_order2(vc_class &vc) {
1127 if(!collapse_order1(vc)) return false;
1128 int a,b,i,j,k,l;
1129 while(mec[2]>0) {
1131 // Pick a order 2 vertex and read in its edges
1132 i=--mec[2];
1133 j=mep[2][5*i];k=mep[2][5*i+1];
1134 if(j==k) {
1135 #if VOROPP_VERBOSE >=1
1136 fputs("Order two vertex joins itself",stderr);
1137 #endif
1138 return false;
1141 // Scan the edges of j to see if joins k
1142 for(l=0;l<nu[j];l++) {
1143 if(ed[j][l]==k) break;
1146 // If j doesn't already join k, join them together.
1147 // Otherwise delete the connection to the current
1148 // vertex from j and k.
1149 a=mep[2][5*i+2];b=mep[2][5*i+3];i=mep[2][5*i+4];
1150 if(l==nu[j]) {
1151 ed[j][a]=k;
1152 ed[k][b]=j;
1153 ed[j][nu[j]+a]=b;
1154 ed[k][nu[k]+b]=a;
1155 } else {
1156 if(!delete_connection(vc,j,a,false)) return false;
1157 if(!delete_connection(vc,k,b,true)) return false;
1160 // Compact the memory
1161 --p;
1162 if(up==i) up=0;
1163 if(p!=i) {
1164 if(up==p) up=i;
1165 ptsq[3*i]=ptsq[3*p];
1166 ptsq[3*i+1]=ptsq[3*p+1];
1167 ptsq[3*i+2]=ptsq[3*p+2];
1168 for(k=0;k<nu[p];k++) ed[ed[p][k]][ed[p][nu[p]+k]]=i;
1169 vc.n_copy_pointer(i,p);
1170 ed[i]=ed[p];
1171 nu[i]=nu[p];
1172 ed[i][nu[i]<<1]=i;
1175 // Collapse any order 1 vertices if they were created
1176 if(!collapse_order1(vc)) return false;
1178 return true;
1181 /** Order one vertices can potentially be created during the order two collapse
1182 * routine. This routine keeps removing them until there are none left.
1183 * \return False if the vertex removal was unsuccessful, indicative of the cell
1184 * having zero volume and disappearing; true if the vertex removal was
1185 * successful. */
1186 template<class vc_class>
1187 inline bool voronoicell_base::collapse_order1(vc_class &vc) {
1188 int i,j,k;
1189 while(mec[1]>0) {
1190 up=0;
1191 #if VOROPP_VERBOSE >=1
1192 fputs("Order one collapse\n",stderr);
1193 #endif
1194 i=--mec[1];
1195 j=mep[1][3*i];k=mep[1][3*i+1];
1196 i=mep[1][3*i+2];
1197 if(!delete_connection(vc,j,k,false)) return false;
1198 --p;
1199 if(up==i) up=0;
1200 if(p!=i) {
1201 if(up==p) up=i;
1202 ptsq[3*i]=ptsq[3*p];
1203 ptsq[3*i+1]=ptsq[3*p+1];
1204 ptsq[3*i+2]=ptsq[3*p+2];
1205 for(k=0;k<nu[p];k++) ed[ed[p][k]][ed[p][nu[p]+k]]=i;
1206 vc.n_copy_pointer(i,p);
1207 ed[i]=ed[p];
1208 nu[i]=nu[p];
1209 ed[i][nu[i]<<1]=i;
1212 return true;
1215 /** This routine deletes the kth edge of vertex j and reorganizes the memory.
1216 * If the neighbor computation is enabled, we also have to supply an handedness
1217 * flag to decide whether to preserve the plane on the left or right of the
1218 * connection.
1219 * \return False if a zero order vertex was formed, indicative of the cell
1220 * disappearing; true if the vertex removal was successful. */
1221 template<class vc_class>
1222 inline bool voronoicell_base::delete_connection(vc_class &vc,int j,int k,bool hand) {
1223 int q=hand?k:cycle_up(k,j);
1224 int i=nu[j]-1,l,*edp,*edd,m;
1225 #if VOROPP_VERBOSE >=1
1226 if(i<1) {
1227 fputs("Zero order vertex formed\n",stderr);
1228 return false;
1230 #endif
1231 if(mec[i]==mem[i]) add_memory(vc,i,ds2);
1232 vc.n_set_aux1(i);
1233 for(l=0;l<q;l++) vc.n_copy_aux1(j,l);
1234 while(l<i) {
1235 vc.n_copy_aux1_shift(j,l);
1236 l++;
1238 edp=mep[i]+((i<<1)+1)*mec[i]++;
1239 edp[i<<1]=j;
1240 for(l=0;l<k;l++) {
1241 edp[l]=ed[j][l];
1242 edp[l+i]=ed[j][l+nu[j]];
1244 while(l<i) {
1245 m=ed[j][l+1];
1246 edp[l]=m;
1247 k=ed[j][l+nu[j]+1];
1248 edp[l+i]=k;
1249 ed[m][nu[m]+k]--;
1250 l++;
1253 edd=mep[nu[j]]+((nu[j]<<1)+1)*--mec[nu[j]];
1254 for(l=0;l<=(nu[j]<<1);l++) ed[j][l]=edd[l];
1255 vc.n_set_aux2_copy(j,nu[j]);
1256 vc.n_set_to_aux2(edd[nu[j]<<1]);
1257 vc.n_set_to_aux1(j);
1258 ed[edd[nu[j]<<1]]=edd;
1259 ed[j]=edp;
1260 nu[j]=i;
1261 return true;
1264 /** Calculates the volume of the Voronoi cell, by decomposing the cell into
1265 * tetrahedra extending outward from the zeroth vertex, whose volumes are
1266 * evaluated using a scalar triple product.
1267 * \return A floating point number holding the calculated volume. */
1268 double voronoicell_base::volume() {
1269 if(!synced) sync();
1270 const double fe=1/48.0;
1271 double vol=0;
1272 int i,j,k,l,m,n;
1273 double ux,uy,uz,vx,vy,vz,wx,wy,wz;
1274 for(i=1;i<p;i++) {
1275 ux=*pts-pts[3*i];
1276 uy=pts[1]-pts[3*i+1];
1277 uz=pts[2]-pts[3*i+2];
1278 for(j=0;j<nu[i];j++) {
1279 k=ed[i][j];
1280 if(k>=0) {
1281 ed[i][j]=-1-k;
1282 l=cycle_up(ed[i][nu[i]+j],k);
1283 vx=pts[3*k]-*pts;
1284 vy=pts[3*k+1]-pts[1];
1285 vz=pts[3*k+2]-pts[2];
1286 m=ed[k][l];ed[k][l]=-1-m;
1287 while(m!=i) {
1288 n=cycle_up(ed[k][nu[k]+l],m);
1289 wx=pts[3*m]-*pts;
1290 wy=pts[3*m+1]-pts[1];
1291 wz=pts[3*m+2]-pts[2];
1292 vol+=ux*vy*wz+uy*vz*wx+uz*vx*wy-uz*vy*wx-uy*vx*wz-ux*vz*wy;
1293 k=m;l=n;vx=wx;vy=wy;vz=wz;
1294 m=ed[k][l];ed[k][l]=-1-m;
1299 reset_edges();
1300 return vol*fe;
1303 /** Calculates the areas of each face of the Voronoi cell and prints the
1304 * results to an output stream.
1305 * \param[out] v the vector to store the results in. */
1306 void voronoicell_base::face_areas(vector<double> &v) {
1307 if(!synced) sync();
1308 double area;
1309 v.clear();
1310 int i,j,k,l,m,n;
1311 double ux,uy,uz,vx,vy,vz,wx,wy,wz;
1312 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
1313 k=ed[i][j];
1314 if(k>=0) {
1315 area=0;
1316 ed[i][j]=-1-k;
1317 l=cycle_up(ed[i][nu[i]+j],k);
1318 m=ed[k][l];ed[k][l]=-1-m;
1319 while(m!=i) {
1320 n=cycle_up(ed[k][nu[k]+l],m);
1321 ux=pts[3*k]-pts[3*i];
1322 uy=pts[3*k+1]-pts[3*i+1];
1323 uz=pts[3*k+2]-pts[3*i+2];
1324 vx=pts[3*m]-pts[3*i];
1325 vy=pts[3*m+1]-pts[3*i+1];
1326 vz=pts[3*m+2]-pts[3*i+2];
1327 wx=uy*vz-uz*vy;
1328 wy=uz*vx-ux*vz;
1329 wz=ux*vy-uy*vx;
1330 area+=sqrt(wx*wx+wy*wy+wz*wz);
1331 k=m;l=n;
1332 m=ed[k][l];ed[k][l]=-1-m;
1334 v.push_back(0.125*area);
1337 reset_edges();
1341 /** Calculates the total surface area of the Voronoi cell.
1342 * \return The computed area. */
1343 double voronoicell_base::surface_area() {
1344 if(!synced) sync();
1345 double area=0;
1346 int i,j,k,l,m,n;
1347 double ux,uy,uz,vx,vy,vz,wx,wy,wz;
1348 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
1349 k=ed[i][j];
1350 if(k>=0) {
1351 ed[i][j]=-1-k;
1352 l=cycle_up(ed[i][nu[i]+j],k);
1353 m=ed[k][l];ed[k][l]=-1-m;
1354 while(m!=i) {
1355 n=cycle_up(ed[k][nu[k]+l],m);
1356 ux=pts[3*k]-pts[3*i];
1357 uy=pts[3*k+1]-pts[3*i+1];
1358 uz=pts[3*k+2]-pts[3*i+2];
1359 vx=pts[3*m]-pts[3*i];
1360 vy=pts[3*m+1]-pts[3*i+1];
1361 vz=pts[3*m+2]-pts[3*i+2];
1362 wx=uy*vz-uz*vy;
1363 wy=uz*vx-ux*vz;
1364 wz=ux*vy-uy*vx;
1365 area+=sqrt(wx*wx+wy*wy+wz*wz);
1366 k=m;l=n;
1367 m=ed[k][l];ed[k][l]=-1-m;
1371 reset_edges();
1372 return 0.125*area;
1376 /** Calculates the centroid of the Voronoi cell, by decomposing the cell into
1377 * tetrahedra extending outward from the zeroth vertex.
1378 * \param[out] (cx,cy,cz) references to floating point numbers in which to
1379 * pass back the centroid vector. */
1380 void voronoicell_base::centroid(double &cx,double &cy,double &cz) {
1381 if(!synced) sync();
1382 double tvol,vol=0;cx=cy=cz=0;
1383 int i,j,k,l,m,n;
1384 double ux,uy,uz,vx,vy,vz,wx,wy,wz;
1385 for(i=1;i<p;i++) {
1386 ux=*pts-pts[3*i];
1387 uy=pts[1]-pts[3*i+1];
1388 uz=pts[2]-pts[3*i+2];
1389 for(j=0;j<nu[i];j++) {
1390 k=ed[i][j];
1391 if(k>=0) {
1392 ed[i][j]=-1-k;
1393 l=cycle_up(ed[i][nu[i]+j],k);
1394 vx=pts[3*k]-*pts;
1395 vy=pts[3*k+1]-pts[1];
1396 vz=pts[3*k+2]-pts[2];
1397 m=ed[k][l];ed[k][l]=-1-m;
1398 while(m!=i) {
1399 n=cycle_up(ed[k][nu[k]+l],m);
1400 wx=pts[3*m]-*pts;
1401 wy=pts[3*m+1]-pts[1];
1402 wz=pts[3*m+2]-pts[2];
1403 tvol=ux*vy*wz+uy*vz*wx+uz*vx*wy-uz*vy*wx-uy*vx*wz-ux*vz*wy;
1404 vol+=tvol;
1405 cx+=(wx+vx-ux)*tvol;
1406 cy+=(wy+vy-uy)*tvol;
1407 cz+=(wz+vz-uz)*tvol;
1408 k=m;l=n;vx=wx;vy=wy;vz=wz;
1409 m=ed[k][l];ed[k][l]=-1-m;
1414 reset_edges();
1415 if(vol>tolerance_sq) {
1416 vol=0.125/vol;
1417 cx=cx*vol+0.5*(*pts);
1418 cy=cy*vol+0.5*pts[1];
1419 cz=cz*vol+0.5*pts[2];
1420 } else cx=cy=cz=0;
1423 /** Computes the maximum radius squared of a vertex from the center of the
1424 * cell. It can be used to determine when enough particles have been testing an
1425 * all planes that could cut the cell have been considered.
1426 * \return The maximum radius squared of a vertex.*/
1427 double voronoicell_base::max_radius_squared() {
1428 if(!synced) sync();
1429 double r,s,*ptsp=pts+3,*ptse=pts+3*p;
1430 r=*pts*(*pts)+pts[1]*pts[1]+pts[2]*pts[2];
1431 while(ptsp<ptse) {
1432 s=*ptsp*(*ptsp);ptsp++;
1433 s+=*ptsp*(*ptsp);ptsp++;
1434 s+=*ptsp*(*ptsp);ptsp++;
1435 if(s>r) r=s;
1437 return r;
1440 /** Calculates the total edge distance of the Voronoi cell.
1441 * \return A floating point number holding the calculated distance. */
1442 double voronoicell_base::total_edge_distance() {
1443 if(!synced) sync();
1444 int i,j,k;
1445 double dis=0,dx,dy,dz;
1446 for(i=0;i<p-1;i++) for(j=0;j<nu[i];j++) {
1447 k=ed[i][j];
1448 if(k>i) {
1449 dx=pts[3*k]-pts[3*i];
1450 dy=pts[3*k+1]-pts[3*i+1];
1451 dz=pts[3*k+2]-pts[3*i+2];
1452 dis+=sqrt(dx*dx+dy*dy+dz*dz);
1455 return 0.5*dis;
1458 /** Outputs the edges of the Voronoi cell in POV-Ray format to an open file
1459 * stream, displacing the cell by given vector.
1460 * \param[in] (x,y,z) a displacement vector to be added to the cell's position.
1461 * \param[in] fp a file handle to write to. */
1462 void voronoicell_base::draw_pov(double x,double y,double z,FILE* fp) {
1463 if(!synced) sync();
1464 int i,j,k;double *ptsp=pts,*pt2;
1465 char posbuf1[128],posbuf2[128];
1466 for(i=0;i<p;i++,ptsp+=3) {
1467 sprintf(posbuf1,"%g,%g,%g",x+*ptsp*0.5,y+ptsp[1]*0.5,z+ptsp[2]*0.5);
1468 fprintf(fp,"sphere{<%s>,r}\n",posbuf1);
1469 for(j=0;j<nu[i];j++) {
1470 k=ed[i][j];
1471 if(k<i) {
1472 pt2=pts+3*k;
1473 sprintf(posbuf2,"%g,%g,%g",x+*pt2*0.5,y+0.5*pt2[1],z+0.5*pt2[2]);
1474 if(strcmp(posbuf1,posbuf2)!=0) fprintf(fp,"cylinder{<%s>,<%s>,r}\n",posbuf1,posbuf2);
1480 /** Outputs the edges of the Voronoi cell in gnuplot format to an output stream.
1481 * \param[in] (x,y,z) a displacement vector to be added to the cell's position.
1482 * \param[in] fp a file handle to write to. */
1483 void voronoicell_base::draw_gnuplot(double x,double y,double z,FILE *fp) {
1484 if(!synced) sync();
1485 int i,j,k,l,m;
1486 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
1487 k=ed[i][j];
1488 if(k>=0) {
1489 fprintf(fp,"%g %g %g\n",x+0.5*pts[3*i],y+0.5*pts[3*i+1],z+0.5*pts[3*i+2]);
1490 l=i;m=j;
1491 do {
1492 ed[k][ed[l][nu[l]+m]]=-1-l;
1493 ed[l][m]=-1-k;
1494 l=k;
1495 fprintf(fp,"%g %g %g\n",x+0.5*pts[3*k],y+0.5*pts[3*k+1],z+0.5*pts[3*k+2]);
1496 } while (search_edge(l,m,k));
1497 fputs("\n\n",fp);
1500 reset_edges();
1503 inline bool voronoicell_base::search_edge(int l,int &m,int &k) {
1504 for(m=0;m<nu[l];m++) {
1505 k=ed[l][m];
1506 if(k>=0) return true;
1508 return false;
1511 /** Outputs the Voronoi cell in the POV mesh2 format, described in section
1512 * 1.3.2.2 of the POV-Ray documentation. The mesh2 output consists of a list of
1513 * vertex vectors, followed by a list of triangular faces. The routine also
1514 * makes use of the optional inside_vector specification, which makes the mesh
1515 * object solid, so the the POV-Ray Constructive Solid Geometry (CSG) can be
1516 * applied.
1517 * \param[in] (x,y,z) a displacement vector to be added to the cell's position.
1518 * \param[in] fp a file handle to write to. */
1519 void voronoicell_base::draw_pov_mesh(double x,double y,double z,FILE *fp) {
1520 if(!synced) sync();
1521 int i,j,k,l,m,n;
1522 double *ptsp=pts;
1523 fprintf(fp,"mesh2 {\nvertex_vectors {\n%d\n",p);
1524 for(i=0;i<p;i++,ptsp+=3) fprintf(fp,",<%g,%g,%g>\n",x+*ptsp*0.5,y+ptsp[1]*0.5,z+ptsp[2]*0.5);
1525 fprintf(fp,"}\nface_indices {\n%d\n",(p-2)<<1);
1526 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
1527 k=ed[i][j];
1528 if(k>=0) {
1529 ed[i][j]=-1-k;
1530 l=cycle_up(ed[i][nu[i]+j],k);
1531 m=ed[k][l];ed[k][l]=-1-m;
1532 while(m!=i) {
1533 n=cycle_up(ed[k][nu[k]+l],m);
1534 fprintf(fp,",<%d,%d,%d>\n",i,k,m);
1535 k=m;l=n;
1536 m=ed[k][l];ed[k][l]=-1-m;
1540 fputs("}\ninside_vector <0,0,1>\n}\n",fp);
1541 reset_edges();
1544 /** Several routines in the class that gather cell-based statistics internally
1545 * track their progress by flipping edges to negative so that they know what
1546 * parts of the cell have already been tested. This function resets them back
1547 * to positive. When it is called, it assumes that every edge in the routine
1548 * should have already been flipped to negative, and it bails out with an
1549 * internal error if it encounters a positive edge. */
1550 inline void voronoicell_base::reset_edges() {
1551 int i,j;
1552 for(i=0;i<p;i++) for(j=0;j<nu[i];j++) {
1553 if(ed[i][j]>=0) voro_fatal_error("Edge reset routine found a previously untested edge",VOROPP_INTERNAL_ERROR);
1554 ed[i][j]=-1-ed[i][j];
1558 /** Checks to see if a given vertex is inside, outside or within the test
1559 * plane. If the point is far away from the test plane, the routine immediately
1560 * returns whether it is inside or outside. If the routine is close the the
1561 * plane and within the specified tolerance, then the special check_marginal()
1562 * routine is called.
1563 * \param[in] n the vertex to test.
1564 * \param[out] ans the result of the scalar product used in evaluating the
1565 * location of the point.
1566 * \return -1 if the point is inside the plane, 1 if the point is outside the
1567 * plane, or 0 if the point is within the plane. */
1568 inline int voronoicell_base::m_test(int n,mpq_class &ans) {
1569 mpq_class *pp=ptsq+n+(n<<1);
1570 ans=*(pp++)*px;
1571 ans+=*(pp++)*py;
1572 ans+=*pp*pz-prsq;
1573 if(ans<0) {
1574 return -1;
1575 } else if(ans>0) {
1576 return 1;
1577 } else return 0;
1580 /** For each face of the Voronoi cell, this routine prints the out the normal
1581 * vector of the face, and scales it to the distance from the cell center to
1582 * that plane.
1583 * \param[out] v the vector to store the results in. */
1584 void voronoicell_base::normals(vector<double> &v) {
1585 if(!synced) sync();
1586 int i,j,k;
1587 v.clear();
1588 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
1589 k=ed[i][j];
1590 if(k>=0) normals_search(v,i,j,k);
1592 reset_edges();
1595 /** This inline routine is called by normals(). It attempts to construct a
1596 * single normal vector that is associated with a particular face. It first
1597 * traces around the face, trying to find two vectors along the face edges
1598 * whose vector product is above the numerical tolerance. It then constructs
1599 * the normal vector using this product. If the face is too small, and none of
1600 * the vector products are large enough, the routine may return (0,0,0) as the
1601 * normal vector.
1602 * \param[in] v the vector to store the results in.
1603 * \param[in] i the initial vertex of the face to test.
1604 * \param[in] j the index of an edge of the vertex.
1605 * \param[in] k the neighboring vertex of i, set to ed[i][j]. */
1606 inline void voronoicell_base::normals_search(vector<double> &v,int i,int j,int k) {
1607 ed[i][j]=-1-k;
1608 int l=cycle_up(ed[i][nu[i]+j],k),m;
1609 double ux,uy,uz,vx,vy,vz,wx,wy,wz,wmag;
1610 do {
1611 m=ed[k][l];ed[k][l]=-1-m;
1612 ux=pts[3*m]-pts[3*k];
1613 uy=pts[3*m+1]-pts[3*k+1];
1614 uz=pts[3*m+2]-pts[3*k+2];
1616 // Test to see if the length of this edge is above the tolerance
1617 if(ux*ux+uy*uy+uz*uz>tolerance_sq) {
1618 while(m!=i) {
1619 l=cycle_up(ed[k][nu[k]+l],m);
1620 k=m;m=ed[k][l];ed[k][l]=-1-m;
1621 vx=pts[3*m]-pts[3*k];
1622 vy=pts[3*m+1]-pts[3*k+1];
1623 vz=pts[3*m+2]-pts[3*k+2];
1625 // Construct the vector product of this edge with
1626 // the previous one
1627 wx=uz*vy-uy*vz;
1628 wy=ux*vz-uz*vx;
1629 wz=uy*vx-ux*vy;
1630 wmag=wx*wx+wy*wy+wz*wz;
1632 // Test to see if this vector product of the
1633 // two edges is above the tolerance
1634 if(wmag>tolerance_sq) {
1636 // Construct the normal vector and print it
1637 wmag=1/sqrt(wmag);
1638 v.push_back(wx*wmag);
1639 v.push_back(wy*wmag);
1640 v.push_back(wz*wmag);
1642 // Mark all of the remaining edges of this
1643 // face and exit
1644 while(m!=i) {
1645 l=cycle_up(ed[k][nu[k]+l],m);
1646 k=m;m=ed[k][l];ed[k][l]=-1-m;
1648 return;
1651 v.push_back(0);
1652 v.push_back(0);
1653 v.push_back(0);
1654 return;
1656 l=cycle_up(ed[k][nu[k]+l],m);
1657 k=m;
1658 } while (k!=i);
1659 v.push_back(0);
1660 v.push_back(0);
1661 v.push_back(0);
1665 /** Returns the number of faces of a computed Voronoi cell.
1666 * \return The number of faces. */
1667 int voronoicell_base::number_of_faces() {
1668 int i,j,k,l,m,s=0;
1669 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
1670 k=ed[i][j];
1671 if(k>=0) {
1672 s++;
1673 ed[i][j]=-1-k;
1674 l=cycle_up(ed[i][nu[i]+j],k);
1675 do {
1676 m=ed[k][l];
1677 ed[k][l]=-1-m;
1678 l=cycle_up(ed[k][nu[k]+l],m);
1679 k=m;
1680 } while (k!=i);
1684 reset_edges();
1685 return s;
1688 /** Returns a vector of the vertex orders.
1689 * \param[out] v the vector to store the results in. */
1690 void voronoicell_base::vertex_orders(vector<int> &v) {
1691 v.resize(p);
1692 for(int i=0;i<p;i++) v[i]=nu[i];
1695 /** Outputs the vertex orders.
1696 * \param[out] fp the file handle to write to. */
1697 void voronoicell_base::output_vertex_orders(FILE *fp) {
1698 if(p>0) {
1699 fprintf(fp,"%d",*nu);
1700 for(int *nup=nu+1;nup<nu+p;nup++) fprintf(fp," %d",*nup);
1704 /** Returns a vector of the vertex vectors using the local coordinate system.
1705 * \param[out] v the vector to store the results in. */
1706 void voronoicell_base::vertices(vector<double> &v) {
1707 if(!synced) sync();
1708 v.resize(3*p);
1709 double *ptsp=pts;
1710 for(int i=0;i<3*p;i+=3) {
1711 v[i]=*(ptsp++)*0.5;
1712 v[i+1]=*(ptsp++)*0.5;
1713 v[i+2]=*(ptsp++)*0.5;
1717 /** Outputs the vertex vectors using the local coordinate system.
1718 * \param[out] fp the file handle to write to. */
1719 void voronoicell_base::output_vertices(FILE *fp) {
1720 if(!synced) sync();
1721 if(p>0) {
1722 fprintf(fp,"(%g,%g,%g)",*pts*0.5,pts[1]*0.5,pts[2]*0.5);
1723 for(double *ptsp=pts+3;ptsp<pts+3*p;ptsp+=3) fprintf(fp," (%g,%g,%g)",*ptsp*0.5,ptsp[1]*0.5,ptsp[2]*0.5);
1728 /** Returns a vector of the vertex vectors in the global coordinate system.
1729 * \param[out] v the vector to store the results in.
1730 * \param[in] (x,y,z) the position vector of the particle in the global
1731 * coordinate system. */
1732 void voronoicell_base::vertices(double x,double y,double z,vector<double> &v) {
1733 if(!synced) sync();
1734 v.resize(3*p);
1735 double *ptsp=pts;
1736 for(int i=0;i<3*p;i+=3) {
1737 v[i]=x+*(ptsp++)*0.5;
1738 v[i+1]=y+*(ptsp++)*0.5;
1739 v[i+2]=z+*(ptsp++)*0.5;
1743 /** Outputs the vertex vectors using the global coordinate system.
1744 * \param[out] fp the file handle to write to.
1745 * \param[in] (x,y,z) the position vector of the particle in the global
1746 * coordinate system. */
1747 void voronoicell_base::output_vertices(double x,double y,double z,FILE *fp) {
1748 if(!synced) sync();
1749 if(p>0) {
1750 fprintf(fp,"(%g,%g,%g)",x+*pts*0.5,y+pts[1]*0.5,z+pts[2]*0.5);
1751 for(double *ptsp=pts+3;ptsp<pts+3*p;ptsp+=3) fprintf(fp," (%g,%g,%g)",x+*ptsp*0.5,y+ptsp[1]*0.5,z+ptsp[2]*0.5);
1755 /** This routine returns the perimeters of each face.
1756 * \param[out] v the vector to store the results in. */
1757 void voronoicell_base::face_perimeters(vector<double> &v) {
1758 if(!synced) sync();
1759 v.clear();
1760 int i,j,k,l,m;
1761 double dx,dy,dz,perim;
1762 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
1763 k=ed[i][j];
1764 if(k>=0) {
1765 dx=pts[3*k]-pts[3*i];
1766 dy=pts[3*k+1]-pts[3*i+1];
1767 dz=pts[3*k+2]-pts[3*i+2];
1768 perim=sqrt(dx*dx+dy*dy+dz*dz);
1769 ed[i][j]=-1-k;
1770 l=cycle_up(ed[i][nu[i]+j],k);
1771 do {
1772 m=ed[k][l];
1773 dx=pts[3*m]-pts[3*k];
1774 dy=pts[3*m+1]-pts[3*k+1];
1775 dz=pts[3*m+2]-pts[3*k+2];
1776 perim+=sqrt(dx*dx+dy*dy+dz*dz);
1777 ed[k][l]=-1-m;
1778 l=cycle_up(ed[k][nu[k]+l],m);
1779 k=m;
1780 } while (k!=i);
1781 v.push_back(0.5*perim);
1784 reset_edges();
1787 /** For each face, this routine outputs a bracketed sequence of numbers
1788 * containing a list of all the vertices that make up that face.
1789 * \param[out] v the vector to store the results in. */
1790 void voronoicell_base::face_vertices(vector<int> &v) {
1791 int i,j,k,l,m,vp(0),vn;
1792 v.clear();
1793 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
1794 k=ed[i][j];
1795 if(k>=0) {
1796 v.push_back(0);
1797 v.push_back(i);
1798 ed[i][j]=-1-k;
1799 l=cycle_up(ed[i][nu[i]+j],k);
1800 do {
1801 v.push_back(k);
1802 m=ed[k][l];
1803 ed[k][l]=-1-m;
1804 l=cycle_up(ed[k][nu[k]+l],m);
1805 k=m;
1806 } while (k!=i);
1807 vn=v.size();
1808 v[vp]=vn-vp-1;
1809 vp=vn;
1812 reset_edges();
1815 /** Outputs a list of the number of edges in each face.
1816 * \param[out] v the vector to store the results in. */
1817 void voronoicell_base::face_orders(vector<int> &v) {
1818 int i,j,k,l,m,q;
1819 v.clear();
1820 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
1821 k=ed[i][j];
1822 if(k>=0) {
1823 q=1;
1824 ed[i][j]=-1-k;
1825 l=cycle_up(ed[i][nu[i]+j],k);
1826 do {
1827 q++;
1828 m=ed[k][l];
1829 ed[k][l]=-1-m;
1830 l=cycle_up(ed[k][nu[k]+l],m);
1831 k=m;
1832 } while (k!=i);
1833 v.push_back(q);;
1836 reset_edges();
1839 /** Computes the number of edges that each face has and outputs a frequency
1840 * table of the results.
1841 * \param[out] v the vector to store the results in. */
1842 void voronoicell_base::face_freq_table(vector<int> &v) {
1843 int i,j,k,l,m,q;
1844 v.clear();
1845 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
1846 k=ed[i][j];
1847 if(k>=0) {
1848 q=1;
1849 ed[i][j]=-1-k;
1850 l=cycle_up(ed[i][nu[i]+j],k);
1851 do {
1852 q++;
1853 m=ed[k][l];
1854 ed[k][l]=-1-m;
1855 l=cycle_up(ed[k][nu[k]+l],m);
1856 k=m;
1857 } while (k!=i);
1858 if((unsigned int) q>=v.size()) v.resize(q+1,0);
1859 v[q]++;
1862 reset_edges();
1865 /** This routine tests to see whether the cell intersects a plane by starting
1866 * from the guess point up. If up intersects, then it immediately returns true.
1867 * Otherwise, it calls the plane_intersects_track() routine.
1868 * \param[in] (x,y,z) the normal vector to the plane.
1869 * \param[in] rsq the distance along this vector of the plane.
1870 * \return False if the plane does not intersect the plane, true if it does. */
1871 bool voronoicell_base::plane_intersects(double xd,double yd,double zd,double rsqd) {
1872 mpq_class x,y,z,rsq,g;
1873 x=xd;y=yd;z=zd;rsq=rsqd;
1874 g=x*ptsq[3*up]+y*ptsq[3*up+1]+z*ptsq[3*up+2];
1875 if(g<rsq) return plane_intersects_track(x,y,z,rsq,g);
1876 return true;
1879 /** This routine tests to see if a cell intersects a plane. It first tests a
1880 * random sample of approximately sqrt(p)/4 points. If any of those are
1881 * intersect, then it immediately returns true. Otherwise, it takes the closest
1882 * point and passes that to plane_intersect_track() routine.
1883 * \param[in] (x,y,z) the normal vector to the plane.
1884 * \param[in] rsq the distance along this vector of the plane.
1885 * \return False if the plane does not intersect the plane, true if it does. */
1886 bool voronoicell_base::plane_intersects_guess(double xd,double yd,double zd,double rsqd) {
1887 mpq_class x,y,z,rsq,g,m;
1888 x=xd;y=yd;z=zd;rsq=rsqd;
1889 up=0;
1890 g=x*ptsq[3*up]+y*ptsq[3*up+1]+z*ptsq[3*up+2];
1891 if(g<rsq) {
1892 int ca=1,cc=p>>3,mp=1;
1893 while(ca<cc) {
1894 m=x*ptsq[3*mp]+y*ptsq[3*mp+1]+z*ptsq[3*mp+2];
1895 if(m>g) {
1896 if(m>rsq) return true;
1897 g=m;up=mp;
1899 ca+=mp++;
1901 return plane_intersects_track(x,y,z,rsq,g);
1903 return true;
1906 /* This routine tests to see if a cell intersects a plane, by tracing over the cell from
1907 * vertex to vertex, starting at up. It is meant to be called either by plane_intersects()
1908 * or plane_intersects_track(), when those routines cannot immediately resolve the case.
1909 * \param[in] (x,y,z) the normal vector to the plane.
1910 * \param[in] rsq the distance along this vector of the plane.
1911 * \param[in] g the distance of up from the plane.
1912 * \return False if the plane does not intersect the plane, true if it does. */
1913 inline bool voronoicell_base::plane_intersects_track(mpq_class x,mpq_class y,mpq_class z,mpq_class rsq,mpq_class g) {
1914 int count=0,ls,us,tp;
1915 mpq_class t;
1917 // The test point is outside of the cutting space
1918 for(us=0;us<nu[up];us++) {
1919 tp=ed[up][us];
1920 t=x*ptsq[3*tp]+y*ptsq[3*tp+1]+z*ptsq[3*tp+2];
1921 if(t>g) {
1922 ls=ed[up][nu[up]+us];
1923 up=tp;
1924 while (t<rsq) {
1925 if(++count>=p) {
1926 #if VOROPP_VERBOSE >=1
1927 fputs("Bailed out of convex calculation",stderr);
1928 #endif
1929 for(tp=0;tp<p;tp++) if(x*ptsq[3*tp]+y*ptsq[3*tp+1]+z*ptsq[3*tp+2]>rsq) return true;
1930 return false;
1933 // Test all the neighbors of the current point
1934 // and find the one which is closest to the
1935 // plane
1936 for(us=0;us<ls;us++) {
1937 tp=ed[up][us];
1938 g=x*ptsq[3*tp]+y*ptsq[3*tp+1]+z*ptsq[3*tp+2];
1939 if(g>t) break;
1941 if(us==ls) {
1942 us++;
1943 while(us<nu[up]) {
1944 tp=ed[up][us];
1945 g=x*ptsq[3*tp]+y*ptsq[3*tp+1]+z*ptsq[3*tp+2];
1946 if(g>t) break;
1947 us++;
1949 if(us==nu[up]) return false;
1951 ls=ed[up][nu[up]+us];up=tp;t=g;
1953 return true;
1956 return false;
1959 /** Counts the number of edges of the Voronoi cell.
1960 * \return the number of edges. */
1961 int voronoicell_base::number_of_edges() {
1962 int edges=0,*nup=nu;
1963 while(nup<nu+p) edges+=*(nup++);
1964 return edges>>1;
1967 /** Outputs a custom string of information about the Voronoi cell. The string
1968 * of information follows a similar style as the C printf command, and detailed
1969 * information about its format is available at
1970 * http://math.lbl.gov/voro++/doc/custom.html.
1971 * \param[in] format the custom string to print.
1972 * \param[in] i the ID of the particle associated with this Voronoi cell.
1973 * \param[in] (x,y,z) the position of the particle associated with this Voronoi
1974 * cell.
1975 * \param[in] r a radius associated with the particle.
1976 * \param[in] fp the file handle to write to. */
1977 void voronoicell_base::output_custom(const char *format,int i,double x,double y,double z,double r,FILE *fp) {
1978 char *fmp=(const_cast<char*>(format));
1979 vector<int> vi;
1980 vector<double> vd;
1981 while(*fmp!=0) {
1982 if(*fmp=='%') {
1983 fmp++;
1984 switch(*fmp) {
1986 // Particle-related output
1987 case 'i': fprintf(fp,"%d",i);break;
1988 case 'x': fprintf(fp,"%g",x);break;
1989 case 'y': fprintf(fp,"%g",y);break;
1990 case 'z': fprintf(fp,"%g",z);break;
1991 case 'q': fprintf(fp,"%g %g %g",x,y,z);break;
1992 case 'r': fprintf(fp,"%g",r);break;
1994 // Vertex-related output
1995 case 'w': fprintf(fp,"%d",p);break;
1996 case 'p': output_vertices(fp);break;
1997 case 'P': output_vertices(x,y,z,fp);break;
1998 case 'o': output_vertex_orders(fp);break;
1999 case 'm': fprintf(fp,"%g",0.25*max_radius_squared());break;
2001 // Edge-related output
2002 case 'g': fprintf(fp,"%d",number_of_edges());break;
2003 case 'E': fprintf(fp,"%g",total_edge_distance());break;
2004 case 'e': face_perimeters(vd);voro_print_vector(vd,fp);break;
2006 // Face-related output
2007 case 's': fprintf(fp,"%d",number_of_faces());break;
2008 case 'F': fprintf(fp,"%g",surface_area());break;
2009 case 'A': {
2010 face_freq_table(vi);
2011 voro_print_vector(vi,fp);
2012 } break;
2013 case 'a': face_orders(vi);voro_print_vector(vi,fp);break;
2014 case 'f': face_areas(vd);voro_print_vector(vd,fp);break;
2015 case 't': {
2016 face_vertices(vi);
2017 voro_print_face_vertices(vi,fp);
2018 } break;
2019 case 'l': normals(vd);
2020 voro_print_positions(vd,fp);
2021 break;
2022 case 'n': neighbors(vi);
2023 voro_print_vector(vi,fp);
2024 break;
2026 // Volume-related output
2027 case 'v': fprintf(fp,"%g",volume());break;
2028 case 'c': {
2029 double cx,cy,cz;
2030 centroid(cx,cy,cz);
2031 fprintf(fp,"%g %g %g",cx,cy,cz);
2032 } break;
2033 case 'C': {
2034 double cx,cy,cz;
2035 centroid(cx,cy,cz);
2036 fprintf(fp,"%g %g %g",x+cx,y+cy,z+cz);
2037 } break;
2039 // End-of-string reached
2040 case 0: fmp--;break;
2042 // The percent sign is not part of a
2043 // control sequence
2044 default: putc('%',fp);putc(*fmp,fp);
2046 } else putc(*fmp,fp);
2047 fmp++;
2049 fputs("\n",fp);
2052 /** This initializes the class to be a rectangular box. It calls the base class
2053 * initialization routine to set up the edge and vertex information, and then
2054 * sets up the neighbor information, with initial faces being assigned ID
2055 * numbers from -1 to -6.
2056 * \param[in] (xmin,xmax) the minimum and maximum x coordinates.
2057 * \param[in] (ymin,ymax) the minimum and maximum y coordinates.
2058 * \param[in] (zmin,zmax) the minimum and maximum z coordinates. */
2059 void voronoicell_neighbor::init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax) {
2060 init_base(xmin,xmax,ymin,ymax,zmin,zmax);
2061 int *q=mne[3];
2062 *q=-5;q[1]=-3;q[2]=-1;
2063 q[3]=-5;q[4]=-2;q[5]=-3;
2064 q[6]=-5;q[7]=-1;q[8]=-4;
2065 q[9]=-5;q[10]=-4;q[11]=-2;
2066 q[12]=-6;q[13]=-1;q[14]=-3;
2067 q[15]=-6;q[16]=-3;q[17]=-2;
2068 q[18]=-6;q[19]=-4;q[20]=-1;
2069 q[21]=-6;q[22]=-2;q[23]=-4;
2070 *ne=q;ne[1]=q+3;ne[2]=q+6;ne[3]=q+9;
2071 ne[4]=q+12;ne[5]=q+15;ne[6]=q+18;ne[7]=q+21;
2074 /** This initializes the class to be an octahedron. It calls the base class
2075 * initialization routine to set up the edge and vertex information, and then
2076 * sets up the neighbor information, with the initial faces being assigned ID
2077 * numbers from -1 to -8.
2078 * \param[in] l The distance from the octahedron center to a vertex. Six
2079 * vertices are initialized at (-l,0,0), (l,0,0), (0,-l,0),
2080 * (0,l,0), (0,0,-l), and (0,0,l). */
2081 void voronoicell_neighbor::init_octahedron(double l) {
2082 init_octahedron_base(l);
2083 int *q=mne[4];
2084 *q=-5;q[1]=-6;q[2]=-7;q[3]=-8;
2085 q[4]=-1;q[5]=-2;q[6]=-3;q[7]=-4;
2086 q[8]=-6;q[9]=-5;q[10]=-2;q[11]=-1;
2087 q[12]=-8;q[13]=-7;q[14]=-4;q[15]=-3;
2088 q[16]=-5;q[17]=-8;q[18]=-3;q[19]=-2;
2089 q[20]=-7;q[21]=-6;q[22]=-1;q[23]=-4;
2090 *ne=q;ne[1]=q+4;ne[2]=q+8;ne[3]=q+12;ne[4]=q+16;ne[5]=q+20;
2093 /** This initializes the class to be a tetrahedron. It calls the base class
2094 * initialization routine to set up the edge and vertex information, and then
2095 * sets up the neighbor information, with the initial faces being assigned ID
2096 * numbers from -1 to -4.
2097 * \param (x0,y0,z0) a position vector for the first vertex.
2098 * \param (x1,y1,z1) a position vector for the second vertex.
2099 * \param (x2,y2,z2) a position vector for the third vertex.
2100 * \param (x3,y3,z3) a position vector for the fourth vertex. */
2101 void voronoicell_neighbor::init_tetrahedron(double x0,double y0,double z0,double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3) {
2102 init_tetrahedron_base(x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3);
2103 int *q=mne[3];
2104 *q=-4;q[1]=-3;q[2]=-2;
2105 q[3]=-3;q[4]=-4;q[5]=-1;
2106 q[6]=-4;q[7]=-2;q[8]=-1;
2107 q[9]=-2;q[10]=-3;q[11]=-1;
2108 *ne=q;ne[1]=q+3;ne[2]=q+6;ne[3]=q+9;
2111 /** This routine checks to make sure the neighbor information of each face is
2112 * consistent. */
2113 void voronoicell_neighbor::check_facets() {
2114 int i,j,k,l,m,q;
2115 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
2116 k=ed[i][j];
2117 if(k>=0) {
2118 ed[i][j]=-1-k;
2119 q=ne[i][j];
2120 l=cycle_up(ed[i][nu[i]+j],k);
2121 do {
2122 m=ed[k][l];
2123 ed[k][l]=-1-m;
2124 if(ne[k][l]!=q) fprintf(stderr,"Facet error at (%d,%d)=%d, started from (%d,%d)=%d\n",k,l,ne[k][l],i,j,q);
2125 l=cycle_up(ed[k][nu[k]+l],m);
2126 k=m;
2127 } while (k!=i);
2130 reset_edges();
2133 /** The class constructor allocates memory for storing neighbor information. */
2134 voronoicell_neighbor::voronoicell_neighbor() {
2135 int i;
2136 mne=new int*[current_vertex_order];
2137 ne=new int*[current_vertices];
2138 for(i=0;i<3;i++) mne[i]=new int[init_n_vertices*i];
2139 mne[3]=new int[init_3_vertices*3];
2140 for(i=4;i<current_vertex_order;i++) mne[i]=new int[init_n_vertices*i];
2143 /** The class destructor frees the dynamically allocated memory for storing
2144 * neighbor information. */
2145 voronoicell_neighbor::~voronoicell_neighbor() {
2146 for(int i=current_vertex_order-1;i>=0;i--) if(mem[i]>0) delete [] mne[i];
2147 delete [] mne;
2148 delete [] ne;
2151 /** Computes a vector list of neighbors. */
2152 void voronoicell_neighbor::neighbors(vector<int> &v) {
2153 v.clear();
2154 int i,j,k,l,m;
2155 for(i=1;i<p;i++) for(j=0;j<nu[i];j++) {
2156 k=ed[i][j];
2157 if(k>=0) {
2158 v.push_back(ne[i][j]);
2159 ed[i][j]=-1-k;
2160 l=cycle_up(ed[i][nu[i]+j],k);
2161 do {
2162 m=ed[k][l];
2163 ed[k][l]=-1-m;
2164 l=cycle_up(ed[k][nu[k]+l],m);
2165 k=m;
2166 } while (k!=i);
2169 reset_edges();
2172 /** Prints the vertices, their edges, the relation table, and also notifies if
2173 * any memory errors are visible. */
2174 void voronoicell_base::print_edges() {
2175 if(!synced) sync();
2176 int j;
2177 double *ptsp=pts;
2178 for(int i=0;i<p;i++,ptsp+=3) {
2179 printf("%d %d ",i,nu[i]);
2180 for(j=0;j<nu[i];j++) printf(" %d",ed[i][j]);
2181 printf(" ");
2182 while(j<(nu[i]<<1)) printf(" %d",ed[i][j]);
2183 printf(" %d",ed[i][j]);
2184 print_edges_neighbors(i);
2185 printf(" %g %g %g %p",*ptsp,ptsp[1],ptsp[2],(void*) ed[i]);
2186 if(ed[i]>=mep[nu[i]]+mec[nu[i]]*((nu[i]<<1)+1)) puts(" Memory error");
2187 else puts("");
2191 /** This prints out the neighbor information for vertex i. */
2192 void voronoicell_neighbor::print_edges_neighbors(int i) {
2193 if(nu[i]>0) {
2194 int j=0;
2195 printf(" (");
2196 while(j<nu[i]-1) printf("%d,",ne[i][j++]);
2197 printf("%d)",ne[i][j]);
2198 } else printf(" ()");
2201 void voronoicell_base::sync() {
2202 for(int i=0;i<3*p;i++) pts[i]=ptsq[i].get_d();
2205 // Explicit instantiation
2206 template bool voronoicell_base::nplane(voronoicell&,double,double,double,double,int);
2207 template bool voronoicell_base::nplane(voronoicell_neighbor&,double,double,double,double,int);
2208 template void voronoicell_base::check_memory_for_copy(voronoicell&,voronoicell_base*);
2209 template void voronoicell_base::check_memory_for_copy(voronoicell_neighbor&,voronoicell_base*);