2012-01-26 5 views
6

I는 다음과 같은 내용을 가지고계산 센터

  • radiusX (RX)
  • radiusY (RY)
  • X1
  • Y1
  • X2
  • Y2

SVG 사양을 사용하면 반지름을 지정하여 호, 시작점과 끝점을 지정합니다. 시작 지점이 끝점에 도달하는 방법을 정의하는 데 도움이되는 large-arc-flagsweep-flag과 같은 다른 옵션이 있습니다. More details here.

저는 수학적으로 경사가 없기 때문에 all of this을 이해하는 것은 거의 불가능합니다.

나는 SVG의 arc 명령에 의해 받아 들여지는 모든 인수가 주어진다면 centerXcenterY 값을 알고있는 간단한 방정식을 찾고 있다고 생각한다.

도움을 주시면 감사하겠습니다.

검색 한 결과 stackoverflow가 없으며 일반 영어로 해답을 설명 할 수 없습니다.

답변

1

I은 ​​X 축 회전의 시작 및 종료 포인트 = 0 방정식의 경우 고려하고 :

X1 = CX + RX * COS (startAngle로부터)

Y1 = CY + 스피을 * 죄 (startAngle로부터)

X2 = CX + RX * COS (EndAngle)

Y2 = CY + 스피 * 죄 (EndAngle) 식으로부터 PA

제외 각도

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

스피^2 * (X2- : IRS 우릴 준다 이 방정식 시스템은 (cx, cy)에 대해 손으로 또는 수학 패킷의 도움으로 분석적으로 풀릴 수있다. (수학 식 (cx, cy)^2 + rx^2 * (y2-cy)^2 = rx^2 * ry^2

메이플, 매스 매 티카 등). 이차 방정식의 두 가지 해법이 있습니다 (대형 아크 플래그와 스윕 플래그 조합으로 인해).

+0

감사하지만이 방정식을 해결하는 방법을 인정하지 않아야합니다. – James

2

이 자바 스크립트 함수를 사용하여 계산할 수 있습니다.

// 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