root/as2/Seyself/src/com/seyself/math/GeomMath.as

リビジョン 108, 11.0 kB (コミッタ: michi, コミット時期: 1 年 前)

--

Line 
1 /*
2 * Copyright 2007 Michiyasu Wada
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, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 import flash.geom.Point;
18
19 /**
20 * com.seyself.math.GeomMath
21 *
22 * 形状に関する計算処理もろもろ
23 * static関数のみで構成されています。
24 *
25 * @author               Michiyasu Wada
26 */
27 class com.seyself.math.GeomMath
28 {
29        
30         private function GeomMath(){}
31        
32         /**
33         * 3つ以上の直線によって構成された多角形の面積を求めます。
34         * 引数には x, y の数値プロパティを持つオブジェクトを3つ以上渡す必要があります。
35         *
36         * @param arguments : Point -  x, y の数値プロパティを持つオブジェクト
37         * @return Number - 面積
38         * @usage <code>
39         * import com.seyself.math.GeomMath;
40         * var a = { x:10 , y:50 };
41         * var b = { x:20 , y:30 };
42         * var c = { x:30 , y:50 };
43         * var d = { x:25 , y:80 };
44         * var e = { x:15 , y:80 };
45         * trace( GeomMath.polygonArea( a, b, c, d, e ) ); // 出力 : 650
46         * </code>
47         */
48         public static function polygonArea():Number
49         {
50                 var leng = arguments.length;
51                 var products = 0;
52                 for(var i=0;i<leng;i++){
53                         var n = (i==leng-1)? 0 : i+1;
54                         var p = arguments[i];
55                         var q = arguments[n];
56                         var product = (p.x-q.x)*(p.y+q.y);
57                         products += product;
58                 }
59                 return products/2;
60         }
61        
62         /**
63         * 楕円形の面積を求めます。
64         * 楕円を求めるには最短の直径と最長の直径が分かっていないといけません。
65         *
66         * @param width : Number -  楕円の最短の直径
67         * @param height : Number -  楕円の最長の直径
68         * @return Number - 面積
69         * @usage <code>
70         * import com.seyself.math.GeomMath;
71         * trace( GeomMath.ellipseArea( 50 , 100 ) ); // 出力 : 3926.99081698724
72         * </code>
73         */
74         public static function ellipseArea( width:Number , height:Number ):Number
75         {
76                 return (width/2)*(height/2)*Math.PI;
77         }
78        
79         /**
80         * 楕円形の円周の近似値を求めます。(楕円積分)
81         * 楕円を求めるには最短の直径と最長の直径が分かっていないといけません。
82         *
83         * @param width : Number -  楕円の最短の直径
84         * @param height : Number -  楕円の最長の直径
85         * @return Number - 円周の近似値
86         * @usage <code>
87         * import com.seyself.math.GeomMath;
88         * trace( GeomMath.circumference( 50 , 100 ) ); // 出力 : 3926.99081698724
89         * </code>
90         */
91         public static function circumference( width:Number , height:Number ):Number
92         {
93                 var a = Math.min( width , height );
94                 var b = Math.max( width , height );
95                 var c = (a-b)/(a+b);
96                 return Math.PI*(a+b)*( 1+1/4*Math.pow(c,2)+1/64*Math.pow(c,4)+1/256*Math.pow(c,6));
97         }
98        
99        
100         /**
101         * 直線AB と直線CD の交点を求めます。
102         * 2つの直線が平行である場合は null を返します。
103         *
104         * @param a : Point -  直線AB の点Aの座標( x, y の数値プロパティを持つオブジェクト )
105         * @param b : Point -  直線AB の点Bの座標( x, y の数値プロパティを持つオブジェクト )
106         * @param c : Point -  直線CD の点Cの座標( x, y の数値プロパティを持つオブジェクト )
107         * @param d : Point -  直線CD の点Dの座標( x, y の数値プロパティを持つオブジェクト )
108         * @return Point - 2直線の交点座標
109         * @usage <code>
110         * import com.seyself.math.GeomMath;
111         * var a = { x:0 , y:0 };
112         * var b = { x:200 , y:200 };
113         * var c = { x:100 , y:0 };
114         * var d = { x:50 , y:200 };
115         * trace( GeomMath.intersection( a, b, c, d ) ); // 出力 : (x=80, y=80)
116         * </code>
117         */
118         public static function intersection( a:Object, b:Object, c:Object, d:Object ):Point
119         {
120                 var pos1 = (b.y-a.y)/(b.x-a.x);
121                 var pos2 = (d.y-c.y)/(d.x-c.x);
122                 var pi = Number.POSITIVE_INFINITY;
123                 var ni = Number.NEGATIVE_INFINITY;
124                
125                 if(pos1==pos2){
126                         return null;
127                 }
128                 if( pos1 == ni || pos1 == pi ){
129                         pos1 = b.y-a.y;
130                 }
131                 if( pos2 == ni || pos2 == pi ){
132                         pos2 = d.y-c.y;
133                 }
134                
135                 var nx = ( ( a.x*pos1 ) - a.y - ( c.x*pos2 ) + c.y )/( pos1-pos2 );
136                 var ny = pos1*( nx-a.x ) + a.y;
137                
138                 return new Point( nx, ny );
139         }
140        
141         /**
142         * 2次ベジェ曲線を描くための座標を求めます.
143         * 引数には x, y の数値プロパティを持つオブジェクトを3つと中間点の数を渡す必要があります.
144         * <listing>
145         * import flash.display.Sprite;
146         * import flash.geom.Point;
147         * import com.seyself.math.GeomMath;
148         *
149         * var t:Number = 0;
150         * var a:Point = new Point( 0, 0 );
151         * var b:Point = new Point( 20, 70 );
152         * var c:Point = new Point( 100, 100 );
153         *
154         * var sprite:Sprite = new Sprite();
155         * this.addChild( sprite );
156         * sprite.graphics.lineStyle( 1 , 0 , 1 );
157         * sprite.graphics.moveTo( a.x , a.y );
158         * for(t=0;t<=1;t+=0.05){
159         *       var p:Point = GeomMath.quadraticBezier( a, b, c, t );
160         *       sprite.graphics.lineTo( p.x , p.y );
161         *       trace( p );
162         * }
163         * </listing>
164         *
165         * @param a : Point -  開始点( x, y の数値プロパティを持つオブジェクト )
166         * @param b : Point -  アンカー( x, y の数値プロパティを持つオブジェクト )
167         * @param c : Point -  終了点( x, y の数値プロパティを持つオブジェクト )
168         * @param t : Number -  戻り値が持つ座標の数
169         * @return Array - 曲線の座標
170         */
171         public static function quadraticBezier( a:Object, b:Object, c:Object, t:Number ):Point
172         {
173                 var s:Number = 1-t;
174                 var nx:Number = s*s*a.x + 2*s*t*b.x + t*t*c.x;
175                 var ny:Number = s*s*a.y + 2*s*t*b.y + t*t*c.y;
176                 return new Point( nx , ny );
177         }
178        
179         /**
180         * 3次ベジェ曲線を描くための座標を求めます.
181         * 引数には x, y の数値プロパティを持つオブジェクトを4つと中間点の数を渡す必要があります.
182         * <listing>
183         * import flash.display.Sprite;
184         * import flash.geom.Point;
185         * import com.seyself.math.GeomMath;
186         *
187         * var t:Number = 0;
188         * var a:Point = new Point( 0, 0 );
189         * var b:Point = new Point( 12, 60 );
190         * var c:Point = new Point( 80, 20 );
191         * var d:Point = new Point( 100, 100 );
192         *
193         * var sprite:Sprite = new Sprite();
194         * this.addChild( sprite );
195         * sprite.graphics.lineStyle( 1 , 0 , 1 );
196         * sprite.graphics.moveTo( a.x , a.y );
197         * for(t=0;t<=1;t+=0.05){
198         *       var p:Point = GeomMath.cubicBezier( a, b, c, d, t );
199         *       sprite.graphics.lineTo( p.x , p.y );
200         *       trace( p );
201         * }
202         * </listing>
203         *
204         * @param a  開始点( x, y の数値プロパティを持つオブジェクト )
205         * @param b  点 a のアンカー( x, y の数値プロパティを持つオブジェクト )
206         * @param c  点 b のアンカー( x, y の数値プロパティを持つオブジェクト )
207         * @param d  終了点( x, y の数値プロパティを持つオブジェクト )
208         * @param t  戻り値が持つ座標の数
209         * @return 曲線の座標
210         */
211         public static function cubicBezier( a:Object, b:Object, c:Object, d:Object, t:Number ):Point
212         {
213                 var s:Number = 1-t;
214                 var nx:Number = s*s*s*a.x + 3*(s*s)*t*b.x + 3*s*(t*t)*c.x + t*t*t*d.x;
215                 var ny:Number = s*s*s*a.y + 3*(s*s)*t*b.y + 3*s*(t*t)*c.y + t*t*t*d.y;
216                 return new Point( nx , ny );
217         }
218        
219         public static function toRadian( degrees:Number )
220         {
221                 var r:Number = degrees % 360;
222                 if( r<=-180 ) return ( 360+r )/ 180 * Math.PI;
223                 if( r > 180 ) return -( 360-r )/ 180 * Math.PI;
224                 return r / 180 * Math.PI;
225         }
226        
227         public static function toDegrees( radian:Number )
228         {
229                 var d:Number = ( radian % ( Math.PI*2 ) ) / Math.PI * 180;
230                 if( d<0 ) return 360+d;
231                 return d;
232         }
233        
234         /**
235         * 指定したムービークリップのプロパティを、その位置、階層に関わらず、_root座標を基にした値に変換します。
236         * 対象となるプロパティは _x , _y , _xscale , _yscale , _width , _height , _rotation の7つです。
237         * 但し、 _xscale , _yscale はそれぞれ _width , _height に置き換えられます。
238         *
239         * @param        target : MovieClip - 対象とするムービークリップ
240         * @param        prop : Object - target の対象とするプロパティの値を示したオブジェクト
241         * @return Object - 変換後のプロパティ値を持ったオブジェクト
242         * @usage <code>
243         * import com.seyself.math.GeomMath;
244         * var main = this.createEmptyMovieClip( "main" , 0 );
245         * var rect = main.createEmptyMovieClip( "rect" , 0 );
246         * rect.beginFill( 0 , 100 );
247         * rect.moveTo( 0, 0 );
248         * rect.lineTo( 0, 100 );
249         * rect.lineTo( 100, 100 );
250         * rect.lineTo( 100, 0 );
251         * rect.lineTo( 0, 0 );
252         * rect.endFill();
253         *
254         * main._x = 50;
255         * main._y = 50;
256         * main._width = 400;
257         * main._height = 350;
258         *
259         * var prop = {
260         *         _x : 50 ,
261         *         _y : 50 ,
262         *         _width : 100 ,
263         *         _yscale : 50
264         *     }
265         * var changeProp = GeomMath.staticProp( rect , prop );
266         * trace( rect._x = changeProp._x ); // 出力 : 0
267         * trace( rect._y = changeProp._y ); // 出力 : 0
268         * trace( rect._width = changeProp._width ); // 出力 : 25
269         * trace( rect._height = changeProp._height ); // 出力 : 14.3
270         * </code>
271         */
272         public static function staticProp( target:MovieClip , prop:Object ):Object
273         {
274                 var _result = {};
275                 for(var val in prop){
276                         if( typeof( prop[val] )=="number" || typeof( prop[val] )=="boolean" ){
277                                 _result[val] = prop[val];
278                         }
279                 }
280                
281                 if( prop._x != undefined || prop._y != undefined ){
282                         var tmp = {
283                                 x:(( prop._x==undefined )?target._x:prop._x) ,
284                                 y:(( prop._y==undefined )?target._y:prop._y)
285                         };
286                         target._parent.globalToLocal( tmp );
287                         if( prop._x != undefined ){
288                                 _result._x = tmp.x;
289                         }
290                         if( prop._y != undefined ){
291                                 _result._y = tmp.y;
292                         }
293                 }
294                
295                 if( prop._xscale != undefined || prop._yscale != undefined ){
296                         if( prop._xscale != undefined ){
297                                 prop._width = prop._xscale/100*target._width;
298                                 delete prop._xscale;
299                         }
300                         if( prop._yscale != undefined ){
301                                 prop._height = prop._yscale/100*target._height;
302                                 delete prop._yscale;
303                         }
304                 }
305                
306                 if( prop._width != undefined || prop._height != undefined ){
307                         var tmp = {
308                                 x:(( prop._width==undefined )?target._width : prop._width) ,
309                                 y:(( prop._height==undefined )?target._height : prop._height)
310                         };
311                         var tmp2 = { x:0 , y:0 };
312                        
313                         target._parent.globalToLocal( tmp2 );
314                         target._parent.globalToLocal( tmp );
315                         if( prop._width != undefined ){
316                                 _result._width = tmp.x-tmp2.x;
317                         }
318                         if( prop._height != undefined ){
319                                 _result._height = tmp.y-tmp2.y;
320                         }
321                 }
322                
323                 if( prop._rotation != undefined ){
324                         var _rot = 0;
325                         var parentTarget = target._parent;
326                         while( parentTarget!=_root ){
327                                 _rot += parentTarget._rotation;
328                                 parentTarget = parentTarget._parent;
329                         }
330                         _result._rotation = prop._rotation-_rot;
331                 }
332                
333                 return _result;
334         }
335        
336        
337 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。