2012-01-26 57 views
6

我有以下信息:計算中心

  • 半徑X(RX)
  • 半徑Y(RY)
  • X1
  • Y1
  • X2
  • Y2

SVG規範允許您定義通過指定其半徑以及起點和終點來指定圓弧。還有其他選項,如large-arc-flagsweep-flag,這些選項有助於定義您希望起點到達終點的方式。 More details here

我不是數學上的傾向,所以理解all of this幾乎是不可能的。

我想我正在尋找一個簡單的公式,結果讓我知道了給定的所有參數由SVG的arc命令提供的centerXcenterY值。

任何幫助表示讚賞。

我已經搜索了stackoverflow,沒有一個答案似乎用簡單的英語解釋瞭解決方案。

回答

1

我考慮x軸旋轉= 0 方程開始和結束點的情況下:

X1 = CX + RX * COS(由startAngle)

Y1 = CY + RY * SIN(由startAngle)

X2 = CX + RX * COS(EndAngle)

Y2 = CY + RY * SIN(EndAngle)

從方程PA排除角度IRS給我們:

RY^2 *(X1-CX)^ 2 + RX^2 *(Y1-CY)^ 2 = RX^2 * RY^2

RY^2 *(X2-這個方程系統可以通過手或在數學數據包的幫助下分析地求解(cx,cy)((cx,cy))(cx,cy),這個方程組可以通過Maple,Mathematica等)。二次方程有兩個解(由於大弧標誌和掃描標誌組合)。

+0

謝謝,但我不得不承認,我不知道如何解決方程式。 – James

2

你可以使用這個javascript函數來計算。

// svg : [A | a] (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ 

/* x1 y1 x2 y2 fA fS rx ry φ */ 
function radian(ux, uy, vx, vy) { 
    var dot = ux * vx + uy * vy; 
    var mod = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy)); 
    var rad = Math.acos(dot/mod); 
    if(ux * vy - uy * vx < 0.0) rad = -rad; 
    return rad; 
} 
//conversion_from_endpoint_to_center_parameterization 
//sample : convert(200,200,300,200,1,1,50,50,0,{}) 
function convert(x1, y1, x2, y2, fA, fS, rx, ry, phi) { 
     var cx,cy,theta1,delta_theta; 

     if(rx == 0.0 || ry == 0.0) return -1; // invalid arguments 

     var s_phi = Math.sin(phi); 
     var c_phi = Math.cos(phi); 
     var hd_x = (x1 - x2)/2.0; // half diff of x 
     var hd_y = (y1 - y2)/2.0; // half diff of y 
     var hs_x = (x1 + x2)/2.0; // half sum of x 
     var hs_y = (y1 + y2)/2.0; // half sum of y 

     // F6.5.1 
     var x1_ = c_phi * hd_x + s_phi * hd_y; 
     var y1_ = c_phi * hd_y - s_phi * hd_x; 

     var rxry = rx * ry; 
     var rxy1_ = rx * y1_; 
     var ryx1_ = ry * x1_; 
     var sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_; // sum of square 
     var coe = Math.sqrt((rxry * rxry - sum_of_sq)/sum_of_sq); 
     if(fA == fS) coe = -coe; 

     // F6.5.2 
     var cx_ = coe * rxy1_/ry; 
     var cy_ = -coe * ryx1_/rx; 

     // F6.5.3 
     cx = c_phi * cx_ - s_phi * cy_ + hs_x; 
     cy = s_phi * cx_ + c_phi * cy_ + hs_y; 

     var xcr1 = (x1_ - cx_)/rx; 
     var xcr2 = (x1_ + cx_)/rx; 
     var ycr1 = (y1_ - cy_)/ry; 
     var ycr2 = (y1_ + cy_)/ry; 

     // F6.5.5 
     theta1 = radian(1.0, 0.0, xcr1, ycr1); 

     // F6.5.6 
     delta_theta = radian(xcr1, ycr1, -xcr2, -ycr2); 
     var PIx2 = Math.PI * 2.0; 
     while(delta_theta > PIx2) delta_theta -= PIx2; 
     while(delta_theta < 0.0) delta_theta += PIx2; 
     if(fS == false) delta_theta -= PIx2; 

     var outputObj = { /* cx, cy, theta1, delta_theta */ 
      cx : cx, 
      cy : cy, 
      theta1 : theta1, 
      delta_theta : delta_theta 
     } 
     console.dir(outputObj); 

     return outputObj; 
} 
+1

這是引用的SVG附錄的很好的實現。不幸的是,它並不適用於所有情況。有一些(不是很少見的)邊緣情況,其中在計算'coe'時sqrt內的值是負值。請參閱http://svn.apache.org/repos/asf/xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/geom/ExtendedGeneralPath.java中的'computeArc'。請注意,如果值爲負數,則此實現將中心點設置爲(0,0),這似乎適用於我。一個例子是從(0,100)到(100,0)的rx = ry = 60的弧。 – brianmearns