Сегодня в рамках большинства технических и гуманитарных направлений изучется дисциплина «Компьютерная графика», в рамках которой студент знакомиться с понятиями растровой, векорной и фрактальной графики. Практикумы проводятся в соответствующих видам графики редакторах, это может быть Adobe Photoshop, Adobe Illustrator, Corel Photo-Paint, Corel Draw и другие. Для проведения занятий можно подобрать большое количество, из существующих, бесплатных графических редакторов.
Одной из наиболее интересных тем в курсе ставновится тема об использовании элементов программирования для построения графических изображений. В контексте данной темы студенты рисуют изображения, создают анимацию в одной из сред интегрированного программирования.
Приведем примеры раскрытия данной темы используя среду программирования Visual Studio для создания графических изображений на языке С#.
На первом занятии студенты знакомятся с понятием интерфейса Windows — GDI (Graphics Device Interface, Graphical Device Interface), предназначенным для представления графических объектов и выводом их на монитор или принтер. В его задачу входит отрисовка линий, кривых, отображение шрифтов и обработку палитры. Данная технология предоставляет богатые возможности для работы с векторной и фрактальной графикой.
Перед тем как рисовать линии и фигуры, отображать текст, выводить изображения и управлять ими в GDI необходимо создать объект Graphics. Объект Graphics представляет поверхность рисования GDI и используется для создания графических изображений. Graphics — поверхность для рисования, дополнительно класс содержит методы и свойства, позволяющие эффективно манипулировать геометрическими объектами на поверхности рисования.
Выделим три варианта использования данного объекта:
1. объект для визуализации графических изображений возвращает метод CreateGraphics(), который имеется у всех объектов управления, производных от класса Control.
Graphics gr;
gr = this.CreateGraphics();
2. объект экземпляра класса Graphics можно создать, взяв за основу файл с точечным изображением:
Bitmap bim = new Bitmap(“c:\\Catalog\\image.bmp”);
Graphics g = Graphics.FromImage(bim);
3. ссылка на объект для рисования может быть получена из параметра PaintEventArgs, который передаётся в обработчик события Paint.
4. Graphics g = Graphics.FromHwnd(this.Handle);
Graphics.FromHwnd(this.Handle) — используемый метод FromHwnd из класса Graphics, который задает ссылку Handle на форму Windows.
Graphics g = Graphics.FromHwnd(pictureBox1.Handle);
// выводит на объект pictureBox1
Определены два этапа работы с графикой.
- Создание объекта Graphics.
- Использование объекта Graphics для рисования линий и фигур, отображения текста или изображения и управления ими.
В ходе нескальких занятий студенты знакомятся с основными механизмами рисования и анимирования объектов, получают задания для выполнения в ходе самостоятельной работы и контрольных заданий.
Задания:
- Опишите 3 метода или свойства классов Graphics, Color, Pen и SolidBrush, не рассморенных в теоретической части.
- Создайте собственное приложение выводящий на форму рисунок, состоящий из различных объектов (линий, многоугольников, эллипсов, прямоугольников и пр.), не закрашенных и закрашенных полностью. Используйте разные цвета и стили линий (сплошные, штриховые, штрихпунктирные). Пользователь может по нажатию клавиш перемещать его по экрану, менять его размер и поворачивать. Представьте три варианта создания изображение: через bitmap, через параметр PaintEventArgs, через ссылку Handle на форму Windows.
- Постройте график функции по своему варианту из лабораторной работы. Добавьте заголовок.
- Создайте фрактал по своему варианту.
- Анимация объекта
- Работа с растровым изображением.
Приведем некоторые результаты решения данных задач студентами.
1. Объектом для рисования становится поверхность формы. Студентам необходимо на форме изобразить соответсвующий график, учитывая, что система координат на форме, следующая: левый верхний угол формы являтся точкой с координатами 0,0 (центр системы координат); отсчет по оси абсцисс слава-направа — положительные значения х; отсчет по оси ординат сверху-вниз — положительные значения y. Предложенно простейшее решение: расчитать координаты графика функций, с учетом предложенного шага, ось ординат перенести на линию со значением 150 (данное число впоследствии можно сделать динамическим, зависящим от высоты окна), приступить к построению графика учитывая сдвиг и расширить значения по осям.
// y=x^3
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.Clear(Color.White);
double x0 = -3F;
double xk = 3F;
double step = 0.1F;
int count = (int)((xk — x0) / step);
textBox1.Text = count.ToString();
double[] y = new double[count];
int i = 0;
while (i {
y[i] = Math.Pow((x0 + step * i), 3); //x в кубе
i++;
}
for (i = 1; i {
g.DrawLine(new Pen(Brushes.Black, 1), (i — 1)*10, (float)(y[i — 1] * 10 * (-1) + 150), i*10, (float)(y[i] * 10 * (-1) + 150));
// 10 это расширение еденицы графика
// 150 это сдвиг по у (150 — ось абсцисс)
// *(-1) для зеркального отражения, так как центр в левом вехнем углу
textBox1.Text += Environment.NewLine + (i — 1) + "," + (y[i — 1] * 10 + 150);
}
}
// y=5/x.
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.Clear(Color.White);
double x0 = -3F;
double xk = 3F;
double step = 0.1F;
int count = (int)((xk — x0) / step);
textBox1.Text = count.ToString();
double[] y = new double[count];
int i = 0;
while (i {
y[i] = 5/(x0 + step * i); //гипербола
i++;
}
for (i = 1; i {
try
{
//точки разрыва вызовут ошибку переполнения — конструкция перехвата
g.DrawLine(new Pen(Brushes.Black, 2), (i — 1) * 15, (float)(y[i — 1] * 15 * (-1) + 150), i * 15, (float)(y[i] * 15 * (-1) + 150));
}
catch
{
continue;
}
// 15 это расширение еденицы графика
// 150 это сдвиг по у (150 — ось абсцисс)
// *(-1) для зеркального отражения, так как центр в левом вехнем углу
textBox1.Text += Environment.NewLine + (i — 1) + "," + (y[i — 1] * 10 + 150);
}
}
2. Построение фрактала «Кривая дракона». Алгоритм рекурсивного построения студентами изучен. Объетом для рисования становится объект pictureBoxNew.
public partial class Form1 : Form3. Пример анимирования объекта на форме. Случайное движение объекта (звезда). За изменение прорисовки объекта с новыми координатами отвечает Timer: вычислив новые координаты он вызывает метод Paint для новой прорисовки на форме (при этом стирать старый объект не нужно).
{
public Form1()
{
InitializeComponent();
}
Graphics grf;
void dragon_func(int x1, int y1, int x2, int y2, int k)
{
int tx, ty;
var drawingPen = new Pen(Brushes.Navy, 1);
if (k > 0)
{
tx = (x1 + x2) / 2 + (y2 — y1) / 2;
ty = (y1 + y2) / 2 — (x2 — x1) / 2;
dragon_func(x2, y2, tx, ty, k — 1);
dragon_func(x1, y1, tx, ty, k — 1);
}
var point1 = new Point(x1, y1);
var point2 = new Point(x2, y2);
gr.DrawLine(drawingPen, point1, point2);
}
Bitmap frac()
{
Bitmap bmp = new Bitmap(pictureBoxNew.Width, pictureBoxNew.Height);
grf = Graphics.FromImage(bmp);
int x1, y1, x2, y2, k;
x1 = 200;
y1 = 200;
x2 = 300;
y2 = 400;
k = 15;
dragon_func(x1, y1, x2, y2, k);
return bmp;
}
private void button1_Click(object sender, EventArgs e)
{
pictureBoxNew.Image = frac();
}
private void button2_Click(object sender, EventArgs e) // очистка
{
Graphics gr = Graphics.FromHwnd(pictureBoxNew.Handle);
var bgcolor = new SolidBrush(Color.White);
gr.FillRectangle(bgcolor, 0, 0, pictureBoxNew.Width, pictureBoxNew.Height);
}
}
public partial class Form1 : Form
{
//описываем переменные
private int x1 = 30, y1 = 30, x2 = 100, y2 = 100, r;
double x, y;
private Pen pen = new Pen(Color.DarkRed, 2);
public Form1()
{
InitializeComponent();
x = Convert.ToDouble(this.Width);
y = Convert.ToDouble(this.Height);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
//рисуем звезду
g.DrawLine(pen, x1, y1, x2, y2);
g.DrawLine(pen, x1, y1 + 70, x2, y2 — 70);
g.DrawLine(pen, x1 — 5, y1 + 35, x2 + 5, y2 — 35);
g.DrawLine(pen, x1 + 35, y1 + 75, x2 — 35, y2 — 75);
}
private void timer1_Tick(object sender, EventArgs e)
{
// определение пути движения объекта случайным образом
Random rnd = new Random();
int i = rnd.Next(-15, 16);
if (x1 + i > 0 && x1 + i 0 && x2 + i {
x1 += i;
x2 += i;
}
i = rnd.Next(-15, 16);
if (y1 + i > 0 && y1 + i 0 && y2 + i {
y1 += i;
y2 += i;
}
Invalidate(); //вынудительный вызов перерисовки (Paint)
}
}
Рассмотренные выше примеры формируют понимание принципов создания векторного и фрактального изображений.
Предлагаются студентам так же и задания по работе с растровыми изображениями, где ставятся задания по загрузке на форму растрового рисунка, определения цветовых каналов каждй точки и создания на основе старого изображения нового в котором предложенным образом будут изменены цвета.
Таким образом, на занятиях по программированию элементов компьютерной графики студенты опытным путем знакомятся с базовыми принципами формирования растрового, векторного и фрактального изображения и углубляют свои знания по основам програмирования в интегрированных визуальных средах.