2011-04-15 74 views
7

這應該是一個簡單的幾何體:我如何計算在下面的代碼中繪製線條的點,以使其形成二維錐體或楔形形狀?從圓上的一個點到相反的切線繪製一條線? AS3中的錐體/楔形形狀

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 

UPDATE:
感謝球員,我應該提到我的目的不是畫一個楔形,而是從一個隨機點到現有圈子的邊緣畫一條線。

如果你比動作更適合代數,也許你可以看看這個圖形併爲我發佈公式? tangents

+0

+1偉大的問題。我真的很喜歡試圖解決它 – Chris 2011-04-16 05:03:20

+0

我知道有人會喜歡它!這是我的目標:D 感謝噸的簡單解決方案。 – cronoklee 2011-04-16 11:12:54

+0

沒問題。 Goodluck與該項目 – Chris 2011-04-16 11:15:07

回答

2

你的問題是關於泰勒斯定理(見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); 

最終產品:

enter image description here

隨着繪製的第二圓圈(你實際上並不需要在第二圈畫,你只需要它的圓心和半徑)

enter image description here

簽出以下SWF以查看動作(刷新以查看不同的隨機圓圈):

http://megaswf.com/serve/1097652

0

graphics.curveTo(controlX,ControlY,endX,endY);

繪製貝塞爾與對照(X,Y)當前點和端部(X,Y)之間的曲線朝向(如Photoshop中的筆工具)彎曲的點。設置爲一半的Delta X並使用Y來調整其強度。

+0

謝謝,我應該提到我的目的不是畫一個楔形,而是畫一條線到現有的一個圓的邊緣。 – cronoklee 2011-04-16 00:23:44

0

以下是繪製2D楔形圖的代碼片段。您可以調整startAngleangle變量來控制楔形的角度。半徑將決定形狀的寬度。這應該用在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(); 
1

爲區分點爲P,圓心爲M,並在圓切點爲十三角PMT是一個直角三角形。您可能需要在紙上畫出它,以便更易於理解。

X的位置就是M加上X的位置,即X的邊緣MX。然後計算是關於計算向量MX。

矢量MX可以分解爲兩個垂直分量。一個與MP平行,另一個與MP垂直。首先要做的是在這兩個方向上獲得單位向量。第一個很簡單,因爲它只是MP的標準化版本。通過交換組件和否定一個組件,在2D中很容易獲得垂直向量。由於您最終需要兩條切線,因此此處取消哪個分量無關緊要。

現在我們有了兩個單位向量,我們需要計算出每個向量需要多少來創建徑向向量MX。用θ表示角度PMX,我們用簡單的直角三角形表示cos(θ)= r/| MP |其中r是圓的半徑,| MP |是MP的長度(你已經計算得到你的單位矢量)。

從X到MP的垂線下降給出了另一個直角三角形,其中theta的相對和相鄰邊表示我們需要的兩個分量。這些邊的長度只是MP方向上的r * cos(θ)和垂直方向上的r * sin(theta)。

因此,最終的結果基本上是

X = M + R * COS(THETA)* unit_MP + R * SIN(THETA)* unit_MP_perp_1

爲切點之一,

X = M + r *cosθ* unit_MP + r *sinθ* 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 (x2,y2)= cy + R *cosθ* Uy + R * sin(theta)* U1y

。在這些等式中

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

+0

非常感謝@Troubadour,但我仍然有點迷失於你的變數。你可能看看上面的圖片,並使用我的條款重寫你的公式?它看起來就是我需要的! – cronoklee 2011-04-16 01:02:46

+0

你的解釋是什麼「M」?你在那裏失去了我。 – 2011-04-16 01:49:22

+0

Woops,我全心全意道歉。我用M作爲圓的中心寫出了步驟,因爲你的變量被稱爲mc,但後來認識到它應該是C!當我寫下我的答案時,我開始使用C語言,但很快就回到了使用M的階段。抱歉讓每個人都感到困惑!我已經將它更改爲M,因爲大部分答案已經使用了。 – Troubadour 2011-04-16 06:38:12

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是上的圈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]; 

祝您好運與此,因爲我非常糟糕微積分,再加上它的4點在這裏,所以你可以打賭,有一個錯誤的地方,但它應該讓你在正確的方向;)