import toxi.math.conversion.*;
import toxi.geom.*;
import toxi.math.*;
import toxi.geom.mesh2d.*;
import toxi.util.datatypes.*;
import toxi.util.events.*;
import toxi.geom.mesh.subdiv.*;
import toxi.geom.mesh.*;
import toxi.math.waves.*;
import toxi.util.*;
import toxi.math.noise.*;
import toxi.processing.*;
ToxiclibsSupport gfx;
Voronoi voronoi;
import processing.svg.*;
boolean makeSVG = false;
import processing.pdf.*;
boolean makePDF = false;
String docBase = "voronoi_arcs";
String docName = "";
color bg = color(243, 242, 234);
color[] colorArray = {
color(39, 225, 193),
color(14, 162, 147),
color(47, 15, 93),
color(65, 42, 98),
color(107, 36, 95)
};
ArrayList<PVector> pointsList;
ArrayList<Cell> voronCells;
float cellSpace = 100;
void setup() {
size(1300, 850, P2D);
background(bg);
gfx = new ToxiclibsSupport(this);
// make a list of the points, evenly distributed around the canvas
pointsList = new ArrayList<PVector>();
pointsList = poissonDiskSampling(cellSpace, 30);
voronCells = new ArrayList<Cell>();
voronoi = new Voronoi();
makeVoronoi();
smooth(8);
//noLoop();
}
void draw() {
background(bg);
if(makeSVG){
docName = timeStamp(docBase);
beginRecord(SVG, "svg/" + docName + ".svg");
} else{ docName = ""; }
if(makePDF){
docName = timeStamp(docBase);
beginRecord(PDF, "pdf/" + docName + ".pdf");
} else{ docName = ""; }
for(Cell c : voronCells){
c.render();
}
if(makeSVG){
endRecord();
makeSVG = false;
saveImage();
}
if(makePDF){
endRecord();
makePDF = false;
}
}
void makeVoronoi() {
// for each of those points now make a voronoi shape then make a corresponding voronoi cell
for(PVector vec : pointsList){
voronoi.addPoint(new Vec2D(vec.x, vec.y));
}
for(Polygon2D polygon : voronoi.getRegions()) {
Vec2D polyV = polygon.getCentroid();
PVector vec = new PVector(0,0);
if(polyV.x <= 0 || polyV.x >= width || polyV.y <= 0 || polyV.y >= height){
for(Vec2D v : voronoi.getSites()){
if(polygon.containsPoint(v)){
vec.set(v.x, v.y);
}
}
} else{
vec.set(polyV.x, polyV.y);
}
color clr = colorArray[floor(random(colorArray.length))];
voronCells.add(new Cell(vec, polygon, cellSpace, clr));
}
}
void keyPressed() {
if(key == ' ') reset();
if(key == 'a') saveImage();
if(key == 's') svgExport();
if(key == 'd') pdfExport();
}
void reset() {
background(bg);
pointsList.clear();
voronCells.clear();
pointsList = new ArrayList<PVector>();
pointsList = poissonDiskSampling(cellSpace, 30);
voronCells = new ArrayList<Cell>();
voronoi = new Voronoi();
makeVoronoi();
//redraw();
}
void saveImage() {
if(docName == ""){
docName = timeStamp(docBase);
}
saveFrame("png/" + docName + ".png");
}
void svgExport() {
makeSVG = true;
//redraw();
}
void pdfExport() {
makePDF = true;
//redraw();
}
String timeStamp(String name) {
return name + "-" + year() + nf(month(), 2) + nf(day(), 2) +
"-" + nf(hour(), 2) + nf(minute(), 2) + nf(second(), 2);
}
class Cell {
PVector midPt;
float radius;
color clrSelect;
float angle;
PVector outerPt;
PVector drawPt;
PVector boxPt;
int imgSize;
float boxCornerRad;
PGraphics curves;
PGraphics masker;
Polygon2D voron;
Cell(PVector thePos, Polygon2D theVoron, float theRad, color theClr) {
midPt = thePos;
voron = theVoron;
radius = theRad;
clrSelect = theClr;
angle = random(TWO_PI);
outerPt = PVector.fromAngle(angle).setMag(radius).add(midPt);
drawPt = PVector.fromAngle(angle).setMag((radius/2)-5).add(outerPt);
imgSize = int(radius * 2)+5;
boxCornerRad = (imgSize * sqrt(2)) / 2;
boxPt = PVector.fromAngle(PI+QUARTER_PI).setMag(boxCornerRad).add(midPt);
curves = makeCurves();
masker = makeMask();
}
void render() {
curves.mask(masker);
pushMatrix();
translate(drawPt.x, drawPt.y);
rotate(angle + HALF_PI + QUARTER_PI);
image(curves, 0,0);
popMatrix();
}
PGraphics makeCurves() {
PGraphics img = createGraphics(imgSize, imgSize);
img.beginDraw();
img.clear();
img.background(bg);
img.noFill();
img.stroke(clrSelect);
img.strokeWeight(2);
for(int i=0; i<10; i++){
float currRad = 40 + (i * 15);
pushMatrix();
translate(outerPt.x, outerPt.y);
img.arc((radius/4), (radius/4), currRad*2, currRad*2, -QUARTER_PI, HALF_PI+QUARTER_PI);
popMatrix();
}
img.endDraw();
return img;
}
PGraphics makeMask() {
ArrayList<PVector> voronPositions = new ArrayList<PVector>();
PVector originOffsetPt = PVector.sub(midPt, boxPt);
for(int i=0; i<voron.vertices.size(); i++){
PVector currPt = new PVector(voron.vertices.get(i).x, voron.vertices.get(i).y);
float distFromCenter = PVector.dist(midPt, currPt) - 5;
PVector fromCenterPt = PVector.sub(midPt, currPt);
pushMatrix();
translate(midPt.x, midPt.y);
float cornerAng = fromCenterPt.heading();
popMatrix();
float xPos = cos(cornerAng + PI - angle - HALF_PI - QUARTER_PI) * distFromCenter;
float yPos = sin(cornerAng + PI - angle - HALF_PI - QUARTER_PI) * distFromCenter;
voronPositions.add(new PVector(xPos, yPos));
}
PGraphics msk = createGraphics(imgSize, imgSize);
msk.beginDraw();
msk.clear();
msk.translate(originOffsetPt.x, originOffsetPt.y);
msk.beginShape();
for(int j=0; j<voronPositions.size(); j++){
msk.vertex(voronPositions.get(j).x, voronPositions.get(j).y);
}
msk.endShape(CLOSE);
msk.endDraw();
return msk;
}
}