C# 如何用半径和起止角绘制圆弧
如果在画布元素的DataContext中有以下四个属性C# 如何用半径和起止角绘制圆弧,c#,wpf,xaml,geometry,C#,Wpf,Xaml,Geometry,如果在画布元素的DataContext中有以下四个属性 Point Center double Radius double StartAngle double EndAngle 我可以在没有任何额外代码的情况下绘制圆弧吗?提供自定义组件是最好的解决方案。我在代码中这样使用它 <Controls:Arc Center="{Binding Path=PreviousMousePositionPixels}" Stroke="White" Stroke
Point Center
double Radius
double StartAngle
double EndAngle
我可以在没有任何额外代码的情况下绘制圆弧吗?提供自定义组件是最好的解决方案。我在代码中这样使用它
<Controls:Arc Center="{Binding Path=PreviousMousePositionPixels}"
Stroke="White"
StrokeDashArray="4 4"
SnapsToDevicePixels="True"
StartAngle="0"
EndAngle="{Binding Path=DeltaAngle}"
SmallAngle="True"
Radius="40" />
我可以提供一个稍微不同的解决方案吗
class ArcII:FrameworkElement
{
/// <summary>
/// Center point of Arc.
/// </summary>
[Category("Arc")]
public Point Center
{
get { return (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("Center", typeof(Point), typeof(ArcII), new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Forces the Arc to the center of the Parent container.
/// </summary>
[Category("Arc")]
public bool OverrideCenter
{
get { return (bool)GetValue(OverrideCenterProperty); }
set { SetValue(OverrideCenterProperty, value); }
}
// Using a DependencyProperty as the backing store for OverrideCenter. This enables animation, styling, binding, etc...
public static readonly DependencyProperty OverrideCenterProperty =
DependencyProperty.Register("OverrideCenter", typeof(bool), typeof(ArcII), new FrameworkPropertyMetadata((bool)false, FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Start angle of arc, using standard coordinates. (Zero is right, CCW positive direction)
/// </summary>
[Category("Arc")]
public double StartAngle
{
get { return (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("StartAngle", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Length of Arc in degrees.
/// </summary>
[Category("Arc")]
public double SweepAngle
{
get { return (double)GetValue(SweepAngleProperty); }
set { SetValue(SweepAngleProperty, value); }
}
// Using a DependencyProperty as the backing store for SweepAngle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SweepAngleProperty =
DependencyProperty.Register("SweepAngle", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata((double)180, FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Size of Arc.
/// </summary>
[Category("Arc")]
public double Radius
{
get { return (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("Radius", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));
[Category("Arc")]
public Brush Stroke
{
get { return (Brush)GetValue(StrokeProperty); }
set { SetValue(StrokeProperty, value); }
}
// Using a DependencyProperty as the backing store for Stroke. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StrokeProperty =
DependencyProperty.Register("Stroke", typeof(Brush), typeof(ArcII), new FrameworkPropertyMetadata((Brush)Brushes.Black,FrameworkPropertyMetadataOptions.AffectsRender));
[Category("Arc")]
public double StrokeThickness
{
get { return (double)GetValue(StrokeThicknessProperty); }
set { SetValue(StrokeThicknessProperty, value); }
}
// Using a DependencyProperty as the backing store for StrokeThickness. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StrokeThicknessProperty =
DependencyProperty.Register("StrokeThickness", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata((double)1,FrameworkPropertyMetadataOptions.AffectsRender));
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
Draw(dc);
}
private void Draw(DrawingContext dc)
{
Point center = new Point();
if (OverrideCenter)
{
Rect rect = new Rect(RenderSize);
center = Polar.CenterPointFromRect(rect);
}
else
{
center = Center;
}
Point startPoint = Polar.PolarToCartesian(StartAngle, Radius, center);
Point endPoint = Polar.PolarToCartesian(StartAngle + SweepAngle, Radius, center);
Size size = new Size(Radius, Radius);
bool isLarge = (StartAngle + SweepAngle) - StartAngle > 180;
List<PathSegment> segments = new List<PathSegment>(1);
segments.Add(new ArcSegment(endPoint, new Size(Radius, Radius), 0.0, isLarge, SweepDirection.Clockwise, true));
List<PathFigure> figures = new List<PathFigure>(1);
PathFigure pf = new PathFigure(startPoint, segments, true);
pf.IsClosed = false;
figures.Add(pf);
Geometry g = new PathGeometry(figures, FillRule.EvenOdd, null);
dc.DrawGeometry(null, new Pen(Stroke,StrokeThickness), g);
}
}
类别ArcII:框架元素
{
///
///弧的中心点。
///
[类别(“Arc”)]
公共点中心
{
获取{return(Point)GetValue(CenterProperty);}
set{SetValue(CenterProperty,value);}
}
//使用DependencyProperty作为Center的后台存储。这将启用动画、样式、绑定等。。。
公共静态只读DependencyProperty CenterProperty=
DependencyProperty.Register(“中心”、typeof(点)、typeof(ArcII)、新FrameworkPropertyMetadata(新点(0,0)、FrameworkPropertyMetadata选项.AffectsRender));
///
///将圆弧强制到父容器的中心。
///
[类别(“Arc”)]
公共布尔覆盖中心
{
获取{return(bool)GetValue(OverrideCenterProperty);}
set{SetValue(OverrideCenterProperty,value);}
}
//使用DependencyProperty作为OverrideCenter的备份存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性OverrideCenterProperty=
DependencyProperty.Register(“OverrideCenter”,typeof(bool),typeof(ArcII),new FrameworkPropertyMetadata((bool)false,FrameworkPropertyMetadata.AffectsRender));
///
///弧的起始角,使用标准坐标。(零为右,逆时针正方向)
///
[类别(“Arc”)]
公共双星纠缠
{
获取{return(double)GetValue(StartAngleProperty);}
set{SetValue(StartAngleProperty,value);}
}
//使用DependencyProperty作为StartAngle的后台存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性StartAngleProperty=
DependencyProperty.Register(“StartAngle”、typeof(double)、typeof(ArcII)、新的FrameworkPropertyMetadata(0.0,FrameworkPropertyMetadataOptions.AffectsRender));
///
///弧的长度(以度为单位)。
///
[类别(“Arc”)]
公共双扫掠角
{
获取{return(double)GetValue(sweepingproperty);}
set{SetValue(sweepingproperty,value);}
}
//使用DependencyProperty作为扫描角度的后备存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性SweepAngleProperty=
DependencyProperty.Register(“扫掠角度”、typeof(double)、typeof(ArcII)、新FrameworkPropertyMetadata((double)180、FrameworkPropertyMetadata选项.AffectsRender));
///
///弧的大小。
///
[类别(“Arc”)]
公共双半径
{
获取{return(double)GetValue(radiuproperty);}
set{SetValue(radiuproperty,value);}
}
//使用DependencyProperty作为Radius的后台存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性RadiusProperty=
DependencyProperty.Register(“半径”、typeof(双精度)、typeof(ArcII)、新FrameworkPropertyMetadata(10.0,FrameworkPropertyMetadataOptions.AffectsRender));
[类别(“Arc”)]
公共画笔
{
获取{return(Brush)GetValue(StrokeProperty);}
set{SetValue(StrokeProperty,value);}
}
//使用DependencyProperty作为笔划的后备存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性StrokeProperty=
DependencyProperty.Register(“Stroke”、typeof(Brush)、typeof(ArcII)、new FrameworkPropertyMetadata((Brush)Brush.Black、FrameworkPropertyMetadata Options.AffectsRender));
[类别(“Arc”)]
公共双冲程
{
获取{return(double)GetValue(StrokeThicknessProperty);}
set{SetValue(StrokeThicknessProperty,value);}
}
//使用DependencyProperty作为StrokeThickness的后台存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性StrokeThicknessProperty=
DependencyProperty.Register(“StrokeThickness”、typeof(double)、typeof(ArcII)、new FrameworkPropertyMetadata((double)1、FrameworkPropertyMetadata.AffectsRender));
受保护的覆盖无效OnRender(DrawingContext dc)
{
base.OnRender(dc);
抽签(dc);
}
专用作废绘图(DrawingContext dc)
{
点中心=新点();
如果(覆盖中心)
{
Rect Rect=新的Rect(renderize);
中心=极轴。中心点FROMRECT(rect);
}
其他的
{
中心=中心;
}
点startPoint=极坐标。极笛卡尔坐标(星形、半径、中心);
点端点=极坐标。极笛卡尔坐标(星形缠结+扫掠角、半径、中心);
尺寸=新尺寸(半径、半径);
布尔isLarge=(星形缠结+扫掠角)-星形缠结>180;
列表段=新列表(1);
添加(新圆弧段(端点,新尺寸(半径,半径),0.0,isLarge,SweepDirection.顺时针,true));
列表数字=新列表(1);
PathFigure pf=新的路径图(起点、分段、真);
pf.IsClosed=false;
图.添加(pf);
几何图形g=新的路径几何图形(figures,FillRule.EvenOdd,null);
DrawGeometry(空,新笔(笔划,笔划厚度),g);
}
}
用法:
<!--Centerd on Parent-->
<local:ArcII Center="0,0"
OverrideCenter="True"
StartAngle="150"
SweepAngle="240"
Radius="100"
Stroke="Red"
StrokeThickness="3"
/>
<!--Centerd on Parent-->
<local:ArcII Center="0,0"
OverrideCenter="True"
StartAngle="150"
SweepAngle="240"
Radius="95"
Stroke="Red"
StrokeThickness="3"
/>
<!--Centerd on Parent-->
<local:ArcII Center="0,0"
OverrideCenter="True"
StartAngle="150"
SweepAngle="240"
Radius="90"
Stroke="Red"
StrokeThickness="3"
/>
<!--Centerd on Point-->
<local:ArcII Center="0,150"
OverrideCenter="False"
StartAngle="270"
SweepAngle="180"
Radius="100"
/>
<!--Centerd on Point-->
<local:ArcII Center="525,150"
OverrideCenter="False"
StartAngle="90"
SweepAngle="180"
Radius="100"
/>
注:
A) 这不会产生360度扫掠角,因为它使用椭圆。
B) OverrideCenter:将圆弧的中心置于其父圆弧的中心。请注意,可以分区的网格等元素仍有一个中心,该中心可能不是弧所在的列或行。可能几乎有用,但
<!--Centerd on Parent-->
<local:ArcII Center="0,0"
OverrideCenter="True"
StartAngle="150"
SweepAngle="240"
Radius="100"
Stroke="Red"
StrokeThickness="3"
/>
<!--Centerd on Parent-->
<local:ArcII Center="0,0"
OverrideCenter="True"
StartAngle="150"
SweepAngle="240"
Radius="95"
Stroke="Red"
StrokeThickness="3"
/>
<!--Centerd on Parent-->
<local:ArcII Center="0,0"
OverrideCenter="True"
StartAngle="150"
SweepAngle="240"
Radius="90"
Stroke="Red"
StrokeThickness="3"
/>
<!--Centerd on Point-->
<local:ArcII Center="0,150"
OverrideCenter="False"
StartAngle="270"
SweepAngle="180"
Radius="100"
/>
<!--Centerd on Point-->
<local:ArcII Center="525,150"
OverrideCenter="False"
StartAngle="90"
SweepAngle="180"
Radius="100"
/>