fixing up ArrayLists for generics, also Kock curve updates

This commit is contained in:
Daniel Shiffman
2013-03-06 22:33:56 -05:00
parent c41905d3f1
commit 2b33333182
5 changed files with 144 additions and 140 deletions
@@ -11,7 +11,6 @@ KochFractal k;
void setup() {
size(640, 360);
background(0);
frameRate(1); // Animate slowly
k = new KochFractal();
}
@@ -29,137 +28,3 @@ void draw() {
}
// A class to manage the list of line segments in the snowflake pattern
class KochFractal {
Point start; // A point for the start
Point end; // A point for the end
ArrayList lines; // A list to keep track of all the lines
int count;
KochFractal() {
start = new Point(0, height/2 + height/4);
end = new Point(width, height/2 + height/4);
lines = new ArrayList();
restart();
}
void nextLevel() {
// For every line that is in the arraylist
// create 4 more lines in a new arraylist
lines = iterate(lines);
count++;
}
void restart() {
count = 0; // Reset count
lines.clear(); // Empty the array list
lines.add(new KochLine(start,end)); // Add the initial line (from one end point to the other)
}
int getCount() {
return count;
}
// This is easy, just draw all the lines
void render() {
for(int i = 0; i < lines.size(); i++) {
KochLine l = (KochLine)lines.get(i);
l.render();
}
}
// This is where the **MAGIC** happens
// Step 1: Create an empty arraylist
// Step 2: For every line currently in the arraylist
// - calculate 4 line segments based on Koch algorithm
// - add all 4 line segments into the new arraylist
// Step 3: Return the new arraylist and it becomes the list of line segments for the structure
// As we do this over and over again, each line gets broken into 4 lines, which gets broken into 4 lines, and so on. . .
ArrayList iterate(ArrayList before) {
ArrayList now = new ArrayList(); //Create emtpy list
for (int i = 0; i < before.size(); i++) {
KochLine l = (KochLine)lines.get(i); // A line segment inside the list
// Calculate 5 koch points (done for us by the line object)
Point a = l.start();
Point b = l.kochleft();
Point c = l.kochmiddle();
Point d = l.kochright();
Point e = l.end();
// Make line segments between all the points and add them
now.add(new KochLine(a,b));
now.add(new KochLine(b,c));
now.add(new KochLine(c,d));
now.add(new KochLine(d,e));
}
return now;
}
}
// A class to describe one line segment in the fractal
// Includes methods to calculate midpoints along the line according to the Koch algorithm
class KochLine {
// Two points,
// a is the "left" point and
// b is the "right point
Point a, b;
KochLine(Point a_, Point b_) {
a = a_.copy();
b = b_.copy();
}
void render() {
stroke(255);
line(a.x, a.y, b.x, b.y);
}
Point start() {
return a.copy();
}
Point end() {
return b.copy();
}
// This is easy, just 1/3 of the way
Point kochleft() {
float x = a.x + (b.x - a.x) / 3f;
float y = a.y + (b.y - a.y) / 3f;
return new Point(x,y);
}
// More complicated, have to use a little trig to figure out where this point is!
Point kochmiddle() {
float x = a.x + 0.5f * (b.x - a.x) + (sin(radians(60))*(b.y-a.y)) / 3;
float y = a.y + 0.5f * (b.y - a.y) - (sin(radians(60))*(b.x-a.x)) / 3;
return new Point(x,y);
}
// Easy, just 2/3 of the way
Point kochright() {
float x = a.x + 2*(b.x - a.x) / 3f;
float y = a.y + 2*(b.y - a.y) / 3f;
return new Point(x,y);
}
}
class Point {
float x,y;
Point(float x_, float y_) {
x = x_;
y = y_;
}
Point copy() {
return new Point(x,y);
}
}
@@ -0,0 +1,67 @@
// Koch Curve
// A class to manage the list of line segments in the snowflake pattern
class KochFractal {
PVector start; // A PVector for the start
PVector end; // A PVector for the end
ArrayList<KochLine> lines; // A list to keep track of all the lines
int count;
public KochFractal() {
start = new PVector(0,height-20);
end = new PVector(width,height-20);
lines = new ArrayList<KochLine>();
restart();
}
void nextLevel() {
// For every line that is in the arraylist
// create 4 more lines in a new arraylist
lines = iterate(lines);
count++;
}
void restart() {
count = 0; // Reset count
lines.clear(); // Empty the array list
lines.add(new KochLine(start,end)); // Add the initial line (from one end PVector to the other)
}
int getCount() {
return count;
}
// This is easy, just draw all the lines
void render() {
for(KochLine l : lines) {
l.display();
}
}
// This is where the **MAGIC** happens
// Step 1: Create an empty arraylist
// Step 2: For every line currently in the arraylist
// - calculate 4 line segments based on Koch algorithm
// - add all 4 line segments into the new arraylist
// Step 3: Return the new arraylist and it becomes the list of line segments for the structure
// As we do this over and over again, each line gets broken into 4 lines, which gets broken into 4 lines, and so on. . .
ArrayList iterate(ArrayList<KochLine> before) {
ArrayList now = new ArrayList<KochLine>(); // Create emtpy list
for(KochLine l : before) {
// Calculate 5 koch PVectors (done for us by the line object)
PVector a = l.start();
PVector b = l.kochleft();
PVector c = l.kochmiddle();
PVector d = l.kochright();
PVector e = l.end();
// Make line segments between all the PVectors and add them
now.add(new KochLine(a,b));
now.add(new KochLine(b,c));
now.add(new KochLine(c,d));
now.add(new KochLine(d,e));
}
return now;
}
}
@@ -0,0 +1,74 @@
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
// Koch Curve
// A class to describe one line segment in the fractal
// Includes methods to calculate midPVectors along the line according to the Koch algorithm
class KochLine {
// Two PVectors,
// a is the "left" PVector and
// b is the "right PVector
PVector a;
PVector b;
KochLine(PVector start, PVector end) {
a = start.get();
b = end.get();
}
void display() {
stroke(255);
line(a.x, a.y, b.x, b.y);
}
PVector start() {
return a.get();
}
PVector end() {
return b.get();
}
// This is easy, just 1/3 of the way
PVector kochleft() {
PVector v = PVector.sub(b, a);
v.div(3);
v.add(a);
return v;
}
// More complicated, have to use a little trig to figure out where this PVector is!
PVector kochmiddle() {
PVector v = PVector.sub(b, a);
v.div(3);
PVector p = a.get();
p.add(v);
rotate(v,-radians(60));
p.add(v);
return p;
}
// Easy, just 2/3 of the way
PVector kochright() {
PVector v = PVector.sub(a, b);
v.div(3);
v.add(b);
return v;
}
}
public void rotate(PVector v, float theta) {
float xTemp = v.x;
// Might need to check for rounding errors like with angleBetween function?
v.x = v.x*cos(theta) - v.y*sin(theta);
v.y = xTemp*sin(theta) + v.y*cos(theta);
}
@@ -15,12 +15,11 @@ class ParticleSystem {
}
void run() {
Iterator<Particle> it = particles.iterator();
while (it.hasNext()) {
Particle p = it.next();
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = particles.get(i);
p.run();
if (p.isDead()) {
it.remove();
particles.remove(i);
}
}
}
@@ -12,7 +12,6 @@ ParticleSystem ps;
void setup() {
size(640,360);
smooth();
ps = new ParticleSystem(new PVector(width/2,50));
}