parseArcCommand method

void parseArcCommand(
  1. ShapePath path,
  2. double rx,
  3. double ry,
  4. double xAxisRotation,
  5. double largeArcFlag,
  6. double sweepFlag,
  7. Vector start,
  8. Vector end,
)

Implementation

void parseArcCommand(ShapePath path, double rx, double ry, double xAxisRotation, double largeArcFlag, double sweepFlag, Vector start, Vector end) {
  if (rx == 0 || ry == 0) {
    // draw a line if either of the radii == 0
    path.lineTo(end.x, end.y);
    return;
  }

  xAxisRotation = xAxisRotation * math.pi / 180;

  // Ensure radii are positive
  rx = rx.abs();
  ry = ry.abs();

  // Compute (x1', y1')
  final dx2 = (start.x - end.x) / 2.0;
  final dy2 = (start.y - end.y) / 2.0;
  final x1p = math.cos(xAxisRotation) * dx2 + math.sin(xAxisRotation) * dy2;
  final y1p = -math.sin(xAxisRotation) * dx2 + math.cos(xAxisRotation) * dy2;

  // Compute (cx', cy')
  double rxs = rx * rx;
  double rys = ry * ry;
  final x1ps = x1p * x1p;
  final y1ps = y1p * y1p;

  // Ensure radii are large enough
  final cr = x1ps / rxs + y1ps / rys;

  if (cr > 1) {
    // scale up rx,ry equally so cr == 1
    final s = math.sqrt(cr);
    rx = s * rx;
    ry = s * ry;
    rxs = rx * rx;
    rys = ry * ry;
  }

  final dq = (rxs * y1ps + rys * x1ps);
  final pq = (rxs * rys - dq) / dq;
  double q = math.sqrt(math.max(0, pq));
  if (largeArcFlag == sweepFlag) q = -q;
  final cxp = q * rx * y1p / ry;
  final cyp = -q * ry * x1p / rx;

  // Step 3: Compute (cx, cy) from (cx', cy')
  final cx = math.cos(xAxisRotation) * cxp -
      math.sin(xAxisRotation) * cyp +
      (start.x + end.x) / 2;
  final cy = math.sin(xAxisRotation) * cxp +
      math.cos(xAxisRotation) * cyp +
      (start.y + end.y) / 2;

  // Step 4: Compute θ1 and Δθ
  final theta = svgAngle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
  final delta = svgAngle((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx,
          (-y1p - cyp) / ry) %
      (math.pi * 2);

  path.currentPath.absellipse(
      cx, cy, rx, ry, theta, theta + delta, sweepFlag == 0, xAxisRotation);
}