Dr. O. Hoffmann
Vergnügen an Veränderung ist dem Menschen bleibend eigen.
Georg Christoph Lichtenberg
Nicht nur, um die Dateigröße zu verkleinern, können
verschiedene Elemente zu Gruppen (nicht im mathematischen Sinne, dort sind es
eher Mengen) zusammengefaßt werden. Das g
-Element vererbt auch
Transformationen auf die von ihm umschlossenen Elemente, ebenso andere Eigenschaften.
Für Transformationen von Elementen wird das Attribut transform
verwendet. Der Wert ist eine leerzeichenseparierte Liste mit folgenden Operationen als mögliche Listenpunkte: matrix,
translate, scale, rotate, skewX, skewY.
Bereits im vorherigen Abschnitt vorgestellte Grundformen sind ja alle noch sehr einfach. Mittels Transformationen wie Translation, Skalierung, Drehung und Scherung (oder Neigung) des Koordinatensystems kann man die Erscheinung von Elementen beeinflussen. Eine Skalierung mit einem negativen Faktor für x oder y ergibt eine Spiegelung. Statt der Einzelangaben ist auch die Angabe einer Transformationsmatrix möglich. Diese ist vor allem vorteilhaft, wenn Anfangs- und Endpunkte vorliegen, die ineinander transformiert werden sollen. Drei ansonsten frei wählbare Anfangspunkte dürfen dann nicht auf einer Geraden liegen, die drei Endpunkte sind beliebig wählbar. Zu jeder Kombination solcher 6 Punkte gibt es genau eine Matrix, welche die Anfangspunkte in die Positionen der Endpunkte transformiert. Zur normalen Schreibweise gehören für die Punkte Spaltenvektoren (x y 1). Mit der 1 als dritter Komponente wird bei den zweidimensionalen Vektorgraphiken die Translation in die Matrix hinein gemogelt. Ähnliche Matrizen werden auch Transfermatrizen genannt. Die Transformationsmatrix in der Kurzdarstellung matrix(a b c d e f) hat folgende Anordnung der Einträge:
a | c | e |
b | d | f |
0 | 0 | 1 |
Als alternative Darstellung mit x' und y' den Koordinaten nach der Transformation und x und
y davor ergibt sich:
x' = a x + c y +e
y' = b x + d y +f
Mit matrix(0 0 0 0 0 0) wird die Darstellung der zu transformierenden Elemente unterbunden.
Offenbar ist matrix(0 0 0 0 e f) eine Abbildung auf den Punkt (e f), das Ergebnis ist nicht sichtbar
(in SVG tiny 1.2 gibt es die Möglichkeit, dies mit der Eigenschaft vector-effect
=
"non-scaling-stroke" zu ändern).
matrix(1 0 0 1 e f) = translate(e f) ist eine Translation.
matrix(1 0 0 1 e 0) = translate(e) ist eine Translation in x-Richtung.
matrix(a 0 0 a 0 0) = scale(a) ist eine Skalierung um a,
matrix(a 0 0 d 0 0) = scale(a d) ist eine Skalierung um (a d), entsprechend
matrix(-1 0 0 1 0 0) = scale(-1 1) eine Spiegelung an der x-Achse,
matrix(1 0 0 -1 0 0) = scale(1 -1) eine Spiegelung an der y-Achse,
matrix(-1 0 0 -1 0 0) = scale(-1 -1) eine Punktpiegelung am Ursprung,
matrix(cos(a) sin(a) -sin(a) cos(a) 0 0) = rotate(a 0 0) eine Drehung um den Winkel a,
matrix(1 0 tan(a) 1 0 0) = skewX(a) ist eine Neigung in x um den Winkel a,
matrix(1 tan(a) 0 1 0 0) = skewY(a) ist eine Neigung in y um den Winkel a
rotate(a b c) ist eine Drehung um den Winkel a um den Punkt (b c), das läßt sich
natürlich auch als Matrix darstellen, ist aber kein so einfacher Ausdruck wie obige mehr, dazu ist es notwendig, eine Translation,
eine Drehung und die Translation zurück auszuführen.
Nehmen wir als ein Beispiel an, wir wollen eine Transformation durchführen,
welche (0 0) nach (q(x1) q(y1)), (x 0) nach (q(x2) q(y2)) und (0 y) nach (q(x3) q(y3))
abbildet, so rechnet man schnell aus, daß für die Transformationsmatrix
matrix(a b c d e f) gilt:
(q(x1) q(y1)) = (e f) (Translation)
a= (q(x2) - q(x1))/x
b =(q(y2) - q(y1))/x
c= (q(x3) - q(x1))/y
d =(q(y3) - q(y1))/y
Dies und die Verallgemeinerung davon sind natürlich wieder eine ideale
Anwendung von PHP - womit sich solche Matrizen schnell ausrechnen lassen und
man die genaue Kontrolle über die Zielpunkte der Transformation hat.
Beispiel für eine Transformation mit
einer Matrix
(Quelltext zur
Transformation mit einer Matrix).
Es handelt sich immer um affine Transformationen, diese erlauben es,
ausgedehnte Objekte zu transformieren, in dem nur charakteristische Punkte etwa
Ecken eines Objektes transformiert werden und dann wieder durch elementare Kurven oder
Geraden miteinander verbunden werden können:
Weitere Beispiele zu Transformationen
und Gruppen mit SVG
(Quelltext zu
Transformationen und Gruppen).
Man beachte dabei aber, daß das Ergebnis für den mit stroke
gemalten
Rand in der Regel ein anderes ist, wenn mittels transform
eine Scherung durchgeführt
wird als etwa mit PHP mit nachfolgender Darstellung des transformierten Pfades durch SVG.
Letztere Darstellung kann in SVG tiny 1.2 ebenfalls mit vector-effect
=
"non-scaling-stroke" bei SVG-transformierten Objekten erreicht werden, wobei sich die
Eigenschaft allerdings nicht vererbt, was einige Anwendungen etwas mühsam macht:
Beispiel non-scaling-stroke
(Quelltext zu non-scaling-stroke).
Das gleiche Beispiel ohne non-scaling-stroke:
Beispiel ohne non-scaling-stroke
(Quelltext zu Beispiel ohne non-scaling-stroke).
Um die Dateigröße zu verkleinern und allgemein zur
effektiven Verwendung zu wiederholender Elemente gibt es auch verschiedene Möglichkeiten,
Abkürzungen zu verwenden. Dies setzt nicht erst bei SVG
an, sondern schon bei XML, wo der Autor durch eine Ergänzung der Dokument-Typ-Definition
Abkürzungen einführen darf. SVG selbst bietet einige weitere
Möglichkeiten mit Elementen wie defs
, symbol
,
use
, image
. Zum Referenzieren wird nicht nur
SVG verwendet, sondern ein weiteres XML-Format namens
xlink, welches dann ebenfalls als Namensraum (xmlns
)
anzugeben ist.
Anmerkung: symbol
ist nicht Bestandteil von SVG tiny und wird
auch nicht von Opera 8 interpretiert.
Stattdessen kann das Element g
auch innerhalb von defs
verwendet werden.
image
mit SVG-Format ist ebenfalls nicht Bestandteil von SVG tiny
(nur JPEG und PNG) und wird ebenfalls nicht von Opera 8 oder 9 interpretiert
(nur JPEG und PNG). Integrierte svg
-Elemente sind ebenfalls
nicht Bestandteil von SVG tiny.
Abkürzungen und Transformationen (Quelltext zu Abkürzungen und Transformationen (1)).
Weiteres zu Abkürzungen und Transformationen (Quelltext zu Abkürzungen und Transformationen (2)).
In SVG tiny 1.2 gibt es die Möglichkeit, vorherige Transformationen wieder rückgängig
zu machen und so Objekte mitten im Quelltext zu notieren, die effektiv das Koordinatensystem des Anzeigebereiches
nutzen. Bei Gruppen können Kindelemente von dort aus wieder transformiert werden.
Die Einschränkung erfolgt mittels transform
= "ref(svg)"
Eingeschränkte Transformation
(Quelltext zur eingeschränkten Transformation).
Man beachte, daß nicht alle Transformationen invertierbar sind. Schlechte Implementierungen dieser Funktion
können daher bei nicht invertierbaren Transformationen abstürzen. Bessere Implementierungen werden
die betroffenen Objekte gar nicht erst transformieren, weswegen bei denen keine Rücktransformation notwendig
ist, um den Effekt zu erreichen.
Mit einem Zusatz zweier Koordinaten transform
= "ref(svg, -100,-100)"
kann das Element zusätzlich verschoben werden. Alternativ kann man offenbar die Einschräkung auch auf ein
Element g
anwenden und darin weitere Transformationen anwenden.
Eingeschränkte Transformation mit Verschiebung
(Quelltext zur eingeschränkten Transformation
mit Verschiebung).
Diese neue Funktion kann es offenbar etwas erleichtern, mit den Einschränkungen der Zeichenreihenfolge zurechtzukommen.
Ohne diese Funktion ist es erforderlich, die vorherigen Elemente und die nachfolgenden in Gruppen unterzubringen und getrennt
zu transformieren und das verbleibende Element eben nicht. Zusätzlich ist dann die viewBox
so anzugeben, daß keine Transformation dadurch stattfinden, dies wäre dann ebenfalls auf die Gruppen zu verschieben.
Eine sehr interessante Anwendung von Transformationen sind IFS-Fraktale
(use
-Elementes
ergibt sich eine sehr
einfache Möglichkeit, diese zu realisieren. Ein paar sehr einfache Beispiele:
IFS-Fraktal mit SVG (a),
IFS-Fraktal mit SVG (b),
IFS-Fraktal mit SVG (c),
IFS-Fraktal mit SVG (d),
IFS-Fraktal mit SVG (e),
IFS-Fraktal mit SVG (f).
Je nach Rechenleistung und
verwendetem Darstellungsprogramm kann es etwas dauern, bis das Fraktal angezeigt wird.
Opera 8 und 9 scheinen da auch mit mäßig schnellen Prozessoren Beachtliches zu leisten.
KSVG 1 zeigt sich als prima Unterhalter und zeigt jeden Interationsschritt - das Bild baut sich
also nach und nach auf - eine gute Idee eigentlich, da wird der Betrachter weniger ungeduldig,
weil er sieht, daß es voran geht. Gerade bei Darstellungen im internet werden einige
Nutzer ja schnell ungeduldig, obgleich hier einmal nicht das Laden der Datei Zeit dauert, sondern
eher die Darstellung der Datei, nachdem sie bereits auf dem eigenen Rechner angekommen ist.
Relativ schnell wird man solche Fraktale mit einem PHP-Skript erstellen wollen.
PHP kann man etwa leicht anwenden, um einige Parameter zufällig zu variieren:
IFS-Fraktal mit SVG und PHP
(Quelltext zum IFS-Fraktal mit SVG und PHP).
Durch eine einfache Rechnung kann auch abgeschätzt werden,
wie groß das Fraktal maximal wird. Dazu geht man vereinfachend davon aus,
daß nur jeweils um einen Faktor q <1 verkleinerte Stücke eindimensional
an die Grundform der Länge a angesetzt werden.
Dann ergibt sich bei unendlich vielen Iterationen als geometrische Reihe eine
Gesamtlänge von a /(1 -q).
Bei zweidimensionalen Objekten und zusätzlichen Drehungen ist es etwas komplizierter.
Gehen wir davon aus, daß die Transformation im Ursprung beginnt und eine verkleinerte
Kopie (Faktor q) im radialen Abstand r angefertigt wird, dann ergibt sich r/(1-q).
Für bessere Abschätzungen lohnt es sich, die genaue Grundform anzusehen und
sich ein wenig in die Thematik von mathematischen Reihen einzulesen, vor allem auch, um
eine gute Abschätzung für die minimale Größe zu erhalten.
Erste Versuche eines zufälligen und automatischen Strauch- oder Baumgenerators
mit SVG-Fraktalen:
IFS-Strauch oder -Baum,
noch ein Strauch.
Es sehen noch nicht alle zufällig erzeugten Sträucher wirklich gut aus und der
Preis für die einfachen IFS-Fraktale ist, daß in den Folgegenerationen kaum noch
Zufall einzubauen ist - dafür muß man ein oder zwei Schritte zurück und
flexibler arbeiten, was dann größere Dateien zur Folge hat, die dann aber
eher nach natürlich gewachsenen Strukturen aussehen dürften. Hier jedenfalls
könnte man bereits ganz gut gelungene Büsche per Hand weiterverarbeiten.
Einige weitere pflanzenartige Fraktale (Darstellung kann etwas länger dauern):
IFS-Fraktal mit SVG (g),
IFS-Fraktal mit SVG (h),
IFS-Fraktal mit SVG (i),
IFS-Fraktal mit SVG (j)
Darstellungen von Cantor-Mengen basieren auf den gleichen Mechanismen, wobei man
bedenken muß, daß sie eigentlich gar keine flächigen, darstellbaren Objekte sind. Dargestellt wird
vielmehr wie bei den Fraktalen auch das Ergebnis eines endlichen Iterationsschrittes.
Darstellung von Cantor-Mengen mit SVG (1).
Darstellung von Cantor-Mengen mit SVG (2).
Auch Zufallslinien oder Risse lassen sich so leicht erzeugen.
Während ein richtiger Riß zumeist keine zwei vorgegebenen Enden hat, sondern sich von
Anfang bis Ende zufällig ausbreitet, ist es für die Darstellung meist vorteilhafter,
beide Enden festzulegen.
Die Linie dazwischen teilt man auf und setzt eine kürzere Strecke senkrecht auf den Trennpunkt, die Auslenkung.
Damit ergeben sich zwei Strecken, die man erneut teilt, worauf man vier Strecken hat und so weiter.
Ein Parameter ist also die Anzahl dieser Iterationen, ein weiterer, wo eine Strecke geteilt wird
und noch ein weiterer, wie weit der Zwischenpunkt jeweils von der Verbindungslinie entfernt ist.
Letztere beide Parameter wird man natürlich aus einem gewissen Bereich zufällig auswählen, um
eine zufällige, unregelmäßige Struktur zu erreichen. Dabei kann man natürlich auch noch entscheiden,
ob man die Richtung der Auslenkung zufällig wählt, oder immer in die gleiche Richtung.
Riß (1)
(Quelltext zum Riß (1))
Parameter:
n: zwischen 2 und 12 für die Anzahl der Iterationen
abt: maximale relative Abweichung des Trennpunktes vom Mittelwert 0.5, zwischen 0 und 0.49
arp: maximale Auslenkung relativ zum Trennpunkt
ari: zufälliger Vorzeichenwechsel bei Auslenkung? 0 nein, 1 oder sonst ja
Nimmt man mehr als zwei Punkte entlang einer Kurve und legt man die Auslenkung von einem Trennpunkt auf der Kurve fest, lassen sich natürlich auch andere Formen realisieren, insbesondere geschlossene, um den Eindruck eines Loches zu erwecken.
Die lokale Korrelation zu benachbarten Punkten kann natürlich auch durch andere Arten von Iterationen erreicht werden. So kann man etwa in jedem Iterationsschritt über die Nachbarn mitteln und dazu einen Zufallswert addieren, der im Mittel null ist. Den Zufallswert kann man zudem mit jedem Iterationsschritt etwas verkleinern. Die relative Gewichtung zwischen Mittelwert und Zufallswert und der Verkleinerungsfaktor pro Iterationsschritt entscheiden dann über die Form der Zufallslinie.
Riß (2)
(Quelltext zum Riß (2))
Parameter:
n: zwischen 5 und 2000 für die Anzahl der Iterationen
df: Dämpfungsfaktor pro Interation (0 > df > 1)
zuf: Gewicht Zufallsanteil zum Mittelwert der Nachbarpunkte bei der ersten Iteration (0 > zuf >= 1000, typisch 100)
Bei Transformationen in SVG handelt es sich immer nur um affine Abbildungen. Eine Transformation von einem problem-orientierten Koordinatensystem (Polarkoordinaten, Zylinderkoordinaten, hyperbolische Koordinaten etc oder auch Projektionstransformationen) in ein anderes oder umgekehrt ist leider nicht möglich. Dazu wäre dann immer PHP zu verwenden, um in die kartesischen Koordinaten von SVG umzurechnen. Zu beachten dabei ist, daß dies in der Regel nur punktweise korrekt ist, eine affine Funktion in Koordinaten des einen Koordinatensystems ist nicht auch eine in einem beliebigen anderen Koordinatensystem. Das kann höheren Rechenaufwand und Näherungen bei der Darstellung von ausgedehnten Objekten bedeuten, wo es eben nicht ausreicht, nur die Ecken zu transformieren.
Was ich bereits bei den Polygonen benutzt habe, sind Polarkoordinaten oder
Kreiskoordinaten in
der zweidimensionalen Ebene, rudimentär treten die in SVG auf bei Kreisen, Ellipsen und
bei den Drehungen, wirklich durchgehend nutzen kann man sie in SVG allerdings nicht. Dazu
ist eine Transformation in kartesische Koordinaten zum Beispiel mit PHP vor der Ausgabe erforderlich.
Ist r die radiale Koordinate und φ die Winkelkoordinate, auch Polarwinkel, so ergibt sich mit
den kartesischen Koordinaten x und y:
x = r cos(φ)
y = r sin(φ)
Durch Wahl oder Transformation des Vorzeichens von φ von positiv zu negativ kann zwischen
einem Linkssystem und einem Rechtssystem gewechselt werden - SVG nutzt ohne zusätzliche
Spiegelungen ein Linkssystem. Durch Addition eines Winkels zu φ kann offenbar das
Koordinatensystem um diesen Winkel gedreht werden. Durch Addition von Konstanten kann der
Ursprung verschoben werden, wie schon bei den kartesischen Koordinaten.
Bei Zylinderkoordinaten im Dreidimensionalen wählt man als
dritte Koordinate h als Höhe des Zylinders, was keine Änderung gegenüber
den kartesischen Koordinaten bedeutet, also
z = h.
Bei dreidimensionalen Koordinaten ist vor der
Ausgabe mit SVG natürlich eine Projektion auf einen zweidimensionalen kartesischen
Unterraum vorzunehmen.
Sphärische Koordinaten oder Kugelkoordinaten
haben die drei Koordinaten r, φ und θ, wobei r wieder die radiale Koordinate ist
und φ wie bei den Zylinderkoordinaten der Polarwinkel mit Werten zwischen 0 und
360 Grad. θ ist der Azimutwinkel, dieser wird von einer Achse senkrecht zu jener
Ebene gemessen, welche die Polarwinkel aufspannen. Die Werte reichen
von 0 bis 180 Grad. Es gilt also:
x = r cos(φ) sin(θ)
y = r sin(φ) sin(θ)
z = r cos(θ)
Auch hier ist vor der Ausgabe wieder eine Projektion auf einen zweidimensionalen kartesischen
Unterraum vorzunehmen. Alternativ kann natürlich auch r festgehalten werden, dann
erhält man eine Kugeloberfläche.
Bei Toruskoordinaten hat man in der Regel einen großen, polaren Radius R und einen
kleinen r, einen Polarwinkel φ des großen, polaren Radius R und einen Winkel
θ des kleinen r. Werden R und r festgehalten, so ergibt sich eine zweidimensionale
Fläche in einem dreidimensionalen Raum:
x = (R + r cos(θ)) cos(φ)
y = (R + r cos(θ)) sin(φ)
z = r sin(θ)
Beide Winkel gehen von 0 bis 360 Grad. Je nach Wahl von R und r kann die
Oberfläche sich selbst schneiden.
Hyperbolische Koordinaten verfügen gleich über
mehrere Parametrisierungen, je nach Problemstellung. Ein Hyperboloid wird
in kartesischen Koordinaten beschrieben durch die Gleichung:
(x/a)2 +
(y/a)2 -
(z/c)2 = 1.
Parametrisierungen der Fläche sind zum Beispiel:
x = a ( 1+ u2)1/2 cos(φ)
y = a ( 1+ u2)1/2 sin(φ)
z = c u
φ ist wieder ein Polarwinkel zwischen 0 und 360 Grad, u ein weiterer unbeschränkter
Parameter, a und c feste Konstanten.
Andere Möglichkeit:
x = a (cos(φ) (-,+) u sin(φ)
y = a (sin(φ) (+,-) u cos(φ)
z = (+,-) c u
Bei den in Klammern stehenden Vorzeichen ist jeweils entweder das erste oder das zweite zu
wählen. Die Konstruktion ist besonders schön, denn man kann sich die beiden
Parameterscharen entstanden vorstellen aus einem Zylinder, bei welchem ein Ende polar
verdreht wird.
Noch eine Möglichkeit:
x = a cosh(u) cos(φ)
y = a cosh(u) sin(φ)
z = c sinh(u)
Die einfachste Projektion oder Projektionstransformation
besteht darin, einfach eine der drei
Koordinaten x y z nicht darzustellen und die anderen beiden mit den zwei Koordinaten in
der Ebene zu identifizieren. Das nennt sich Parallelprojektion, dabei
wird eine der drei Achsen mit 0 multipliziert, also auf 0 abgebildet.
Etwas eleganter und allgemeiner ist es, eine affine Abbildung
auf den zweidimensionalen kartesischen Unterraum vorzunehmen, etwa durch eine Drehung
im Raum in ein neues System x' y' z' mit anschließender Parallelprojektion von z' auf 0.
Drehungen um die z-Achse um den Winkel φ kennen wir bereits:
x' = cos(φ) x - sin(φ) y
y' = sin(φ) x + cos(φ) y
z' = z
Drehung um die x-Achse entsprechend
y' = cos(φ) y - sin(φ) z
z' = sin(φ) y + cos(φ) z
x' = x
und Drehung um die y-Achse
z' = cos(φ) z - sin(φ) x
x' = sin(φ) z + cos(φ) x
y' = y
Drehung um eine Achse (x, y, z) = (p, q, r) (Einheitsvektor):
x' = (t p p + c) x + (t p q - s r) y + (t p r + s q) z
y' = (t p q + s r) x + (t q q + c) y + (t q r - s p) z
z' = (t p r - s q) x + (t r q + s p) y + (t r r + c) z
mit s = sin(φ), c = cos(φ) und t = 1 - cos(φ)
Drehung einer Pyramide,
(Quelltext zur Drehung einer Pyramide):
Drehung eines Objektes (unregelmäßige dreieckige Pyramide)
um den Mittelpunkt des Bildes um einen Vektor (x, y, z) = (p, q, r)
um den Winkel o in Grad.
Im Ursprung ist eine Ecke der Pyramide, die anderen drei Punkte
liegen auf den Achsen x, y und z. Das Verhältnis der Abstände
auf diesen Achsen ist 1:2:3.
Gezeigt wird die x-y-Ebene, z wird auf 0 abgebildet.
o, p, q, r und ein Skalierungsfaktor s sind als GET-Parameter verfügbar.
Eine Skalierung entspricht einfach der Multiplikation einer Koordinate mit einem
Wert ungleich 0. Die Multiplikation mit 0 kann als Projektion auf den zweidimensionalen
Unterraum ohne diese Koordinate aufgefaßt werden. Skalierung:
x' = a x
y' = b y
z' = c z
Eine Verschiebung oder Translation um
einen Vektor (u, v, w) entspricht einfach der Transformation:
x' = x + u
y' = y + v
z' = z + w
Andere Projektionen berücksichtigen die Sichtweise eines Malers mit einer Leinwand, des menschlichen Auges oder von Photoapparaten, wo auch weiter entfernt liegende Objekte kleiner erscheinen als nähere Objekte. Rechnerisch ist das die Projektion auf eine Fläche zwischen Objekt und Auge mittels des Strahlensatzes. Beim Malermodell ist die Fläche die Leinwand, das zu Malende befindet sich hinter der Leinwand, der Maler oder das Auge davor. Gemalt wird nur, was sich jenseits der Leinwand befindet. Beim Photoapparat ist die Fläche die Film- oder Chipebene, beim Auge die gekrümmte Rückseite des Augapfels, dargestellt wird eigentlich alles, was sich vor der Fläche befindet, also mehr als beim klassischen Malermodell, auch die Anordnung der Strahlen im Strahlensatz ist etwas anders. Auge und Kamera haben eine Linse, weswegen an sich nur eine Fläche, nicht der ganze Raum scharf dargestellt wird, das wird bei einer Projektion nicht berücksichtigt, was dann eher einer Lochkamera mit punktförmigem Loch entspricht, bei der allerdings praktisch kein Licht auf die Abbildungsfläche träfe oder bei einem großen Loch die Abbildung generell unscharf wäre. Das sind allesamt nur klassische Behandlungen, es wird also keine Beugung oder Interferenz berücksichtigt. An all diesen Punkten läßt sich erkennen, daß die Modelle alle nur einfache Näherungen dessen sind, was wirklich passiert, wenn Objekte mit dem Auge oder einer Kamera betrachtet werden.
Denken wir uns die Projektionsfläche am Ort z = a, das Auge des Betrachters bei
z = 0 und das Objekt bei z = g (Gegenstandsweite). Ist die Größe des Objektes h,
so erscheint ein Bild auf der Projektionsfläche der Größe h' = h a/g
gleich groß.
Das ergibt sich unmittelbar aus dem Strahlensatz. Man beachte, daß immer g > 0 gelten
sollte. Bei g = 0 sitzt das Objekt offenbar im Auge des Betrachters, was sowohl bei der
Projektion als auch im richtigen Leben ein fataler Unfall wäre und daher zu vermeiden ist.
Für g < 0 ist das Objekt hinter dem Betrachter, der es dann nicht sehen kann.
Oft wird die z-Koordinate des Objektes als Gegenstandsweite angenommen.
Das führt zu den Formeln der Zentralprojektion oder des
Malermodells:
x' = x (a/z)
y' = y (a/z)
Um zu gucken, ob es reicht, nur die Eckpunkte oder eben die Stützpunkte eines Pfades zu
transformieren, probieren wir das einfach aus, indem wir die vorherige Figur mit kubischen
Bézierkurven realisieren (wobei das ein leichter Vorgriff auf einen der folgenden
Abschnitte ist):
Drehung und
Zentralprojektion,
(Quelltext zur Drehung und Zentralprojektion):
Drehung eines Objektes (unregelmäßige dreieckige Pyramide)
um den Mittelpunkt des Bildes um einen Vektor (x, y, z) = (p, q, r)
um den Winkel o in Grad.
Im Ursprung ist eine Ecke der Pyramide, die anderen drei Punkte
liegen auf den Achsen x, y und z. Das Verhältnis der Abstände
auf diesen Achsen ist 1:2:3.
Gezeigt wird die x-y-Ebene, z wird auf 0 abgebildet.
o, p, q, r und ein Skalierungsfaktor s sind als GET-Parameter verfügbar.
Zentralprojektion: Das Objekt wird um t in z-Richtung verschoben, die
Bildebene ist bei a, beides ist auch als GET-Parameter verfügbar.
Genaugenommen ist ein Objekt mit x oder y ungleich 0 natürlich auch weiter weg
und somit im Modell eines Auges mit gekrümmter Abbildungsfläche kleiner
darzustellen. Ein Photoapparat hat eine Ebene als Abbildungsfläche, aber auch teils
kompensierte Linsenfehler, eine genaue Simulation ist daher schwierig und abhängig
vom Auge oder dem jeweiligen Modell des Photoapparates samt Objektiv. Zudem beinhaltet
die Abbildung etwas, was einer Punktspiegelung entspricht, was bei einer Projektion nicht
relevant ist und durch ein leicht modifiziertes Modell zu berücksichtigen ist.
Nun kompensiert das Auge in gewissem Maße bereits den Effekt, daß etwa
die Ränder einer Projektionsfläche weiter vom Auge weg sind und objektiv
kleiner erscheinen. Möchte man dies aber korrekt berücksichtigen, so denkt
man sich um das Auge herum eine Halbkugel im Abstand a als Projektionsfläche und
bekommt mit der Hilfsgröße
H = a /(x2 +
y2 +
z2) 1/2
die Kugelprojektion:
x' = H x
y' = H y
Wie unmittelbar zu sehen ist, geht diese Formel für x und y gegen 0 in die Formel
für die Zentralprojektion über. Die andere, dem Betrachter eigentlich nicht sichtbare
Halbkugel könnte den Raum hinter dem Beobachter darstellen. Das Unfallrisiko, daß
das Objekt im Auge steckt, reduziert sich damit auf einen Punkt, während es bei der
Zentralprojektion noch die ganze Ebene war. Da häufig Objekte um den Ursprung herum
definiert sind, ist daran zu denken, daß bei diesen Projektionstransformationen allerdings das
Auge des Betrachters der Ursprung ist. Es ist also am Einfachsten, das Objekt zunächst
in die passende Lage zu drehen, dann in z-Richtung auf einen geeigneten Abstand zu
verschieben und anschließend erst zu projezieren.
Drehung und
Kugelprojektion,
(Quelltext zur Drehung und Kugelprojektion):
Drehung eines Objektes (unregelmäßige dreieckige Pyramide)
um den Mittelpunkt des Bildes um einen Vektor (x, y, z) = (p, q, r)
um den Winkel o in Grad.
Im Ursprung ist eine Ecke der Pyramide, die anderen drei Punkte
liegen auf den Achsen x, y und z. Das Verhältnis der Abstände
auf diesen Achsen ist 1:2:3.
Gezeigt wird die x-y-Ebene, z wird auf 0 abgebildet.
o, p, q, r und ein Skalierungsfaktor s sind als GET-Parameter verfügbar.
Kugelprojektion: Das Objekt wird um t in z-Richtung verschoben, die
Bildebene ist bei a, beides ist auch als GET-Parameter verfügbar.
In diesem Falle ist es, wie bei genauen Hinsehen bemerkt werden kann so, daß Geraden in der
Regel nicht exakt auf Geraden abgebildet werden. Immerhin sind die verwendeten kubischen
Bézierkurven schon eine etwas bessere Näherung als gerade Linien. Noch besser
ginge es, wenn die kubischen Bézierkurven erst nach der Transformation berechnet
würden, was dem Leser zu Übung überlassen bleibt.
Eine weitere interessante Möglichkeit der Projektion ist, einfach zwei der Parameter des speziellen Koordinatensystems in kartesischen Koordinaten darzustellen, letztlich also die inverse Transformation vorzunehmen. Der Torus entspricht topologisch etwa einem endlichen rechteckigen Flächenstück, dessen gegenüberliegende Kanten wieder aneinandergefügt sind - nennt man auch periodische Randbedingungen, welche zum Beispiel gern für Hintergrundbilder auf internet-Seiten verwendet werden. Solche sich periodisch fortsetzenden Bilder entsprechen also eher der (verzerrten) lokalen Sicht auf einer Torusoberfläche, wenn man nicht in der Lage ist, dessen Krümmung in der zusätzlichen Dimension wahrzunehmen.
Nachzuprüfen ob folgende Behauptungen gelten, bleibt dem Leser zu Übung überlassen (Tip: oben sind bereits ein paar Beispiele angegeben):
Weil es nett aussieht, gucken wir uns jetzt noch ein paar Objekte animiert an, die Animation ist
recht einfach und kann mit dem Animationsabschnitt nachvollzogen werden.
So animieren, transformieren und projezieren wir also erstmal Platonische Körper:
Tetraeder
Hexaeder
Oktaeder
Dodekaeder
Ikosaeder.
Bei so einfachen Objekten mit ebenen Oberflächen ist es auch recht einfach, nicht nur
die Kanten darzustellen, sondern ebenso die Flächen. Bei mehrfarbigen Abbildungen von
mehreren Objekten oder Flächen ist dann allerdings auch die Zeichenreihenfolge relevant.
Diese ist ebenfalls zu bestimmen und kann dann berüchsichtigt werden, indem die
Flächen mit use
-Elementen referenziert werden und die Referenzierung
dann eben in einer Animation so getauscht wird, daß immer von hinten nach vorne dargestellt
wird:
Tetraeder - Flächendarstellung
Hexaeder - Flächendarstellung
Oktaeder - Flächendarstellung
Dodekaeder - Flächendarstellung
Ikosaeder - Flächendarstellung.
Weitere Beispiele:
Sterntetraeder
Sterntetraeder - Flächendarstellung
Hyperboloid
Punkte auf Kugel
Achtung, größere Dateien (um die 60 bis 400 kB):
Torus 1,
Torus 2,
Torus 3,
Torus 4,
Torus 5