前言
已知一个直径为 100 的圆,可从12点位置(50,0)顺时针绘制指定角度的圆弧。
根据上述的功能描述,我们可得到下列数据:
参数 | 参数值 |
圆的直径 | 100 |
绘制的角度 | Angle(用户指定的值,未知变量) |
绘制的起点位置 | 50,0 |
绘制的方向 | Clockwise(顺时针) |
接下来我们将使用 ArcSegment 对象绘制圆弧,为了便于读者理解,这里我们对 ArcSegment 中的一些属性进行一个简单的说明。
属性名 | 属性说明 |
IsLargeArc | 获取或设置一个值,该值指示弧是否应大于 180 度。 |
Point | 获取或设置椭圆弧的终结点。 |
Size | 获取或设置弧的 X 轴半径和 Y 轴半径作为 Size 结构。 |
SweepDirection | 获取或设置一个值,该值指定是以 Clockwise 方向还是以 Counterclockwise 方向绘制弧。 |
解决方案
public class ArcSegmentViewModel : ViewModel
{
private int angle;
private int diameter = 100;
/// <summary>
/// 直径
/// </summary>
public int Diameter
{
get => diameter;
set => this.SetValue(ref diameter, value);
}
/// <summary>
/// 角度
/// </summary>
public int Angle
{
get => angle;
set => this.SetValue(ref angle, value);
}
public ICommand DrawCommand { get; }
public ArcSegmentViewModel()
{
DrawCommand = new DelegateCommand<Path>(DrawCommandExecuteMethod);
}
private void DrawCommandExecuteMethod(Path path)
{
Draw1(path);
}
private void Draw1(Path path)
{
var degree = 180;
// 0° 和 360° 是重合在一起的,ArcSegment 无法绘制重合的弧度。
// 所以,最大角度是359。如果,目标值是 360° 则使用 PathFigure 中的属性 IsClose 闭合圆。
var maxAngle = 359;
// 获取最终角度
var angle = Math.Min(maxAngle, Angle);
// 绘制直径时,需要去掉边框尺寸,不然绘制的圆会超出正方形。
var diameter = Diameter - path.StrokeThickness;
// 根据数学公式计算出当前角度的弧度
var arc = angle * Math.PI / degree;
// 获取正弦值:a/c
var sin = Math.Sin(arc);
// 获取余弦值:b/c
var cos = Math.Cos(arc);
// 获取半径:c
var radius = diameter / 2;
// 获取 a
var a = radius * sin;
// 获取 b
var b = radius * cos;
// 获取终点位置:X
var x = radius + a;
// 获取终点位置:Y
var y = radius - b;
// 获取终点位置
var endPoint = new Point(x, y);
var segment = new ArcSegment();
segment.IsLargeArc = angle > degree;
segment.SweepDirection = SweepDirection.Clockwise;
segment.Size = new Size(radius, radius);
segment.Point = endPoint;
var figure = new PathFigure();
// 设置起点位置
figure.StartPoint = new Point(radius, 0);
figure.IsClosed = angle >= maxAngle;
figure.Segments.Add(segment);
var geometry = new PathGeometry();
geometry.Figures.Add(figure);
path.Data = geometry;
}
}