Работа с графикой (C++/CLI)
демонстрируется обработка изображений с помощью Windows SDK.
В следующих разделах демонстрируется использование System.Drawing.Image класса для выполнения манипуляций с изображениями.
отображение изображений с помощью платформа .NET Framework
В следующем примере кода обработчик событий onpain изменяется для получения указателя на Graphics объект главной формы. OnPaintфункция предназначена для Windows Forms приложения, которая, скорее всего, создается с помощью мастера Visual Studio приложений.
Как рисовать графики в с
БлогNot. Visual C++/CLI: рисуем простой график функции в PictureBox
Visual C++/CLI: рисуем простой график функции в PictureBox
В этом примере мы хотим нарисовать простой график на компоненте PictureBox «по точкам», а не с использованием готовой компоненты Chart.
Создав проект Windows Forms в любой версии Studio 2012 и выше, придадим окну формы удобный размер и перетащим туда компоненту TableLayoutPanel , установим ей свойство Dock=Fill , затем удалим последнюю строку так, чтобы осталось 2 столбца, первому столбцу зададим относительную ширину 100%, а второму — абсолютную ширину 100 пикселов (как выполнять такие действия, показано в этой заметке).
В правую ячейку TableLayoutPanel перетащим кнопку Button и привяжем её ко всем краям формы, кроме нижнего (свойство Anchor = Top, Left, Right , свойство Dock=Top ).
В левую ячейку перетащим PictureBox и также установим ему Dock=Fill . Внешний вид полученной формы показан на рисунке:
Вид формы приложения
Так как экранный шаг в пикселах в условии не задан, установим его в переменной unit . Для порядка шаблон отрисовываемой функции double f(double x) опишем как делегат соответствующего типа. Весь этот код можно поместить после директивы #pragma endregion в файле MyForm.h :
Нам придётся запрограммировать только щелчок по кнопке, после двойного щелчка по ней в конструкторе создастся обработчик события
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) <
>
в который мы и поместим весь показанный ниже код с комментариями.
График перерисовывается каждый раз при нажатии кнопки. Пожалуй, это даже экономичнее по ресурсам, чем использование события Paint .
Можно подойти к задаче и по-другому, заранее задав интервал изменения переменной по оси X, а шаг по ней (как и по оси Y) рассчитывая так, чтобы он был равен одному пикселу. Тогда при той же самой форме пользовательская часть кода примет следующий вид (для простоты исключено рисование линий сетки).
Вид формы приложения (2)
Рисование сеточных графиков трехмерных функций и изолиний к ним
Статья представляет собой нечто вроде “практического руководства” для построения весьма интересных трехмерных графиков функций вида z=f(x,y), с примером реализации на C#.
Рисовать будем в компоненте Chart, разумеется, можно использовать любой canvas-подобный элемент. При большом количестве точек будут наблюдаться задержки в рисовании, но этот компонент легко использовать и для демонстрации он вполне сгодится.
Строим график
Для этого нам понадобится сетка или поле, каждый узел которой будет иметь координаты x, y и содержать значение z. Эту сетку можно заполнять любым способом, раз мы строим график функции, то будем заполнять ее значениями этой функции (z=f(x,y)). Шаг между двумя последовательными значениями x или y выберем равный одному, для более простой и наглядной демонстрации, размерность сетки N x N. Значения в узлах сетки достаточно считать один раз. Для преобразования трехмерных координат в двухмерные и для поворота графика будем использовать матрицу поворота и углы Эйлера.
Обозначим углы α, β и γ углами a, b и c соответственно и будем использовать их значения в градусах. Запишем матрицу через коэффициенты:
Запишем итоговое преобразование из трехмерных координат в двухмерные:
X=l1x+l2y+l3z
Y=m1x+m2y+m3z
x,y,z –это “внутренние” координаты для графика, X,Y – итоговые экранные координаты. Коэффициенты n1,n2 и n3 нам для этой задачи не понадобятся.
Добавим события, при которых будут меняться углы и будет происходить вращение графика. Например, это будет движение курсора при зажатой левой кнопке мышки и изменение углов b и с:
Проверим на тестовой функции 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 вариантов:
Не будем писать весь код заново, возьмем часть кода из той статьи и изменим под нашу задачу:
Попробуем опять же на нашей тестовой функции 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, выбирается в зависимости от направления движения для предыдущего и следующего шагов.
Напишем для этого такой, не очень хороший код:
И получаем результат, который нас уже более устраивает:
Пример «ненужных точек», которые мы исключили.
Из возможных улучшений следует отметить, что наша реализация будет строить все изолинии только для монотонно возрастающих (для убывающих следует поменять знак на “>”) функций. Для функций периодически возрастающих и убывающих следует изменить, например функцию поиска начальной позиции и выполнять её несколько раз.
Пример работы итоговой программы.
На практике это можно применять для анализа карт, или для поиска контура на изображении.