グラフィックス

グラフィック画面の座標に縛られないよう、最初から座標変換を導入します。

座標変換

MyDC クラスの、座標変換部分です。 図形の平行移動、拡大・縮小、回転ができるようにします。

#pragma once

//
//	MyDC クラス(デバイスコンテキスト)
//		MyDC.h
//

class MyDC{
protected:	
	HDC hdc;

	// 座標変換
	double a, b, c, d, p, q;
	int px(double x, double y){
	 	return (int)(a * x + c * y + p);
	}
	int py(double x, double y){
		return (int)(b * x + d * y + q);
	}

public:
	// コンストラクタ
	MyDC(HDC hDc){
		hdc = hDc;
		a = 1; b = 0;
		c = 0; d = 1;
		p = q = 0;
	}
	
	// 座標変換
	void Trans(double a1, double b1, double c1, double d1, double p1, double q1){
		a = a1;
		b = b1;
		c = c1;
		d = d1;
		p = p1;
		q = q1;
	}
	void Trans(double a1, double b1, double c1, double d1){
		a = a1;
		b = b1;
		c = c1;
		d = d1;
	}
	void Trans(double p1, double q1){
		p = p1;
		q = q1;
	}

	// 直線
	void MoveTo(double x, double y){
		MoveToEx(hdc, px(x, y), py(x, y), NULL);
	}
	
	void LineTo(double x, double y){
		::LineTo(hdc, px(x, y), py(x, y));
	}
};

解説

座標変換のための計算式です。

x' = ax + cy + p
y' = bx + dy + q

内容は簡単です。

-------------------------------------
原点 (0, 0) から考えて、
  点 (1, 0) は点 (a, b)へ、
  点 (0, 1) は点 (c, d) に移ります。
これで、拡大・縮小・回転します。そして、
  原点 (0, 0) は点 (p, q) に移ります。
これで、平行移動します。
--------------------------------------

メンバーは、a, b, c, d, p, q です。 値は実数値の、double 型にします。

private:
	double a, b, c, d, p, q;

コンストラクタです。 これは、クラスを宣言するとき、1度だけ実行します。 ですから、メンバーの初期化に使えます。 最初は、変換はしない値を代入します。

public:	                            
// コンストラクタ
	a = 1; 	b = 0;
	c = 0; 	d = 1;
	p = q = 0;

メンバーに値を代入するメソッド Trans です。 Trans が幾つもあります。 このように、引数が異なれば幾つでも作れます。 値は返さないので、void を付けます。

// 座標変換
void Trans(double a1, double b1, double c1, double d1, double p1, double q1){
	a = a1;
	b = b1;
	c = c1;
	d = d1;
	p = p1;
	q = q1;
}

座標を計算するメソッドです。 上の計算式となっています。 返す値は、return の後ろに書きます。 x座標を返すのが、px で、y座標を返すのは、py です。

// 座標を変換
int px(double x, double y) {
 	return (int)(a * x + c * y + p);
}

int py(double x, double y) {
	return (int)(b * x + d * y + q);
}

使用例(win143)

"MyApp.h" です。 青い部分だけ見てください。

//
//	MyApp.h
//

class MyApp : public MyMainWnd{
public:
	// WM_PAINT
	void wmPaint(HDC hdc){
		MyDC g(hdc);
		
		g.Trans(50, 0, 0, 50);
		// 直線を描く----------------------------
		g.MoveTo(0, 0);
		g.LineTo(3, 3);
	}
};

実行画面です。

解説

点(0, 0) と点(3, 3) を線で結んでいます。 しかし、スクリーンの座標はドット単位ですから、座標変換しなければ短い線となってしまいます。 そこで、次のようにしています。

		g.Trans(50, 0, 0, 50);

これより、 点(1, 0) は、点(50, 0) に、点(0, 1) は点(0, 50) に移ります。 結局、縦横に50倍に拡大したことになります。 ですから、長い線になりました。

この他にも、スクリーン座標のy座標は、下に向かって増えていきますが、逆にすることもできます。 たとえば、点(0, 1) を点(0, -1) のようにします。

		g.Trans(1, 0, 0, -1);

このように、スクリーン座標から開放されます。


[前] [目次] [次]