在WPF中绘制sin函数

时间:2016-01-02 19:47:25

标签: c# wpf xaml

我的数学老师让我写一个程序来绘制图表。我真的不知道我必须实现什么,所以我决定画一个sin函数。由于我在Windows Phone开发方面有一些经验,我决定用WPF编写它。所以我写了以下XAML:

res.pipe(url)

和C#代码:

<Window x:Class="DemoMath.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DemoMath"
        mc:Ignorable="d"
        Title="MathDemo" DataContext="{Binding RelativeSource={RelativeSource Self}}" Height="301.645" Width="525">
            <StackPanel VerticalAlignment="Center" Grid.Row="1">

            <Canvas Background="CornflowerBlue" x:Name="drawingSurface" Height="128">
                <TextBlock Width="{Binding ActualWidth, ElementName=drawingSurface}" Canvas.Top="25" x:Name="placeholder"  FontSize="40" Foreground="#FFF"  Text="Graph" TextAlignment="Center" FontFamily="Segoe Print"/>
                <Polyline Points="{Binding Graph2DPoints, Converter={StaticResource PointConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Stroke="White" StrokeThickness="2" Visibility="Collapsed" x:Name="graph2D"/>
                <Polyline Visibility="Collapsed" x:Name="scale"/>
            </Canvas>
            <Grid>
                <Button x:Name="button" Click="Button_Click_1" Width="100">
                    <Button.Content>
                        <TextBlock Text="Generate" FontSize="16" FontFamily="Times New Roman"/>
                    </Button.Content>
                </Button>
            </Grid>
        </StackPanel>
</Window>

一段时间后,它会显示一些奇怪的内容, public class ToPointCollection : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if(value!=null) return new PointCollection(value as ObservableCollection<Point>); return null; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } } public partial class MainWindow : Window , INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged = delegate { }; private void RaisePropertyChanged(string propertyName) { var handlers = PropertyChanged; handlers(this, new PropertyChangedEventArgs(propertyName)); } ObservableCollection<Point> _graph2DPoints = new ObservableCollection<Point>(); public ObservableCollection<Point> Graph2DPoints { get { return _graph2DPoints; } set { _graph2DPoints = value; RaisePropertyChanged("Graph2DPoints"); } } Timer timer = new Timer() { Interval=1, AutoReset=true }; double HeightSurface; public MainWindow() { InitializeComponent(); Graph2DPoints.CollectionChanged += (s, e) => { RaisePropertyChanged("Graph2DPoints"); }; timer.Elapsed += Timer_Elapsed; HeightSurface = drawingSurface.Height / 2; } private void Button_Click_1(object sender, RoutedEventArgs e) { timer.Stop(); button.Visibility = Visibility.Collapsed; placeholder.Visibility = Visibility.Collapsed; List<Point> GraphPoints = new List<Point>(), scalePoints = new List<Point>(); for (double phi = 0.0; phi <= 4* Math.PI; phi = phi + 0.1) { phi = Math.Round(phi, 2); var cosValue = -Math.Cos(phi); scalePoints.Add(new Point(20 + phi * 15, drawingSurface.Height / 2)); Graph2DPoints.Add(new Point(20 + phi * 15, drawingSurface.Height / 2 + cosValue * 15)); } scale.Points = new PointCollection(scalePoints); scale.Stroke = new SolidColorBrush(Colors.WhiteSmoke); scale.StrokeThickness = 1; graph2D.Visibility = Visibility.Visible; scale.Visibility = Visibility.Visible; graph3D.Visibility = Visibility.Collapsed; timer.Start(); } double phase = Math.PI/2+0.1; private void Timer_Elapsed(object sender, ElapsedEventArgs e) { timer.Stop(); for (int i = 0; i < Graph2DPoints.Count; i++) { Graph2DPoints[i] = new Point(Graph2DPoints[i].X - 0.5, Graph2DPoints[i].Y); } if (Graph2DPoints[0].X < 0) { Graph2DPoints.RemoveAt(0); Point p = Graph2DPoints.Last(); System.Diagnostics.Debug.WriteLine(p.X); Graph2DPoints.Add(new Point(p.X + 4.5, HeightSurface - Math.Cos(phase) * 15)); } phase += 0.1; if (phase >= 5*Math.PI/2) phase = Math.PI / 2; phase = Math.Round(phase, 2); timer.Start(); } } } 只返回一个值:

enter image description here

1 个答案:

答案 0 :(得分:1)

好!干得好首先!

你所说的一段时间之后实际上是程序开始运行 if(Graph2DPoints [0] .X <0)语句的主体。< / p>

奇怪行为的原因是这两行之间存在不一致:

for (int i = 0; i < Graph2DPoints.Count; i++)
        {
            Graph2DPoints[i] = new Point(Graph2DPoints[i].X - 0.5, Graph2DPoints[i].Y);
        }

Graph2DPoints.Add(new Point(p.X + 4.5, HeightSurface - Math.Cos(phase) * 15));

问题在于,在代码的顶部,您将图表推进了-0.5像素,而在第二部分中,您将图表推进了4.5!

我建议你设置-0.5到-4.5然后再试一次!如你所见,问题已经消失。但是你可能会抱怨更长的波长。你有两种选择:

1-而不是4.5,使用较低的值,如2.5! 2-尝试将Y值相乘,使其看起来更好。

一开始还有一点小问题,你可以通过改变开始阶段来解决它。

;)玩得开心。