• ベストアンサー

角度を求めるプログラム

x,y座標上の2点を結んでできる線の度数での角度(45度、270度といった) を得たいのですがそういうプログラムまたは関数などはあるのでしょうか? 例えばA(0,1)とB(1,2)だと、B-Aでx=1,y=1になりy/x=1という数字が出てきます。 この1が45度になるようなアルゴリズムが知りたいです。

質問者が選んだベストアンサー

  • ベストアンサー
  • wp_
  • ベストアンサー率54% (132/242)
回答No.5

>>度数=90 x=6.12303176911E-17 y=1 >>度数=180 x=-1 y=1.22460635382E-16 >>度数=270 x=-1.83690953073E-16 y=-1 あー。 よくある話ですね。 これはコンピュータを扱う上で避けられない仕様です。 // たまにバグと言う奴が居ますがバグではありません。 // バグと言う奴には哀れみの眼差しを送りましょう。 無理数piや三角関数の結果などは正確な値を用いて計算しているわけではありません。 コンピュータとて有限の資源(メモリ)を使って計算しているわけですから、必ずどこかで値を丸めて使っています。 この場合ですと、$aが完全なpi/2を使っているわけではなく(正確にはpi/2を11桁くらいで丸めた値)、そのせいでsin,cosが通常では表せない極小な値を吐こうとしているのでしょう。 対策としては、cosで吐かれた値を明示的に丸めることが考えられます。 パッと思いついた感じでは以下の感じですかね。 $fig = 10000000; // 小数点以下8桁で丸め $a = deg2rad($i); $c_tmp = cos($a); $s_tmp = sin($a); // 整数部位以下を捨ててもう一回割ると0.00000000001のような数字は0になる $c = intval($c_tmp * $fig) / $fig; $s = intval($s_tmp * $fig) / $fig; なにか適用できる関数があった気もしますが。 sprintfでも丸めて表示が出来たかもしれません。

takagoo100
質問者

お礼

ご返答ありがとうございます。 なるほど、これは無限ではなくて小さい値だったんですね、勘違いしてました・・・ 試してみましたが0にすることができました。ありがとうございます。

その他の回答 (4)

  • wp_
  • ベストアンサー率54% (132/242)
回答No.4

ここまでくると数学の問題ですな^^; >度数からx,yの値を求める方法をご存知でしたら教えてもらえないでしょうか? 普通に度数をラジアン単位に直し、sin()やcos()をかませば求められますよ。 幸いにもphpにはラジアン単位に直す関数があるので利用すると良いかと。 まにゅある deg2rad() http://jp.php.net/deg2rad ただ、ラジアン単位だけでは正弦・余弦の値しか求められないので、 座標を求めると言う意味では一次結合で使うような係数が必要かと思われます。

takagoo100
質問者

お礼

ご返答ありがとうございます。 たしかに完全に数学ですね・・・ 早速試してみたのですが、sinをy、cosをxとみなして調べてみたら理想とする結果がでてきました。 ただ90度、180度、270度の時に無限と思われる値がでてきて >度数=90 x=6.12303176911E-17 y=1 >度数=180 x=-1 y=1.22460635382E-16 >度数=270 x=-1.83690953073E-16 y=-1 これをなんとかして0にできないかと試したのですが無理でした・・・ 下が例ですが、 for ($i = 0; $i < 360; $i++) { $a = deg2rad($i); $c = cos($a); $s = sin($a); // if (is_infinite($s)){ $s = 0; } // if (is_infinite($c)){ $c = 0; } if ($c < -1 || 1 < $c){ $c = 0; } if ($s < -1 || 1 < $s){ $s = 0; } print "度数={$i} x={$c} y={$s}<br>\n"; } is_infinite関数や-1より下または1より上でのチェックが効きません・・・ この場合の数のチェックは何を使えば良いのかご存知でしょうか?

  • wp_
  • ベストアンサー率54% (132/242)
回答No.3

答えは既に出ておりますけども、 円周率はpi()を使った方が見やすいかもですね。 好みの問題ですけど^^; まにゅある 円周率 http://jp.php.net/pi

takagoo100
質問者

お礼

ご返答ありがとうございます。 たしかにpi()を使った方が良さそうですね。ありがとうございます。 追加で申し訳ないのですが、wp_さんにもNo.1のお礼で説明している 度数からx,yの値を求める方法をご存知でしたら教えてもらえないでしょうか? お願いします。

  • sayaama
  • ベストアンサー率44% (8/18)
回答No.2

<?php $a = atan2(1,1);//y,x $deg = $a * 180.0 / 3.14159265358979323846; printf($deg); ?> でどうですか? atan2は、x=0であっても正しく計算されます。 $a = atan2(1,0); $deg = $a * 180.0 / 3.14159265358979323846; とすれば、$deg=90となります。

takagoo100
質問者

お礼

ご返答ありがとうございます。 全ての値で度数が求まりました。ありがとうございます。 追加で申し訳ないのですが、sayaamaさんにもNo.1のお礼で説明した 度数からx,yの値を求めるやり方を考えてもらないでしょうか? お願いします。

  • 10ken16
  • ベストアンサー率27% (475/1721)
回答No.1

方向ベクトルの傾きを正接とする角を求めればいいので、 x2≠x1のとき (y2-y1)/(x2-x1)のアークタンジェントではだめですか?

takagoo100
質問者

お礼

ご返答ありがとうございます。 そのやり方でできました。ありがとうございます。 追加で申し訳ないのですが、 求めた度数(90度270度など)から逆にx,yの値を求めることはできないでしょうか? 例えばANo.2のsayaamaさんで紹介されたプログラムを利用して求めると (1,0)が90度になるのですが、 >$a = atan2(1,0);//y,x >$deg = $a * 180.0 / 3.14159265358979323846; これをどのように逆算すればx,yの値が求まるのでしょうか? ((1,1)の45度の場合など、(2,2)でも同じことなので、 x,yの値は-1から1までの間ということになると思います)

関連するQ&A