2. Kapitel
Positionierung von Objekten auf dem Bildschirm mittels Koordinaten-Transformation
Klassische Koordinatentransformation
Um Objekte auf dem Bildschirm darstellen zu können, müssen sie positioniert werden. Wie wir in sahen, liefern unsere Berechnungen die Koordinaten für die darzustellenden Objekte. Nun müssen also diese Koordinaten den Pixelpositionen auf dem Bildschirm zugeordnet werden. Abbildung . zeigt wie die Pixel, deren Lage durch einen x- und einen y-Wert bestimmt sind, auf dem Bildschirm positioniert werden. Anders als wir das gewohnt sind, liegt der Nullpunkt in der linken oberen Ecke des Bildschirms und, was noch ungewöhnlicher ist, die y-Achse verläuft von oben nach unten.Das bleibt nicht ohne Konsequenzen auf andere Koordinaten. So wird in "processing" oder "p5.js" auch der Drehsinn umgekehrt.
Diese etwas ungewöhnliche Orientierung des Koordinatensystems geht auf die
seligen Zeiten der Röhrenfernsehapparate zurück. Da lief nämlich der
Elektronenstrahl zeilenweise von links oben nach rechts unten. Und da die
ersten Computermonitore mit Bildröhren bestückt waren, mussten die Entwickler
der Steuersoftware wohl oder übel auf diesen Zeilenlauf Rücksicht nehmen.
on/off
Geübte Programmierer haben sich so an diese Tatsachen gewöhnt, dass sie bei der Entwicklung ihrer Programme keine Probleme damit haben. Wem diese Besonderheiten aber zu unbequem erscheinen, dem gebe ich hier einige Transformationsregeln zur Hand, die die Computerwelt vom Kopf auf die Füße stellt und zudem noch weitere Vorzüge in sich vereinen.
Zunächst einmal ist es unvorteilhaft, wenn der Mittelpunkt einer Szene (entspricht dem Ursprung des Koordinatensystems) stets in der linken oberen Ecke liegt. Besser wäre es, einen frei wählbaren Mittelpunkt zu haben. Da wäre also zunächst eine Verschiebung des Ursprungs erforderlich. Was bedeutet das? Der Mittelpunkt meines gewünschten Koordinatensystems (kartesisches K. genannt) muss so in die Bildschirmkoordinaten (interne K. genannt) umgerechnet werden, dass die kartesischen Werte xk = 0 und yk = 0 in die internen Werte xi = 400 und yi = 300 umgerechnet werden, wenn der Ursprung des kartesischen Koordinatensystems genau in der Mitte des Fensters, das mit size(800, 600) (processing) oder createCanvas(800, 600) (p5.js) definiert wurde, liegen soll.
Bei dieser Gelegenheit wollen wir gleich den Makel des verkehrten Laufs der y-Achse mit beheben, das geschieht, indem wir eine Vorzeichenumkehr aller y-Werte vornehmen.
Der Ursprung des Bildschirm-Koordinatensystems (internes K. genannt) wird durch
Verschiebung um die Werte xi0 und
yi0 zum Ursprung des szenarischen Koordinatensystem
(kartesisches K. genannt). Somit stellt der Punkt (xi0;
yi0) die "Schnittstelle" zwischen den Koordinatensystemen dar.
on/off
Die Transformationsgleichungen führen diese Operationen aus. Mit dem Index i werden die internen und mit dem Index k die kartesischen Koordinaten gekennzeichnet. Worin xi0 und yi0 die Lage des Ursprungs des kartesischen Koordinatensystems im internen Koordinatensystem bezeichnen ().
()
Aber auch die umgekehrte Transformation muss möglich sein. Denn eine Interaktion zwischen Spieler und Computer findet in der Regel mit Hilfe der Maus statt. Dazu werden neben den Maustasten vor allem die Mauskoordinaten abgefragt. Die Mauskoordinaten werden natürlich im internen Koordinatensystem angegeben. Also muss es eine Umrechnung interner in kartesische Koordinaten geben, damit die Mausparameter tatsächlich in die Szene passen. Die Transformation () stellen die umgekehrte Transformation dar.
Um die Mauskoordinaten richtig in die Szene zu bringen, müssen sogar die
Änderungen des Maßstabs und die Adaption an die aktuelle Fenstergröße
berücksichtigt werden!
()
on/off
So sieht die Programm technische Umsetzung beider Transformationen in processing bzw. p5.js aus:
Abb. Programmauszug Koordinaten-Transformation
... und so werden die Transformationsfunktionen angewendet:
Abb. Transformation kartesich ↔ Koordinaten-Transformation
Im unteren Teil des Programmauszugs in wird gezeigt, wie die Transformation der Mauskoordinaten, die ja in internen Koordinaten und ohne Maßstab angegeben werden, in kartesische Koordinaten maßstabsrichtig umgerechnet werden. So kann ein Objekt (im Beispiel ein Kreis), das mit der Maus verschoben werden soll, auch in kartesischen Koordinaten plaziert werden. Das erleichtert das konsequente Rechnen in kartesischen Koordinaten.
Das Beispiel in zeigt, wie ein Rechteck abgebildet wird, dessen Koordinaten einmal im internen Koordinatensystem und einmal nach erfolgter Transformation im kartesischen Koordinatensystem angegeben werden. Das kartesische Koordinatensystem ist im Beispiel genau mittig angeordnet. Das ist zu sehen, wenn die Maus genau auf den Ursprung des Koordinatenkreuzes zeigt.
Fährt die Maus über die Koordinaten der Rechtecke, werden sowohl die internen wie auch nach Rücktransformation die kartesischen Koordinaten der Mausposition angezeigt. Mit den weißen Kreisen werden die Plazierungen des kartesischen Koordinatensystems bzw. der Rechtecke angedeutet. Während das rote Rechteck ohne Koordinaten-Transformation plaziert wird, wird das grüne Rechteck transformiert und maßstäblich plaziert. Alle Koordinatenwerte werden numerisch angezeigt!
Bitte einen Augenblick Geduld
während das Programm geladen wird!
Abb. Bildschirm-Koordinatensystemwährend das Programm geladen wird!
ACHTUNG! In diesem Programmbeispiel wird ausnahmsweise mit einem nicht dynamischen Maßstab gerechnet, um die maßstäbliche Umrechnung von kartesischen in interne Koordinaten und umgekehrt zu demonstrieren. Deshalb kann es bei einigen Bildschirmauflösungen zu Beschneidungen des Darstellbereiches kommen!
Koordinatentransformation mit Hilfe der Matrix-Operationen
Wer mit Processing oder p5.js arbeitet, hat einen Vorteil. Beide Entwicklungsumgebungen bieten nämlich mit den Matrix-Befehlen (processing) bzw. (p5.js) einen besonderen Befehlssatz an. Dieser Befehlssatz erlaubt die selektive Kreation von Koordinatensystemen, die dank besonderer Befehle verschoben, rotiert und skaliert werden können. Auf diese Weise kannst Du Teile der Szenerie unabhängig von einander bewegen, drehen oder skalieren.Aber beachte: für die Matrix-Befehle gelten für die y-Achse eine entgegen der positiven mathematischen Orientierung und für den Rotationswinkel eine entgegen den mathematisch positiven Winkeln definierter Drehsinn.
An dieser Stelle wollen wir die Matrix-Befehle zunächst nur für die Koordinatentransformation benutzen. Die Verwendung der Matrix-Befehle sollte nach einem strikten Ritual erfolgen: zuerst wird das bisher gültige Koordinatensystem im stack gesichert. Das besorgt die Anweisung pushMatrix() (processing) bzw. push() (p5.js), dann erfolgt die Generierung des neuen Koordinatensystems und die hierfür gedachte Szenerie wird implementiert. Ist das geschehen, wird das vorherige Koordinatensystem mit der Anweisung popMatrix() bzw. pop() wieder in Kraft gesetzt. Diese Reihenfolge ist unbedingt einzuhalten. Sollte in einem Programm einmal eine der beiden Anweisungen vergessen worden sein, dann rächt sich die Entwicklungsumgebung mit einem stackoverflow!
Das Programmbeispiel in zeigt, um wieviel bequemer die Programmierung durch die Anwendung der Matrix-Operationen wird. Denn die eigentliche Transformation wird durch den translate()- Befehl ausgeführt. Wenn xi0 und yi0 die Koordinaten des neuen Systems bezogen auf das Ursprungssystem (linke obere Ecke des Fensters) sind, dann können im verschobenen Koordinatensystem alle Koordinaten absolut angegeben werden.
Bleibt noch die Richtungsumkehr der y-Achse. Dafür stehen uns zwei Möglichkeiten zur Verfügung:
-
Benutzung des Matrix/Befehls scale(1, -1);. Dieser Befehl bewirkt,
dass alle x-Werte 1:1 übernommen, die y-Werte aber
bei der Darstellung mit dem Faktor -1 multipliziert, also an der
x-Achse gespiegelt werden.
Achtung! Die Verwendung dieser Variante spiegelt alle Objekte in der Folge dieses Befehlts. Also auch Texte, Primitives oder Images!
- Bei der Darstellung eines Objektes werden alle y-Werte mit einem negativen Vorzeichen eingetragen. Das verursacht mehr Schreibarbeit umgeht aber das Spiegelungsproblem.
Abb. Koordinaten-Transformation mittels Matrix-Befehlen
Die Positionierung der Ellipse erfolgt nach der 1. Variante mit Hilfe des scale()-Befehls, die des Rectangles nach der 2. Variante durch Vorzeichenumkehr.
Kosmisches Beispiel für Nullpunkt-Transformation und Maßstabsbestimmung
Es soll die in gezeigte kosmische Konstellation Mond-Erde-Raumschiff auf dem Computerbildschirm dargestellt werden. In der oberen Hälfte der Abbildung sind die kosmischen Dimensionen wie Durchmesser bzw. Entfernung angegeben. Da das Raumschiff um die Erde kreisen soll, ist die Festlegung des Bahnmittelpunktes auf der Erdmittelpunkt zweckmäßig. Daraus folgt, dass der Nullpunkt des kosmischen Koordinatensystems mit den Mittelpunkten der Erde und der Flugbahn übereinstimmen sollte.Abb. kosmisches Szenarium Erde-Mond-Raumschiff
In der unteren Hälfte der ist die auf Bildschirmverhältnisse (Bild-Welt) transformierte reale Welt gezeigt. Die Fenstergröße wurde mit 800 x 600 Pixeln festgelegt.
Zunächst wurden Vorgaben für die Wahl des Mittelpunktes der Erde in der Bild-Welt gemacht. Der Bild-Nullpunkt wurde mit xi0 = 650 Pixel und yi0 = 300 Pixel gewählt. Ebenso wurde die Entfernung vom Mond zur Erde mit 550 Pixeln festgelegt. Beide Festlegungen ergeben sich aus der Forderung, dass sowohl der Mond als auch die Erde maßstabsgerecht auf dem Bild zu sehen sein müssen. Nun können sowohl das interne Koordinatensystem mittels Koordinatentransformation um xi0 und yi0 verschoben, als auch der Maßstab M bestimmt werden ().
()
Rotation mit Hilfe der Matrix-Befehle
Unverzichtbar sind Befehle, die die Drehung eines Objektes gestatten. Im Beispiel des Sonnensystems liegt ein solcher Fall vor. Während hier die Anwendung der trigonometrischen Funktionen für die Darstellung der kreisenden Planeten bzw. Kometen schon ausreichen würde, wäre die Darstellung von gedrehten Images oder nichtsymmetrischer Objekten gänzlich unmöglich! Hier leisten die Matrix-Befehle unverzichtbare Dienste!Im folgenden wollen wir beispielhaft am Sonnensystem die Anwendung der Matrix-Befehle verfolgen (). Das Szenarium ist einigermaßen anspruchsvoll, denn nicht nur dreht sich die Erde um die Sonne, es dreht sich auch noch der Mond um die Erde und gemeinsam mit dieser um die Sonne!
Entsprechend sind die folgenden Schritte erforderlich:
-
zunächst wird das Koordinatensystem aus seiner natürlichen Position
(0,0) in den Mittelpunkt der Sonne (nicht dargestellt) verschoben. Die Koordinaten der
Sonne fallen mit den Koordinaten xi0,
yi0, die den Nullpunkt des kartesischen Koordinatensystems
bestimmen, überein. Dazu muss mit einem pushMatrix() bzw. push()
das bisherige Koordinatensystem gesichert und mit einem translate(xi0, xi0)
die Verschiebung vorgenommen werden.
-
dieser Schritt befasst sich nun mit der Positionierung der Erde. Da sich
die Erde um die Sonne drehen soll, muss es eine Drehbewegung um den Winkel
φErde = ωErde ·t geben, der die zeitliche Änderung
der Drehung fixiert. Mit diesem Winkel wird ein rotate(φErde)
des im 1. Schritt verschobenen Koordinatensystems ausgeführt. Weiterhin muss
noch eine weitere Verschiebung um den Erdbahnradius erfolgen, damit die Erde
wirklich im Abstand von RErde um die Sonne kreist.
Die Erde selbst wird vereinfacht durch eine hellblau gefüllte ellipse()
dargestellt. Sie wird auf den Nullpunkt des aktuellen Koordinatensystems
gesetzt: ellipse(0, 0, ØErde, ØErde).
-
jetzt ist der Mond an der Reihe. Das Koordinatensystem des Mondes bewegt
sich zusätzlich zum Koordinatensystem der Erde, darum muss dieses auch durch ein
pushMatrix() bzw. push() gesichert werden. Da sich der
Mond um die Erde drehen soll, muss es eine Drehbewegung um den Winkel
φMond = ωMond ·t für die
Mondposition geben. Mit diesem Winkel wird ein weiteres rotate(φMond)
des im 2. Schritt verschobenen Koordinatensystems ausgeführt. Die erforderliche
Verschiebung um den Mondbahnradius kann in dem Befehl zur Darstellung des
Mondes (ellipse(0, 0, ØMond, ØMond))
übernommen werden, da keine weiteren Objekte um den Mond kreisen.
- Am Ende der Darstellung des vollständigen Erde-Mond-Systems müssen die gesicherten Koordinatensysteme mit einem zweifachen popMatrix() bzw. pop() rekonstruiert werden.
Abb. Programmauszug Anwendung rotate() in Verbindung mit translate()
Eine ausführliche Besprechung des Programms findest Du im Abschnitt KEPLERsche Gesetze im 9. Kapitel.