うしブログ

うしブログ

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

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

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

任意の点から関数グラフに接線を引く

任意の点を通る、関数グラフの接線を、すべて取得して、リストオブジェクトとして返す方法を紹介する。

GeoGebraで描けるオブジェクトの中でも、かなり設計が難しい部類に入ると思われる。 

任意の点から関数グラフに接線を引く – GeoGebra

解説

はじめに

この記事は、GeoGebra バージョン 6.0.536.0-w を前提にしている。現時点では、接線を返すコマンド「Tangent」は、関数グラフ上にない点から、関数グラフへ接線を引く機能を持たない。

もっとも、

Tangent[ <点>, <陰関数曲線> ]

は、任意の点から陰関数曲線に引いた接線を、いくつか返してくれる。

この事実を知ったのは、Hydrophobic Hyperbola様「接線の本数」というアプレットである。ここに記し、感謝申し上げる。

 

したがって、ある関数fに対して、陰関数曲線

y - f = 0

を作成し、Tangentコマンドを実行すれば、任意の点から関数 f に、いくつかの接線を引くことができる。

3次関数くらいなら、こちらの方法で十分対応可能である。複雑な関数(たとえば、cos(2x)sin(x) )を扱うと、接線の返し漏れが生じる場合もあるようだ。

以下では、すべての接線を漏れなく返す方法を紹介していく。

構文

まずは(可読性はともかく)接線をどんな定義で描いているのかを紹介しよう。

関数f、点Aを所与として、点Aを通る関数fの接線のリストは、GeoGebraでは以下のように表せる。

Unique[Zip[Tangent[s, f], s, Unique[Join[{{Intersect[f(x) + f'(x) (x(A) - x) - y(A), x - x, x(Corner[1]), x(Corner[2])]}, KeepIf[f(x(s)) + f'(x(s)) (x(A) - x(s)) - y(A) ≟ 0, s, {Intersect[Derivative[f(x) + f'(x) (x(A) - x) - y(A)], x - x, x(Corner[1]), x(Corner[2])]}]}]]]]

基本設計

上記の定義を、順に説明しよう。

まず、新たな関数gを、以下の定義で作成する。

g(x) = f(x) + f'(x) (x(A) - x) - y(A)

すると、gの定義上、g(x) = 0 を満たすxの値は、点Aからfのグラフに接線を引いた場合の、(各)接点のx座標と一致する。

ところで、gのグラフとx軸との交点のリストは、GeoGebraでは以下のように表せる。

{Intersect[g, x - x, x(Corner[1]), x(Corner[2])]}

Intersectコマンドの構文のうち、

Intersect[ <オブジェクト>, <オブジェクト> ]

は、1つの交点しか返さない。

したがって、例えば

{Intersect[g, y = 0]}

 と書いても、gのグラフとx軸との交点を、1つしか返してくれない。せめて画面(グラフィックスビュー)上に見えている交点は、すべて返してほしいものである。つまり、せいぜい

x(Corner[1]) <= x <= x(Corner[2])

区間くらいは、全ての交点を返してほしい。

そこで、Intersectの別構文

Intersect[ <関数>, <関数>, <x開始値>, <x終了値> ]

を使う。これを使えば、区間内の全ての交点を返してくれる。問題は、第二引数で、「x軸」を、いかにしてxの関数としてGeoGebraに認識させるかである。

{Intersect[g, y=0, x(Corner[1]), x(Corner[2])]}

では、構文エラーとなる。GeoGebraが、第二引数y=0を、xの関数とは認識してくれないからである。うまくいくのは、

{Intersect[g, x - x, x(Corner[1]), x(Corner[2])]} 

である。これによって、gのグラフとx軸との交点のリストを得られる。このリストをlistGとしよう。

あとは、

Zip[Tangent[s, f], s, listG]

で、目的の接線リストが得られる。これは、

Tangent[ <点P>, <関数f> ]

で、f上の点( x(P), f( x(P) ) )におけるfの接線を得られることを利用している。Zipコマンドについての解説は省く(公式マニュアル参照)。

細かい仕様への対応

以上が基本的なアイデアだが、話はこれだけでは済まない。GeoGebraの細かい仕様に対応しなければならない。

上記でlistGとして紹介した

{Intersect[g, x - x, x(Corner[1]), x(Corner[2])]}

は、関数gとx軸が(交わらず)接するだけのとき、その接点を返してくれない。しかし、これもg(x) = 0を満たす以上、無視できない。そこで、いったん、gの導関数g'と、x軸との交点リストlistG'を作る。その定義は以下のとおりである。

{Intersect[g', x - x, x(Corner[1]), x(Corner[2])]}

さらに、

KeepIf[g(x(s)) ≟ 0, s, listG']

によって、listG'の要素のうち、gとx軸との接点のみを抽出する。これで、Intersectコマンドが返し漏らした、gとx軸との接点のリストを得ることができた(このリストを、listGTangentとしよう)。

目的の接線リストを得るための数式として上述した、

Zip[Tangent[s, f], s, listG]

のうち、listGの部分を、Join[{listG, listGTangent}]に置き換える。これで、返し漏らしを回収できる。

Zip[Tangent[s, f], s, Join[{listG, listGTangent}]]

以上の処理をすべてネストしたものが、「構文」の項で紹介した定義である。なお、当該定義においては、重複を削除するUniqueコマンドを入れている。

※これでもまだ、Intersectのデリケートな仕様に完璧に対応できているわけではない。したがって、予期せず描画の厳密性を欠く場合があるかもしれない。あくまで参考程度の描画方法と考えて頂きたい。

オリジナルツール「PerfectTangent」

上記知見を用いて、オリジナルツールを作成した。

PerfectTangent[ <点>, <関数> ]

で、点から関数グラフに引いた接線のリストを返す。

PerfectTangent Tool - GeoGebra