Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.70/88: Рейтинг темы: голосов - 88, средняя оценка - 4.70
88 / 86 / 55
Регистрация: 14.11.2015
Сообщений: 1,098
1

[WPF] Построить график функции

19.04.2017, 08:36. Показов 18180. Ответов 6
Метки нет (Все метки)

Допустим, мне необходимо построить график следующей функции:
[WPF] Построить график функции


Точки получаю так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
            List<Point> points = new List<Point>();
            double y;
            for (double x = -12.6; x <= 12.6; x += 0.1)
            {
                y = (3 * x + 4 * 1 / Math.Tan(x));
                points.Add(new Point(x, y));
            }
 
            foreach(Point p in points) {
                Line lne = new Line();
                lne.X1 = p.X;
                lne.X2 = p.X + 1;
                lne.Y1 = p.Y;
                lne.Y2 = p.Y + 1;
 
                lne.StrokeThickness = 2;
                lne.Stroke = Brushes.Black;
                canvas.Children.Add(lne);
            }
Как спроектировать реальные координаты функции на Canvas? То есть сделать систему координат на канвасе такую же, в какой я получаю точки?(сделать макс. и мин. значения на осях)

Сейчас ситуация такая
[WPF] Построить график функции


Хочу сделать чтобы координатная система была следующая:
[WPF] Построить график функции


Буду рад любой помощи.
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.04.2017, 08:36
Ответы с готовыми решениями:

Построить график в WPF
Здравствуйте. Есть программа которая сортирует массив по указанному методу и фиксирует время...

Построить график wpf на основе данных из БД
Возникла необходимость построить график в wpf приложении на основе данных из БД. Мне нужно вытащить...

График (C# и WPF)
Нужно нарисовать график, но не знаю каким способом лучше всего сделать. Программа с графиком...

WPF и Curve график
Коллеги, подскажите пожалуйста. Нужно построить график по нескольким точкам. В WFA есть такая шняга...

6
8424 / 4617 / 1807
Регистрация: 11.02.2013
Сообщений: 9,827
19.04.2017, 20:54 2
Функцию ты не самую лёгкую выбрал, в том смысле, что она не непрерывная. Выложи, что уже сделано.
2
88 / 86 / 55
Регистрация: 14.11.2015
Сообщений: 1,098
19.04.2017, 21:07  [ТС] 3
[WPF] Не рисуется линия на canvas

Хочу просто разобраться с логикой построения этой системы координат(чтобы строить любые функции), никак она мне не дается.
0
8424 / 4617 / 1807
Регистрация: 11.02.2013
Сообщений: 9,827
19.04.2017, 21:16 4
Artmal, проект выложи. Логика там простая. Значения функции собираешь в список на том интервале, на котором тебе нужно, не думая о форме. Для вывода на форму лучше использовать Path, в который через конвертер положить твои значения. И применить к Path уже масштаб и всё остальное. Сейчас не могу написать, может попозже или завтра.
2
88 / 86 / 55
Регистрация: 14.11.2015
Сообщений: 1,098
19.04.2017, 21:24  [ТС] 5
ThirdLab.zip
0
8424 / 4617 / 1807
Регистрация: 11.02.2013
Сообщений: 9,827
19.04.2017, 23:31 6
Лучший ответ Сообщение было отмечено Artmal как решение

Решение

Ну примерно так. Я причесал твою разметку: сделал её "резиновой" и выбросил всё, что не нужно, из кода окна. Значения из формы в код передаю через свойства зависимостей: параметры для расчётов и список точек, расчитанных по формуле. Оси рисуются из разметки через конвертер DivideByTwoConverter. Точки перегоняются в фигуру конвертером PointsToPathConverter.
В расчётах, чтобы график не вылезал за пределы канвы, я отбрасываю значения возле ассимптот
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
public partial class MainWindow : Window
{
 
    #region Свойства
    public static readonly DependencyProperty PointsProperty = DependencyProperty.Register(
        "Points", typeof(ObservableCollection<Point>), typeof(MainWindow), new PropertyMetadata(default(ObservableCollection<Point>)));
 
    public ObservableCollection<Point> Points
    {
        get
        {
            return (ObservableCollection<Point>)GetValue(PointsProperty);
        }
        set
        {
            SetValue(PointsProperty, value);
        }
    }
 
    public static readonly DependencyProperty AProperty = DependencyProperty.Register(
        "A", typeof(double), typeof(MainWindow), new PropertyMetadata(5.0));
 
    public double A
    {
        get
        {
            return (double)GetValue(AProperty);
        }
        set
        {
            SetValue(AProperty, value);
        }
    }
 
    public static readonly DependencyProperty BProperty = DependencyProperty.Register(
        "B", typeof(double), typeof(MainWindow), new PropertyMetadata(3.8));
 
    public double B
    {
        get
        {
            return (double)GetValue(BProperty);
        }
        set
        {
            SetValue(BProperty, value);
        }
    }
 
    public static readonly DependencyProperty RangeFromProperty = DependencyProperty.Register(
        "RangeFrom", typeof(double), typeof(MainWindow), new PropertyMetadata(default(double)));
 
    public double RangeFrom
    {
        get
        {
            return (double)GetValue(RangeFromProperty);
        }
        set
        {
            SetValue(RangeFromProperty, value);
        }
    }
 
    public static readonly DependencyProperty RangeToProperty = DependencyProperty.Register(
        "RangeTo", typeof(double), typeof(MainWindow), new PropertyMetadata(default(double)));
 
    public double RangeTo
    {
        get
        {
            return (double)GetValue(RangeToProperty);
        }
        set
        {
            SetValue(RangeToProperty, value);
        }
    }
 
    public static readonly DependencyProperty AccuracyProperty = DependencyProperty.Register(
        "Accuracy", typeof(double), typeof(MainWindow), new PropertyMetadata(1e-4));
 
    public double Accuracy
    {
        get
        {
            return (double)GetValue(AccuracyProperty);
        }
        set
        {
            SetValue(AccuracyProperty, value);
        }
    } 
    #endregion
 
    public MainWindow()
    {
        InitializeComponent();
    }
 
    private void Start_Button_Click(object sender, RoutedEventArgs e)
    {
        List<Point> points = new List<Point>();
 
        for (double x = -12.6; x <= 12.6; x += 0.1)
        {
            if (Math.Abs(x) < 1e-2)
            {
                continue;
            }
            var y = (A * x + B * 1 / Math.Tan(x));
            points.Add(new Point(x, y));
        }
        Points = new ObservableCollection<Point>(points);
    }
}
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<Window x:Class="ThirdLab.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:thirdLab="clr-namespace:ThirdLab"
        Title="MainWindow"
        x:Name="Window"
        Width="800"
        Height="600">
    <Window.Resources>
        <thirdLab:DivideByTwoConverter x:Key="DivideByTwo" />
        <thirdLab:PointsToPathConverter x:Key="PointsToPath" />
        <Style TargetType="TextBox">
            <Setter Property="Margin"
                    Value="2" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <DockPanel LastChildFill="False">
            <Label Content="a:" />
            <TextBox Text="{Binding ElementName=Window, Path=A}"
                     MinWidth="40" />
            <Label Content="b:" />
            <TextBox Text="{Binding ElementName=Window, Path=B}"
                     MinWidth="40" />
            <Label Content="Root search range:" />
            <TextBox Text="{Binding ElementName=Window, Path=RangeFrom}"
                     MinWidth="40" />
            <TextBox Text="{Binding ElementName=Window, Path=RangeTo}"
                     MinWidth="40" />
            <Label Content="Accuracy:" />
            <TextBox Text="{Binding ElementName=Window, Path=Accuracy}"
                     MinWidth="40" />
            <Button Click="Start_Button_Click"
                    MinWidth="40"
                    Margin="2"
                    Padding="2"
                    Content="Start" />
            <Label Content="y = ax + b ctg(x)"
                   DockPanel.Dock="Right"
                   HorizontalAlignment="Right" />
        </DockPanel>
        <Canvas Grid.Row="1"
                x:Name="canvas"
                Background="Yellow"
                Margin="0 5 0 0"
                MinHeight="0">
            <!--Ось Y-->
            <Line X1="{Binding ElementName=canvas, Path=ActualWidth, Converter={StaticResource DivideByTwo}}"
                  Y1="0"
                  X2="{Binding RelativeSource={RelativeSource Self}, Path=X1}"
                  Y2="{Binding ElementName=canvas, Path=ActualHeight}"
                  Stroke="Green" />
            <!--Ось X-->
            <Line X1="0"
                  Y1="{Binding ElementName=canvas, Path=ActualHeight, Converter={StaticResource DivideByTwo}}"
                  X2="{Binding ElementName=canvas, Path=ActualWidth}"
                  Y2="{Binding RelativeSource={RelativeSource Self}, Path=Y1}"
                  Stroke="Green" />
            <!--График-->
            <Path Stroke="Red"
                  StrokeThickness="3">
                <Path.Data>
                    <MultiBinding Converter="{StaticResource PointsToPath}">
                        <Binding ElementName="Window"
                                 Path="Points" />
                        <Binding ElementName="canvas"
                                 Path="ActualWidth" />
                        <Binding ElementName="canvas"
                                 Path="ActualHeight" />
                    </MultiBinding>
                </Path.Data>
                <Path.RenderTransform>
                    <TransformGroup>
                        <TranslateTransform X="{Binding ElementName=canvas, Path=ActualWidth, Converter={StaticResource DivideByTwo}}"
                                            Y="{Binding ElementName=canvas, Path=ActualHeight, Converter={StaticResource DivideByTwo}}" />
                    </TransformGroup>
                </Path.RenderTransform>
            </Path>
        </Canvas>
    </Grid>
</Window>
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/// <summary>
/// Конвертер для перевода просчитанных точек в фигуру.
/// </summary>
public class PointsToPathConverter
    : IMultiValueConverter
{
 
    #region Implementation of IMultiValueConverter
 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var points = values[0] as IEnumerable<Point>;
        if (points == null)
        {
            return null;
        }
        var w = (double)values[1] * .8;//Ширина зоны построения. 80% от ширины полотна
        var h = (double)values[2] * .8;//Высота зоны построения. 80% от высоты полотна
        var pg = new PathGeometry();//Геометрия, которую будем возвращать.
        var ps = new List<PathSegment>();//Набор сегментов пути
        //Размах значений по X
        var rangeX = points.Max(p => p.X) - points.Min(p => p.X);
        //Размах значений по Y
        var rangeY = points.Max(p => p.Y) - points.Min(p => p.Y);
        //Масштаб по X
        var scaleX = w / rangeX;
        //Масштаб по Y
        var scaleY = h / rangeY;
        //Пересчёт точек
        points = points.Select(p => new Point(p.X * scaleX, p.Y * scaleY));
        //по точкам добавляем сегменты пути
        ps.Add(new PolyLineSegment(points, true));
        //Из сегментов пути строим фигуру с первой точкой вначале.
        var pf = new PathFigure(points.First(), ps, false);
        //Добавляем фигуру в геометрию
        pg.Figures.Add(pf);
        //Возвращаем геометрию.
        return pg;
    }
 
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
 
    #endregion
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/// <summary>
/// Конвертер для деления числа на 2
/// </summary>
public class DivideByTwoConverter
    : IValueConverter
{
    #region Implementation of IValueConverter
 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
        {
            return value;
        }
        return (double)value / 2;
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
 
    #endregion
}
Миниатюры
[WPF] Построить график функции  
Вложения
Тип файла: zip ThirdLab.zip (10.6 Кб, 300 просмотров)
7
16 / 3 / 2
Регистрация: 24.10.2018
Сообщений: 132
17.05.2020, 13:31 7
ViterAlex, Пжалуйста помогите, тут не работает график -x + 4/(3-x) - 2;
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.05.2020, 13:31

Как создать график в wpf?
Необходимо построить график, который будет считывать информацию из файла. Как это реализовать?...

Построить на pictureBox график функции
Построить на pictureBox график функции f(x)=sin(x), x 0 . Построение выполнять попиксельно. За...

Нужно построить график функции y = x2 на интервале [-3,3] и Построить график функции (эллипс) x^2/16 + y^2/9 = 1
Нужно построить график функции y = x2 на интервале и Построить график функции (эллипс) x^2/16 +...

Найти производные функции и на одном графике построить график данной функции, график первой и второй производной.
найти производные первого и второго порядка функции и на одном графике построить график данной...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru