rSector static method

Path rSector({
  1. required Offset center,
  2. required double r,
  3. required double r0,
  4. required double startAngle,
  5. required double endAngle,
  6. required bool clockwise,
  7. required Radius topLeft,
  8. required Radius topRight,
  9. required Radius bottomRight,
  10. required Radius bottomLeft,
  11. Path? path,
})

A sector with corner radiuses.

This functions can either return a new path or add to existing path.

For a sector, Radius.x is circular, Radius.y is radial, top is outer side, bottom is inner side, left is anticlockwise, right is clockwise.

Implementation

static Path rSector({
  required Offset center,
  required double r,
  required double r0,
  required double startAngle,
  required double endAngle,
  required bool clockwise,
  required Radius topLeft,
  required Radius topRight,
  required Radius bottomRight,
  required Radius bottomLeft,
  Path? path,
}) {
  path = path ?? Path();

  final sweepAngle = endAngle - startAngle;
  final sweepAngleAbs = (sweepAngle).abs();

  if (sweepAngleAbs.equalTo(0)) {
    return path;
  }

  // The canvas can not fill a ring, so it is devided to two semi rings
  if (sweepAngleAbs.equalTo(pi * 2)) {
    sector(
      center: center,
      r: r,
      r0: r0,
      startAngle: 0,
      endAngle: pi,
      clockwise: true,
      path: path,
    );
    sector(
      center: center,
      r: r,
      r0: r0,
      startAngle: pi,
      endAngle: pi * 2,
      clockwise: true,
      path: path,
    );
    return path;
  }

  double arcStart;
  double arcEnd;
  double arcSweep;

  // Makes sure the corners correct when radiuses or angles are reversed.

  final cornerCircularSign = sweepAngle / sweepAngleAbs;
  final radialInterval = r - r0;
  final cornerRadialSign = radialInterval / radialInterval.abs();

  // Calculates the top angles.

  arcStart = clockwise
      ? startAngle + cornerCircularSign * (topLeft.x / r)
      : startAngle - cornerCircularSign * (topLeft.x / r);
  arcEnd = clockwise
      ? endAngle - cornerCircularSign * (topRight.x / r)
      : endAngle + cornerCircularSign * (topRight.x / r);
  arcSweep = clockwise ? arcEnd - arcStart : arcStart - arcEnd;

  // The top left corner.

  path.moveTo(
    cos(startAngle) * (r - cornerRadialSign * topLeft.y) + center.dx,
    sin(startAngle) * (r - cornerRadialSign * topLeft.y) + center.dy,
  );
  path.quadraticBezierTo(
    cos(startAngle) * r + center.dx,
    sin(startAngle) * r + center.dy,
    cos(arcStart) * r + center.dx,
    sin(arcStart) * r + center.dy,
  );

  // The top arc.

  path.arcTo(
    Rect.fromCircle(center: center, radius: r),
    arcStart,
    arcSweep,
    false,
  );

  // The top right corner.

  path.quadraticBezierTo(
    cos(endAngle) * r + center.dx,
    sin(endAngle) * r + center.dy,
    cos(endAngle) * (r - cornerRadialSign * topRight.y) + center.dx,
    sin(endAngle) * (r - cornerRadialSign * topRight.y) + center.dy,
  );
  path.lineTo(
    cos(endAngle) * (r0 + cornerRadialSign * bottomRight.y) + center.dx,
    sin(endAngle) * (r0 + cornerRadialSign * bottomRight.y) + center.dy,
  );

  if (r0 != 0) {
    // Calculates the bottom angles.

    arcStart = clockwise
        ? startAngle + cornerCircularSign * (bottomLeft.x / r0)
        : startAngle - cornerCircularSign * (bottomLeft.x / r0);
    arcEnd = clockwise
        ? endAngle - cornerCircularSign * (bottomRight.x / r0)
        : endAngle + cornerCircularSign * (bottomRight.x / r0);
    arcSweep = clockwise ? arcEnd - arcStart : arcStart - arcEnd;

    // The bottom right corner.

    path.quadraticBezierTo(
      cos(endAngle) * r0 + center.dx,
      sin(endAngle) * r0 + center.dy,
      cos(arcEnd) * r0 + center.dx,
      sin(arcEnd) * r0 + center.dy,
    );

    // The bottom arc.

    path.arcTo(
      Rect.fromCircle(center: center, radius: r0),
      arcEnd,
      -arcSweep,
      false,
    );

    // The bottom left corner.
    path.quadraticBezierTo(
      cos(startAngle) * r0 + center.dx,
      sin(startAngle) * r0 + center.dy,
      cos(startAngle) * (r0 + cornerRadialSign * bottomLeft.y) + center.dx,
      sin(startAngle) * (r0 + cornerRadialSign * bottomLeft.y) + center.dy,
    );
  }

  path.close();

  return path;
}