在我的旧代数教科书中度过了一段美好的时光后,我为您提供了一个完整的解决方案。
这使用WpfLib Nuget 包(免责声明:我是该包的作者)作为INotifyPropertyChanged
支持,但您应该能够轻松更改您想要的任何更改事件系统。完整的解决方案可以从BitBucket下载。
XAML:
<Window
x:Class="ViewingAngle.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ViewingAngle"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="525"
Height="350"
d:DataContext="{d:DesignInstance local:MainWindowVm}"
mc:Ignorable="d">
<DockPanel Margin="4">
<StackPanel DockPanel.Dock="Bottom">
<TextBlock Margin="4,4,4,0" Text="{Binding Path=FieldOfView, StringFormat='Field of View: {0}'}" />
<Slider
Margin="4"
Maximum="360"
Minimum="0"
TickFrequency="5"
TickPlacement="Both"
Value="{Binding Path=FieldOfView}" />
<TextBlock Margin="4,4,4,0" Text="{Binding Path=TargetAngle, StringFormat='Target Angle: {0}'}" />
<Slider
Margin="4"
Maximum="360"
Minimum="0"
TickFrequency="5"
TickPlacement="Both"
Value="{Binding Path=TargetAngle}" />
</StackPanel>
<Viewbox Margin="4" Stretch="Uniform">
<Canvas Width="500" Height="500">
<Path
Fill="Blue"
Stroke="Blue"
StrokeThickness="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="250,250">
<LineSegment Point="{Binding Path=StartPoint}" />
<ArcSegment
IsLargeArc="{Binding Path=IsLargeArc}"
Point="{Binding Path=EndPoint}"
Size="250,250"
SweepDirection="Clockwise" />
<LineSegment Point="250,250" />
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Canvas>
</Viewbox>
</DockPanel>
</Window>
视图模型:
using System;
using System.Windows;
using AgentOctal.WpfLib;
namespace ViewingAngle
{
class MainWindowVm : ViewModel
{
private const int Radius = 250;
private const int CenterX = 250;
private const int CenterY = 250;
public MainWindowVm()
{
FieldOfView = 45;
TargetAngle = 90;
}
private int _fieldOfView;
public int FieldOfView
{
get { return _fieldOfView; }
set
{
SetValue(ref _fieldOfView, value);
RecalculateArc();
}
}
private int _targetAngle;
public int TargetAngle
{
get { return _targetAngle; }
set
{
SetValue(ref _targetAngle, value);
RecalculateArc();
}
}
private double GetRadians(int angle)
{
return angle * Math.PI / 180;
}
private void RecalculateArc()
{
var targetAngle = GetRadians(_targetAngle);
var fieldOfView = GetRadians(_fieldOfView);
var halfFieldOfView = fieldOfView / 2;
var startAngle = targetAngle - halfFieldOfView;
var endAngle = targetAngle + halfFieldOfView;
double angleDiff = endAngle - startAngle;
IsLargeArc = angleDiff >= Math.PI;
StartPoint = new Point(CenterX + Radius * Math.Cos(startAngle), CenterY + Radius * Math.Sin(startAngle));
EndPoint = new Point(CenterX + Radius * Math.Cos(endAngle), CenterY + Radius * Math.Sin(endAngle));
}
private Point _startPoint;
public Point StartPoint
{
get { return _startPoint; }
set { SetValue(ref _startPoint, value); }
}
private Point _endPoint;
public Point EndPoint
{
get { return _endPoint; }
set { SetValue(ref _endPoint, value); }
}
private bool _isLargeArc;
public bool IsLargeArc
{
get { return _isLargeArc; }
set { SetValue(ref _isLargeArc, value); }
}
}
}
所有的魔法都发生在RecalculateArc
每当TargetAngle
或被FieldOfView
改变时被调用。所有的数学运算都必须以弧度表示,所以它做的第一件事就是转换值。它使用一些涉及正弦和余弦的相当简单的代数计算新的StartPoint
和EndPoint
值ArcSegment
(尽管我仍然需要查数学,因为高中毕业后谁还记得这些东西?)。
在 XAML 中,我放置了一些绑定到 的滑块TargetAngle
,并FieldOfView
允许您控制角度。它还包含Canvas
绘制图形的位置,这是在 a 中ViewBox
,只是为了使指标填充可用空间。
该Canvas
包含Path
,这是由一个高达PathFigure
。所述PathFigure
在250250(500×500的中心开始Canvas
),绘制LineSegment
出到弧的起点,这势必会StartPoint
。一个ArcSegment
然后加入,即在端部EndPoint
。IsLargeArc
只是用来让绘图系统知道要绘制弧的“一半”。添加另一个LineSegment
在中心结束的PathFigure
.
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句