うしブログ

うしブログ

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

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

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

正四面体に4つの球を内接させる

課題

正四面体を作成する。下図のように、その正四面体に内接し、互いに外接する4つの球を描け。

f:id:usiblog:20191128230003p:plain

 

見本アプレット

https://www.geogebra.org/m/xgbxzwgq

今回は、まずは3面に内接するように球を作成し、パラメータを調節することで、球同士を外接させる、というアプローチで作成してみた。

 

作成手順

正四面体を作成する

自由な点A,Bを、グラフィックスビュー1上に作成する。

正四面体の底面となる正三角形bottomを、以下の定義で作成する*1

bottom = Element[{Polygon[A, B, 3, xOy平面]}, 1]

f:id:usiblog:20191128221841p:plain

 

底面bottomの3頂点からなるリストbottomVerticeを、以下の定義で作成する。

bottomVertice = {Vertex[bottom]}

f:id:usiblog:20191128222020p:plain

 

底面bottomの重心bottomCentroidを、以下の定義で作成する。

bottomCentroid = Centroid[bottom]

f:id:usiblog:20191128222123p:plain

 

正四面体tetraを、以下の定義で作成する*2

tetra = Element[{Tetrahedron[bottom, true]}, 1]

f:id:usiblog:20191128222405p:plain

 

正四面体tetraの頂点Topを、以下の定義で作成する。

Top = Translate[bottomCentroid, Vector[(0, 0, Height[tetra])]]

正四面体tetraの4頂点からなるリストtetraVerticeを、以下の定義で作成する。

tetraVertice = Join[{bottomVertice, {Top}}]

f:id:usiblog:20191128222513p:plain

4つの球を作成する

正四面体tetraの4面のそれぞれの重心からなるリストcentroidsを、以下の定義で作成する。

centroids = {Centroid[Polygon[Element[tetraVertice, 2], Element[tetraVertice, 3], Element[tetraVertice, 4]]], Centroid[Polygon[Element[tetraVertice, 3], Element[tetraVertice, 4], Element[tetraVertice, 1]]], Centroid[Polygon[Element[tetraVertice, 4], Element[tetraVertice, 1], Element[tetraVertice, 2]]], Centroid[Polygon[Element[tetraVertice, 1], Element[tetraVertice, 2], Element[tetraVertice, 3]]]}

f:id:usiblog:20191128222811g:plain

 

頂点と、対面の重心とを結んだ線分のリストsegsを、以下の定義で作成する。

segs = Zip[Segment[α, β], α, tetraVertice, β, centroids] 

f:id:usiblog:20191128223042g:plain

 

数値オブジェクトparamを、範囲0〜1で作成し、スライダーを作成する。

パス・パラメータがparamであるような、segs上の点リストcoresを、以下の定義で作成する。

cores = Zip[Point[γ, param], γ, segs]

f:id:usiblog:20191128223400g:plain

 

球の半径radiusは、以下のように表されるので、これを作成する。

radius = z(Element[cores, 1])

4つの球リストsprsを、以下の定義で作成する。

sprs = Zip[Sphere[δ, radius], δ, cores]

f:id:usiblog:20191128224010g:plain

 

球同士が外接するときのparamの値を求める

球同士が外接するときのparamの値を求めて、paramをその値にすれば、目的の図を描くことができる。その値は、計算によって求めることも可能だが、今回はせっかくなので、GeoGebraに計算してもらおう。

 

点A側の球Element[sprs, 1]上の点のうち、点B側の球の中心Element[cores, 2]に最も近い点Pを、以下の定義で作成する。

P = ClosestPointRegion[Element[sprs, 1], Element[cores, 2]]

点B側の球Element[sprs, 2]上の点のうち、点A側の球の中心Element[cores, 1]に最も近い点Qを、以下の定義で作成する。

Q = ClosestPointRegion[Element[sprs, 2], Element[cores, 1]]

球同士が外接するならば、Distance[P,Q]は0である。

f:id:usiblog:20191128224838g:plain

 

paramとDistance[P,Q]との関係を調べよう。そのために、x軸にparam、y軸にDistance[P,Q]をとったときのグラフを考えよう。当該グラフ上の点graphPointは、

graphPoint = (param, Distance[P, Q])

と表せる。

Locus[graphPoint,param]

によって、グラフを描いてみると、下図のようになる。

f:id:usiblog:20191128225330g:plain

param = 0.53あたりで、球が外接することがわかる。証明は省略するが、paramが0から0.53あたりまで増加するに伴って、Distance[P, Q]は単調減少する。そこで、今回は、これを利用して、球が外接するときのparamの値を計算することにしよう。

 

graphPointの定義式を、paramに依存するオブジェクト名を用いずに、直接paramを用いて表すと、以下のようになる(graphPointNested)。

graphPointNested = (param, Distance[ClosestPointRegion[Element[Zip[Sphere[δ, z[Element[Zip[Point[γ, param], γ, segs], 1]]], δ, Zip[Point[γ, param], γ, segs]], 1], Element[Zip[Point[γ, param], γ, segs], 2]], ClosestPointRegion[Element[Zip[Sphere[δ, z[Element[Zip[Point[γ, param], γ, segs], 1]]], δ, Zip[Point[γ, param], γ, segs]], 2], Element[Zip[Point[γ, param], γ, segs], 1]]])

param=0におけるgraphPointの値は、graphPointNestedの定義式における「param」を、「0」に置換することによって得られる(graphPoint00)。

graphPoint00 = (0, Distance[ClosestPointRegion[Element[Zip[Sphere[δ, z[Element[Zip[Point[γ, 0], γ, segs], 1]]], δ, Zip[Point[γ, 0], γ, segs]], 1], Element[Zip[Point[γ, 0], γ, segs], 2]], ClosestPointRegion[Element[Zip[Sphere[δ, z[Element[Zip[Point[γ, 0], γ, segs], 1]]], δ, Zip[Point[γ, 0], γ, segs]], 2], Element[Zip[Point[γ, 0], γ, segs], 1]]])

同様に、param=0.5におけるgraphPointの値をもつ点として、graphPoint05を作成する。

graphPoint05 = (0.5, Distance[ClosestPointRegion[Element[Zip[Sphere[δ, z[Element[Zip[Point[γ, 0.5], γ, segs], 1]]], δ, Zip[Point[γ, 0.5], γ, segs]], 1], Element[Zip[Point[γ, 0.5], γ, segs], 2]], ClosestPointRegion[Element[Zip[Sphere[δ, z[Element[Zip[Point[γ, 0.5], γ, segs], 1]]], δ, Zip[Point[γ, 0.5], γ, segs]], 2], Element[Zip[Point[γ, 0.5], γ, segs], 1]]])

 

求めるparamの値は、Line[graphPoint00, graphPoint05]とx軸との交点AnsPointの、x座標の値に等しい。

AnsPoint = Intersect[Line[graphPoint00, graphPoint05], x軸]

 

ボタンを作成し、On Click スクリプトに、以下を記述する。

SetValue[param,x(AnsPoint)]

ボタンをクリックすると、4つの球が互いに外接するように、paramの値が調整される。

 

*1:このように、bottomは、{}で囲んでリストにして、その第一要素として定義している。これをしないと、正三角形の線分が自動的に作成され、数式ビューがごちゃつく。そのため、できるだけオブジェクトの数を少なくして、数式ビューの見通しをよくする趣旨で、このような処理をしている。

*2:これも、リストオブジェクトとして作成して、その第一要素として呼び出すことで、辺、面オブジェクトが大量に自動生成されることによる、数式ビューのごちゃつきを回避している。