Trypophobia
I have to walk through the radio station to get to campus every day, and there’s a small wooded area with lots of leaves on the ground (as there tends to be in the fall). I noticed that some of these leaves have weird holes in them–probably from small, hungry, bugs, but unsettling nonetheless. These creepy leaves reminded me of this phenomena coined trypophobia, where people find themselves intensely afraid of small, patterned holes such as those in lotus flowers or honeycomb. Small, patterned holes are also a regular natural occurrence, besides lotus flower and honeycomb they can be found in wood, plants, coral, sponges, and more. Clearly the art of generating small, patterned holes was worth investigation.
./wp-content/uploads/sites/2/2013/10/screen02.pdf
I ended up with two variants. The first of which has a lot more variation in size and shape, and completely fills the wooded area. I basically shot particles at a board and if they were too close to an edge or another particle they’d fall off. Not very simulation heavy!
import processing.pdf.*;
int inch = 60;
int margin = inch/2;
ArrayList blobs;
void setup() {
size(inch*12, inch*12, PDF, "screen05.pdf");
background(255);
noFill();
smooth();
float rad, x, y, maxr, minr;
float desiredseperation = 0;
boolean addBlob = true;
int points, attempts, maxblob;
blobs = new ArrayList();
minr = inch/8;
maxr = 1.5*inch;
maxblob = 300;
attempts = 0;
while ((blobs.size() != maxblob) && (attempts < 6000)) { rad = random(minr, maxr - map(blobs.size(), 0, maxblob, 0, maxr-minr+1)); points = int(random(5, 25 - map(blobs.size(), 0, maxblob, 0, 20))); //x = random(margin+rad, width-(margin+rad)); //y = random(margin+rad, height-(margin+rad)); x = (width/2) + random(0,inch*4)*cos(TWO_PI*random(0,2)); y = (height/2) + random(0,inch*4)*sin(TWO_PI*random(0,2)); addBlob = true; if (blobs.size() > 0) {
for (Blob other : blobs) {
desiredseperation = rad + other.r + (inch/8);
if (dist(x, y, other.cx, other.cy) < desiredseperation) {
addBlob = false;
attempts += 1;
}
}
if (addBlob) {
blobs.add(new Blob(rad, points, x, y));
attempts = 0;
}
}
if (blobs.size() == 0) {
blobs.add(new Blob(rad, points, x, y));
}
}
for (Blob b : blobs) {
b.display();
}
println(blobs.size());
}
void draw() {
// Exit the program
println("Finished.");
exit();
}
class Blob {
float r;
float cx, cy;
int points;
float px, py, pr, angle, offset;
Blob (float inr, int inpoints, float inx, float iny) {
r = inr; // random(inch/8, inch*2)
points = inpoints; // random(3, 12)
cx = inx;
cy = iny;
}
void display() {
beginShape();
offset = random(0,1);
for (int i = 0; i < points; i++) {
angle = TWO_PI*(i+offset)/points;
pr = random(.6, 1) * r;
px = cx + pr*cos(angle);
py = cy + pr*sin(angle);
curveVertex(px, py);
if ((i == 0) || (i == points-1)) {
curveVertex(px, py);
}
}
endShape(CLOSE);
}
}
./wp-content/uploads/sites/2/2013/10/frame-0214.pdf
The second one used Golan’s particle class to create a fleet of small holes that then drifted away from each other within a larger circle.
import processing.pdf.*;
boolean record;
int inch = 60;
ArrayList particles;
void setup() {
size(inch*12, inch*12);
background(255);
noFill();
smooth();
particles = new ArrayList();
for (int i = 0; i < 150; i++) { float rad = random(inch/8, inch/4); particles.add(new Particle(width/2 + random(-inch, inch), height/2 + random(-inch, inch), rad)); } } void draw() { if (record) { // Note that #### will be replaced with the frame number. Fancy! beginRecord(PDF, "frame-####.pdf"); } background(255); float gravityForceX = 0; float gravityForceY = 0.0; float mutualRepulsionAmount = inch/16; for (Particle p : particles) { for (Particle other : particles) { float desiredseperation = p.r + other.r + (inch/8); float dx = p.px - other.px; float dy = p.py - other.py; float dh = sqrt(dx*dx + dy*dy); if (dh > 1.0) {
float componentInX = dx/dh;
float componentInY = dy/dh;
float proportionToDistanceSquared = 1.0/(dh*dh);
float repulsionForcex = mutualRepulsionAmount * componentInX * proportionToDistanceSquared;
float repulsionForcey = mutualRepulsionAmount * componentInY * proportionToDistanceSquared;
p.addForce( repulsionForcex, repulsionForcey); // add in forces
other.addForce(-repulsionForcex, -repulsionForcey); // add in forces
}
/*if (dist(p.px, p.py, other.px, other.py) < desiredseperation) {
}*/
}
}
// update the particles
for (int i=0; i<particles.size(); i++) {
particles.get(i).bPeriodicBoundaries = false;
particles.get(i).update(); // update all locations
}
for (int i=0; i<particles.size(); i++) { particles.get(i).addForce(gravityForceX, gravityForceY); } for (Particle p : particles) { p.render(); } if (record) { endRecord(); record = false; } } // Use a keypress so thousands of files aren't created void mousePressed() { record = true; } class Particle { float r; float px; float py; float vx; float vy; float damping; float mass; boolean bLimitVelocities = true; boolean bPeriodicBoundaries = false; float margin = 2; float offset, qx, qy, qr, angle; // stuff float cx = width / 2; float cy = height / 2; float boundr = 300; // Constructor for the Particle Particle (float x, float y, float inr) { r = inr; px = x; py = y; vx = vy = 0; damping = 0.95; mass = 1.0; } // Add a force in. One step of Euler integration. void addForce (float fx, float fy) { float ax = fx / mass; float ay = fy / mass; vx += ax; vy += ay; } // Update the position. Another step of Euler integration. void update() { vx *= damping; vy *= damping; limitVelocities(); handleBoundaries(); px += vx; py += vy; } void limitVelocities() { if (bLimitVelocities) { float speed = sqrt(vx*vx + vy*vy); float maxSpeed = 6.0; if (speed > maxSpeed) {
vx *= maxSpeed/speed;
vy *= maxSpeed/speed;
}
}
}
void handleBoundaries() {
if (bPeriodicBoundaries) {
if (px > width ) px -= width;
if (px < 0 ) px += width; if (py > height) py -= height;
if (py < 0 ) py += height; } else { //super tenuous circular boundaries if (dist(cx, cy, px+vx, py+vy) > boundr - r) {
vx *= -1;
vy *= -1;
}
}
}
void render() {
float noiseVal = noise((mouseX)*80,
mouseY*80);
stroke(0);
beginShape();
offset = random(0,1);
for (int i = 0; i < 10; i++) {
angle = TWO_PI*(i+offset)/10;
qr = random(0.75, 1) * r;
qx = px + qr*cos(angle);
qy = py + qr*sin(angle);
curveVertex(qx, qy);
if ((i == 0) || (i == 10-1)) {
curveVertex(qx, qy);
}
}
endShape(CLOSE);
}
}