График в c sharp

Создание графиков в WinForms C#

Доброго времени суток! В данной статье мы рассмотрим, как можно создавать графики в WinForms C#. В качестве платформы примера нужно взять .Net Framework 4.8. Далее в ссылки проекта необходимо добавить ссылку на сборку System.Windows.Forms.DataVisualization. Для этого нужно в обозревателе решений нажать правой мыши на элемент меню Ссылки и далее Добавить ссылку. В открывшемся окне необходимо найти сборку и выделить ее галочкой. В панели элементов должен появиться новый элемент — Chart. Обратите внимание, что проект должен быть для версии .Net Framework 4.*. Теперь рассмотрим пример кода:

using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace ChartsWinForms
public partial class MainForm : Form
public MainForm()
InitializeComponent();

// Установим палитру
chart.Palette = ChartColorPalette.SeaGreen;

// Заголовок графика
chart.Titles.Add(«Посетители»);

// Добавляем последовательность
for (int i = 0; i < daysOfWeek.Length; i++)
Series series = chart.Series.Add(daysOfWeek[i]);

// Добавляем точку
series.Points.Add(numberOfVisitors[i]);
>

Таким образом, вот так просто можно создавать графики в WinForms C#.

Создано 16.03.2023 13:36:01

  • Михаил Русаков
  • Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

    Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
    Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

    Если Вы не хотите пропустить новые материалы на сайте,
    то Вы можете подписаться на обновления: Подписаться на обновления

    Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

    Порекомендуйте эту статью друзьям:

    Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

    1. Кнопка:
      Она выглядит вот так:
    2. Текстовая ссылка:
      Она выглядит вот так: Как создать свой сайт
    3. BB-код ссылки для форумов (например, можете поставить её в подписи):

    Комментарии ( 0 ):

    Для добавления комментариев надо войти в систему.
    Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.

    Copyright © 2010-2023 Русаков Михаил Юрьевич. Все права защищены.

    Источник

    Рисование сеточных графиков трехмерных функций и изолиний к ним

    Статья представляет собой нечто вроде “практического руководства” для построения весьма интересных трехмерных графиков функций вида z=f(x,y), с примером реализации на C#.

    Рисовать будем в компоненте Chart, разумеется, можно использовать любой canvas-подобный элемент. При большом количестве точек будут наблюдаться задержки в рисовании, но этот компонент легко использовать и для демонстрации он вполне сгодится.

    Строим график

    image

    Для этого нам понадобится сетка или поле, каждый узел которой будет иметь координаты x, y и содержать значение z. Эту сетку можно заполнять любым способом, раз мы строим график функции, то будем заполнять ее значениями этой функции (z=f(x,y)). Шаг между двумя последовательными значениями x или y выберем равный одному, для более простой и наглядной демонстрации, размерность сетки N x N. Значения в узлах сетки достаточно считать один раз. Для преобразования трехмерных координат в двухмерные и для поворота графика будем использовать матрицу поворота и углы Эйлера.

    Обозначим углы α, β и γ углами a, b и c соответственно и будем использовать их значения в градусах. Запишем матрицу через коэффициенты:

    | l1, l2, l3 | M=| m1, m2, m3 | | n1, n2, n3 | l1 = cos(a) * cos(c) - cos(b) * sin(a) * sin(c) m1 = sin(a) * cos(c) + cos(b) * cos(a) * sin(c) n1 = sin(b) * sin(c) l2 = -cos(a) * sin(c) + cos(b) * sin(a) * cos(c) m2 = -sin(a) * sin(c) + cos(b) * cos(a) * cos(c) n2 = sin(b) * cos(c) l3 = sin(b) * sin(a) m3 = -sin(b) * cos(a) n3 = cos(b)

    Запишем итоговое преобразование из трехмерных координат в двухмерные:
    X=l1x+l2y+l3z
    Y=m1x+m2y+m3z
    x,y,z –это “внутренние” координаты для графика, X,Y – итоговые экранные координаты. Коэффициенты n1,n2 и n3 нам для этой задачи не понадобятся.

    double[,] a; //массив размерностью N x N … double X, Y; //Рисуем вертикальные линии при постоянном значении x for (int x = 0; x < N; x++) < for (int y = 0; y < N; y++) < X = l1() * (x - N / 2.0) + l2() * (y - N / 2.0) + l3() * a[x, y]; Y = m1() * (x - N / 2.0) + m2() * (y - N / 2.0) + m3() * a[x, y]; chart1.Series[n].Points.AddXY(X, Y); >n++; > //Рисуем горизонтальные линии при постоянном значении y for (int y = 0; y < N; y++) < for (int x = 0; x < N; x++) < X = l1() * (x - N / 2.0) + l2() * (y - N / 2.0) + l3() * a[x, y]; Y = m1() * (x - N / 2.0) + m2() * (y - N / 2.0) + m3() * a[x, y]; chart1.Series[n].Points.AddXY(X, Y); >n++; > 

    Добавим события, при которых будут меняться углы и будет происходить вращение графика. Например, это будет движение курсора при зажатой левой кнопке мышки и изменение углов b и с:

     bool onmove = false; Point startpos; … private void chart1_MouseDown(object sender, MouseEventArgs e) < if (e.Button == MouseButtons.Left) < onmove = true; startpos = e.Location; >> private void chart1_MouseMove(object sender, MouseEventArgs e) < if (onmove) < if ((startpos.Y - e.Y) < 0) b--; if ((startpos.Y - e.Y) >0) b++; if ((startpos.X - e.X) < 0) c--; if ((startpos.X - e.X) >0) c++; if (b > 359) b = 0; if (c > 359) c = 0; if (b < 0) b = 359; if (c < 0) c = 359; drawscene(); >> private void chart1_MouseUp(object sender, MouseEventArgs e)

    Проверим на тестовой функции z=x 2 +y 2 :

    Вид сверху на функцию где видно ту самую сетку и показаны значения в узлах.

    Вид на функцию под углом.
    Возможно, стоит по-другому изменять углы, при вращении используя все 3 угла и использовать сетку с шагом меньше 1, но мы упростили ситуацию.

    Строим изолинии

    Воспользуемся алгоритмом Движущихся квадратов (“Marching squares”), в Википедии дано достаточно подробное описание. Гугл также выдает очень хорошую статью, где описывается этот алгоритм и реализовывается на C#.
    Суть кратко:
    1. Требуется найти начальную позицию — откуда пойдет изолиния.
    2. Затем сравнить значения в соседних узлах сетки, которые образуют квадрат с вершинами: (xi,yj), (xi-1,yj), (xi,yj-1), (xi-1,yj-1).

    3. Выбрать дальнейшее направление обхода, в зависимости от полученного значения на шаге 2, и перейти в следующую точку, в которой опять проделать шаг 2.
    4. Выполнять до тех пор, пока не попадем обратно в начальную позицию или не достигнем края сетки.
    Всего может быть 16 вариантов:
    image
    Не будем писать весь код заново, возьмем часть кода из той статьи и изменим под нашу задачу:

     enum dir < None, Up, Left, Down, Right >dir prevStep; dir nextStep; bool border; int startx, starty; void findstartpos() < for (int y = 0; y < N; y++) for (int x = 0; x < N; x++) if (arr[x, y] < Z) < startx = x; starty = y; return; >> bool check(int x, int y) < if (x == N - 1 || y == N - 1 || x == 0 || y == 0) border = true; if (x < 0 || y < 0 || x >= N || y >= N) return false; if (arr[x, y] < Z) return true; return false; >void step(int x, int y) < bool ul = check(x - 1, y - 1); bool ur = check(x, y - 1); bool dl = check(x - 1, y); bool dr = check(x, y); prevStep = nextStep; int state = 0; if (ul) state |= 1; if (ur) state |= 2; if (dl) state |= 4; if (dr) state |= 8; switch (state) < case 1: nextStep = dir.Down; break; case 2: nextStep = dir.Right; break; case 3: nextStep = dir.Right; break; case 4: nextStep = dir.Left; break; case 5: nextStep = dir.Down; break; case 6: if (prevStep == dir.Down) < nextStep = dir.Left; >else < nextStep = dir.Right; >break; case 7: nextStep = dir.Right; break; case 8: nextStep = dir.Up; break; case 9: if (prevStep == dir.Right) < nextStep = dir.Down; >else < nextStep = dir.Up; >break; case 10: nextStep = dir.Up; break; case 11: nextStep = dir.Up; break; case 12: nextStep = dir.Left; break; case 13: nextStep = dir.Down; break; case 14: nextStep = dir.Left; break; default: nextStep = dir.None; break; > > 

    Попробуем опять же на нашей тестовой функции z=x 2 +y 2 :

    Как видно на картинке алгоритм довольно успешно справился и отделил точки где значение функции выше 5, но немного правее и выше. Изолиния получилась угловатой, поэтому проведем интерполяцию. Смысл интерполяции в том, что мы на основании значениях z в соседних узлах сетки вычисляем более близкое значение x, или y, к реальной изолинии, что делает изолинию более правдоподобной.
    Будем использовать формулу линейной интерполяции:
    x=(Z-f(xi-1,yj)/(f(xi,yj)-f(xi-1,yj))+xi-1,
    y=(Z-f(xi,yj-1)/(f(xi,yj)-f(xi,yj-1))+yj-1,
    где Z- значение, на котором нужно провести изолинию.
    Интерполирование по координате x, или по координате y, выбирается в зависимости от направления движения для предыдущего и следующего шагов.
    Напишем для этого такой, не очень хороший код:

     . List res; . //Изменение координаты x или y int dx = 0, dy = 0; switch (prevStep) < case dir.Down: dy = 1; break; case dir.Left: dx = 1;break; case dir.Up: dy = -1; break; case dir.Right: dx = -1; break; default: break; >. double X = x0 + x; double Y = y0 + y; if (ip) //ip - interpolation < //Интерполируем при неизменном направлении if (dx != 0 && prevStep == nextStep) Y = y0 + y + (Z - a[x, y - 1]) / (a[x, y] - a[x, y - 1]) - 1; if (dy != 0 && prevStep == nextStep) X = x0 + x + (Z - a[x - 1, y]) / (a[x, y] - a[x - 1, y]) - 1; //Интерполируем при изменении направления if (nextStep == dir.Down && prevStep == dir.Left) Y = y0 + y + (Z - a[x, y - 1]) / (a[x, y] - a[x, y - 1]) - 1; if (nextStep == dir.Left && prevStep == dir.Down) X = x0 + x + (Z - a[x - 1, y]) / (a[x, y] - a[x - 1, y]) - 1; if (nextStep == dir.Up && prevStep == dir.Right) X = x0 + x + (Z - a[x - 1, y]) / (a[x, y] - a[x - 1, y]) - 1; if (nextStep == dir.Up && prevStep == dir.Left) X = x0 + x + (Z - a[x - 1, y]) / (a[x, y] - a[x - 1, y]) - 1; if (nextStep == dir.Right && prevStep == dir.Up) Y = y0 + y + (Z - a[x, y - 1]) / (a[x, y] - a[x, y - 1]) - 1; if (nextStep == dir.Right && prevStep == dir.Down) X = x0 + x + (Z - a[x - 1, y]) / (a[x, y] - a[x - 1, y]) - 1; //Исключаем "ненужные" точки if (!(nextStep == dir.Down && prevStep == dir.Right) && !(nextStep == dir.Left && prevStep == dir.Up)) res.Add(new PointF((float)X, (float)Y)); >. 

    И получаем результат, который нас уже более устраивает:


    Пример «ненужных точек», которые мы исключили.
    Из возможных улучшений следует отметить, что наша реализация будет строить все изолинии только для монотонно возрастающих (для убывающих следует поменять знак на “>”) функций. Для функций периодически возрастающих и убывающих следует изменить, например функцию поиска начальной позиции и выполнять её несколько раз.

    Пример работы итоговой программы.
    На практике это можно применять для анализа карт, или для поиска контура на изображении.

    Источник

    Графики C#

    Пару примеров работы с графиками C# с использованием компонента Chart. Программа позволяет считать файл с координатами X и Y с помощью openFileDialog и построить по ним график.

    Для работы с файлами необходимо подключить пространство имен System.IO

    Приводится пример кода, который позволяет сохранить некоторый массив чисел в файл с помощью компонента saveFileDialog.

    Демонстрация графиков с помощью компонента chart c#

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; namespace chart < public partial class Form1 : Form < public Form1() < InitializeComponent(); openFileDialog1.Filter = "Text files(*.txt)|*.txt|All files(*.*)|*.*"; saveFileDialog1.Filter = "Text files(*.txt)|*.txt|All files(*.*)|*.*"; >//Массивы для хранения List x; List y; int[] a; private void ОткрытьToolStripMenuItem_Click(object sender, EventArgs e) < if (openFileDialog1.ShowDialog() == DialogResult.OK) < try < //Инициализация массивов x = new List(); y = new List(); //Чтение файла и запись значений в List x и y StreamReader sr = new StreamReader(openFileDialog1.FileName); string line; string[] line2; while ((line = sr.ReadLine()) != null) < line2 = line.Split(','); //разбиваем строку на подстроки x.Add(Convert.ToInt32(line2[0])); y.Add(Convert.ToInt32(line2[1])); >sr.Close(); //Заполняем график считанными значениями chart1.Series["Series1"].LegendText = "График XY"; for (int i = 0; i < x.Count; i++) < chart1.Series["Series1"].Points.AddXY(x[i], y[i]); >> catch (Exception ex) < MessageBox.Show($"Error.\n\nError message: \n\n" + $"Details:\n\n"); > > > private void СохранитьToolStripMenuItem_Click(object sender, EventArgs e) < if (saveFileDialog1.ShowDialog() == DialogResult.Cancel) return; // получаем выбранный файл string filename = saveFileDialog1.FileName; //Начинаем запись в файл StreamWriter sw = new StreamWriter(filename); foreach (int val in a) sw.WriteLine(val); sw.Close(); MessageBox.Show("Файл сохранен"); >private void ЗаполнитьГистограммуToolStripMenuItem_Click(object sender, EventArgs e) < try < //Инициализация массивов a = new int[100]; //Заполняем массив а случайными числами Random rnd = new Random(); for (int i = 0; i < a.Length; i++) a[i] = rnd.Next(1, 20); //Добавляем точки на график foreach (int val in a) chart2.Series["Series1"].Points.Add(val); >catch (Exception ex) < MessageBox.Show($"Error.\n\nError message: \n\n" + $"Details:\n\n"); > > > >

    Источник

    LiveCharts. Строим графики в WinForms

    Вот готовый проект AnalitikProg, если лень читать.

    Итак, поехали.
    1) Создаем проект WinForm называем его AnalitikProg, платформа .Net Framework 4.7.2
    2) Св-ву Name формы присваиваем значение «AnalitikProg».
    3) Добавляем на форму элемент ToolStrip, делаем кнопке Display равным «Text».

    4) Выделяем кнопку и меняем св-во name на «toolStripButtonGenerate», а св-ву Text значение «Сформировать график».

    5) Теперь необходимо добавить nuget-пакет, который называется LiveChart.

    6) Обратим внимание, что в панели элементов появились новые элементы:

    7) Перетаскиваем на форму элемент CartesianChart и его св-ву Dock выставим Fill.
    8) Теперь дважды нажимаем кнопку «Сформировать график», переходим в код и за пределами метода обработчика нажатия по кнопке создаем класс Data, так сказать «заготовочка» для будущей коллекции со значения для графика.

    9) Перед методом Form1 создаем переменную типа List , а в методе Form1 после компонента initializeComponent() инициализируем обобщенную коллекцию в которой будут содержаться элементы типа Data и заполним ее данными.
    Значит легенда такая, программа нужна трейдеру, чтобы просматривать динамику изменения его заработка.

    datas = new List() < new Data()< values=35000,date=new DateTime(2020,01,01) >, new Data()< values=30000,date=new DateTime(2020,01,02) >, new Data()< values=40000,date=new DateTime(2020,01,03) >, new Data()< values=55000,date=new DateTime(2020,01,04) >, new Data()< values=55000,date=new DateTime(2020,01,05) >, new Data()< values=30000,date=new DateTime(2020,01,06) >, new Data()< values=35000,date=new DateTime(2020,01,07) >, new Data()< values=42000,date=new DateTime(2020,01,08) >, new Data()< values=57000,date=new DateTime(2020,01,09) >, new Data()< values=88000,date=new DateTime(2020,01,10) >, new Data()< values=51000,date=new DateTime(2020,01,11) >, new Data()< values=65000,date=new DateTime(2020,01,12) >, new Data()< values=100000,date=new DateTime(2020,01,13) >, new Data()< values=75000,date=new DateTime(2020,01,14) >, new Data()< values=88000,date=new DateTime(2020,01,15) >, new Data()< values=92000,date=new DateTime(2020,01,16) >, new Data()< values=99000,date=new DateTime(2020,01,17) >, new Data()< values=87000,date=new DateTime(2020,01,18) >, new Data() < values=110000,date=new DateTime(2020,01,19) >>;

    10) Теперь переходим к кнопке, кликаем по ней 2 раза и забиваем в нее следующий код.

    SeriesCollection series = new SeriesCollection(); //отображение данных на график. Линии и т.д. ChartValues zp = new ChartValues(); //Значения которые будут на линии, будет создания чуть позже. List date = new List(); //здесь будут храниться значения для оси X foreach (var item in datas) //Заполняем коллекции < zp.Add(item.values); date.Add(item.date.ToShortDateString()); >cartesianChart1.AxisX.Clear(); //Очищаем ось X от значений по умолчанию cartesianChart1.AxisX.Add(new Axis //Добавляем на ось X значения, через блок инициализатора. < Title = "Дата", Labels = date >); LineSeries line = new LineSeries(); //Создаем линию, задаем ей значения из коллекции line.Title = ""; line.Values = zp; series.Add(line); //Добавляем линию на график cartesianChart1.Series = series; //Отрисовываем график в интерфейсе

    12) В общем то все, осталось запустить и проверить

    Могу порекомендовать сходить на сайт поддержки библиотеки https://lvcharts.net там есть много интересной информации и раскрыты все возможности библиотеки.

    Если понравилось — ставь лайк!

    Один комментарий к “LiveCharts. Строим графики в WinForms”

    а если надо динамически данные добавлять на график, а не в коде? ну например по нажатию кнопки добавить новые значения? 🙂 м?

    Добавить комментарий Отменить ответ

    Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

    Источник

    Читайте также:  Вывод глобальной переменной php
    Оцените статью