Вы находитесь на странице: 1из 16

TRANSFORMATIONS IN 2 DIMENSIONS

One of the most common and important tasks in computer graphics is to transform the coordinates ( position, orientation, and size ) of either objects within the graphical scene or the camera that is viewing the scene.

It is also frequently necessary to transform coordinates from one coordinate system to another, ( e.g. world coordinates to viewpoint coordinates to screen coordinates. )

All of these transformations can be efficiently and succintly handled using some simple matrix representations, which we will see can be particularly useful for combining multiple transformations into a single composite transform matrix.

We will look first at simple translation, scaling, and rotation in 2D, then extend our results to 3D, and finally see how multiple transformations can be easily combined into a composite transform.
TRANSLATION IN 2D
point (X,Y) is to be translated by amount Dx and Dy to a new location (X',Y')

X' = Dx + X Y' = Dy + Y or P' = T + P where


_ P' = | | _ T = | | _ P = | | _ X' | Y' | _ Dx | Dy | _ X | Y | -

SCALING IN 2D
Point (X,Y) is to be scaled by amount Sx and Sy to location (X',Y') X' = Sx * X Y' = Sy * Y or P' = S * P where _ P' = | | _ S = | | _ P = | | _ X' | Y' | _ Sx 0 _ X Y | | 0 | Sy | -

Scaling is performed about the origin (0,0) not about the center of the line/polygon/whatever Scale > 1 enlarge the object and move it away from the origin. Scale = 1 leave the object alone Scale< 1 shrink the object and move it towards the origin. Uniform scaling: Sx = Sy Differential scaling Sx != Sy -> alters proportions

ROTATION IN 2D
Point (X,Y) is to be rotated about the origin by angle theta to location (X',Y') X' = X * cos(theta) - Y * sin(theta) Y' = X * sin(theta) + Y *cos(theta) note that this does involve sin and cos which are much more costly than addition or multiplication or P' = R * P where _ _ P' = | X' | | Y' | - _ _ R = | cos(theta) -sin(theta) | | sin(theta) cos(theta) | _ _ P =| X | | Y | - Rotation is performed about the origin (0,0) not about the center of the line/polygon/whatever

Derivation of the 2D Rotation Equations


Where does this matrix come from? (X,Y) is located r away from (0,0) at an angle of phi from the X axis. (X',Y') is located r away from (0,0) at an angle of theta+phi from the X axis. Since rotation is about the origin, (X',Y') must be the same distance from the origin as (X,Y). from trigonometry we have: X = r * cos(phi) Y = r * sin(phi) and X' = r * cos(theta+phi) Y' = r * sin(theta+phi) Now making use of the following trigonometric identities: cos(a+b) = cos(a) * cos(b) - sin(a) * sin(b) sin(a+b) = sin(a) * cos(b) + cos(a) * sin(b) and substituting in for the above equations for X' and Y', we get: X' = r * cos(theta) * cos(phi) - r * sin(theta) * sin(phi) Y' = r * sin(theta) * cos(phi) + r * cos(theta) * sin(phi) Then we substitute in X and Y from their definitions above, and the final result simplifies to: X' = X * cos(theta) - Y * sin(theta) Y' = X * sin(theta) + Y * cos(theta)

HOMOGENEOUS COORDINATES IN 2 DIMENSIONS


Scaling and rotations are both handled using matrix multiplication, which can be combined as we will see shortly. The translations cause a difficulty, however, since they use addition instead of multiplication. We want to be able to treat all 3 transformations (translation, scaling, rotation) in the same way - as multiplications. The solution is to give each point a third coordinate (X, Y, W), which will allow translations to be handled as a multiplication also. ( Note that we are not really moving into the third dimension yet. The third coordinate is being added to the mathematics solely in order to combine the addition and multiplication of 2-D coordinates. ) Two triples (X,Y,W) and (X',Y',W') represent the same point if they are multiples of each other e.g. (1,2,3) and (2,4,6). At least one of the three coordinates must be nonzero. If W is 0 then the point is at infinity. This situation will rarely occur in practice in computer graphics. If W is nonzero we can divide the triple by W to get the cartesian coordinates of X and Y which will be identical for triples representing the same point (X/W, Y/W, 1). This step can be considered as mapping the point from 3-D space onto the plane W=1.

Conversely, if the 2-D cartesian coordinates of a point are known as ( X, Y ), then the homogenous coordinates can be given as ( X, Y, 1 ) So, how does this apply to translation, scaling, and rotation of 2D coordinates?

Translation of 2D Homogenous Coordinates point (X,Y) is to be translated by amount Dx and Dy to location (X',Y') X' = Dx + X Y' = Dy + Y or P' = T * P where _ P' = | | | T _ X' | Y' | 1 | _ _ = | 1 0 Dx | = T(Dx,Dy) | 0 1 Dy | | 0 0 1 | _ _ = | X | | Y | | 1 | -

NB: Translation is now a multiplication instead of an addition

Scaling of 2D Homogenous Coordinates


P' = S * P where _ _ P' = | X' | | Y' | | 1 | _ _ S = | Sx 0 0 | = S(Sx,Sy) | 0 Sy 0 | | 0 0 1 | _ _ P = | X | | Y | | 1 | Rotation of 2D Homogenous Coordinates P' = R * P where _ _ P' = | X' | | Y' | | 1 | _ _ R = | cos(theta) -sin(theta) 0 | = R(theta) | sin(theta) cos(theta) 0 | | 0 0 1 | -

_ _ = | X | | Y | | 1 | -

Composition of 2D Transformations
There are many situations in which the final transformation of a point is a combination of several ( often many ) individual transformations. For example, the position of the finger of a robot might be a function of the rotation of the robots hand, arm, and torso, as well as the position of the robot on the railroad train and the position of the train in the world, and the rotation of the planet around the sun, and . . . Applying each transformation individually to all points in a model would take a lot of time. Instead of applying several transformations matrices to each point we want to combine the transformations to produce 1 matrix which can be applied to each point. In the simplest case we want to apply the same type of transformation (translation, rotation, scaling) more than once. Translation is additive as expected Scaling is multiplicative as expected Rotation is additive as expected But what if we want to combine different types of transformations?

A very common reason for doing this is to rotate a polygon about an arbitrary point (e.g. the center of the polygon) rather than around the origin. Translate so that P1 is at the origin T(-Dx,-Dy) Rotate R(theta) Translate so that the point at the origin is at P1 T(Dx,Dy) Note the order of operations here is right to left:

P' = T(Dx,Dy) * R(theta) * T(-Dx,-Dy) * P i.e. P' = T(Dx,Dy) * { R(theta) * [ T(-Dx,-Dy) * P ] } i.e. P' = [ T(Dx,Dy) * R(theta) * T(-Dx,-Dy) ] * P
The matrix that results from these 3 steps can then be applied to all of the points in the polygon. Another common reason for doing this is to scale a polygon about an arbitrary point (e.g. the center of the polygon) rather than around the origin. Translate so that P1 is at the origin Scale Translate so that the point at the origin is at P1 How do we determine the 'center' of the polygon?

Specifically define the center (e.h. the center of mass) Average the location of all the vertices Take the center of the bounding box of the polygon

Window to Viewport
Generally user's prefer to work in world-coordinates. 1 unit can be 1 micron 1 unit can be 1 meter 1 unit can be 1 kilometer 1 unit can be 1 mile These coordinates must then be translated to screen coordinates to be displayed in a rectangular region of the screen called the viewport The objects are in world coordinates (with n dimensions) The viewport is in screen coordinates (with n=2) Want one matrix that can be applied to all points: rectangular area of world from (Xmin,Ymin) to (Xmax,Ymax) world-coordinate window rectangular area of screen from (Umin,Vmin) to (Umax,Vmax) viewport need to rescale the world-coordinate rectangle to the screen rectangle 1. translate world-coordinate window to the origin of the world coordinate system. 2. rescale the window to the size and aspect ratio of the viewport. 3. translate the viewport to its position on the screen in the screen coordinate system.

Pscreen = M * Pworld M = T(Umin,Vmin) * S(deltaU/deltaX, deltaV/deltaY) * T(Xmin, -Ymin)


****************************************************************************

Source Code : 2D Transformations Using OpenGL


#include #include #include #include #include #include <windows.h> <math.h> <GL/glut.h> <GL/glu.h> <stdio.h> <stdlib.h>

typedef float Matrix3x3 [3][3]; Matrix3x3 theMatrix; int NEdges; float ptsIni[20][2]; float ptsFin[20][2]; float refpt[2]; float RotAngle; float TransDistX,TransDistY; float ScaleX,ScaleY; int choice,choiceRef,choiceShear; float slope,yIntercept; float shearValue; void matrixSetIdentity(Matrix3x3 m) // Initialises the matrix as Unit Matrix { int i, j; for (i=0; i<3; i++) for (j=0; j<3; j++) m[i][j] = (i == j); } void matrixPreMultiply(Matrix3x3 a , Matrix3x3 b) // Multiplies matrix a times b, putting result in b { int i,j; Matrix3x3 tmp; for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) tmp[i][j] = a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]; for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) theMatrix[i][j] = tmp[i][j]; } void Translate(int tx, int ty) { Matrix3x3 m; matrixSetIdentity(m); m[0][2] = tx;

m[1][2] = ty; matrixPreMultiply(m, theMatrix); } void Scale(float sx , float sy) { Matrix3x3 m; matrixSetIdentity(m); m[0][0] = sx; m[0][2] = (1 - sx)*refpt[0]; m[1][1] = sy; m[1][2] = (1 - sy)*refpt[1]; matrixPreMultiply(m , theMatrix); } void Rotate(float a) { Matrix3x3 m; matrixSetIdentity(m); a = a*22/1260; m[0][0] = cos(a); m[0][1] = -sin(a) ; m[0][2] = refpt[0]*(1 - cos(a)) + refpt[1]*sin(a); m[1][0] = sin(a); m[1][1] = cos(a); m[1][2] = refpt[1]*(1 - cos(a)) - refpt[0]*sin(a); matrixPreMultiply(m , theMatrix); } void Reflect(int xy) { Matrix3x3 m; matrixSetIdentity(m); if(xy == 2) m[1][1] = -1; if(xy == 3) m[0][0] = -1; matrixPreMultiply(m , theMatrix); } void Shear(int xy) { Matrix3x3 m; matrixSetIdentity(m); if(xy == 1) m[0][1] = shearValue; if(xy == 2) m[1][0] = shearValue; matrixPreMultiply(m , theMatrix); } void TransformPoints(void) { int k; float tmp ; for (k = 0 ; k<NEdges && k<20 ; k++) { ptsFin[k][0] = theMatrix[0][0]*ptsIni[k][0] + theMatrix[0][1]*ptsIni[k][1] + theMatrix[0][2]; ptsFin[k][1] = theMatrix[1][0]*ptsIni[k][0] + theMatrix[1][1]*ptsIni[k][1] + theMatrix[1][2]; } }

void display(void) { glClear (GL_COLOR_BUFFER_BIT); glColor3f (0.0, 0.0, 0.0); // Set the color to BLACK glBegin(GL_LINES); // Plotting X-Axis glVertex2s(-1000 ,0); glVertex2s( 1000 ,0); glEnd(); glBegin(GL_LINES); // Plotting Y-Axis glVertex2s(0 ,-1000); glVertex2s(0 , 1000); glEnd(); glColor3f (1.0, 0.0, 0.0); // Set the color to RED int PlotCt; glBegin(GL_POLYGON); // Plot the Initial Polygon for(PlotCt=0 ; PlotCt<NEdges ; PlotCt++) { glVertex2s(ptsIni[PlotCt][0],ptsIni[PlotCt][1]); } glEnd(); matrixSetIdentity(theMatrix); switch(choice) { case 1: Scale(ScaleX, ScaleY); Rotate(RotAngle); Translate(TransDistX , TransDistY); break; case 2: Translate(TransDistX , TransDistY); break; case 3: Rotate(RotAngle); break; case 4: Scale(ScaleX, ScaleY); break; case 5: switch(choiceRef) { case 1 : refpt[0]=0.0; refpt[1]=0.0; Rotate(180); break; case 2 : Reflect(2); break; case 3 : Reflect(3); break; case 4 : Translate(slope/yIntercept , -yIntercept); Rotate(-1260*atan(slope)/22); Reflect(2); Rotate(1260*atan(slope)/22); Translate(-slope/yIntercept , yIntercept); glBegin(GL_LINES); glVertex2s(-1000 ,-slope*1000 + yIntercept); glVertex2s( 1000 , slope*1000 + yIntercept); glEnd(); break; } case 6: Shear(choiceShear); break; } TransformPoints(); glColor3f (0.0, 1.0, 0.0); // Set the color to GREEN

glBegin(GL_POLYGON); for(PlotCt=0 ; PlotCt<NEdges ; PlotCt++) // Plot the Final Polygon { glVertex2s(ptsFin[PlotCt][0],ptsFin[PlotCt][1]); } glEnd(); glFlush(); } void init(void) { glClearColor (1.0, 1.0, 1.0, 1.0); // Set the Background color to WHITE glOrtho(-200.0, 200.0, -200.0, 200.0, -1.0, 1.0); // Set the no. of Co-ordinates along X & Y axes and their gappings } int main (int argc, char *argv) { glutInit(&argc, &argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (750, 750); glutInitWindowPosition (0, 0); glutCreateWindow (" Basic Transformations "); init (); printf("Enter the no. of Vertices of polygon:\n=> "); scanf("%d",&NEdges); printf("Enter %d Co-ordinate pairs \n",NEdges); int PlotCt; for(PlotCt=0 ; PlotCt<NEdges ; PlotCt++) scanf("%f %f",&ptsIni[PlotCt][0],&ptsIni[PlotCt][1]); printf("Enter your choice number:\n1.Composite TransFormation\n2.Translation\n3.Rotation\n4.Scaling\n5.Reflection\n6.Shearing\n=>"); scanf("%d",&choice); switch(choice) { case 1: printf("Enter reference point Co-ordinates:\n=>"); scanf("%f %f",&refpt[0],&refpt[1]); printf("Enter Angle of Rotation\n=>"); scanf("%f",&RotAngle); printf("Enter translation along X & Y\n=>"); scanf("%f%f",&TransDistX , &TransDistY); printf("Enter Scaling ratios along X & Y\n=>"); scanf("%f%f",&ScaleX , &ScaleY); break; case 2: printf("Enter translation along X & Y\n=>"); scanf("%f%f",&TransDistX , &TransDistY); break; case 3: printf("Enter Angle of Rotation\n=>"); scanf("%f",&RotAngle); printf("Enter reference point Co-ordinates:\n=>"); scanf("%f %f",&refpt[0],&refpt[1]); break; case 4: printf("Enter Scaling ratios along X & Y\n=>"); scanf("%f%f",&ScaleX , &ScaleY); break; case 5: printf("Enter your choice number for Reflection about:\n1.Origin\n 2.Xaxis\n 3.Y-axis\n 4.y = mx+c\n=>"); scanf("%d",&choiceRef); if(choiceRef == 4)

{ printf("Enter m & c: \n=>"); scanf("%f %f",&slope,&yIntercept); } break; case 6: printf("Enter your choice number to shear about:\n1.x-axis\n 2.y-axis\n=>"); scanf("%d",&choiceShear); printf("Enter shear value:\n=>"); scanf("%f",&shearValue); break; default: printf("You are an Asshole!!!\n"); return 0; } glutDisplayFunc(display); glutMainLoop(); return 0; }

Вам также может понравиться