The idea of a black and white buffer is to use it to see if a new ellipse (or any other shape) can be drawn without flowing over the given area or touching other shapes. To put this in practice you start with a fully white buffer (nothing may be drawn). Then you draw a fully black shape from your svg (disable the actual colors, make it black). Now you have a buffer that allows some new shapes. Then you need a function that can give you an answer if a new shape can be drawn depending on the shape (in this case a circle of a certain radius) and the buffer. You need a buffer, because your buffer will start to fill with shapes incrementally leaving less and less space for shapes. So it's not only checking if a shape is inside the svg, but also considering already drawn shapes. Only in the uncommon occasion that you want your final output to look like the buffer, you wouldn't need to separate things. In most cases it is more convenient to keep these things (output, buffer, svg) separate, but feel free to choose the solution that fits your intentions best.
Press any key to cycle through the three different screens in this example:
- final output
- black and white buffer
- original svg.
Code Example
- String url = "http://openclipart.org/people/mightyman/win7_wifi.svg";
- PGraphics buffer, output;
- PShape svg;
- int diam = 20; // set the diameter of the circles
- int currentScreen;
-
- void setup() {
- size(500, 500);
- createBuffer();
- // stepSize of 1 gives the highest density
- // stepSize of diam gives 'perfect fit'
- // stepsize > diam gives space between circles
- createOutput(diam+1);
- fill(0);
- }
-
- void draw() {
- background(255);
- switch(currentScreen) {
- case 0: image(output, 0, 0); text("output", 10, 20); break;
- case 1: image(buffer, 0, 0); text("buffer", 10, 20); break;
- case 2: shape(svg, 100, 100, width-200, height-200); text("svg", 10, 20); break;
- }
- }
-
- void keyPressed() {
- currentScreen = (currentScreen+1)%3;
- }
-
- void createBuffer() {
- svg = loadShape(url);
- svg.disableStyle();
- buffer = createGraphics(width, height, JAVA2D);
- buffer.beginDraw();
- buffer.background(255);
- buffer.fill(0);
- buffer.stroke(0);
- buffer.shape(svg, 100, 100, width-200, height-200);
- buffer.noStroke();
- buffer.fill(255);
- buffer.smooth();
- buffer.endDraw();
- svg.enableStyle();
- }
-
- void createOutput(int stepSize) {
- output = createGraphics(width, height, JAVA2D);
- output.beginDraw();
- output.background(255);
- output.smooth();
- output.noStroke();
- for (int y=0; y<output.height; y+=stepSize) {
- for (int x=0; x<output.width; x+=stepSize) {
- if (ellipsePossible(x, y, diam/2)) {
- output.fill(random(200), random(200), random(200));
- output.ellipse(x, y, diam, diam);
- buffer.beginDraw();
- buffer.ellipse(x, y, diam, diam);
- buffer.endDraw();
- }
- }
- }
- output.endDraw();
- }
-
- boolean ellipsePossible(int x, int y, int radius) {
- if (x-radius < 0 || x+radius > buffer.width || y-radius < 0 || y+radius > buffer.width) {
- return false;
- } else {
- for (int i=x-radius; i<x+radius; i++) {
- for (int j=y-radius; j<y+radius; j++) {
- if (dist(i, j, x, y) <= radius) {
- int index = i + j*buffer.width;
- if (buffer.pixels[index] == -1) {
- return false;
- }
- }
- }
- }
- return true;
- }
- }