Übersicht

Dichotomes Verzweigungsmuster

Demodatei: Demo5.pov

Während das Verzweigungsmuster aus dem vorherigen Kapitel mehr oder weniger zufällig definiert wurde, wollen wir nun ein streng dichotomes Verzweigungsmuster bilden. (Dieses Muster wird allerdings mit einer gewissen Restvariabilität versehen werden.)

Dichotomes Verzweigungsmuster

Ein derartiges Muster wird in drei Schritten erzeugt: Im ersten Schritt werden alle Positionen des Musters definiert. Der entsprechende Makro, der nun zunächst erläutert wird, baut auf der Tatsache auf, dass sich bei einem dichotomen Verzweigungsmuster die Anzahl der Positionen in jeder Ebene verdoppelt.

#macro DichotomousBranching (StartPosition, Levels, StartDistance, Anglexy0, Anglez0, Variance)
//Dieser Makro definiert die Positionen für ein dichotomes Verzweigungsmuster entlang der x-Achse und
//speichert diese Positionen im Array Positions.
//Parameter des Makros sind die Startposition, die Anzahl der verschiedenen Stufen, der Anfangsabstand zwischen zwei Stufen,
//die Winkel zwischen den Ästen der ersten Ebenen und ein Zufallsfaktor.
//Anglexy entspricht einer Drehung um die z-Achse, Anglez einer Drehung um die y-Achse.

//Intialisieren der Arrays zum Speichern von Positionen und Winkeln.

#declare Positions = array [Levels + 1][pow(2, Levels + 1) + 1];
#local AAnglexy = array [Levels + 1][pow(2, Levels + 1) + 1];
#local AAnglez = array [Levels + 1][pow(2, Levels + 1) + 1];

//Definition der Positionen

//Definition der Startposition.
#local ticker2 = 0;
#local ticker = 0;
#local P1 = StartPosition;
#declare Positions [ticker2][ticker] = P1;
#local AAnglexy [ticker2][ticker] = 0;
#local AAnglez [ticker2][ticker] = 0;

//Definition der weiteren Ebenen.
//Die zwei folgenden verschränkten Schleifen durchlaufen einerseits die verschiedenen Ebenen (ticker2)
//und andererseits die verschiedenen Positionen auf diesen Ebenen (ticker1).

#local ticker2 = 1;
#while (ticker2 <Levels)
#local Elements = pow (2, ticker2);//Die Anzahl der Positionen verdoppelt sich mit jeder Ebene.
#local Distance = 0.4 + StartDistance * sin (pi/2 + ticker2 * pi/18);//Die Abstände werden mit jeder Ebene verkürzt.
#local Anglexy = Anglexy0 - 10 * sin (ticker2 * pi/18);//Anglexy wir mit jeder Ebene verkleinert.
#local Anglez = Anglez0 - 10 * sin (ticker2 * pi/18);//Anglez wir mit jeder Ebene verkleinert.
#local ticker = 0;
#while ( ticker <Elements)
#local var1 = rand(chance1);
#local var2 = rand(chance2);
#local var3 = rand(chance3);

//Die Positionen und Winkel der vorhergehende Ebene werden aus den entsprechenden Arrays abgelesen.
#local P0 = Positions [ticker2-1][int(ticker/2)];
#local Angle0xy = AAnglexy [ticker2-1][int(ticker/2)];
#local Angle0z = AAnglez [ticker2-1][int(ticker/2)];

//Definition der Positionen und Winkel der aktuellen Ebene. Die if-Schleifen ergeben ein dichotomes alternierendes Verzweigungsmuster.
#if (mod(ticker2, 2) >0)
#if (mod(ticker, 2) >0)
#local P1=<P0.x + ((cos(radians(Angle0xy + Anglexy)) * Distance) * (cos(radians(Angle0z)))) + Variance * (0.5 - rand(chance1))/10, P0.y + (sin(radians(Angle0xy + Anglexy)) * Distance) + Variance * (0.5 - rand(chance2)), P0.z + (sin(radians(Angle0z)) * Distance * (cos(radians(Angle0xy + Anglexy)))) + Variance * (0.5 - rand(chance3))>;
#local AAnglexy [ticker2][ticker] = (Angle0xy + Anglexy);
#local AAnglez [ticker2][ticker] = (Angle0z);
#else
#local P1=<P0.x + ((cos(radians(Angle0xy - Anglexy)) * Distance) * (cos(radians(Angle0z)))) + Variance * (0.5 - rand(chance1))/10, P0.y + (sin(radians(Angle0xy - Anglexy)) * Distance) + Variance * (0.5 - rand(chance2)), P0.z + (sin(radians(Angle0z)) * Distance * (cos(radians(Angle0xy + Anglexy)))) + Variance * (0.5 - rand(chance3))>;
#local AAnglexy [ticker2][ticker] = (Angle0xy - Anglexy);
#local AAnglez [ticker2][ticker] = (Angle0z);
#end
#else
#if (mod(ticker, 2) >0)
#local P1=<P0.x + ((cos(radians(Angle0z + Anglez)) * Distance) * (cos(radians(Angle0xy)))) + Variance * (0.5 - rand(chance1))/10, P0.y + (sin(radians(Angle0xy)) * Distance) + Variance * (0.5 - rand(chance2)), P0.z + (sin(radians(Angle0z + Anglez)) * Distance * (cos(radians(Angle0xy)))) + Variance * (0.5 - rand(chance3))>;
#local AAnglexy [ticker2][ticker] = (Angle0xy);
#local AAnglez [ticker2][ticker] = (Angle0z + Anglez);
#else
#local P1=<P0.x + ((cos(radians(Angle0z - Anglez)) * Distance) * (cos(radians(Angle0xy)))) + Variance * (0.5 - rand(chance1))/10, P0.y + (sin(radians(Angle0xy)) * Distance) + Variance * (0.5 - rand(chance2)), P0.z + (sin(radians(Angle0z - Anglez)) * Distance * (cos(radians(Angle0xy)))) + Variance * (0.5 - rand(chance3))>;
#local AAnglexy [ticker2][ticker] = (Angle0xy);
#local AAnglez [ticker2][ticker] = (Angle0z - Anglez);
#end
#end

//Speichern der Position im entsprechenden Array.
#declare Positions [ticker2][ticker] = P1;
#local ticker = ticker + 1;
#end
#local ticker2 = ticker2 + 1;
#end
#end

Im zweiten Schritt werden die Positionen für einzelne Sphere_Sweeps aus den oben definierten Positionen ausgewählt und in einem neuen Array abgespeichert. Der entsprechende Makro wird nachstehend erläutert. Die Auswahl der einzelnen Positionen wird an der höchsten Ebene begonnen. Mit einer entsprechenden Schleife wird diese Operation für jede einzelne der Postionen in dieser Ebene wiederholt.

#macro SearchDichotomousBranch (Levels, InputArray, Branch)
//Dieser Makro definiert einzelne Äste in dem oben definierten dichotomen Verzweigungsmuster.
//Parameter für den Makro sind die Anzahl der verschiedenen Ebenen, der Name des
//Inputarrays und die Anzahl der spezifischen Endpunkte in der letzten Ebene.
//Der Outputarray dieses Makros hat den Namen SweepPositions.

//Zunächst wird ein Punkt aus der höchsten Ebene aus dem Inputarray abgelesen.

#local PEnd = Positions [Levels-1][Branch];

//Initialisierung des Outputarrays.
#declare SweepPositions = array [Levels + 1];

//Definition der äußeren Positionen des Sphere_Sweeps.

#declare SweepPositions[Levels] = PEnd;
#declare SweepPositions[1] = Positions [0][0];
#declare SweepPositions[0] = SweepPositions[1] - ((PEnd - SweepPositions[1])/Levels);

//Definition der inneren Positionen des Sphere_Sweeps.
#local Number = Branch;
#local ticker4 = 1;
#while (ticker4 <Levels-1)
#local Level = Levels-ticker4;
#local PNext = Positions [Level-1][int(Number/2)];
#local Number = int(Number/2);
#declare SweepPositions[Level] = PNext;
#local ticker4 = ticker4 + 1;
#end
#end

Hier kommen nun die Zeilen, die die oben definierten Makros aufrufen und die die dabei definierten Arrays benutzen, um die entsprechenden Sphere_Sweeps (und Kugeln zum Markieren der Positionen) tatsächlich darzustellen.

//Initialisierung von pseudo-random Streams.
#local chance1 = seed (13);
#local chance2 = seed (15);
#local chance3 = seed (23);

//Definition der Anzahl der Verzweigungsebenen.
#declare Levels = 10;

//Makro zur Definition der Positionen des Verzweigungsmusters.
DichotomousBranching (<0, 0, 0>, Levels, 1.5, 20, 20, 0.2, )

//Die folgende Schleife erzeugt für jede Position der äußersten Ebenen einen Sphere_Sweep.
#declare ticker3 = 0;
#while (ticker3 <pow (2, (Levels-1)))
//Dieser Makro sucht einen Pfad durch das Verzweigungsmuster.
//Der Pfad wird im Array SweepPositions gespeichert.
SearchDichotomousBranch (Levels, Positions, ticker3)

//Der folgende Makro stellt die Sphere_Sweeps dar.
DrawSphereSweep (SweepPositions, 0.12, Levels)

//Und dieser Makro ist für die Kugeln verantwortlich.
DrawSpheres (SweepPositions, 0.135, Levels-1)

#declare ticker3 = ticker3 + 1;
#end

Übersicht