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

空間ベクトル

2 次元から 3 次元へ

「地図で場所を示すのに東西と南北の 2 つの情報があれば十分でしたが、飛行機の位置を示すには高さ(高度)も必要」——これが 3 次元ベクトルが必要になる理由です。

2 次元のベクトル (a1,a2)(a_1, a_2) に第 3 成分を加えて、3 次元ベクトル (a1,a2,a3)(a_1, a_2, a_3) を定義します——「x, y に加えて z(高さ・奥行き)の方向も扱えるようにする」のです。

基本ベクトル(それぞれ x, y, z 方向の「単位矢印」):

e1=(1,0,0),e2=(0,1,0),e3=(0,0,1)\vec{e_1} = (1, 0, 0), \quad \vec{e_2} = (0, 1, 0), \quad \vec{e_3} = (0, 0, 1)

任意のベクトルはこれらの線形結合で書けます——「x方向に a1a_1、y方向に a2a_2、z方向に a3a_3 だけ動かす」:

a=a1e1+a2e2+a3e3=(a1,a2,a3)\vec{a} = a_1\vec{e_1} + a_2\vec{e_2} + a_3\vec{e_3} = (a_1, a_2, a_3)

3 次元での演算

加算・スカラー倍

「2 次元のときと全く同じルール」——成分が 1 つ増えただけです:

a+b=(a1+b1,a2+b2,a3+b3)\vec{a} + \vec{b} = (a_1+b_1, a_2+b_2, a_3+b_3) ka=(ka1,ka2,ka3)k\vec{a} = (ka_1, ka_2, ka_3)

大きさ

「2 次元でピタゴラスの定理を使ったように、3 次元でも同じ発想」——3 つの成分すべてを二乗して足して平方根:

a=a12+a22+a32|\vec{a}| = \sqrt{a_1^2 + a_2^2 + a_3^2}

内積

「2 次元の内積の成分版と全く同じ構造」——成分が 1 つ増えて 3 項になるだけです:

ab=a1b1+a2b2+a3b3=abcosθ\vec{a} \cdot \vec{b} = a_1b_1 + a_2b_2 + a_3b_3 = |\vec{a}||\vec{b}|\cos\theta

外積(クロス積)

「2 つのベクトルが決める平面に対して、直角に突き刺さる矢印を作る演算」——これが外積で、3 次元特有の操作です。ドライバーを 2 方向で決まる平面にねじ込むイメージです。

3 次元特有の演算で、結果はベクトル(2 つのベクトル両方に垂直):

a×b=e1e2e3a1a2a3b1b2b3=(a2b3a3b2, a3b1a1b3, a1b2a2b1)\vec{a} \times \vec{b} = \begin{vmatrix}\vec{e_1} & \vec{e_2} & \vec{e_3} \\ a_1 & a_2 & a_3 \\ b_1 & b_2 & b_3\end{vmatrix} = (a_2b_3-a_3b_2, \ a_3b_1-a_1b_3, \ a_1b_2-a_2b_1)

外積の大きさ a×b=absinθ|\vec{a} \times \vec{b}| = |\vec{a}||\vec{b}|\sin\theta は、a\vec{a}b\vec{b} が作る平行四辺形の面積に等しいです——「外積の長さ = 2 本の矢印で作った平行四辺形の広さ」と覚えましょう。

インタラクティブ図解:3D ベクトル(回転視点)

3 次元空間のベクトルを透視投影で表示します。マウスを左右に動かすと視点が回転します。

マウスを左右に動かして3D視点を回転させる。a⃗×b⃗(外積)が2本のベクトルと垂直になることを確認しよう

var OX = 300, OY = 190;
var t = 0;

function project(x, y, z, rotY) {
// Y軸まわりの回転
var cosR = Math.cos(rotY), sinR = Math.sin(rotY);
var rx = x * cosR + z * sinR;
var ry = y;
var rz = -x * sinR + z * cosR;
// 簡易透視投影
var fov = 400;
var d = fov / (fov + rz + 200);
return [OX + rx * d * 80, OY - ry * d * 80, d];
}

function drawLine3D(x1,y1,z1,x2,y2,z2,rotY,color,lw,dash) {
var p1 = project(x1,y1,z1,rotY);
var p2 = project(x2,y2,z2,rotY);
ctx.beginPath(); ctx.moveTo(p1[0],p1[1]); ctx.lineTo(p2[0],p2[1]);
ctx.strokeStyle=color; ctx.lineWidth=lw||1;
if(dash){ctx.setLineDash([4,3]);}else{ctx.setLineDash([]);}
ctx.stroke(); ctx.setLineDash([]);
}

function arrow3D(x1,y1,z1,x2,y2,z2,rotY,color,lw) {
var p1=project(x1,y1,z1,rotY);
var p2=project(x2,y2,z2,rotY);
var dx=p2[0]-p1[0],dy=p2[1]-p1[1];
var len=Math.sqrt(dx*dx+dy*dy);
if(len<2)return;
var ux=dx/len,uy=dy/len;
var hw=8,hl=12;
ctx.beginPath();ctx.moveTo(p1[0],p1[1]);ctx.lineTo(p2[0]-ux*hl,p2[1]-uy*hl);
ctx.strokeStyle=color;ctx.lineWidth=lw||2;ctx.stroke();
ctx.beginPath();ctx.moveTo(p2[0],p2[1]);
ctx.lineTo(p2[0]-ux*hl-uy*hw,p2[1]-uy*hl+ux*hw);
ctx.lineTo(p2[0]-ux*hl+uy*hw,p2[1]-uy*hl-ux*hw);
ctx.closePath();ctx.fillStyle=color;ctx.fill();
}

function label3D(x,y,z,rotY,text,color) {
var p=project(x,y,z,rotY);
ctx.fillStyle=color;ctx.font='bold 13px sans-serif';
ctx.fillText(text,p[0]+6,p[1]-6);
}

function loop() {
ctx.clearRect(0, 0, W, H);
t += 0.008;

var rotY = (mx / W) * Math.PI * 2;

var axLen = 3;

// 軸
drawLine3D(-0.2,0,0,axLen,0,0,rotY,'#30363d',1.5);
drawLine3D(0,-0.2,0,0,axLen,0,rotY,'#30363d',1.5);
drawLine3D(0,0,-0.2,0,0,axLen,rotY,'#30363d',1.5);
var xp=project(axLen+0.2,0,0,rotY);
var yp=project(0,axLen+0.2,0,rotY);
var zp=project(0,0,axLen+0.2,rotY);
ctx.fillStyle='#8b949e';ctx.font='13px sans-serif';
ctx.fillText('x',xp[0],xp[1]);
ctx.fillText('y',yp[0],yp[1]);
ctx.fillText('z',zp[0],zp[1]);

// ベクトル a = (2, 1, 0)
var ax=2,ay=1,az=0;
// ベクトル b = (0.5, 1, 2)
var bx=0.5,by=1,bz=2;
// a+b
var sx=ax+bx,sy=ay+by,sz=az+bz;

// 平行四辺形の点線
drawLine3D(ax,ay,az,sx,sy,sz,rotY,'#30363d',1,true);
drawLine3D(bx,by,bz,sx,sy,sz,rotY,'#30363d',1,true);

// 外積 a×b
var cpx = ay*bz - az*by;
var cpy = az*bx - ax*bz;
var cpz = ax*by - ay*bx;
var cpLen = Math.sqrt(cpx*cpx+cpy*cpy+cpz*cpz);

// 外積(正規化して 2.5 倍)
if (cpLen > 0.01) {
  var scale = 2.5 / cpLen;
  arrow3D(0,0,0,cpx*scale,cpy*scale,cpz*scale,rotY,'#ffa657',2.5);
  label3D(cpx*scale,cpy*scale,cpz*scale,rotY,'a⃗×b⃗','#ffa657');
}

// ベクトル a
arrow3D(0,0,0,ax,ay,az,rotY,'#58a6ff',3);
label3D(ax,ay,az,rotY,'a⃗=('+ax+','+ay+','+az+')','#58a6ff');

// ベクトル b
arrow3D(0,0,0,bx,by,bz,rotY,'#f0883e',3);
label3D(bx,by,bz,rotY,'b⃗=('+bx+','+by+','+bz+')','#f0883e');

// a+b
arrow3D(0,0,0,sx,sy,sz,rotY,'#56d364',3);
label3D(sx,sy,sz,rotY,'a⃗+b⃗','#56d364');

// 平面 (a と b が張る平面の格子)
var alpha = Math.sin(t)*0.5+0.5;
for(var gi=-1;gi<=2;gi++){
  drawLine3D(gi*ax*0.5,gi*ay*0.5,gi*az*0.5,
             gi*ax*0.5+bx,gi*ay*0.5+by,gi*az*0.5+bz,
             rotY,'#58a6ff15',1);
  drawLine3D(gi*bx*0.5,gi*by*0.5,gi*bz*0.5,
             gi*bx*0.5+ax,gi*by*0.5+ay,gi*bz*0.5+az,
             rotY,'#f0883e15',1);
}

// 情報パネル
ctx.fillStyle='#0d1117e0';
ctx.fillRect(8,8,230,110);
ctx.strokeStyle='#30363d';ctx.lineWidth=1;
ctx.strokeRect(8,8,230,110);
ctx.font='12px monospace';
ctx.fillStyle='#58a6ff';
ctx.fillText('a⃗ = (2, 1, 0)',16,28);
ctx.fillStyle='#f0883e';
ctx.fillText('b⃗ = (0.5, 1, 2)',16,46);
ctx.fillStyle='#56d364';
ctx.fillText('a⃗+b⃗ = ('+sx+', '+sy+', '+sz+')',16,64);
ctx.fillStyle='#ffa657';
ctx.fillText('a⃗·b⃗ = '+(ax*bx+ay*by+az*bz),16,82);
ctx.fillText('a⃗×b⃗ = ('+(ay*bz-az*by).toFixed(1)+','+(az*bx-ax*bz).toFixed(1)+','+(ax*by-ay*bx).toFixed(1)+')',16,100);

requestAnimationFrame(loop);
}
loop();

平面の方程式

「床・壁・天井のような平らな面を数式で表す」——空間の平面はベクトルを使って 2 通りで表せます。

法線ベクトルを使った形

「平面に対して垂直に立てた矢印」が法線ベクトルです——「この矢印の方向が分かれば、平面の向きが分かる」というアイデアです。

法線ベクトル(平面に垂直なベクトル)n=(a,b,c)\vec{n} = (a, b, c) と、平面上の 1 点 (x0,y0,z0)(x_0, y_0, z_0) から:

a(xx0)+b(yy0)+c(zz0)=0a(x-x_0) + b(y-y_0) + c(z-z_0) = 0

展開すると:

ax+by+cz=ax0+by0+cz0=d(定数)ax + by + cz = ax_0 + by_0 + cz_0 = d \quad \text{(定数)}

パラメータ表示

「基点から 2 方向に自由に動けるすべての点の集合」——平面上の 1 点 P と 2 つの独立ベクトル u\vec{u}, v\vec{v} を使って:

r=p+su+tv(s,tR)\vec{r} = \vec{p} + s\vec{u} + t\vec{v} \quad (s, t \in \mathbb{R})

直線の方程式(空間)

「点 P を出発して、決まった方向 d\vec{d} にどこまでも進む線」——点 P(x0,y0,z0)(x_0, y_0, z_0) を通り、方向ベクトル d=(l,m,n)\vec{d} = (l, m, n) の直線:

xx0l=yy0m=zz0n\frac{x-x_0}{l} = \frac{y-y_0}{m} = \frac{z-z_0}{n}

または媒介変数表示(パラメータ tt を変化させると直線上の点が得られる):

(x,y,z)=(x0+lt, y0+mt, z0+nt)(x, y, z) = (x_0 + lt, \ y_0 + mt, \ z_0 + nt)

点と平面の距離

「2 次元で点と直線の距離を求めたのと同じ発想」——点 (x1,y1,z1)(x_1, y_1, z_1) から平面 ax+by+cz+d=0ax + by + cz + d = 0 までの距離(2 次元と同様の形):

D=ax1+by1+cz1+da2+b2+c2D = \frac{|ax_1 + by_1 + cz_1 + d|}{\sqrt{a^2 + b^2 + c^2}}

2 平面の関係

「2 枚の板が平行か垂直かを調べる」——法線ベクトルの関係を見れば分かります:

平面 π1:a1x+b1y+c1z=d1\pi_1: a_1x + b_1y + c_1z = d_1π2:a2x+b2y+c2z=d2\pi_2: a_2x + b_2y + c_2z = d_2 の法線ベクトルを n1=(a1,b1,c1)\vec{n_1} = (a_1, b_1, c_1)n2=(a2,b2,c2)\vec{n_2} = (a_2, b_2, c_2) とすると:

  • 平行     n1n2    (a1:b1:c1)=(a2:b2:c2)\iff \vec{n_1} \parallel \vec{n_2} \iff (a_1 : b_1 : c_1) = (a_2 : b_2 : c_2)——「法線が同じ方向 = 平面が平行」
  • 垂直     n1n2=0    a1a2+b1b2+c1c2=0\iff \vec{n_1} \cdot \vec{n_2} = 0 \iff a_1a_2 + b_1b_2 + c_1c_2 = 0——「法線が直交 = 平面が垂直」

2 平面のなす角 θ\theta

cosθ=n1n2n1n2\cos\theta = \frac{|\vec{n_1}\cdot\vec{n_2}|}{|\vec{n_1}||\vec{n_2}|}

まとめ

  • 3D ベクトルは成分が 3 つ:(a1,a2,a3)(a_1, a_2, a_3)——「x, y, z の 3 方向を同時に扱う」
  • 内積は 2D と同様:ab=a1b1+a2b2+a3b3\vec{a}\cdot\vec{b} = a_1b_1 + a_2b_2 + a_3b_3——「成分が 1 つ増えるだけ」
  • 外積は 3D 固有:結果がベクトル、両ベクトルに垂直——「2 本の矢印が作る面の「法線」を生み出す演算」
  • 平面の方程式:ax+by+cz=dax + by + cz = d(法線ベクトル (a,b,c)(a, b, c) を持つ)——「平面の向きは法線ベクトル 1 本で決まる」

次回は数の世界を実数から複素数へ拡張し、複素数平面(アルガン図)を学びます。