在圆上从点到相对切线画一条线? AS3中的圆锥/楔形。

| 这应该是一些简单的几何:如何在下面的代码中计算点以画线,以使其成为2D圆锥形或楔形?
import flash.geom.Point;

//draw circle
var mc=new Sprite()
mc.graphics.lineStyle(0,0)
mc.graphics.drawCircle(0,0,30)
mc.x=mc.y=Math.random()*300+100
addChild(mc)

//draw lines:
graphics.lineStyle(0,0)
var p=new Point(Math.random()*500,Math.random()*400)
graphics.moveTo(p.x, p.y)
graphics.lineTo(mc.x,mc.y) // << should be point on edge of circle
graphics.moveTo(p.x, p.y)
graphics.lineTo(mc.x,mc.y) // << should be point on opposite edge of circle
更新: 谢谢大家,我应该提到我的目标不是绘制楔形,而是绘制从随机点到现有圆的边缘的直线。 如果您更喜欢代数而不是动作脚本,也许您可​​以看一下这张图片并为​​我发布公式?     
已邀请:
您的问题与Thales定理有关(请参阅http://en.wikipedia.org/wiki/Thales%27_theorem)。 以下是定理稍作修改以与AS3一起使用的定理。 导入flash.geom.Point;
// The radius of the circle
var r1:Number = 30;
// The center point of the circle
var cp:Number = Math.random() * 300+100;
var c:Point = new Point(cp, cp);

// draw circle
var mc=new Sprite();
mc.graphics.lineStyle(0,0);
mc.graphics.drawCircle(0,0,r1);
mc.x = mc.y = cp;
addChild(mc);

// The point
var p = new Point(Math.random() * 500, Math.random() * 400);

// Calculate points for intesecting circle
var c2:Point = Point.interpolate(c, p, 0.5);
var r2:Number = Point.distance(c2, c);
var d:Number = Point.distance(c, c2);

// Remove comment below to see intersecting circle
//graphics.beginFill(0xFF0000, 0.25);
//graphics.drawCircle(c2.x, c2.y, r2);

var a:Number = (r1*r1 - r2*r2 + d*d) / (2*d);
var p2x:Number = c.x + a * ( c2.x - c.x ) / d;
var p2y:Number = c.y + a * ( c2.y - c.y ) / d;
var h:Number = Math.sqrt(r1*r1 - a*a);

var d1x:Number = p2x + h * ( c2.y - c.y ) / d;
var d1y:Number = p2y - h * ( c2.x - c.x ) / d;
var d2x:Number = p2x - h * ( c2.y - c.y ) / d;
var d2y:Number = p2y + h * ( c2.x - c.x ) / d;

// Draw lines
graphics.lineStyle(1, 0xFF00FF, 0.5);
graphics.moveTo(p.x, p.y);
graphics.lineTo(d1x, d1y);
graphics.moveTo(p.x, p.y);
graphics.lineTo(d2x, d2y);
最终产品: 绘制第二个圆(实际上并不需要绘制第二个圆,只需要其中心点和半径) 检出以下SWF以查看实际效果(刷新以查看不同的随机圆): http://megaswf.com/serve/1097652     
(xP, yP)
为切线的交点,
(xC,yY)
为圆的中心,您在此处寻找切线点的坐标
(xT,yT)
。此外,令
T
为切线的向量,
R
为半径的向量。由于它们是垂直的,所以您有
R . T = 0
。 这给了我们
(xT-xC,yT-yC) . (xT-xP, yT-yP) = 0
r
为圆的半径,令
x:=xT-xC, y:=yT-yC, xp:=xP-xC, yp:=yP-yC
(基本上,将圆移至into11ѭ)。 切线在圆上,所以您有
x²+y²=r²
,因此也有
y=sqrt(r²-x²)
。 应用于上述方程式的变量替换给我们:
(x,y) . (x-xp, y-yp) = 0
x²-xp*x + y²-yp*y = 0
使用圈子信息,我们可以:
r² -xp*x - yp*sqrt(r²-x²) = 0
r² -xp*x = yp*sqrt(r²-x²)
r^4 - 2*r²*xp*x + xp²*x² = yp²*(r²-x²)
(yp²+xp²)*x² - 2*r²*xp*x + r^4-yp²*r² = 0

now let a:=yp²+xp², b:=2*r²*xp, c:= (r²-yp²)*r²
=> ax² + bx + c = 0
这是具有0、1或2个解的二次方程。如果P在圆上,则为0;如果P在圆上,则为1;如果P在圆外,则为2。 如果将此处介绍的变量映射为代码中的变量,则我不会在此处放置显式解决方案,因为它是公式的地狱,而且编写起来容易得多。
var sq:Function = function (f:Number) { return f*f; }, sqrt:Function = Math.sqrt;
var xp:Number = xP-xC, yp:Number = yP-yC,
    a:Number = sq(xp)+sq(yp), b:Number = 2*sq(r)*xp, c:Number = sq(r)*(sq(r)-sq(yp));
var x1:Number = (-b+sqrt(sq(b)-4*a*c)) / (2 * a),
    x2:Number = (-b+sqrt(sq(b)-4*a*c)) / (2 * a);
if (isNan(x1)) return [];
var p1:Point = new Point(x1+cX, sqrt(sq(r)-sq(x1))+cY),//calculate y and undo shift
    p2:Point = new Point(x2+cX, sqrt(sq(r)-sq(x2))+cY);
return p1.equals(p2) ? [p1] : [p1, p2];
祝您好运,因为我对微积分很不好,这里是04:00,所以您可以打赌,某处有一个错误,但是它应该使您朝着正确的方向;)     
将您的点表示为P,将圆心表示为M,将圆上的切点表示为X。三角形PMT是直角三角形。您可能希望在遍历纸本时在纸上画出草图,以使其更容易遵循。 X的位置就是M的位置加上X的径向矢量,即边缘MX。然后,该计算是关于计算向量MX。 向量MX可以分解为两个垂直分量。一种与MP平行,另一种与MP垂直。首先要做的是获得这两个方向上的单位向量。第一个很容易,因为它只是MP的规范化版本。通过交换分量并求反一个分量,可以轻松地在2D中获得与此垂直的向量。否定哪个分量在这里无关紧要,因为您最终想要两条切线。 现在我们有了两个单位向量,我们需要计算出创建径向向量MX所需的每个单位向量。我们用简单的直角三角形用theta表示角度PMX,cos(theta)= r / | MP |其中r是圆的半径,| MP |是MP的长度(您已经计算出其长度以得到单位矢量)。 将垂直线从X放到MP会得到另一个包含theta的直角三角形,其相对和相邻的边代表我们想要的两个分量。这些边的长度在MP方向上仅为r * cos(theta),在垂直方向上为r * sin(theta)。 所以你的最终结果实质上是 X = M + r * cos(θ)* unit_MP + r * sin(theta)* unit_MP_perp_1 对于其中一个切点 X = M + r * cos(θ)* unit_MP + r * sin(theta)* unit_MP_perp_2 对于其他。 Unit_MP和unit_MP_perp_1 / 2是我们之前得出的单位向量。 perp向量的1/2版本对应于交换之后否定第一或第二分量。 编辑 根据您添加的图,等式变为 x1 = cx + R * cos(θ)* Ux + R * sin(theta)* U1x y1 = cy + R * cos(theta)* Uy + R * sin(theta)* U1y 具有类似的方程式(x2,y2)。在这些方程式中 cos(θ)= r / D sin(θ)= A / D 其中D = sqrt((px-cx)^ 2 +(py-cy)^ 2) 和 Ux =(px -cx)/ D Uy =(py -cy)/ D 所以 U1x = -Uy U1y = Ux 另一个切点的垂直单位向量为 U2x = Uy U2y = -Ux     
graphics.curveTo(controlX,ControlY,endX,endY);
在当前点和端点(x,y)之间绘制贝塞尔曲线,控件(x,y)为曲线弯曲的点(如Photoshop中的笔工具)。设置为半增量X,并使用Y调整其强度。     
这是用于绘制2D楔形形状的代码段。您可以调节
startAngle
angle
变量来控制楔形的角度。半径将确定形状的宽度。应该在Shape,Sprite,MovieClip或具有图形对象的某些子类中使用。
var i:int;
var p:Point = new Point();
var g:Graphics = graphics;
var radius:Number = 100;
var startAngle:Number = 130;
var angle:Number = 280;
var segments:Number = 40;
var degrees:Number = ( startAngle + ( angle - startAngle ) ) / segments;

g.beginFill( 0xFF0000, 1 );
for( i = 0; i <= segments; i++ ) 
{
    p.x = Math.cos( ( ( degrees * i ) + startAngle ) * Math.PI / 180 ) * radius;
    p.y = Math.sin( ( ( degrees * i ) + startAngle ) * Math.PI / 180 ) * radius;
    g.lineTo( p.x, p.y );
}
g.endFill();
    

要回复问题请先登录注册