座標が線分に近いか遠いかを調べる「ベクトル」というのは、とっつきにくい印象が強いらしい。「内積」とか「外積」とか、果たして何の積なのか。いずれも、式そのものは単なる四則演算だ。そもそもどんなときに使うのかわらないのが、近寄りがたい理由だろう[*1]。そこで、内積も加えて、最近小学校の算数教材の制作で使った例を採上げる。式は前述のとおり四則演算なので、考え方に重点を置いてご説明したい。外積と内積を使う」の参加者向けとして書いた。当日のYouTube録画をつぎに掲げる。MeetUpでは、「珍味ベクトル外積3種盛り」と題して外積の使い道について一席務めた(15分間のYouTube録画も掲載)。本稿はその続編といえる。興味のある方は、リンクの第12回レジュメもご覧いただきたい。座標でかたちを扱う算数教材でベクトルの外積や内積を使ったのは、図形の上でマウスポインタが重なった面や辺をハイライトするという処理だ(図001)。以下のサンプル001は、もっとも簡単なかたちである三角形について、ポインタ座標の重なりを確かめている。pointerマウスポインタが重なるとハイライトするというのは、ボタンにも使われる動きだ。Flashでは、予めハイライトのパーツを置いておき、初めは見えないようにしたうえで、ロールオーバーしたら表示するというつくり方がよく用いられる(図002)。CC)しかし、図形をパーツに分けて扱うのが適さない場合もある。立体図形をアニメーションさせるときは、3次元の頂点座標をデータにして計算し、辺や面は線と塗りで描く方が扱いやすい(図003)。すると、マウスポインタとの重なりも、座標にもとづいて確かめなければならない。図003■立体をアニメーションさせるには3次元の頂点座標で扱うただし、ここで気をつけなければならないのは、マウスポインタの座標は2次元(xとy)であり、重なりは2次元平面で調べるということだ。立体の頂点座標は3次元であっても、それらに遠近法を加えて2次元平面に投影する(図004)。「透視投影」と呼ばれる考え方だ(「遠近法が投影された座標を求める」参照)。座標が面の中か外かを調べるマウスポインタと面との重なり、つまり座標が面の中か外かを調べるにはベクトルの外積が使える。3次元ベクトルの外積A×Bはベクトルで表され、方向と大きさをもつ(図005)。ベクトルの外積は交換法則が成立たない。掛ける順序が変わると、方向は逆になる。図005■3次元ベクトルの外積は方向と大きさをもつ方向は右ネジのベクトル大きさは平行四辺形の面積2次元ベクトルの外積の大きさは、3次元ベクトルと同じくふたつのベクトルを2辺とする平行四辺形の面積に等しい。方向はなく、そのかわりに正負が定められている。ふたつのベクトルの位置が右ネジなら+、左ネジなら-になる。by)の外積A×Bはつぎの式で導かれる。外積は乗算ではないので、記号「×」は「クロス」と読む。前掲サンプル001には、以下のように2次元座標のクラス(Vector2D)に外積を求めるメソッド(crossProduct2D())が備わっている。crossProduct;};2次元平面の三角形について、座標が内側にあるかどうかは、3辺と調べる座標の外積で確かめられる。3辺のベクトルは、向きを時計回りに決めておく(図007)。各ベクトルの始点と調べる座標を結んだベクトルから、それぞれ外積を計算する。3つの外積がいずれも正なら、調べた座標は3辺すべてに対して右ネジの位置にある。三角形の内側に座標があるということになる。図007■2次元平面上の座標が三角形の内側にあるかどうかを外積で調べる前掲サンプル001は、つぎのように三角形を定めるクラス(Triangle)に備えたメソッド(hitTestPoint())により、引数の座標が三角形の内側にあるかどうか調べている。このクラスはプロパティ(vertex0とvertex1およびvertex2)に3頂点座標をもつ。ふたつの座標をメソッド(subtract())で引き算することにより、それらを結ぶベクトルが求まる。座標が線分に近いか遠いかを調べる座標が辺つまり線分に近いか遠いかは、距離で調べることになる。2次元平面における直線と点との距離は外積で求められる(図008)。線分(ab)と点(c)をベクトル(PとQ)として求めた外積の大きさ(|P×Q|)は平行四辺形の面積に等しい。|Q|sinθ)は線分と点との距離になる。|P|ただし、外積から求めた距離は、線分(ab)ではなく直線に対する値になる。点が線分の外側にあっても、両端から伸ばした直線との距離が導かれる。線分の両端より外側の点(c'やc'')は省きたい(図009)。そこでベクトルの内積を使う。by)の内積A・Bはつぎの式で導かれる。内積の記号「・」は「ドット」と読む。前掲サンプル001には、以下のように2次元座標のクラス(Vector2D)に内積を求めるメソッド(dotProduct2D())も備わっている。|A||B|cosθの正負はcosθの値で決まる。ふたつのベクトルのなす角θは、内積が正なら鋭角、負は鈍角、0のとき直角になる(図011)。線分(ab)と点(cまたはc')をベクトルとして求めた内積が負なら、点(c')は線分の外にある。|P||Q|cosθを一方のベクトル(P)の絶対値(|P|)で割れば、他方のベクトル(Q)にそのベクトルを投影した大きさ(|Q|cosθ)が求まる(図010参照)。その大きさが一方のベクトル(P)よりも長ければ、やはりその点(c'')は線分の端(b)を超えている(図012)。図012■点c"が点bを通る垂線の外側にあると|Q"|cosθ"は|P|より大きい前掲サンプル001では、つぎのように三角形を定めるクラス(Triangle)に備えたメソッド(getCloseLine())が、引数の座標の近くに辺を返す。近い辺がなければ、戻り値はnullとした。座標のクラス(Vector2D)の外積を求めるメソッド(crossProduct2D())で、距離が一定値(threshold)より近いかどうかを調べる。近かったら、つぎに内積を求めるメソッド(dotProduct2D())で、座標が線分の両端より内側であることを確かめた[*2]。前述のとおり、考え方としては外積の絶対値(crossProductAbs)を底辺のベクトルの長さ(vectorLength)で割れば距離が求まる。割る値が0でないことを確かめなければならない。距離の値を直接用いるのでなく、一定値(threshold)より小さいことを確かめたいだけなので、逆にその値に底辺のベクトルの長さを乗じて比べた。{内積(dotProduct)を線分のベクトルの長さ(vectorLength)で割って座標のベクトルの投影値と比較する処理についても、割り算をせずに比べる相手のベクトルの長さに乗じている。MeetupのYouTube録画を掲載。