うしブログ

うしブログ

趣味で運営する、GeoGebraの専門ブログ。

(作業メモ)StartPoint要検証(2行の場合;テキスト変更時未定義問題)

(要修復)ToggleButton・RollPolygonWithoutSlipping・貯金時計・直感力トレーニング

「ベクトルのリスト」から行列を返すオリジナルツール

課題

ベクトルのリストvectorList の各要素を列ベクトルと考えて、行列を得たい。たとえば、ベクトル

u = (1,2)

v = (3,4)

に対して、

vectorList = {u, v}

を作成したとする。vectorListを引数として、行列

f:id:usiblog:20190512032857p:plain

を得られるような、オリジナルツールを作成する方法を考える。

なお、以下の説明は、GeoGebra バージョン6.0.536.0-wを前提としている。

比較的単純な方法(うまくいかない)

①ベクトルの各成分を並べて行列を作成(matrix1)

matrix1 = Transpose[Zip[{x(α), y(α), z(α)}, Vector[α], vectorList]]

②matrix1の3行目(z座標を集めたもの)が全て0、すなわち2次元ベクトルであれば1、そうでなければ(3次元ベクトルならば)0を返す数値を取得(dimensionChecker)。

dimensionChecker = Product[Zip[α ≟ 0, α, Element[matrix1, 3]]]

③2次元ベクトルの場合には3行目をカットする(output)

output = If[dimensionChecker ≟ 1, Take[matrix1, 1, 2], matrix1]

④outputを、vectorListのみで表したもの

If[Product[Zip[α ≟ 0, α, Element[Transpose[Zip[{x(β), y(β), z(β)}, Vector[β],vectorList]], 3]]] ≟ 1, Take[Transpose[Zip[{x(γ), y(γ), z(γ)}, Vector[γ],vectorList]], 1, 2], Transpose[Zip[{x(δ), y(δ), z(δ)}, Vector[δ],vectorList]]]

うまくいかない原因

④の数式は、GeoGebra(バージョン6.0.536.0-w現在)の仕様上、うまくオリジナルツール化できない(オリジナルツールにした途端に、戻り値が正しくなくなる)。その理由は、概略以下のとおりである。

vectorListを唯一の引数としてオリジナルツールを作成する場合、vectorListは自由オブジェクトである必要がある(そうしなければ、ツール作成時にエラーが生じてしまう)。そのため、vectorListを、

{u, v}

のように、他のオブジェクトに依存する形で定義するのではなく、たとえば

{ (1,2), (3,4) }

のように、座標を用いた形で定義する必要がある。

ところが、どうやら、GeoGebra(バージョン6.0.536.0-w現在)の仕様上、

{ (1,2), (3,4) }

が「点のリスト」なのか、「ベクトルのリスト」なのか、ハッキリしないという点に起因して、Zipコマンド使用時に想定外の処理が行われているようだ。

そこで、まずは、vectorListをZipコマンドにかける前に、vectorListの要素が点なのかベクトルなのかを、こちら側でハッキリさせる必要がある。

 ベクトルと点の区別

GeoGebraでは、ある座標を定義にもつオブジェクトが、ベクトルなのか点なのかを判定して、結果に応じて異なる値(true / falseなり、1 / 0なり)を返すことは、きわめて難しい。さしあたり、以下の裏技的手法が有効である*1。すなわち、ある座標で定義されたオブジェクトは、

<オブジェクト> ≟ Translate[ <オブジェクト>, (0, 1) ]

がtrueならばベクトルであり、falseならば点である。

以下では、これを利用して、オリジナルツール作成を目指す。

 

ベクトルと点を区別して作成する方法(うまくいった)

①vectorListの各要素に対して、ベクトルであれば1、点であれば0として判定し、結果をリストとして取得する(isVector)。

isVector = ¬(¬Sequence[Element[vectorList, α] ≟ Translate[Element[vectorList, α], (0, 1)], α, 1, Length[vectorList]])

②vectorListの各要素に対して、点であれば1、ベクトルであれば0として判定し、結果をリストとして取得する(isPoint)。感覚的には、isVectorの裏返しである。

isPoint = ¬Sequence[Element[vectorList, β] ≟ Translate[Element[vectorList, β], (0, 1)], β, 1, Length[vectorList]]

③pointListの要素のうち、ベクトルであるものについては、そのベクトルの成分を用いた点を返す。pointListの要素のうち、点であるものについては、点(0,0)を返す(pointList1)。

pointList1 = vectorList * isVector

④pointListの要素のうち、点であるものについては、そのベクトルの成分を用いた点を返す。pointListの要素のうち、ベクトルであるものについては、点(0,0)を返す(pointList2)。

pointList2 = vectorList * isPoint

⑤pointList1とpointList2を足し算すると、vectorListの全要素を、すべて点オブジェクトに変換したものを得ることができる(pointListAll)

pointListAll = pointList1 + pointList2

⑥pointListAllを、いったん3次元にする(pointListAll3D)。

pointListAll3D = pointListAll + (0, 0, 0)

⑦各座標を並べて行列を作成する(matrix1)。

matrix1 = Transpose[Zip[{x(γ), y(γ), z(γ)}, γ, pointListAll3D]]

⑧2次元ベクトルの場合には3行目をカットする(output)。

output = If[Product[Zip[δ ≟ 0, δ, Element[matrix1, 3]]] ≟ 0, matrix1, Take[matrix1, 1, 2]]

⑨outputを、vectorListのみで表したもの

If[Product[Zip[δ ≟ 0, δ, Element[Transpose[Zip[{x(γ), y(γ), z(γ)}, γ, vectorList (¬(¬Sequence[Element[vectorList, α] ≟ Translate[Element[vectorList, α], Vector[(0, 1)]], α, 1, Length[vectorList]])) + vectorList (¬Sequence[Element[vectorList, β] ≟ Translate[Element[vectorList, β], Vector[(0, 1)]], β, 1, Length[vectorList]]) + (0, 0, 0)]], 3]]] ≟ 0, Transpose[Zip[{x(γ), y(γ), z(γ)}, γ, vectorList (¬(¬Sequence[Element[vectorList, α] ≟ Translate[Element[vectorList, α], Vector[(0, 1)]], α, 1, Length[vectorList]])) + vectorList (¬Sequence[Element[vectorList, β] ≟ Translate[Element[vectorList, β], Vector[(0, 1)]], β, 1, Length[vectorList]]) + (0, 0, 0)]], Take[Transpose[Zip[{x(γ), y(γ), z(γ)}, γ, vectorList (¬(¬Sequence[Element[vectorList, α] ≟ Translate[Element[vectorList, α], Vector[(0, 1)]], α, 1, Length[vectorList]])) + vectorList (¬Sequence[Element[vectorList, β] ≟ Translate[Element[vectorList, β], Vector[(0, 1)]], β, 1, Length[vectorList]]) + (0, 0, 0)]], 1, 2]]

この方法なら、正しくオリジナルツールを作成することができた。以下では、ツールについて紹介する。

 

オリジナルツール「VtoM」

VtoM tool - GeoGebra

構文は、

VtoM[ <ベクトルのリスト> ]

である。

f:id:usiblog:20190512030615g:plainf:id:usiblog:20190512030706g:plain

 

(追記)より簡便な方法

より簡便な方法を思いついたので、紹介する。

①ベクトルのリストに (0,0,0) を加えると、3次元の点のリストを得られる(pointList3D)。これだけで、点のリストであることを明確にできる。

pointList3D = vectorList + (0, 0, 0)

②各座標を並べて行列を作成する(matrix1)。

matrix1 = Transpose[Zip[{x(α), y(α), z(α)}, α, pointList3D]]

③2次元ベクトルの場合には3行目をカットする(output)。

output = If[Product[Zip[β ≟ 0, β, Element[matrix1, 3]]] ≟ 0, matrix1, Take[matrix1, 1, 2]]

④outputを、vectorListのみで表したもの

If[Product[Zip[β ≟ 0, β, Element[Transpose[Zip[{x(α), y(α), z(α)}, α, vectorList + (0, 0, 0)]], 3]]] ≟ 0, Transpose[Zip[{x(α), y(α), z(α)}, α, vectorList + (0, 0, 0)]], Take[Transpose[Zip[{x(α), y(α), z(α)}, α, vectorList + (0, 0, 0)]], 1, 2]]

この方法を用いたオリジナルツール「VtoM」

VtoM tool_v2 - GeoGebra

*1:他にも、ベクトルオブジェクトに{true}を掛けると、点オブジェクトのリストが返されることを利用して、

<オブジェクト> ≟ Element[ <オブジェクト> * {true}, 1 ]

とする方法もある。こちらは、オブジェクトが点ならばtrue、falseならばベクトルである。