下図△ABCの、AとBの座標、そして各辺の長さが分かっているときに、点Cの座標を求めるには。
点Aと点Bからの距離がそれぞれわかっているので、円の方程式を使って解くことはできる。
とすると
これを解けば座標は出るだろうけど、なんともめんどくさい。
他に方法はないだろうか?と探してみて、見つけたのがコレ。
座標計算の公式 -土地家屋調査士の勉強してます。座標計算で、1秒でも- 数学 | 教えて!goo
回答番号:No.4 のものがプログラム的にも求めやすい。
ちょっと改造しつつ自分なりに書いてみる。
- まず点Aが原点にくるよう点Aと点Bを平行移動
- 点Bがx軸上にくるよう、原点(点A')を中心に回転移動
このときの角度は、arctanを使って求められる。
ここでx軸上に移動してきたB'のx座標をdとすると、これは点Aと点Bの距離なのでピタゴラスの定理を使って求めることができるし、
というように求めることもできる。
- A'から距離b, B'から距離aの点を求める
x軸上にある2点から、それぞれの距離を使って点C'の座標を求める。
とすると、
ピタゴラスの定理から
これを整理すると
となる。
また、△A'B'C'の面積Sは
で表され、
またヘロンの公式を使って
と表されるので、この2つから
が導きだされる。
y'は正負両方が存在することに注意。
- 回転を元に戻し、平行移動も元に戻す
こうして求めた点C'のx, y座標を、元通りに角だけ回転させてだけ平行移動させることで、求めたかった点Cの座標を求めることができる。
Perlで書くと
こんなカンジで求めることができる。
use Math::Trig 'atan'; sub calc_coordinate { my ($a, $b, $dist_from_a, $dist_from_b) = @_; my $alpha = atan(($b->{y} - $a->{y}) / ($b->{x} - $a->{x})); my $dist = ($b->{x} - $a->{x}) / cos($alpha); my $s = ($dist_from_a + $dist_from_b + $dist) / 2; my $tempX = ($dist_from_a ** 2 - $dist_from_b ** 2 + $dist ** 2) / ($dist * 2); my $tempY = 2 * sqrt($s * ($s - $dist_from_a) * ($s - $dist_from_b) * ($s - $dist)) / $dist; return [{ x => $tempX * cos($alpha) - $tempY * sin($alpha) + $a->{x}, y => $tempX * sin($alpha) + $tempY * cos($alpha) + $a->{y}, }, { x => $tempX * cos($alpha) + $tempY * sin($alpha) + $a->{x}, y => $tempX * sin($alpha) - $tempY * cos($alpha) + $a->{y}, }]; }