フラクタル
提供:kuhalaboWiki
(版間での差分)
(→再帰的な円) |
(→コッホ図形) |
||
| 81行: | 81行: | ||
[[ファイル:Koch.jpg]] | [[ファイル:Koch.jpg]] | ||
[[ファイル:Koch2.jpg]] | [[ファイル:Koch2.jpg]] | ||
| + | |||
| + | === 全体 === | ||
| + | <pre> | ||
| + | // Renders a simple fractal, the Koch snowflake | ||
| + | // Each recursive level drawn in sequence | ||
| + | |||
| + | KochFractal k; | ||
| + | |||
| + | void setup() { | ||
| + | size(800,250); | ||
| + | background(255); | ||
| + | frameRate(1); // Animate slowly | ||
| + | k = new KochFractal(); | ||
| + | } | ||
| + | |||
| + | void draw() { | ||
| + | background(255); | ||
| + | // Draws the snowflake! | ||
| + | k.render(); | ||
| + | // Iterate | ||
| + | k.nextLevel(); | ||
| + | // Let's not do it more than 5 times. . . | ||
| + | if (k.getCount() > 5) { | ||
| + | k.restart(); | ||
| + | } | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | === KochLineクラス=== | ||
| + | <pre> | ||
| + | // 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(0); | ||
| + | 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); | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | === KochFractalクラス === | ||
| + | <pre> | ||
| + | // 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; | ||
| + | } | ||
| + | |||
| + | } | ||
| + | </pre> | ||
2020年11月2日 (月) 05:35時点における版
目次 |
概要
古代ギリシャからあるユークリッド幾何学と20世紀のフラクタル幾何学の比較
- 考察
- 古代エジプト人は3:4:5の辺を持つ三角形で直角が得られることを知っていた.ピラミッドなどの巨大建造物.
- 三平方の定理を発見したピタゴラスはどこがすごいか?
- Nature of Code, Ch 8 Fractals
- https://github.com/nature-of-code/noc-examples-processing/tree/master/chp08_fractals
再帰的呼び出し
再帰的(recursive)呼び出しとは,サブルーチンや関数が,自分自身を呼び出すアルゴリズムをいう。 これを利用すると,複雑な手順を簡潔に記述することができる。
- 再帰的(Recursive)呼び出し
- "Recursive"という言葉を「頭山的」と訳した人がいる。
- 落語「自分の頭の上に穴があいて池ができた。その人が将来を悲観して,その池に身を投げた」
- 再帰的な定義の例: GNU: " GNU is Not Unix "
再帰は数学的帰納法であり,「局所的なルールで全体を記述する」ことである。 i)最初のコマを倒す。ii)n番目のコマが倒れると,n+1番目のコマも倒れる。iii)すべてのコマが倒れる。
- nの階乗を再帰と反復で計算する際の比較
- n! = n * (n-1) * (n-2) * ... * 3 * 2 * 1
- 1! = 1
// 再帰:n!=n*(n-1)! という漸化式で計算する。
int factorial(int n){
if (n == 1){
return 1;
}else{
return n * factorial(n-1); //再帰的呼び出し
}
}
// 反復:1からnまでを乗算する。
int factorial(int n){
int f = 1;
for (int i = 0; i < n; i++){
f = f * (i+1);
}
return f;
}
再帰的な円
void setup() {
size(640,360);
}
void draw() {
background(255);
drawCircle(width/2,height/2,400);
noLoop();
}
// Recursive function
void drawCircle(float x, float y, float r) {
stroke(0);
noFill();
ellipse(x, y, r, r);
if(r > 2) {
// Now we draw two more circles, one to the left
// and one to the right
drawCircle(x + r/2, y, r/2);
drawCircle(x - r/2, y, r/2);
}
}
コッホ図形
全体
// Renders a simple fractal, the Koch snowflake
// Each recursive level drawn in sequence
KochFractal k;
void setup() {
size(800,250);
background(255);
frameRate(1); // Animate slowly
k = new KochFractal();
}
void draw() {
background(255);
// Draws the snowflake!
k.render();
// Iterate
k.nextLevel();
// Let's not do it more than 5 times. . .
if (k.getCount() > 5) {
k.restart();
}
}
KochLineクラス
// 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(0);
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);
}
KochFractalクラス
// 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;
}
}

