How to draw arc with radius and start and stop angle(如何用半径和开始和停止角度绘制圆弧)
问题描述
如果我的 Canvas 元素的 DataContext 中有以下四个属性
If I have the following four properties in my DataContext of my Canvas element
Point Center
double Radius
double StartAngle
double EndAngle
我可以在没有任何额外代码的情况下绘制圆弧吗?
can I draw an arc without any extra code behind?
推荐答案
事实证明,提供自定义组件是最好的解决方案.我在我的代码中这样使用它
Providing a custom component turned out to be the best solution. I use it like this in my code
<Controls:Arc Center="{Binding Path=PreviousMousePositionPixels}"
Stroke="White"
StrokeDashArray="4 4"
SnapsToDevicePixels="True"
StartAngle="0"
EndAngle="{Binding Path=DeltaAngle}"
SmallAngle="True"
Radius="40" />
SmallAngle 当true 将渲染点之间的小角度,而与StartAngle 和EndAngle 的顺序无关.当 SmallAngle 为 false 时,弧线逆时针渲染.
SmallAngle when true will render the small angle between the points irrespective of order of StartAngle and EndAngle. When SmallAngle is false the arc is rendered counter clockwise.
实现是
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
public sealed class Arc : Shape
{
public Point Center
{
get => (Point)GetValue(CenterProperty);
set => SetValue(CenterProperty, value);
}
// Using a DependencyProperty as the backing store for Center. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CenterProperty =
DependencyProperty.Register(nameof(Center), typeof(Point), typeof(Arc),
new FrameworkPropertyMetadata(new Point(), FrameworkPropertyMetadataOptions.AffectsRender));
public double StartAngle
{
get => (double)GetValue(StartAngleProperty);
set => SetValue(StartAngleProperty, value);
}
// Using a DependencyProperty as the backing store for StartAngle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StartAngleProperty =
DependencyProperty.Register(nameof(StartAngle), typeof(double), typeof(Arc),
new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double EndAngle
{
get => (double)GetValue(EndAngleProperty);
set => SetValue(EndAngleProperty, value);
}
// Using a DependencyProperty as the backing store for EndAngle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty EndAngleProperty =
DependencyProperty.Register(nameof(EndAngle), typeof(double), typeof(Arc),
new FrameworkPropertyMetadata(Math.PI / 2.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double Radius
{
get => (double)GetValue(RadiusProperty);
set => SetValue(RadiusProperty, value);
}
// Using a DependencyProperty as the backing store for Radius. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RadiusProperty =
DependencyProperty.Register(nameof(Radius), typeof(double), typeof(Arc),
new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));
public bool SmallAngle
{
get => (bool)GetValue(SmallAngleProperty);
set => SetValue(SmallAngleProperty, value);
}
// Using a DependencyProperty as the backing store for SmallAngle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SmallAngleProperty =
DependencyProperty.Register(nameof(SmallAngle), typeof(bool), typeof(Arc),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));
static Arc() => DefaultStyleKeyProperty.OverrideMetadata(typeof(Arc), new FrameworkPropertyMetadata(typeof(Arc)));
protected override Geometry DefiningGeometry
{
get
{
double a0 = StartAngle < 0 ? StartAngle + 2 * Math.PI : StartAngle;
double a1 = EndAngle < 0 ? EndAngle + 2 * Math.PI : EndAngle;
if (a1 < a0)
a1 += Math.PI * 2;
SweepDirection d = SweepDirection.Counterclockwise;
bool large;
if (SmallAngle)
{
large = false;
d = (a1 - a0) > Math.PI ? SweepDirection.Counterclockwise : SweepDirection.Clockwise;
}
else
large = (Math.Abs(a1 - a0) < Math.PI);
Point p0 = Center + new Vector(Math.Cos(a0), Math.Sin(a0)) * Radius;
Point p1 = Center + new Vector(Math.Cos(a1), Math.Sin(a1)) * Radius;
List<PathSegment> segments = new List<PathSegment>
{
new ArcSegment(p1, new Size(Radius, Radius), 0.0, large, d, true)
};
List<PathFigure> figures = new List<PathFigure>
{
new PathFigure(p0, segments, true)
{
IsClosed = false
}
};
return new PathGeometry(figures, FillRule.EvenOdd, null);
}
}
}
这篇关于如何用半径和开始和停止角度绘制圆弧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何用半径和开始和停止角度绘制圆弧
基础教程推荐
- 重新排序 WPF TabControl 中的选项卡 2022-01-01
- Mono https webrequest 失败并显示“身份验证或解密失败" 2022-01-01
- 更新 Visual Studio 中的 DataSet 结构以匹配新的 SQL 数据库结构 2022-01-01
- 将数据集转换为列表 2022-01-01
- 从 C# 控制相机设备 2022-01-01
- 在 VB6 或经典 ASP 中使用 .NET 2022-01-01
- SonarQube C# 分析失败“不是指针的有效行偏移" 2022-01-01
- 如果条件可以为空 2022-01-01
- 获取C#保存对话框的文件路径 2022-01-01
- C# 9 新特性——record的相关总结 2023-04-03
