odd_even.cc – An odd–even coloring of a Voronoi cell

An odd/even coloring of a Voronoi cell

The voronoicell class contains a number of functions that can be used to directly interrogate the structure of a Voronoi cell. In the cell_statistics.cc example code many features of a Voronoi cell are calculated and printed to the screen. However, for every aspect of the cell, there are also routines that can directly pass back the information about the cell.

Several of these routines return information using the C++ vector template in the STL. For some aspects of the Voronoi cell, it is difficult to know a priori how much data will be returned, and using vectors provides a standard way to return a variable amount of data.

In the following code, a random Voronoi cell is constructed using 250 planes, using the same procedure as in the single_cell.cc example code. On line 41, a vector of face orders is created: each entry of the vector corresponds to the number of sides making up one face (eg. 3=triangle, 4=quadrilateral, 5=pentagon). On line 42, a vector of the normal vectors for each face is computed. Voro++ guarantees that all routines that return information about faces do so in the same order, allowing the entries into the two vectors to be matched with each other.

Lines 46–52 construct the Voronoi cell as a POV-Ray intersection of planes. For each face, a plane is constructed with a normal from the previously computed vector. The texture is chosen depending on whether the face has an odd or even number of sides, using a bitwise AND operation to test whether the first bit is 0 or 1.

On line 55, the standard POV-Ray routine is used to output the Voronoi cell in POV-Ray format using cylinders for edges and spheres for vertices. These can be rendered with the command

povray +H800 +W800 +A0.1 -J +Oodd_even.png odd_even.pov

to produce the image above. Faces with an even number of sides are shown in black and those with an odd number of sides are shown in white.

Code listing

 1: // Odd/even face coloring code
 2: //
 3: // Author   : Chris H. Rycroft (LBL / UC Berkeley)
 4: // Email    : chr@alum.mit.edu
 5: // Date     : August 30th 2011
 6: 
 7: #include <vector>
 8: using namespace std;
 9: 
10: #include "voro++.hh"
11: using namespace voro;
12: 
13: // This function returns a random floating point number between 0 and 1
14: double rnd() {return double(rand())/RAND_MAX;}
15: 
16: int main() {
17:         unsigned int i;
18:         double x,y,z,rsq,r;
19:         voronoicell v;
20: 
21:         // Initialize the Voronoi cell to be a cube of side length 2, centered
22:         // on the origin
23:         v.init(-1,1,-1,1,-1,1);
24: 
25:         // Cut the cell by 250 random planes which are all a distance 1 away
26:         // from the origin, to make an approximation to a sphere
27:         for(i=0;i<250;i++) {
28:                 x=2*rnd()-1;
29:                 y=2*rnd()-1;
30:                 z=2*rnd()-1;
31:                 rsq=x*x+y*y+z*z;
32:                 if(rsq>0.01&&rsq<1) {
33:                         r=1/sqrt(rsq);x*=r;y*=r;z*=r;
34:                         v.plane(x,y,z,1);
35:                 }
36:         }
37: 
38:         // Calculate the orders of the faces and the normal vectors
39:         vector<int> f_vert;
40:         vector<double> nor;
41:         v.face_orders(f_vert);
42:         v.normals(nor);
43: 
44:         // Output POV-Ray planes with textures based on whether a face is
45:         // composed of an odd or even number of edges
46:         const char* parity[2]={"even","odd"};
47:         FILE *fp=safe_fopen("odd_even_pl.pov","w");
48:         for(i=0;i<f_vert.size();i++)
49:                 fprintf(fp,"plane{<%g,%g,%g>,0.5 texture{t_%s}}\n"
50:                         ,nor[3*i],nor[3*i+1],nor[3*i+2]
51:                         ,parity[f_vert[i]&1]);
52:         fclose(fp);
53: 
54:         // Save the Voronoi cell as a spheres and cylinders
55:         v.draw_pov(0,0,0,"odd_even_v.pov");
56: }