Печатать книгуПечатать книгу

§ 14. Интерактивная графика

Сайт: Профильное обучение
Курс: Информатика. 11 класс (Повышенный уровень)
Книга: § 14. Интерактивная графика
Напечатано:: Гость
Дата: Суббота, 27 Апрель 2024, 20:41

14.1. Понятие об интерактивной графике

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

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

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

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

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

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

В среде CBuilder выбор команд можно осуществлять с помощью элементов управления: кнопок, текстовых полей, переключателей и т. д.

Пример 14.1. Пассивная графика — график функции y = x2sin(x) на промежутке
[-10; 10].

Интерактивное управление процессом построения графика функции[1]:

Результат:



[1] https://math.semestr.ru/math/plot.php

Примером интерактивной графики является проект[1] «Наберите Луну (Dial A Moon)», где можно указать дату и время и увидеть, в какой фазе находится луна. Подборка интересных проектов интерактивной графики собрана на сайте «Профессиональный конструктор лендингов для бизнеса».[2] (Лендинг — автономная интернет-страница, на которую потенциальный клиент попадает после клика по рекламному объявлению или в результате поиска).

Согласно исследованиям, человек запоминает около 10% информации, которую слышит, 20% от прочитанного. Люди запоминают порядка 80% того, что видят и делают. В этом случае объединяются два канала восприятия информации: визуальный и кинестетический (ощущения положения и движения органов тела). Интерактивная инфографика заставляет человека совершать какие-либо целенаправленные действия во время чтения, что значительно облегчает передачу и усвоение информации.


[1] https://svs.gsfc.nasa.gov/cgi-bin/details.cgi?aid=4236

[2 https://lpgenerator.ru/blog/2017/11/30/luchshie-primery-ispolzovaniya-interaktivnoj-infografiki-na-lendingah/

14.2. Построение изображения в зависимости от размера и положения

Пример 14.2. Создать проект, в котором будет строиться изображение «сердечка». Пользователь задает высоту и ширину изображения. Местоположение рисунка будет определяться кликом мыши (в точке, где кликнули, должен располагаться центр изображения). Если изображение целиком не помещается в области рисования, то следует вывести соответствующее сообщение.

Этапы выполнения задания

  1. Разместить на форме компоненты: Image и два компонента LabeledEdit для ввода размеров изображения.
  2. Написать обработчик события OnMouseDown для компонента Image1.
    2.1. По клику мыши рисуем «сердечко».
    2.2. Для рисования одного изображения опишем функцию heart. Эта функция должна стать методом формы, поэтому ее объявление нужно добавить в заголовочный файл. Для того, чтобы функция была определена в области видимости класса формы перед ее заголовком необходимо прописать void __fastcall TForm1::.
    2.3. Изображение «сердечка» можно разбить на части: равнобедренный треугольник и два полукруга.
    2.3.1. Для построения треугольника будем использовать метод канвы Polygon. У этого метода два параметра — массив точек и номер точки в массиве, которую нужно соединить с нулевой. Массив из трех точек можно описать следующим образом:
    TPoint t[3] = {{x4,y4},{x6,y6},{x3,y3}};
    2.3.2. Для построения полукруга будем использовать метод канвы Pie.
    2.4.  Все координаты для рисования рассчитываются относительно центральной точки и размеров изображения, введенных пользователем.
    2.5. Изображение будем строить с красной границей и зальем его красным цветом.
  3. Проверить, поместится ли изображение в область рисования можно считая, что прямоугольник, определяемый диагональю (x1; y1) — (x2; y2) должен помещаться в компонент Image1.

Пример 14.3. Создать проект, в котором можно будет выбирать, как располагать «сердечки»:

а) одно «сердечко» в случайном месте Image;
б) «сердечки» расположены по одному в ряд вдоль левого края Image;
в) «сердечки» равномерно заполняют весь Image.

Выбор необходимо осуществлять с помощью соответствующих кнопок.

Этапы выполнения задания

  1. Разместить на форме: компонент Image и три кнопки.
  2. Будем использовать функцию рисования «сердечка» из примера 14.2.
  3. Написать обработчик события OnClick для компонента Button1. Рисуем одно «сердечко». Размер и местоположение определяем случайным образом.
  4. Написать обработчик события OnClick для компонента Button2. В цикле меняем вертикальную координату, определяющую местоположения «сердечка». Размер — 30 на 30 пикселей. Цикл выполняется, пока вертикальная координата меньше высоты Image1.
  5. Написать обработчик события OnClick для компонента Button3. Используем два вложенных цикла, в которых будут меняться горизонтальная и вертикальная координаты, определяющие местоположения сердечка. Размер — 30 на 30 пикселей. Циклы выполняются, пока координаты меньше размеров Image1.
  6. В начале каждого обработчика необходимо очищать Image1 от предыдущих изображений.

Пример 14.2. Добавление метода heart в заголовочный файл формы:

Расчет элементов изображения:

Значения  и  вводятся пользователем, значение d = w/2. Значения x0, y0 определяются кликом мыши, остальные координаты высчитываются по следующим формулам:

x1 = x0 – w/2; y1 = y0 – h/2;
x2 = x0 + w/2; y2 = y0 + h/2;
x3 = x1y3 = y1 + d/2;
x4 = x2y4 = y3;
x5 = x3 + dy5 = y3;
x6 = x5y6 = y2;

Обработчик события OnMouseDown и функция рисования:

void __fastcall TForm1::heart(int x0, int y0, 
                              int w, int h)

{

  Image1 -> Canvas -> Pen -> Color = clRed;

  Image1 -> Canvas -> Brush -> Color = clRed;

  int d = w / 2;

  int x1 = x0 - w/2, y1 = y0 - h/2;

  int x2 = x0 + w/2, y2 = y0 + h/2;

  int x3 = x1, y3 = y1 + d/2;

  int x4 = x2, y4 = y3;

  int x5 = x3 + d, y5 = y3;

  int x6 = x5, y6 = y2;

  Image1 -> Canvas -> Pie(x1, y1, x5, y5 + d / 2, x5, y5, x3, y3);

  Image1 ->Canvas -> Pie(x5, y5 - d / 2, x4, y4 + d / 2, x4, y4, x5, y5);

  TPoint t[3] = {{x4,y4},{x6,y6},{x3,y3}};

  Image1 ->Canvas ->Polygon(t, 2);

}

//---------------------------------

void __fastcall TForm1::Image1MouseDown
(TObject *Sender, TMouseButton Button, 
TShiftState Shift,   
int X, int Y)

{

  int width = StrToInt(LabeledEdit1 ->Text);

  int height = StrToInt(LabeledEdit2 ->Text);

  if (X - width / 2 < 0 || Y - height / 2 < 0 ||

     X + width / 2 > Image1 -> Width ||

     Y + height / 2 > Image1 -> Height)

    ShowMessage("Не поместится");

  else

    heart(X, Y, width, height);

}

Работающее приложение:

 Пример 14.3. Обработчики событий для кнопок:

void __fastcall TForm1::Button1Click
                (TObject *Sender)

{

  Image1 -> Canvas -> Pen -> Color = clWhite;

  Image1 -> Canvas -> Brush -> Color = clWhite;

  Image1 -> Canvas -> Rectangle(0, 0,

      Image1 -> Width, Image1 -> Height);

  int width = rand() % 300 + 30;

  int height = rand() % 300 + width;

  int x = rand() %(Image1 ->Width - 2 * width) + width / 2;

  int y = rand() %(Image1 ->Height - 2 * height) + height / 2;

  heart(x, y, width, height);

}

//---------------------------------

void __fastcall TForm1::Button2Click
               (TObject *Sender)

{

  Image1 -> Canvas -> Pen -> Color = clWhite;

  Image1 -> Canvas -> Brush -> Color = clWhite;

  Image1 -> Canvas -> Rectangle(0, 0,

      Image1 -> Width, Image1 -> Height);

  for (int y = 16; y < Image1 -> Height - 16; y += 45)

    heart(16, y, 3030);

}

//---------------------------------

void __fastcall TForm1::Button3Click
                (TObject *Sender)

{

  Image1 -> Canvas -> Pen -> Color = clWhite;

  Image1 -> Canvas -> Brush -> Color = clWhite;

  Image1 -> Canvas -> Rectangle(0, 0,

      Image1 -> Width, Image1 -> Height);

  for (int x = 16; x < Image1 -> Width - 16; x += 45)

    for (int y = 16; y < Image1 -> Height - 16; y += 45)

      heart(x, y, 3030);

}

Работающее приложение:

14.3. Битовые образы

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

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

В программе битовый образ — это объект типа TBitmap. Класс TBitmap, определен в CBuilder как Graphic::TBitmap. Этот класс поддерживает как растровые изображения в виде массива пикселей, так и изображения в формате BMP. Некоторые свойства и методы объекта TBitmap приведены в примере 14.4.

Описание битовой матрицы с именем Pict осуществляется следующим образом:

Graphics::TBitmap *Pict = new Graphics::TBitmap();

— указатель на место в памяти, где будет размещен объект, хранящий изображение.

Для вывода битового образа на канву можно воспользоваться методом Draw(x, y, Pict). Параметры x, y определяют местоположение верхнего левого угла изображения, хранящегося в переменной Pict (объект типа TBitmap).

Пример 14.5. Создать проект, в котором по клику мыши поверх фонового изображения леса необходимо нарисовать картинки зверей, хранящихся в файлах. Для корректной работы все рисунки должны быть в BMP формате. Рисунки следует сохранить в папке Win32\Debug. Рисунки, на которых изображены звери, должны иметь однородный фон[1].

Этапы выполнения задания

  1. Поместить на форму компонент Image.
  2. В событии OnCreat для формы загрузить фоновое изображение в компонент Image1. Изображение необходимо загружать в своих реальных размерах (свойство Scratch = false). В противном случае при клике по изображению координаты точки не будут соответствовать реальной картинке.
  3. Написать обработчик события OnMouseDown для компонента Image.

3.1. Создать объект Pict для хранения битового образа;
3.2. С помощью диалога OpenPictureDialog1 загрузить рисунок в память.
3.3. Установить прозрачный цвет для фона.
3.4. Вывести рисунок методом Draw.

Битовые образы могут использоваться для заливки фигур, нарисованных на канве. Для этого свойству Brush -> Bitmap нужно присвоить значение битового образа.

Image1->Canvas->Brush->Bitmap = Pict;

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

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

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

Image1->Canvas->Brush->Bitmap = NULL;

[1] При необходимости рисунок нужно предварительно обработать в графическом редакторе.

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

Пример 14.4. Некоторые свойства объекта TBitmap.

Свойство

Назначение

Canvas

Определяет холст для изображения битового образа

Empty

Указывает, содержит ли объект битовый образ

Height

Высота изображения в пикселях

Transparent

Определяет, должно ли изображение быть «прозрачным»

TransparentColor

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

Width

Указывает ширину изображения в пикселах

Некоторые методы объекта TBitmap.

Метод Assign копирует изображение из другого графического объекта.

Методы LoadFromFile и SaveToFile используются для чтения изображение из файла и записи изображения в файл.

Пример 14.5. Форма на этапе конструирования:

Обработчик события OnCreat.

void __fastcall TForm1::FormCreate(TObject *Sender)

{

  Image1 ->Picture ->LoadFromFile("лес.bmp");

  OpenPictureDialog1 -> InitialDir =

  ExtractFilePath(ParamStr(0));

}

Обработчик события OnMouseDown

void __fastcall TForm1::Image1MouseDown
                TObject *Sender, 
                TMouseButton Button, 
                TShiftState Shift, 
int X, int Y)

{

  if (OpenPictureDialog1 ->Execute()){

    Graphics::TBitmap *Pict = 

    new Graphics::TBitmap();

    Pict ->LoadFromFile

    (OpenPictureDialog1 ->FileName);

    Pict ->Transparent = true;

    Pict ->TransparentColor =

    Pict ->Canvas ->Pixels[0][0];

    Image1 ->Canvas ->Draw(X, Y, Pict);

  }

}

Работающее приложение:

Пример 14.6. Заливка с использованием битовых образов:

Код обработчика нажатия кнопки «Эллипс» (для прямоугольника аналогично):

Graphics::TBitmap *Pict = 

  new Graphics::TBitmap();

Pict -> LoadFromFile("розы.bmp");

Image1 -> Canvas-> Brush -> Bitmap = Pict;

Image1 -> Canvas-> Ellipse(1010500350);

Image1 -> Canvas-> Brush -> Bitmap = NULL;

Константа NULL, имеет значение «ничего». Формально — это значение указателя, который не ссылается ни на какой объект.

Вопросы к параграфу

1. Что понимают под интерактивной графикой?

2. Какими параметрами интерактивного изображения может управлять пользователь?

3. Каким образом пользователь может управлять интерактивным изображением?

4. Что понимают под битовыми образами?

5. Как описать битовый образ?

6. Как использовать битовый образ для заливки фигур?

Упражнения

  

1. Добавьте в проект из примера 14.2. перечисленные возможности:

  1. Выбор цвета для рисования «сердечка».
  2. Кнопку «Очистка», которая будет очищать область рисования (нарисовать прямоугольник белого цвета, совпадающий по размерам с компонентом Image).

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

  1. Нарисовать на экране квадрат, со сторонами параллельными сторонам экрана. Длина стороны квадрата вводится, местоположение верхнего левого угла определяется кликом мыши.
  2. Нарисовать на экране прямоугольную трапецию. Длины оснований, высоты и координаты верхнего левого угла трапеции вводятся. (Трапецию расположить так, чтобы ее основания были параллельны одной из сторон экрана)
  3. Нарисовать на экране два квадрата, со сторонами параллельными сторонам экрана. Один из квадратов лежит в другом, так что квадраты имеют общий центр (точка пересечения диагоналей). Длины сторон квадратов вводятся, центр квадрата определяется кликом мыши.
  4. Нарисовать на экране ромб. Длины диагоналей ромба вводятся, координаты точки пересечения диагоналей определяются кликом мыши. (Ромб расположить так, чтобы его диагонали были параллельны сторонам экрана)
  5. Нарисовать на экране квадрат, со сторонами параллельными сторонам экрана. Длина стороны квадрата и координаты верхнего левого угла вводятся. Описать окружность вокруг квадрата.
  6. Нарисовать на экране треугольник, заданный координатами своих вершин. Провести медианы этого треугольника. Точку пересечения медиан выделить контрастным цветом. (Построить круг радиуса 3)

3. Добавьте в проект из примера 14.3. следующее:

  1. Выбор цвета и размера для рисования «сердечка».
  2. Компонент CheckBox, с помощью которого можно определить, что цвет будет задаваться случайным образом.
  3. Компоненты CheckBox, с помощью которых можно выбирать вдоль какой границы Image (слева, справа, сверху, снизу, по диагонали) рисовать сердечки.

4. Измените проект примера из 14.3 так, чтобы рисовались не сердечки, а следующие фигурки. Продумайте управление вывода изображения на экран.

  1. квадратики;
  2. равнобедренные треугольники;
  3. грибочки: 
  4. пирамидки: 
  5. флажки: 
  6. предложите свои фигурки.

5. Добавьте возможность заливки домика растровым изображением (изменить проект из  примера 13.8).

Примерный вид формы

Клик мышью по рисунку, если CheckBox не активен

Клик мышью по рисунку, если CheckBox активен

Результат закраски