3 2D-Graphik: Transformationen, Clipping
Verarbeitungsschritte von der Szene zum Bild

Mögliche Transformationen
Verschiebung
Skalierung
Spiegelung an x und y oder am Ursprung
Drehung
Scherung in x und y
Verkettung von Transformationen
Werden zwei Transformationen in unterschiedlicher Reihenfolge ausgeführt,
ergeben sich im allgemeinen unterschiedliche Ergebnisse.
Affine Abbildung
Eine einfache Möglichkeit, solche Modellierungs-Transformationen
mathematisch zu beschreiben bzw. vom Rechner ausführen zu lassen, sind sog.
affine Abbildungen.
Homogene Darstellung affiner
Abbildungen
(Skalierung, Rotation, Spiegelung und Scherung) =
Matrix-Vektor-Multiplikation.
(Transformationen)=Multiplikation von Matrizen
(Verschiebung)=Vektor-Addition
Vereinheitlichung der Berechnung, so dass sich alle Transformationen mit Hilfe
einer Matrix-Vektor-Multiplikation berechnen lassen.
3D-Graphik: Transformationen
|
Codierung: Bit 1: links des Rechtecks Bit 2: rechts des Rechtecks Bit 3: unter dem Recheck Bit 4: über dem Rechteck |
![]() |
1. Ist die Oder-Verknüpfung der Codes der
beiden Endpunkte gleich 0000, ist die Strecke vollständig im Clip-Rechteck
enthalten
2. Ist die Und-Verknüpfung der Codes der beiden Endpunkte ungleich 0000, liegt
die Strecke sicher außerhalb des Clip-Rechtecks
3 Ansonsten: weitere Untersuchung nötig
BEGIN
j:=0;
IF (n>2) THEN
i:=1;
pn+1:=p1;
WHILE (i<=n) DO
r:=pi;
IF (IstAufSichtbarerSeite(r,g)) THEN
j:=j+1; qj:=r;
i:=i+1;
s:=Schnitt(r,pi,g);
IF (s != unendlich) THEN
j:=j+1; qj:=s;
m:=j;
END
OpenGL- 2D Viewport
Transformation
Viewport-Transformation Ausschnitt
void
gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
Beschreibung
Erzeugt eine Matrix M für die Projektion zweidimensionaler Koordinaten auf
den Bildschirm und multipliziert die aktuelle Projektionsmatrix mit M. Das
Clip-Rechteck besitzt die extremen Eckpunkte (left, bottom)T und (right,top)T.
Beispiel
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 10.0, 0.0, 10.0);
Viewport-Transformation Viewport
void glViewport(GLint x, GLint y, Glsizei width, GLsizei
height)
Beschreibung
Definiert die linke untere Ecke sowie die Breite und Höhe des aktuellen
Viewports.
Ergenzender Code:
/****************************************************************************************/
/* Clippen von Linien an einem Fenster nach Cohen-Sutherland */
/****************************************************************************************/
private static final byte EMPTY = 0;
private static final byte LEFT = 1;
private static final byte RIGHT = 2; // 4-Bit-Bereichscodes
private static final byte BOTTOM = 4;
private static final byte TOP = 8;
private int xmin, xmax, ymin, ymax; // Clip-Fensterraender
private byte region_code( // liefert den region-code
Point P ) // fuer den Punkt P
{
byte c;
c = EMPTY;
if (P.x < xmin) c = LEFT; else
if (P.x > xmax) c = RIGHT;
if (P.y < ymin) c |= BOTTOM; else
if (P.y > ymax) c |= TOP;
return(c);
}
private void set_clip_window( // setzt die Variablen xmin, ymin, xmax, ymax
Point P, // anhand des Ursprungs P des Clip-Fensters
Point delta ) // und anhand seiner Breite/Hoehe delta
{
xmin = P.x; xmax = P.x + delta.x;
ymin = P.y; ymax = P.y + delta.y;
}
private boolean cohen_sutherland( // liefert true,
Point p1, Point p2, // falls die Gerade p1-p2 sichtbar ist
Point Q1, Point Q2) // liefert ggf. sichtbaren Teil Q1-Q2 zurueck
{
boolean finite_slope; // true falls Gerade p1-p2 nicht senkrecht laeuft
double slope = 0.0; // Steigung der Geraden p1-p2
byte C, C1, C2; // 4-Bit-Bereichs-Code
Point Q = new Point(); // zu berechnender Schnittpunkt mit Gerade
Point P1 = new Point(p1); // lokale
Point P2 = new Point(p2); // Variablen
finite_slope = (P1.x != P2.x);
if (finite_slope) slope = (double)(P2.y-P1.y)/(double)(P2.x-P1.x);
C1 = region_code(P1);
C2 = region_code(P2);
while ((C1 != EMPTY) || (C2 != EMPTY)) { // mind. ein Endpunkt noch ausserhalb
if ((C1&C2) != EMPTY) return(false); // beide auf derselben Seite ausserhalb
else
{
if (C1 == EMPTY) C = C2; else C = C1; // C ist ausserhalb. Berechne
// einen Schnittpunkt mit den
// verlaengerten Fensterkanten
if ((C & LEFT) != EMPTY) { // schneide mit linker Fenster-Kante
Q.x = xmin;
Q.y = (int)((Q.x-P1.x)*slope + P1.y);
} else
if ((C & RIGHT) != EMPTY){ // schneide mit rechter Fenster-Kante
Q.x = xmax;
Q.y = (int)((Q.x-P1.x)*slope + P1.y);
} else
if ((C & BOTTOM) != EMPTY) { // schneide mit unterer Fenster-Kante
Q.y = ymin;
if (finite_slope)
Q.x = (int)((Q.y-P1.y)/slope + P1.x); else
Q.x = P1.x;
}else
if ((C & TOP) != EMPTY) { // schneide mit oberer Fenster-Kante
Q.y = ymax;
if (finite_slope)
Q.x = (int)((Q.y-P1.y)/slope + P1.x); else
Q.x = P1.x;
}
if (C==C1) {
P1.x = Q.x; P1.y = Q.y; C1 = region_code (P1);
} else {
P2.x = Q.x; P2.y = Q.y; C2 = region_code (P2);
}
}
}
// uebergib Anfang und Ende des sichtbaren Teils
Q1.x=P1.x; Q1.y=P1.y;
Q2.x=P2.x; Q2.y=P2.y;
return(true);
}