root/as3/Utils/src/org/libspark/utils/GeomUtil.as

リビジョン 804, 15.3 kB (コミッタ: michi, コミット時期: 2 年 前)

asdoc追加

Line 
1 /*
2  * Copyright(c) 2006-2008 the Spark project.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific language
14  * governing permissions and limitations under the License.
15  */
16
17
18 package org.libspark.utils
19 {
20
21     import flash.display.DisplayObject;
22     import flash.errors.IllegalOperationError;
23     import flash.geom.Matrix;
24     import flash.geom.Point;
25     import flash.geom.Rectangle;
26     import flash.geom.ColorTransform;
27     import flash.geom.Transform;
28    
29     /**
30      * 図形計算のためのユーティリティクラスです
31      */
32         public class GeomUtil
33     {
34        
35         /**
36          * @private
37          */
38         public function GeomUtil()
39         {
40             throw new IllegalOperationError("Error #2012: GeomUtil class cannot be instantiated.");
41         }
42        
43         /**
44          * 2つのPoint間の角度を求めます
45          * @param       pt1
46          * @param       pt2
47          * @return  2点間の角度
48          * @author  michi at seyself.com
49          */
50         public static function angle( pt1:Point, pt2:Point ):Number
51         {
52             return Math.atan2( pt2.y - pt1.y, pt2.x - pt1.x );
53         }
54        
55         /**
56          * 極座標ペアを直交点座標に変換し、指定のポイント(座標)に加算した新しいポイントを作成します。
57          *
58          * @param       pt 追加するポイント
59          * @param       len 極座標ペアの長さ座標
60          * @param       angle 極座標ペアの角度 (ラジアン単位)
61          * @return  新しいポイント
62          * @author  michi at seyself.com
63          */
64         public static function addPolar( pt:Point, len:Number, angle:Number ):Point
65         {
66             return pt.add( Point.polar( len, angle ) );
67         }
68        
69         /**
70         * 3つ以上の直線によって構成された多角形の面積を求めます.
71         * 引数には x, y の数値プロパティを持つオブジェクトを3つ以上渡す必要があります.
72         *
73         * @param arguments  x, y の数値プロパティを持つオブジェクト
74         * @return 面積
75         * @author  michi at seyself.com
76         */
77         public static function polygonArea( ...points ):Number
78         {
79             var leng:uint = points.length;
80             var products:Number = 0;
81             for(var i:uint=0;i<leng;i++){
82                 var n:Number = (i==leng-1)? 0 : i+1;
83                 var p:Object = points[i];
84                 var q:Object = points[n];
85                 var product:Number = (p.x-q.x)*(p.y+q.y);
86                 products += product;
87             }
88             return products/2;
89         }
90        
91         /**
92         * 楕円形の面積を求めます.
93         * 楕円を求めるには最短の直径と最長の直径が分かっていないといけません.
94         *
95         * @param width  楕円の最短の直径
96         * @param height  楕円の最長の直径
97         * @return 面積
98         * @author  michi at seyself.com
99         */
100         public static function ellipseArea( width:Number , height:Number ):Number
101         {
102             return (width/2)*(height/2)*Math.PI;
103         }
104        
105         /**
106         * 楕円形の円周の近似値を求めます(楕円積分).
107         * 楕円を求めるには最短の直径と最長の直径が分かっていないといけません.
108         *
109         * @param width  楕円の最短の直径
110         * @param height  楕円の最長の直径
111         * @return 円周の近似値
112         * @author  michi at seyself.com
113         */
114         public static function circumference( width:Number , height:Number ):Number
115         {
116             var a:Number = Math.min( width , height );
117             var b:Number = Math.max( width , height );
118             var c:Number = (a-b)/(a+b);
119             return Math.PI*(a+b)*( 1+1/4*Math.pow(c,2)+1/64*Math.pow(c,4)+1/256*Math.pow(c,6));
120         }
121        
122        
123         /**
124         * 直線AB と直線CD の交点を求めます.
125         * 2つの直線が平行である場合は null を返します.
126         *
127         * @param a  直線AB の点Aの座標( x, y の数値プロパティを持つオブジェクト )
128         * @param b  直線AB の点Bの座標( x, y の数値プロパティを持つオブジェクト )
129         * @param c  直線CD の点Cの座標( x, y の数値プロパティを持つオブジェクト )
130         * @param d  直線CD の点Dの座標( x, y の数値プロパティを持つオブジェクト )
131         * @return 2直線の交点座標
132         * @author  michi at seyself.com
133         */
134         public static function intersection( a:Object, b:Object, c:Object, d:Object ):Point
135         {
136             var pos1:Number = (b.y-a.y)/(b.x-a.x);
137             var pos2:Number = (d.y-c.y)/(d.x-c.x);
138             var pi:Number = Number.POSITIVE_INFINITY;
139             var ni:Number = Number.NEGATIVE_INFINITY;
140            
141             if(pos1==pos2) return null;
142             if( pos1 == ni || pos1 == pi ) pos1 = b.y-a.y;
143             if( pos2 == ni || pos2 == pi ) pos2 = d.y-c.y;
144            
145             var nx:Number = ( ( a.x*pos1 ) - a.y - ( c.x*pos2 ) + c.y )/( pos1-pos2 );
146             var ny:Number = pos1*( nx-a.x ) + a.y;
147            
148             return new Point( nx, ny );
149         }
150        
151         /**
152          * 指定オブジェクトのプロパティ x, y から新しい Point インスタンスを作成します。
153          *
154          * @param       target 指定オブジェクト
155          * @return  新しい Point インスタンス
156          * @author  michi at seyself.com
157          */
158         public static function getPoint( target:Object ):Point
159         {
160             var pt:Point = new Point();
161             if ( target.hasOwnProperty("x") ) pt.x = target.x;
162             if ( target.hasOwnProperty("y") ) pt.y = target.y;
163             return pt;
164         }
165        
166         /**
167          * 指定オブジェクトのプロパティ x, y, width, height から新しい Rectangle インスタンスを作成します。
168          *
169          * @param       target 指定オブジェクト
170          * @return  新しい Rectangle インスタンス
171          * @author  michi at seyself.com
172          */
173         public static function getRect( target:Object ):Rectangle
174         {
175             var rect:Rectangle = new Rectangle();
176             if ( target.hasOwnProperty("x") )      rect.x      = target.x;
177             if ( target.hasOwnProperty("y") )      rect.y      = target.y;
178             if ( target.hasOwnProperty("width") )  rect.width  = target.width;
179             if ( target.hasOwnProperty("height") ) rect.height = target.height;
180             return rect;
181         }
182        
183         /**
184          * 指定オブジェクトのプロパティ x, y に、それぞれポイントの値を代入します。
185          *
186          * @param       target 指定オブジェクト
187          * @param       pt 適応する Point オブジェクト
188          * @author  michi at seyself.com
189          */
190         public static function setPoint( target:Object, pt:Point ):void
191         {
192             if ( target.hasOwnProperty("x") ) target.x = pt.x;
193             if ( target.hasOwnProperty("y") ) target.y = pt.y;
194         }
195        
196         /**
197          * 指定オブジェクトのプロパティ x, y, width, height に、それぞれ Rectangle の値を代入します。
198          *
199          * @param       target 指定オブジェクト
200          * @param       rect 適応する Rectangle オブジェクト
201          * @author  michi at seyself.com
202          */
203         public static function setRect( target:Object, rect:Rectangle ):void
204         {
205             if ( target.hasOwnProperty("x") )      target.x      = rect.x;
206             if ( target.hasOwnProperty("y") )      target.y      = rect.y;
207             if ( target.hasOwnProperty("width") )  target.width  = rect.width;
208             if ( target.hasOwnProperty("height") ) target.height = rect.height;
209         }
210        
211         /**
212          * 指定のマトリックスオブジェクトから回転値(ラジアン単位)を調べます。
213          *
214          * @param       mt 対象となるマトリックスオブジェクト
215          * @return  回転値(ラジアン単位)
216          * @author  michi at seyself.com
217          */
218         public static function getRotateFromMatrix(mt:Matrix):Number
219         {
220             var sx:Number = Math.sqrt(mt.a * mt.a + mt.b * mt.b);
221             var angle:Number = Math.acos( mt.a / sx );
222             if (mt.b < 0) angle *= -1;
223             return angle;
224         }
225        
226         /**
227          * 指定のマトリックスオブジェクトから拡大・縮小値を調べます。
228          * scaleX 、 scaleY は、それぞれ新たに作成されたポイントオブジェクトの x , y に代入されます。
229          *
230          * @param       mt 対象となるマトリックスオブジェクト
231          * @return  拡大率の情報を持つポイントオブジェクト
232          * @author  michi at seyself.com
233          */
234         public static function getScaleFromMatrix(mt:Matrix):Point
235         {
236             var sx:Number = Math.sqrt(mt.a * mt.a + mt.b * mt.b);
237             var sy:Number = Math.sqrt(mt.c * mt.c + mt.d * mt.d);
238             return new Point(sx, sy);
239         }
240        
241         /**
242          * 指定のマトリックスオブジェクトから位置情報を調べ、ポイントオブジェクトを作成します。
243          *
244          * @param       mt 対象となるマトリックスオブジェクト
245          * @return  位置情報を持つポイントオブジェクト
246          * @author  michi at seyself.com
247          */
248         public static function getPositionFromMatrix(mt:Matrix):Point
249         {
250             return new Point(mt.tx, mt.ty);
251         }
252        
253         /**
254          * 指定のマトリックスオブジェクトから Matrix.createBox の逆算を行います。
255          * getRotateFromMatrix や getScaleFromMatrix で得られる結果とは異なりますので注意してください。
256          *
257          * @param       mt 対象となるマトリックスオブジェクト
258          * @return  scaleX, scaleY, rotation, x, y のプロパティを持つオブジェクト
259          * 得られた結果オブジェクトは toString() で内容を確認用の文字列に変換します。
260          */
261         public static function degradeBox(mt:Matrix):Object
262         {
263             var t:Number = mt.a * mt.d - mt.b * mt.c;
264             var sx:Number = Math.sqrt(mt.a * mt.a + mt.c * mt.c);
265             var sy:Number = t / sx;
266             var angle:Number = Math.acos( mt.a / sx );
267             var obj:Object = { scaleX:sx , scaleY:sy, rotation:angle, x:mt.tx, y:mt.ty };
268             obj.toString = function():String {
269                 return "(scaleX="+this.scaleX+" , scaleY="+this.scaleY+
270                      ", rotation="+this.rotation+", x="+this.x+", y="+this.y+")";
271             }
272             return obj;
273         }
274        
275         /**
276          * 3つの座標数値から2次ベジェ曲線のコントロールポイントの座標を取得します。
277          *
278          * @param       start 始点の座標数値
279          * @param       passage 通過点の座標数値
280          * @param       anchor 終点の座標数値
281          * @return  コントロールポイントの座標数値
282          * @author  michi at seyself.com
283          */
284         public static function getCurveControlPoint( start:Number, passage:Number, anchor:Number ):Number
285         {
286             return ( passage * 4 - start - anchor ) * 0.5;
287         }
288        
289         /**
290          * 3つの座標数値から2次ベジェ曲線の中間座標を取得します。
291          *
292          * @param       a 始点の座標数値
293          * @param       b コントロールポイントの座標数値
294          * @param       c 終点の座標数値
295          * @param       t 曲線の進度値。0 から 1 の小数値で指定します。
296          * @return  指定された時点におけるベジェ式の値。
297          * @author  michi at seyself.com
298          */
299         public static function quadraticBezier( a:Number, b:Number, c:Number, t:Number ):Number
300         {
301             var s:Number = 1-t;
302             return s*s*a + 2*s*t*b + t*t*c;
303         }
304        
305         /**
306          * 4つの座標数値から3次ベジェ曲線の中間座標を取得します。
307          *
308          * @param       a 始点の座標数値
309          * @param       b 点 a のコントロールポイントの座標数値
310          * @param       c 点 b のコントロールポイントの座標数値
311          * @param       d 終点の座標数値
312          * @param       t 曲線の進度値。0 から 1 の小数値で指定します。
313          * @return  指定された時点におけるベジェ式の値。
314          * @author  michi at seyself.com
315          */
316         public static function cubicBezier( a:Number, b:Number, c:Number, d:Number, t:Number ):Number
317         {
318             var s:Number = 1-t;
319             return s*s*s*a + 3*s*s*t*b + 3*s*t*t*c + t*t*t*d;
320         }
321        
322                 /**
323                  * 4つの座標数値からスプライン曲線の中間座標を取得します。
324                  *
325                  * @param       p0 始点座標数値
326                  * @param       p1 通過点座標数値(求められる曲線の始点)
327                  * @param       p2 通過点座標数値(求められる曲線の終点)
328                  * @param       p3 終点座標数値
329                  * @param       t 2 つの座標間の補間値。 0 から 1 までの数値
330                  * @return  p1 から p2 の間にある t の位置を示す座標値
331                  * @author  michi at seyself.com
332                  */
333         public static function spline(p0:Number, p1:Number, p2:Number, p3:Number, t:Number):Number
334         {
335             var v0:Number = (p2 - p0) * 0.5;
336             var v1:Number = (p3 - p1) * 0.5;
337             var t2:Number = t * t;
338             var t3:Number = t2 * t;
339             return (2 * p1 - 2 * p2 + v0 + v1) * t3 +
340                 ( -3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
341         }
342        
343         /**
344          * 指定されたオブジェクトのストリング表現を返します。
345          *
346          * @param       target 出力対象オブジェクト
347          * @return  オブジェクトのストリング表現
348          * @author  michi at seyself.com
349          */
350         public static function toString(target:Object):String
351         {
352             if (target is Rectangle) return target.toString();
353             if (target is Point) return target.toString();
354             if (target is ColorTransform) return target.toString();
355             if (target is Transform) {
356                 target = target.matrix;
357             }
358            
359             if (target is Matrix) {
360                 var mt:Matrix = target as Matrix;
361                 return degradeBox(mt).toString();
362             }
363            
364             return getRect(target).toString();
365         }
366        
367     }
368
369 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。