1 #include "v_network.hh"
3 /** Initializes the Voronoi network object. The geometry is set up to match a
4 * corresponding container class, and memory is allocated for the network.
5 * \param[in] c a reference to a container or container_poly class. */
6 template<class c_class
>
7 voronoi_network::voronoi_network(c_class
&c
,double net_tol_
) :
8 bx(c
.bx
), bxy(c
.bxy
), by(c
.by
), bxz(c
.bxz
), byz(c
.byz
), bz(c
.bz
),
9 nx(c
.nx
), ny(c
.ny
), nz(c
.nz
), nxyz(nx
*ny
*nz
),
10 xsp(nx
/bx
), ysp(ny
/by
), zsp(nz
/bz
), net_tol(net_tol_
) {
13 // Allocate memory for vertex structure
14 pts
=new double*[nxyz
];
19 pts
[l
]=new double[4*init_network_vertex_memory
];
20 idmem
[l
]=new int[init_network_vertex_memory
];
21 ptsc
[l
]=0;ptsmem
[l
]=init_network_vertex_memory
;
24 // Allocate memory for network edges and related statistics
25 edc
=0;edmem
=init_network_vertex_memory
*nxyz
;
28 pered
=new unsigned int*[edmem
];
29 raded
=new block
*[edmem
];
34 // Allocate memory for back pointers
38 // Allocate edge memory
39 for(l
=0;l
<edmem
;l
++) {
40 ed
[l
]=new int[2*init_network_edge_memory
];
41 ne
[l
]=ed
[l
]+init_network_edge_memory
;
43 for(l
=0;l
<edmem
;l
++) raded
[l
]=new block
[init_network_edge_memory
];
44 for(l
=0;l
<edmem
;l
++) pered
[l
]=new unsigned int[init_network_edge_memory
];
45 for(l
=0;l
<edmem
;l
++) {nu
[l
]=nec
[l
]=0;numem
[l
]=init_network_edge_memory
;}
48 vmap
=new int[4*init_vertices
];
49 map_mem
=init_vertices
;
52 /** The voronoi_network destructor removes the dynamically allocated memory. */
53 voronoi_network::~voronoi_network() {
56 // Remove Voronoi mapping array
59 // Remove individual edge arrays
60 for(l
=0;l
<edmem
;l
++) delete [] pered
[l
];
61 for(l
=0;l
<edmem
;l
++) delete [] raded
[l
];
62 for(l
=0;l
<edmem
;l
++) delete [] ed
[l
];
64 // Remove back pointers
65 delete [] regp
;delete [] reg
;
67 // Remove memory for edges and related statistics
68 delete [] numem
;delete [] nec
;delete [] nu
;
69 delete [] raded
;delete [] pered
;
70 delete [] ne
;delete [] ed
;
72 // Remove vertex structure arrays
77 delete [] ptsmem
;delete [] ptsc
;
78 delete [] idmem
;delete [] pts
;
81 /** Increase network memory for a particular region. */
82 void voronoi_network::add_network_memory(int l
) {
85 // Check to see that an absolute maximum in memory allocation
86 // has not been reached, to prevent runaway allocation
87 if(ptsmem
[l
]>max_network_vertex_memory
)
88 voro_fatal_error("Container vertex maximum memory allocation exceeded",VOROPP_MEMORY_ERROR
);
90 // Allocate new arrays
91 double *npts(new double[4*ptsmem
[l
]]);
92 int *nidmem(new int[ptsmem
[l
]]);
94 // Copy the contents of the old arrays into the new ones
95 for(int i
=0;i
<4*ptsc
[l
];i
++) npts
[i
]=pts
[l
][i
];
96 for(int i
=0;i
<ptsc
[l
];i
++) nidmem
[i
]=idmem
[l
][i
];
98 // Delete old arrays and update pointers to the new ones
99 delete [] pts
[l
];delete [] idmem
[l
];
100 pts
[l
]=npts
;idmem
[l
]=nidmem
;
103 /** Increase edge network memory. */
104 void voronoi_network::add_edge_network_memory() {
108 // Allocate new arrays
109 int **ned(new int*[edmem
]);
110 int **nne(new int*[edmem
]);
111 block
**nraded(new block
*[edmem
]);
112 unsigned int **npered(new unsigned int*[edmem
]);
113 int *nnu(new int[edmem
]);
114 int *nnec(new int[edmem
]);
115 int *nnumem(new int[edmem
]);
116 int *nreg(new int[edmem
]);
117 int *nregp(new int[edmem
]);
119 // Copy the contents of the old arrays into the new ones
132 // Carry out new allocation
134 ned
[i
]=new int[2*init_network_edge_memory
];
135 nne
[i
]=ned
[i
]+init_network_edge_memory
;
136 nnu
[i
]=nnec
[i
]=0;nnumem
[i
]=init_network_edge_memory
;
137 nraded
[i
]=new block
[init_network_edge_memory
];
138 npered
[i
++]=new unsigned int[init_network_edge_memory
];
141 // Delete old arrays and update pointers to the new ones
144 delete [] raded
;raded
=nraded
;
145 delete [] pered
;pered
=npered
;
147 delete [] nec
;nec
=nnec
;
148 delete [] numem
;numem
=nnumem
;
149 delete [] reg
;reg
=nreg
;
150 delete [] regp
;regp
=nregp
;
153 /** Increase a particular vertex memory. */
154 void voronoi_network::add_particular_vertex_memory(int l
) {
157 // Check that the vertex allocation does not exceed a maximum safe
159 if(numem
[l
]>max_vertex_order
)
160 voro_fatal_error("Particular vertex maximum memory allocation exceeded",VOROPP_MEMORY_ERROR
);
162 // Allocate new arrays
163 int *ned(new int[2*numem
[l
]]);
164 int *nne(ned
+numem
[l
]);
165 block
*nraded(new block
[numem
[l
]]);
166 unsigned int *npered(new unsigned int[numem
[l
]]);
168 // Copy the contents of the old arrays into the new ones
169 for(int i
=0;i
<nu
[l
];i
++) {
171 nraded
[i
]=raded
[l
][i
];
172 npered
[i
]=pered
[l
][i
];
174 for(int i
=0;i
<nec
[l
];i
++) nne
[i
]=ne
[l
][i
];
176 // Delete old arrays and update pointers to the new ones
177 delete [] ed
[l
];ed
[l
]=ned
;ne
[l
]=nne
;
178 delete [] raded
[l
];raded
[l
]=nraded
;
179 delete [] pered
[l
];pered
[l
]=npered
;
183 /** Increases the memory for the vertex mapping.
184 * \param[in] pmem the amount of memory needed. */
185 void voronoi_network::add_mapping_memory(int pmem
) {
186 do {map_mem
<<=1;} while(map_mem
<pmem
);
188 vmap
=new int[4*map_mem
];
191 /** Clears the class of all vertices and edges. */
192 void voronoi_network::clear_network() {
195 for(l
=0;l
<nxyz
;l
++) ptsc
[l
]=0;
196 for(l
=0;l
<edmem
;l
++) nu
[l
]=0;
199 /** Outputs the network in a format that can be read by gnuplot.
200 * \param[in] fp a file handle to write to. */
201 void voronoi_network::draw_network(FILE *fp
) {
205 ptsp
=pts
[reg
[l
]]+4*regp
[l
];
206 x
=*(ptsp
++);y
=*(ptsp
++);z
=*ptsp
;
207 for(q
=0;q
<nu
[l
];q
++) {
208 unpack_periodicity(pered
[l
][q
],ai
,aj
,ak
);
209 if(ed
[l
][q
]<l
&&ai
==0&&aj
==0&&ak
==0) continue;
210 ptsp
=pts
[reg
[ed
[l
][q
]]]+4*regp
[ed
[l
][q
]];
211 fprintf(fp
,"%g %g %g\n%g %g %g\n\n\n",x
,y
,z
,
212 *ptsp
+bx
*ai
+bxy
*aj
+bxz
*ak
,
213 ptsp
[1]+by
*aj
+byz
*ak
,ptsp
[2]+bz
*ak
);
218 /** Prints out the network.
219 * \param[in] fp a file handle to write to.
220 * \param[in] reverse_remove a boolean value, setting whether or not to remove
222 void voronoi_network::print_network(FILE *fp
,bool reverse_remove
) {
223 int ai
,aj
,ak
,j
,l
,ll
,q
;
224 double x
,y
,z
,x2
,y2
,z2
,*ptsp
;
226 // Print the vertex table
227 fprintf(fp
,"Vertex table:\n%d\n",edc
);
230 ptsp
=pts
[reg
[l
]];j
=4*regp
[l
];
231 fprintf(fp
,"%d %g %g %g %g",l
,ptsp
[j
],ptsp
[j
+1],ptsp
[j
+2],ptsp
[j
+3]);
232 for(ll
=0;ll
<nec
[l
];ll
++) fprintf(fp
," %d",ne
[l
][ll
]);
236 // Print out the edge table, loop over vertices
237 fputs("\nEdge table:\n",fp
);
240 // Store the position of this vertex
241 ptsp
=pts
[reg
[l
]];j
=4*regp
[l
];
242 x
=ptsp
[j
];y
=ptsp
[j
+1];z
=ptsp
[j
+2];
244 // Loop over edges of this vertex
245 for(q
=0;q
<nu
[l
];q
++) {
247 unpack_periodicity(pered
[l
][q
],ai
,aj
,ak
);
249 // If this option is enabled, then the code will not
250 // print edges from i to j for j<i.
251 if(reverse_remove
) if(ed
[l
][q
]<l
&&ai
==0&&aj
==0&&ak
==0) continue;
253 fprintf(fp
,"%d -> %d",l
,ed
[l
][q
]);
254 raded
[l
][q
].print(fp
);
256 // Compute and print the length of the edge
257 ptsp
=pts
[reg
[ed
[l
][q
]]];j
=4*regp
[ed
[l
][q
]];
258 x2
=ptsp
[j
]+ai
*bx
+aj
*bxy
+ak
*bxz
-x
;
259 y2
=ptsp
[j
+1]+aj
*by
+ak
*byz
-y
;
260 z2
=ptsp
[j
+2]+ak
*bz
-z
;
261 fprintf(fp
," %d %d %d %g\n",ai
,aj
,ak
,sqrt(x2
*x2
+y2
*y2
+z2
*z2
));
266 // Converts three periodic image displacements into a single unsigned integer.
267 // \param[in] i the periodic image in the x direction.
268 // \param[in] j the periodic image in the y direction.
269 // \param[in] k the periodic image in the z direction.
270 // \return The packed integer. */
271 inline unsigned int voronoi_network::pack_periodicity(int i
,int j
,int k
) {
272 unsigned int pa
=((unsigned int) (127+i
));
273 pa
<<=8;pa
+=((unsigned int) (127+j
));
274 pa
<<=8;pa
+=((unsigned int) (127+k
));
278 /** Unpacks an unsigned integer into three periodic image displacements.
279 * \param[in] pa the packed integer.
280 // \param[out] i the periodic image in the x direction.
281 // \param[out] j the periodic image in the y direction.
282 // \param[out] k the periodic image in the z direction. */
283 inline void voronoi_network::unpack_periodicity(unsigned int pa
,int &i
,int &j
,int &k
) {
284 i
=((signed int) (pa
>>16))-127;
285 j
=((signed int) ((pa
>>8)&255))-127;
286 k
=((signed int) (pa
&255))-127;
289 /** Adds a Voronoi cell to the network structure. The routine first checks all
290 * of the Voronoi cell vertices and merges them with existing ones where
291 * possible. Edges are then added to the structure.
292 * \param[in] c a reference to a Voronoi cell.
293 * \param[in] (x,y,z) the position of the Voronoi cell.
294 * \param[in] idn the ID number of the particle associated with the cell. */
295 template<class v_cell
>
296 void voronoi_network::add_to_network_internal(v_cell
&c
,int idn
,double x
,double y
,double z
,double rad
,int *cmap
) {
297 int i
,j
,k
,ijk
,l
,q
,ai
,aj
,ak
,*vmp(cmap
);
298 double gx
,gy
,vx
,vy
,vz
,crad
,*cp(c
.pts
);
300 // Loop over the vertices of the Voronoi cell
301 for(l
=0;l
<c
.p
;l
++,vmp
+=4) {
303 // Compute the real position of this vertex, and evaluate its
304 // position along the non-rectangular axes
305 vx
=x
+cp
[4*l
]*0.5;vy
=y
+cp
[4*l
+1]*0.5;vz
=z
+cp
[4*l
+2]*0.5;
306 gx
=vx
-vy
*(bxy
/by
)+vz
*(bxy
*byz
-by
*bxz
)/(by
*bz
);
309 // Compute the adjusted radius, which will be needed either way
310 crad
=0.5*sqrt(cp
[4*l
]*cp
[4*l
]+cp
[4*l
+1]*cp
[4*l
+1]+cp
[4*l
+2]*cp
[4*l
+2])-rad
;
312 // Check to see if a vertex very close to this one already
313 // exists in the network
314 if(search_previous(gx
,gy
,vx
,vy
,vz
,ijk
,q
,vmp
[1],vmp
[2],vmp
[3])) {
316 // If it does, then just map the Voronoi cell
320 // Store this radius if it smaller than the current
322 if(pts
[ijk
][4*q
+3]>crad
) pts
[ijk
][4*q
+3]=crad
;
324 k
=step_int(vz
*zsp
);if(k
<0||k
>=nz
) {ak
=step_div(k
,nz
);vx
-=bxz
*ak
;vy
-=byz
*ak
;vz
-=bz
*ak
;k
-=ak
*nz
;} else ak
=0;
325 j
=step_int(gy
*ysp
);if(j
<0||j
>=ny
) {aj
=step_div(j
,ny
);vx
-=bxy
*aj
;vy
-=by
*aj
;j
-=aj
*ny
;} else aj
=0;
326 i
=step_int(gx
*xsp
);if(i
<0||i
>=nx
) {ai
=step_div(i
,nx
);vx
-=bx
*ai
;i
-=ai
*nx
;} else ai
=0;
328 vmp
[1]=ai
;vmp
[2]=aj
;vmp
[3]=ak
;
331 if(edc
==edmem
) add_edge_network_memory();
332 if(ptsc
[ijk
]==ptsmem
[ijk
]) add_network_memory(ijk
);
334 reg
[edc
]=ijk
;regp
[edc
]=ptsc
[ijk
];
335 pts
[ijk
][4*ptsc
[ijk
]]=vx
;
336 pts
[ijk
][4*ptsc
[ijk
]+1]=vy
;
337 pts
[ijk
][4*ptsc
[ijk
]+2]=vz
;
338 pts
[ijk
][4*ptsc
[ijk
]+3]=crad
;
339 idmem
[ijk
][ptsc
[ijk
]++]=edc
;
343 // Add the neighbor information to this vertex
344 add_neighbor(*vmp
,idn
);
347 add_edges_to_network(c
,x
,y
,z
,rad
,cmap
);
350 /** Adds a neighboring particle ID to a vertex in the Voronoi network, first
351 * checking that the ID is not already recorded.
352 * \param[in] k the Voronoi vertex.
353 * \param[in] idn the particle ID number. */
354 inline void voronoi_network::add_neighbor(int k
,int idn
) {
355 for(int i
=0;i
<nec
[k
];i
++) if(ne
[k
][i
]==idn
) return;
356 if(nec
[k
]==numem
[k
]) add_particular_vertex_memory(k
);
360 /** Adds edges to the network structure, after the vertices have been
361 * considered. This routine assumes that the cmap array has a mapping between
362 * Voronoi cell vertices and Voronoi network vertices. */
363 template<class v_cell
>
364 void voronoi_network::add_edges_to_network(v_cell
&c
,double x
,double y
,double z
,double rad
,int *cmap
) {
365 int i
,j
,ai
,aj
,ak
,bi
,bj
,bk
,k
,l
,q
,*vmp
;unsigned int cper
;
366 double vx
,vy
,vz
,wx
,wy
,wz
,dx
,dy
,dz
,dis
;double *pp
;
368 vmp
=cmap
+4*l
;k
=*(vmp
++);ai
=*(vmp
++);aj
=*(vmp
++);ak
=*vmp
;
369 pp
=pts
[reg
[k
]]+4*regp
[k
];
370 vx
=pp
[0]+ai
*bx
+aj
*bxy
+ak
*bxz
;
371 vy
=pp
[1]+aj
*by
+ak
*byz
;
373 for(q
=0;q
<c
.nu
[l
];q
++) {
376 j
=*(vmp
++);bi
=*(vmp
++);bj
=*(vmp
++);bk
=*vmp
;
378 // Skip if this is a self-connecting edge
379 if(j
==k
&&bi
==ai
&&bj
==aj
&&bk
==ak
) continue;
380 cper
=pack_periodicity(bi
-ai
,bj
-aj
,bk
-ak
);
381 pp
=pts
[reg
[j
]]+(4*regp
[j
]);
382 wx
=pp
[0]+bi
*bx
+bj
*bxy
+bk
*bxz
;
383 wy
=pp
[1]+bj
*by
+bk
*byz
;
385 dx
=wx
-vx
;dy
=wy
-vy
;dz
=wz
-vz
;
386 dis
=(x
-vx
)*dx
+(y
-vy
)*dy
+(z
-vz
)*dz
;
387 dis
/=dx
*dx
+dy
*dy
+dz
*dz
;
388 if(dis
<0) dis
=0;if(dis
>1) dis
=1;
389 wx
=vx
-x
+dis
*dx
;wy
=vy
-y
+dis
*dy
;wz
=vz
-z
+dis
*dz
;
390 int nat
=not_already_there(k
,j
,cper
);
392 if(nu
[k
]==numem
[k
]) add_particular_vertex_memory(k
);
394 raded
[k
][nu
[k
]].first(sqrt(wx
*wx
+wy
*wy
+wz
*wz
)-rad
,dis
);
395 pered
[k
][nu
[k
]++]=cper
;
397 raded
[k
][nat
].add(sqrt(wx
*wx
+wy
*wy
+wz
*wz
)-rad
,dis
);
403 template<class v_cell
>
404 void voronoi_network::add_to_network_rectangular_internal(v_cell
&c
,int idn
,double x
,double y
,double z
,double rad
,int *cmap
) {
405 int i
,j
,k
,ijk
,l
,q
,ai
,aj
,ak
,*vmp(cmap
);
406 double vx
,vy
,vz
,crad
,*cp(c
.pts
);
408 for(l
=0;l
<c
.p
;l
++,vmp
+=4) {
409 vx
=x
+cp
[4*l
]*0.5;vy
=y
+cp
[4*l
+1]*0.5;vz
=z
+cp
[4*l
+2]*0.5;
410 crad
=0.5*sqrt(cp
[4*l
]*cp
[4*l
]+cp
[4*l
+1]*cp
[4*l
+1]+cp
[4*l
+2]*cp
[4*l
+2])-rad
;
411 if(safe_search_previous_rect(vx
,vy
,vz
,ijk
,q
,vmp
[1],vmp
[2],vmp
[3])) {
414 // Store this radius if it smaller than the current
416 if(pts
[ijk
][4*q
+3]>crad
) pts
[ijk
][4*q
+3]=crad
;
421 vz
-=ak
*bz
;vy
-=ak
*byz
;vx
-=ak
*bxz
;k
-=ak
*nz
;
426 vy
-=aj
*by
;vx
-=aj
*bxy
;j
-=aj
*ny
;
437 if(edc
==edmem
) add_edge_network_memory();
438 if(ptsc
[ijk
]==ptsmem
[ijk
]) add_network_memory(ijk
);
439 reg
[edc
]=ijk
;regp
[edc
]=ptsc
[ijk
];
440 pts
[ijk
][4*ptsc
[ijk
]]=vx
;
441 pts
[ijk
][4*ptsc
[ijk
]+1]=vy
;
442 pts
[ijk
][4*ptsc
[ijk
]+2]=vz
;
443 pts
[ijk
][4*ptsc
[ijk
]+3]=crad
;
444 idmem
[ijk
][ptsc
[ijk
]++]=edc
;
448 add_neighbor(*vmp
,idn
);
451 add_edges_to_network(c
,x
,y
,z
,rad
,cmap
);
454 int voronoi_network::not_already_there(int k
,int j
,unsigned int cper
) {
455 for(int i
=0;i
<nu
[k
];i
++) if(ed
[k
][i
]==j
&&pered
[k
][i
]==cper
) return i
;
459 bool voronoi_network::search_previous(double gx
,double gy
,double x
,double y
,double z
,int &ijk
,int &q
,int &pi
,int &pj
,int &pk
) {
460 int ai
=step_int((gx
-net_tol
)*xsp
),bi
=step_int((gx
+net_tol
)*xsp
);
461 int aj
=step_int((gy
-net_tol
)*ysp
),bj
=step_int((gy
+net_tol
)*ysp
);
462 int ak
=step_int((z
-net_tol
)*zsp
),bk
=step_int((z
+net_tol
)*zsp
);
464 double px
,py
,pz
,px2
,py2
,px3
,*pp
;
466 for(k
=ak
;k
<=bk
;k
++) {
467 pk
=step_div(k
,nz
);px
=pk
*bxz
;py
=pk
*byz
;pz
=pk
*bz
;mk
=k
-nz
*pk
;
468 for(j
=aj
;j
<=bj
;j
++) {
469 pj
=step_div(j
,ny
);px2
=px
+pj
*bxy
;py2
=py
+pj
*by
;mj
=j
-ny
*pj
;
470 for(i
=ai
;i
<=bi
;i
++) {
471 pi
=step_div(i
,nx
);px3
=px2
+pi
*bx
;mi
=i
-nx
*pi
;
472 ijk
=mi
+nx
*(mj
+ny
*mk
);
474 for(q
=0;q
<ptsc
[ijk
];q
++,pp
+=4) if(fabs(*pp
+px3
-x
)<net_tol
&&fabs(pp
[1]+py2
-y
)<net_tol
&&fabs(pp
[2]+pz
-z
)<net_tol
) return true;
481 bool voronoi_network::safe_search_previous_rect(double x
,double y
,double z
,int &ijk
,int &q
,int &ci
,int &cj
,int &ck
) {
482 const double tol(0.5*net_tol
);
483 if(search_previous_rect(x
+tol
,y
+tol
,z
+tol
,ijk
,q
,ci
,cj
,ck
)) return true;
484 if(search_previous_rect(x
-tol
,y
+tol
,z
+tol
,ijk
,q
,ci
,cj
,ck
)) return true;
485 if(search_previous_rect(x
+tol
,y
-tol
,z
+tol
,ijk
,q
,ci
,cj
,ck
)) return true;
486 if(search_previous_rect(x
-tol
,y
-tol
,z
+tol
,ijk
,q
,ci
,cj
,ck
)) return true;
487 if(search_previous_rect(x
+tol
,y
+tol
,z
-tol
,ijk
,q
,ci
,cj
,ck
)) return true;
488 if(search_previous_rect(x
-tol
,y
+tol
,z
-tol
,ijk
,q
,ci
,cj
,ck
)) return true;
489 if(search_previous_rect(x
+tol
,y
-tol
,z
-tol
,ijk
,q
,ci
,cj
,ck
)) return true;
490 return search_previous_rect(x
-tol
,y
-tol
,z
-tol
,ijk
,q
,ci
,cj
,ck
);
493 bool voronoi_network::search_previous_rect(double x
,double y
,double z
,int &ijk
,int &q
,int &ci
,int &cj
,int &ck
) {
494 int k
=step_int(z
*zsp
);
497 z
-=ck
*bz
;y
-=ck
*byz
;x
-=ck
*bxz
;k
-=ck
*nz
;
500 int j
=step_int(y
*ysp
);
503 y
-=cj
*by
;x
-=cj
*bxy
;j
-=cj
*ny
;
512 ijk
+=nx
*(j
+ny
*k
);double *pp(pts
[ijk
]);
513 for(q
=0;q
<ptsc
[ijk
];q
++,pp
+=4)
514 if(fabs(*pp
-x
)<net_tol
&&fabs(pp
[1]-y
)<net_tol
&&fabs(pp
[2]-z
)<net_tol
) return true;
518 /** Custom int function, that gives consistent stepping for negative numbers.
519 * With normal int, we have (-1.5,-0.5,0.5,1.5) -> (-1,0,0,1).
520 * With this routine, we have (-1.5,-0.5,0.5,1.5) -> (-2,-1,0,1). */
521 inline int voronoi_network::step_int(double a
) {
522 return a
<0?int(a
)-1:int(a
);
525 /** Custom integer division function, that gives consistent stepping for
526 * negative numbers. */
527 inline int voronoi_network::step_div(int a
,int b
) {
528 return a
>=0?a
/b
:-1+(a
+1)/b
;
531 // Explicit instantiation
532 template voronoi_network::voronoi_network(container_periodic
&, double);
533 template voronoi_network::voronoi_network(container_periodic_poly
&, double);
534 template void voronoi_network::add_to_network
<voronoicell
>(voronoicell
&, int, double, double, double, double);
535 template void voronoi_network::add_to_network
<voronoicell_neighbor
>(voronoicell_neighbor
&, int, double, double, double, double);
536 template void voronoi_network::add_to_network_rectangular
<voronoicell
>(voronoicell
&, int, double, double, double, double);
537 template void voronoi_network::add_to_network_rectangular
<voronoicell_neighbor
>(voronoicell_neighbor
&, int, double, double, double, double);