Метеостанция + построение графика + c#

Визуализация данных в виде графика — SFMonitor

С помощью Ардуино можно легко собирать данные с самых разных датчиков. Можно, к примеру, измерить температуру, скорость ветра и влажность воздуха на улице. А если добавим к этому списку МЭМС барометр и датчик освещенности, получим настоящую погодную станцию у себя во дворе. Но что делать с огромной массой полученных данных? Как проанализировать накопленные массивы чисел?

Самое простое, что мы можем сделать — это вывести показания датчиков в монитор COM-порта в виде таблицы, а затем построить с помощью них график в одном из редакторов таблиц. Например, показания барометра, полученные с помощью трех разных датчиков в одном из моих экспериментов, выглядели так:

Такой подход хорош, когда нам достаточно оценить показания датчиков уже после проведения эксперимента. Если же график нужно строить в режиме реального времени потребуется специальное приложение для визуализации потоков данных. Например, это можно сделать с помощью известного пакета MatLab. В одной из послежний версий Arduino IDE также появилась возможность строить простые графики.

На этом уроке мы поговорим еще про один инструмент для визуализации — приложение SFMonitor.

Это монитор последовательного порта с открытыми исходными кодами, который я разработал пару лет назад для работы над системой стабилизации беспилотников.

В основе SFMonitor лежит проект Eli Bendersky написанный на языке python и библиотеки PyQt. Монитор позволяет строить сразу несколько графиков, используя для передачи данных библиотеку SerialFlow. Обо всем этом я расскажу далее.

1. Строим простой график в SFMonitor

Для того, чтобы построить в SFMonitor самый простой тип графика, потребуется несложная программа, которая будет отправлять в COM-порт показания какого-нибудь датчика. Для примера используем фоторезистор, подключенный к аналоговому порту Ардуино.

const int adc1Pin = A0; int val = 0; void setup(){ Serial.begin(115200); pinMode(adc1Pin, INPUT); } void loop(){ val = analogRead(adc1Pin); val = map(val, 0, 1023, 0, 255); Serial.write(val); delay(20); }

Важно отметить, что мы будем передавать всего один байт за раз, а это число от 0 до 255. АЦП же нам дает число от 0 до 1023. Мы используем функцию map, чтобы нормировать результат АЦП в 1 байт.

Также следует после каждой отправки данных в порт делать небольшую паузу, не менее 10мс.  В противном случае COM-порт персонального компьютера начнет тормозить.

Теперь включим монитор и настроим параметры. Первое, что нужно будет выбрать — это тип графика. В выпадающем меню выбираем «Простой».

Затем настраиваем формат данных в пакете. Для этого зайдем в пункт меню «Данные/Настройка потоков».

На вкладке «Общие» выбираем размер чисел в пакете — 1 байт.

Переходим на вкладку «Поток №1» и ставим галку «Беззнаковые значения». Это означает, что мы будем принимать строго положительные числа от 0 до 255.

Теперь выбираем COM-порт Ардуино и скорость передачи данных.

Наконец, запускаем монитор и наблюдаем график.

2. Пакетная передача данных

Что делать, если нам нужно строить график по шкале от 0 до 1024? или еще больше, от -1 000 000 до 1 000 000. А еще интересно, как сразу передавать данные с двух, или с трех датчиков? Нужен другой способ передачи данных.

Способ, при котором данные складываются в некий виртуальный пакет в заданном порядке, затем отправляются адресату, который разворачивает пакет. Собственно, такой метод передачи данных и называют пакетным.

 На основе пакетов работает весь интернет и большинство промышленных линий связи.

В SFMonitor для пакетной передачи используется библиотека SerialFlow. Эта библиотека позволяет задать формат пакета и предоставляет функции для упаковки данных в пакет и для их распаковки обратно.

Напишем программу для Ардуино, которая будет передавать показания акселерометра ADXL345 для всех трех осей в диапазоне от -32768 до 32767.

#include #include ADXL345 accelerometer; SerialFlow rd(&Serial); // RX, TX Vector araw; void setup() { rd.setPacketFormat(2, 3, 0); rd.begin(115200); accelerometer.begin(); accelerometer.setRange(ADXL345_RANGE_2G); } void loop() { araw = accelerometer.readRaw(); rd.setPacketValue( araw.XAxis ); rd.setPacketValue( araw.YAxis ); rd.setPacketValue( araw.ZAxis ); rd.sendPacket(); }

Чтобы SFMonitor смог отобразить три графика настроим следующие параметры:

  • Формат данных — выбираем v(t);
  • Потоки — ставим галку для всех трех;
  • Размер значения в пакете — 2 байта;
  • Беззнаковые значения — ставим для всех трех потоков.

После запуска монитора получим такие вот три графика:

3. Построение графиков в Arduino IDE

Начиная с версии 1.6.6 в среде Arduino IDE появилось штатное средство для построения графиков. Немного изменим программу, чтобы Ардуино смогла корректно передавать данные с акселерометра для встроенного монитора.

#include ADXL345 accelerometer; Vector araw; void setup() { Serial.begin(115200); accelerometer.begin(); accelerometer.setRange(ADXL345_RANGE_16G); } void loop() { araw = accelerometer.readRaw(); Serial.println( araw.XAxis ); delay(20); }

Используем обычный println. Загружаем программу на Ардуино и запускаем встроенный монитор через меню «Инструменты/ Плоттер по последовательному соединению». Результат ниже.

К сожалению, встроенный инструмент Arduino IDE пока позволяет строить только один график, и не имеет вообще никаких настроек.

Заключение

SFMonitor постоянно дорабатывается и прирастает новыми возможностями. Например, в последней версии появился режим векторного отображения, который использовался для визуализации данных датчика TSL1401.

В будущих версиях планируется режим отображения трехмерных данных, который удобно использовать для визуализации данных инклинометра. И напоминаю, приложение SFMonitor полностью открытое, и мы приветствуем любую помощь по доработке!

Ресурсы

Источник: http://robotclass.ru/articles/sfmonitor-plot-serial-data/

Создание диаграмм

128

ASP.NET — Веб-сайты ASP.NET — Создание диаграмм

Одной из наиболее распространенных графических задач является построение диаграммы. Элемент управления Chart в ASP.NET предлагает широкий набор типов диаграмм и параметров конфигурации. Элемент управления Chart был доступен как загружаемый дополнительно в .NET версии 3.5 SP1, но теперь входит в состав .NET 4.0.

Многообразие функциональных средств и параметров этого элемента управления столь велико, что их просто невозможно осветить в одной статье.

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

С более полным набором примеров можно ознакомиться в библиотеке образцов, которая содержит свыше 200 примеров различных элементов управления Chart.

Создание базовой диаграммы

Как и при изучении многих аспектов ASP.NET, ознакомление с элементом управления Chart лучше всего начать с примера. На рисунке ниже показана простая диаграмма.

Мы рассмотрим последовательность действий для создания этой диаграммы, а затем ряд различных способов ее индивидуальной настройки и адаптации.

Чтобы было легче понять работу элемента управления Chart, рисунок снабжен надписями, указывающими основные элементы.

Диаграмму можно добавить, перетаскивая элемент управления Chart из панели инструментов (он находится в группе Data (Данные)) на поверхность визуального конструктора или помещая дескриптор в код разметки. Объявление для этого примера диаграммы выглядит так:

Каждая диаграмма имеет одну или более областей, в которых можно отображать данные. В приведенном выше базовом объявлении определена одна диаграмма, которая будет использоваться для графического отображения двух наборов данных. Как и в случае большинства элементов управления ASP.

NET, для работы с диаграммой можно применять файл отделенного кода или продолжать пользоваться кодом разметки. Вначале рассмотрим подход с отделенным кодом.

Все начинается с настройки внешнего вида диаграммы (чтобы файл кода можно было использовать с элементом управления Chart, должно быть импортировано пространство имен System.Web.UI.DataVisualization.Charting):

protected void Page_Load(object sender, EventArgs e) { // Форматировать диаграмму Chart1.BackColor = Color.Gray; Chart1.BackSecondaryColor = Color.WhiteSmoke; Chart1.BackGradientStyle = GradientStyle.DiagonalRight; Chart1.BorderlineDashStyle = ChartDashStyle.Solid; Chart1.BorderlineColor = Color.Gray; Chart1.BorderSkin.SkinStyle = BorderSkinStyle.Emboss; // Форматировать область диаграммы Chart1.ChartAreas[0].BackColor = Color.Wheat; // Добавить и форматировать заголовок Chart1.Titles.Add(“ASP.NET Chart”); Chart1.Titles[0].Font = new Font(“Utopia”, 16); }

Фон диаграммы – это пространство, которое окружает область диаграммы. В качестве фона диаграммы была выбрана градиентная заливка с диагональным переходом от серого цвета (Gray) до белого дыма (WhiteSmoke), что было указано с помощью свойств BackColor, BackSecondaryColor и BackGradientStyle. При визуализации диаграммы фон создается с применением выбранной цветовой схемы.

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

Значение Solid из перечисления ChartDashStyle обеспечивает рисование вокруг края диаграммы линии толщиной в один пиксель цветом, заданным в свойстве BorderlineColor. в качестве которого был установлен цвет Gray.

Свойство BorderSkin поддерживает множество опций, но в примере была установлена только опция SkinStyle в Emboss, что создает трехмерный эффект приподнятой рамки с тенью.

Следующий шаг – выбор цвета фона для области диаграммы и определение заголовка. Обратите внимание, что ссылка на область диаграммы выполняется по индексному значению.

Это связано с тем, что диаграмма может иметь более одной области, в которой могут графически представляться данные. Решение этой задачи рассматривается далее в статье.

Диаграмма имеет только одну область, и для нее выбран цвет Wheat (пшеничный).

Диаграмма может иметь более одного заголовка, поэтому новый заголовок понадобится добавить в коллекцию Titles с помощью метода Add(), а затем сослаться на нужный заголовок по индексу для его форматирования. Форматирование сводится к установке шрифта и размера. Диаграмма с выполненными на данный момент настройками показана на рисунке ниже:

Если для тестирования сайтов ASP.NET вы используете IIS, а не встроенный в Visual Studio сервер разработки IIS Express, то в файле web.config придется добавить следующие настройки HTTP-обработчика для диаграмм:

Существует множество различных способов форматирования диаграммы, и выбор подходящего набора опций может требовать некоторого времени.

Мы начали с задания внешнего вида диаграммы, поскольку по странной иронии процесс добавления данных проще подбора подходящей цветовой схемы.

Элемент управления Chart настолько гибкий и обладает таким многообразием опций, что бремя выбора само по себе становится достаточно серьезным препятствием.

Как только основные настройки представления данных определены, можно заняться самими данными. Наборы данных представлены с использованием класса Series, и каждый создаваемый класс Series должен быть добавлен в коллекцию Chart.Series с помощью метода Add(). Обычно создание и добавление класса Series осуществляется в одном шаге, как показано в следующем фрагменте кода:

protected void Page_Load(object sender, EventArgs e) { // … Chart1.Series.Add(new Series(“ColumnSeries”) { ChartType = SeriesChartType.Column }); }

В этом коде создается новая серия ColumnSeries и за счет установки свойства ChartType в SeriesChartType.Column указывается, что данные этой последовательности должны быть представлены в виде столбчатой диаграммы.

Свойство SeriesChartType принимает 35 различных значений, каждое из которых соответствует отдельной разновидности диаграммы.

Если значение свойства ChartType не указано, по умолчанию для него выбирается Column (столбчатая диаграмма).

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

Chart1.Series.Add(new Series(“SplineSeries”) { ChartType = SeriesChartType.Spline, BorderWidth = 3, ShadowOffset = 2, Color = Color.PaleVioletRed });

Для этой диаграммы в качестве типа был выбран Spline (график в виде плавной линии).

Значение BorderWidth управляет толщиной линейного графика, а установка значения для свойства ShadowOffset создает эффект наличия трехмерной тени под вычерчиваемой линией.

Свойство Color определяет цвет, используемый для рисования графика. Для этого примера был выбран бросающийся в глаза оттенок PaleVioletRed.

Последний шаг состоит в добавлении данных в набор. Существует множество различных способов связывания данных с диаграммой. В этом примере применяется простейший из них – перечисление статических значений:

Chart1.Series[0].Points.DataBindY( new int [] { 5, 3, 12, 14, 11, 7, 3, 5, 9, 12, 11, 10 }); Chart1.Series[1].Points.DataBindY( new int [] { 3, 7, 13, 2, 7, 15, 23, 20, 1, 5, 7, 6 });

Каждая коллекция Series содержит коллекцию Points.

Мы использовали метод DataBindY(), реализующий интерфейс IEnumerable, который позволяет для указания данных применять массив целочисленных значений.

Индекс данных используется в качестве X-координаты для каждого значения Y в массиве. При загрузке страницы, содержащей элемент управления Chart, результат выглядит, как показано на первом рисунке в статье.

Конфигурирование элемента управления Chart можно полностью выполнить также с помощью разметки. Определение рассмотренной диаграммы в этой форме имеет следующий вид:

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

Мы не станем подробно останавливаться на всех доступных опциях представления диаграмм, но одна из обычно встречающихся задач – генерация трехмерных диаграмм. Чтобы преобразовать нашу простую диаграмму в трехмерную, добавим следующую строку кода в метод Page_Load:

Chart1.ChartAreas[0].Area3DStyle.Enable3D = true;

Активизация трехмерного представления производится на уровне области диаграммы (ChartArea). Если диаграмма содержит несколько областей, двухмерные и трехмерные графики можно сочетать. Элементарная диаграмма в трехмерном представлении показана на рисунке ниже. А вот изменение, которое должно быть внесено в код разметки:

Кроме статических данных, которые использовались в предыдущем примере, элемент управления Chart может быть заполнен данными из множества различных источников. В настоящем разделе мы рассмотрим наиболее часто используемые источники данных.

Привязка к таблице базы данных

В этом примере для демонстрации привязки диаграммы к таблице базы данных используется таблица Products тестовой базы данных Northwind. Процесс начинается с форматирования элемента управления Chart, во многом подобно тому, как это делалось в предыдущем примере.

Для определения соединения с базой данных Northwind с использованием свойства ConnectionString применяются стандартные классы ADO.NET из пространства имен System.Data.SqlClient. После этого определяется запрос, который будет использоваться для генерации данных в диаграмме.

Дня этого примера был выбран запрос столбцов ProductName и UnitsInStock таблицы Products с выбором товаров, которые не были сняты с производства, при этом результаты ограничиваются пятью строками.

Затем открывается соединение и создается объект SqlDataReader – все это стандартный код ADO.NET:

protected void Page_Load(object sender, EventArgs e) { // Форматировать диаграмму Chart1.BackColor = Color.Gray; Chart1.BackSecondaryColor = Color.WhiteSmoke; Chart1.BackGradientStyle = GradientStyle.DiagonalRight; Chart1.BorderlineDashStyle = ChartDashStyle.Solid; Chart1.BorderlineColor = Color.Gray; Chart1.BorderSkin.SkinStyle = BorderSkinStyle.Emboss; // Форматировать область диаграммы Chart1.ChartAreas[0].BackColor = Color.Wheat; // Добавить и форматировать заголовок Chart1.Titles.Add(“ASP.NET Chart”); Chart1.Titles[0].Font = new Font(“Utopia”, 16); // Создать соединение с базой данных SqlConnection conn = new SqlConnection( ConfigurationManager.ConnectionStrings[“Northwind”].ConnectionString) ; // Определить команду SqlCommand command = new SqlCommand(“SELECT TOP (5) ProductName, UnitsInStock ” + “FROM Products WHERE (Discontinued = 'FALSE')”, conn); // Открыть команду и создать объект чтения command.Connection.Open(); SqlDataReader reader = command.ExecuteReader(); // Очистить серии диаграммы и привязаться к таблице Chart1.Series.Clear(); Chart1.DataBindTable(reader); Chart1.Series[“UnitsInStock”].ChartType = SeriesChartType.StackedBar; // Закрыть объект чтения и соединение reader.Close(); conn.Close(); }

В этом коде, после того как диаграмма сформатирована, а соединение с данными создано, данные привязываются к диаграмме. Процесс начинается с очистки коллекции Chart.Series.

Это необходимо потому, что при привязке таблицы элемент управления Chart автоматически создает новый экземпляр Series для каждого числового столбца, найденного в данных. В результате будет создан экземпляр Series по имени UnitsInStock.

Однако созданный по умолчанию экземпляр Series (получивший имя Series1) не удаляется, а это может привести к проблемам при изменении значения свойства Series.

ChartType на такое, которое не сможет быть графически представлено в той же области ChartArea, что и столбчатая диаграмма (Column), являющаяся стандартным типом для серий по умолчанию. Рекомендуется перед привязкой к данным созданный по умолчанию класс Series удалить, чтобы в конечном итоге остался только экземпляр Series, ассоциированный с данными.

Затем нужно выполнить привязку с использованием метода DataBindTable(), который принимает ранее созданный SqlDataReader в качестве аргумента. Как уже упоминалось ранее, привязка к таблице автоматически создает по одной серии данных для каждого числового столбца данных. В данном случае запрашиваются столбцы ProductName и UnitsInStock.

Элемент управления Chart проигнорирует текстовый столбец ProductName и создаст новый экземпляр Series для столбца UnitsInStock. Форматирование объекта Series невозможно до тех пор, пока он не будет создан, поэтому свойство ChartType устанавливается после того, как таблица привязана к элементу управления.

И, наконец, объекты SqlDataReader и SqlCommand закрываются.

Диаграмма, созданная этим кодом, показана на рисунке ниже:

Проблема с этой диаграммой состоит в том, что столбец ProductName был проигнорирован. Во время процесса привязки элемент управления Chart работал исходя из того, что все SQL-данные должны были интерпретироваться как значения по оси Y, и отбрасывал все, что не могло использоваться подобным образом.

Если один из столбцов должен служить в качестве значений по оси X, об этом нужно явно сообщить элементу управления Chart, выполняя привязку данных с помощью метода Points.DataBindXY() класса Series. Чтобы адаптировать предыдущий пример, закомментируйте три строки начиная с Chart1.Series.Clear() и добавьте две новых строки в файл отделенного кода:

// Очистить серии диаграммы и привязаться к таблице /* Chart1.Series.Clear(); Chart1.DataBindTable(reader); Chart1.Series[“UnitsInStock”].ChartType = SeriesChartType.StackedBar; */ // Привязать значения X и Y к созданным по умолчанию сериям и форматировать диаграмму Chart1.Series.Add(new Series(“Default”) { ChartType = SeriesChartType.StackedBar }); Chart1.Series[0].Points.DataBindXY(reader, “ProductName”, reader, “UnitsInStock”);

Метод DataBindXY() позволяет предоставлять источник данных и имена столбцов, которые должны применяться для осей X и Y. В рассматриваемом примере источником данных для обеих осей является SqlDataReader, а именами столбцов – ProductName и UnitsInStock.

Обратите внимание, что в этот раз коллекция Series не очищается. Метод DataBindXY() применяется к уже существующей коллекции Series (а не создает новую), и в примере была использована та, которая создается по умолчанию.

Открыв измененную страницу, можно увидеть результат, показанный на рисунке ниже:

Привязка к объектному источнику данных

Один из наиболее гибких механизмов заполнения диаграммы предусматривает использование ObjectDataSource, когда определяется объект, который может получать данные, а в качестве моста между логикой извлечения данных в коде и элементом управления Chart служит ObjectDataSource. Класс извлечения должен быть создан в папке App_Code. В следующем примере возвращаются простые статические данные:

public class MyObjectDataSource { public class DataItem { public string Name { get; set; } public double Popularity { get; set; } } public DataItem[] GetData() { return new DataItem[] { new DataItem() {Name = “Ватрушка”, Popularity = 30}, new DataItem() {Name = “Мороженное”, Popularity = 30}, new DataItem() {Name = “Орешки”, Popularity = 20}, new DataItem() {Name = “Шоколадка”, Popularity = 20} }; } }

В этом примере определен класс DataItem, имеющий свойства Name и Popularity. Метод GetData() генерирует и возвращает массив элементов DataItem. Эта методика привязки будет также работать с методами, которые возвращают объекты DataSet и DataTable.

Гибкость использования ObjectDataSource обусловлена тем, что средства, определяющие источник данных, абстрагируются от диаграммы, что позволяет свободно изменять бизнес-логику.

Для работы с данными создается новый экземпляр ObjectDataSource с передачей конструктору имени созданного класса извлечения и имени метода, который должен быть вызван для получения данных. В рассматриваемом примере ими соответственно являются MyObjectDataSource и GetData():

protected void Page_Load(object sender, EventArgs e) { // Форматировать диаграмму Chart1.BackColor = Color.Gray; Chart1.BackSecondaryColor = Color.WhiteSmoke; Chart1.BackGradientStyle = GradientStyle.DiagonalRight; Chart1.BorderlineDashStyle = ChartDashStyle.Solid; Chart1.BorderlineColor = Color.Gray; Chart1.BorderSkin.SkinStyle = BorderSkinStyle.Emboss; // Форматировать область диаграммы Chart1.ChartAreas[0].BackColor = Color.Wheat; // Добавить и форматировать заголовок Chart1.Titles.Add(“ASP.NET Chart”); Chart1.Titles[0].Font = new Font(“Utopia”, 16); Chart1.Series.Add(new Series(“Default”) { ChartType = SeriesChartType.Pie }); // Создать объектный источник данных ObjectDataSource ds = new ObjectDataSource(“MyObjectDataSource”, “GetData”) ; // Привязать источник к диаграмме Chart1.DataSource = ds; Chart1.Series[0].XValueMember = “Name”; Chart1.Series[0].YValueMembers = “Popularity”; }

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

Эта информация предоставляется с использованием свойств Series.XValueMember и Series.YValueMember, которые позволяют определять, какие члены объекта ObjectDataSource должны применяться для осей X и Y.

Диаграмма, созданная этим методом, показана на рисунке ниже:

Источник: https://professorweb.ru/my/ASP_NET/sites/level4/4_9.php

Свечной график

Chart – графический компонет, который позволяет строить биржевые графики: свечи, индикаторы, и отображать на графиках маркеры заявок и сделок.

Ниже приведен пример построения графика при помощи компонета Chart. За основу взят пример из Samples/Quik/SampleCandles, в который внесены некоторые изменения.

  1. В XAML создаем окно и добавляем в него графический компонент StockSharp.Xaml.ChartingChart. Присваиваем компоненту имя Chart. Обратите внимание, что при создании окна нужно добавить пространство имен http://schemas.stocksharp.com/xaml.

  2. В коде главного окна декларируем переменные для областей графика, элементов графика и индикаторов.

    private readonly Dictionary _chartWindows = new Dictionary(); private QuikTrader _trader; private readonly LogManager _logManager; private ChartArea _candlesArea; private ChartArea _indicatorsArea; private ChartIndicatorElement _smaChartElement; private ChartIndicatorElement _macdChartElement; private ChartCandleElement _candlesElem; private SimpleMovingAverage _sma; private MovingAverageConvergenceDivergence _macd;

  3. В обработчике события Click кнопки Connect, наряду с подпиской на события коннектора и вызовом метода Connect, подписываемся на событие ConnectorCandleSeriesProcessing. В обработчике этого события при получении новой свечи будет выполнятся отрисовка графика.

    private void ConnectClick(object sender, RoutedEventArgs e) { …………………………………… if (_trader == null) { _trader = isLua ? new QuikTrader { LuaFixServerAddress = Address.Text.To(), LuaLogin = Login.Text, LuaPassword = Password.Password.To() } : new QuikTrader(Path.Text) { IsDde = true }; …………………………………… _logManager.Sources.Add(_trader); _trader.Restored += () => this.GuiAsync(() => MessageBox.Show(this, LocalizedStrings.Str2958)); _trader.ConnectionError += error => this.GuiAsync(() => MessageBox.Show(this, error.ToString())); _trader.Error += error => this.GuiAsync(() => MessageBox.Show(this, error.ToString(), “Ошибка обработки данных”)); _trader.MarketDataSubscriptionFailed += (security, type, error) => this.GuiAsync(() => MessageBox.Show(this, error.ToString(), LocalizedStrings.Str2956Params.Put(type, security))); Security.SecurityProvider = new FilterableSecurityProvider(_trader); _trader.CandleSeriesProcessing += DrawCandle; _trader.Connect(); ConnectBtn.IsEnabled = false; } }

  4. В обработчике кнопки ShowChart создаем объекты индикаторов, областей и элементов графика. Добавляем элементы к областям, а области к чарту. Открываем окно графика и запускаем работу кандлменеджера.

    private void ShowChartClick(object sender, RoutedEventArgs e) { var security = SelectedSecurity; var series = new CandleSeries(CandlesSettings.Settings.CandleType, security, CandlesSettings.Settings.Arg); _chartWindows.SafeAdd(series, key => { var wnd = new ChartWindow { Title = “{0} {1} {2}”.Put(security.Code, series.CandleType.Name, series.Arg) }; wnd.MakeHideable(); _sma = new SimpleMovingAverage() { Length = 11 }; _macd = new MovingAverageConvergenceDivergence(); _smaChartElement = new ChartIndicatorElement(); _macdChartElement = new ChartIndicatorElement(); _candlesElem = new ChartCandleElement(); _macdChartElement.DrawStyle = ChartIndicatorDrawStyles.Histogram; _candlesArea = new ChartArea(); _indicatorsArea = new ChartArea(); wnd.Chart.Areas.Add(_candlesArea); wnd.Chart.Areas.Add(_indicatorsArea); _candlesArea.Elements.Add(_candlesElem); _candlesArea.Elements.Add(_smaChartElement); _indicatorsArea.Elements.Add(_macdChartElement); return wnd; }).Show(); _trader.SubscribeCandles(series, DateTime.Today.Subtract(TimeSpan.FromDays(30)), DateTime.Now); }

  5. В обработчике события ConnectorCandleSeriesProcessing производим отрисовку свечи и значений индикаторов для каждой завершенной свечи. Для этого:

    1. Вычисляем значения индикаторов.

    2. Заполняем словарь elements парами “объект элемента – значение элемента”

    3. Для отрисовки графика вызываем метод ChartDraw(ChartDrawData), в который передаем время и словарь элементов.

    Результат работы программы представлен на рисунке выше.

    private void DrawCandle(CandleSeries series, Candle candle) { var wnd = _chartWindows.TryGetValue(series); if (wnd != null) { if (candle.State != CandleStates.Finished) return; var smaValue = _sma.Process(candle); var macdValue = _macd.Process(candle); var data = new ChartDrawData(); data .Group(candle.OpenTime) .Add(_candlesElem, candle) .Add(_smaChartElement, smaValue) .Add(_macdChartElement, macdValue); wnd.Chart.Draw(data); } }

Источник: http://doc.stocksharp.ru/html/a76a0a9c-bb95-4596-9464-9903379b3096.htm

Построение графиков на основе данных из таблицы базы данных с помощью элемента управления Chart

С помощью элемента управления Chart можно легко визуализировать информацию из баз данных. Существуют два основных способа это сделать: использовать обычный ADO.NET или использовать LINQ.

В качестве примера, рассмотрим построение графика по данным из простейшей Базы данных (БД). Эта БД содержит всего одну таблицу MyTable. Её содержимое показано на рисунке ниже.

Данная БД и таблица были созданы специально для этой статьи. Поэтому, не стоит искать в них какой-либо смысл, кроме демонстрации работы с Chart. Как говорится, все совпадения случайны.

Способ с использованием ADO.NET

Для реализации подключения к БД необходимо использовать не визуальный элемент управления DataSet. После создания подключения к БД (создаётся в режиме мастера) поместим на форму не визуальный элемент управления BindingSource. Укажем в его свойстве DataSource DataSet с созданным подключением к БД, а в свойстве DataMembers таблицу с данными (MyTable).

После этого Visual Studio автоматически создаст компонент TableAdapter для получения данных из таблицы.

Теперь, когда всё подготовлено, приступим непосредственно к построению графика. Для этого сперва получим необходимые данные, затем зададим какой столбец будет осью абсцисс и ординат.

Необходимо отметить, что по умолчанию Chart уже содержит один ряд данных (имя по умолчанию Series1).

myTableTableAdapter.Fill(dbDataSet1.MyTable);chart1.Series[“Series1”].XValueMember = (dbDataSet1.Tables[0].Columns[0]).ToString();chart1.Series[“Series1”].YValueMembers = (dbDataSet1.Tables[0].Columns[1]).ToString();

После этого, собственно, строим график.

Способ с использованием LINQ

То же самое можно сделать и с применением LINQ. В качестве примера используем туже БД, но экспортированную в MS SQL Server.

После создания классов LINQ to SQL для этой БД выполним инициализацию и напишем запрос для получения данных.

DataClasses1DataContext dcc = new DataClasses1DataContext();var res = from tbl in dcc.MyTable select new { tbl.CurrentDate, tbl.Value };

После этого в цикле foreach заполняем ряд данных.

    chart1.Series[“Series1”].Points.AddXY(r.CurrentDate, r.Value);

Далее строим график.

Результат построения графиков первым и вторым способом одинаковый.

С помощью описанных способов можно визуализировать практически любые данные.

Источник: http://streletzcoder.ru/postroenie-grafikov-na-osnove-dannyih-iz-tablitsyi-bazyi-dannyih-s-pomoshhyu-elementa-upravleniya-chart/

Элемент Chart – настройка графика

Вопрос: Элемент Chart – настройка графика

Здравствуйте, столкнулся с проблемой, визуального оформления графика, имеется два масива: В первом – 100-300 – целых чисел Во втором – 100-300 – дат, формата дд.мм.гг. чч.мм Нужно отобразить график где Y первый массив, и для каждого значения своя дата.

Пытался сделать через Column – гистограмма, выглядит, не так, как хотелось бы Хочется видеть что-то вроде этого Где при наведение на точку, показывало бы соответствующее значение и дату.

Может быть посоветуете другие способы это сделать, либо подскажите как настроить Chart

Ответ:Понял, что то, что мне нужно, это Chart Areas, как сделать, что бы для каждого значения, он на диаграмме делал точку(метку) на которую уже можно было бы наводить мышкой?

Вопрос: Рисование графиков элемент chart

Помогите доработать код под свои потребности

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
List x1 = new List();
                List y1 = new List();
                List y2 = new List();
 
                Series s1 = new Series(“Подача”);
                Series s2 = new Series(“Обратка”);
                s1.ChartType = SeriesChartType.Spline;
                s2.ChartType = SeriesChartType.Spline;
                s2.Color = Color.Blue;
                s1.Color = Color.Red;
                s1.Points.DataBindXY(x1, y1);
                s2.Points.DataBindXY(x1, y2);
                chart1.Series.Clear();
                chart1.Series.Add(s1);
                chart1.Series.Add(s2);

На форме расположены 3 элемента: char1, char2,char3. На каждом char надо построить 2 графика. По оси X градуировка 1,2,3,4,5. По оси Y данные берутся их пяти text.Box для одного графика и из 5-ти textBox для другого графика. Надо построить по 2 графика на char1, char2,char3.

Еще вопрос можно ли название serios, которое находится справа от графика поместить вверху, а то эта надпись отбирает лишнее место у элемента char.Разобрался может кому пригодится. Все делается через свойства компонента chart.

Для одного компонента chart1 будет выглядеть так

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
 // Настройки графиков
                chart1.Series[0].Name = “Подача”;    // Задает имя 1-го графика
                chart1.Series[1].Name = “Обратка”;   // Задает имя 2-го графика
 
                chart1.Series[0].ChartType = SeriesChartType.Line; // Тип графика – линия
                chart1.Series[1].ChartType = SeriesChartType.Line; //
 
                chart1.Series[0].BorderWidth = 5;    // устанавливаем толщину линии
                chart1.Series[1].BorderWidth = 5;    //      
 
 
                chart1.ChartAreas[0].AxisX.Minimum = 1; // настройка минимума и максимума оси X
                chart1.ChartAreas[0].AxisX.Maximum = 5;
                chart1.ChartAreas[1].AxisX.Minimum = 1; //
                chart1.ChartAreas[1].AxisX.Maximum = 5;
 
                // Для увеличения масштабирования по оси Y
                // массив по которому будет искаться min и max оси Y
                double[] arrAxisY = { float.Parse(textBox41Text),float.Parse(textBox42.Text),float.Parse(textBox43.Text),
                                               float.Parse(textBox44Text),float.Parse(textBox45.Text) ….
                                              };
 
                double min_val = Round(arrAxisY.Min(),2); //ищем min и max по оси Y
                double max_val = Round(arrAxisY.Max(),2);
               
                chart1.ChartAreas[0].AxisY.Minimum = min_val; // настройка минимума и максимума оси Y
                chart1.ChartAreas[0].AxisY.Maximum = max_val;
                chart1.ChartAreas[1].AxisY.Minimum = min_val; //
                chart1.ChartAreas[1].AxisY.Maximum = max_val;
 
                // Добавление точек на график 1
                 chart1.Series[“Подача”].Points.Add(float.Parse(textBox41.Text));
                 chart1.Series[“Подача”].Points.Add(float.Parse(textBox42.Text));
                 ….
                // Добавление точек на график 2
                 chart1.Series[“Обратка”].Points.Add(float.Parse(textBox101.Text));
                 chart1.Series[“Обратка”].Points.Add(float.Parse(textBox102.Text));
                ….

Ответ:Еще пару строк кода:

C#
1
2
3
4
5
6
7
8
9
10
chart1.ChartAreas[0].AxisY.IsStartedFromZero = false;  //увеличение масштаба по оси Y
chart1.ChartAreas[0].AxisX.MajorGrid.Enabled = false; //убрать сетку по оси X
chart1.ChartAreas[0].AxisY.MajorGrid.Enabled = false; //убрать сетку по оси Y
// Настройка меток
chart1.Series[0].IsValueShownAsLabel = true;  // при true отображает значение точки в виде метки
chart1.Series[0].IsValueShownAsLabel = false;  // при false не отображает значение точки в виде метки
chart1.Series[0].LabelFormat = “F3”;  // форматирование: кол-во знаков после запятой
chart1.Series[0].MarkerStyle = MarkerStyle.Square; // стиль маркера точки данных
chart1.Series[0].MarkerColor = System.Drawing.Color.LimeGreen; //цвет точки маркера
chart1.Series[0].Font = new Font(“Microsoft Sans Serif”, 8f, FontStyle.Regular);  //настройка шрифта маркера

Вопрос: Элемент Chart – перерисовка графика

Всем, доброго дня! Вопрос в следующем, рассчитываю функцию и строю кривую при помощи Chart, но каждый раз при пересчете старая кривая сохраняется и поверх рисуется новая, как задать чтобы график обновлялся?

Заранее благодарю

Ответ:ну главное ты суть проблемы удовил… Я ж твоего кода не видел. я вообще всегда удаляю полностью Series и перестраиваю заново, так как имена могу отличаться при каждом динамическом построении. если данные идут из выборки БД. Вобщем от задачи зависит.
А ты видимо не перестраиваешь Серию а просто меняешь позиции точек…

Вопрос: Элемент Chart Windows Forms

Доброго времени суток! Подскажите кто-нибудь, пожалуйста, почему недоступен элемент Chart (серым цветом в Панели элементов)? Visual Studio 2010, FrameWork 3.5, MS Chart для FrameWork 3.5.

Голову уже сломала…

Ответ:Поставила FW 4.5, в свойствах проекта поменяла требуемую версию FW, а элемент всё равно недоступен

Вопрос: Добавление изображений на элемент chart

Здравствуйте! Можно ли как как-то реализовать добавление изображений на элемент chart??? Изображения представляют себя некие объекты, вокруг которых будут строятся графики.

Ответ:

Вопрос: Добавление изображение в элемент chart

Здравствуйте! Подскажите пожалуйста, как можно добавить изображение на элемент chart??

без использования функции BackImage, которая задает фон рисунком.

Ответ: ViterAlex, как такой контрол можно сделать?? не было опыта в создании такого

Вопрос: Как отобразить в chart несколько графиков?

Добрый день! Подскажите пожалуйста, на форме есть CheckBoxList, и Chart, проблема в том как отобразить в этом чарте больше одного графика, я могу написать например

C#
1
2
3
4
5
6
7
8
public Form1()
        {
            InitializeComponent();
            this.chart1.Series[0].ChartType = SeriesChartType.Line;
 
            this.chart1.Series[1].ChartType = SeriesChartType.Line;
 
        }

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

C#
1
2
3
4
5
6
7
8
9
10
11
12
        private void Load_graf()
        {
            int i = 0; //Переменная которая будет определять индекс графика
           
 
            foreach (object itemChecked in chechBoxList1.CheckedItems)
            {
                this.chart1.Series[i].Name = itemChecked.ToString();
                this.chart1.Series[i].ChartType = SeriesChartType.Line;//тип графика(линия)
                this.chart1.Series[i].BorderWidth = 6;//толщина линии
 
            }

и где-нибудь дописать i++, но вылетает исключение что индекс выходит за пределы диапазонатож не работает

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}
");let k=document.querySelector(".flat_pm_modal[data-id-modal=\""+a.ID+"\"]");if(-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(k,d):jQuery(k).html(b+d),"px"==a.how.popup.px_s)e.bind(h,()=>{e.scrollTop()>a.how.popup.after&&(e.unbind(h),f.unbind(i),j())}),void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{e.unbind(h),f.unbind(i),j()});else{let b=setTimeout(()=>{f.unbind(i),j()},1e3*a.how.popup.after);void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{clearTimeout(b),f.unbind(i),j()})}f.on("click",".flat_pm_modal .flat_pm_crs",()=>{jQuery.arcticmodal("close")})}if(void 0!==a.how.outgoing){let b,c="0"==a.how.outgoing.indent?"":" style=\"bottom:"+a.how.outgoing.indent+"px\"",e="true"==a.how.outgoing.cross?"":"",f=jQuery(window),g="scroll.out"+a.ID,h=void 0===flatPM_getCookie("flat_out_"+a.ID+"_mb")||"false"!=flatPM_getCookie("flat_out_"+a.ID+"_mb"),i=document.createElement("div"),j=jQuery("body"),k=()=>{void 0!==a.how.outgoing.cookie&&"false"==a.how.outgoing.cookie&&h&&(jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show"),j.on("click",".flat_pm_out[data-id-out=\""+a.ID+"\"] .flat_pm_crs",function(){flatPM_setCookie("flat_out_"+a.ID+"_mb",!1)})),(void 0===a.how.outgoing.cookie||"false"!=a.how.outgoing.cookie)&&jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show")};switch(a.how.outgoing.whence){case"1":b="top";break;case"2":b="bottom";break;case"3":b="left";break;case"4":b="right";}jQuery("body > *").eq(0).before("
"+e+"
");let m=document.querySelector(".flat_pm_out[data-id-out=\""+a.ID+"\"]");-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(m,d):jQuery(m).html(e+d),"px"==a.how.outgoing.px_s?f.bind(g,()=>{f.scrollTop()>a.how.outgoing.after&&(f.unbind(g),k())}):setTimeout(()=>{k()},1e3*a.how.outgoing.after),j.on("click",".flat_pm_out .flat_pm_crs",function(){jQuery(this).parent().removeClass("show").addClass("closed")})}countMode&&(flat_count["block_"+a.ID]={},flat_count["block_"+a.ID].count=1,flat_count["block_"+a.ID].click=0,flat_count["block_"+a.ID].id=a.ID)}catch(a){console.warn(a)}}function flatPM_start(){let a=flat_pm_arr.length;if(0==a)return flat_pm_arr=[],void jQuery(".flat_pm_start, .flat_pm_end").remove();flat_body=flat_body||jQuery("body"),!flat_counter&&countMode&&(flat_counter=!0,flat_body.on("click","[data-flat-id]",function(){let a=jQuery(this),b=a.attr("data-flat-id");flat_count["block_"+b].click++}),flat_body.on("mouseenter","[data-flat-id] iframe",function(){let a=jQuery(this),b=a.closest("[data-flat-id]").attr("data-flat-id");flat_iframe=b}).on("mouseleave","[data-flat-id] iframe",function(){flat_iframe=-1}),jQuery(window).on("beforeunload",()=>{jQuery.isEmptyObject(flat_count)||jQuery.ajax({async:!1,type:"POST",url:ajaxUrlFlatPM,dataType:"json",data:{action:"flat_pm_ajax",data_me:{method:"flat_pm_block_counter",arr:flat_count}}})}).on("blur",()=>{-1!=flat_iframe&&flat_count["block_"+flat_iframe].click++})),flat_userVars.init();for(let b=0;bflat_userVars.textlen||void 0!==a.chapter_sub&&a.chapter_subflat_userVars.titlelen||void 0!==a.title_sub&&a.title_subc&&cc&&c>d&&(b=flatPM_addDays(b,-1)),b>e||cd||c-1!=flat_userVars.referer.indexOf(a))||void 0!==a.referer.referer_disabled&&-1!=a.referer.referer_disabled.findIndex(a=>-1!=flat_userVars.referer.indexOf(a)))&&(c=!0),c||void 0===a.browser||(void 0===a.browser.browser_enabled||-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser))&&(void 0===a.browser.browser_disabled||-1==a.browser.browser_disabled.indexOf(flat_userVars.browser)))){if(c&&void 0!==a.browser&&void 0!==a.browser.browser_enabled&&-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser)&&(c=!1),!c&&(void 0!==a.geo||void 0!==a.role)&&(""==flat_userVars.ccode||""==flat_userVars.country||""==flat_userVars.city||""==flat_userVars.role)){flat_pm_then.push(a),flatPM_setWrap(a),flat_body.hasClass("flat_pm_block_geo_role")||(flat_body.addClass("flat_pm_block_geo_role"),flatPM_ajax("flat_pm_block_geo_role")),c=!0}c||(flatPM_setWrap(a),flatPM_next(a))}}}let b=jQuery(".flatPM_sticky");b.each(function(){let a=jQuery(this),b=a.data("height")||350,c=a.data("top");a.wrap("
");let d=a.parent()[0];flatPM_sticky(this,d,c)}),debugMode||countMode||jQuery("[data-flat-id]:not([data-id-out]):not([data-id-modal])").contents().unwrap(),flat_pm_arr=[],jQuery(".flat_pm_start, .flat_pm_end").remove()}
C#
1
2
3
4
            for (int i = 0; i

Источник: http://forundex.ru/yap/Element-Chart—nastrojka-grafika-219635

График линейной функции

Листинг 24.1. Наш код в шаблоне метода для кнопки Graph.

double a_Form3, b_Form3, x_min_Form3, x_max_Form3;

a_Form3 = Convert.ToDouble(textBox1.Text);

b_Form3 = Convert.ToDouble(textBox2.Text);

x_min_Form3 = Convert.ToDouble(textBox3.Text);

x_max_Form3 = Convert.ToDouble(textBox4.Text);

Form5 myForm5 = new Form5();

myForm5.a = a_Form3;

myForm5.b = b_Form3;

myForm5.x_min = x_min_Form3;

myForm5.x_max = x_max_Form3;

myForm5.Show();

Для программной реализации этого алгоритма дважды щелкаем значок timer1 (ниже формы в режиме проектирования). Появляется файл с шаблоном, в который записываем наш следующий код:

//Объявляем булеву переменную myColor со значением false:

bool myColor = false;

private void timer1_Tick(object sender, EventArgs e)

{

//Вводим анимацию:

if (myColor == false)

{

//Выводим красный цвет переключателя:

this.radioButton2.BackColor =

System.Drawing.Color.Red;

//Изменяем значение myColor на противоположное:

myColor = true;

}

else

{

//Выводим белый цвет переключателя:

this.radioButton2.BackColor =

System.Drawing.Color.White;

//Изменяем значение myColor на противоположное:

myColor = false;

}

}

Листинг 24.2. Первая часть кода (выше шаблона pictureBox1_Paint).

//Параметры графика функции y = a*x + b

//в виде глобальных переменных:

public float a, b, x_min, x_max;

float Function_of_graph(float x)

{

float Function;

//Метод y = f(x), график которой будем строить:

Function = a * x + b;

return Function;

}

Листинг 24.3. Вторая часть кода (выше шаблона pictureBox1_Paint).

//Число точек графика:

public int Npoints = 100;

//Величины (в пикселах) O_x_pix и O_y_pix

//для параллельного переноса

//осей “x” и “y” новой системы координат (по сравнению

//со старой системой в верхнем левом углу рамки PictureBox):

public float O_x_pix = 500;

public float O_y_pix = 350;

//Масштабы по осям “x” и “y” (M_x и M_y) для перехода

//от действительных значений к пикселам

//и построения графика в пикселах:

public float M_x = 450;

public float M_y = 300;

Теперь внутрь этого (приведенного выше) шаблона для процедуры pictureBox1_Paint записываем основную часть нашего кода для вывода графика на экран монитора. Перед каждым логическим блоком кода мы даем подробный комментарий, чтобы читатель мог изучить это важный код и мог грамотно внести изменения (в случае необходимости).

Листинг 24.4. Главный код построения графика функции на экране монитора.

//Шаг по оси абсцисс “x” между точками графика:

float step_x = (x_max-x_min)/Npoints;

//Наибольшее абсолютное значение x_max_abs

//из двух концов заданного нами числового интервала

//x_min и x_max:

float x_max_abs = Math.Abs(x_max);

if (x_max_abs < Math.Abs(x_min)) x_max_abs = Math.Abs(x_min);

//Промежуточные локальные переменные:

float x_0, y_0, x_1, y_1, x_0_pix, y_0_pix, x_1_pix, y_1_pix;

//Расчет минимального y_min и максимального y_max

//действительных значений функции:

float y_min, y_max;

//Присваиваем y_min, y_max значение y_0

//для нулевой точки (i=0):

x_0 = x_min; y_0 = Function_of_graph(x_0);

y_min = y_0; y_max = y_0; int i;

//Организовываем цикл по всем точкам, начиная с i=1:

for (i=1; i y_1) y_min = y_1;

if (y_max < y_1) y_max = y_1;

}

//Т.к. в последней точке i = Npoints

//значение x_1 = x_min + Npoints * step_x

//может отличаться от заданного значения x_max

//(из-за накапливания погрешности в цикле), то проверяем,

//может быть y_min или y_max находится в последней

//точке при точном задании нами значения x_max:

x_1 = x_max; y_1 = Function_of_graph(x_1);

//Проверка минимального и максимального

//значений функции в последней точке:

if (y_min > y_1) y_min = y_1;

if (y_max < y_1) y_max = y_1;

//Наибольшее абсолютное значение функции y_max_abs

//из двух значений y_min и y_max:

float y_max_abs = Math.Abs(y_max);

if (y_max_abs < Math.Abs(y_min)) y_max_abs = Math.Abs(y_min);

//Строим сетку координат:

//Сначала строим ось абсцисс “x” от x = -1 до x = 1:

//Задаем абсциссу последней точки оси абсцисс “x”

//при x = 1:

float x_point_end, x_point_end_pix; x_point_end = 1;

x_point_end_pix = x_point_end * M_x + O_x_pix;

//Выбираем зеленое перо толщиной 2:

Pen greenPen_x = new Pen(Color.Green, 2);

//Задаем координаты двух граничных точек оси:

PointF point1 = new PointF(-1 * M_x + O_x_pix, O_y_pix);

PointF point2 = new PointF(x_point_end_pix, O_y_pix);

//Строим линию через две заданные граничные точки:

e.Graphics.DrawLine(greenPen_x, point1, point2);

//Строим горизонтальные линии сетки координат

//(кроме оси “x”):

//Ширина (размах) графика по оси ординат “y”:

float span_y = y_max – y_min;

//Число шагов по всей высоте сетки (по оси “y”):

int N_step_grid_y = 20;

//Шаг сетки в направлении оси “y”

//(высота всей сетки равна 2 единицам):

float step_grid_y, step_grid_y_pix;

//Преобразование типов переменных:

step_grid_y = (float) 2 / N_step_grid_y;

step_grid_y_pix = step_grid_y * M_y;

//Выбираем красное перо толщиной 1:

Pen redPen = new Pen(Color.Red, 1);

//Строим сетку от нулевой линии в одну сторону (вниз):

int j_y; float y1, y1_pix;

for (j_y = 1; j_y

Источник: http://csharp-cs.blogspot.com/2010/04/blog-post_3370.html