shapes.as
来自「用于flash/flex的 as3的 2D图形图像图表的动态生成」· AS 代码 · 共 551 行 · 第 1/2 页
AS
551 行
* @param outer the outer radius of the wedge
* @param inner the inner radius of the wedge
* @param a0 the starting angle of the wedge (in radians)
* @param a1 the ending angle of the wedge (in radians)
*/
public static function drawWedge(g:Graphics, x:Number, y:Number,
outer:Number, inner:Number, a0:Number, a1:Number) : void
{
var a:Number = Math.abs(a1-a0);
var slices:int = Math.max(4, int(a * outer / 6));
var cx:Number = x, cy:Number = y, x0:Number, y0:Number;
var circle:Boolean = (a >= 2*Math.PI - 0.001);
if (slices <= 0) return;
// pick starting point
if (inner <= 0 && !circle) {
g.moveTo(cx, cy);
} else {
x0 = cx + outer * Math.cos(a0);
y0 = cy + -outer * Math.sin(a0);
g.moveTo(x0, y0);
}
// draw outer arc
for (var i:uint = 0; i <= slices; ++i) {
a = a0 + i*(a1-a0)/slices;
x = cx + outer * Math.cos(a);
y = cy + -outer * Math.sin(a);
g.lineTo(x,y);
}
if (circle) {
// return to starting point
g.lineTo(x0, y0);
} else if (inner > 0) {
// draw inner arc
for (i = slices+1; --i >= 0;) {
a = a0 + i*(a1-a0)/slices;
x = cx + inner * Math.cos(a);
y = cy + -inner * Math.sin(a);
g.lineTo(x,y);
}
g.lineTo(x0, y0);
} else {
// return to center
g.lineTo(cx, cy);
}
}
/**
* Draws a polygon shape.
* @param g the graphics context to draw with
* @param a a flat array of x, y values defining the polygon
*/
public static function drawPolygon(g:Graphics, a:Array) : void
{
g.moveTo(a[0], a[1]);
for (var i:uint=2; i<a.length; i+=2) {
g.lineTo(a[i], a[i+1]);
}
g.lineTo(a[0], a[1]);
}
/**
* Draws a cubic Bezier curve.
* @param g the graphics context to draw with
* @param ax x-coordinate of the starting point
* @param ay y-coordinate of the starting point
* @param bx x-coordinate of the first control point
* @param by y-coordinate of the first control point
* @param cx x-coordinate of the second control point
* @param cy y-coordinate of the second control point
* @param dx x-coordinate of the ending point
* @param dy y-coordinate of the ending point
* @param move if true (the default), the graphics context will be
* moved to the starting point before drawing starts. If false,
* no move command will be issued; this is useful when connecting
* multiple curves to define a filled region.
*/
public static function drawCubic(g:Graphics, ax:Number, ay:Number,
bx:Number, by:Number, cx:Number, cy:Number, dx:Number, dy:Number,
move:Boolean=true) : void
{
var subdiv:int, u:Number, xx:Number, yy:Number;
// determine number of line segments
subdiv = int((Math.sqrt((xx=(bx-ax))*xx + (yy=(by-ay))*yy) +
Math.sqrt((xx=(cx-bx))*xx + (yy=(cy-by))*yy) +
Math.sqrt((xx=(dx-cx))*xx + (yy=(dy-cy))*yy)) / 4);
if (subdiv < 1) subdiv = 1;
// compute Bezier co-efficients
var c3x:Number = 3 * (bx - ax);
var c2x:Number = 3 * (cx - bx) - c3x;
var c1x:Number = dx - ax - c3x - c2x;
var c3y:Number = 3 * (by - ay);
var c2y:Number = 3 * (cy - by) - c3y;
var c1y:Number = dy - ay - c3y - c2y;
if (move) g.moveTo(ax, ay);
for (var i:uint=0; i<=subdiv; ++i) {
u = i/subdiv;
xx = u*(c3x + u*(c2x + u*c1x)) + ax;
yy = u*(c3y + u*(c2y + u*c1y)) + ay;
g.lineTo(xx, yy);
}
}
// -- BSpline rendering state variables --
private static var _knot:Array = new Array(20);
private static var _basis:Array = new Array(36);
/**
* Draws a cubic open uniform B-spline. The spline passes through the
* first and last control points, but not necessarily any others.
* @param g the graphics context to draw with
* @param p an array of points defining the spline control points
* @param slack a slack parameter determining the "tightness" of the
* spline. At value 1 (the default) a normal b-spline will be drawn,
* at value 0 a straight line between the first and last points will
* be drawn. Intermediate values interpolate smoothly between these
* two extremes.
* @param move if true (the default), the graphics context will be
* moved to the starting point before drawing starts. If false,
* no move command will be issued; this is useful when connecting
* multiple curves to define a filled region.
*/
public static function drawBSpline(g:Graphics, p:Array, npts:int=-1,
move:Boolean=true):void
{
var N:int = (npts < 0 ? p.length/2 : npts);
var k:int = N<4 ? 3 : 4, nplusk:int = N+k;
var i:int, j:int, s:int, subdiv:int = 40;
var x:Number, y:Number, step:Number, u:Number;
// if only two points, draw a line between them
if (N==2) {
if (move) g.moveTo(p[0],p[1]);
g.lineTo(p[2],p[3]);
return;
}
// initialize knot vector
for (i=1, _knot[0]=0; i<nplusk; ++i) {
_knot[i] = _knot[i-1] + (i>=k && i<=N ? 1 : 0);
}
// calculate the points on the bspline curve
step = _knot[nplusk-1] / subdiv;
for (s=0; s <= subdiv; ++s) {
u = step * s;
// calculate basis function -----
for (i=0; i < nplusk-1; ++i) { // first-order
_basis[i] = (u >= _knot[i] && u < _knot[i+1] ? 1 : 0);
}
for (j=2; j <= k; ++j) { // higher-order
for (i=0; i < nplusk-j; ++i) {
x = (_basis[i ]==0 ? 0 : ((u-_knot[i])*_basis[i]) / (_knot[i+j-1]-_knot[i]));
y = (_basis[i+1]==0 ? 0 : ((_knot[i+j]-u)*_basis[i+1]) / (_knot[i+j]-_knot[i+1]));
_basis[i] = x + y;
}
}
if (u == _knot[nplusk-1]) _basis[N-1] = 1; // last point
// interpolate b-spline point -----
for (i=0, j=0, x=0, y=0; i<N; ++i, j+=2) {
x += _basis[i] * p[j];
y += _basis[i] * p[j+1];
}
if (s==0) {
if (move) g.moveTo(x, y);
} else {
g.lineTo(x, y);
}
}
}
/**
* Draws a cardinal spline composed of piecewise connected cubic
* Bezier curves. Curve control points are inferred so as to ensure
* C1 continuity (continuous derivative).
* @param g the graphics context to draw with
* @param p an array defining a polygon or polyline to render with a
* cardinal spline
* @param s a tension parameter determining the spline's "tightness"
* @param closed indicates if the cardinal spline should be a closed
* shape. False by default.
*/
public static function drawCardinal(g:Graphics, p:Array, npts:int=-1,
s:Number=0.15, closed:Boolean=false) : void
{
// compute the size of the path
var len:uint = (npts < 0 ? p.length : 2*npts);
if (len < 6)
throw new Error("Cardinal splines require at least 3 points");
var dx1:Number, dy1:Number, dx2:Number, dy2:Number;
g.moveTo(p[0], p[1]);
// compute first control points
if (closed) {
dx2 = p[2]-p[len-2];
dy2 = p[3]-p[len-1];
} else {
dx2 = p[4]-p[0]
dy2 = p[5]-p[1];
}
// iterate through control points
var i:uint = 0;
for (i=2; i<len-2; i+=2) {
dx1 = dx2; dy1 = dy2;
dx2 = p[i+2] - p[i-2];
dy2 = p[i+3] - p[i-1];
drawCubic(g, p[i-2], p[i-1],
p[i-2]+s*dx1, p[i-1]+s*dy1,
p[i] -s*dx2, p[i+1]-s*dy2,
p[i], p[i+1], false);
}
// finish spline
if (closed) {
dx1 = dx2; dy1 = dy2;
dx2 = p[0] - p[i-2];
dy2 = p[1] - p[i-1];
drawCubic(g, p[i-2], p[i-1], p[i-2]+s*dx1, p[i-1]+s*dy1,
p[i]-s*dx2, p[i+1]-s*dy2, p[i], p[i+1], false);
dx1 = dx2; dy1 = dy2;
dx2 = p[2] - p[len-2];
dy2 = p[3] - p[len-1];
drawCubic(g, p[len-2], p[len-1], p[len-2]+s*dx1, p[len-1]+s*dy1,
p[0]-s*dx2, p[1]-s*dy2, p[0], p[1], false);
} else {
drawCubic(g, p[i-2], p[i-1], p[i-2]+s*dx1, p[i-1]+s*dy1,
p[i]-s*dx2, p[i+1]-s*dy2, p[i], p[i+1], false);
}
}
/**
* A helper function for consolidating end points and control points
* for a spline into a single array.
* @param x1 the x-coordinate for the first end point
* @param y1 the y-coordinate for the first end point
* @param controlPoints an array of control points
* @param x2 the x-coordinate for the second end point
* @param y2 the y-coordinate for the second end point
* @param p the array in which to store the consolidated points.
* If null, a new array will be created and returned.
* @return the consolidated array of all points
*/
public static function consolidate(x1:Number, y1:Number,
controlPoints:Array, x2:Number, y2:Number, p:Array=null):Array
{
var len:int = 4 + controlPoints.length;
if (!p) {
p = new Array(len);
} else {
while (p.length < len) p.push(0);
}
Arrays.copy(controlPoints, p, 0, 2);
p[0] = x1;
p[1] = y1;
p[len-2] = x2;
p[len-1] = y2;
return p;
}
} // end of class Shapes
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?