We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › New programmer, working with Koch example
Page Index Toggle Pages: 1
New programmer, working with Koch example (Read 561 times)
New programmer, working with Koch example
Apr 30th, 2009, 4:03pm
 
Alright, so I'm a (semi)new programmer, but I've realized my initial goal of a custom cellular autonoma was a tad grand, so I'm starting small and working up.

I've always loved fractals, and I'd like to be able to write code to draw custom fractal curves. I've begun trying to alter the Koch Curve example, but I've hit a wall.

I've found where (i think) the angle is set, but when I reset it from 60 to 45, it doesn't change that much. To test it I set it to 89 (near-right angle, but still a triangle) and it was still at a semi-sharp inward angle. I'd like to be able to have all angle-based calculation done by a variable, because I'd like to set the angle dependent on the position of the mouse.

Ok, so here's what I've done to the code so far, if anybody can tell me how to directly control the angle, that'd be exactly what I'm looking for.

I've added room for it to breathe on all sides following some sketches and counting on graph paper to get the points that it ever approaches, as well as sped up the refresh rate and disabled redrawing the background, for debugging purposes.


KochFractal k;

void setup() {
 size(1024, 512);
 background(0);
 frameRate(24);  // Animate slowly
 k = new KochFractal();
 smooth();
}

void draw() {
 //background(0);
 // Draws the snowflake!
 k.render();
 // Iterate
 k.nextLevel();
 // Let's not do it more than 5 times. . .
 if (k.getCount() > 15) {
   k.restart();
 }

}


// 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;
 
 public KochFractal()
 {
   start = new Point(width/4, height*2/5);
   end = new Point(width*3/4, height*2/5);
   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();
   }
 }
//I CHANGED IT SO IT CALCULATED FROM THE ENDS, NOW WHAT?
 // 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));
*/
     now.add(new KochLine(a,c));
     now.add(new KochLine(c,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 + .5f * (b.x - a.x) + (sin(radians(360))*(b.y-a.y)) / 2;
   float y = a.y + .5f * (b.y - a.y) - (sin(radians(300))*(b.x-a.x)) / 2;
   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);
 }
}


(the fractal I'm attempting to draw right now is the Levy C Curve, which can be found by google it's name (I can't post links... too new)
Re: New programmer, working with Koch example
Reply #1 - May 1st, 2009, 3:07pm
 
Quote:
 // More complicated, have to use a little trig to figure out where this point is!
 Point kochmiddle()
 {
   float x = a.x + .5f * (b.x - a.x) + (sin(radians(360))*(b.y-a.y)) / 2;
   float y = a.y + .5f * (b.y - a.y) - (sin(radians(300))*(b.x-a.x)) / 2;
   return new Point(x,y);
 }    


you have 360 for x and 300 for y. define an integer for angle and use that instead - saves you having to remember to change the same value in two places.

float sine = sin(radians(45));
float x = a.x + .5f * (b.x - a.x) + (sine * (b.y - a.y)) / 2;
float y = a.y + .5f * (b.y - a.y) - (sine * (b.x - a.x)) / 2;

although what the angle (45 here) has to do with the angle on screen i can't really tell. i think your trig needs a little work (the .5 looks suspect, like it should also be a function of the angle)

this has the code for the 45% case

http://www.utdallas.edu/~rcb012200/cgi-bin/codeview.pl?fileName=LevyCCurve.c
Re: New programmer, working with Koch example
Reply #2 - May 2nd, 2009, 9:58am
 
ok, a bit more. specifically about the angles.

...

the new point C is a rotation by theta degrees about a point M which is halfway between A and B. the two new lines are AC and CB.

mx = (ax + bx) / 2;
my = (ay + by) / 2;

rotating around a point other than the origin requires you to translate the centre to the origin, do the rotation, and translate back

Code:

float angle = 90;
// midpoint
mx = (ax + bx) / 2;
my = (ay + by) / 2;

// rotate A around M by 'angle' degrees

// first translate by -M
float tx = ax - mx;
float ty = ay - my;

// standard 2d rotate
float theta = radians(angle);
float rx = cos(theta) * tx - sin(theta) * ty;
float ry = sin(theta) * tx + cos(theta) * ty;

// translate by M
cx = rx + mx;
cy = ry + my;


NB the angle in the above is the angle at the middle, not at A. (a 90 degree angle corresponds to the link i posted above and cos(90) = 0 and sin(90) = 1 which simplifies things dramatically)
Re: New programmer, working with Koch example
Reply #3 - May 4th, 2009, 6:53pm
 
I'm not seeing how to implement your code within the full program. Sorry if I'm a bit slow at this.
Re: New programmer, working with Koch example
Reply #4 - May 5th, 2009, 3:13am
 
that's a replacement for the code in kochmiddle (although it's not Koch anymore, it's Levy C).
Page Index Toggle Pages: 1