• Регистрация
Sancho
Sancho +99.25
н/д

Анимация в MATLAB. Часть 4

11.08.2020

В этой публикации мы коснёмся анимации в MATLAB.

Имеется 2 подхода для создание анимаций: 

  1. Через изменение свойств отображаемого объекта напрямую.
  2. Выполнение преобразований над объектом или над группами объектов: трансляций, поворотов и масштабирования.

О них и пойдёт речь ниже. 

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

Когда нужно рисовать график, используются команды типа plot, scatter, и т.д., а для изменения особенных свойств используется Property Inspector или команды типа legend, xlim и т.д.

Некоторые из этих хорошо известных вам команд порождают объекты, другие меняют свойства этих объектов. В MATLAB существует четкая иерархия типов объектов отображения, а к свойствам этих объектов (таким как оси, линии и т.д.) можно обращаться непосредственно из кода.

Окно графика формируется следующим образом: сначала появляется поле окна (класс Figure), на котором могут отображаться, в свою очередь, другие объекты, в частности, поля для графиков (класс Axes). Некоторые свойства объектов типа Axes наследуются от объекта типа Figure, на котором он был отображен. Говоря шире, класс Axes является "классом-наследником" по отношению к классу Figure, а класс Figure, в свою очередь, является "классом-родителем" по отношению к Axes.

Другими подобными объектами являются линии (создаваемые функцией plot, например), текстовые окна, стрелки и т п, все из них обладают разными, но известными свойствами. 

Теперь перейдём непосредственно к анимации.

В MATLAB имеется 2 подхода для создание анимаций: 

  1. Через изменение свойств отображаемого объекта напрямую.
  2. Выполнение преобразований над объектом или над группами объектов: трансляций, поворотов и масштабирования. 

У объектов типа line есть свойства XData, YData (для трёхмерных линий ZData), которые содержат в себе координаты отображаемых точек. Их можно изменять в цикле, что и позволит создать анимацию.

Второй подход заключается в преобразовании объектов типа transform, но об этом детальнее поговорим позже. Итак, перейдём к первому примеру.

1-й подход к созданию анимаций посредством изменения свойств отображаемого объекта напрямую.

Пример 1. Зашумление синуса.

Давайте нарисуем наш первый анимированный график.

На осях будут 2 графика:

  • первый – синус в виде линии.
  • Второй будет точечный и изначально тоже синус.

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

Сначала нарисуем оба этих графика стандартными функциями. Далее добавим цикл для отображения анимации. Можно использовать цикл for,  но можно поступить и по-другому. Пусть наша анимация будет работать, пока фигура не будет закрыта. Когда фигура закрывается, ссылка на неё становится недействительной. Проверить действительна ли ссылка можно функцией isvalid.

Реализуем цикл while.

Укажем задержку – функцией pause в 0.01 секунду, далее к данным по оси ординат будет прибавлять нормально распределённую случайную величину, укажем команду drawnow, которая обновит графику с учётом изменённых свойств. Запустим скрипт.

Работает.

Пример 2. Два круга + экспорт в видеоформат.

Отобразим 2 круга: один будет изменять свой радиус, а другой будет вращаться вокруг первого. Также научимся экспортировать анимацию из матлаба в видеофайл.

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

Теперь попробуем записать анимацию в видеофайл. Будем использовать для этого функцию getframe. Эта функция позволяет запоминать текущее изображение фигуры - фрейм.

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

  1. Создадим видеофайл с помощью функции Videowriter;
  2. Укажем количество кадров в секунду – фреймрейт;
  3. Откроем видеофайл;
  4. Организуем цикл записи через функцию writeVideo, принимающую на вход название файла и сам фрейм;
  5. Закроем видео.

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

Запустим скрипт и увидим, что видео записалось.

Рассмотрим ещё один пример – изменяющуюся во времени поверхность.

Пример 3. Изменяющаяся поверхность.

 

 

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

Сначала выполним разметку командой meshgrid, после чего получим соответственно матрицу значений искомой функции. Нарисуем поверхность командой surf, при этом ограничим вертикальную ось.

Получилось.

Теперь организуем анимацию через цикл while.

Будем изменять свойство ZData объекта S типа  Surf таким образом, чтобы волны двигались из центра. Запустим скрипт.

Теперь рассмотрим альтернативный способ отрисовки анимированных линий – объект типа animatedline.

Пример 4.1. Движение по спирали.

Также посмотрим, как изменять положение объектов других типов, в данном случае – объектов типа Text.

Создадим на осях объект типа animatedline. Изначально это объект, не имеющий данных для отображения. Эти данные можно добавить командой addpoints: добавим к линии a1 начало координат. Также нарисуем красный кружок известной командой plot, а также добавим текстовое поле командой text, указав левый верхний угол текстового поля, а также его содержимое – координаты текущей точки. 

Организуем анимацию движения по спирали уже отработанным способом: через цикл while. Двигаться будем по спирали, которая будет логарифмически расширяться. Командой addpoints будем добавлять новые точки в каждом цикле. У текстового поля будем изменять положение его верхнего левого угла и отображаемый текст. Красный кружок будет также двигаться по спирали. Запустим.

Работает.

Как можно догадаться, при длительной работе animatedline разрастается. Чтобы этой потенциальной проблемы избежать можно задать, сколько точек сохранять и отображать. Для этого определим свойство MaximumNumPoints.

Запустим ещё раз. Будет видно, что отображаются только ограниченное количество точек, при этом старые точки затираются. Это может быть полезно, когда вы хотите визуализировать в MATLAB данные, полученные с приборов в реальном времени

2-й подход к отображения анимации в MATLAB – посредством преобразований. 

Допустим применить преобразование сразу к группе объектов: например, подвинуть их на какое-то расстояние, повернуть их или масштабировать. Наши объекты  во-первых, не сгруппированы, а во-вторых, напрямую обращаться к ним как к изображениям не получится. Для этого существует класс transform. Объекты этого класса создаются на осях, и с ними уже можно проводить преобразования. 

Следует перенести объекты с осей axes на объект класса transform. Это можно сделать для отображаемых объектов в свойстве Parent, явно указав родителя, – объект класса transform. Сами преобразования можно осуществлять с помощью знакомых многим матриц преобразования размерами 4х4, которые содержат информацию о преобразовании: будь то трансляция, поворот или масштабирование. 

Эти матрицы можно создавать вручную, а можно воспользоваться функцией makehgtform, в которой следует явно указать тип преобразования и его параметры. Последний шаг - полученную матрицу следует записать в свойство Matrix объекта класса transform.

Организовав такие преобразования в цикле, мы и получим желаемую анимацию. 

Переходим к следующему примеру - движение по спирали преобразованием.

Пример 4.2. Движение по спирали преобразованием.

На этот раз будем использовать преобразование для группы из двух объектов: красного кружочка и текстового поля.

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

Заставим их двигаться с помощью преобразования. 

Теперь создадим объект класса transform на осях ax, явно указав родственную связь. Нарисуем также красный кружочек командой plot, также указав родственную связь. То же самое делаем и с текстовым полем. В цикле создаём матрицу преобразования. Это будет трансляция на x по оси x, на y по оси y и на 0 по оси z соответственно.Полученную матрицу запишем в свойство объекта h.

Запустим скрипт. Работает.

Пример 5. Табуретка.


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

Посмотрим, как нарисовать такой шедевр и как заставить эту конструкцию двигаться. Действовать будем так: сначала нарисуем один параллелепипед, потом нарисуем ножки, потом эллипсоид, соединим их в единый объект, поместим его в объект типа transform, после чего организуем в цикле сразу 3 типа преобразований одновременно: поворот,  трансляцию и масштабирование.

Для начала создадим функцию, которая подготавливает точки для рисования параллелепипеда. Проверим, правильно ли рисует параллелепипед?

Как видим – правильно. 

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

Проверим, корректно ли отобразили объект.

Отобразили правильно. 

Перейдем непосредственно к преобразованию. Создадим объект типа transform известной нам командой, укажем родителя. Организуем цикл, в нём создадим 3 матрицы, для поворота  относительно вертикальной оси, для трансляции и для масштабирования. Матрицы следует перемножать в определенном порядке: следует перемножить матрицу поворота на матрицу трансляций, и только потом на матрицу масштабирований. Теперь изменим Удалим лишний параллелепипед, который мы рисовали в начале.

Запустим скрипт. Всё работает. 

Видеообзор по теме решения систем Д/У описанный в публикации доступен по ссылке.

 

Предыдущие публикации по теме: 

Часть 1. Решение систем обыкновенных дифференциальных уравнений в среде MATLAB

Часть 2. Решение систем обыкновенных дифференциальных уравнений в среде MATLAB. Опции решателей odeXY

Часть 3. Решение систем обыкновенных дифференциальных уравнений в среде MATLAB. Выполнение скриптов в процессе решения и отслеживание событий

Теги

    11.08.2020

    Комментарии