这应该是一个简单的几何:我如何计算在下面的代码中绘制线条的点,以便它形成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
更新:
谢谢大家,我应该提到我的目标不是绘制楔形,而是从随机点到现有圆的边缘画一条线。
如果你对代数比动作更舒服,也许你可以看看这个图形并为我发布一个公式?
答案 0 :(得分:2)
你的问题是关于Thales定理(见http://en.wikipedia.org/wiki/Thales%27_theorem)。
以下是与AS3一起使用的略有修改的定理。
import 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以查看操作(刷新以查看不同的随机圆圈):
答案 1 :(得分:1)
将您的点表示为P,将圆心表示为M,将圆上的切点表示为X.三角形PMT是一个直角三角形。您可能希望在阅读时将其绘制在纸上,以便更容易理解。
X的位置正好是M的位置加上X的径向矢量,即边缘MX。然后计算关于计算向量MX。
矢量MX可以分解为两个垂直分量。一个与MP平行且一个与MP垂直的。首先要做的是在这两个方向上获得单位向量。第一个很简单,因为它只是MP的标准化版本。通过交换组件和否定一个组件,可以在2D中容易地获得对此的垂直向量。你否定哪个组件在这里是无关紧要的,因为你最终想要两条切线。
现在我们有了两个单位向量,我们需要计算出创建径向向量MX所需的每个向量。将角度PMX表示为θ,我们从简单的直角三角形中得出cos(θ)= r / | MP |其中r是圆的半径和| MP |是MP的长度(您已计算得到上面的单位向量)。
垂直从X到MP的垂直给出另一个直角三角形,包括theta,其相对和相邻的边代表我们想要的两个分量。这些边的长度只是MP方向的r * cos(θ)和垂直方向的r * sin(θ)。
所以你的最终结果基本上是
X = M + r * cos(theta)* unit_MP + r * sin(theta)* unit_MP_perp_1
用于其中一个切点和
X = M + r * cos(theta)* unit_MP + r * sin(theta)* unit_MP_perp_2
为另一个。 Unit_MP和unit_MP_perp_1 / 2是我们之前制定的单位向量。 perp向量的1/2版本对应于交换后否定第一个或第二个组件。
修改强>
根据您添加的图表,等式变为
x1 = cx + R * cos(theta)* Ux + R * sin(theta)* U1x
y1 = cy + R * cos(theta)* Uy + R * sin(theta)* U1y
具有相似的方程(x2,y2)。在这些方程中
cos(theta)= r / D
sin(theta)= 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
答案 2 :(得分:1)
让(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
(基本上,我们将圆圈移动到(0,0)
)。
切点位于圆上,因此您有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
这是quadratic equation,包含0,1或2个解决方案。 0,如果P 在圆圈中,1,如果P on 圆圈,则为2,如果P 在外圆圈。
我不会在这里提出明确的解决方案,因为如果你将这里介绍的变量映射到你的代码中的变量,它是一个公式的地狱而且编写起来容易得多:
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,所以你可以打赌,某处有一个错误,但它应该让你朝着正确的方向前进;)
答案 3 :(得分:0)
graphics.curveTo(controlX,ControlY,endX,endY);
在当前点和结束(x,y)之间绘制一个Bézier,其中控制(x,y)是曲线弯曲的点(就像Photoshop中的钢笔工具一样)。设置为半角X并使用Y调整其强度。
答案 4 :(得分:0)
这是一个用于绘制2D Wedge形状的片段。您可以调整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();