高校数学をプログラミングで解く(数学B編)「2-4 位置ベクトルと図形」
マガジンリスト > 数学B編 2.空間のベクトル > 2-4 位置ベクトルと図形
はじめに
今回は、数学Bで学ぶ「位置ベクトルと図形」について、線分の内分点や外分点の位置ベクトルを計算して空間に描くプログラムや空間上の3点が一直線上にあるかどうかを確認するためのプログラムを作成します。
空間の位置ベクトルと内分点・外分点
まず、空間の位置ベクトルと内分点・外分点についてまとめておきます。と言っても、記事『高校数学をプログラミングで解く(数学B編)「1-3 位置ベクトル」』で解説した平面ベクトルでの内分点・外分点とほとんど変わりません。ベクトルの成分が平面ベクトルのとき2つであったものが空間ベクトルでは3つになるだけです。
以下では、$${\mathrm{A} ( \vec{a} )}$$、$${\mathrm{B} ( \vec{b} )}$$、$${\mathrm{C} ( \vec{c} )}$$とします。
① $${ \overrightarrow{ \mathrm{AB} } = \vec{b} - \vec{a} }$$
② 内分点・外分点
線分ABを$${m:n}$$に内分または外分する点について
$$
\mathrm{内分点} \mathrm{P} ( \vec{p} ) : \vec{p} = \frac{n \vec{a} + m \vec{b}}{m+n} \\
\mathrm{外分点} \mathrm{Q} ( \vec{q} ) : \vec{q} = \frac{-n \vec{a} + m \vec{b}}{m-n} \\
\mathrm{中点} \mathrm{M} ( \vec{m} ) : \vec{m} = \frac{ \vec{a} + \vec{b}}{2}
$$
③ 重心
$$
\mathrm{△ABCの重心} \mathrm{G} ( \vec{g} ) : \vec{g} = \frac{ \vec{a} + \vec{b} + \vec{c} }{3}
$$
空間ベクトルと図形に関する性質
次に、空間ベクトルと図形に関する性質についてまとめておきます。この性質については、記事『高校数学をプログラミングで解く(数学B編)「1-4 ベクトルと図形」』で解説した平面ベクトルと図形に関する性質に加え、同じ平面上にある点に関する性質があります。
一直線上の3点
2点$${\mathrm{A, B}}$$が異なるとき
点$${\mathrm{P}}$$が直線$${\mathrm{AB}}$$上にある $${ \Leftrightarrow }$$ $${ \overrightarrow{ \mathrm{AP} } = k \overrightarrow{ \mathrm{AB} } }$$となる実数$${k}$$がある
同じ平面上にある点
一直線上にない3点$${\mathrm{A,B,C}}$$と点$${\mathrm{P}}$$に対して
① 点$${\mathrm{P}}$$が平面$${\mathrm{ABC}}$$上にある $${ \Leftrightarrow }$$$${ \overrightarrow{ \mathrm{CP} } = s \overrightarrow{ \mathrm{CA} } + t\overrightarrow{ \mathrm{CB} } }$$となる実数$${s,t}$$がある
② 点$${\mathrm{P} ( \vec{p} )}$$が3点$${\mathrm{A} ( \vec{a} )}$$,$${\mathrm{B} ( \vec{b} )}$$,$${\mathrm{C} ( \vec{c} )}$$の定める平面$${\mathrm{ABC}}$$上にある
$${ \Leftrightarrow }$$$${ \vec{p}= s\vec{a}+t\vec{b}+u\vec{c}, \ s+t+u=1 }$$となる実数$${s,t,u}$$がある
空間ベクトルの相等
(同じ平面上にない4点$${\mathrm{O,A,B,C}}$$)
$${ \overrightarrow{ \mathrm{OA} } = \vec{a} }$$,$${ \overrightarrow{ \mathrm{OB} } = \vec{b} }$$,$${ \overrightarrow{ \mathrm{OC} } = \vec{c} }$$とし、$${ s, t, u, s', t', u' }$$は実数とするとき
$$
s \vec{a} + t \vec{b} + u \vec{c} = s' \vec{a} + t' \vec{b} + u' \vec{c} \Leftrightarrow s = s', \ t = t', \ u = u'
$$
特に
$$
s \vec{a} + t \vec{b} + u \vec{c} = \vec{0} \Leftrightarrow s=t=u=0
$$
内分点・外分点に関する問題
まず、下記の内分点・外分点に関する問題を解くプログラムを作成していきます。
内分点・外分点に関する問題
4つの点$${ \mathrm{A}(\vec{a}) }$$、$${ \mathrm{B}(\vec{b}) }$$、$${ \mathrm{C}(\vec{c}) }$$、$${ \mathrm{D}(\vec{d}) }$$
$$
\vec{a} = (-1,1,4), \ \vec{b} = (3,1,-1), \ \vec{c} = (-2,2,-2), \ \vec{d} = (-1,-3,0)
$$
を頂点とする四面体を考えます。このとき、次の点の位置ベクトルをキャンバス上に描け。
(1) 線分$${\mathrm{BC}}$$を$${1:2}$$に内分する点$${ \mathrm{P}( \vec{p} ) }$$
(2) 線分$${\mathrm{DP}}$$を$${3:2}$$に外分する点$${ \mathrm{Q}( \vec{q} ) }$$
(3) 線分$${\mathrm{AQ}}$$の中点$${ \mathrm{R}( \vec{r} ) }$$
内分点・外分点を描くプログラム
今回の問題は空間の位置ベクトルの内分点・外分点を定義通りにプログラミングしていくだけです。
記事『高校数学をプログラミングで解く(数学B編)「2-0-3 右手系で図形を描く」』で作成したスケッチ「draw3DCoordinates_temp」を再利用します。以下の zip ファイルをダウンロードして展開または解凍してください。
そして、スケッチの名前(フォルダ名)を「drawPositionVector3D」と変更し、またスケッチ「drawPositionVector3D」内の「draw3DCoordinates_temp.pde」ファイルの名前を「drawPositionVector3D.pde」に変更します。そして、pdeファイル「drawPositionVector3D.pde」をダブルクリックしてスケッチ「drawPositionVector3D」の開発環境ウィンドウを立ち上げます。開発環境ウィンドウのタブ欄で「drawPositionVector3D」タブを選択し、そのテキストエリアのソースコードを以下で書き換えます。
// 四面体を描く、各位置ベクトルを描く
float range; // 座標系での表示範囲-range≦x,y.z≦range
float res; // 座標系のサイズをキャンバスのサイズに変換するパラメータ
float angle = 0.0;
PVector a, b, c, d; // 四面体の各頂点を表す位置ベクトル
PVector p; // 辺BCを1:2に内分する点の位置ベクトル
PVector q; // 線分DPを3:2に外分する点の位置ベクトル
PVector r; // 線分AQの中点の位置ベクトル
void setup(){
size(400, 400, P3D);
noFill();
ortho();
range = 10.0;
res = width / 2.0 / range;
// 四面体の頂点を表わす4つの空間ベクトル
a = new PVector(-1.0, 1.0, 4.0);
b = new PVector(3.0, 1.0, -1.0);
c = new PVector(-2.0, 2.0, -2.0);
d = new PVector(-1.0, -3.0, 0.0);
// 辺BCを1:2に内分する点の位置ベクトル
float m = 1.0;
float n = 2.0;
p = b.copy().mult(n).add( c.copy().mult(m) ).mult(1.0/(m+n));
// 線分DPを3:2に外分する点の位置ベクトル
m = 3.0;
n = 2.0;
q = d.copy().mult(-n).add( p.copy().mult(m) ).mult(1.0/(m-n));
// 線分AQの中点の位置ベクトル
m = 1.0;
n = 1.0;
r = a.copy().mult(n).add( q.copy().mult(m) ).mult(1.0/(m+n));
println("点Pの位置ベクトル:", p);
println("点Qの位置ベクトル:", q);
println("点Rの位置ベクトル:", r);
}
void draw(){
background(204); // 背景をグレーにする
// 視点を設定する
camera(200.0, -200.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0);
// マウスボタンが押されたときの処理
if(mousePressed){
if( mouseButton == LEFT ){ // 左ボタンがおされたときはz軸時計周りに回転
angle = angle + 1.0;
} else if( mouseButton == RIGHT ){ // 右ボタンがおされたときはz軸反時計周りに回転
angle = angle -1.0;
} else {
}
}
// z軸周りに回転
rotateZ(radians(angle));
// 座標軸の設定
fill(255,0,0);
stroke(255,0,0);
arrow3D(0.0,0.0,0.0,range * res,0.0,0.0); // x軸(赤色)
fill(0,255,0);
stroke(0,255,0);
arrow3D(0.0,0.0,0.0,0.0,range * res,0.0); // y軸(緑色)
fill(0,0,255);
stroke(0,0,255);
arrow3D(0.0,0.0,0.0,0.0,0.0,range * res); // z軸(青色)
noFill();
stroke(0,0,0);
// 以下に、図形を描いていく
// 空間ベクトルa,b,c,dを描く
fill(0,0,0);
stroke(0,0,0);
arrow3D(0.0,0.0,0.0, a.x*res,a.y*res,a.z*res);
fill(0,0,0);
stroke(0,0,0);
arrow3D(0.0,0.0,0.0, b.x*res,b.y*res,b.z*res);
fill(0,0,0);
stroke(0,0,0);
arrow3D(0.0,0.0,0.0, c.x*res,c.y*res,c.z*res);
fill(0,0,0);
stroke(0,0,0);
arrow3D(0.0,0.0,0.0, d.x*res,d.y*res,d.z*res);
// 四面体ABCDを描く
//fill(128,128,128);
noFill();
stroke(128,128,128);
triangle_rhs(a.copy().mult(res),b.copy().mult(res),c.copy().mult(res));
triangle_rhs(a.copy().mult(res),c.copy().mult(res),d.copy().mult(res));
triangle_rhs(a.copy().mult(res),d.copy().mult(res),b.copy().mult(res));
triangle_rhs(b.copy().mult(res),c.copy().mult(res),d.copy().mult(res));
// 空間ベクトルpを描く(黄色)
fill(255,255,0);
stroke(255,255,0);
arrow3D(0.0,0.0,0.0, p.x*res,p.y*res,p.z*res);
// 空間ベクトルqを描く(水色)
fill(0,255,255);
stroke(0,255,255);
arrow3D(0.0,0.0,0.0, q.x*res,q.y*res,q.z*res);
// 空間ベクトルrを描く(桃色)
fill(255,0,255);
stroke(255,0,255);
arrow3D(0.0,0.0,0.0, r.x*res,r.y*res,r.z*res);
}
ソースコード1 内分点・外分点を描くプログラム
このスケッチ「drawPositionVector3D」を実行すると、図1のように、開発環境ウィンドウのコンソールに、
点Pの位置ベクトル: [ 1.3333334, 1.3333334, -1.3333334 ]
点Qの位置ベクトル: [ 6.0, 10.0, -4.0 ]
点Rの位置ベクトル: [ 2.5, 5.5, 0.0 ]
と出力されます。これらの結果が正しいことは別途確認しておいてください。
また、図2のように、実行ウィンドウのキャンバスに空間の座標系を表す3つの空間ベクトル(赤色:$${x}$$軸、緑色:$${y}$$軸、青色:$${z}$$軸)を基準にして、空間の4つの位置ベクトル$${\vec{a},\vec{b},\vec{c},\vec{d}}$$とそれらの4点を頂点とする四面体を黒色、線分$${\mathrm{BC}}$$を$${1:2}$$に内分する点の位置ベクトルを黄色、線分$${\mathrm{DP}}$$を$${3:2}$$に外分する点の位置ベクトルを水色、線分$${\mathrm{AQ}}$$の中点の位置ベクトルを桃色として表示しています。
なお、実行ウィンドウのキャンバス内をクリックすると$${z}$$軸回りに図形が回転するので、いろいろな角度から空間ベクトルを眺めてみてください。
空間ベクトルの性質に関する問題
次に、空間ベクトルの性質に関する問題を解くプログラムを作成していきます。
3点が一直線上にあるかを確認する問題
四面体$${\mathrm{ABCD}}$$の辺$${\mathrm{AB,BC,CD}}$$をそれぞれ$${ 5:3, 3:1, 7:1}$$に内分する点を$${\mathrm{P,Q,R}}$$とする。△$${\mathrm{BCD}}$$, △$${\mathrm{PQR}}$$の重心をそれぞれ$${\mathrm{G,H}}$$とするとき、$${\mathrm{A,H,G}}$$は一直線上にあることを示せ。また、$${\mathrm{AH}:\mathrm{HG}}$$を求めよ。
3点が一直線上にあるかを確認する問題の考え方
まず、四面体の各頂点の位置ベクトルは、内分点・外分点に関する問題と同じものを設定します。
$$
\vec{a} = (-1,1,4), \ \vec{b} = (3,1,-1), \ \vec{c} = (-2,2,-2), \ \vec{d} = (-1,-3,0)
$$
今回の問題のポイントは『$${\mathrm{A,H,G}}$$は一直線上にある』ことをどう示していくかです。これは空間ベクトルと図形に関する性質「一直線上の3点」から$${ \overrightarrow{ \mathrm{AH} } = k \overrightarrow{ \mathrm{AG} } }$$となる実数$${k}$$を見つけることで示すことができます。そこで、今回は以下の手順で示してみます。
① $${ \overrightarrow{ \mathrm{AH} }}$$と$${ \overrightarrow{ \mathrm{AG} } }$$を求めます。
② $${ \overrightarrow{ \mathrm{AH} }}$$の$${x}$$成分を$${ \overrightarrow{ \mathrm{AG} } }$$の$${x}$$成分で割った値を$${k}$$とします。
③ $${ \overrightarrow{ \mathrm{AG} } }$$を$${k}$$倍したものと$${ \overrightarrow{ \mathrm{AH} }}$$を比較して相等であれば、$${\mathrm{A,H,G}}$$は一直線上にあるということができます。
また、$${\mathrm{AH}:\mathrm{HG}}$$については、上記で求めた$${k}$$を用いて表すことができます。つまり、$${ \overrightarrow{ \mathrm{AH} } = k \overrightarrow{ \mathrm{AG} } }$$となったこと、そして$${ \mathrm{AG}=\mathrm{AH}+\mathrm{HG} }$$であることを利用すると、
$$
\mathrm{AH}:\mathrm{HG} = \mathrm{AH}:(\mathrm{AG}-\mathrm{AH}) = k\mathrm{AG}:(\mathrm{AG}-k\mathrm{AG})=k:(1-k)
$$
で得ることができます。
3点が一直線上にあるかを確認するためのプログラム
今回は、先ほど作成した内分点・外分点を描くプログラムを流用していきます。スケッチ「drawPositionVector3D」をフォルダごとコピーして、スケッチの名前(フォルダ名)を「drawPositionVector3D2」と変更し、またスケッチ「drawPositionVector3D2」内の「drawPositionVector3D.pde」ファイルの名前を「drawPositionVector3D2.pde」に変更します。そして、pdeファイル「drawPositionVector3D2.pde」をダブルクリックしてスケッチ「drawPositionVector3D2」の開発環境ウィンドウを立ち上げます。開発環境ウィンドウのタブ欄で「drawPositionVector3D2」タブを選択し、そのテキストエリアのソースコードを以下で書き換えます。
// 3点が一直線上にあるかどうかを確認する
float range; // 座標系での表示範囲-range≦x,y.z≦range
float res; // 座標系のサイズをキャンバスのサイズに変換するパラメータ
float angle = 0.0;
PVector a, b, c, d; // 四面体の各頂点を表す位置ベクトル
PVector p; // 辺ABを5:3に内分する点の位置ベクトル
PVector q; // 辺BCを3:1に内分する点の位置ベクトル
PVector r; // 辺CDを7:1に内分する点の位置ベクトル
PVector g; // △BCDの重心
PVector h; // △PQRの重心
PVector vec_AG; // ベクトルAG
PVector vec_AH; // ベクトルAH
void setup(){
size(400, 400, P3D);
noFill();
ortho();
range = 5.0;
res = width / 2.0 / range;
// 四面体の頂点を表わす4つの空間ベクトル
a = new PVector(-1.0, 1.0, 4.0);
b = new PVector(3.0, 1.0, -1.0);
c = new PVector(-2.0, 2.0, -2.0);
d = new PVector(-1.0, -3.0, 0.0);
// 辺ABを5:3に内分する点の位置ベクトル
float m = 5.0;
float n = 3.0;
p = a.copy().mult(n).add( b.copy().mult(m) ).mult(1.0/(m+n));
// 辺BCを3:1に内分する点の位置ベクトル
m = 3.0;
n = 1.0;
q = b.copy().mult(n).add( c.copy().mult(m) ).mult(1.0/(m+n));
// 辺CDを7:1に内分する点の位置ベクトル
m = 7.0;
n = 1.0;
r = c.copy().mult(n).add( d.copy().mult(m) ).mult(1.0/(m+n));
// △BCDの重心
g = b.copy().add( c.copy() ).add( d.copy() ).mult(1.0/3.0);
// △PQRの重心
h = p.copy().add( q.copy() ).add( r.copy() ).mult(1.0/3.0);
// AGベクトル
vec_AG = g.copy().sub( a.copy() );
// AHベクトル
vec_AH = h.copy().sub( a.copy() );
// AGベクトルとAHベクトルの大きさの比
float k = vec_AH.x / vec_AG.x;
// AGベクトルをk倍する
PVector k_vec_AG = vec_AG.copy().mult(k);
/*
println("点Pの位置ベクトル:", p);
println("点Qの位置ベクトル:", q);
println("点Rの位置ベクトル:", r);
println("点Gの位置ベクトル:", g);
println("点Hの位置ベクトル:", h);
*/
println("k =",k);
println("ベクトルAGのk倍:", k_vec_AG);
println("ベクトルAH:", vec_AH);
println("AH : HG =", k, ":", 1.0-k);
}
void draw(){
background(204); // 背景をグレーにする
// 視点を設定する
camera(200.0, -200.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0);
// マウスボタンが押されたときの処理
if(mousePressed){
if( mouseButton == LEFT ){ // 左ボタンがおされたときはz軸時計周りに回転
angle = angle + 1.0;
} else if( mouseButton == RIGHT ){ // 右ボタンがおされたときはz軸反時計周りに回転
angle = angle -1.0;
} else {
}
}
// z軸周りに回転
rotateZ(radians(angle));
// 座標軸の設定
fill(255,0,0);
stroke(255,0,0);
arrow3D(0.0,0.0,0.0,range * res,0.0,0.0); // x軸(赤色)
fill(0,255,0);
stroke(0,255,0);
arrow3D(0.0,0.0,0.0,0.0,range * res,0.0); // y軸(緑色)
fill(0,0,255);
stroke(0,0,255);
arrow3D(0.0,0.0,0.0,0.0,0.0,range * res); // z軸(青色)
noFill();
stroke(0,0,0);
// 以下に、図形を描いていく
// 空間ベクトルa,b,c,dを描く
fill(0,0,0);
stroke(0,0,0);
arrow3D(0.0,0.0,0.0, a.x*res,a.y*res,a.z*res);
fill(0,0,0);
stroke(0,0,0);
arrow3D(0.0,0.0,0.0, b.x*res,b.y*res,b.z*res);
fill(0,0,0);
stroke(0,0,0);
arrow3D(0.0,0.0,0.0, c.x*res,c.y*res,c.z*res);
fill(0,0,0);
stroke(0,0,0);
arrow3D(0.0,0.0,0.0, d.x*res,d.y*res,d.z*res);
// 四面体ABCDを描く
//fill(128,128,128);
noFill();
stroke(128,128,128);
triangle_rhs(a.copy().mult(res),b.copy().mult(res),c.copy().mult(res));
triangle_rhs(a.copy().mult(res),c.copy().mult(res),d.copy().mult(res));
triangle_rhs(a.copy().mult(res),d.copy().mult(res),b.copy().mult(res));
triangle_rhs(b.copy().mult(res),c.copy().mult(res),d.copy().mult(res));
// 空間ベクトルp,q,rを描く(黄色)
fill(255,255,0);
stroke(255,255,0);
arrow3D(0.0,0.0,0.0, p.x*res,p.y*res,p.z*res);
fill(255,255,0);
stroke(255,255,0);
arrow3D(0.0,0.0,0.0, q.x*res,q.y*res,q.z*res);
fill(255,255,0);
stroke(255,255,0);
arrow3D(0.0,0.0,0.0, r.x*res,r.y*res,r.z*res);
// △BCDの重心の空間ベクトルgを描く(水色)
fill(0,255,255);
stroke(0,255,255);
arrow3D(0.0,0.0,0.0, g.x*res,g.y*res,g.z*res);
// △PQRの重心の空間ベクトルhを描く(桃色)
fill(255,0,255);
stroke(255,0,255);
arrow3D(0.0,0.0,0.0, h.x*res,h.y*res,h.z*res);
}
ソースコード2 3点が一直線上にあるかを確認するためのプログラム
このスケッチ「drawPositionVector3D2」を実行すると、図3のように、開発環境ウィンドウのコンソールに、
k = 0.875
ベクトルAGのk倍: [ 0.875, -0.875, -4.375 ]
ベクトルAH: [ 0.875, -0.875, -4.375 ]
AH : HG = 0.875 : 0.125
と出力されます。この結果をみると、$${ \overrightarrow{ \mathrm{AH} } = k \overrightarrow{ \mathrm{AG} } }$$となっていますので、3点$${\mathrm{A,H,G}}$$が一直線上にあることがわかります。また、このときの$${k}$$の値もわかりましたので、$${\mathrm{AH}:\mathrm{HG} = 0.875 : 0.125 = 7:1}$$であることがわかります。
また、図4のように、実行ウィンドウのキャンバスに空間の座標系を表す3つの空間ベクトル(赤色:$${x}$$軸、緑色:$${y}$$軸、青色:$${z}$$軸)を基準にして、空間の4つの位置ベクトル$${\vec{a},\vec{b},\vec{c},\vec{d}}$$とそれらの4点を頂点とする四面体を黒色、辺$${\mathrm{AB,BC,CD}}$$をそれぞれ$${ 5:3, 3:1, 7:1}$$に内分する点の位置ベクトルを黄色、△$${\mathrm{BCD}}$$の位置ベクトルを水色、△$${\mathrm{PQR}}$$の重心
の位置ベクトルを桃色として表示しています。
なお、今回は、ソースコード2において、
range = 5.0;
とすることで、図形の描画サイズを調整しました。
まとめ
今回は、数学Bで学ぶ「位置ベクトルと図形」について、線分の内分点や外分点の位置ベクトルを計算して空間に描くプログラムや空間上の3点が一直線上にあるかどうかを確認するためのプログラムを作成しました。
位置ベクトルの計算は、記事『高校数学をプログラミングで解く(数学B編)「1-3 位置ベクトル」』で平面ベクトルで示したものとほぼ同じ扱いでPVectorクラスを利用して計算することができます。PVectorクラスは今後もよく利用しますので、その扱い方に少しずつ慣れていってください。
参考文献
改訂版 教科書傍用 スタンダード 数学B(数研出版、ISBN9784410209468)