Introduction
In computer graphics, affine transformations are very important. With beginners, trying to implement an affine transformation in a programming language (C/C++)
is really a challenge. So this article will show you guys some simple examples that apply
affine transformations. These were written in C++, and include:
- A rotation triangle inside a circle
- A fan rotation
Background
In geometry, an affine transformation or affine map or an affinity (from the Latin, affinis, "connected with") is a transformation which preserves straight
lines (i.e., all points lying on a line initially still lie on a line after transformation) and ratios of distances between points lying
on a straight line (e.g., the midpoint of a line segment remains the midpoint after transformation).
It does not necessarily preserve angles or lengths, but does have the property that sets of parallel lines will remain parallel to each other after an affine transformation.
Examples of affine transformations include translation, geometric contraction, expansion, homothety, reflection, rotation, shear mapping, similarity transformation,
and spiral similarities and compositions of them.
An affine transformation is equivalent to a linear transformation followed by a translation.
Example 1: Rotation Triangle
Note: The IDE for usage is Dev-C++. After installing this IDE successfully, you need to do something to build, and run graphic programs in it.
Refer to this.
Firstly, we have to define Affine
:
#include<math.h>
typedef float Point[2];
typedef float Affine[3][3];
void ptoa(Point A,Affine &B){
B[0][0]=A[0];
B[0][1]=A[1];
B[0][2]=1;
}
void MatMul(Affine A,Affine B,Affine &C,int m,int n){
int i,j,k;
for(i=0;i<m;i++)
for(j=0;j<n;j++){
C[i][j]=0;
for(k=0;k<n;k++)
C[i][j]+=A[i][k]*B[k][j];
}
}
void Rotate(Affine &T,float fi){
T[0][0]=cos(fi);
T[0][1]=sin(fi);
T[0][2]=0;
T[1][0]=-sin(fi);
T[1][1]=cos(fi);
T[1][2]=0;
T[2][0]=0;
T[2][1]=0;
T[2][2]=1;
}
void Move(Affine &T,float x,float y){
T[0][0]=1;
T[0][1]=0;
T[0][2]=0;
T[1][0]=0;
T[1][1]=1;
T[1][2]=0;
T[2][0]=x;
T[2][1]=y;
T[2][2]=1;
}
The main class is as below:
#include <stdio.h>
#include <graphics.h>
#include "affine.h"
#define RAD 0.017452
main(){
int gd=0,gm=0,n=0;
int k[50];
Point x={300,200},y;
Affine Tz,Ty,Tzz,Tx,Txx,Tyy,Tu,Tuu,T;
initgraph(&gd,&gm,"");
ptoa(x,Tx);
Move(T,-x[0],-x[1]);MatMul(Tx,T,Txx,1,3);
Move(T,0,100);MatMul(Txx,T,Ty,1,3);
Rotate(T,120*RAD);MatMul(Ty,T,Tz,1,3);
Rotate(T,120*RAD);MatMul(Tz,T,Tu,1,3);
Move(T,x[0],x[1]);
MatMul(Txx,T,Tx,1,3);
MatMul(Ty,T,Tyy,1,3);
MatMul(Tz,T,Tzz,1,3);
MatMul(Tu,T,Tuu,1,3);
circle(int(x[0]),int(x[1]),101);
setwritemode(XOR_PUT);
while(!kbhit()){
Move(T,-x[0],-x[1]);
MatMul(Tyy,T,Ty,1,3);
MatMul(Tzz,T,Tz,1,3);
MatMul(Tuu,T,Tu,1,3);
Rotate(T,n*RAD);
MatMul(Ty,T,Tyy,1,3);
MatMul(Tz,T,Tzz,1,3);
MatMul(Tu,T,Tuu,1,3);
Move(T,x[0],x[1]);
MatMul(Tyy,T,Ty,1,3);
MatMul(Tzz,T,Tz,1,3);
MatMul(Tuu,T,Tu,1,3);
Tyy[0][0]=Ty[0][0];Tyy[0][1]=Ty[0][1];
Tzz[0][0]=Tz[0][0];Tzz[0][1]=Tz[0][1];
Tuu[0][0]=Tu[0][0];Tuu[0][1]=Tu[0][1];
k[0]=Ty[0][0];k[1]=Ty[0][1];
k[2]=Tz[0][0];k[3]=Tz[0][1];
k[4]=Tu[0][0];k[5]=Tu[0][1];
k[6]=Ty[0][0];k[7]=Ty[0][1];
setcolor(LIGHTRED);
drawpoly(4,k);
delay(50);
drawpoly(4,k);
n+=1;
}
getch();
closegraph();
}
That's it. Let's see the result:
Example 2: Rotation Fan
This example shows how we can have a "moving" object but without using
Affine
. Let's explore the code below:
#include<graphics.h>
#include<conio.h>
#include<math.h>
#include<dos.h>
#define RAD 0.01745329
int main()
{
int r,tx,ty; int rc,rq,d;
int gd =0,gm,i;
int c1[8];
int c2[8];
int c3[8];
initgraph(&gd,&gm,"");
tx=getmaxx()/2;
ty=getmaxy()/3;
c1[0]=c1[6]=tx;c1[1]=c1[7]=ty;
c2[0]=c2[6]=tx;c2[1]=c2[7]=ty;
c3[0]=c3[6]=tx;c3[1]=c3[7]=ty;
d=0;
r=100;
rq=r-20;
rc=30;
circle(tx,ty,r);
rectangle(tx-2,ty+r,tx+2,ty+r*2);
rectangle(tx-10,ty+r*2,tx+10,ty+r*3);
rectangle(tx-50,ty+r*3,tx+50,ty+r*3+20);
while(!kbhit())
{
setcolor(BLACK);
c1[2]=tx+rq*sin(d*RAD);
c1[3]=ty-rq*cos(d*RAD);
c1[4]=tx+rq*sin((d+rc)*RAD);
c1[5]=ty-rq*cos((d+rc)*RAD);
c2[2]=tx+rq*sin((d+120)*RAD);
c2[3]=ty-rq*cos((d+120)*RAD);
c2[4]=tx+rq*sin((d+120+rc)*RAD);
c2[5]=ty-rq*cos((d+120+rc)*RAD);
c3[2]=tx+rq*sin((d+240)*RAD);
c3[3]=ty-rq*cos((d+240)*RAD);
c3[4]=tx+rq*sin((d+240+rc)*RAD);
c3[5]=ty-rq*cos((d+240+rc)*RAD);
setfillstyle(2,BLUE);
fillpoly(4,c1);
fillpoly(4,c2);
fillpoly(4,c3);
delay(5);
setfillstyle(2,BLACK);
fillpoly(4,c1);
fillpoly(4,c2);
fillpoly(4,c3);
d+=2;
if(d==360) d=0;
}
getch();
closegraph();
return 0;
}
Got the result:
References
History
- First version published on Dec 28, 2012