getEllipticalArcCenterParameters function

List<double> getEllipticalArcCenterParameters(
  1. double x1,
  2. double y1,
  3. double rx,
  4. double ry,
  5. double phi,
  6. double fA,
  7. double fS,
  8. double x2,
  9. double y2,
)

Implementation

List<double> getEllipticalArcCenterParameters(double x1, double y1, double rx,
    double ry, double phi, double fA, double fS, double x2, double y2) {
  var cosPhi = cos(phi);
  var sinPhi = sin(phi);

  var x = (x1 - x2) / 2;
  var y = (y1 - y2) / 2;

  var x1p = x * cosPhi + y * sinPhi;
  var y1p = -x * sinPhi + y * cosPhi;

  var r = correctOutOfRangeRadii(rx, ry, x1p, y1p);
  rx = r[0];
  ry = r[1];

  var rx2 = rx * rx;
  var ry2 = ry * ry;
  var x1p2 = x1p * x1p;
  var y1p2 = y1p * y1p;
  var k = sqrt(max(
    (rx2 * ry2 - rx2 * y1p2 - ry2 * x1p2) / (rx2 * y1p2 + ry2 * x1p2),
    0,
  ));

  var sign = fA == fS ? -1 : 1;
  var cxp = sign * k * (rx * y1p) / ry;
  var cyp = sign * k * (-ry * x1p) / rx;

  x = (x1 + x2) / 2;
  y = (y1 + y2) / 2;
  var cx = cxp * cosPhi - cyp * sinPhi + x;
  var cy = cxp * sinPhi + cyp * cosPhi + y;

  x = (x1p - cxp) / rx;
  y = (y1p - cyp) / ry;
  var theta1 = vectorAngle(1, 0, x, y);

  var x_ = (-x1p - cxp) / rx;
  var y_ = (-y1p - cyp) / ry;
  var dtheta = (vectorAngle(x, y, x_, y_) / RADIANS) % 360;

  if (fS == 0 && dtheta > 0) {
    dtheta -= 360;
  } else if (fS == 1 && dtheta < 0) {
    dtheta += 360;
  }

  return [cx, cy, theta1, dtheta * DEGREES];
}