|
Prof.
Urban
|
![]() |
![]() |
||
Das wichtigste an einem Baum sind seine Verzweigungen. Ganz stark vereinfacht könnten wir sagen:
![]() |
![]() |
![]() |
![]() |
| Stufe 1 | Stufe 2 | Stufe 3 | Stufe 4 |
Das klingt nicht nur rekursiv, es ist auch bequem so zu formulieren. In POV-Ray geht es nicht ganz so elegant wie in Python, doch konnen wir mit dem Schlüsselwort #macro Funktionen mit Übergabeparametern definieren. #local erlaubt uns die Verwendung von lokalen Variablen.
// Verzweigungen rekursiv
camera {
location <0,1,-3.5>
right image_width/image_height*x // für *jede* Bildgröße
look_at <0,0.25,0>
}
light_source { <0,4,-4> 1}
# declare Winkel = 50; // Abzweig-Winkel rechts und links
# declare Shrink = 0.7; // Verkürzung für den nächsten Ast
// a=Startpunkt, b=Endpunkt, r=Zylinderradius, n=Rekursionstiefe
#macro Tree(a,b,r,n)
#if (n>0) // Rekursionsende bei n=0
#local d=b-a; // Richtungsvektor dieses Astes
union{
// ein Stück Ast von a bis b
cylinder {a,b,r}
// daran hängt ab b ein rechter Zweig
Tree(b,b+Shrink*vrotate(d,-Winkel*z),r,n-1)
// und ein linker Zweig
Tree(b,b+Shrink*vrotate(d,Winkel*z),r,n-1)
}
#end
#end
#declare Depth = 5;
object { Tree(<0,-1,0>,<0,0,0>, 0.05, Depth)
pigment {color rgb <0,1.5,0> }
}
Die Richtung des abzweigenden Astes wird hier mit der POV-Ray Standard-Funktion vrotate(v,w) berechnet: sie liefert den Vektor, der bei Drehung von v um w entsteht. Wir drehen um die z-Achse, also liegen alle Äste in einer Ebene.
Wenn wir so weit gekommen sind, fängt der Spaß an. Warum sollten wir nicht Blätter an die Zweige heften? Die letzte Rekursionsstufe erkennen wir an n=0, dann zeichnen wir einfach eine rote Kugel. Das Pigment für die Äste wandert in den Macro hinein, da nicht mehr die ganze Figur einheitlich gefärbt ist. Damit ergibt sich
// ... Anfang wie oben ...
// a=Startpunkt, b=Endpunkt, r=Zylinderradius, n=Rekursionstiefe
#macro Tree(a,b,r,n)
#if (n=0)
//ein Blatt
sphere { a,r*1.25
pigment { color rgb <1.5,0,0> }
}
#else
#local d=b-a; // Richtungsvektor dieses Astes
union{
// ein Stück Ast von a bis b
cylinder {a,b,r pigment {color rgb <0,1.5,0> } }
// daran hängt ab b ein rechter Zweig
Tree(b,b+Shrink*vrotate(d,-Winkel*z),r,n-1)
// und ein linker linker Zweig
Tree(b,b+Shrink*vrotate(d,Winkel*z),r,n-1)
}
#end
#end
#declare Depth = 5;
object { Tree(<0,-1,0>,<0,0,0>, 0.05, Depth) }
und als Bild:

Wirkliche Bäume sind in alle Richtungen verwinkelt. Wir müssen bei der Drehung mit vrotate einen krummen Winkel statt der z-Achse einsetzen. Die einzigen Änderungen sind
// daran hängt ab b ein rechter Zweig
Tree(b,b+Shrink*vrotate(d,-Winkel*(z+<0.4,-0.3,0>)),r,n-1)
// und ein linker linker Zweig
Tree(b,b+Shrink*vrotate(d,Winkel*(z+<0.3,0.2,0.3>)),r,n-1)

Welche Variationen fallen uns noch ein:
Wie sieht ein Farn aus: nicht wie oben eine Stiel und an dessen Ende eine Verzweigung, sondern: ein Stiel, und rechts hinaus, links hinaus und vorne dran ein neuer kleinerer Farn (erinnere Dich an Mathe - rekursive Beschreibung selbstähnlicher Figuren). Zusatzverbesserung: Statt einfacher Zylinder wählen wir Kegelstumpf-Objekte. Mit ihnen kann das Dünnerwerden der neuen Äste nachgebildet werden. Wenn der Radius am Ende des alten Zweiges mit dem am Beginn des neuen übereinstimmt, dann passt es nahtlos zusammen. Wir führen in unserem Makro also auch Buch über beide Radien und übergeben einfach immer den neuen kleineren an die nächste Generation.
// ein künstlicher Farn
camera {
location <0,1,-7>
look_at <0,1.5,0>
}
global_settings { assumed_gamma 1.0 }
light_source { <0,4,-4> 1}
#macro Tree(a,b,r,n)
#if (n=0)
cone { a,r, b,0.8*r }
#else
#local d=b-a;
#local c=a+0.5*d;
union{ cone {a,r, b,0.8*r }
Tree(c,c+0.4*vrotate(d,-45*z),0.9*r,n-1)
Tree(b,b+0.3*vrotate(d,45*z),0.8*r,n-1)
Tree(b,b+0.9*vrotate(d,3*z),0.8*r,n-1)}
#end
#end
object { Tree(<0,-1,0>,<0,0,0>,0.03, 8)
pigment { color rgb 1.0 }
}
Das Ergebnis ist recht beeindruckend
![]() |
![]() |
| dicker | dünner und tiefere (8) Rechnung |
Weitere Experimente: