Calculate SVG Arc Center

I have the following information:

  • radiusX (rx)
  • radiusY (ry)
  • x1
  • y1
  • x2
  • y2

The SVG specification allows you to define an arc by specifying its radius, start and end points. There are other options, such as large-arc-flag and sweep-flag , that help determine how you want the starting point to reach the ending point. More details here .

I am not mathematically inclined, so understanding all this is practically impossible.

I assume that I am looking for a simple equation that leads to the fact that I know the values ​​of centerX and centerY , given all the arguments accepted by the SVG arc command.

Any help is appreciated.

I have a stackoverflow search and none of the answers explain this solution in plain English.

+6
source share
2 answers

You can use this javascript function to calculate.

 // svg : [A | a] (rx ry x-axis-rotation large-arc-flag sweep-flag xy)+ 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 : svgArcToCenterParam(200,200,50,50,0,1,1,300,200) // x1 y1 rx ry Ο† fA fS x2 y2 function svgArcToCenterParam(x1, y1, rx, ry, phi, fA, fS, x2, y2) { var cx, cy, startAngle, deltaAngle, endAngle; var PIx2 = Math.PI * 2.0; if (rx < 0) { rx = -rx; } if (ry < 0) { ry = -ry; } if (rx == 0.0 || ry == 0.0) { // invalid arguments throw Error('rx and ry can not be 0'); } 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; // F.6.6 Correction of out-of-range radii // Step 3: Ensure radii are large enough var lambda = (x1_ * x1_) / (rx * rx) + (y1_ * y1_) / (ry * ry); if (lambda > 1) { rx = rx * Math.sqrt(lambda); ry = ry * Math.sqrt(lambda); } var rxry = rx * ry; var rxy1_ = rx * y1_; var ryx1_ = ry * x1_; var sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_; // sum of square if (!sum_of_sq) { throw Error('start point can not be same as end point'); } var coe = Math.sqrt(Math.abs((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 startAngle = radian(1.0, 0.0, xcr1, ycr1); // F6.5.6 deltaAngle = radian(xcr1, ycr1, -xcr2, -ycr2); while (deltaAngle > PIx2) { deltaAngle -= PIx2; } while (deltaAngle < 0.0) { deltaAngle += PIx2; } if (fS == false || fS == 0) { deltaAngle -= PIx2; } endAngle = startAngle + deltaAngle; while (endAngle > PIx2) { endAngle -= PIx2; } while (endAngle < 0.0) { endAngle += PIx2; } var outputObj = { /* cx, cy, startAngle, deltaAngle */ cx: cx, cy: cy, startAngle: startAngle, deltaAngle: deltaAngle, endAngle: endAngle, clockwise: (fS == true || fS == 1) } return outputObj; } 

Usage example:

Svg

 <path d="M 0 100 A 60 60 0 0 0 100 0"/> 

Js

 var result = svgArcToCenterParam(0, 100, 60, 60, 0, 0, 0, 100, 0); console.log(result); /* will output: { cx: 49.99999938964844, cy: 49.99999938964844, startAngle: 2.356194477985314, deltaAngle: -3.141592627780225, endAngle: 5.497787157384675, clockwise: false } */ 
+2
source

I am considering the case of x-axis-rotation = 0. The equations for the start and end points are:

x1 = cx + rx * cos (StartAngle)

y1 = cy + ry * sin (StartAngle)

x2 = cx + rx * cos (EndAngle)

y2 = cy + ry * sin (EndAngle)

The exclusion of angles from pairs of equations gives:

gu ^ 2 * (x1-cx) ^ 2 + gx ^ 2 * (y1-su) ^ 2 = gx ^ 2 * gu ^ 2

gy ^ 2 * (x2-cx) ^ 2 + gx ^ 2 * (y2-su) ^ 2 = gx ^ 2 * gu ^ 2

This system of equations can be analytically solved for (cx, cy) by hand or using mathematical packages (Maple, Mathematica, etc.). There are two solutions to the quadratic equation (due to the combination of a large arc and a flag).

+1
source

Source: https://habr.com/ru/post/906926/


All Articles