うしブログ

うしブログ

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

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

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

楕円反射_うしver

このアプレットは、miyamath84様「楕円反射」に触発されて作りました。

 

楕円反射_うしver – GeoGebra

楕円形のビリヤードです。焦点から白い球を打つと、必ずもう一つの焦点を通過し、もとの焦点に帰ってくる様子が観察でき、楕円の性質を視覚的に確認することができます。

主な設計

前提オブジェクト

自由な点オブジェクト:F1, F2(楕円の焦点として使用)、P(楕円の周上の1点として使用)

楕円:ellipseAsPolyLine = PolyLine[Sequence[Point[Ellipse[F1, F2, P], α], α, 0, 1, 0.001]] ・・・後ほどIntersectコマンドを使う際に、交点の返し漏れを防ぐために、PolyLineによって作成する。

点Direction:Point[Circle[F1, 1]] ・・・球を打つ方向を決定するためのもの

数値n(1〜36):球の数

数値t:球が進んだ長さ(なお、摩擦による減速を再現するため、tのアニメーション速度は一定ではない)

数値constLength = 2 (Distance[F1, P] + Distance[P, F2]) ・・・F1〜P〜F2の長さの2倍(これがPの位置によらず一定であるのが、楕円の性質である)

f:id:usiblog:20190814050616p:plain

球(のリスト)のつくりかた

n個の球を、リストとしてまとめて作ってしまう(以下の図は、n=6の場合である)。そのために、SequenceやZipといったコマンドを活用していく。

toFirstRay = Sequence[Rotate[Direction, α, F1], α, 2π / n, 2π, 2π / n] ・・・F1を始点とする半直線を確定するための点。

f:id:usiblog:20190814050813p:plain

firstRayList = Zip[Ray[F1, β], β, toFirstRay] ・・・この半直線が楕円の周に届くまでが、球の最初の軌道となる。

f:id:usiblog:20190814051004p:plain

firstRef = Zip[Intersect[γ, ellipseAsPolyLine], γ, firstRayList] ・・・球が最初に楕円の周にぶつかる点。

f:id:usiblog:20190814051241p:plain

toSecondRay = Zip[Dilate[δ, (SemiMajorAxisLength[Ellipse[F1, F2, P]] - Distance[F1, F2] / 2) / 2 / Distance[δ, F2], F2], δ, firstRef] ・・・firstRefからF2を通り、ふたたび楕円の周にぶつかるまでの軌道を、半直線で表すための、当該半直線の始点。始点が楕円の外に作られないようにするために(もし外に作ってしまうと、半直線と楕円の交点が2つになってしまい、都合が悪い)、始点は、かならずF2から、「F2〜楕円の最短距離÷2」の位置に作られるよう、Dilateの比率を調整してある。

f:id:usiblog:20190814051452p:plain

secondRayList = Zip[Ray[ε, F2], ε, toSecondRay] ・・・firstRefからF2を通り、ふたたび楕円の周にぶつかるまでの軌道を、半直線で表したもの。

f:id:usiblog:20190814051701p:plain

secondRef = Zip[Intersect[ζ, ellipseAsPolyLine], ζ, secondRayList] ・・・球が2回目に楕円の周にぶつかる点。

f:id:usiblog:20190814051843p:plain

球は、F1→firstRef(の各要素)→F2→secondRef(の各要素)→F1という軌道をたどる。

f:id:usiblog:20190814052345p:plain

finalPointList = Zip[If[t < Distance[F1, α], Dilate[α, t / Distance[F1, α], F1], Distance[F1, α] ≤ t < Distance[F1, α] + Distance[α, β], Dilate[β, (t - Distance[F1, α]) / Distance[α, β], α], Dilate[F1, (t - Distance[F1, α] - Distance[α, β]) / Distance[β, F1], β]], α, firstRef, β, secondRef] ・・・これが球を表す。tに対応するように、球の位置を設定している。

 

1つ目の条件(t < Distance[F1, α]、ただしαはfirstRefの各要素)は、球がF1〜firstRef(の各要素)の間にある場合である。このとき、球の位置は、Dilate[α, t / Distance[F1, α], F1] 、すなわち、F1から、firstRefの各要素に向かって、長さtだけ進んだ場所とする。

 

2つ目の条件(Distance[F1, α] ≤ t < Distance[F1, α] + Distance[α, β]、αはfirstRefの各要素、βはsecondRefの各要素)は、球がfirstRef(の各要素)〜secondRef(の各要素)の間にある場合である。このとき、球の位置は、Dilate[β, (t - Distance[F1, α]) / Distance[α, β], α]、すなわち、firstRefの各要素から、secondRefの対応する要素に向かって、長さt - Distance[F1, α]だけ進んだ場所とする。

 

3つ目の条件(1つ目の条件も2つ目の条件も満たさない場合)は、球がsecondRef(の各要素)〜F1の間にある場合である。このとき、球の位置は、Dilate[F1, (t - Distance[F1, α] - Distance[α, β]) / Distance[β, F1], β]、すなわち、secondRedの各要素から、F1に向かって、長さt - Distance[F1, α] - Distance[α, β]だけ進んだ場所とする。