トップページ > 記事閲覧
画像を90度の倍数角に回転させる
名前:MKII 日時: 2019/11/21 12:18

画像を回転させて描画したい場合、DrawRotaGraph() 関数を使ってます。 ですが、この関数に指定する描画角度はラジアンなので、90度にしたい場合は PI/2 になる。 そこで思いついたことですが、特殊の角度(90,180,270)なら、 浮動小数点数型の計算は一切いらないで素早く(且つ精確に)計算できるじゃない?
メンテ

Page: 1 |

Re: 画像を90度の倍数角に回転させる ( No.1 )
名前:管理人 日時:2019/11/21 23:32

> そこで思いついたことですが、特殊の角度(90,180,270)なら、 > 浮動小数点数型の計算は一切いらないで素早く(且つ精確に)計算できるじゃない? 確かにその通りです 現在のCPUの性能を考えると態々専用の関数を使用する必要があるシチュエーションはかなり少なそうですが…
メンテ
Re: 画像を90度の倍数角に回転させる ( No.2 )
名前:MKII 日時:2019/11/24 17:38

確かに、専用の関数に分けでも色々使い分けしないといけないので正直面倒くさい。 こんな形はいかがでしょう:『ラジアンの代わりに、角度を使う』回転関数を用意する。 先ずは90度単位で回転し、残った角度を内部でラジアンを換算して回転する。 2Dゲームなら割と90度単位の回転使うことが多いと思う。 そうじゃない場合でも、ラジアンを計算する場合、PI の使用---と float 型 の精度---の関係で、 どうしても「回転角度が0に近い程精度が高い、遠い程精度が落ちる。」 逆に90度の回転は絶対精確なので、組合せば回転の精度を上げるじゃない? 編集:すみません見間違いました。Angle 引数は float 型でわなく double 型です。 (float 型のは DrawRotaGraphFast でした)
メンテ
Re: 画像を90度の倍数角に回転させる ( No.3 )
名前:NNN 日時:2019/11/23 22:20

<こんな形はいかがでしょう:『ラジアンの代わりに、角度を使う』回転関数を用意する。 これはMKIIさんが用意すれば良いのではないでしょうか? if( 角度 % 90 == 0 ) DrawGraph( ..., 回転済みグラフィック ); else DrawRotaGraph( ... ); DXライブラリに整数型(?)の角度を引数とする関数を用意するというのは使用頻度の割に影響範囲が大きすぎに思えます
メンテ
Re: 画像を90度の倍数角に回転させる ( No.4 )
名前:名無三 日時:2019/11/24 12:00

math.h関連などでもラジアンを用いることや、整数型の角度だとかなり精度が落ちるので… 2Dオンリーであれば普通にデータの方を用意した方が(あまりにも考慮に値するには差が小さすぎますが)速度は上がるのではないでしょうか? 精度の問題もー3.14〜3.14の範囲ですれば誤差は少ないでしょうし。
メンテ
Re: 画像を90度の倍数角に回転させる ( No.5 )
名前:管理人 日時:2019/11/25 02:00

> 確かに、専用の関数に分けでも色々使い分けしないといけないので正直面倒くさい。 >  > こんな形はいかがでしょう:『ラジアンの代わりに、角度を使う』回転関数を用意する。 >  > 先ずは90度単位で回転し、残った角度を内部でラジアンを換算して回転する。 こちらの『角度』の引数は int型でしょうか? もし『角度』も float や double の浮動小数点型の場合、ラジアンが角度になっただけのような… int型の場合は、確かに 0〜359 の sin, cos の結果をテーブルで持っておけば若干の処理速度の向上と、 int型なので仮に 482554681度 のような、float型なら精度が落ちそうな角度でも精度を落ちない結果が得られそうです ( ただ、小数点以下の角度が指定できないこと自体を『精度が低い』と言ってしまえばそれまでですが… )
メンテ
Re: 画像を90度の倍数角に回転させる ( No.6 )
名前:MKII 日時:2019/11/30 02:53

返事が遅くなってすみません。 >こちらの『角度』の引数は int型でしょうか? いいえ、double 型です。プログラム的に、ラジアンでも角度でも簡単に換算出来ますのでどちでもいい。 ですがラジアンの場合、特殊の角度を指定するのは(無理ではないが)難しい。 PIに掛かるので、『引数を計算する段階』から捨入誤差が生じる。 特殊の角度(90度など)を直観的に引数として指定できるように、ラジアンの代わりに角度を使うことを提案しました。 整数角度の場合 double 90.0 == int 90 なので、引数の段階では何の捨入も生じません。 ーーーーーーーーーー 以前に仰る通り、現在のCPUの性能を考えると処理速度に関しての特殊処理はあんまり気にする必要がないようですが、 自分が言いたい「精度」は resolution や precision ではなく, accuracy です。 例えば90度単位で回転する場合、accuracy は絶対です。 ラジアンを使う場合、引数は「本当の」PI/2 ではなくその捨入した後の計算結果なので、非常に90度に近い角度で回転することになる。 ーーーーーーーーーー 自分が考えた関数はこんな感じです: void RotateByDegrees(double angle_in_degrees) { RotateBy90Degrees( (int)angle_in_degrees / 90 ); // 90 度で回転する回数、accuracy は絶対です(0 の場合は即終了) RotateByRadians(angle_in_degrees % 90 * PI / 180); // ここで捨入誤差の問題で precision が落ちる(angle % 90 == 0 の場合は即終了なので落ちない) } ラジアン使う回転は如何しても精度(precision)誤差があるので、それを使う以前出来るだけ精確(accuracy)に90度単位で回転する。
メンテ
Re: 画像を90度の倍数角に回転させる ( No.7 )
名前:管理人 日時:2019/12/01 23:38

ご解説ありがとうございます、ラジアンの代わりに角度を使用する意義は分かりました ただ、整数型ではなく浮動小数点型を使用する以上「回転角度が0に近い程精度が高い、遠い程精度が落ちる。」は 単位がラジアンでも角度でも変わりませんので、やはりあまり意味が無いように感じます ( 例えば float Angle = 90.0f; に Angle += 0.1234f; を実行した後の Angle の値は 90.1233978f ですが、 float Angle = 90000.0f; に Angle += 0.1234f; を実行した後の Angle の値は 90000.1250f です )
メンテ
Re: 画像を90度の倍数角に回転させる ( No.8 )
名前:名無三 日時:2019/12/02 08:24

確かにどういう理屈なのかは理解できましたが、ほかの多数のDXLib関数や標準関数が皆ラジアンで計算しているので、その変換がとても面倒に感じます。 むしろDrawcirclegaugeなんかの例外をラジアンに統一する方が良いような… それに、精度が微妙に良くなる以外に利点はあるのでしょうか?描画する画面上でその1度未満の差が如実に現れるのでしょうか?
メンテ
Re: 画像を90度の倍数角に回転させる ( No.9 )
名前:MKII 日時:2019/12/03 21:08

「回転角度が0に近い程精度が高い、遠い程精度が落ちる」という自分の表現は間違ってます、お忘れください。 ーーーーーーーーーー 正直、PI に掛かる回転は結構多いと思う。引数を計算するたびに捨入誤差が生じる、どうしても PI を消せたい! 角度を引数にする発想を捨て、もっと本質的に:  『PI の乗数』(double 型) を引数にするのはどうでしょう? 内部では cos(ラジアン) の代わりに cospi(P Iの乗数) を使うことより、全体的に精度を上げると思う。
メンテ
Re: 画像を90度の倍数角に回転させる ( No.10 )
名前:管理人 日時:2019/12/04 00:36

cospi という関数は C言語の標準関数にはありませんので、最終的にラジアンに変換することになります また、名無三さんも仰られていますが、ラジアンで扱うか、角度で扱うかによる僅かな精度の違いは 描画結果には表れないと思います なので、申し訳ありませんが、以下のような引数を角度で取るラッパー関数を用意して対応するようにしてください m(_ _;m int DrawRotaGraphPI( int x, int y, double ExRate, double Angle, int GrHandle, int TransFlag, int ReverseXFlag = FALSE, int ReverseYFlag = FALSE ) { DrawRotaGraph( x, y, ExRate, Angle * PI, GrHandle, TransFlag, ReverseXFlag, ReverseYFlag ); }
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存