Chaos Game: Sierpinski n-Ecke



Weshalb es funktioniert
Wie kann aus einer zufälligen Verteilung der Punkte das Sierpinski-Dreieck entstehen? Hexerei? Schauen Sie sich folgendes Bild an:

Einige 100000 Punkte (in schwarz) wurden, dem Alogrithmus entspechend, bereits eingetragen. Nun verfolgen wir einen Startpunkt im großen Innendreieck auf seinem weiteren (zufälligen) Weg. Es fällt auf, dass alle sechs nachfolgenden Punkte in einem weißen immer kleiner werdenden Dreieck landen. Beim sechsten Iterationsschritt kann man das Dreieck gerade noch erkennen. Ginge man einige Schritte weiter, so wäre das getroffene Dreick nicht mehr sichtbar. Der Punkt würde auf einem schwarzen Punkt des Sierpinski-Dreiecks landen und diesen entsprechend einfärben. Das bedeutet zweierlei: Erstens sollte man die ersten 10 Elemente nicht einzeichnen und zweitens werden danach Punkte nur noch auf dem schwarzen Bereich landen. Zumindest sieht es in dieser Auflösung so aus. Könnte man unendlich tief in das Dreieck zoomen, so blieben nur unendlich viele Eckpunkte aller Dreiecke übrig, - Punkte ohne Ausdehnung. Von daher besitzt das Sierpinski Dreieck die Fläche 0. Seine fraktale Dimension beträgt 1,585.
Kissing-Ratio
Funktioniert das Chaos Game auch mit mehr als 3 Ecken? Schauen wir uns den Fall für fünf Ecken an. Die Eckpunkte eines regelmäßigen Fünfecks lassen sich ganz einfach erzeugen, wenn man Polarkoordinaten verwendet. Der erste Punkt wird auf die x-Achse gesetzt. Sein Abstand zum Ursprung sei R. Im folgenden bleibt der Radius unverändert. Man muss nun lediglich 360 Grad durch 5 teilen, um den Winkel zum nächsten Punkt zu erhalten. So erhält man letztendlich alle Eckpunkte. (n ...Anzahl der Eckpunkte, w = 2· π/n)
for(int i=0; i<n;i++){
    Punkte[i] = new PVector();
    Punkte[i].x = R*cos(i*w);
    Punkte[i].y = R*sin(i*w);
}

Verwenden wir zunächst wie beim Dreieck den Faktor 0.5. Dann bekommen wir folgendes Bild:

Enttäuschend, oder? Die Teile überlagern sich. Und damit ist dies kein Sierpinski Fünf-Eck! Was bei drei Ecken funktioniert hat, klappt mit fünf Ecken nicht mehr. Die Frage ist offensichtlich: Welchen Faktor muss man bei n Ecken wählen, damit die einzelnen Teile sich gerade berühren? Diesen von n abhängigen Faktor nennt man Kissing Ratio (kR). Für n = 5 findet man, dass kR etwa 0.62 sein muss. Für n = 6 erhält man als Kissing Ratio, ebenfalls durch probieren, etwa 0.67. Wählt man diese kR-Werte, dann sehen die beiden Sierpinski n-Ecke so aus:


Um sich das mühevolle Herantasten an kR zu ersparen, benötigt man eine Formel, die den Wert in Abhängigkeit von n angibt.
Mit Hilfe der folgenden Skizze (Idee Tom Bates) kann man die gesuchte Formel herleiten. Zu sehen ist ein kleiner Ausschnitt eines regelmäßigen Neunecks (blaue Linien). Nun sollen die "Kind-Neunecke" innen so eingepasst werden, dass eine bzw. zwei Seite der kleinen Neunecke auf einer Seite des großen Neunecks liegen. Wenn wir kR bestimmen wollen, müssen sich die kleinen Neunecke zusätzlich berühren. Diese Berührung findet für n = 9 am dritten Eckpunkt des kleinen Neunecks statt (von der gemeinsamen Ecke 0 aus gezählt .
Für den Fall n = 9 gilt β = 2.5⋅2⋅α. Für allgemeines n ist der Faktor vor 2⋅α     ceil(n/4 - 0.5).
(Die Methode ceil() verwandelt ein float Attribut in integer. Und zwar so, dass die nächst höhere ganze Zahl gewählt wird. Beispiel: ceil(0.25) = 1)


Nun könnte man die "Kind-Neunecke" auch außerhalb des großen Neunecks anbringen.
Hier gilt (ohne Beweis):    kan = 1 + r   wobei   kan : Außen Kissing Ratio eines regelmäßigen n-Ecks.
Die Kissing Rations ki und ka lassen sich in einer Methode bestimmen:
void kissingRatioBestimmen(){
    println("Anzahl der Ecken: "+n);
    Punkte = new PVector[n];
    w = 2*PI/n;
    a= w/2;
    b=2*a*(ceil((float)n/4.0)-0.5);
    c=b-PI/2;
    kI = 1 - sin(a)/(sin(a)+cos(c));
    kA = 1 + sin(a)/(sin(a)+cos(c));
    println("Kissing Ratio innen = "+kI);println();
    println("Kissing Ratio außen = "+kA);println();
    FI = 1-kI; FA = 1 - kA;
}
Für den Fall n = 5 liefert uns die Methode ki = 0.618034 und ka = 1.381966. Im Fall n = 6 sind es die Werte ki = 0.66666666 und ka = 1.3333333.
Die zusätzliche Verwendung von ka erweitert die fraktalen Sierpinski n-Ecke. Bleiben wir bei n = 5 und n = 6. Dann bekommt man mit der Erweiterung ka diese Bilder:

History
Schauen wir uns noch einmal das Sierpinski Dreieck an (Bild unten links). Die Selbstähnlichkeit steht außer Zweifel. Die Farbe allerdings macht nicht mit. Die Farbe kam dadurch zustande, dass man jedem Eckpunkt eine Farbe zugeordnet hatte und dann jedem eingezeichneten Punkt die Farbe der Ecke gab, die als letzte für die Iteration verwendet wurde. Zoomt man beispielsweise in das blaue "Kind-Dreick", so bleibt die Farbe immer genau gleich. Um das zu ändern, verwenden wir die Information, welche Ecke bei der vorherigen Iteration benutzt wurde. Die Dreiecks-Punkte, auf die der schmale weiße Pfeil zeigt, müssen ein Schritt zuvor im lila Dreieck, auf die der breite weiße Pfeil zeigt, gewesen sein. Wir geben daher dem "Enkel-Dreieck" diese Farbe (Bild unten Mitte), dann ist zumindest in dieser Zoomstufe die Selbstähnlichkeit auch in der Farbe korrekt. Dazu muss man nur alle in der Iteration vorkommenden Ecken zum Beispiel in int[] history speichern. Die "history-Tiefe" beträgt in diesem Fall t = 1. Geht man noch einen Schritt weiter und verwendet man t = 2, dann bekommt man das Dreieck im Bild unten rechts. Eine history-Tiefe von mehr als t = 5 macht keinen Sinn, da von den "Ururenkel-Dreiecke" nur noch Punkte zu sehen sind.


So kann man die Idee in Processing realisieren:
int N = 1000000;//Anzahl der Punkte
int t = 1; //history-Tiefe
int[] history;
history = new int[N+t];
...................................
for (int i = 0; i < N; i++) {
    float z = random(1);
    float d = 1.0/(float)n;
    getroffen = false;
    for(int j=0; j<n;j++){
        if(z>j*d && z<(j+1)*d){
            affAb(x,y,PM[j][0],PM[j][1],PM[j][2],PM[j][3],PM[j][4],PM[j][5]);
            getroffen = true;
            history[i+t] = j;
        }
        if(getroffen)break;
    }
    if (i > 10) {
        xK = map(x,xU,xO,0,width);
        yK = map(y,yU,yO,height,0);
        point(xK , yK );
    }
}
Am besten, Sie testen all diese Möglichkeiten selbst in folgendem Sketch:



Tasten- oder Mausaktion Wirkung
Taste n Anzahl der Punkte verdoppeln
Taste + Anzahl der Ecken um 1 erhöhen
Taste - Anzahl der Ecken um 1 verringern
Taste h ki und ka um 0.05 erhöhen
Taste t ki und ka um 0.05 verringern
Taste a Farben verändern
Taste 0 History-Tiefe 0
Taste 1 History-Tiefe 1
Taste 2 History-Tiefe 2
Taste 3 History-Tiefe 3
Taste w Hintergrund weiß/schwarz
Taste k Außenelemente zeichnen
Maus-Klick ins Fenster Zoomen an dieser Stelle

Solange die Tasten "h" und "t" nicht gedrückt wurden, werden immer die Kissing Ratio ki und ka verwendet.





Sketch ChaosGameSierpinskiNEcke

Menu