Files
charts_flutter/lib/src/canvas/circle_sector_painter.dart
2025-04-03 14:27:30 +07:00

104 lines
4.0 KiB
Dart

// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'dart:math' show cos, pi, sin, Point;
import 'package:flutter/material.dart';
import 'package:charts_common/common.dart' as common show Color;
/// Draws a sector of a circle, with an optional hole in the center.
class CircleSectorPainter {
/// Draws a sector of a circle, with an optional hole in the center.
///
/// [center] The x, y coordinates of the circle's center.
/// [radius] The radius of the circle.
/// [innerRadius] Optional radius of a hole in the center of the circle that
/// should not be filled in as part of the sector.
/// [startAngle] The angle at which the arc starts, measured clockwise from
/// the positive x axis and expressed in radians.
/// [endAngle] The angle at which the arc ends, measured clockwise from the
/// positive x axis and expressed in radians.
/// [fill] Fill color for the sector.
/// [stroke] Stroke color of the arc and radius lines.
/// [strokeWidthPx] Stroke width of the arc and radius lines.
static void draw({
required Canvas canvas,
required Paint paint,
required Point center,
required double radius,
required double innerRadius,
required double startAngle,
required double endAngle,
common.Color? fill,
}) {
paint.color = new Color.fromARGB(fill!.a, fill.r, fill.g, fill.b);
paint.style = PaintingStyle.fill;
final innerRadiusStartPoint = new Point<double>(
innerRadius * cos(startAngle) + center.x,
innerRadius * sin(startAngle) + center.y);
final innerRadiusEndPoint = new Point<double>(
innerRadius * cos(endAngle) + center.x,
innerRadius * sin(endAngle) + center.y);
final radiusStartPoint = new Point<double>(
radius * cos(startAngle) + center.x,
radius * sin(startAngle) + center.y);
final centerOffset = new Offset(center.x.toDouble(), center.y.toDouble());
final isFullCircle = startAngle != null &&
endAngle != null &&
endAngle - startAngle == 2 * pi;
final midpointAngle = (endAngle + startAngle) / 2;
final path = new Path()
..moveTo(innerRadiusStartPoint.x, innerRadiusStartPoint.y);
path.lineTo(radiusStartPoint.x, radiusStartPoint.y);
// For full circles, draw the arc in two parts.
if (isFullCircle) {
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: radius),
startAngle, midpointAngle - startAngle, true);
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: radius),
midpointAngle, endAngle - midpointAngle, true);
} else {
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: radius),
startAngle, endAngle - startAngle, true);
}
path.lineTo(innerRadiusEndPoint.x, innerRadiusEndPoint.y);
// For full circles, draw the arc in two parts.
if (isFullCircle) {
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: innerRadius),
endAngle, midpointAngle - endAngle, true);
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: innerRadius),
midpointAngle, startAngle - midpointAngle, true);
} else {
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: innerRadius),
endAngle, startAngle - endAngle, true);
}
// Drawing two copies of this line segment, before and after the arcs,
// ensures that the path actually gets closed correctly.
path.lineTo(radiusStartPoint.x, radiusStartPoint.y);
canvas.drawPath(path, paint);
}
}