うしブログ

うしブログ

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

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

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

Geogebraスキルアップ問題集(001解答)

001

 

Geogebraファイルの見本

Geogebraファイル

 

基本的なアイデア

点Cが線分ABを押していないときには、線分AB(Segment[A,B])を表示させ、押しているときには非表示にして、かわりに曲線Spline[{A, C, B}, 3]を表示させている。

問題は、「点Cが線分ABを押しているとき」というのを、どのように表現するかである。

 

半直線の作成

f:id:usiblog:20160816194326p:plain

点Cから線分ABと平行に、2本の半直線を引く(h, i)。hの作成方法を例にすると、まず点Cを通り線分ABに平行な直線Line[C, Segment[A,B]]を作成し、その直線上であって点Cより左側に点を作成し(点Fとする)、点Cから点Fを通るように引いた半直線Ray[C, F]をhとする。

点Aから線分ABと垂直に、また点Bから線分ABと垂直に、それぞれ2本の半直線を引く(j, e, k, f)。

 

半直線同士の交点の作成

半直線同士の交点L, M, H, Iを作成する。各点の定義は、以下の通りである。

L=Intersect[h, j]

M=Intersect[i, k]

H=Intersect[e, h]

I=Intersect[f, i]

 

曲線の表示条件

点L, M, H, Iは、Cの位置によって、定義されないこともある。

f:id:usiblog:20160816195403p:plain

この図では、L, Mは定義されているが、H, Iは定義されていない。その理由は、hとe、およびiとfが交点をもたないからである。

 

f:id:usiblog:20160816195857p:plain

この図では、H, Iは定義されているが、L, Mは定義されていない。その理由は、hとj、およびiとkが交点をもたないからである。

 

f:id:usiblog:20160816195734p:plain

この図では、Mは定義されているが、L, H, Iは定義されていない。

 

「点Cが上から線分ABを押しているとき」には、Hが定義されていて、かつ、Iが定義されている。

f:id:usiblog:20160816195857p:plain

 

「点Cが下から線分ABを押しているとき」には、Lが定義されていて、かつ、Mが定義されている。

f:id:usiblog:20160816200256p:plain

 

したがって、曲線Spline[{A, C, B}, 3]の表示条件を、以下のようにすることが考えられる。

( IsDefined[H] ≟ true ∧ IsDefined[I] ≟ true )

( IsDefined[L] ≟ true ∧ IsDefined[M] ≟ true )

しかしながら、表示条件をこのようにしてしまうと、点Cが線分ABの上から線分ABを通過する(押す)場合と、点Cが線分ABの横に回り込んで、線分ABの下にくる場合が区別されない。前者では曲線Spline[{A, C, B}, 3]を表示させたいが、後者では表示させたくない(かわりに線分ABを表示させたい)。点Cが線分ABを下から押す場合と、点Cが線分ABの下側から線分ABの横に回り込んで、線分ABの上側に行く場合との区別も、同様に必要となる。

f:id:usiblog:20160816201352g:plain

 

そこで、「押す場合」と、「回り込む場合」とを区別する方法を考えなければならない。

 

真偽値の利用

2つの真偽値オブジェクトup, downを作成する。

点Cが線分ABの横を回り込んで、線分ABの上側に来たとき、up=true, down=falseとなるようにする。また、点Cが線分ABの横を回り込んで、線分ABの下側に来たとき、up=false, down=trueとなるようにする。

f:id:usiblog:20160816202750g:plain

 

これを実現するためには、点CのOn Update スクリプトとして、以下の4行を記述する。

If[(IsDefined[L]==true∧IsDefined[M]==false)∨(IsDefined[L]==false∧IsDefined[M]==true),SetValue[up,true]]


If[(IsDefined[L]==true∧IsDefined[M]==false)∨(IsDefined[L]==false∧IsDefined[M]==true),SetValue[down,false]]


If[(IsDefined[H]==true∧IsDefined[I]==false)∨(IsDefined[H]==false∧IsDefined[I]==true),SetValue[up,false]]


If[(IsDefined[H]==true∧IsDefined[I]==false)∨(IsDefined[H]==false∧IsDefined[I]==true),SetValue[down,true]]

上2行は、「Cを動かして、LかMのどちらか一方のみが定義されているに至った場合には、upをtrueにし(1行目)、downをfalseにしなさい(2行目)」という命令である。点Cが線分ABの下側から上側に回り込む場合の命令である。

下2行は、「Cを動かして、HかIのどちらか一方のみが定義されているに至った場合には、upをfalseにし(3行目)、downをtrueにしなさい(4行目)」という命令である。点Cが線分ABの上側から下側に回り込む場合の命令である。

 

こうして、「押す場合」と「回り込む場合」の区別ができた。

すなわち、点Cが線分ABの上から線分ABを通過する(押す)場合は、up=true, down=falseのままであるが、点Cが線分ABの横に回り込んで、線分ABの下にくる場合には、up=false, down=trueに真偽値が変更され、両者が真偽値によって区別される(下から押す場合と、回り込んで上側に行く場合との区別についても同様である)。

 

f:id:usiblog:20160816203552g:plain

 

曲線Spline[{A, C, B}, 3]の表示条件は、真偽値による区別を加味して、以下のように記述する。

( up ≟ true ∧ IsDefined[H] ≟ true ∧ IsDefined[I] ≟ true )

( down ≟ true ∧ IsDefined[L] ≟ true ∧ IsDefined[M] ≟ true )

 これによって、線分ABの上側から、線分の横を回り込んで、下側に行った場合(すなわちdown=trueの場合)に、曲線が表示されるのを防ぎ(1行目)、また線分ABの下側から、線分の横を回り込んで、上側に行った場合(すなわちup=trueの場合)にも、曲線が表示されるのを防いでいる。

 

線分ABの表示条件

線分ABは、曲線Spline[{A, C, B}, 3]が表示されない場合に表示したい。そのため、曲線Spline[{A, C, B}, 3]の表示条件を否定した論理式を、線分ABの表示条件とする。ド・モルガンの法則がたいへん役に立つ。

( up ≟ false ∨ IsDefined[H] ≟ false ∨ IsDefine

d[I] ≟ false )

( down ≟ false ∨ IsDefined[L] ≟ false ∨ IsDefined[M] ≟ false ) 

 

仕上げ

仕上げとして、不要なオブジェクト(半直線、点L, M, H, I、真偽値チェックボックス)を非表示にすれば、完成である。

 

別解

上記のアプレットは、線分ABをドラッグして、点Cの横を通って、点Cの上側に持っていくと、線分ABは曲がってしまう。

f:id:usiblog:20160915014421g:plain

これを克服するには、別解が必要になる。

 

別のアプローチで作成したアプレット

GeoGebraファイル