Strip extra spaces from code.
[voro++.git] / branches / exact / src / cell.hh
blob91b30941ba415daffd5c18735859b636dfc436d8
1 // Voro++, a 3D cell-based Voronoi library
2 //
3 // Author : Chris H. Rycroft (LBL / UC Berkeley)
4 // Email : chr@alum.mit.edu
5 // Date : August 30th 2011
7 /** \file cell.hh
8 * \brief Header file for the voronoicell and related classes. */
10 #ifndef VOROPP_CELL_HH
11 #define VOROPP_CELL_HH
13 #include <cstdio>
14 #include <cstdlib>
15 #include <cmath>
16 #include <vector>
17 #include <gmpxx.h>
18 using namespace std;
20 #include "config.hh"
21 #include "common.hh"
23 namespace voro {
25 /** \brief A class representing a single Voronoi cell.
27 * This class represents a single Voronoi cell, as a collection of vertices
28 * that are connected by edges. The class contains routines for initializing
29 * the Voronoi cell to be simple shapes such as a box, tetrahedron, or octahedron.
30 * It the contains routines for recomputing the cell based on cutting it
31 * by a plane, which forms the key routine for the Voronoi cell computation.
32 * It contains numerous routine for computing statistics about the Voronoi cell,
33 * and it can output the cell in several formats.
35 * This class is not intended for direct use, but forms the base of the
36 * voronoicell and voronoicell_neighbor classes, which extend it based on
37 * whether neighboring particle ID information needs to be tracked. */
38 class voronoicell_base {
39 public:
40 /** This holds the current size of the arrays ed and nu, which
41 * hold the vertex information. If more vertices are created
42 * than can fit in this array, then it is dynamically extended
43 * using the add_memory_vertices routine. */
44 int current_vertices;
45 /** This holds the current maximum allowed order of a vertex,
46 * which sets the size of the mem, mep, and mec arrays. If a
47 * vertex is created with more vertices than this, the arrays
48 * are dynamically extended using the add_memory_vorder routine.
50 int current_vertex_order;
51 /** This sets the size of the main delete stack. */
52 int current_delete_size;
53 /** This sets the size of the auxiliary delete stack. */
54 int current_delete2_size;
55 /** This sets the total number of vertices in the current cell.
57 int p;
58 /** This is the index of particular point in the cell, which is
59 * used to start the tracing routines for plane intersection
60 * and cutting. These routines will work starting from any
61 * point, but it's often most efficient to start from the last
62 * point considered, since in many cases, the cell construction
63 * algorithm may consider many planes with similar vectors
64 * concurrently. */
65 int up;
66 /** This is a two dimensional array that holds information
67 * about the edge connections of the vertices that make up the
68 * cell. The two dimensional array is not allocated in the
69 * usual method. To account for the fact the different vertices
70 * have different orders, and thus require different amounts of
71 * storage, the elements of ed[i] point to one-dimensional
72 * arrays in the mep[] array of different sizes.
74 * More specifically, if vertex i has order m, then ed[i]
75 * points to a one-dimensional array in mep[m] that has 2*m+1
76 * entries. The first m elements hold the neighboring edges, so
77 * that the jth edge of vertex i is held in ed[i][j]. The next
78 * m elements hold a table of relations which is redundant but
79 * helps speed up the computation. It satisfies the relation
80 * ed[ed[i][j]][ed[i][m+j]]=i. The final entry holds a back
81 * pointer, so that ed[i+2*m]=i. The back pointers are used
82 * when rearranging the memory. */
83 int **ed;
84 /** This array holds the order of the vertices in the Voronoi
85 * cell. This array is dynamically allocated, with its current
86 * size held by current_vertices. */
87 int *nu;
88 /** This in an array with size 3*current_vertices for holding
89 * the positions of the vertices. */
90 double *pts;
91 mpq_class *ptsq;
92 bool synced;
93 voronoicell_base();
94 ~voronoicell_base();
95 void init_base(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax);
96 void init_octahedron_base(double l);
97 void 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);
98 void translate(double x,double y,double z);
99 void draw_pov(double x,double y,double z,FILE *fp=stdout);
100 /** Outputs the cell in POV-Ray format, using cylinders for edges
101 * and spheres for vertices, to a given file.
102 * \param[in] (x,y,z) a displacement to add to the cell's
103 * position.
104 * \param[in] filename the name of the file to write to. */
105 inline void draw_pov(double x,double y,double z,const char *filename) {
106 FILE *fp=safe_fopen(filename,"w");
107 draw_pov(x,y,z,fp);
108 fclose(fp);
110 void draw_pov_mesh(double x,double y,double z,FILE *fp=stdout);
111 /** Outputs the cell in POV-Ray format as a mesh2 object to a
112 * given file.
113 * \param[in] (x,y,z) a displacement to add to the cell's
114 * position.
115 * \param[in] filename the name of the file to write to. */
116 inline void draw_pov_mesh(double x,double y,double z,const char *filename) {
117 FILE *fp=safe_fopen(filename,"w");
118 draw_pov_mesh(x,y,z,fp);
119 fclose(fp);
121 void draw_gnuplot(double x,double y,double z,FILE *fp=stdout);
122 /** Outputs the cell in Gnuplot format a given file.
123 * \param[in] (x,y,z) a displacement to add to the cell's
124 * position.
125 * \param[in] filename the name of the file to write to. */
126 inline void draw_gnuplot(double x,double y,double z,const char *filename) {
127 FILE *fp=safe_fopen(filename,"w");
128 draw_gnuplot(x,y,z,fp);
129 fclose(fp);
131 void sync();
132 double volume();
133 double max_radius_squared();
134 double total_edge_distance();
135 double surface_area();
136 void centroid(double &cx,double &cy,double &cz);
137 int number_of_faces();
138 int number_of_edges();
139 void vertex_orders(vector<int> &v);
140 void output_vertex_orders(FILE *fp=stdout);
141 void vertices(vector<double> &v);
142 void output_vertices(FILE *fp=stdout);
143 void vertices(double x,double y,double z,vector<double> &v);
144 void output_vertices(double x,double y,double z,FILE *fp=stdout);
145 void face_areas(vector<double> &v);
146 /** Outputs the areas of the faces.
147 * \param[in] fp the file handle to write to. */
148 inline void output_face_areas(FILE *fp=stdout) {
149 vector<double> v;face_areas(v);
150 voro_print_vector(v,fp);
152 void face_orders(vector<int> &v);
153 /** Outputs a list of the number of sides of each face.
154 * \param[in] fp the file handle to write to. */
155 inline void output_face_orders(FILE *fp=stdout) {
156 vector<int> v;face_orders(v);
157 voro_print_vector(v,fp);
159 void face_freq_table(vector<int> &v);
160 /** Outputs a */
161 inline void output_face_freq_table(FILE *fp=stdout) {
162 vector<int> v;face_freq_table(v);
163 voro_print_vector(v,fp);
165 void face_vertices(vector<int> &v);
166 /** Outputs the */
167 inline void output_face_vertices(FILE *fp=stdout) {
168 vector<int> v;face_vertices(v);
169 voro_print_face_vertices(v,fp);
171 void face_perimeters(vector<double> &v);
172 /** Outputs a list of the perimeters of each face.
173 * \param[in] fp the file handle to write to. */
174 inline void output_face_perimeters(FILE *fp=stdout) {
175 vector<double> v;face_perimeters(v);
176 voro_print_vector(v,fp);
178 void normals(vector<double> &v);
179 /** Outputs a list of the perimeters of each face.
180 * \param[in] fp the file handle to write to. */
181 inline void output_normals(FILE *fp=stdout) {
182 vector<double> v;normals(v);
183 voro_print_positions(v,fp);
185 /** Outputs a custom string of information about the Voronoi
186 * cell to a file. It assumes the cell is at (0,0,0) and has a
187 * the default_radius associated with it.
188 * \param[in] format the custom format string to use.
189 * \param[in] fp the file handle to write to. */
190 inline void output_custom(const char *format,FILE *fp=stdout) {output_custom(format,0,0,0,0,default_radius,fp);}
191 void output_custom(const char *format,int i,double x,double y,double z,double r,FILE *fp=stdout);
192 template<class vc_class>
193 bool nplane(vc_class &vc,double x,double y,double z,double rs,int p_id);
194 bool plane_intersects(double x,double y,double z,double rs);
195 bool plane_intersects_guess(double x,double y,double z,double rs);
196 void construct_relations();
197 void check_relations();
198 void check_duplicates();
199 void print_edges();
200 /** Returns a list of IDs of neighboring particles
201 * corresponding to each face.
202 * \param[out] v a reference to a vector in which to return the
203 * results. If no neighbor information is
204 * available, a blank vector is returned. */
205 virtual void neighbors(vector<int> &v) {v.clear();}
206 /** This is a virtual function that is overridden by a routine
207 * to print a list of IDs of neighboring particles
208 * corresponding to each face. By default, when no neighbor
209 * information is available, the routine does nothing.
210 * \param[in] fp the file handle to write to. */
211 virtual void output_neighbors(FILE *fp=stdout) {}
212 /** This a virtual function that is overridden by a routine to
213 * print the neighboring particle IDs for a given vertex. By
214 * default, when no neighbor information is available, the
215 * routine does nothing.
216 * \param[in] i the vertex to consider. */
217 virtual void print_edges_neighbors(int i) {};
218 /** This is a simple inline function for picking out the index
219 * of the next edge counterclockwise at the current vertex.
220 * \param[in] a the index of an edge of the current vertex.
221 * \param[in] p the number of the vertex.
222 * \return 0 if a=nu[p]-1, or a+1 otherwise. */
223 inline int cycle_up(int a,int p) {return a==nu[p]-1?0:a+1;}
224 /** This is a simple inline function for picking out the index
225 * of the next edge clockwise from the current vertex.
226 * \param[in] a the index of an edge of the current vertex.
227 * \param[in] p the number of the vertex.
228 * \return nu[p]-1 if a=0, or a-1 otherwise. */
229 inline int cycle_down(int a,int p) {return a==0?nu[p]-1:a-1;}
230 protected:
231 /** This a one dimensional array that holds the current sizes
232 * of the memory allocations for them mep array.*/
233 int *mem;
234 /** This is a one dimensional array that holds the current
235 * number of vertices of order p that are stored in the mep[p]
236 * array. */
237 int *mec;
238 /** This is a two dimensional array for holding the information
239 * about the edges of the Voronoi cell. mep[p] is a
240 * one-dimensional array for holding the edge information about
241 * all vertices of order p, with each vertex holding 2*p+1
242 * integers of information. The total number of vertices held
243 * on mep[p] is stored in mem[p]. If the space runs out, the
244 * code allocates more using the add_memory() routine. */
245 int **mep;
246 inline void reset_edges();
247 template<class vc_class>
248 void check_memory_for_copy(vc_class &vc,voronoicell_base* vb);
249 void copy(voronoicell_base* vb);
250 private:
251 /** This is the delete stack, used to store the vertices which
252 * are going to be deleted during the plane cutting procedure.
254 int *ds,*stacke;
255 /** This is the auxiliary delete stack, which has size set by
256 * current_delete2_size. */
257 int *ds2,*stacke2;
258 /** This stores the current memory allocation for the marginal
259 * cases. */
260 int current_marginal;
261 /** This stores the total number of marginal points which are
262 * currently in the buffer. */
263 int n_marg;
264 /** This array contains a list of the marginal points, and also
265 * the outcomes of the marginal tests. */
266 int *marg;
267 /** The x coordinate of the normal vector to the test plane. */
268 mpq_class px;
269 /** The y coordinate of the normal vector to the test plane. */
270 mpq_class py;
271 /** The z coordinate of the normal vector to the test plane. */
272 mpq_class pz;
273 /** The magnitude of the normal vector to the test plane. */
274 mpq_class prsq;
275 template<class vc_class>
276 void add_memory(vc_class &vc,int i,int *stackp2);
277 template<class vc_class>
278 void add_memory_vertices(vc_class &vc);
279 template<class vc_class>
280 void add_memory_vorder(vc_class &vc);
281 void add_memory_ds(int *&stackp);
282 void add_memory_ds2(int *&stackp2);
283 template<class vc_class>
284 inline bool collapse_order1(vc_class &vc);
285 template<class vc_class>
286 inline bool collapse_order2(vc_class &vc);
287 template<class vc_class>
288 inline bool delete_connection(vc_class &vc,int j,int k,bool hand);
289 inline bool plane_intersects_track(mpq_class x,mpq_class y,mpq_class z,mpq_class rs,mpq_class g);
290 inline void normals_search(vector<double> &v,int i,int j,int k);
291 inline bool search_edge(int l,int &m,int &k);
292 inline int m_test(int n,mpq_class &ans);
293 friend class voronoicell;
294 friend class voronoicell_neighbor;
297 /** \brief Extension of the voronoicell_base class to represent a Voronoi
298 * cell without neighbor information.
300 * This class is an extension of the voronoicell_base class, in cases when
301 * is not necessary to track the IDs of neighboring particles associated
302 * with each face of the Voronoi cell. */
303 class voronoicell : public voronoicell_base {
304 public:
305 using voronoicell_base::nplane;
306 /** Copies the information from another voronoicell class into
307 * this class, extending memory allocation if necessary.
308 * \param[in] c the class to copy. */
309 inline void operator=(voronoicell &c) {
310 voronoicell_base* vb((voronoicell_base*) &c);
311 check_memory_for_copy(*this,vb);copy(vb);
313 /** Cuts a Voronoi cell using by the plane corresponding to the
314 * perpendicular bisector of a particle.
315 * \param[in] (x,y,z) the position of the particle.
316 * \param[in] rsq the modulus squared of the vector.
317 * \param[in] p_id the plane ID, ignored for this case where no
318 * neighbor tracking is enabled.
319 * \return False if the plane cut deleted the cell entirely,
320 * true otherwise. */
321 inline bool nplane(double x,double y,double z,double rsq,int p_id) {
322 return nplane(*this,x,y,z,rsq,0);
324 /** Cuts a Voronoi cell using by the plane corresponding to the
325 * perpendicular bisector of a particle.
326 * \param[in] (x,y,z) the position of the particle.
327 * \param[in] p_id the plane ID, ignored for this case where no
328 * neighbor tracking is enabled.
329 * \return False if the plane cut deleted the cell entirely,
330 * true otherwise. */
331 inline bool nplane(double x,double y,double z,int p_id) {
332 double rsq=x*x+y*y+z*z;
333 return nplane(*this,x,y,z,rsq,0);
335 /** Cuts a Voronoi cell using by the plane corresponding to the
336 * perpendicular bisector of a particle.
337 * \param[in] (x,y,z) the position of the particle.
338 * \param[in] rsq the modulus squared of the vector.
339 * \return False if the plane cut deleted the cell entirely,
340 * true otherwise. */
341 inline bool plane(double x,double y,double z,double rsq) {
342 return nplane(*this,x,y,z,rsq,0);
344 /** Cuts a Voronoi cell using by the plane corresponding to the
345 * perpendicular bisector of a particle.
346 * \param[in] (x,y,z) the position of the particle.
347 * \return False if the plane cut deleted the cell entirely,
348 * true otherwise. */
349 inline bool plane(double x,double y,double z) {
350 double rsq=x*x+y*y+z*z;
351 return nplane(*this,x,y,z,rsq,0);
353 /** Initializes the Voronoi cell to be rectangular box with the
354 * given dimensions.
355 * \param[in] (xmin,xmax) the minimum and maximum x coordinates.
356 * \param[in] (ymin,ymax) the minimum and maximum y coordinates.
357 * \param[in] (zmin,zmax) the minimum and maximum z coordinates. */
358 inline void init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax) {
359 init_base(xmin,xmax,ymin,ymax,zmin,zmax);
361 /** Initializes the cell to be an octahedron with vertices at
362 * (l,0,0), (-l,0,0), (0,l,0), (0,-l,0), (0,0,l), and (0,0,-l).
363 * \param[in] l a parameter setting the size of the octahedron.
365 inline void init_octahedron(double l) {
366 init_octahedron_base(l);
368 /** Initializes the cell to be a tetrahedron.
369 * \param[in] (x0,y0,z0) the coordinates of the first vertex.
370 * \param[in] (x1,y1,z1) the coordinates of the second vertex.
371 * \param[in] (x2,y2,z2) the coordinates of the third vertex.
372 * \param[in] (x3,y3,z3) the coordinates of the fourth vertex.
374 inline void 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) {
375 init_tetrahedron_base(x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3);
377 private:
378 inline void n_allocate(int i,int m) {};
379 inline void n_add_memory_vertices(int i) {};
380 inline void n_add_memory_vorder(int i) {};
381 inline void n_set_pointer(int p,int n) {};
382 inline void n_copy(int a,int b,int c,int d) {};
383 inline void n_set(int a,int b,int c) {};
384 inline void n_set_aux1(int k) {};
385 inline void n_copy_aux1(int a,int b) {};
386 inline void n_copy_aux1_shift(int a,int b) {};
387 inline void n_set_aux2_copy(int a,int b) {};
388 inline void n_copy_pointer(int a,int b) {};
389 inline void n_set_to_aux1(int j) {};
390 inline void n_set_to_aux2(int j) {};
391 inline void n_allocate_aux1(int i) {};
392 inline void n_switch_to_aux1(int i) {};
393 inline void n_copy_to_aux1(int i,int m) {};
394 inline void n_set_to_aux1_offset(int k,int m) {};
395 inline void n_neighbors(vector<int> &v) {v.clear();};
396 friend class voronoicell_base;
399 /** \brief Extension of the voronoicell_base class to represent a Voronoi cell
400 * with neighbor information.
402 * This class is an extension of the voronoicell_base class, in cases when the
403 * IDs of neighboring particles associated with each face of the Voronoi cell.
404 * It contains additional data structures mne and ne for storing this
405 * information. */
406 class voronoicell_neighbor : public voronoicell_base {
407 public:
408 using voronoicell_base::nplane;
409 /** This two dimensional array holds the neighbor information
410 * associated with each vertex. mne[p] is a one dimensional
411 * array which holds all of the neighbor information for
412 * vertices of order p. */
413 int **mne;
414 /** This is a two dimensional array that holds the neighbor
415 * information associated with each vertex. ne[i] points to a
416 * one-dimensional array in mne[nu[i]]. ne[i][j] holds the
417 * neighbor information associated with the jth edge of vertex
418 * i. It is set to the ID number of the plane that made the
419 * face that is clockwise from the jth edge. */
420 int **ne;
421 voronoicell_neighbor();
422 ~voronoicell_neighbor();
423 void operator=(voronoicell &c);
424 void operator=(voronoicell_neighbor &c);
425 /** Cuts the Voronoi cell by a particle whose center is at a
426 * separation of (x,y,z) from the cell center. The value of rsq
427 * should be initially set to \f$x^2+y^2+z^2\f$.
428 * \param[in] (x,y,z) the normal vector to the plane.
429 * \param[in] rsq the distance along this vector of the plane.
430 * \param[in] p_id the plane ID (for neighbor tracking only).
431 * \return False if the plane cut deleted the cell entirely,
432 * true otherwise. */
433 inline bool nplane(double x,double y,double z,double rsq,int p_id) {
434 return nplane(*this,x,y,z,rsq,p_id);
436 /** This routine calculates the modulus squared of the vector
437 * before passing it to the main nplane() routine with full
438 * arguments.
439 * \param[in] (x,y,z) the vector to cut the cell by.
440 * \param[in] p_id the plane ID (for neighbor tracking only).
441 * \return False if the plane cut deleted the cell entirely,
442 * true otherwise. */
443 inline bool nplane(double x,double y,double z,int p_id) {
444 double rsq=x*x+y*y+z*z;
445 return nplane(*this,x,y,z,rsq,p_id);
447 /** This version of the plane routine just makes up the plane
448 * ID to be zero. It will only be referenced if neighbor
449 * tracking is enabled.
450 * \param[in] (x,y,z) the vector to cut the cell by.
451 * \param[in] rsq the modulus squared of the vector.
452 * \return False if the plane cut deleted the cell entirely,
453 * true otherwise. */
454 inline bool plane(double x,double y,double z,double rsq) {
455 return nplane(*this,x,y,z,rsq,0);
457 /** Cuts a Voronoi cell using the influence of a particle at
458 * (x,y,z), first calculating the modulus squared of this
459 * vector before passing it to the main nplane() routine. Zero
460 * is supplied as the plane ID, which will be ignored unless
461 * neighbor tracking is enabled.
462 * \param[in] (x,y,z) the vector to cut the cell by.
463 * \return False if the plane cut deleted the cell entirely,
464 * true otherwise. */
465 inline bool plane(double x,double y,double z) {
466 double rsq=x*x+y*y+z*z;
467 return nplane(*this,x,y,z,rsq,0);
469 void init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax);
470 void init_octahedron(double l);
471 void 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);
472 void check_facets();
473 virtual void neighbors(vector<int> &v);
474 virtual void print_edges_neighbors(int i);
475 virtual void output_neighbors(FILE *fp=stdout) {
476 vector<int> v;neighbors(v);
477 voro_print_vector(v,fp);
479 private:
480 int *paux1;
481 int *paux2;
482 inline void n_allocate(int i,int m) {mne[i]=new int[m*i];}
483 inline void n_add_memory_vertices(int i) {
484 int **pp=new int*[i];
485 for(int j=0;j<current_vertices;j++) pp[j]=ne[j];
486 delete [] ne;ne=pp;
488 inline void n_add_memory_vorder(int i) {
489 int **p2=new int*[i];
490 for(int j=0;j<current_vertex_order;j++) p2[j]=mne[j];
491 delete [] mne;mne=p2;
493 inline void n_set_pointer(int p,int n) {
494 ne[p]=mne[n]+n*mec[n];
496 inline void n_copy(int a,int b,int c,int d) {ne[a][b]=ne[c][d];}
497 inline void n_set(int a,int b,int c) {ne[a][b]=c;}
498 inline void n_set_aux1(int k) {paux1=mne[k]+k*mec[k];}
499 inline void n_copy_aux1(int a,int b) {paux1[b]=ne[a][b];}
500 inline void n_copy_aux1_shift(int a,int b) {paux1[b]=ne[a][b+1];}
501 inline void n_set_aux2_copy(int a,int b) {
502 paux2=mne[b]+b*mec[b];
503 for(int i=0;i<b;i++) ne[a][i]=paux2[i];
505 inline void n_copy_pointer(int a,int b) {ne[a]=ne[b];}
506 inline void n_set_to_aux1(int j) {ne[j]=paux1;}
507 inline void n_set_to_aux2(int j) {ne[j]=paux2;}
508 inline void n_allocate_aux1(int i) {paux1=new int[i*mem[i]];}
509 inline void n_switch_to_aux1(int i) {delete [] mne[i];mne[i]=paux1;}
510 inline void n_copy_to_aux1(int i,int m) {paux1[m]=mne[i][m];}
511 inline void n_set_to_aux1_offset(int k,int m) {ne[k]=paux1+m;}
512 friend class voronoicell_base;
517 #endif