1 // Voro++, a 3D cell-based Voronoi library
3 // Author : Chris H. Rycroft (LBL / UC Berkeley)
4 // Email : chr@alum.mit.edu
5 // Date : August 30th 2011
8 * \brief Function implementations for the voronoicell and related classes. */
19 /** Constructs a Voronoi cell and sets up the initial memory. */
20 voronoicell_base::voronoicell_base(double max_len_sq
) :
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 current_xsearch_size(init_xsearch_size
),
24 ed(new int*[current_vertices
]), nu(new int[current_vertices
]),
25 mask(new unsigned int[current_vertices
]),
26 pts(new double[current_vertices
<<2]), tol(tolerance
*max_len_sq
),
27 tol_cu(tol
*sqrt(tol
)), big_tol(big_tolerance_fac
*tol
), mem(new int[current_vertex_order
]),
28 mec(new int[current_vertex_order
]),
29 mep(new int*[current_vertex_order
]), ds(new int[current_delete_size
]),
30 stacke(ds
+current_delete_size
), ds2(new int[current_delete2_size
]),
31 stacke2(ds2
+current_delete2_size
), xse(new int[current_xsearch_size
]),
32 stacke3(xse
+current_xsearch_size
), maskc(0) {
34 for(i
=0;i
<current_vertices
;i
++) mask
[i
]=0;
36 mem
[i
]=init_n_vertices
;mec
[i
]=0;
37 mep
[i
]=new int[init_n_vertices
*((i
<<1)+1)];
39 mem
[3]=init_3_vertices
;mec
[3]=0;
40 mep
[3]=new int[init_3_vertices
*7];
41 for(i
=4;i
<current_vertex_order
;i
++) {
42 mem
[i
]=init_n_vertices
;mec
[i
]=0;
43 mep
[i
]=new int[init_n_vertices
*((i
<<1)+1)];
47 /** The voronoicell destructor deallocates all the dynamic memory. */
48 voronoicell_base::~voronoicell_base() {
49 for(int i
=current_vertex_order
-1;i
>=0;i
--) if(mem
[i
]>0) delete [] mep
[i
];
51 delete [] ds2
;delete [] ds
;
52 delete [] mep
;delete [] mec
;
53 delete [] mem
;delete [] pts
;
55 delete [] nu
;delete [] ed
;
58 /** Ensures that enough memory is allocated prior to carrying out a copy.
59 * \param[in] vc a reference to the specialized version of the calling class.
60 * \param[in] vb a pointered to the class to be copied. */
61 template<class vc_class
>
62 void voronoicell_base::check_memory_for_copy(vc_class
&vc
,voronoicell_base
* vb
) {
63 while(current_vertex_order
<vb
->current_vertex_order
) add_memory_vorder(vc
);
64 for(int i
=0;i
<current_vertex_order
;i
++) while(mem
[i
]<vb
->mec
[i
]) add_memory(vc
,i
);
65 while(current_vertices
<vb
->p
) add_memory_vertices(vc
);
68 /** Copies the vertex and edge information from another class. The routine
69 * assumes that enough memory is available for the copy.
70 * \param[in] vb a pointer to the class to copy. */
71 void voronoicell_base::copy(voronoicell_base
* vb
) {
74 for(i
=0;i
<current_vertex_order
;i
++) {
76 for(j
=0;j
<mec
[i
]*(2*i
+1);j
++) mep
[i
][j
]=vb
->mep
[i
][j
];
77 for(j
=0;j
<mec
[i
]*(2*i
+1);j
+=2*i
+1) ed
[mep
[i
][j
+2*i
]]=mep
[i
]+j
;
79 for(i
=0;i
<p
;i
++) nu
[i
]=vb
->nu
[i
];
80 for(i
=0;i
<(p
<<2);i
++) pts
[i
]=vb
->pts
[i
];
83 /** Copies the information from another voronoicell class into this
84 * class, extending memory allocation if necessary.
85 * \param[in] c the class to copy. */
86 void voronoicell_neighbor::operator=(voronoicell
&c
) {
87 voronoicell_base
*vb
=((voronoicell_base
*) &c
);
88 check_memory_for_copy(*this,vb
);copy(vb
);
90 for(i
=0;i
<c
.current_vertex_order
;i
++) {
91 for(j
=0;j
<c
.mec
[i
]*i
;j
++) mne
[i
][j
]=0;
92 for(j
=0;j
<c
.mec
[i
];j
++) ne
[c
.mep
[i
][(2*i
+1)*j
+2*i
]]=mne
[i
]+(j
*i
);
96 /** Copies the information from another voronoicell_neighbor class into this
97 * class, extending memory allocation if necessary.
98 * \param[in] c the class to copy. */
99 void voronoicell_neighbor::operator=(voronoicell_neighbor
&c
) {
100 voronoicell_base
*vb
=((voronoicell_base
*) &c
);
101 check_memory_for_copy(*this,vb
);copy(vb
);
103 for(i
=0;i
<c
.current_vertex_order
;i
++) {
104 for(j
=0;j
<c
.mec
[i
]*i
;j
++) mne
[i
][j
]=c
.mne
[i
][j
];
105 for(j
=0;j
<c
.mec
[i
];j
++) ne
[c
.mep
[i
][(2*i
+1)*j
+2*i
]]=mne
[i
]+(j
*i
);
109 /** Translates the vertices of the Voronoi cell by a given vector.
110 * \param[in] (x,y,z) the coordinates of the vector. */
111 void voronoicell_base::translate(double x
,double y
,double z
) {
114 while(ptsp
<pts
+(p
<<2)) {
115 *(ptsp
++)+=x
;*(ptsp
++)+=y
;*ptsp
+=z
;ptsp
+=2;
119 /** Increases the memory storage for a particular vertex order, by increasing
120 * the size of the of the corresponding mep array. If the arrays already exist,
121 * their size is doubled; if they don't exist, then new ones of size
122 * init_n_vertices are allocated. The routine also ensures that the pointers in
123 * the ed array are updated, by making use of the back pointers. For the cases
124 * where the back pointer has been temporarily overwritten in the marginal
125 * vertex code, the auxiliary delete stack is scanned to find out how to update
126 * the ed value. If the template has been instantiated with the neighbor
127 * tracking turned on, then the routine also reallocates the corresponding mne
129 * \param[in] i the order of the vertex memory to be increased. */
130 template<class vc_class
>
131 void voronoicell_base::add_memory(vc_class
&vc
,int i
) {
134 vc
.n_allocate(i
,init_n_vertices
);
135 mep
[i
]=new int[init_n_vertices
*s
];
136 mem
[i
]=init_n_vertices
;
137 #if VOROPP_VERBOSE >=2
138 fprintf(stderr
,"Order %d vertex memory created\n",i
);
143 if(mem
[i
]>max_n_vertices
) voro_fatal_error("Point memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR
);
144 #if VOROPP_VERBOSE >=2
145 fprintf(stderr
,"Order %d vertex memory scaled up to %d\n",i
,mem
[i
]);
149 vc
.n_allocate_aux1(i
);
154 vc
.n_set_to_aux1_offset(k
,m
);
157 for(dsp
=ds2
;dsp
<stackp2
;dsp
++) {
158 if(ed
[*dsp
]==mep
[i
]+j
) {
160 vc
.n_set_to_aux1_offset(*dsp
,m
);
165 for(dsp
=xse
;dsp
<stackp3
;dsp
++) {
166 if(ed
[*dsp
]==mep
[i
]+j
) {
168 vc
.n_set_to_aux1_offset(*dsp
,m
);
172 if(dsp
==stackp3
) voro_fatal_error("Couldn't relocate dangling pointer",VOROPP_INTERNAL_ERROR
);
174 #if VOROPP_VERBOSE >=3
175 fputs("Relocated dangling pointer",stderr
);
178 for(k
=0;k
<s
;k
++,j
++) l
[j
]=mep
[i
][j
];
179 for(k
=0;k
<i
;k
++,m
++) vc
.n_copy_to_aux1(i
,m
);
183 vc
.n_switch_to_aux1(i
);
187 /** Doubles the maximum number of vertices allowed, by reallocating the ed, nu,
188 * and pts arrays. If the allocation exceeds the absolute maximum set in
189 * max_vertices, then the routine exits with a fatal error. If the template has
190 * been instantiated with the neighbor tracking turned on, then the routine
191 * also reallocates the ne array. */
192 template<class vc_class
>
193 void voronoicell_base::add_memory_vertices(vc_class
&vc
) {
194 int i
=(current_vertices
<<1),j
,**pp
,*pnu
;
196 if(i
>max_vertices
) voro_fatal_error("Vertex memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR
);
197 #if VOROPP_VERBOSE >=2
198 fprintf(stderr
,"Vertex memory scaled up to %d\n",i
);
202 for(j
=0;j
<current_vertices
;j
++) pp
[j
]=ed
[j
];
204 vc
.n_add_memory_vertices(i
);
206 for(j
=0;j
<current_vertices
;j
++) pnu
[j
]=nu
[j
];
208 pmask
=new unsigned int[i
];
209 for(j
=0;j
<current_vertices
;j
++) pmask
[j
]=mask
[j
];
210 while(j
<i
) pmask
[j
++]=0;
211 delete [] mask
;mask
=pmask
;
212 ppts
=new double[i
<<2];
213 for(j
=0;j
<(current_vertices
<<2);j
++) ppts
[j
]=pts
[j
];
214 delete [] pts
;pts
=ppts
;
218 /** Doubles the maximum allowed vertex order, by reallocating mem, mep, and mec
219 * arrays. If the allocation exceeds the absolute maximum set in
220 * max_vertex_order, then the routine causes a fatal error. If the template has
221 * been instantiated with the neighbor tracking turned on, then the routine
222 * also reallocates the mne array. */
223 template<class vc_class
>
224 void voronoicell_base::add_memory_vorder(vc_class
&vc
) {
225 int i
=(current_vertex_order
<<1),j
,*p1
,**p2
;
226 if(i
>max_vertex_order
) voro_fatal_error("Vertex order memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR
);
227 #if VOROPP_VERBOSE >=2
228 fprintf(stderr
,"Vertex order memory scaled up to %d\n",i
);
231 for(j
=0;j
<current_vertex_order
;j
++) p1
[j
]=mem
[j
];while(j
<i
) p1
[j
++]=0;
232 delete [] mem
;mem
=p1
;
234 for(j
=0;j
<current_vertex_order
;j
++) p2
[j
]=mep
[j
];
235 delete [] mep
;mep
=p2
;
237 for(j
=0;j
<current_vertex_order
;j
++) p1
[j
]=mec
[j
];while(j
<i
) p1
[j
++]=0;
238 delete [] mec
;mec
=p1
;
239 vc
.n_add_memory_vorder(i
);
240 current_vertex_order
=i
;
243 /** Doubles the size allocation of the main delete stack. If the allocation
244 * exceeds the absolute maximum set in max_delete_size, then routine causes a
246 void voronoicell_base::add_memory_ds() {
247 current_delete_size
<<=1;
248 if(current_delete_size
>max_delete_size
) voro_fatal_error("Delete stack 1 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR
);
249 #if VOROPP_VERBOSE >=2
250 fprintf(stderr
,"Delete stack 1 memory scaled up to %d\n",current_delete_size
);
252 int *dsn
=new int[current_delete_size
],*dsnp
=dsn
,*dsp
=ds
;
253 while(dsp
<stackp
) *(dsnp
++)=*(dsp
++);
254 delete [] ds
;ds
=dsn
;stackp
=dsnp
;
255 stacke
=ds
+current_delete_size
;
258 /** Doubles the size allocation of the auxiliary delete stack. If the
259 * allocation exceeds the absolute maximum set in max_delete2_size, then the
260 * routine causes a fatal error. */
261 void voronoicell_base::add_memory_ds2() {
262 current_delete2_size
<<=1;
263 if(current_delete2_size
>max_delete2_size
) voro_fatal_error("Delete stack 2 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR
);
264 #if VOROPP_VERBOSE >=2
265 fprintf(stderr
,"Delete stack 2 memory scaled up to %d\n",current_delete2_size
);
267 int *dsn
=new int[current_delete2_size
],*dsnp
=dsn
,*dsp
=ds2
;
268 while(dsp
<stackp2
) *(dsnp
++)=*(dsp
++);
269 delete [] ds2
;ds2
=dsn
;stackp2
=dsnp
;
270 stacke2
=ds2
+current_delete2_size
;
273 /** Doubles the size allocation of the auxiliary delete stack. If the
274 * allocation exceeds the absolute maximum set in max_delete2_size, then the
275 * routine causes a fatal error. */
276 void voronoicell_base::add_memory_xse() {
277 current_xsearch_size
<<=1;
278 if(current_xsearch_size
>max_xsearch_size
) voro_fatal_error("Extra search stack memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR
);
279 #if VOROPP_VERBOSE >=2
280 fprintf(stderr
,"Extra search stack memory scaled up to %d\n",current_xsearch_size
);
282 int *dsn
=new int[current_xsearch_size
],*dsnp
=dsn
,*dsp
=xse
;
283 while(dsp
<stackp3
) *(dsnp
++)=*(dsp
++);
284 delete [] xse
;xse
=dsn
;stackp3
=dsnp
;
285 stacke3
=xse
+current_xsearch_size
;
289 /** Initializes a Voronoi cell as a rectangular box with the given dimensions.
290 * \param[in] (xmin,xmax) the minimum and maximum x coordinates.
291 * \param[in] (ymin,ymax) the minimum and maximum y coordinates.
292 * \param[in] (zmin,zmax) the minimum and maximum z coordinates. */
293 void voronoicell_base::init_base(double xmin
,double xmax
,double ymin
,double ymax
,double zmin
,double zmax
) {
294 for(int i
=0;i
<current_vertex_order
;i
++) mec
[i
]=0;up
=0;
295 mec
[3]=p
=8;xmin
*=2;xmax
*=2;ymin
*=2;ymax
*=2;zmin
*=2;zmax
*=2;
296 *pts
=xmin
;pts
[1]=ymin
;pts
[2]=zmin
;
297 pts
[4]=xmax
;pts
[5]=ymin
;pts
[6]=zmin
;
298 pts
[8]=xmin
;pts
[9]=ymax
;pts
[10]=zmin
;
299 pts
[12]=xmax
;pts
[13]=ymax
;pts
[14]=zmin
;
300 pts
[16]=xmin
;pts
[17]=ymin
;pts
[18]=zmax
;
301 pts
[20]=xmax
;pts
[21]=ymin
;pts
[22]=zmax
;
302 pts
[24]=xmin
;pts
[25]=ymax
;pts
[26]=zmax
;
303 pts
[28]=xmax
;pts
[29]=ymax
;pts
[30]=zmax
;
305 *q
=1;q
[1]=4;q
[2]=2;q
[3]=2;q
[4]=1;q
[5]=0;q
[6]=0;
306 q
[7]=3;q
[8]=5;q
[9]=0;q
[10]=2;q
[11]=1;q
[12]=0;q
[13]=1;
307 q
[14]=0;q
[15]=6;q
[16]=3;q
[17]=2;q
[18]=1;q
[19]=0;q
[20]=2;
308 q
[21]=2;q
[22]=7;q
[23]=1;q
[24]=2;q
[25]=1;q
[26]=0;q
[27]=3;
309 q
[28]=6;q
[29]=0;q
[30]=5;q
[31]=2;q
[32]=1;q
[33]=0;q
[34]=4;
310 q
[35]=4;q
[36]=1;q
[37]=7;q
[38]=2;q
[39]=1;q
[40]=0;q
[41]=5;
311 q
[42]=7;q
[43]=2;q
[44]=4;q
[45]=2;q
[46]=1;q
[47]=0;q
[48]=6;
312 q
[49]=5;q
[50]=3;q
[51]=6;q
[52]=2;q
[53]=1;q
[54]=0;q
[55]=7;
313 *ed
=q
;ed
[1]=q
+7;ed
[2]=q
+14;ed
[3]=q
+21;
314 ed
[4]=q
+28;ed
[5]=q
+35;ed
[6]=q
+42;ed
[7]=q
+49;
315 *nu
=nu
[1]=nu
[2]=nu
[3]=nu
[4]=nu
[5]=nu
[6]=nu
[7]=3;
318 /** Initializes an L-shaped Voronoi cell of a fixed size for testing the
319 * convexity robustness. */
320 void voronoicell::init_l_shape() {
321 for(int i
=0;i
<current_vertex_order
;i
++) mec
[i
]=0;up
=0;
324 *pts
=-2;pts
[1]=-2;pts
[2]=-2;
325 pts
[4]=2;pts
[5]=-2;pts
[6]=-2;
326 pts
[8]=-2;pts
[9]=0;pts
[10]=-2;
327 pts
[12]=-j
;pts
[13]=j
;pts
[14]=-2;
328 pts
[16]=0;pts
[17]=2;pts
[18]=-2;
329 pts
[20]=2;pts
[21]=2;pts
[22]=-2;
330 pts
[24]=-2;pts
[25]=-2;pts
[26]=2;
331 pts
[28]=2;pts
[29]=-2;pts
[30]=2;
332 pts
[32]=-2;pts
[33]=0;pts
[34]=2;
333 pts
[36]=-j
;pts
[37]=j
;pts
[38]=2;
334 pts
[40]=0;pts
[41]=2;pts
[42]=2;
335 pts
[44]=2;pts
[45]=2;pts
[46]=2;
337 *q
=1;q
[1]=6;q
[2]=2;q
[6]=0;
338 q
[7]=5;q
[8]=7;q
[9]=0;q
[13]=1;
339 q
[14]=0;q
[15]=8;q
[16]=3;q
[20]=2;
340 q
[21]=2;q
[22]=9;q
[23]=4;q
[27]=3;
341 q
[28]=3;q
[29]=10;q
[30]=5;q
[34]=4;
342 q
[35]=4;q
[36]=11;q
[37]=1;q
[41]=5;
343 q
[42]=8;q
[43]=0;q
[44]=7;q
[48]=6;
344 q
[49]=6;q
[50]=1;q
[51]=11;q
[55]=7;
345 q
[56]=9;q
[57]=2;q
[58]=6;q
[62]=8;
346 q
[63]=10;q
[64]=3;q
[65]=8;q
[69]=9;
347 q
[70]=11;q
[71]=4;q
[72]=9;q
[76]=10;
348 q
[77]=7;q
[78]=5;q
[79]=10;q
[83]=11;
349 *ed
=q
;ed
[1]=q
+7;ed
[2]=q
+14;ed
[3]=q
+21;ed
[4]=q
+28;ed
[5]=q
+35;
350 ed
[6]=q
+42;ed
[7]=q
+49;ed
[8]=q
+56;ed
[9]=q
+63;ed
[10]=q
+70;ed
[11]=q
+77;
351 for(int i
=0;i
<12;i
++) nu
[i
]=3;
352 construct_relations();
355 /** Initializes a Voronoi cell as a regular octahedron.
356 * \param[in] l The distance from the octahedron center to a vertex. Six
357 * vertices are initialized at (-l,0,0), (l,0,0), (0,-l,0),
358 * (0,l,0), (0,0,-l), and (0,0,l). */
359 void voronoicell_base::init_octahedron_base(double l
) {
360 for(int i
=0;i
<current_vertex_order
;i
++) mec
[i
]=0;up
=0;
362 *pts
=-l
;pts
[1]=0;pts
[2]=0;
363 pts
[4]=l
;pts
[5]=0;pts
[6]=0;
364 pts
[8]=0;pts
[9]=-l
;pts
[10]=0;
365 pts
[12]=0;pts
[13]=l
;pts
[14]=0;
366 pts
[16]=0;pts
[17]=0;pts
[18]=-l
;
367 pts
[20]=0;pts
[21]=0;pts
[22]=l
;
369 *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;
370 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;
371 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;
372 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;
373 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;
374 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;
375 *ed
=q
;ed
[1]=q
+9;ed
[2]=q
+18;ed
[3]=q
+27;ed
[4]=q
+36;ed
[5]=q
+45;
376 *nu
=nu
[1]=nu
[2]=nu
[3]=nu
[4]=nu
[5]=4;
379 /** Initializes a Voronoi cell as a tetrahedron. It assumes that the normal to
380 * the face for the first three vertices points inside.
381 * \param (x0,y0,z0) a position vector for the first vertex.
382 * \param (x1,y1,z1) a position vector for the second vertex.
383 * \param (x2,y2,z2) a position vector for the third vertex.
384 * \param (x3,y3,z3) a position vector for the fourth vertex. */
385 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
) {
386 for(int i
=0;i
<current_vertex_order
;i
++) mec
[i
]=0;up
=0;
388 *pts
=x0
*2;pts
[1]=y0
*2;pts
[2]=z0
*2;
389 pts
[4]=x1
*2;pts
[5]=y1
*2;pts
[6]=z1
*2;
390 pts
[8]=x2
*2;pts
[9]=y2
*2;pts
[10]=z2
*2;
391 pts
[12]=x3
*2;pts
[13]=y3
*2;pts
[14]=z3
*2;
393 *q
=1;q
[1]=3;q
[2]=2;q
[3]=0;q
[4]=0;q
[5]=0;q
[6]=0;
394 q
[7]=0;q
[8]=2;q
[9]=3;q
[10]=0;q
[11]=2;q
[12]=1;q
[13]=1;
395 q
[14]=0;q
[15]=3;q
[16]=1;q
[17]=2;q
[18]=2;q
[19]=1;q
[20]=2;
396 q
[21]=0;q
[22]=1;q
[23]=2;q
[24]=1;q
[25]=2;q
[26]=1;q
[27]=3;
397 *ed
=q
;ed
[1]=q
+7;ed
[2]=q
+14;ed
[3]=q
+21;
398 *nu
=nu
[1]=nu
[2]=nu
[3]=3;
401 /** Checks that the relational table of the Voronoi cell is accurate, and
402 * prints out any errors. This algorithm is O(p), so running it every time the
403 * plane routine is called will result in a significant slowdown. */
404 void voronoicell_base::check_relations() {
406 for(i
=0;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) if(ed
[ed
[i
][j
]][ed
[i
][nu
[i
]+j
]]!=i
)
407 printf("Relational error at point %d, edge %d.\n",i
,j
);
410 /** This routine checks for any two vertices that are connected by more than
411 * one edge. The plane algorithm is designed so that this should not happen, so
412 * any occurrences are most likely errors. Note that the routine is O(p), so
413 * running it every time the plane routine is called will result in a
414 * significant slowdown. */
415 void voronoicell_base::check_duplicates() {
417 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
])
418 printf("Duplicate edges: (%d,%d) and (%d,%d) [%d]\n",i
,j
,i
,k
,ed
[i
][j
]);
421 /** Constructs the relational table if the edges have been specified. */
422 void voronoicell_base::construct_relations() {
424 for(i
=0;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
429 if(l
==nu
[k
]) voro_fatal_error("Relation table construction failed",VOROPP_INTERNAL_ERROR
);
435 /** Starting from a point within the current cutting plane, this routine attempts
436 * to find an edge to a point outside the cutting plane. This prevents the plane
438 * \param[in,out] up */
439 inline bool voronoicell_base::search_for_outside_edge(int &up
) {
440 int i
,lp
,lw
,*j
=ds2
,sc2
=stackp2
-ds2
;
445 for(i
=0;i
<nu
[up
];i
++) {
452 else if(lw
==1) add_to_stack(sc2
,lp
);
459 /** Adds a point to the auxiliary delete stack if it is not already there.
460 * \param[in] vc a reference to the specialized version of the calling class.
461 * \param[in] lp the index of the point to add.
462 * \param[in,out] stackp2 a pointer to the end of the stack entries. */
463 inline void voronoicell_base::add_to_stack(int sc2
,int lp
) {
464 for(int *k
=ds2
+sc2
;k
<stackp2
;k
++) if(*k
==lp
) return;
465 if(stackp2
==stacke2
) add_memory_ds2();
469 /** Assuming that the point up is outside the cutting plane, this routine
470 * searches upwards along edges trying to find an edge that intersects the
472 * \param[in] rsq the distance along this vector of the plane.
473 * \param[in,out] u the dot product of point up with the normal.
474 * \return True if the cutting plane was reached, false otherwise. */
475 inline bool voronoicell_base::search_upward(unsigned int &uw
,int &lp
,int &ls
,int &us
,double &l
,double &u
) {
479 // The test point is outside of the cutting space
480 for(ls
=0;ls
<nu
[lp
];ls
++) {
485 if(ls
==nu
[lp
]) if(definite_max(lp
,ls
,l
,u
,uw
)) {
491 //if(++count>=p) failsafe_find(lp,ls,us,l,u);
493 // Test all the neighbors of the current point
494 // and find the one which is closest to the
496 vs
=ed
[lp
][nu
[lp
]+ls
];lp
=up
;l
=u
;
497 for(ls
=0;ls
<nu
[lp
];ls
++) {
503 if(ls
==nu
[lp
]&&definite_max(lp
,ls
,l
,u
,uw
)) {
508 us
=ed
[lp
][nu
[lp
]+ls
];
512 /** Checks whether a particular point lp is a definite maximum, searching
513 * through any possible minor non-convexities, for a better maximum.
514 * \param[in] (x,y,z) the normal vector to the plane. */
515 bool voronoicell_base::definite_max(int &lp
,int &ls
,double &l
,double &u
,unsigned int &uw
) {
520 // Check to see whether point up is a well-defined maximum. Otherwise
521 // any neighboring vertices of up that are marginal need to be
522 // followed, to see if they lead to a better maximum.
523 for(ts
=0;ts
<nu
[tp
];ts
++) {
526 if(q
>l
-big_tol
) break;
528 if(ts
==nu
[tp
]) return true;
530 // The point tp is marginal, so it will be necessary to do the
531 // flood-fill search. Mark the point tp and the point qp, and search
532 // any remaining neighbors of the point tp.
542 if(stackp
==stacke
) add_memory_ds();
549 // Consider additional marginal points, starting with the original
554 for(ts
=0;ts
<nu
[tp
];ts
++) {
557 // Skip the point if it's already marked
558 if(ed
[qp
][nu
[qp
]<<1]<0) continue;
561 // This point is a better maximum. Reset markers and
571 while(stackp
>ds
) flip(*(--stackp
));
575 // The point is marginal and therefore must also be
589 // Reset markers and return false
591 while(stackp
>ds
) flip(*(--stackp
));
595 inline bool voronoicell_base::search_downward(unsigned int &lw
,int &lp
,int &ls
,int &us
,double &l
,double &u
) {
598 // The test point is outside of the cutting space
599 for(us
=0;us
<nu
[up
];us
++) {
604 if(us
==nu
[up
]) if(definite_min(lp
,us
,l
,u
,lw
)) return false;
607 //if(++count>=p) failsafe_find(lp,ls,us,l,u);
609 // Test all the neighbors of the current point
610 // and find the one which is closest to the
612 vs
=ed
[up
][nu
[up
]+us
];up
=lp
;u
=l
;
613 for(us
=0;us
<nu
[up
];us
++) {
619 if(us
==nu
[up
]&&definite_min(lp
,us
,l
,u
,lw
)) return false;
621 ls
=ed
[up
][nu
[up
]+us
];
625 bool voronoicell_base::definite_min(int &lp
,int &us
,double &l
,double &u
,unsigned int &lw
) {
630 // Check to see whether point up is a well-defined maximum. Otherwise
631 // any neighboring vertices of up that are marginal need to be
632 // followed, to see if they lead to a better maximum.
633 for(ts
=0;ts
<nu
[tp
];ts
++) {
636 if(q
<u
+big_tol
) break;
638 if(ts
==nu
[tp
]) return true;
640 // The point tp is marginal, so it will be necessary to do the
641 // flood-fill search. Mark the point tp and the point qp, and search
642 // any remaining neighbors of the point tp.
652 if(stackp
==stacke
) add_memory_ds();
659 // Consider additional marginal points, starting with the original
664 for(ts
=0;ts
<nu
[tp
];ts
++) {
667 // Skip the point if it's already marked
668 if(ed
[qp
][nu
[qp
]<<1]<0) continue;
671 // This point is a better minimum. Reset markers and
681 while(stackp
>ds
) flip(*(--stackp
));
685 // The point is marginal and therefore must also be
699 // Reset markers and return false
701 while(stackp
>ds
) flip(*(--stackp
));
705 /** Cuts the Voronoi cell by a particle whose center is at a separation of
706 * (x,y,z) from the cell center. The value of rsq should be initially set to
708 * \param[in] vc a reference to the specialized version of the calling class.
709 * \param[in] (x,y,z) the normal vector to the plane.
710 * \param[in] rsq the distance along this vector of the plane.
711 * \param[in] p_id the plane ID (for neighbor tracking only).
712 * \return False if the plane cut deleted the cell entirely, true otherwise. */
713 template<class vc_class
>
714 bool voronoicell_base::nplane(vc_class
&vc
,double x
,double y
,double z
,double rsq
,int p_id
) {
715 int i
,j
,lp
=up
,cp
,qp
,*dsp
;
718 int *edp
,*edd
;stackp
=ds
;
721 // Initialize the safe testing routine
722 px
=x
;py
=y
;pz
=z
;prsq
=rsq
;
724 if(maskc
<4) reset_mask();
728 if(!search_downward(lw
,lp
,ls
,us
,l
,u
)) return false;
729 if(lw
==1) {up
=lp
;lp
=-1;}
731 if(!search_upward(uw
,lp
,ls
,us
,l
,u
)) return true;
737 // Set stack pointers
738 stackp
=ds
;stackp2
=ds2
;stackp3
=xse
;
740 // Store initial number of vertices
743 if(create_facet(vc
,lp
,ls
,l
,us
,u
,p_id
)) return false;
745 while(xse
+k
<stackp3
) {
748 for(ls
=0;ls
<nu
[lp
];ls
++) {
751 // Skip if this is a new vertex
756 if(u
>-big_tol
&&ed
[up
][nu
[up
]<<1]!=-1) {
757 ed
[up
][nu
[up
]<<1]=-1;
758 if(stackp3
==stacke3
) add_memory_xse();
763 // This is a possible facet starting
764 // from a vertex on the cutting plane
765 if(create_facet(vc
,-1,0,0,0,u
,p_id
)) return false;
768 // This is a new facet
769 us
=ed
[lp
][nu
[lp
]+ls
];
771 if(create_facet(vc
,lp
,ls
,l
,us
,u
,p_id
)) return false;
777 // Reset back pointers on extra search stack
778 for(dsp
=xse
;dsp
<stackp3
;dsp
++) {
783 // Delete points: first, remove any duplicates
787 if(ed
[j
][nu
[j
]]!=-1) {
790 } else *dsp
=*(--stackp
);
793 // Add the points in the auxiliary delete stack,
794 // and reset their back pointers
795 for(dsp
=ds2
;dsp
<stackp2
;dsp
++) {
798 if(ed
[j
][nu
[j
]]!=-1) {
800 if(stackp
==stacke
) add_memory_ds();
805 // Scan connections and add in extras
806 for(dsp
=ds
;dsp
<stackp
;dsp
++) {
808 for(edp
=ed
[cp
];edp
<ed
[cp
]+nu
[cp
];edp
++) {
810 if(qp
!=-1&&ed
[qp
][nu
[qp
]]!=-1) {
823 // Delete them from the array structure
826 while(ed
[p
][nu
[p
]]==-1) {
828 edp
=ed
[p
];edd
=(mep
[j
]+((j
<<1)+1)*--mec
[j
]);
829 while(edp
<ed
[p
]+(j
<<1)+1) *(edp
++)=*(edd
++);
830 vc
.n_set_aux2_copy(p
,j
);
831 vc
.n_copy_pointer(ed
[p
][(j
<<1)],p
);
832 ed
[ed
[p
][(j
<<1)]]=ed
[p
];
839 pts
[(up
<<2)]=pts
[(p
<<2)];
840 pts
[(up
<<2)+1]=pts
[(p
<<2)+1];
841 pts
[(up
<<2)+2]=pts
[(p
<<2)+2];
845 edp
=ed
[up
];edd
=(mep
[j
]+((j
<<1)+1)*--mec
[j
]);
846 while(edp
<ed
[up
]+(j
<<1)+1) *(edp
++)=*(edd
++);
847 vc
.n_set_aux2_copy(up
,j
);
848 vc
.n_copy_pointer(ed
[up
][j
<<1],up
);
849 vc
.n_copy_pointer(up
,p
);
850 ed
[ed
[up
][j
<<1]]=ed
[up
];
855 for(i
=0;i
<nu
[up
];i
++) ed
[ed
[up
][i
]][ed
[up
][nu
[up
]+i
]]=up
;
856 ed
[up
][nu
[up
]<<1]=up
;
860 // Check for any vertices of zero order
861 if(*mec
>0) voro_fatal_error("Zero order vertex formed",VOROPP_INTERNAL_ERROR
);
863 // Collapse any order 2 vertices and exit
864 return collapse_order2(vc
);
867 /** Creates a new facet.
868 * \return True if cell deleted, false otherwise. */
869 template<class vc_class
>
870 bool voronoicell_base::create_facet(vc_class
&vc
,int lp
,int ls
,double l
,int us
,double u
,int p_id
) {
871 int i
,j
,k
,qp
,qs
,iqs
,cp
,cs
,rp
,*edp
,*edd
;
873 bool new_double_edge
=false,double_edge
=false;
876 // We're about to add the first point of the new facet. In either
877 // routine, we have to add a point, so first check there's space for
879 if(p
==current_vertices
) add_memory_vertices(vc
);
883 // We want to be strict about reaching the conclusion that the
884 // cell is entirely within the cutting plane. It's not enough
885 // to find a vertex that has edges which are all inside or on
886 // the plane. If the vertex has neighbors that are also on the
887 // plane, we should check those too.
888 if(!search_for_outside_edge(up
)) return true;
890 // The search algorithm found a point which is on the cutting
891 // plane. We leave that point in place, and create a new one at
892 // the same location.
893 pts
[(p
<<2)]=pts
[(up
<<2)];
894 pts
[(p
<<2)+1]=pts
[(up
<<2)+1];
895 pts
[(p
<<2)+2]=pts
[(up
<<2)+2];
897 // Search for a collection of edges of the test vertex which
898 // are outside of the cutting space. Begin by testing the
905 // The first edge is either inside the cutting space,
906 // or lies within the cutting plane. Test the edges
907 // sequentially until we find one that is outside.
912 // If we reached the last edge with no luck
913 // then all of the vertices are inside
914 // or on the plane, so the cell is completely
916 if(i
==nu
[up
]) return true;
922 // We found an edge outside the cutting space. Keep
923 // moving through these edges until we find one that's
924 // inside or on the plane.
932 // Compute the number of edges for the new vertex. In
933 // general it will be the number of outside edges
934 // found, plus two. But we need to recognize the
935 // special case when all but one edge is outside, and
936 // the remaining one is on the plane. For that case we
937 // have to reduce the edge count by one to prevent
939 if(j
==nu
[up
]&&i
==1&&rw
==1) {
945 // Add memory for the new vertex if needed, and
947 while (nu
[p
]>=current_vertex_order
) add_memory_vorder(vc
);
948 if(mec
[nu
[p
]]==mem
[nu
[p
]]) add_memory(vc
,nu
[p
]);
949 vc
.n_set_pointer(p
,nu
[p
]);
950 ed
[p
]=mep
[nu
[p
]]+((nu
[p
]<<1)+1)*mec
[nu
[p
]]++;
953 // Copy the edges of the original vertex into the new
954 // one. Delete the edges of the original vertex, and
955 // update the relational table.
971 // In this case, the zeroth edge is outside the cutting
972 // plane. Begin by searching backwards from the last
973 // edge until we find an edge which isn't outside.
980 // If i reaches zero, then we have a point in
981 // the plane all of whose edges are outside
982 // the cutting space, so we just exit
983 if(i
==0) return false;
988 // Now search forwards from zero
998 // Compute the number of edges for the new vertex. In
999 // general it will be the number of outside edges
1000 // found, plus two. But we need to recognize the
1001 // special case when all but one edge is outside, and
1002 // the remaining one is on the plane. For that case we
1003 // have to reduce the edge count by one to prevent
1012 // Add memory to store the vertex if it doesn't exist
1015 while(nu
[p
]>=current_vertex_order
) add_memory_vorder(vc
);
1016 if(mec
[nu
[p
]]==mem
[nu
[p
]]) add_memory(vc
,nu
[p
]);
1018 // Copy the edges of the original vertex into the new
1019 // one. Delete the edges of the original vertex, and
1020 // update the relational table.
1021 vc
.n_set_pointer(p
,nu
[p
]);
1022 ed
[p
]=mep
[nu
[p
]]+((nu
[p
]<<1)+1)*mec
[nu
[p
]]++;
1027 qs
=ed
[up
][nu
[up
]+i
];
1028 vc
.n_copy(p
,k
,up
,i
);
1032 ed
[qp
][nu
[qp
]+qs
]=k
;
1039 qs
=ed
[up
][nu
[up
]+i
];
1040 vc
.n_copy(p
,k
,up
,i
);
1044 ed
[qp
][nu
[qp
]+qs
]=k
;
1051 vc
.n_copy(p
,k
,up
,qs
);
1053 } else vc
.n_copy(p
,0,up
,qs
);
1055 // Add this point to the auxiliary delete stack
1056 if(stackp2
==stacke2
) add_memory_ds2();
1059 // Look at the edges on either side of the group that was
1060 // detected. We're going to commence facet computation by
1061 // moving along one of them. We are going to end up coming back
1062 // along the other one.
1066 us
=ed
[up
][nu
[up
]+us
];
1068 ed
[qp
][nu
[qp
]<<1]=-p
;
1072 // The search algorithm found an intersected edge between the
1073 // points lp and up. Create a new vertex between them which
1074 // lies on the cutting plane. Since u and l differ by at least
1075 // the tolerance, this division should never screw up.
1076 if(stackp
==stacke
) add_memory_ds();
1079 pts
[p
<<2]=pts
[lp
<<2]*r
+pts
[up
<<2]*l
;
1080 pts
[(p
<<2)+1]=pts
[(lp
<<2)+1]*r
+pts
[(up
<<2)+1]*l
;
1081 pts
[(p
<<2)+2]=pts
[(lp
<<2)+2]*r
+pts
[(up
<<2)+2]*l
;
1083 // This point will always have three edges. Connect one of them
1086 if(mec
[3]==mem
[3]) add_memory(vc
,3);
1087 vc
.n_set_pointer(p
,3);
1089 vc
.n_copy(p
,1,up
,us
);
1090 vc
.n_copy(p
,2,lp
,ls
);
1091 ed
[p
]=mep
[3]+7*mec
[3]++;
1095 ed
[lp
][nu
[lp
]+ls
]=1;
1100 // Set the direction to move in
1105 // When the code reaches here, we have initialized the first point, and
1106 // we have a direction for moving it to construct the rest of the facet
1108 while(qp
!=up
||qs
!=us
) {
1110 // We're currently tracing round an intersected facet. Keep
1111 // moving around it until we find a point or edge which
1112 // intersects the plane.
1118 // The point is still in the cutting space. Just add it
1119 // to the delete stack and keep moving.
1120 qs
=cycle_up(ed
[qp
][nu
[qp
]+qs
],lp
);
1123 if(stackp
==stacke
) add_memory_ds();
1128 // The point is outside of the cutting space, so we've
1129 // found an intersected edge. Introduce a regular point
1130 // at the point of intersection. Connect it to the
1131 // point we just tested. Also connect it to the previous
1132 // new point in the facet we're constructing.
1133 if(p
==current_vertices
) add_memory_vertices(vc
);
1135 pts
[p
<<2]=pts
[lp
<<2]*r
+pts
[qp
<<2]*l
;
1136 pts
[(p
<<2)+1]=pts
[(lp
<<2)+1]*r
+pts
[(qp
<<2)+1]*l
;
1137 pts
[(p
<<2)+2]=pts
[(lp
<<2)+2]*r
+pts
[(qp
<<2)+2]*l
;
1139 if(mec
[3]==mem
[3]) add_memory(vc
,3);
1140 ls
=ed
[qp
][qs
+nu
[qp
]];
1141 vc
.n_set_pointer(p
,3);
1143 vc
.n_copy(p
,1,qp
,qs
);
1144 vc
.n_copy(p
,2,lp
,ls
);
1145 ed
[p
]=mep
[3]+7*mec
[3]++;
1152 ed
[lp
][nu
[lp
]+ls
]=1;
1154 ed
[cp
][nu
[cp
]+cs
]=0;
1161 // We've found a point which is on the cutting plane.
1162 // We're going to introduce a new point right here, but
1163 // first we need to figure out the number of edges it
1165 if(p
==current_vertices
) add_memory_vertices(vc
);
1167 // If the previous vertex detected a double edge, our
1168 // new vertex will have one less edge.
1170 qs
=ed
[qp
][nu
[qp
]+qs
];
1174 // Start testing the edges of the current point until
1175 // we find one which isn't outside the cutting space
1183 // Now we need to find out whether this marginal vertex
1184 // we are on has been visited before, because if that's
1185 // the case, we need to add vertices to the existing
1186 // new vertex, rather than creating a fresh one. We also
1187 // need to figure out whether we're in a case where we
1188 // might be creating a duplicate edge.
1189 j
=-ed
[qp
][nu
[qp
]<<1];
1190 if(qp
==up
&&qs
==us
) {
1192 // If we're heading into the final part of the
1193 // new facet, then we never worry about the
1194 // duplicate edge calculation.
1195 new_double_edge
=false;
1200 // This vertex was visited before, so
1201 // count those vertices to the ones we
1205 // The only time when we might make a
1206 // duplicate edge is if the point we're
1207 // going to move to next is also a
1208 // marginal point, so test for that
1212 // Now see whether this marginal point
1213 // has been visited before.
1214 i
=-ed
[lp
][nu
[lp
]<<1];
1217 // Now see if the last edge of that other
1218 // marginal point actually ends up here.
1219 if(ed
[i
][nu
[i
]-1]==j
) {
1220 new_double_edge
=true;
1222 } else new_double_edge
=false;
1225 // That marginal point hasn't been visited
1226 // before, so we probably don't have to worry
1227 // about duplicate edges, except in the
1228 // case when that's the way into the end
1229 // of the facet, because that way always creates
1231 if(j
==rp
&&lp
==up
&&ed
[qp
][nu
[qp
]+qs
]==us
) {
1232 new_double_edge
=true;
1234 } else new_double_edge
=false;
1236 } else new_double_edge
=false;
1239 // The vertex hasn't been visited
1240 // before, but let's see if it's
1244 // If it is, we need to check
1245 // for the case that it's a
1246 // small branch, and that we're
1247 // heading right back to where
1249 i
=-ed
[lp
][nu
[lp
]<<1];
1251 new_double_edge
=true;
1253 } else new_double_edge
=false;
1254 } else new_double_edge
=false;
1258 // k now holds the number of edges of the new vertex
1259 // we are forming. Add memory for it if it doesn't exist
1261 while(k
>=current_vertex_order
) add_memory_vorder(vc
);
1262 if(mec
[k
]==mem
[k
]) add_memory(vc
,k
);
1264 // Now create a new vertex with order k, or augment
1268 // If we're augmenting a vertex but we don't
1269 // actually need any more edges, just skip this
1270 // routine to avoid memory confusion
1273 // Allocate memory and copy the edges
1274 // of the previous instance into it
1276 edp
=mep
[k
]+((k
<<1)+1)*mec
[k
]++;
1279 vc
.n_copy_aux1(j
,i
);
1281 edp
[k
+i
]=ed
[j
][nu
[j
]+i
];
1286 // Remove the previous instance with
1287 // fewer vertices from the memory
1289 edd
=mep
[nu
[j
]]+((nu
[j
]<<1)+1)*--mec
[nu
[j
]];
1291 for(int lll
=0;lll
<=(nu
[j
]<<1);lll
++) ed
[j
][lll
]=edd
[lll
];
1292 vc
.n_set_aux2_copy(j
,nu
[j
]);
1293 vc
.n_copy_pointer(edd
[nu
[j
]<<1],j
);
1294 ed
[edd
[nu
[j
]<<1]]=ed
[j
];
1296 vc
.n_set_to_aux1(j
);
1301 // Allocate a new vertex of order k
1302 vc
.n_set_pointer(p
,k
);
1303 ed
[p
]=mep
[k
]+((k
<<1)+1)*mec
[k
]++;
1305 if(stackp2
==stacke2
) add_memory_ds2();
1307 pts
[p
<<2]=pts
[qp
<<2];
1308 pts
[(p
<<2)+1]=pts
[(qp
<<2)+1];
1309 pts
[(p
<<2)+2]=pts
[(qp
<<2)+2];
1310 ed
[qp
][nu
[qp
]<<1]=-p
;
1316 // Unless the previous case was a double edge, connect
1317 // the first available edge of the new vertex to the
1318 // last one in the facet
1324 ed
[cp
][nu
[cp
]+cs
]=i
;
1328 // Copy in the edges of the underlying vertex,
1329 // and do one less if this was a double edge
1331 while(i
<(new_double_edge
?k
:k
-1)) {
1333 lp
=ed
[qp
][qs
];ls
=ed
[qp
][nu
[qp
]+qs
];
1334 vc
.n_copy(j
,i
,qp
,qs
);
1338 ed
[lp
][nu
[lp
]+ls
]=i
;
1345 vc
.n_copy(j
,new_double_edge
?0:cs
,qp
,qs
);
1347 // Update the double_edge flag, to pass it
1348 // to the next instance of this routine
1349 double_edge
=new_double_edge
;
1353 // Connect the final created vertex to the initial one
1356 ed
[cp
][nu
[cp
]+cs
]=0;
1361 /** During the creation of a new facet in the plane routine, it is possible
1362 * that some order two vertices may arise. This routine removes them.
1363 * Suppose an order two vertex joins c and d. If there's a edge between
1364 * c and d already, then the order two vertex is just removed; otherwise,
1365 * the order two vertex is removed and c and d are joined together directly.
1366 * It is possible this process will create order two or order one vertices,
1367 * and the routine is continually run until all of them are removed.
1368 * \return False if the vertex removal was unsuccessful, indicative of the cell
1369 * reducing to zero volume and disappearing; true if the vertex removal
1370 * was successful. */
1371 template<class vc_class
>
1372 inline bool voronoicell_base::collapse_order2(vc_class
&vc
) {
1373 if(!collapse_order1(vc
)) return false;
1377 // Pick a order 2 vertex and read in its edges
1379 j
=mep
[2][5*i
];k
=mep
[2][5*i
+1];
1381 #if VOROPP_VERBOSE >=1
1382 fputs("Order two vertex joins itself",stderr
);
1387 // Scan the edges of j to see if joins k
1388 for(l
=0;l
<nu
[j
];l
++) {
1389 if(ed
[j
][l
]==k
) break;
1392 // If j doesn't already join k, join them together.
1393 // Otherwise delete the connection to the current
1394 // vertex from j and k.
1395 a
=mep
[2][5*i
+2];b
=mep
[2][5*i
+3];i
=mep
[2][5*i
+4];
1402 if(!delete_connection(vc
,j
,a
,false)) return false;
1403 if(!delete_connection(vc
,k
,b
,true)) return false;
1406 // Compact the memory
1411 pts
[i
<<2]=pts
[p
<<2];
1412 pts
[(i
<<2)+1]=pts
[(p
<<2)+1];
1413 pts
[(i
<<2)+2]=pts
[(p
<<2)+2];
1414 for(k
=0;k
<nu
[p
];k
++) ed
[ed
[p
][k
]][ed
[p
][nu
[p
]+k
]]=i
;
1415 vc
.n_copy_pointer(i
,p
);
1421 // Collapse any order 1 vertices if they were created
1422 if(!collapse_order1(vc
)) return false;
1427 /** Order one vertices can potentially be created during the order two collapse
1428 * routine. This routine keeps removing them until there are none left.
1429 * \return False if the vertex removal was unsuccessful, indicative of the cell
1430 * having zero volume and disappearing; true if the vertex removal was
1432 template<class vc_class
>
1433 bool voronoicell_base::collapse_order1(vc_class
&vc
) {
1437 #if VOROPP_VERBOSE >=1
1438 fputs("Order one collapse\n",stderr
);
1441 j
=mep
[1][3*i
];k
=mep
[1][3*i
+1];
1443 if(!delete_connection(vc
,j
,k
,false)) return false;
1448 pts
[i
<<2]=pts
[p
<<2];
1449 pts
[(i
<<2)+1]=pts
[(p
<<2)+1];
1450 pts
[(i
<<2)+2]=pts
[(p
<<2)+2];
1451 for(k
=0;k
<nu
[p
];k
++) ed
[ed
[p
][k
]][ed
[p
][nu
[p
]+k
]]=i
;
1452 vc
.n_copy_pointer(i
,p
);
1461 /** This routine deletes the kth edge of vertex j and reorganizes the memory.
1462 * If the neighbor computation is enabled, we also have to supply an handedness
1463 * flag to decide whether to preserve the plane on the left or right of the
1465 * \return False if a zero order vertex was formed, indicative of the cell
1466 * disappearing; true if the vertex removal was successful. */
1467 template<class vc_class
>
1468 bool voronoicell_base::delete_connection(vc_class
&vc
,int j
,int k
,bool hand
) {
1469 int q
=hand
?k
:cycle_up(k
,j
);
1470 int i
=nu
[j
]-1,l
,*edp
,*edd
,m
;
1471 #if VOROPP_VERBOSE >=1
1473 fputs("Zero order vertex formed\n",stderr
);
1477 if(mec
[i
]==mem
[i
]) add_memory(vc
,i
);
1479 for(l
=0;l
<q
;l
++) vc
.n_copy_aux1(j
,l
);
1481 vc
.n_copy_aux1_shift(j
,l
);
1484 edp
=mep
[i
]+((i
<<1)+1)*mec
[i
]++;
1488 edp
[l
+i
]=ed
[j
][l
+nu
[j
]];
1499 edd
=mep
[nu
[j
]]+((nu
[j
]<<1)+1)*--mec
[nu
[j
]];
1500 for(l
=0;l
<=(nu
[j
]<<1);l
++) ed
[j
][l
]=edd
[l
];
1501 vc
.n_set_aux2_copy(j
,nu
[j
]);
1502 vc
.n_copy_pointer(edd
[nu
[j
]<<1],j
);
1503 vc
.n_set_to_aux1(j
);
1504 ed
[edd
[nu
[j
]<<1]]=ed
[j
];
1510 /** This routine is a fall-back, in case floating point errors caused the usual
1511 * search routine to fail. In the fall-back routine, we just test every edge to
1512 * find one straddling the plane. */
1513 bool voronoicell_base::failsafe_find(int &lp
,int &ls
,int &us
,double &l
,double &u
) {
1514 fputs("Bailed out of convex calculation (not supported yet)\n",stderr
);
1517 for(qp=0;qp<p;qp++) {
1521 // The point is inside the cutting space. Now
1522 // see if we can find a neighbor which isn't.
1523 for(us=0;us<nu[qp];us++) {
1533 complicated_setup=true;
1535 complicated_setup=false;
1537 ls=ed[up][nu[up]+us];
1543 // The point is outside the cutting space. See
1544 // if we can find a neighbor which isn't.
1545 for(ls=0;ls<nu[qp];ls++) {
1555 complicated_setup=true;
1557 complicated_setup=false;
1559 us=ed[lp][nu[lp]+ls];
1565 // The point is in the plane, so we just
1566 // proceed with the complicated setup routine
1568 complicated_setup=true;
1572 if(qp==p) return qw==-1?true:false;*/
1575 /** Calculates the volume of the Voronoi cell, by decomposing the cell into
1576 * tetrahedra extending outward from the zeroth vertex, whose volumes are
1577 * evaluated using a scalar triple product.
1578 * \return A floating point number holding the calculated volume. */
1579 double voronoicell_base::volume() {
1580 const double fe
=1/48.0;
1583 double ux
,uy
,uz
,vx
,vy
,vz
,wx
,wy
,wz
;
1586 uy
=pts
[1]-pts
[(i
<<2)+1];
1587 uz
=pts
[2]-pts
[(i
<<2)+2];
1588 for(j
=0;j
<nu
[i
];j
++) {
1592 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
1594 vy
=pts
[(k
<<2)+1]-pts
[1];
1595 vz
=pts
[(k
<<2)+2]-pts
[2];
1596 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1598 n
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
1599 wx
=pts
[(m
<<2)]-*pts
;
1600 wy
=pts
[(m
<<2)+1]-pts
[1];
1601 wz
=pts
[(m
<<2)+2]-pts
[2];
1602 vol
+=ux
*vy
*wz
+uy
*vz
*wx
+uz
*vx
*wy
-uz
*vy
*wx
-uy
*vx
*wz
-ux
*vz
*wy
;
1603 k
=m
;l
=n
;vx
=wx
;vy
=wy
;vz
=wz
;
1604 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1613 /** Calculates the contributions to the Minkowski functionals for this Voronoi cell.
1614 * \param[in] r the radius to consider.
1615 * \param[out] ar the area functional.
1616 * \param[out] vo the volume functional. */
1617 void voronoicell_base::minkowski(double r
,double &ar
,double &vo
) {
1620 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
1624 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
1625 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1627 n
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
1628 minkowski_contrib(i
,k
,m
,r
,ar
,vo
);
1630 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1639 inline void voronoicell_base::minkowski_contrib(int i
,int k
,int m
,double r
,double &ar
,double &vo
) {
1640 double ix
=pts
[4*i
],iy
=pts
[4*i
+1],iz
=pts
[4*i
+2],
1641 kx
=pts
[4*k
],ky
=pts
[4*k
+1],kz
=pts
[4*k
+2],
1642 mx
=pts
[4*m
],my
=pts
[4*m
+1],mz
=pts
[4*m
+2],
1643 ux
=kx
-ix
,uy
=ky
-iy
,uz
=kz
-iz
,vx
=mx
-kx
,vy
=my
-ky
,vz
=mz
-kz
,
1644 e1x
=uz
*vy
-uy
*vz
,e1y
=ux
*vz
-uz
*vx
,e1z
=uy
*vx
-ux
*vy
,e2x
,e2y
,e2z
,
1645 wmag
=e1x
*e1x
+e1y
*e1y
+e1z
*e1z
;
1646 if(wmag
<tol
*tol
) return;
1648 e1x
*=wmag
;e1y
*=wmag
;e1z
*=wmag
;
1650 // Compute second orthonormal vector
1652 e2x
=-e1y
;e2y
=e1x
;e2z
=0;
1653 } else if(fabs(e1y
)>0.5) {
1654 e2x
=0;e2y
=-e1z
;e2z
=e1y
;
1656 e2x
=e1z
;e2y
=0;e2z
=-e1x
;
1658 wmag
=1/sqrt(e2x
*e2x
+e2y
*e2y
+e2z
*e2z
);
1659 e2x
*=wmag
;e2y
*=wmag
;e2z
*=wmag
;
1661 // Compute third orthonormal vector
1662 double e3x
=e1z
*e2y
-e1y
*e2z
,
1663 e3y
=e1x
*e2z
-e1z
*e2x
,
1664 e3z
=e1y
*e2x
-e1x
*e2y
,
1665 x0
=e1x
*ix
+e1y
*iy
+e1z
*iz
;
1668 double ir
=e2x
*ix
+e2y
*iy
+e2z
*iz
,is
=e3x
*ix
+e3y
*iy
+e3z
*iz
,
1669 kr
=e2x
*kx
+e2y
*ky
+e2z
*kz
,ks
=e3x
*kx
+e3y
*ky
+e3z
*kz
,
1670 mr
=e2x
*mx
+e2y
*my
+e2z
*mz
,ms
=e3x
*mx
+e3y
*my
+e3z
*mz
;
1671 printf("(%g,%g,%g)\n",e1x
,e1y
,e1z
);
1672 printf("(%g,%g,%g)\n",e2x
,e2y
,e2z
);
1673 printf("(%g,%g,%g)\n",e3x
,e3y
,e3z
);
1674 printf("%g %g %g %g %g %g\n",ir
,is
,kr
,ks
,mr
,ms
);
1676 minkowski_edge(x0
,ir
,is
,kr
,ks
,r
,ar
,vo
);
1677 minkowski_edge(x0
,kr
,ks
,mr
,ms
,r
,ar
,vo
);
1678 minkowski_edge(x0
,mr
,ms
,ir
,is
,r
,ar
,vo
);
1681 void voronoicell_base::minkowski_edge(double x0
,double r1
,double s1
,double r2
,double s2
,double r
,double &ar
,double &vo
) {
1682 double r12
=r2
-r1
,s12
=s2
-s1
,l12
=r12
*r12
+s12
*s12
;
1683 printf("ME %g %g %g %g\n",r1
,s1
,r2
,s2
);
1684 if(l12
<tol
*tol
) return;
1685 l12
=1/sqrt(l12
);r12
*=l12
;s12
*=l12
;
1686 double y0
=-s12
*r1
+r12
*s1
;
1687 printf("ME2 y0=(%g,%g) z0=%g z0=%g\n",y0
,-s12
*r2
+r12
*s2
,-r12
*r1
-s12
*s1
,r12
*r2
+s12
*s2
);
1688 if(fabs(y0
)<tol
) return;
1689 minkowski_formula(x0
,y0
,r12
*r1
+s12
*s1
,r
,ar
,vo
);
1690 minkowski_formula(x0
,y0
,-r12
*r2
-s12
*s2
,r
,ar
,vo
);
1693 void voronoicell_base::minkowski_formula(double x0
,double y0
,double z0
,double r
,double &ar
,double &vo
) {
1694 printf("MF %g %g %g\n",x0
,y0
,z0
);
1695 const double pi
=3.1415926535897932384626433832795;
1696 if(fabs(z0
)<tol
) return;
1698 if(z0
<0) {z0
=-z0
;si
=-1;} else si
=1;
1699 if(y0
<0) {y0
=-y0
;si
=-si
;}
1700 double xs
=x0
*x0
,ys
=y0
*y0
,zs
=z0
*z0
,res
=xs
+ys
,rvs
=res
+zs
,theta
=atan(z0
/y0
),rs
=r
*r
,rc
=rs
*r
,temp
,voc
,arc
;
1703 temp
=2*theta
-0.5*pi
-asin((zs
*xs
-ys
*rvs
)/(res
*(ys
+zs
)));
1707 temp
=0.5*pi
+asin((zs
*xs
-ys
*rvs
)/(res
*(ys
+zs
)));
1708 voc
=theta
*0.5*(rs
*x0
-xs
*x0
/3.)-rc
/6.*temp
;
1709 arc
=theta
*x0
*r
-rs
*0.5*temp
;
1711 temp
=theta
-pi
*0.5+asin(y0
/sqrt(rs
-xs
));
1712 double temp2
=(rs
*x0
-xs
*x0
/3.),
1713 x2s
=rs
*xs
/res
,y2s
=rs
*ys
/res
,
1714 temp3
=asin((x2s
-y2s
-xs
)/(rs
-xs
)),
1715 temp4
=asin((zs
*xs
-ys
*rvs
)/(res
*(ys
+zs
))),
1717 voc
=0.5*temp
*temp2
+x0
*y0
/6.*temp5
+r
*rs
/6*(temp3
-temp4
);
1718 arc
=x0
*r
*temp
-0.5*temp2
*y0
*r
/((rs
-xs
)*temp5
)+x0
*y0
/6.*r
/temp5
+rs
*0.5*temp3
+rs
*rs
/3.*2*xs
*ys
/(res
*(rs
-xs
)*sqrt((rs
-xs
)*(rs
-xs
)-(x2s
-y2s
-xs
)*(x2s
-y2s
-xs
)))-rs
*0.5*temp4
;
1728 /** Calculates the areas of each face of the Voronoi cell and prints the
1729 * results to an output stream.
1730 * \param[out] v the vector to store the results in. */
1731 void voronoicell_base::face_areas(std::vector
<double> &v
) {
1735 double ux
,uy
,uz
,vx
,vy
,vz
,wx
,wy
,wz
;
1736 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
1741 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
1742 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1744 n
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
1745 ux
=pts
[4*k
]-pts
[4*i
];
1746 uy
=pts
[4*k
+1]-pts
[4*i
+1];
1747 uz
=pts
[4*k
+2]-pts
[4*i
+2];
1748 vx
=pts
[4*m
]-pts
[4*i
];
1749 vy
=pts
[4*m
+1]-pts
[4*i
+1];
1750 vz
=pts
[4*m
+2]-pts
[4*i
+2];
1754 area
+=sqrt(wx
*wx
+wy
*wy
+wz
*wz
);
1756 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1758 v
.push_back(0.125*area
);
1765 /** Calculates the total surface area of the Voronoi cell.
1766 * \return The computed area. */
1767 double voronoicell_base::surface_area() {
1770 double ux
,uy
,uz
,vx
,vy
,vz
,wx
,wy
,wz
;
1771 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
1775 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
1776 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1778 n
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
1779 ux
=pts
[4*k
]-pts
[4*i
];
1780 uy
=pts
[4*k
+1]-pts
[4*i
+1];
1781 uz
=pts
[4*k
+2]-pts
[4*i
+2];
1782 vx
=pts
[4*m
]-pts
[4*i
];
1783 vy
=pts
[4*m
+1]-pts
[4*i
+1];
1784 vz
=pts
[4*m
+2]-pts
[4*i
+2];
1788 area
+=sqrt(wx
*wx
+wy
*wy
+wz
*wz
);
1790 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1799 /** Calculates the centroid of the Voronoi cell, by decomposing the cell into
1800 * tetrahedra extending outward from the zeroth vertex.
1801 * \param[out] (cx,cy,cz) references to floating point numbers in which to
1802 * pass back the centroid vector. */
1803 void voronoicell_base::centroid(double &cx
,double &cy
,double &cz
) {
1804 double tvol
,vol
=0;cx
=cy
=cz
=0;
1806 double ux
,uy
,uz
,vx
,vy
,vz
,wx
,wy
,wz
;
1809 uy
=pts
[1]-pts
[4*i
+1];
1810 uz
=pts
[2]-pts
[4*i
+2];
1811 for(j
=0;j
<nu
[i
];j
++) {
1815 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
1817 vy
=pts
[4*k
+1]-pts
[1];
1818 vz
=pts
[4*k
+2]-pts
[2];
1819 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1821 n
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
1823 wy
=pts
[4*m
+1]-pts
[1];
1824 wz
=pts
[4*m
+2]-pts
[2];
1825 tvol
=ux
*vy
*wz
+uy
*vz
*wx
+uz
*vx
*wy
-uz
*vy
*wx
-uy
*vx
*wz
-ux
*vz
*wy
;
1827 cx
+=(wx
+vx
-ux
)*tvol
;
1828 cy
+=(wy
+vy
-uy
)*tvol
;
1829 cz
+=(wz
+vz
-uz
)*tvol
;
1830 k
=m
;l
=n
;vx
=wx
;vy
=wy
;vz
=wz
;
1831 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1839 cx
=cx
*vol
+0.5*(*pts
);
1840 cy
=cy
*vol
+0.5*pts
[1];
1841 cz
=cz
*vol
+0.5*pts
[2];
1845 /** Computes the maximum radius squared of a vertex from the center of the
1846 * cell. It can be used to determine when enough particles have been testing an
1847 * all planes that could cut the cell have been considered.
1848 * \return The maximum radius squared of a vertex.*/
1849 double voronoicell_base::max_radius_squared() {
1850 double r
,s
,*ptsp
=pts
+4,*ptse
=pts
+(p
<<2);
1851 r
=*pts
*(*pts
)+pts
[1]*pts
[1]+pts
[2]*pts
[2];
1853 s
=*ptsp
*(*ptsp
);ptsp
++;
1854 s
+=*ptsp
*(*ptsp
);ptsp
++;
1855 s
+=*ptsp
*(*ptsp
);ptsp
+=2;
1861 /** Calculates the total edge distance of the Voronoi cell.
1862 * \return A floating point number holding the calculated distance. */
1863 double voronoicell_base::total_edge_distance() {
1865 double dis
=0,dx
,dy
,dz
;
1866 for(i
=0;i
<p
-1;i
++) for(j
=0;j
<nu
[i
];j
++) {
1869 dx
=pts
[k
<<2]-pts
[i
<<2];
1870 dy
=pts
[(k
<<2)+1]-pts
[(i
<<2)+1];
1871 dz
=pts
[(k
<<2)+2]-pts
[(i
<<2)+2];
1872 dis
+=sqrt(dx
*dx
+dy
*dy
+dz
*dz
);
1878 /** Outputs the edges of the Voronoi cell in POV-Ray format to an open file
1879 * stream, displacing the cell by given vector.
1880 * \param[in] (x,y,z) a displacement vector to be added to the cell's position.
1881 * \param[in] fp a file handle to write to. */
1882 void voronoicell_base::draw_pov(double x
,double y
,double z
,FILE* fp
) {
1883 int i
,j
,k
;double *ptsp
=pts
,*pt2
;
1884 char posbuf1
[128],posbuf2
[128];
1885 for(i
=0;i
<p
;i
++,ptsp
+=4) {
1886 sprintf(posbuf1
,"%g,%g,%g",x
+*ptsp
*0.5,y
+ptsp
[1]*0.5,z
+ptsp
[2]*0.5);
1887 fprintf(fp
,"sphere{<%s>,r}\n",posbuf1
);
1888 for(j
=0;j
<nu
[i
];j
++) {
1892 sprintf(posbuf2
,"%g,%g,%g",x
+*pt2
*0.5,y
+0.5*pt2
[1],z
+0.5*pt2
[2]);
1893 if(strcmp(posbuf1
,posbuf2
)!=0) fprintf(fp
,"cylinder{<%s>,<%s>,r}\n",posbuf1
,posbuf2
);
1899 /** Outputs the edges of the Voronoi cell in gnuplot format to an output stream.
1900 * \param[in] (x,y,z) a displacement vector to be added to the cell's position.
1901 * \param[in] fp a file handle to write to. */
1902 void voronoicell_base::draw_gnuplot(double x
,double y
,double z
,FILE *fp
) {
1904 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
1907 fprintf(fp
,"%g %g %g\n",x
+0.5*pts
[i
<<2],y
+0.5*pts
[(i
<<2)+1],z
+0.5*pts
[(i
<<2)+2]);
1910 ed
[k
][ed
[l
][nu
[l
]+m
]]=-1-l
;
1913 fprintf(fp
,"%g %g %g\n",x
+0.5*pts
[k
<<2],y
+0.5*pts
[(k
<<2)+1],z
+0.5*pts
[(k
<<2)+2]);
1914 } while (search_edge(l
,m
,k
));
1921 inline bool voronoicell_base::search_edge(int l
,int &m
,int &k
) {
1922 for(m
=0;m
<nu
[l
];m
++) {
1924 if(k
>=0) return true;
1929 /** Outputs the Voronoi cell in the POV mesh2 format, described in section
1930 * 1.3.2.2 of the POV-Ray documentation. The mesh2 output consists of a list of
1931 * vertex vectors, followed by a list of triangular faces. The routine also
1932 * makes use of the optional inside_vector specification, which makes the mesh
1933 * object solid, so that the POV-Ray Constructive Solid Geometry (CSG) can be
1935 * \param[in] (x,y,z) a displacement vector to be added to the cell's position.
1936 * \param[in] fp a file handle to write to. */
1937 void voronoicell_base::draw_pov_mesh(double x
,double y
,double z
,FILE *fp
) {
1940 fprintf(fp
,"mesh2 {\nvertex_vectors {\n%d\n",p
);
1941 for(i
=0;i
<p
;i
++,ptsp
+=4) fprintf(fp
,",<%g,%g,%g>\n",x
+*ptsp
*0.5,y
+ptsp
[1]*0.5,z
+ptsp
[2]*0.5);
1942 fprintf(fp
,"}\nface_indices {\n%d\n",(p
-2)<<1);
1943 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
1947 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
1948 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1950 n
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
1951 fprintf(fp
,",<%d,%d,%d>\n",i
,k
,m
);
1953 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
1957 fputs("}\ninside_vector <0,0,1>\n}\n",fp
);
1961 /** Several routines in the class that gather cell-based statistics internally
1962 * track their progress by flipping edges to negative so that they know what
1963 * parts of the cell have already been tested. This function resets them back
1964 * to positive. When it is called, it assumes that every edge in the routine
1965 * should have already been flipped to negative, and it bails out with an
1966 * internal error if it encounters a positive edge. */
1967 inline void voronoicell_base::reset_edges() {
1969 for(i
=0;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
1970 if(ed
[i
][j
]>=0) voro_fatal_error("Edge reset routine found a previously untested edge",VOROPP_INTERNAL_ERROR
);
1971 ed
[i
][j
]=-1-ed
[i
][j
];
1975 /** Checks to see if a given vertex is inside, outside or within the test
1976 * plane. If the point is far away from the test plane, the routine immediately
1977 * returns whether it is inside or outside. If the routine is close the the
1978 * plane and within the specified tolerance, then the special check_marginal()
1979 * routine is called.
1980 * \param[in] n the vertex to test.
1981 * \param[out] ans the result of the scalar product used in evaluating the
1982 * location of the point.
1983 * \return -1 if the point is inside the plane, 1 if the point is outside the
1984 * plane, or 0 if the point is within the plane. */
1985 inline unsigned int voronoicell_base::m_test(int n
,double &ans
) {
1986 if(mask
[n
]>=maskc
) {
1989 } else return m_calc(n
,ans
);
1992 unsigned int voronoicell_base::m_calc(int n
,double &ans
) {
1996 ans
+=*(pp
++)*pz
-prsq
;
1998 unsigned int maskr
=ans
<-tol
?0:(ans
>tol
?2:1);
1999 mask
[n
]=maskc
|maskr
;
2004 /** Checks to see if a given vertex is inside, outside or within the test
2005 * plane. If the point is far away from the test plane, the routine immediately
2006 * returns whether it is inside or outside. If the routine is close the the
2007 * plane and within the specified tolerance, then the special check_marginal()
2008 * routine is called.
2009 * \param[in] n the vertex to test.
2010 * \param[out] ans the result of the scalar product used in evaluating the
2011 * location of the point.
2012 * \return -1 if the point is inside the plane, 1 if the point is outside the
2013 * plane, or 0 if the point is within the plane. */
2014 inline unsigned int voronoicell_base::m_testx(int n
,double &ans
) {
2016 if(mask
[n
]>=maskc
) {
2019 } else maskr
=m_calc(n
,ans
);
2020 if(maskr
==0&&ans
>-big_tol
&&ed
[n
][nu
[n
]<<1]!=-1) {
2022 if(stackp3
==stacke3
) add_memory_xse();
2028 /** This routine calculates the unit normal vectors for every face.
2029 * \param[out] v the vector to store the results in. */
2030 void voronoicell_base::normals(std::vector
<double> &v
) {
2033 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
2035 if(k
>=0) normals_search(v
,i
,j
,k
);
2040 /** This inline routine is called by normals(). It attempts to construct a
2041 * single normal vector that is associated with a particular face. It first
2042 * traces around the face, trying to find two vectors along the face edges
2043 * whose vector product is above the numerical tolerance. It then constructs
2044 * the normal vector using this product. If the face is too small, and none of
2045 * the vector products are large enough, the routine may return (0,0,0) as the
2047 * \param[in] v the vector to store the results in.
2048 * \param[in] i the initial vertex of the face to test.
2049 * \param[in] j the index of an edge of the vertex.
2050 * \param[in] k the neighboring vertex of i, set to ed[i][j]. */
2051 inline void voronoicell_base::normals_search(std::vector
<double> &v
,int i
,int j
,int k
) {
2053 int l
=cycle_up(ed
[i
][nu
[i
]+j
],k
),m
;
2054 double ux
,uy
,uz
,vx
,vy
,vz
,wx
,wy
,wz
,wmag
;
2056 m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
2057 ux
=pts
[4*m
]-pts
[4*k
];
2058 uy
=pts
[4*m
+1]-pts
[4*k
+1];
2059 uz
=pts
[4*m
+2]-pts
[4*k
+2];
2061 // Test to see if the length of this edge is above the tolerance
2062 if(ux
*ux
+uy
*uy
+uz
*uz
>tol
) {
2064 l
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
2065 k
=m
;m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
2066 vx
=pts
[4*m
]-pts
[4*k
];
2067 vy
=pts
[4*m
+1]-pts
[4*k
+1];
2068 vz
=pts
[4*m
+2]-pts
[4*k
+2];
2070 // Construct the vector product of this edge with
2075 wmag
=wx
*wx
+wy
*wy
+wz
*wz
;
2077 // Test to see if this vector product of the
2078 // two edges is above the tolerance
2081 // Construct the normal vector and print it
2083 v
.push_back(wx
*wmag
);
2084 v
.push_back(wy
*wmag
);
2085 v
.push_back(wz
*wmag
);
2087 // Mark all of the remaining edges of this
2090 l
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
2091 k
=m
;m
=ed
[k
][l
];ed
[k
][l
]=-1-m
;
2101 l
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
2110 /** Returns the number of faces of a computed Voronoi cell.
2111 * \return The number of faces. */
2112 int voronoicell_base::number_of_faces() {
2114 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
2119 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
2123 l
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
2133 /** Returns a vector of the vertex orders.
2134 * \param[out] v the vector to store the results in. */
2135 void voronoicell_base::vertex_orders(std::vector
<int> &v
) {
2137 for(int i
=0;i
<p
;i
++) v
[i
]=nu
[i
];
2140 /** Outputs the vertex orders.
2141 * \param[out] fp the file handle to write to. */
2142 void voronoicell_base::output_vertex_orders(FILE *fp
) {
2144 fprintf(fp
,"%d",*nu
);
2145 for(int *nup
=nu
+1;nup
<nu
+p
;nup
++) fprintf(fp
," %d",*nup
);
2149 /** Returns a vector of the vertex vectors using the local coordinate system.
2150 * \param[out] v the vector to store the results in. */
2151 void voronoicell_base::vertices(std::vector
<double> &v
) {
2154 for(int i
=0;i
<3*p
;i
+=3) {
2156 v
[i
+1]=*(ptsp
++)*0.5;
2157 v
[i
+2]=*ptsp
*0.5;ptsp
+=2;
2161 /** Outputs the vertex vectors using the local coordinate system.
2162 * \param[out] fp the file handle to write to. */
2163 void voronoicell_base::output_vertices(FILE *fp
) {
2165 fprintf(fp
,"(%g,%g,%g)",*pts
*0.5,pts
[1]*0.5,pts
[2]*0.5);
2166 for(double *ptsp
=pts
+4;ptsp
<pts
+(p
<<2);ptsp
+=4) fprintf(fp
," (%g,%g,%g)",*ptsp
*0.5,ptsp
[1]*0.5,ptsp
[2]*0.5);
2171 /** Returns a vector of the vertex vectors in the global coordinate system.
2172 * \param[out] v the vector to store the results in.
2173 * \param[in] (x,y,z) the position vector of the particle in the global
2174 * coordinate system. */
2175 void voronoicell_base::vertices(double x
,double y
,double z
,std::vector
<double> &v
) {
2178 for(int i
=0;i
<3*p
;i
+=3) {
2179 v
[i
]=x
+*(ptsp
++)*0.5;
2180 v
[i
+1]=y
+*(ptsp
++)*0.5;
2181 v
[i
+2]=z
+*ptsp
*0.5;ptsp
+=2;
2185 /** Outputs the vertex vectors using the global coordinate system.
2186 * \param[out] fp the file handle to write to.
2187 * \param[in] (x,y,z) the position vector of the particle in the global
2188 * coordinate system. */
2189 void voronoicell_base::output_vertices(double x
,double y
,double z
,FILE *fp
) {
2191 fprintf(fp
,"(%g,%g,%g)",x
+*pts
*0.5,y
+pts
[1]*0.5,z
+pts
[2]*0.5);
2192 for(double *ptsp
=pts
+4;ptsp
<pts
+(p
<<2);ptsp
+=4) fprintf(fp
," (%g,%g,%g)",x
+*ptsp
*0.5,y
+ptsp
[1]*0.5,z
+ptsp
[2]*0.5);
2196 /** This routine returns the perimeters of each face.
2197 * \param[out] v the vector to store the results in. */
2198 void voronoicell_base::face_perimeters(std::vector
<double> &v
) {
2201 double dx
,dy
,dz
,perim
;
2202 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
2205 dx
=pts
[k
<<2]-pts
[i
<<2];
2206 dy
=pts
[(k
<<2)+1]-pts
[(i
<<2)+1];
2207 dz
=pts
[(k
<<2)+2]-pts
[(i
<<2)+2];
2208 perim
=sqrt(dx
*dx
+dy
*dy
+dz
*dz
);
2210 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
2213 dx
=pts
[m
<<2]-pts
[k
<<2];
2214 dy
=pts
[(m
<<2)+1]-pts
[(k
<<2)+1];
2215 dz
=pts
[(m
<<2)+2]-pts
[(k
<<2)+2];
2216 perim
+=sqrt(dx
*dx
+dy
*dy
+dz
*dz
);
2218 l
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
2221 v
.push_back(0.5*perim
);
2227 /** For each face, this routine outputs a bracketed sequence of numbers
2228 * containing a list of all the vertices that make up that face.
2229 * \param[out] v the vector to store the results in. */
2230 void voronoicell_base::face_vertices(std::vector
<int> &v
) {
2231 int i
,j
,k
,l
,m
,vp(0),vn
;
2233 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
2239 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
2244 l
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
2255 /** Outputs a list of the number of edges in each face.
2256 * \param[out] v the vector to store the results in. */
2257 void voronoicell_base::face_orders(std::vector
<int> &v
) {
2260 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
2265 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
2270 l
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
2279 /** Computes the number of edges that each face has and outputs a frequency
2280 * table of the results.
2281 * \param[out] v the vector to store the results in. */
2282 void voronoicell_base::face_freq_table(std::vector
<int> &v
) {
2285 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
2290 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
2295 l
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
2298 if((unsigned int) q
>=v
.size()) v
.resize(q
+1,0);
2305 /** This routine tests to see whether the cell intersects a plane by starting
2306 * from the guess point up. If up intersects, then it immediately returns true.
2307 * Otherwise, it calls the plane_intersects_track() routine.
2308 * \param[in] (x,y,z) the normal vector to the plane.
2309 * \param[in] rsq the distance along this vector of the plane.
2310 * \return False if the plane does not intersect the plane, true if it does. */
2311 bool voronoicell_base::plane_intersects(double x
,double y
,double z
,double rsq
) {
2312 double g
=x
*pts
[up
<<2]+y
*pts
[(up
<<2)+1]+z
*pts
[(up
<<2)+2];
2313 if(g
<rsq
) return plane_intersects_track(x
,y
,z
,rsq
,g
);
2317 /** This routine tests to see if a cell intersects a plane. It first tests a
2318 * random sample of approximately sqrt(p)/4 points. If any of those are
2319 * intersect, then it immediately returns true. Otherwise, it takes the closest
2320 * point and passes that to plane_intersect_track() routine.
2321 * \param[in] (x,y,z) the normal vector to the plane.
2322 * \param[in] rsq the distance along this vector of the plane.
2323 * \return False if the plane does not intersect the plane, true if it does. */
2324 bool voronoicell_base::plane_intersects_guess(double x
,double y
,double z
,double rsq
) {
2326 double g
=x
*pts
[up
<<2]+y
*pts
[(up
<<2)+1]+z
*pts
[(up
<<2)+2];
2328 int ca
=1,cc
=p
>>3,mp
=1;
2331 m
=x
*pts
[4*mp
]+y
*pts
[4*mp
+1]+z
*pts
[4*mp
+2];
2333 if(m
>rsq
) return true;
2338 return plane_intersects_track(x
,y
,z
,rsq
,g
);
2343 /* This routine tests to see if a cell intersects a plane, by tracing over the
2344 * cell from vertex to vertex, starting at up. It is meant to be called either
2345 * by plane_intersects() or plane_intersects_track(), when those routines
2346 * cannot immediately resolve the case.
2347 * \param[in] (x,y,z) the normal vector to the plane.
2348 * \param[in] rsq the distance along this vector of the plane.
2349 * \param[in] g the distance of up from the plane.
2350 * \return False if the plane does not intersect the plane, true if it does. */
2351 inline bool voronoicell_base::plane_intersects_track(double x
,double y
,double z
,double rsq
,double g
) {
2353 for(int tp
=0;tp
<p
;tp
++) if(x
*pts
[tp
<<2]+y
*pts
[(tp
<<2)+1]+z
*pts
[(tp
<<2)+2]>rsq
) return true;
2360 // Initialize the safe testing routine
2361 px=x;py=y;pz=z;prsq=rsq;
2363 if(maskc<4) reset_mask();
2365 return search_upward(uw,lp,ls,us,l,u);
2368 int count=0,ls,us,tp;
2370 // The test point is outside of the cutting space
2371 for(us=0;us<nu[up];us++) {
2373 t=x*pts[tp<<2]+y*pts[(tp<<2)+1]+z*pts[(tp<<2)+2];
2375 ls=ed[up][nu[up]+us];
2379 #if VOROPP_VERBOSE >=1
2380 fputs("Bailed out of convex calculation",stderr);
2382 for(tp=0;tp<p;tp++) if(x*pts[tp<<2]+y*pts[(tp<<2)+1]+z*pts[(tp<<2)+2]>rsq) return true;
2386 // Test all the neighbors of the current point
2387 // and find the one which is closest to the
2389 for(us=0;us<ls;us++) {
2390 tp=ed[up][us];double *pp=pts+(tp<<2);
2391 g=x*(*pp)+y*pp[1]+z*pp[2];
2397 tp=ed[up][us];double *pp=pts+(tp<<2);
2398 g=x*(*pp)+y*pp[1]+z*pp[2];
2402 if(us==nu[up]) return false;
2404 ls=ed[up][nu[up]+us];up=tp;t=g;
2412 /** Counts the number of edges of the Voronoi cell.
2413 * \return the number of edges. */
2414 int voronoicell_base::number_of_edges() {
2415 int edges
=0,*nup
=nu
;
2416 while(nup
<nu
+p
) edges
+=*(nup
++);
2420 /** Outputs a custom string of information about the Voronoi cell. The string
2421 * of information follows a similar style as the C printf command, and detailed
2422 * information about its format is available at
2423 * http://math.lbl.gov/voro++/doc/custom.html.
2424 * \param[in] format the custom string to print.
2425 * \param[in] i the ID of the particle associated with this Voronoi cell.
2426 * \param[in] (x,y,z) the position of the particle associated with this Voronoi
2428 * \param[in] r a radius associated with the particle.
2429 * \param[in] fp the file handle to write to. */
2430 void voronoicell_base::output_custom(const char *format
,int i
,double x
,double y
,double z
,double r
,FILE *fp
) {
2431 char *fmp
=(const_cast<char*>(format
));
2432 std::vector
<int> vi
;
2433 std::vector
<double> vd
;
2439 // Particle-related output
2440 case 'i': fprintf(fp
,"%d",i
);break;
2441 case 'x': fprintf(fp
,"%g",x
);break;
2442 case 'y': fprintf(fp
,"%g",y
);break;
2443 case 'z': fprintf(fp
,"%g",z
);break;
2444 case 'q': fprintf(fp
,"%g %g %g",x
,y
,z
);break;
2445 case 'r': fprintf(fp
,"%g",r
);break;
2447 // Vertex-related output
2448 case 'w': fprintf(fp
,"%d",p
);break;
2449 case 'p': output_vertices(fp
);break;
2450 case 'P': output_vertices(x
,y
,z
,fp
);break;
2451 case 'o': output_vertex_orders(fp
);break;
2452 case 'm': fprintf(fp
,"%g",0.25*max_radius_squared());break;
2454 // Edge-related output
2455 case 'g': fprintf(fp
,"%d",number_of_edges());break;
2456 case 'E': fprintf(fp
,"%g",total_edge_distance());break;
2457 case 'e': face_perimeters(vd
);voro_print_vector(vd
,fp
);break;
2459 // Face-related output
2460 case 's': fprintf(fp
,"%d",number_of_faces());break;
2461 case 'F': fprintf(fp
,"%g",surface_area());break;
2463 face_freq_table(vi
);
2464 voro_print_vector(vi
,fp
);
2466 case 'a': face_orders(vi
);voro_print_vector(vi
,fp
);break;
2467 case 'f': face_areas(vd
);voro_print_vector(vd
,fp
);break;
2470 voro_print_face_vertices(vi
,fp
);
2472 case 'l': normals(vd
);
2473 voro_print_positions(vd
,fp
);
2475 case 'n': neighbors(vi
);
2476 voro_print_vector(vi
,fp
);
2479 // Volume-related output
2480 case 'v': fprintf(fp
,"%g",volume());break;
2484 fprintf(fp
,"%g %g %g",cx
,cy
,cz
);
2489 fprintf(fp
,"%g %g %g",x
+cx
,y
+cy
,z
+cz
);
2492 // End-of-string reached
2493 case 0: fmp
--;break;
2495 // The percent sign is not part of a
2497 default: putc('%',fp
);putc(*fmp
,fp
);
2499 } else putc(*fmp
,fp
);
2505 /** This initializes the class to be a rectangular box. It calls the base class
2506 * initialization routine to set up the edge and vertex information, and then
2507 * sets up the neighbor information, with initial faces being assigned ID
2508 * numbers from -1 to -6.
2509 * \param[in] (xmin,xmax) the minimum and maximum x coordinates.
2510 * \param[in] (ymin,ymax) the minimum and maximum y coordinates.
2511 * \param[in] (zmin,zmax) the minimum and maximum z coordinates. */
2512 void voronoicell_neighbor::init(double xmin
,double xmax
,double ymin
,double ymax
,double zmin
,double zmax
) {
2513 init_base(xmin
,xmax
,ymin
,ymax
,zmin
,zmax
);
2515 *q
=-5;q
[1]=-3;q
[2]=-1;
2516 q
[3]=-5;q
[4]=-2;q
[5]=-3;
2517 q
[6]=-5;q
[7]=-1;q
[8]=-4;
2518 q
[9]=-5;q
[10]=-4;q
[11]=-2;
2519 q
[12]=-6;q
[13]=-1;q
[14]=-3;
2520 q
[15]=-6;q
[16]=-3;q
[17]=-2;
2521 q
[18]=-6;q
[19]=-4;q
[20]=-1;
2522 q
[21]=-6;q
[22]=-2;q
[23]=-4;
2523 *ne
=q
;ne
[1]=q
+3;ne
[2]=q
+6;ne
[3]=q
+9;
2524 ne
[4]=q
+12;ne
[5]=q
+15;ne
[6]=q
+18;ne
[7]=q
+21;
2527 /** This initializes the class to be an octahedron. It calls the base class
2528 * initialization routine to set up the edge and vertex information, and then
2529 * sets up the neighbor information, with the initial faces being assigned ID
2530 * numbers from -1 to -8.
2531 * \param[in] l The distance from the octahedron center to a vertex. Six
2532 * vertices are initialized at (-l,0,0), (l,0,0), (0,-l,0),
2533 * (0,l,0), (0,0,-l), and (0,0,l). */
2534 void voronoicell_neighbor::init_octahedron(double l
) {
2535 init_octahedron_base(l
);
2537 *q
=-5;q
[1]=-6;q
[2]=-7;q
[3]=-8;
2538 q
[4]=-1;q
[5]=-2;q
[6]=-3;q
[7]=-4;
2539 q
[8]=-6;q
[9]=-5;q
[10]=-2;q
[11]=-1;
2540 q
[12]=-8;q
[13]=-7;q
[14]=-4;q
[15]=-3;
2541 q
[16]=-5;q
[17]=-8;q
[18]=-3;q
[19]=-2;
2542 q
[20]=-7;q
[21]=-6;q
[22]=-1;q
[23]=-4;
2543 *ne
=q
;ne
[1]=q
+4;ne
[2]=q
+8;ne
[3]=q
+12;ne
[4]=q
+16;ne
[5]=q
+20;
2546 /** This initializes the class to be a tetrahedron. It calls the base class
2547 * initialization routine to set up the edge and vertex information, and then
2548 * sets up the neighbor information, with the initial faces being assigned ID
2549 * numbers from -1 to -4.
2550 * \param (x0,y0,z0) a position vector for the first vertex.
2551 * \param (x1,y1,z1) a position vector for the second vertex.
2552 * \param (x2,y2,z2) a position vector for the third vertex.
2553 * \param (x3,y3,z3) a position vector for the fourth vertex. */
2554 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
) {
2555 init_tetrahedron_base(x0
,y0
,z0
,x1
,y1
,z1
,x2
,y2
,z2
,x3
,y3
,z3
);
2557 *q
=-4;q
[1]=-3;q
[2]=-2;
2558 q
[3]=-3;q
[4]=-4;q
[5]=-1;
2559 q
[6]=-4;q
[7]=-2;q
[8]=-1;
2560 q
[9]=-2;q
[10]=-3;q
[11]=-1;
2561 *ne
=q
;ne
[1]=q
+3;ne
[2]=q
+6;ne
[3]=q
+9;
2564 /** This routine checks to make sure the neighbor information of each face is
2566 void voronoicell_neighbor::check_facets() {
2568 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
2573 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
2577 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
);
2578 l
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
2586 /** The class constructor allocates memory for storing neighbor information. */
2587 void voronoicell_neighbor::memory_setup() {
2589 mne
=new int*[current_vertex_order
];
2590 ne
=new int*[current_vertices
];
2591 for(i
=0;i
<3;i
++) mne
[i
]=new int[init_n_vertices
*i
];
2592 mne
[3]=new int[init_3_vertices
*3];
2593 for(i
=4;i
<current_vertex_order
;i
++) mne
[i
]=new int[init_n_vertices
*i
];
2596 /** The class destructor frees the dynamically allocated memory for storing
2597 * neighbor information. */
2598 voronoicell_neighbor::~voronoicell_neighbor() {
2599 for(int i
=current_vertex_order
-1;i
>=0;i
--) if(mem
[i
]>0) delete [] mne
[i
];
2604 /** Computes a vector list of neighbors. */
2605 void voronoicell_neighbor::neighbors(std::vector
<int> &v
) {
2608 for(i
=1;i
<p
;i
++) for(j
=0;j
<nu
[i
];j
++) {
2611 v
.push_back(ne
[i
][j
]);
2613 l
=cycle_up(ed
[i
][nu
[i
]+j
],k
);
2617 l
=cycle_up(ed
[k
][nu
[k
]+l
],m
);
2625 /** Prints the vertices, their edges, the relation table, and also notifies if
2626 * any memory errors are visible. */
2627 void voronoicell_base::print_edges() {
2630 for(int i
=0;i
<p
;i
++,ptsp
+=4) {
2631 printf("%d %d ",i
,nu
[i
]);
2632 for(j
=0;j
<nu
[i
];j
++) printf(" %d",ed
[i
][j
]);
2634 while(j
<(nu
[i
]<<1)) printf(" %d",ed
[i
][j
]);
2635 printf(" %d",ed
[i
][j
]);
2636 print_edges_neighbors(i
);
2637 printf(" %g %g %g %p",*ptsp
,ptsp
[1],ptsp
[2],(void*) ed
[i
]);
2638 if(ed
[i
]>=mep
[nu
[i
]]+mec
[nu
[i
]]*((nu
[i
]<<1)+1)) puts(" Memory error");
2643 /** This prints out the neighbor information for vertex i. */
2644 void voronoicell_neighbor::print_edges_neighbors(int i
) {
2648 while(j
<nu
[i
]-1) printf("%d,",ne
[i
][j
++]);
2649 printf("%d)",ne
[i
][j
]);
2650 } else printf(" ()");
2653 // Explicit instantiation
2654 template bool voronoicell_base::nplane(voronoicell
&,double,double,double,double,int);
2655 template bool voronoicell_base::nplane(voronoicell_neighbor
&,double,double,double,double,int);
2656 template void voronoicell_base::check_memory_for_copy(voronoicell
&,voronoicell_base
*);
2657 template void voronoicell_base::check_memory_for_copy(voronoicell_neighbor
&,voronoicell_base
*);