2次元図形の幾何変換は、座標変換行列を用いた行列演算によって実現されます。本記事では、Turbo C環境下で平行移動、回転、拡大縮小、対称変換を実装する方法を解説します。各変換処理は、基準座標系を(540, 240)とし、三角形の頂点座標を変換して描画します。
回転処理
90度順時針回転を行列演算で実装します。以下はそのコード例です。
#include <stdio.h>
#include <graphics.h>
#include <math.h>
int baseX = 540;
int baseY = 240;
int vertex1_x = 540, vertex1_y = 240;
int vertex2_x = 650, vertex2_y = 150;
int vertex3_x = 560, vertex3_y = 120;
void drawTriangle() {
line(vertex1_x, vertex1_y, vertex2_x, vertex2_y);
line(vertex2_x, vertex2_y, vertex3_x, vertex3_y);
line(vertex1_x, vertex1_y, vertex3_x, vertex3_y);
}
void rotate90Clockwise() {
int rotationMatrix[3][3] = {{0, 1, 0}, {-1, 0, 0}, {0, 0, 1}};
double relativeCoords[3][3] = {
{0, 0, 1},
{vertex2_x - baseX, vertex2_y - baseY, 1},
{vertex3_x - baseX, vertex3_y - baseY, 1}
};
int transformed[3][2];
for (int i = 0; i < 3; i++) {
double x = 0.0, y = 0.0;
for (int j = 0; j < 3; j++) {
x += relativeCoords[i][j] * rotationMatrix[j][0];
y += relativeCoords[i][j] * rotationMatrix[j][1];
}
transformed[i][0] = (int)x + baseX;
transformed[i][1] = (int)y + baseY;
}
line(transformed[0][0], transformed[0][1], transformed[1][0], transformed[1][1]);
line(transformed[1][0], transformed[1][1], transformed[2][0], transformed[2][1]);
line(transformed[0][0], transformed[0][1], transformed[2][0], transformed[2][1]);
}
int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "e:\\TC\\bgi");
setcolor(4);
setbkcolor(0);
drawTriangle();
rotate90Clockwise();
getchar();
closegraph();
return 0;
}
平行移動処理
指定されたオフセット分だけ座標を移動します。以下は-100, -100の平移例です。
#include <stdio.h>
#include <graphics.h>
int baseX = 540;
int baseY = 240;
int vertex1_x = 540, vertex1_y = 240;
int vertex2_x = 650, vertex2_y = 150;
int vertex3_x = 560, vertex3_y = 120;
void drawTriangle() {
line(vertex1_x, vertex1_y, vertex2_x, vertex2_y);
line(vertex2_x, vertex2_y, vertex3_x, vertex3_y);
line(vertex1_x, vertex1_y, vertex3_x, vertex3_y);
}
void translate() {
int offsetX = -100;
int offsetY = -100;
int translationMatrix[3][3] = {{1, 0, 0}, {0, 1, 0}, {offsetX, offsetY, 1}};
int coordinates[3][3] = {
{vertex1_x, vertex1_y, 1},
{vertex2_x, vertex2_y, 1},
{vertex3_x, vertex3_y, 1}
};
int transformed[3][2];
for (int i = 0; i < 3; i++) {
transformed[i][0] = coordinates[i][0] * translationMatrix[0][0] +
coordinates[i][1] * translationMatrix[1][0] +
coordinates[i][2] * translationMatrix[2][0];
transformed[i][1] = coordinates[i][0] * translationMatrix[0][1] +
coordinates[i][1] * translationMatrix[1][1] +
coordinates[i][2] * translationMatrix[2][1];
}
line(transformed[0][0], transformed[0][1], transformed[1][0], transformed[1][1]);
line(transformed[1][0], transformed[1][1], transformed[2][0], transformed[2][1]);
line(transformed[0][0], transformed[0][1], transformed[2][0], transformed[2][1]);
}
int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "e:\\TC\\bgi");
setcolor(4);
setbkcolor(0);
drawTriangle();
translate();
getchar();
closegraph();
return 0;
}
拡大縮小処理
スケーリング係数を用いて図形を拡大または縮小します。以下は0.5倍の縮小例です。
#include <stdio.h>
#include <graphics.h>
#include <math.h>
int baseX = 540;
int baseY = 240;
int vertex1_x = 540, vertex1_y = 240;
int vertex2_x = 650, vertex2_y = 150;
int vertex3_x = 560, vertex3_y = 120;
void drawTriangle() {
line(vertex1_x, vertex1_y, vertex2_x, vertex2_y);
line(vertex2_x, vertex2_y, vertex3_x, vertex3_y);
line(vertex1_x, vertex1_y, vertex3_x, vertex3_y);
}
void scale() {
double scale = 0.5;
double scalingMatrix[3][3] = {{scale, 0, 0}, {0, scale, 0}, {0, 0, 1}};
double relativeCoords[3][3] = {
{0, 0, 1},
{vertex2_x - baseX, vertex2_y - baseY, 1},
{vertex3_x - baseX, vertex3_y - baseY, 1}
};
int transformed[3][2];
for (int i = 0; i < 3; i++) {
double x = 0.0, y = 0.0;
for (int j = 0; j < 3; j++) {
x += relativeCoords[i][j] * scalingMatrix[j][0];
y += relativeCoords[i][j] * scalingMatrix[j][1];
}
transformed[i][0] = (int)x + baseX;
transformed[i][1] = (int)y + baseY;
}
line(transformed[0][0], transformed[0][1], transformed[1][0], transformed[1][1]);
line(transformed[1][0], transformed[1][1], transformed[2][0], transformed[2][1]);
line(transformed[0][0], transformed[0][1], transformed[2][0], transformed[2][1]);
}
int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "e:\\TC\\bgi");
setcolor(4);
setbkcolor(0);
drawTriangle();
scale();
getchar();
closegraph();
return 0;
}
対称変換処理
y = x に関する対称変換を実装します。以下はそのコード例です。
#include <stdio.h>
#include <graphics.h>
int baseX = 540;
int baseY = 240;
int vertex1_x = 540, vertex1_y = 240;
int vertex2_x = 650, vertex2_y = 150;
int vertex3_x = 560, vertex3_y = 120;
void drawTriangle() {
line(vertex1_x, vertex1_y, vertex2_x, vertex2_y);
line(vertex2_x, vertex2_y, vertex3_x, vertex3_y);
line(vertex1_x, vertex1_y, vertex3_x, vertex3_y);
}
void reflect() {
int reflectionMatrix[3][3] = {{0, 1, 0}, {1, 0, 0}, {0, 0, 1}};
double relativeCoords[3][3] = {
{0, 0, 1},
{vertex2_x - baseX, vertex2_y - baseY, 1},
{vertex3_x - baseX, vertex3_y - baseY, 1}
};
int transformed[3][2];
for (int i = 0; i < 3; i++) {
double x = 0.0, y = 0.0;
for (int j = 0; j < 3; j++) {
x += relativeCoords[i][j] * reflectionMatrix[j][0];
y += relativeCoords[i][j] * reflectionMatrix[j][1];
}
transformed[i][0] = (int)x + baseX;
transformed[i][1] = (int)y + baseY;
}
line(transformed[0][0], transformed[0][1], transformed[1][0], transformed[1][1]);
line(transformed[1][0], transformed[1][1], transformed[2][0], transformed[2][1]);
line(transformed[0][0], transformed[0][1], transformed[2][0], transformed[2][1]);
}
int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "e:\\TC\\bgi");
setcolor(4);
setbkcolor(0);
drawTriangle();
reflect();
getchar();
closegraph();
return 0;
}