サイトトップ

Director Flash 書籍 業務内容 プロフィール

Adobe Flash非公式テクニカルノート

角度のように数値を循環させる

ID: FN1105001 Product: Flash CS3 and above Platform: All Version: 9 and above/ActionScript 3.0

DisplayObject.rotationプロパティは、インスタンスの角度を±180度の範囲の値で示します。そして、この範囲を超える数値を与えても、範囲内の角度に換算されて設定されます。このプロパティ値のように、決まった範囲内で値を循環させる計算について考えます。お題としては、やはりわかりやすいので角度を採上げます[*1]

[*1] 3次元空間におけるxyz各軸ごとにの角度を示すプロパティDisplayObject.rotationX/DisplayObject.rotationY/DisplayObject.rotationZも、値の範囲は±180とされます。しかし、DisplayObject.rotationプロパティとは異なり、範囲外の数値も設定できてしまいます。予期しない結果を招かないためには、予め設定値を決まった範囲に収めておくのが安心です。


01 角度を0から360度の範囲に換算する
まずは、任意の角度を0以上360未満の範囲に換算してみます。数値を0以上にかぎれば、剰余演算子%を使って簡単に計算できます。

数値 % 360

数値がマイナスのときは、剰余に360を加えなければなりません。そうすると、逆に正の場合に値が360以上になってしまいます。それだけでなく、負でも余りが0(たとえば-360)のとき360とされます。この問題を避けるには、改めて360の剰余をとればよいでしょう(表001)。計算の対象となる数値が変数nAngleに収められているとすれば、つぎのとおりです。

(nAngle % 360 + 360) % 360
表001■剰余の式と計算結果
数値
-360 -90 0 90 360
数値 % 360 0 -90 0 90 0
数値 % 360 + 360 360 270 360 450 360
(数値 % 360 + 360) % 360 0 270 0 90 0

正負に拘らずひとつの式で答えを導けることは、パズルの解き方としては優れています。しかし、正数であれば剰余は1回求めれば済むことを考えると、計算には無駄があります。正負を分けた方が、扱いは速められるでしょう。

nAngle %= 360;
if (nAngle < 0) {
  nAngle += 360;
}

360の剰余がマイナスのときのみ360を加えることとしました。これで、要らぬ計算が省けます。


02 角度を±180度の範囲に換算する
つぎは、角度を±180の範囲に換算します。値の幅は360ですので、その剰余をとるという考え方は変わりません。違ってくるのは、下限値が0でなく-180になることです。そこで、一旦180加えて、下限値を0にします。そして、前項と同じように換算した角度を求めたうえで、最後に改めて180を差引きます。これで、±180の範囲を循環する角度が導けます。

前項のスクリプトでは360の剰余をとった後、角度がマイナスのとき360を加えました。そのうえで180差引くなら、合算で180加えればよいことになります。したがって、つぎのスクリプトは、剰余後の正負を分けて計算しています。

nAngle += 180;
nAngle %= 360;
if (nAngle < 0) {
  nAngle += 180;
} else {
  nAngle -= 180;
}

頭から数値の正負それぞれについての式を立て、条件演算子?:により振分けると、もう少し最適化できます[*2]。つぎのスクリプトはラジアン値の±πなどにも応用しやすいように、定数をconst宣言しました。

const FULL:Number = 360;
const HALF:Number = FULL / 2;
nAngle   = (nAngle < 0)
? (nAngle - HALF) % FULL + HALF
: (nAngle + HALF) % FULL - HALF;

循環する数値の計算の仕方は、ほかにもいろいろあるでしょう[*3]

[*2] ただし、このスクリプトは180を-180に、-180は180に変換します。これらふたつは同じ角度とみるべきです。その前に掲げたスクリプトは、どちらの角度も-180とし、180という値を返すことはありません。角度の一意性という点からは、こちらの方が優れています。なお、DisplayObject.rotationプロパティには、ふたつの数値がそのまま設定されますので、角度の一意性について同じ問題があります。

[*3] 本文に紹介したスクリプトも含め、いくつかの計算方法をwonderflで比べてみました。

Restricting range of circulating value - wonderfl build flash online

なお、「radian角度をπ範囲に丸める方法まとめ」も参考になるでしょう。



作成者: 野中文雄
作成日: 2011年5月29日


Copyright © 2001-2011 Fumio Nonaka.  All rights reserved.