Strip extra spaces from code.
[voro++.git] / branches / 2d / src / ctr_boundary_2d.cc
bloba643ef778c40fc8d493f1f47d73bef8b0dfd118b
1 // Voro++, a cell-based Voronoi library
2 //
3 // Authors : Chris H. Rycroft (LBL / UC Berkeley)
4 // Cody Robert Dance (UC Berkeley)
5 // Email : chr@alum.mit.edu
6 // Date : August 30th 2011
8 /** \file ctr_boundary_2d.cc
9 * \brief Function implementations for the ctr_boundary_2d and related classes. */
11 #include <cstring>
13 #include "ctr_boundary_2d.hh"
15 namespace voro {
17 /** The class constructor sets up the geometry of container, initializing the
18 * minimum and maximum coordinates in each direction, and setting whether each
19 * direction is periodic or not. It divides the container into a rectangular
20 * grid of blocks, and allocates memory for each of these for storing particle
21 * positions and IDs.
22 * \param[in] (ax_,bx_) the minimum and maximum x coordinates.
23 * \param[in] (ay_,by_) the minimum and maximum y coordinates.
24 * \param[in] (nx_,ny_) the number of grid blocks in each of the three
25 * coordinate directions.
26 * \param[in] (xperiodic_,yperiodic_) flags setting whether the container is
27 * periodic in each coordinate direction.
28 * \param[in] init_mem the initial memory allocation for each block.
29 * \param[in] ps_ the number of floating point entries to store for each
30 * particle. */
31 container_boundary_2d::container_boundary_2d(double ax_,double bx_,double ay_,double by_,
32 int nx_,int ny_,bool xperiodic_,bool yperiodic_,int init_mem)
33 : voro_base_2d(nx_,ny_,(bx_-ax_)/nx_,(by_-ay_)/ny_),
34 ax(ax_), bx(bx_), ay(ay_), by(by_), xperiodic(xperiodic_), yperiodic(yperiodic_),
35 id(new int*[nxy]), p(new double*[nxy]), co(new int[nxy]), mem(new int[nxy]),
36 wid(new int*[nxy]), nlab(new int*[nxy]), plab(new int**[nxy]), bndpts(new int*[nxy]),
37 boundary_track(-1), edbc(0), edbm(init_boundary_size),
38 edb(new int[2*edbm]), bnds(new double[2*edbm]), ps(2), soi(NULL),
39 vc(*this,xperiodic_?2*nx_+1:nx_,yperiodic_?2*ny_+1:ny_) {
40 int l;
41 // totpar=0;
42 for(l=0;l<nxy;l++) co[l]=0;
43 for(l=0;l<nxy;l++) mem[l]=init_mem;
44 for(l=0;l<nxy;l++) id[l]=new int[init_mem];
45 for(l=0;l<nxy;l++) p[l]=new double[ps*init_mem];
46 for(l=0;l<nxy;l++) nlab[l]=new int[init_mem];
47 for(l=0;l<nxy;l++) plab[l]=new int*[init_mem];
48 for(l=0;l<nxy;l++) bndpts[l]=new int[init_mem];
50 for(l=0;l<nxy;l++) {wid[l]=new int[init_wall_tag_size+2];*(wid[l])=0;wid[l][1]=init_wall_tag_size;}
53 /** The container destructor frees the dynamically allocated memory. */
54 container_boundary_2d::~container_boundary_2d() {
55 int l;
57 // Clear "sphere of influence" array if it has been allocated
58 if(soi!=NULL) delete [] soi;
60 // Deallocate the block-level arrays
61 for(l=nxy-1;l>=0;l--) delete [] wid[l];
62 for(l=nxy-1;l>=0;l--) delete [] bndpts[l];
63 for(l=nxy-1;l>=0;l--) delete [] plab[l];
64 for(l=nxy-1;l>=0;l--) delete [] nlab[l];
65 for(l=nxy-1;l>=0;l--) delete [] p[l];
66 for(l=nxy-1;l>=0;l--) delete [] id[l];
68 // Delete the two-dimensional arrays
69 delete [] id;
70 delete [] p;
71 delete [] co;
72 delete [] mem;
76 /** Put a particle into the correct region of the container.
77 * \param[in] n the numerical ID of the inserted particle.
78 * \param[in] (x,y) the position vector of the inserted particle. */
79 void container_boundary_2d::put(int n,double x,double y) {
80 int ij;
81 if(put_locate_block(ij,x,y)) {
82 //totpar++;
83 id[ij][co[ij]]=n;
84 if(boundary_track!=-1) {
85 bndpts[ij][co[ij]]=edbc;
86 register_boundary(x,y);
87 } else bndpts[ij][co[ij]]=-1;
88 double *pp=p[ij]+2*co[ij]++;
89 *(pp++)=x;*pp=y;
93 /** Put a particle into the correct region of the container, also recording
94 * into which region it was stored.
95 * \param[in] vo the ordering class in which to record the region.
96 * \param[in] n the numerical ID of the inserted particle.
97 * \param[in] (x,y) the position vector of the inserted particle. */
98 void container_boundary_2d::put(particle_order &vo,int n,double x,double y) {
99 int ij;
100 if(put_locate_block(ij,x,y)) {
101 //totpar++;
102 id[ij][co[ij]]=n;
103 if(boundary_track!=-1) {
104 bndpts[ij][co[ij]]=edbc;
105 register_boundary(x,y);
106 } else bndpts[ij][co[ij]]=-1;
107 vo.add(ij,co[ij]);
108 double *pp=p[ij]+2*co[ij]++;
109 *(pp++)=x;*pp=y;
113 /** This routine takes a particle position vector, tries to remap it into the
114 * primary domain. If successful, it computes the region into which it can be
115 * stored and checks that there is enough memory within this region to store
116 * it.
117 * \param[out] ij the region index.
118 * \param[in,out] (x,y) the particle position, remapped into the primary
119 * domain if necessary.
120 * \return True if the particle can be successfully placed into the container,
121 * false otherwise. */
122 inline bool container_boundary_2d::put_locate_block(int &ij,double &x,double &y) {
123 if(put_remap(ij,x,y)) {
124 if(co[ij]==mem[ij]) add_particle_memory(ij);
125 return true;
127 #if VOROPP_REPORT_OUT_OF_BOUNDS ==1
128 fprintf(stderr,"Out of bounds: (x,y)=(%g,%g)\n",x,y);
129 #endif
130 return false;
133 /** Takes a particle position vector and computes the region index into which
134 * it should be stored. If the container is periodic, then the routine also
135 * maps the particle position to ensure it is in the primary domain. If the
136 * container is not periodic, the routine bails out.
137 * \param[out] ij the region index.
138 * \param[in,out] (x,y) the particle position, remapped into the primary domain
139 * if necessary.
140 * \return True if the particle can be successfully placed into the container,
141 * false otherwise. */
142 inline bool container_boundary_2d::put_remap(int &ij,double &x,double &y) {
143 int l;
145 ij=step_int((x-ax)*xsp);
146 if(xperiodic) {l=step_mod(ij,nx);x+=boxx*(l-ij);ij=l;}
147 else if(ij<0||ij>=nx) return false;
149 int j=step_int((y-ay)*ysp);
150 if(yperiodic) {l=step_mod(j,ny);y+=boxy*(l-j);j=l;}
151 else if(j<0||j>=ny) return false;
153 ij+=nx*j;
154 return true;
157 /** Increase memory for a particular region.
158 * \param[in] i the index of the region to reallocate. */
159 void container_boundary_2d::add_particle_memory(int i) {
160 int l,nmem=mem[i]<<1;
162 // Carry out a check on the memory allocation size, and
163 // print a status message if requested
164 if(nmem>max_particle_memory_2d)
165 voro_fatal_error("Absolute maximum memory allocation exceeded",VOROPP_MEMORY_ERROR);
166 #if VOROPP_VERBOSE >=3
167 fprintf(stderr,"Particle memory in region %d scaled up to %d\n",i,nmem);
168 #endif
170 // Allocate new memory and copy in the contents of the old arrays
171 int *idp=new int[nmem];
172 for(l=0;l<co[i];l++) idp[l]=id[i][l];
173 double *pp=new double[ps*nmem];
174 for(l=0;l<ps*co[i];l++) pp[l]=p[i][l];
175 int *nlabp=new int[nmem];
176 for(l=0;l<co[i];l++) nlabp[l]=nlab[i][l];
177 int **plabp=new int*[nmem];
178 for(l=0;l<co[i];l++) plabp[l]=plab[i][l];
179 int *bndptsp=new int[nmem];
180 for(l=0;l<co[i];l++) bndptsp[l]=bndpts[i][l];
182 // Update pointers and delete old arrays
183 mem[i]=nmem;
184 delete [] id[i];id[i]=idp;
185 delete [] p[i];p[i]=pp;
186 delete [] nlab[i];nlab[i]=nlabp;
187 delete [] plab[i];plab[i]=plabp;
188 delete [] bndpts[i];bndpts[i]=bndptsp;
191 /** Outputs the a list of all the container regions along with the number of
192 * particles stored within each. */
193 void container_boundary_2d::region_count() {
194 int i,j,*cop=co;
195 for(j=0;j<ny;j++) for(i=0;i<nx;i++)
196 printf("Region (%d,%d): %d particles\n",i,j,*(cop++));
199 /** Clears a container of particles. */
200 void container_boundary_2d::clear() {
201 for(int *cop=co;cop<co+nxy;cop++) *cop=0;
204 /** Computes all the Voronoi cells and saves customized information about them.
205 * \param[in] format the custom output string to use.
206 * \param[in] fp a file handle to write to. */
207 void container_boundary_2d::print_custom(const char *format,FILE *fp) {
208 c_loop_all_2d vl(*this);
209 print_custom(vl,format,fp);
212 /** Computes all the Voronoi cells and saves customized information about them.
213 * \param[in] format the custom output string to use.
214 * \param[in] filename the name of the file to write to. */
215 void container_boundary_2d::print_custom(const char *format,const char *filename) {
216 FILE *fp=safe_fopen(filename,"w");
217 print_custom(format,fp);
218 fclose(fp);
221 /** Computes all of the Voronoi cells in the container, but does nothing
222 * with the output. It is useful for measuring the pure computation time
223 * of the Voronoi algorithm, without any additional calculations such as
224 * volume evaluation or cell output. */
225 void container_boundary_2d::compute_all_cells() {
226 voronoicell_nonconvex_2d c;
227 c_loop_all_2d vl(*this);
228 if(vl.start()) do compute_cell(c,vl);
229 while(vl.inc());
232 /** Calculates all of the Voronoi cells and sums their volumes. In most cases
233 * without walls, the sum of the Voronoi cell volumes should equal the volume
234 * of the container to numerical precision.
235 * \return The sum of all of the computed Voronoi volumes. */
236 double container_boundary_2d::sum_cell_areas() {
237 voronoicell_nonconvex_2d c;
238 double area=0;
239 c_loop_all_2d vl(*this);
240 if(vl.start()) do if(compute_cell(c,vl)) area+=c.area();while(vl.inc());
241 return area;
244 /** Draws an outline of the domain in gnuplot format.
245 * \param[in] fp the file handle to write to. */
246 void container_boundary_2d::draw_domain_gnuplot(FILE *fp) {
247 fprintf(fp,"%g %g\n%g %g\n%g %g\n%g %g\n%g %g\n",ax,ay,bx,ay,bx,by,ax,by,ax,ay);
250 /** Draws an outline of the domain in POV-Ray format.
251 * \param[in] fp the file handle to write to. */
252 void container_boundary_2d::draw_domain_pov(FILE *fp) {
253 fprintf(fp,"cylinder{<%g,%g,0>,<%g,%g,0>,rr}\n"
254 "cylinder{<%g,%g,0>,<%g,%g,0>,rr}\n",ax,ay,bx,ay,ax,by,bx,by);
255 fprintf(fp,"cylinder{<%g,%g,0>,<%g,%g,0>,rr}\n"
256 "cylinder{<%g,%g,0>,<%g,%g,0>,rr}\n",ax,ay,ax,by,bx,ay,bx,by);
257 fprintf(fp,"sphere{<%g,%g,0>,rr}\nsphere{<%g,%g,0>,rr}\n"
258 "sphere{<%g,%g,0>,rr}\nsphere{<%g,%g,0>,rr}\n",ax,ay,bx,ay,ax,by,bx,by);
261 /** This does the additional set-up for non-convex containers. We assume that
262 * **p, **id, *co, *mem, *bnds, and edbc have already been setup. We then
263 * proceed to setup **wid, *soi, and THE PROBLEM POINTS BOOLEAN ARRAY.
264 * This algorithm keeps the importing seperate from the set-up */
265 void container_boundary_2d::setup(){
266 // double lx,ly;//last (x,y)
267 double cx,cy,nx,ny;//current (x,y),next (x,y)
268 int widl=1,maxwid=1,fwid=1,nwid;//lwid;
269 // bool first=true;
271 tmp=tmpp=new int[3*init_temp_label_size];
272 tmpe=tmp+3*init_temp_label_size;
274 while(widl!=edbc){
275 cx=bnds[2*widl];cy=bnds[2*widl+1];
276 nwid=edb[2*widl];//lwid=edb[2*widl+1];
277 //lx=bnds[lwid*2];ly=bnds[lwid*2+1];
278 nx=bnds[2*nwid];ny=bnds[2*nwid+1];
280 tag_walls(cx,cy,nx,ny,widl);
281 semi_circle_labeling(cx,cy,nx,ny,widl);
283 //make sure that the cos(angle)>1 and the angle points inward
284 //probpts=(lx-cx)*(nx-cx)+(ly-cy)*(ny-cy)>tolerance &&
285 // cross_product(lx-cx,ly-cy,nx-cx,ny-cy);
287 widl=edb[2*widl];
288 if(widl>maxwid) maxwid=widl;
289 if(widl==fwid){
290 widl=maxwid+1;
291 fwid=widl;
292 maxwid++;
293 // first=false;
297 // The temporary array can now be used to set up the label table
298 create_label_table();
300 // Remove temporary array
301 delete [] tmp;
304 /** Given two points, tags all the computational boxes that the line segment
305 * specified by the two points
306 * goes through. param[in] (x1,y1) this is one point
307 * \param[in] (x2,y2) this is the other point.
308 * \param[in] wid this is the wall id bnds[2*wid] is the x index of the first
309 * vertex in the c-c direction. */
310 void container_boundary_2d::tag_walls(double x1,double y1,double x2,double y2,int wid_) {
312 // Find which boxes these points are within
313 int i1=int((x1-ax)*xsp),j1=int((y1-ay)*ysp);
314 int i2=int((x2-ax)*xsp),j2=int((y2-ay)*ysp),k,ij;
316 // Swap to ensure that i1 is smaller than i2
317 double q,yfac;
318 if(i2<i1) {
319 q=x1;x1=x2;x2=q;q=y1;y1=y2;y2=q;
320 k=i1;i1=i2;i2=k;k=j1;j1=j2;j2=k;
323 ij=i1+j1*nx;
324 if(j1<j2) {
325 yfac=1/(y2-y1);
326 do {
327 j1++;
328 q=ay+j1*boxy;
329 k=int((((q-y1)*x2+x1*(y2-q))*yfac-ax)*xsp);
330 if(k>=nx) k=nx-1;
331 tag_line(ij,(j1-1)*nx+k,wid_);
332 ij+=nx;
333 } while(j1<j2);
334 } else if(j1>j2) {
335 yfac=1/(y2-y1);
336 do {
337 q=ay+j1*boxy;
338 k=int((((q-y1)*x2+x1*(y2-q))*yfac-ax)*xsp);
339 if(k>=nx) k=nx-1;
340 tag_line(ij,j1*nx+k,wid_);
341 ij-=nx;
342 j1--;
343 } while(j1>j2);
345 tag_line(ij,i2+j2*nx,wid_);
348 void container_boundary_2d::tag_line(int &ij,int ije,int wid_) {
349 tag(ij,wid_);
350 while(ij<ije) {
351 ij++;
352 tag(ij,wid_);
356 inline void container_boundary_2d::tag(int ij,int wid_) {
357 int *&wp(wid[ij]);
358 if(*wp==wp[1]) {
359 int nws=wp[1]<<1;
360 if(nws>max_wall_tag_size) voro_fatal_error("Maximum wall tag memory exceeded",VOROPP_MEMORY_ERROR);
361 int *np=new int[nws+2];
362 *np=*wp;np[1]=nws;
363 for(int i=2;i<*wp+2;i++) np[i]=wp[i];
364 delete [] wp;
365 wp=np;
367 wp[2+(*wp)++]=wid_;
370 /* Tags particles that are within a semicircle (on the appropriate side) of a
371 * boundary.
372 * \param[in] (x1,y1) the start point of the wall segment, arranged so that it
373 * is the first point reached in the counter-clockwise
374 * direction.
375 * \param[in] (x2,y2) the end points of the wall segment. */
376 void container_boundary_2d::semi_circle_labeling(double x1,double y1,double x2,double y2,int bid) {
378 double radius=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))*0.5,
379 midx=(x1+x2)*0.5,midy=(y1+y2)*0.5,cpx,cpy;
380 int ai=int((midx-radius-ax)*xsp),
381 bi=int((midx+radius-ax)*xsp),
382 aj=int((midy-radius-ay)*ysp),
383 bj=int((midy+radius-ay)*ysp),i,j,ij,k;
384 if(ai<0) ai=0;if(ai>=nx) ai=nx-1;
385 if(bi<0) bi=0;if(bi>=nx) bi=nx-1;
386 if(aj<0) aj=0;if(aj>=ny) aj=ny-1;
387 if(bj<0) bj=0;if(bj>=ny) bj=ny-1;
389 // Now loop through all the particles in the boxes we found, tagging
390 // the ones that are within radius of (midx,midy) and are on the
391 // appropriate side of the wall
392 for(j=aj;j<=bj;j++) for(i=ai;i<=bi;i++) {
393 ij=i+nx*j;
394 for(k=0;k<co[ij];k++) {
395 cpx=p[ij][2*k];
396 cpy=p[ij][2*k+1];
397 if((midx-cpx)*(midx-cpx)+(midy-cpy)*(midy-cpy)<=radius*radius&&
398 cross_product((x1-x2),(y1-y2),(cpx-x2),(cpy-y2))&&
399 (cpx!=x1||cpy==y1)&&(cpx!=x2||cpy!=y2)) {
401 if(tmpp==tmpe) add_temporary_label_memory();
402 *(tmpp++)=ij;
403 *(tmpp++)=k;
404 *(tmpp++)=bid;
410 void container_boundary_2d::create_label_table() {
411 int ij,q,*pp,tlab=0;
413 // Clear label counters
414 for(ij=0;ij<nxy;ij++) for(q=0;q<co[ij];q++) nlab[ij][q]=0;
416 // Increment label counters
417 for(pp=tmp;pp<tmpp;pp+=3) {nlab[*pp][pp[1]]++;tlab++;}
419 // Check for case of no labels at all (which may be common)
420 if(tlab==0) {
421 #if VOROPP_VERBOSE >=2
422 fputs("No labels needed\n",stderr);
423 #endif
424 return;
427 // If there was already a table from a previous call, remove it
428 if(soi!=NULL) delete [] soi;
430 // Allocate the label array, and set up pointers from each particle
431 // to the corresponding location
432 pp=soi=new int[tlab];
433 for(ij=0;ij<nxy;ij++) for(q=0;q<co[ij];pp+=nlab[ij][q++]) plab[ij][q]=pp;
435 // Fill in the label entries
436 for(pp=tmp;pp<tmpp;pp+=3) *(plab[*pp][pp[1]]++)=pp[2];
438 // Reset the label pointers
439 pp=soi;
440 for(ij=0;ij<nxy;ij++) for(q=0;q<co[ij];pp+=nlab[ij][q++]) plab[ij][q]=pp;
443 /** Draws the boundaries. (Note: this currently assumes that each boundary loop
444 * is a continuous block in the bnds array, which will be true for the import
445 * function. However, it may not be true in other cases, in which case this
446 * routine would have to be extended.) */
447 void container_boundary_2d::draw_boundary_gnuplot(FILE *fp) {
448 int i;
450 for(i=0;i<edbc;i++) {
451 fprintf(fp,"%g %g\n",bnds[2*i],bnds[2*i+1]);
453 // If a loop is detected, than complete the loop in the output file
454 // and insert a newline
455 if(edb[2*i]<i) fprintf(fp,"%g %g\n\n",bnds[2*edb[2*i]],bnds[2*edb[2*i]+1]);
459 bool container_boundary_2d::point_inside(double x,double y) {
460 int i=0,j=0,k=0;
461 bool sleft,left,nleft;
463 while(i<edbc) {
464 sleft=left=bnds[2*i]<x;
465 do {
466 j=edb[2*i];
467 nleft=j<i?sleft:bnds[2*j]<x;
468 if(nleft!=left) {
469 if(left) {
470 if(bnds[2*j+1]*(x-bnds[2*i])+bnds[2*i+1]*(bnds[2*j]-x)<y*(bnds[2*j]-bnds[2*i])) k++;
471 } else {
472 if(bnds[2*j+1]*(x-bnds[2*i])+bnds[2*i+1]*(bnds[2*j]-x)>y*(bnds[2*j]-bnds[2*i])) k--;
475 left=nleft;
476 i++;
477 } while(j==i);
480 #if VOROPP_VERBOSE >=2
481 if(k<0) fprintf(stderr,"Negative winding number of %d for (%g,%g)\n",j,x,y);
482 else if(k>1) fprintf(stderr,"Winding number of %d for (%g,%g)\n",j,x,y);
483 #endif
484 return k>0;
487 template<class v_cell_2d>
488 bool container_boundary_2d::boundary_cuts(v_cell_2d &c,int ij,double x,double y) {
489 int i,j,k;
490 double lx,ly,dx,dy,dr;
491 for(i=2;i<*(wid[ij])+2;i++) {
492 j=2*wid[ij][i];k=2*edb[j];
493 dx=bnds[k]-bnds[j];dy=bnds[k+1]-bnds[j+1];
494 dr=dy*(bnds[j]-x)-dx*(bnds[j+1]-y);
495 if(dr<tolerance) continue;
496 lx=bnds[j]+bnds[k]-2*x;
497 ly=bnds[j+1]+bnds[k+1]-2*y;
498 if(lx*lx+ly*ly>dx*dx+dy*dy) continue;
499 if(!c.plane(dy,-dx,2*dr)) return false;
501 return true;
504 bool container_boundary_2d::skip(int ij,int q,double x,double y) {
505 int j;
506 double wx1,wy1,wx2,wy2,dx,dy,lx,ly;
507 double cx=p[ij][ps*q],cy=p[ij][ps*q+1];
509 for(int i=0;i<nlab[ij][q];i++) {
510 j=2*plab[ij][q][i];
511 wx1=bnds[j];
512 wy1=bnds[j+1];
513 j=2*edb[j];
514 wx2=bnds[j];
515 wy2=bnds[j+1];
516 dx=wx1-wx2;
517 dy=wy1-wy2;
518 wx1-=x;wy1-=y;
519 if(dx*wy1-dy*wx1>tolerance) {
520 lx=cx-x;ly=cy-y;
521 if(wx1*ly-wy1*lx>tolerance&&lx*(wy2-y)-ly*(wx2-x)>tolerance) return true;
524 return false;
528 /** Imports a list of particles from an input stream.
529 * \param[in] fp a file handle to read from. */
530 void container_boundary_2d::import(FILE *fp) {
531 int i;
532 double x,y;
533 char *buf(new char[512]);
535 while(fgets(buf,512,fp)!=NULL) {
536 if(strcmp(buf,"#Start\n")==0||strcmp(buf,"# Start\n")==0) {
538 // Check that two consecutive start tokens haven't been
539 // encountered
540 if(boundary_track!=-1) voro_fatal_error("File import error - two consecutive start tokens found",VOROPP_FILE_ERROR);
541 start_boundary();
543 } else if(strcmp(buf,"#End\n")==0||strcmp(buf,"# End\n")==0||
544 strcmp(buf,"#End")==0||strcmp(buf,"# End")==0) {
546 // Check that two consecutive end tokens haven't been
547 // encountered
548 if(boundary_track==-1) voro_fatal_error("File import error - found end token without start token",VOROPP_FILE_ERROR);
549 end_boundary();
550 } else {
552 // Try and read three entries from the line
553 if(sscanf(buf,"%d %lg %lg",&i,&x,&y)!=3) voro_fatal_error("File import error - can't parse particle information",VOROPP_FILE_ERROR);
554 put(i,x,y);
557 if(boundary_track!=-1) voro_fatal_error("File import error - end of file reached without finding end token",VOROPP_FILE_ERROR);
559 if(!feof(fp)) voro_fatal_error("File import error - error reading string from file",VOROPP_FILE_ERROR);
560 delete [] buf;
563 void container_boundary_2d::end_boundary() {
564 if(boundary_track!=edbc) {
565 edb[2*boundary_track+1]=edbc-1;
566 edb[2*(edbc-1)]=boundary_track;
568 boundary_track=-1;
571 void container_boundary_2d::register_boundary(double x,double y) {
572 if(edbc==edbm) add_boundary_memory();
573 if(edbc!=boundary_track) {
574 edb[2*edbc-2]=edbc;
575 edb[2*edbc+1]=edbc-1;
577 bnds[2*edbc]=x;
578 bnds[2*(edbc++)+1]=y;
581 /** Increases the size of the temporary label memory. */
582 void container_boundary_2d::add_temporary_label_memory() {
583 int size(tmpe-tmp);
584 size<<=1;
585 if(size>3*max_temp_label_size)
586 voro_fatal_error("Absolute temporary label memory allocation exceeded",VOROPP_MEMORY_ERROR);
587 #if VOROPP_VERBOSE >=3
588 fprintf(stderr,"Temporary label memory in region scaled up to %d\n",size);
589 #endif
590 int *ntmp(new int[size]),*tp(tmp);tmpp=ntmp;
591 while(tp<tmpe) *(tmpp++)=*(tp++);
592 delete [] tmp;
593 tmp=ntmp;tmpe=tmp+size;
596 /** Increases the memory allocation for the boundary points. */
597 void container_boundary_2d::add_boundary_memory() {
598 int i;
599 edbm<<=1;
600 if(edbm>max_boundary_size)
601 voro_fatal_error("Absolute boundary memory allocation exceeded",VOROPP_MEMORY_ERROR);
602 #if VOROPP_VERBOSE >=3
603 fprintf(stderr,"Boundary memory scaled up to %d\n",size);
604 #endif
606 // Reallocate the boundary vertex information
607 double *nbnds(new double[2*edbm]);
608 for(i=0;i<2*edbc;i++) nbnds[i]=bnds[i];
609 delete [] nbnds;bnds=nbnds;
611 // Reallocate the edge information
612 int *nedb(new int[2*edbm]);
613 for(i=0;i<2*edbc;i++) nedb[i]=edb[i];
614 delete [] edb;edb=nedb;
617 // Explicit instantiation
618 template bool container_boundary_2d::boundary_cuts(voronoicell_nonconvex_2d&,int,double,double);
619 template bool container_boundary_2d::boundary_cuts(voronoicell_nonconvex_neighbor_2d&,int,double,double);