// relevant parameters: comments here and in VoronoiGraph int NUMPOINTS; int MAXORDER; ArrayList points; ArrayList speeds; ArrayList voronoiGraphs; ArrayList borders; void setup(){ size(800,800); // background(255); //white background, irrelevant unless roundof errors leave a gap smooth(); NUMPOINTS=10; // Number of cells per iteration MAXORDER=0; // Number of iteration. Total number of cells is NUMPOINTS^MAXORDER reset(); // Sets a clean slate } void reset(){ generateBorders(); // To recurse the voronoi, all cells need to be closed, including capping at the borders. voronoiGraphs=new ArrayList(); // The main voronoi is created here, parameters: number of cells, enclosing borders, fill color, stroke color points=new ArrayList(); for(int i=0;iwidth){ newx=2*width-newx; currentSpeed.x*=-1.0f; } float newy= currentPoint.y + currentSpeed.y; if (newy<0){ newy*=-1.0f; currentSpeed.y*=-1.0f; } if(newy>height){ newy=2*height-newy; currentSpeed.y*=-1.0f; } SegmentPoint2D point=new SegmentPoint2D(newx,newy); points.set(i,point); } generateBorders(); // To recurse the voronoi, all cells need to be closed, including capping at the borders. voronoiGraphs=new ArrayList(); // The main voronoi is created here, parameters: number of cells, enclosing borders, fill color, stroke color Voronoi mainVoronoi=new Voronoi(NUMPOINTS,borders,points,0,color(0),color(255,200)); VoronoiGraph mainGraph = new VoronoiGraph(mainVoronoi,MAXORDER);// A lower memory version of the voronoi, retains enough information for drawing but throws all construction lines away. voronoiGraphs.add(mainGraph); divide(mainGraph);// Recurse voronoi } void draw(){ background(0); Iterator graphItr = voronoiGraphs.iterator(); while(graphItr.hasNext()){ VoronoiGraph currentGraph = (VoronoiGraph)graphItr.next(); if(currentGraph.order>MAXORDER-2) currentGraph.drawFill(); // Only draw last 2 layers, since fills overlap. } graphItr = voronoiGraphs.iterator(); while(graphItr.hasNext()){ ((VoronoiGraph)graphItr.next()).drawStroke();// Draw all strokes } update(); } void generateBorders(){// Create initial borders borders = new ArrayList(); ArrayList borderPoints = new ArrayList(); Segment2D border=new Segment2D(); boolean circle=false;// If true, then the initial boundary is a circle if (circle){ float a = TWO_PI/128.0f; for(int i=0;i<128;i++){ Point2D borderPoint = new Point2D(width/2+width/2*cos(a*i),height/2+height/2*sin(a*i)); borderPoints.add(borderPoint); } for(int i=0;i<128;i++){ int nexti=(i==127)?0:i+1; border=new Segment2D((Point2D)borderPoints.get(i),(Point2D)borderPoints.get(nexti),i); borders.add(border); } } else{ border=new Segment2D(0,0,width-1,0,0); borders.add(border); border=new Segment2D(0,height-1,0,0,1); borders.add(border); border=new Segment2D(width-1,0,width-1,height-1,2); borders.add(border); border=new Segment2D(width-1,height-1,0,height-1,3); borders.add(border); } } void generateBorders(ArrayList periphery){// Create borders from a cell (so a new graph can be made inside the cell) borders = new ArrayList(); for(int i=0;iperiphery.size()-1)nexti=0; Point2D pointj=(Point2D)periphery.get(nexti); borders.add(new Segment2D(pointi,pointj)); } } void divide(final VoronoiGraph voronoiGraph){ if((voronoiGraph.order