ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/REPOS_ERICCA/poly_occ/voro++-0.4.6/src/cell.cc
Revision: 979
Committed: Thu Oct 18 23:40:32 2018 UTC (6 years, 7 months ago) by francois
File size: 68742 byte(s)
Log Message:
creation de polycristaux avec OCC

File Contents

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