⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 geometry.as

📁 用于flash/flex的 as3的 2D图形图像图表的动态生成
💻 AS
字号:
package flare.util
{
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	/**
	 * Utility methods for computational geometry.
	 */
	public final class Geometry
	{		
        /**
         * Computes the co-efficients for a cubic Bezier curve.
         * @param a the starting point of the curve
         * @param b the first control point of the curve
         * @param c the second control point of the curve
         * @param d the ending point of the curve
         * @param c1 point in which to store the zero-order co-efficients
         * @param c2 point in which to store the first-order co-efficients
         * @param c3 point in which to store the second-order co-efficients
         */
        public static function cubicCoeff(a:Point, b:Point, c:Point, d:Point,
        								  c1:Point, c2:Point, c3:Point) : void
        {            
            c3.x = 3 * (b.x - a.x);
            c2.x = 3 * (c.x - b.x) - c3.x;
            c1.x = d.x - a.x - c3.x - c2.x;
            
            c3.y = 3 * (b.y - a.y);
            c2.y = 3 * (c.y - b.y) - c3.y;
            c1.y = d.y - a.y - c3.y - c2.y;
        }
        
        /**
         * Computes a point along a cubic Bezier curve.
         * @param u the interpolation fraction along the curve (between 0 and 1)
         * @param a the starting point of the curve
		 * @param c1 the zero-order Bezier co-efficients
         * @param c2 the first-order Bezier co-efficients
         * @param c3 the second-order Bezier co-efficients
         * @param p point in which to store the calculated point on the curve
         */
        public static function cubic(u:Number, a:Point, 
        							 c1:Point, c2:Point, c3:Point,
        						     p:Point) : Point
        {
            p.x = u*(c3.x + u*(c2.x + u*c1.x)) + a.x;
			p.y = u*(c3.y + u*(c2.y + u*c1.y)) + a.y;
            return p;
        }
        
        /**
         * Computes the co-efficients for a B-spline.
         * @param p the control points of the spline as an array of x,y values
         * @param a an array for storing the x-components of co-efficients
         * @param b an array for storing the y-components of co-efficients
         */
        public static function bsplineCoeff(p:Array, a:Array, b:Array):void
        {
        	a[0] = (-p[0] + 3 * p[2] - 3 * p[4] + p[6]) / 6.0;
        	a[1] = (3 * p[0] - 6 * p[2] + 3 * p[4]) / 6.0;
			a[2] = (-3 * p[0] + 3 * p[4]) / 6.0;
			a[3] = (p[0] + 4 * p[3] + p[4]) / 6.0;
			
			b[0] = (-p[1] + 3 * p[3] - 3 * p[5] + p[7]) / 6.0;
        	b[1] = (3 * p[1] - 6 * p[3] + 3 * p[5]) / 6.0;
			b[2] = (-3 * p[1] + 3 * p[5]) / 6.0;
			b[3] = (p[1] + 4 * p[4] + p[5]) / 6.0;
        }
        
        /**
         * Computes a point along a B-spline.
         * @param u the interpolation fraction along the curve (between 0 and 1)
         * @param a an array of x-components of the B-spline co-efficients
         * @param b an array of y-components of the B-spline co-efficients
         * @param s point in which to store the calculated point on the curve
         */
        public static function bspline(u:Number, a:Array, b:Array, s:Point) : Point
        {
			s.x = u*(a[2] + u*(a[1] + u*a[0])) + a[3];
			s.y = u*(b[2] + u*(b[1] + u*b[0])) + b[3];
			return s;
		}

		// --------------------------------------------------------------------
		
		/** Indicates no intersection between shapes */
    	public static const NO_INTERSECTION:int = 0;
    	/** Indicates intersection between shapes */
    	public static const COINCIDENT:int      = -1;
    	/** Indicates two lines are parallel */
    	public static const PARALLEL:int        = -2;
		
		/**
	     * Compute the intersection of two line segments.
	     * @param a1x the x-coordinate of the 1st endpoint of the 1st line
	     * @param a1y the y-coordinate of the 1st endpoint of the 1st line
	     * @param a2x the x-coordinate of the 2nd endpoint of the 1st line
	     * @param a2y the y-coordinate of the 2nd endpoint of the 1st line
	     * @param b1x the x-coordinate of the 1st endpoint of the 2nd line
	     * @param b1y the y-coordinate of the 1st endpoint of the 2nd line
	     * @param b2x the x-coordinate of the 2nd endpoint of the 2nd line
	     * @param b2y the y-coordinate of the 2nd endpoint of the 2nd line
	     * @param intersect a Point in which to store the intersection point
	     * @return the intersection code. This is either the number of
	     *  intersections or one of {@link #NO_INTERSECTION},
	     *  {@link #COINCIDENT}, or {@link #PARALLEL}.
	     */
	    public static function intersectLines(a1x:Number, a1y:Number,
	    	a2x:Number, a2y:Number, b1x:Number, b1y:Number, b2x:Number,
	    	b2y:Number, intersect:Point):int
	    {
	        var ua_t:Number = (b2x-b1x)*(a1y-b1y)-(b2y-b1y)*(a1x-b1x);
	        var ub_t:Number = (a2x-a1x)*(a1y-b1y)-(a2y-a1y)*(a1x-b1x);
	        var u_b :Number = (b2y-b1y)*(a2x-a1x)-(b2x-b1x)*(a2y-a1y);
	
	        if (u_b != 0) {
	            var ua:Number = ua_t / u_b;
	            var ub:Number = ub_t / u_b;
	
	            if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
	            	intersect.x = a1x+ua*(a2x-a1x);
	            	intersect.y = a1y+ua*(a2y-a1y);
	                return 1;
	            } else {
	                return NO_INTERSECTION;
	            }
	        } else {
	            return (ua_t == 0 || ub_t == 0 ? COINCIDENT : PARALLEL);
	        }
	    }
		
		/**
	     * Compute the intersection of a line and a rectangle.
	     * @param a1 the first endpoint of the line
	     * @param a2 the second endpoint of the line
	     * @param r the rectangle
	     * @param pts a length 2 or greater array of points in which to store
	     * the results 
	     * @return the intersection code. This is either the number of
	     *  intersections or one of {@link #NO_INTERSECTION},
	     *  {@link #COINCIDENT}, or {@link #PARALLEL}.
	     */
	    public static function intersectLineRect(a1x:Number, a1y:Number,
	    	a2x:Number, a2y:Number, r:Rectangle, p0:Point, p1:Point):int
	    {
	        var xMax:Number = r.right, yMax:Number = r.bottom;
	        var xMin:Number = r.left,  yMin:Number = r.top;
	        
	        var i:int = 0, p:Point = p0;
	        if (intersectLines(xMin,yMin,xMax,yMin, a1x,a1y,a2x,a2y, p) > 0) {
	        	++i; p = p1;
	        }
	        if (intersectLines(xMax,yMin,xMax,yMax, a1x,a1y,a2x,a2y, p) > 0) {
	        	++i; p = p1;
	        }
	        if (i == 2) return i;
	        if (intersectLines(xMax,yMax,xMin,yMax, a1x,a1y,a2x,a2y, p) > 0) {
	        	++i; p = p1;
	        }
	        if (i == 2) return i;
	        if (intersectLines(xMin,yMax,xMin,yMin, a1x,a1y,a2x,a2y, p) > 0) {
	        	++i; p = p1;
	        }
	        return i;
	    }

        /**
         * Computes the convex hull for a set of points.
         * @param p the input points, as a flat array of x,y values
         * @param len the number of points to include in the hull
         * @return the convex hull, as a flat array of x,y values
         */
        public static function convexHull(p:Array, len:uint) : Array
        {
        	// check arguments
            if (len < 3)
            	throw new ArgumentError('Input must have at least 3 points');
            
            var pts:Array = new Array(len-1);
            var stack:Array = new Array(len);
			var i:uint, j:uint, i0:uint = 0;

            // find the starting ref point: leftmost point with the minimum y coord
            for (i = 0; i < len; ++i)
            {
                if (p[i].Y < p[i0].Y) { 
                	i0 = i;
                } else if (p[i].Y == p[i0].Y) {
                	i0 = (p[i].X < p[i0].X ? i : i0);
                }
            }

            // calculate polar angles from ref point and sort
            for (i = 0, j = 0; i < len; ++i) {
                if (i != i0) {
                	pts[j++] = {
                		angle: Math.atan2(p[i].Y-p[i0].Y, p[i].X-p[i0].X),
                		index: i
                	};
                }
            }
            pts.sortOn('angle');

            // toss out duplicated angles
            var angle:Number = pts[0].angle;
            var ti:uint = 0, tj:uint = pts[0].index;
            for (i = 1; i < len-1; i++) {
                j = pts[i].index;
                if (angle == pts[i].angle)
                {
                    // keep angle corresponding to point most distant from reference point
                    var d1:Number = Point.distance(p[i0], p[tj]);
                    var d2:Number = Point.distance(p[i0], p[j]);
                    
                    if (d1 >= d2) {
                        pts[i].index = -1;
                    } else {
                        pts[ti].index = -1;
                        angle = pts[i].angle;
                        ti = i;
                        tj = j;
                    }
                } else {
                    angle = pts[i].angle;
                    ti = i;
                    tj = j;
                }
            }

            // initialize the stack
            var sp:uint = 0;
            stack[sp++] = i0;
            var h:uint = 0;
            for (var k:uint = 0; k < 2; h++) {
                if (pts[h].index != -1) {
                    stack[sp++] = pts[h].index;
                    k++;
                }
            }

            // do graham's scan
            for (; h < len-1; h++)
            {
                if (pts[h].index == -1) continue; // skip tossed out points
                while (isNonLeft(i0, stack[sp-2], stack[sp-1], pts[h].index, p))
                    sp--;
                stack[sp++] = pts[h].index;
            }

            // construct the hull
            var hull:Array = new Array(sp);
            for (i = 0; i < sp; ++i) {
                hull[i] = p[stack[i]];
            }
            return hull;
        }

        private static function isNonLeft(i0:uint, i1:uint, i2:uint, i3:uint, p:Array) : Boolean
        {
            var l1:Number, l2:Number, l4:Number, l5:Number, l6:Number, a:Number, b:Number;

            a = p[i2].y - p[i1].y; b = p[i2].x - p[i1].y; l1 = Math.sqrt(a * a + b * b);
            a = p[i3].y - p[i2].y; b = p[i3].x - p[i2].y; l2 = Math.sqrt(a * a + b * b);
            a = p[i3].y - p[i0].y; b = p[i3].x - p[i0].y; l4 = Math.sqrt(a * a + b * b);
            a = p[i1].y - p[i0].y; b = p[i1].x - p[i0].y; l5 = Math.sqrt(a * a + b * b);
            a = p[i2].y - p[i0].y; b = p[i2].x - p[i0].y; l6 = Math.sqrt(a * a + b * b);
            
            a = Math.acos((l2*l2 + l6*l6 - l4*l4) / (2*l2*l6));
            b = Math.acos((l6*l6 + l1*l1 - l5*l5) / (2*l6*l1));

            return (Math.PI - a - b < 0);
        }
		
	} // end of class Geometry
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -