#14 ふれてみよう高校数学 幾何と図形

複素数平面と変換

複素数の乗算 = 幾何変換

「紙の上の図形を、ハサミで切り取ってクルっと回してサイズを変えて貼り直す」——これが複素数の乗算が持つ幾何的な意味です。

前回、複素数の積では「絶対値の積、偏角の和」になることを学びました:

z1z2=r1r2ei(θ1+θ2)z_1 z_2 = r_1 r_2 \, e^{i(\theta_1 + \theta_2)}

これを幾何的に読み直すと:

複素数 zz に複素数 w=seiϕw = se^{i\phi} を掛けることは、 zz を原点を中心に角 ϕ\phi だけ回転し、ss 倍に拡大縮小する変換

です——「掛け算一発で回転と拡大縮小が同時に実現できる」のが複素数の強みです。

特別な乗数

「どの複素数を掛けると何が起きるか」——代表的なパターンを覚えておきましょう:

乗数 ww効果
ii90°90° 回転(反時計回り)
1-1180°180° 回転(点対称)
i-i270°270° 回転(または 90°-90°
eiθe^{i\theta}θ\theta の回転(大きさ変わらず)
rr (実数)rr 倍の拡大縮小(回転なし)
reiθre^{i\theta}θ\theta 回転 + rr 倍拡大縮小

ii を掛けると 90° 回転する」——具体例で確認しましょう。

z=1+iz = 1 + iw=iw = i を掛けると:

iz=i(1+i)=i+i2=i1=1+iiz = i(1+i) = i + i^2 = i - 1 = -1 + i

(1,1)(1,1)(1, 1) \to (-1, 1):確かに 90°90° 回転しています——「右上にあった点が左上に移動」しました。

インタラクティブ図解:複素数変換

マウスを左右に動かすと乗数 ww の偏角が変わり、点群が回転します。マウスを上下に動かすと絶対値(スケール)が変わります。

マウス左右=回転角、上下=拡大率。点群が複素数の乗算で変換される

var OX = 300, OY = 190, SC = 55;

// 図形の点(文字 'F' に似た形)
var shape = [
[0,0],[1.5,0],[1.5,0.3],[0.3,0.3],[0.3,0.8],[1.2,0.8],[1.2,1.1],
[0.3,1.1],[0.3,1.8],[1.5,1.8],[1.5,2.1],[0,2.1]
];

function mulC(re, im, wr, wi) {
return [re*wr - im*wi, re*wi + im*wr];
}

function toS(re, im) { return [OX + re*SC, OY - im*SC]; }

function loop() {
ctx.clearRect(0, 0, W, H);

// w の偏角と絶対値
var phi = ((mx / W) * 2 - 1) * Math.PI; // -π to π
var scale = 0.3 + (1 - my/H) * 1.7; // 0.3 to 2.0
if (scale < 0.3) scale = 0.3;

var wr = scale * Math.cos(phi);
var wi = scale * Math.sin(phi);

// グリッド
ctx.strokeStyle = '#161b22'; ctx.lineWidth = 1;
for (var gx=-5;gx<=5;gx++){ctx.beginPath();ctx.moveTo(OX+gx*SC,0);ctx.lineTo(OX+gx*SC,H);ctx.stroke();}
for (var gy=-3;gy<=4;gy++){ctx.beginPath();ctx.moveTo(0,OY-gy*SC);ctx.lineTo(W,OY-gy*SC);ctx.stroke();}
ctx.strokeStyle='#30363d';ctx.lineWidth=1.5;
ctx.beginPath();ctx.moveTo(0,OY);ctx.lineTo(W,OY);ctx.stroke();
ctx.beginPath();ctx.moveTo(OX,0);ctx.lineTo(OX,H);ctx.stroke();
ctx.fillStyle='#8b949e';ctx.font='12px sans-serif';
ctx.fillText('Re',W-24,OY-8);ctx.fillText('Im',OX+8,14);

// 単位円
ctx.beginPath(); ctx.arc(OX, OY, SC, 0, Math.PI*2);
ctx.strokeStyle = '#30363d'; ctx.lineWidth = 1; ctx.setLineDash([3,3]); ctx.stroke(); ctx.setLineDash([]);

// w の表示
var wp = toS(wr, wi);
ctx.beginPath(); ctx.moveTo(OX, OY); ctx.lineTo(wp[0], wp[1]);
ctx.strokeStyle = '#ffa657'; ctx.lineWidth = 2; ctx.stroke();
ctx.beginPath(); ctx.arc(wp[0], wp[1], 5, 0, Math.PI*2);
ctx.fillStyle = '#ffa657'; ctx.fill();
ctx.fillStyle = '#ffa657'; ctx.font = 'bold 12px sans-serif';
ctx.fillText('w', wp[0]+8, wp[1]-8);

// 偏角の弧
ctx.beginPath(); ctx.arc(OX, OY, 22, -phi, 0, phi < 0);
ctx.strokeStyle = '#ffa65780'; ctx.lineWidth = 2; ctx.stroke();

// 元の図形(青)
ctx.beginPath();
// 中心を (-2, -1) に配置
var offR = -2, offI = -1;
var start = toS(shape[0][0]+offR, shape[0][1]+offI);
ctx.moveTo(start[0], start[1]);
for (var i=1; i<shape.length; i++) {
  var sp = toS(shape[i][0]+offR, shape[i][1]+offI);
  ctx.lineTo(sp[0], sp[1]);
}
ctx.closePath();
ctx.strokeStyle = '#58a6ff'; ctx.lineWidth = 2; ctx.stroke();
ctx.fillStyle = '#58a6ff20'; ctx.fill();

// 変換後の図形(緑)
ctx.beginPath();
var tp = mulC(shape[0][0]+offR, shape[0][1]+offI, wr, wi);
var ts = toS(tp[0], tp[1]);
ctx.moveTo(ts[0], ts[1]);
for (var j=1; j<shape.length; j++) {
  var qr = shape[j][0]+offR, qi = shape[j][1]+offI;
  var tq = mulC(qr, qi, wr, wi);
  var tqp = toS(tq[0], tq[1]);
  ctx.lineTo(tqp[0], tqp[1]);
}
ctx.closePath();
ctx.strokeStyle = '#56d364'; ctx.lineWidth = 2.5; ctx.stroke();
ctx.fillStyle = '#56d36420'; ctx.fill();

// 対応点の接続(いくつかの頂点)
for (var k=0; k<shape.length; k+=3) {
  var or_ = shape[k][0]+offR, oi_ = shape[k][1]+offI;
  var osp = toS(or_, oi_);
  var tr_ = mulC(or_, oi_, wr, wi);
  var trp = toS(tr_[0], tr_[1]);
  ctx.beginPath(); ctx.moveTo(osp[0],osp[1]); ctx.lineTo(trp[0],trp[1]);
  ctx.strokeStyle = '#8b949e40'; ctx.lineWidth = 1; ctx.setLineDash([3,2]); ctx.stroke(); ctx.setLineDash([]);
}

// 凡例
ctx.fillStyle = '#58a6ff'; ctx.font = 'bold 12px sans-serif';
ctx.fillText('元の図形 z', OX - 4*SC, OY + 3.5*SC < H ? OY + 3.5*SC : H - 20);
ctx.fillStyle = '#56d364';
ctx.fillText('変換後 w·z', OX + 1*SC, OY - 3.5*SC > 0 ? OY - 3.5*SC : 20);

// 情報パネル
ctx.fillStyle = '#0d1117e0';
ctx.fillRect(8, 8, 270, 110);
ctx.strokeStyle = '#30363d'; ctx.lineWidth = 1;
ctx.strokeRect(8, 8, 270, 110);

ctx.font = '13px monospace';
ctx.fillStyle = '#ffa657';
ctx.fillText('w = ' + wr.toFixed(2) + (wi>=0?' + ':' - ') + Math.abs(wi).toFixed(2) + 'i', 16, 28);
ctx.fillStyle = '#e6edf3';
ctx.fillText('|w| = ' + scale.toFixed(2) + '  (スケール)', 16, 48);
ctx.fillText('arg(w) = ' + (phi*180/Math.PI).toFixed(1) + '°  (回転角)', 16, 68);
ctx.fillStyle = '#56d364';
ctx.fillText('乗算 w·z = 回転 + 拡大', 16, 88);
ctx.fillStyle = '#8b949e';
ctx.fillText('左右=回転、上下=スケール', 16, 106);

requestAnimationFrame(loop);
}
loop();

一次変換としての複素数

「移動して・回して・大きさを変える」——これらを同時に行う変換を 1 つの式で表せます。

複素数を使った一次変換 w=az+bw = az + ba,ba, b は複素数定数)は次の合成です:

  1. zazz \to aza|a| 倍に拡大縮小 + arg(a)\arg(a) 回転——「aa を掛ける」
  2. ww+bw \to w + bbb だけ平行移動——「bb を足す」

例:90°90° 回転+(1,1)(1, 1) 平行移動

w=iz+(1+i)w = iz + (1+i)

  • iziz90°90° 回転——「ii を掛けると 90° 回る」
  • +(1+i)+(1+i)(1,1)(1, 1) 平行移動——「点 (1,1)(1,1) に対応する複素数を足す」

原点以外を中心とした回転

「公園の木を中心に、周りをぐるっと回る」——原点以外を中心にした回転も複素数で表せます。

α\alpha を中心に角 θ\theta 回転する変換:

wα=eiθ(zα)w - \alpha = e^{i\theta}(z - \alpha) w=eiθ(zα)+αw = e^{i\theta}(z - \alpha) + \alpha

ステップ:

  1. α\alpha だけ平行移動(zαz - \alpha)して原点を中心に——「α\alpha を原点に持ってくる」
  2. eiθe^{i\theta} を掛けて回転——「原点中心の回転」
  3. α\alpha だけ逆平行移動して戻す——「元の位置に戻す」

メビウス変換(発展)

w=az+bcz+d(adbc0)w = \frac{az + b}{cz + d} \quad (ad - bc \neq 0)

この変換は「円や直線を円や直線に写す」という美しい性質を持ちます(円と直線を統一的に「一般化された円」と見なす)——「直線は半径無限大の円」と考えると、両者を同一視できます。

高校範囲を超えますが、フラクタルや双曲幾何学の基盤です。

複素数変換の応用例

正三角形の頂点を生成

「等間隔に 3 等分した位置に点を打つ」——120°=2π/3120° = 2\pi/3 ずつ回転を繰り返すだけです:

頂点 z0=1z_0 = 1120°=2π/3120° = 2\pi/3 ずつ回転:

z1=ei2π/31=12+32iz_1 = e^{i \cdot 2\pi/3} \cdot 1 = -\frac{1}{2} + \frac{\sqrt{3}}{2}i z2=ei4π/31=1232iz_2 = e^{i \cdot 4\pi/3} \cdot 1 = -\frac{1}{2} - \frac{\sqrt{3}}{2}i

3 点は単位円上に等間隔に並びます——「正三角形の頂点は単位円を 3 等分する点」です。

余弦定理の複素数版

三角形の頂点を α,β,γ\alpha, \beta, \gamma とするとき:

αγ2=αβ2+βγ22Re{(αβ)(βγ)}|\alpha - \gamma|^2 = |\alpha - \beta|^2 + |\beta - \gamma|^2 - 2\text{Re}\{(\alpha-\beta)\overline{(\beta-\gamma)}\}

これは CACB=CACBcosC\vec{CA} \cdot \vec{CB} = |\vec{CA}||\vec{CB}|\cos C と同じ内容です——「ベクトルの内積と複素数の実部が対応している」ことが分かります。

まとめ

  • w=reiϕw = re^{i\phi} を掛ける = rr 倍拡大縮小 + ϕ\phi 回転——「乗算一発で回転と拡大縮小が実現」
  • w=az+bw = az + b は拡大・回転・平行移動の合成——「3 つの変換をまとめた強力な公式」
  • 原点以外を中心とした回転:w=eiθ(zα)+αw = e^{i\theta}(z - \alpha) + \alpha——「ずらして・回して・戻す」
  • 複素数の乗算は、ベクトルの「回転行列」と本質的に同じ操作——「複素数の掛け算は行列の回転変換と同値」

次回は複素数平面の締めくくりとして、「1 の n 乗根」と図形の関係を学びます。