1 Line replacement approach Koch Star (Snowflake) Area replacement approach Sierpenski Triangle Iterated Function System approach Heighway Dragon CSE 20232 CSE 20232 Lecture 34 – Procedural Lecture 34 – Procedural Fractals Fractals
Mar 31, 2015
1
Line replacement approach Koch Star (Snowflake)
Area replacement approach Sierpenski Triangle
Iterated Function System approach Heighway Dragon
CSE 20232CSE 20232Lecture 34 – Procedural FractalsLecture 34 – Procedural Fractals
2
Line replacement
Fractal shapes are based on lines or curves that are replaced by sequences of similar lines or curves at each level of recursion
Shapes are “self-similar” Same/similar shapes at every level
Examples Koch Star (Snowflake) Sierpenski Dragon Heighway Dragon
3
Area Replacement
Fractal shapes are based on simple shapes that are replaced or “cut out” with collections of the same or similar shapes
Again, these are self-similar at all levels of detail
Examples Box Fractal (our Square) Sierpenski Triangle (our Gasket) Sierpenski Carpet
4
Iterated Function System
A method of generating a fractal by repeated application of a set of functions
Each application typically moves one point on the fractal to another
Examples Mandelbrot & Julia Sets (escape time measure) Heighway Dragon (two functions selected at
random) Fern (4 functions randomly chosen with set
frequencies)
5
Koch Star
Based on 3 Koch Curves (triangle shape) Start each curve with a line segment Subdivide segment into thirds Replace middle third with two sides of an equilateral
triangle that would have had the replaced edge segment as its third side
These “bump-outs” always go on the same side of the original line
Original segment after first replacement
6
Koch Star
Initial shape (3 edges forming an equilateral triangle)
Snowflake shown at detail levels 1, 2, 3, 4
Images from wikipedia.com
7
Koch Star
// need to pass WinStuff &X or use it globallyvoid KochStar::draw(void){ if (Xwin->isOpen()) { // call function to draw (after subdividing as necessary) // each of the three triangle edges
subdivide_edge_and_draw(pt[0],pt[1],depth); subdivide_edge_and_draw(pt[1],pt[2],depth); subdivide_edge_and_draw(pt[2],pt[0],depth);
}}
// NOTE: the corner points are in the vector<Point> pt;// and each has an x and y coordinate. KochStar is a class// that inherits from Shape and the outline of any shape is// a polygon of edges between point pairs in the sequence// pt[0] to pt[1], pt[1] to pt[2], ..., pt[n-1] to pt[0]
8
Koch Star edge manipulationvoid KochStar::subdivide_edge_and_draw( const Point& a, const Point& b, int rec_depth){ if (rec_depth > 1) { // Point ab1 is 1/3 distance from a to b Point ab1( (2.0*a.getx()+b.getx()) / 3.0, (2.0*a.gety()+b.gety()) / 3.0);
// Point ab2 is 2/3 distance from a to b Point ab2( (a.getx()+2.0*b.getx()) / 3.0, (a.gety()+2.0*b.gety()) / 3.0);
// calculate length of current edge (a,b) double dx = b.getx() - a.getx(); double dy = b.gety() - a.gety(); double L = sqrt(dx*dx + dy*dy);
9
Koch Star edge manipulation // calculate the direction of the current edge (a,b) double theta = atan2(dy,dx);
// increase angle by 60 degrees theta += PI/3.0; if (theta < 0.0) theta = 2.0*PI + theta;
// calculate coordinates of point bumped out from triangle // it starts at point ab1 and runs at angle theta for 1/3 the // original edge length double outx = ab1.getx() + L*cos(theta)/3.0; double outy = ab1.gety() + L*sin(theta)/3.0;
10
Koch Star edge manipulation // create a Point with these coordiantes Point bump(outx,outy);
// make recursive calls to further subdivide edges and draw // note: rec_depth is decreased by 1 in each call subdivide_edge_and_draw(a,ab1,rec_depth-1); // edge (a,ab1) subdivide_edge_and_draw(ab1,bump,rec_depth-1); // edge (ab1,bump) subdivide_edge_and_draw(bump,ab2,rec_depth-1); // edge (bump,ab2) subdivide_edge_and_draw(ab2,b,rec_depth-1); // edge (ab2,b) } else // now draw the small edge piece from a to b Xwin->X_draw_edge(a.getx(),a.gety(),b.getx(),b.gety(),colorX);}
11
Sierpenski Dragon
Based on 4 curves (square shape) Start each curve with a line segment Subdivide segment into fourths Replace middle two segments with three sides of a square
that would have had the replaced edge segment as its fourth side
These “bump-outs” always go out and then in
Original segment after first replacement
12
Sierpenski Dragon
Initial shape (4 edges forming a square)
Dragon shown at detail levels 1, 2, 3
13
Square Gasket Based on a square shape
Start with a single square Replace the square with 5, each having a side length 1/3rd that of
the original Replacement squares go in each corner and the center
Original after 1st replacement after 2nd
14
Square Gasketvoid Square::draw(){ if (Xwin->isOpen()) { // if this is a depth 1 Square then actually draw it if (depth == 1) // Xlib code to draw 4 edges bounding the square for (int i=0; i<4; i++) Xwin->X_draw_edge(pt[i].getx(),pt[i].gety(),
pt[(i+1)%4].getx(),pt[(i+1)%4].gety(), colorX); else // Otherwise, subdivide & draw smaller Squares subdivide_and_draw(); } }
15
Square subdivisionvoid Square::subdivide_and_draw(void){ double mult=1.0; // 0.5 or other value for interesting shapes if (depth > 1) { // new squares have sides 1/3 length of original double newSide = fabs(pt[0].getx()-pt[2].getx())/3.0;
// Center is halfway between opposite corners pt[0] & pt[2] double cx = 0.5*(pt[0].getx()+pt[2].getx()); double cy = 0.5*(pt[0].gety()+pt[2].gety());
// 5 new squares 1/3 side size as originals Square s1(Xwin,Point(cx,cy),newSide); Square s2(Xwin,Point(cx+mult*newSide,cy+mult*newSide),newSide); Square s3(Xwin,Point(cx+mult*newSide,cy-mult*newSide),newSide); Square s4(Xwin,Point(cx-mult*newSide,cy+mult*newSide),newSide); Square s5(Xwin,Point(cx-mult*newSide,cy-mult*newSide),newSide);
16
Square subdivision // set color of 5 new Squares same as this one int r, g, b; getColor(r,g,b); s1.setColor(r,g,b); s2.setColor(r,g,b); s3.setColor(r,g,b); s4.setColor(r,g,b); s5.setColor(r,g,b);
// set depth to 1 less than this Square s1.setDepth(depth-1); s2.setDepth(depth-1); s3.setDepth(depth-1); s4.setDepth(depth-1); s5.setDepth(depth-1);
// draw the 5 smaller Squares s1.draw(); s2.draw(); s3.draw(); s4.draw(); s5.draw(); }}
17
Sierpenski Gasket Based on a triangle shape
Start with a single triangle Replace the triangle with 3, each having a side length 1/2 that of
the original Replacement triangles go in each corner
Original after 1st replacement after 2nd
18
Heighway Dragon Producible in several ways Folding
Fold strip of paper in half, again and again, in same direction Unfold so each fold is 90 degrees and look at shape edge-on
Line replacement Start with a line (length L) Replace with two segments L/sqrt(2) forming an isosceles
triangle with original The replace each of these in turn, the same way, but alternate
direction of bump, left, right, left, …
Levels of detail 1,2,3,4 from wikipedia.com
19
Heighway Dragon Producible in several ways Iterative Function System
Start with Z as the origin of the complex plane
Randomly alternate between these two functions to derive next point Z from previous Z = ((1+j)*Z)/2 Z = 1 –((1-j)*Z)/2
The UNION of all such points is the Dragon
Example: 100,000 iterations
20
Heighway Dragon IFS (main) // as in Mandelbrot set program, image size is ROWS x COLUMNS, // complex plane is LEFT..RIGHT, TOP..BOTTOM for (r=0;r<ROWS;r++) for (c=0;c<COLUMNS;c++) image[r][c] = 0; // set all pixels to black
Z.setReal(0.0); Z.setImaginary(0.0); for (int i=0; i<count; i++) { nextPoint(Z); // finds next Z in IFS defining dragon r = (int)((TOP-Z.getImaginary())/dy); // find image row c = (int)((Z.getReal()- LEFT)/dx); // find image column if (0 <= r && r < ROWS && 0 <= c && c < COLUMNS) image[r][c] = 32 + i%224; // set pixel color else cout << "bad r,c" << r << ' ' << c << endl; }
21
Heighway Dragon IFS (calc)// the Heighway Dragon is defined by applying each of the// following functions to the previous value of Z in order // to find the next value of Z. The choice of which to // apply is random.
void nextPoint(Complex& Z){ if (rand()%2) Z = 0.5*Complex(1.0,1.0)*Z; else Z = 1.0 - 0.5*Complex(1.0,-1.0)*Z;}
22
Our Fractal Shape Inheritance Hierarchy (for last homework) Point
Simple location in 2D plane Shape
Polygon with edges between sequence of Point pairs KochStar : Shape
Triangle based, edge division and replacement Square : Shape
Square based, area division and replacement SerpGasket* : Shape
Triangle based, area subdivision and replacement SerpDragon* : Shape
Square based, edge division and replacement
* you will complete these based on given examples