Created
August 15, 2017 14:19
-
-
Save jeffThompson/e3d99bbe1be5030389ecf374e48c392e to your computer and use it in GitHub Desktop.
Generates a random path between two predefined points.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
RANDOM PATH | |
Jeff Thompson | 2017 | jeffreythompson.org | |
Generates a random path between two predefined points. | |
*/ | |
import java.util.Date; // imports for timestamp | |
import java.text.SimpleDateFormat; | |
float lineLen = 20; // length of segments | |
float maxAngle = radians(90); // range of random angle towards end | |
float noiseInc = 0.01; // increment in Perlin noise | |
float minDistToEnd = 50; // how close to the end before we quit? | |
float noiseOffset = 0; // current position in Perlin noise | |
PVector end; // target point | |
void setup() { | |
size(1000, 1000); | |
background(30); | |
// create end point at center of screen | |
end = new PVector(width/2, height/2); | |
// create random paths to the center! | |
for (int i=0; i<20; i++) { | |
randomPath(); | |
} | |
// draw the end point | |
fill(0,150,255); | |
noStroke(); | |
ellipse(end.x, end.y, 10,10); | |
} | |
void draw() { | |
// nothing here! | |
} | |
// 's' to save the frame, any other key re-draws new random paths | |
void keyPressed() { | |
if (key == 's') { | |
String filename = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss'.jpg'").format(new Date()); | |
save("output/" + filename); | |
} | |
else { | |
setup(); | |
} | |
} | |
void randomPath() { | |
// create random starting point | |
PVector start = new PVector(random(50, width-50), random(50, height-50)); | |
PVector current = start.copy(); | |
// start line | |
stroke(255, 150); | |
noFill(); | |
beginShape(); | |
vertex(current.x, current.y); | |
// run until we hit the endpoint! | |
int i=0; | |
while (true) { | |
// compute angle b/w current position and the end point | |
float xDist = end.x - current.x; | |
float yDist = end.y - current.y; | |
float between = atan2(yDist, xDist); | |
// use Perlin noise to compute a random value (0-1), change | |
// to range of the maxAngle (this makes the line vary instead of | |
// heading straight towards the endpoint!) | |
float newAngle = between + (noise(noiseOffset) * maxAngle - maxAngle/2); | |
// calculate new x/y position based on the angle, draw a line | |
float x = current.x + cos(newAngle) * lineLen; | |
float y = current.y + sin(newAngle) * lineLen; | |
vertex(x, y); | |
// update current position to the end of the line, figure | |
// out how far we have left to go | |
current = new PVector(x, y); | |
float distLeft = PVector.dist(current, end); | |
// if we're near the endpoint, draw a line to the end and quit | |
if (distLeft <= minDistToEnd) { | |
line(current.x, current.y, end.x, end.y); | |
break; | |
} | |
// update count and Perlin noise variables, continue | |
i += 1; | |
noiseOffset += noiseInc; | |
} | |
// finish the shape! | |
endShape(); | |
// draw the starting point on top | |
fill(255,150,0); | |
noStroke(); | |
ellipse(start.x, start.y, 10,10); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've been searching for an implementation of this for a concept I'm working on. Just discovered yours and love the simplicity. Thank you.