MATLAB.Exponenta
–Û·Ë͇ Matlab&Toolboxes

Приложения с GUI и дескрипторная графика

Дескрипторная графика

Назначение дескрипторной графики

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

·   высокоуровневые графические функции (plot, surf, mesh и многие другие);

·   интерактивную среду Plotting Tools, компонента которой Plot Editor (редактор графиков) также позволяет изменять свойства элементов графика;

·   специализированные функции и средства ToolBox для графического отображения характеристик исследуемых объектов и результатов.

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

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

x = 0:0.2:10;

y = cos(x);

plot(x, y, 'LineWidth', 2, 'Marker', 'o' , 'MarkerSize', 10)

В данном примере при построении графика функцией plot заданы следующие свойства линии:

·   LineWidth - толщина линии 2пт.;

·   Marker - тип маркера (кружок);

·   MarkerSize - размер маркера 10пт.

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

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

Иерархия графических объектов

Зададимся вопросом, что происходит при выполнении следующих команд

x = 0:0.2:10;

y = cos(x);

plot(x, y)

Разумеется, строится график функции, но при рассмотрении дескрипторной графики нам потребуется другой взгляд на этот процесс и соответствующая терминология. Если не было открыто графических окон, то высокоуровневая графическая функция plot создала ряд графических объектов: сначала графическое окно, затем оси и, наконец, линию. Все графические объекты MatLab выстроены в определенную иерархию, оси являются потомком графического окна и не могут существовать сами по себе. В свою очередь, графическое окно - предок для осей. Аналогичным образом дело обстоит с линией. Она является потомком осей, а оси - ее предком. Одновременно может существовать несколько графических окон, каждое из них может содержать и несколько потомков (осей), а каждые оси по нескольку потомков (линий, поверхностей и других графических объектов), например:

x = 0:0.1:5;

f = exp(-x).*sin(x);

g = exp(-x).*sin(2*x);

subplot(2, 1, 1)

plot(x, f, x, g)

subplot(2, 1, 2)

mesh(rand(10))

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

Графических объектов достаточно много, их иерархическая структура представлена на рис. 1 для MatLab версии 7.

 

 

Рис. 1. Иерархическая структура графических объектов

 

Мы последовательно рассмотрим приемы работы с ними, в соответствии с цветовой заливкой на рис. 1. Сначала - оси (Axes), графические окна (Figure) и рисованные объекты (Plot Objects), поскольку, как правило они создаются в результате работы высокоуровневых графических функций plot, bar, surf и др. Затем мы обратимся к свойствам поясняющих объектов (Annotation Objects), которые являются потомками специальных невидимых осей (Hidden Annotation Axes), служащих для размещения текстовых примечаний, стрелок, текстовых выносок и других объектов. После этого мы займемся базовыми объектами, включающими линии, полигональные объекты и ряд других.

Рисованные и базовые объекты могут быть сгруппированы для удобства работы с ними и выполнения однотипных операций. Этот вопрос мы обсудим при конструировании сгруппированных объектов (Group Objects).

Потомки графического окна - панели и элементы пользовательского интерфейса -нужны при создании приложений с графическим интерфейсом пользователя, которому посвящен раздел "Приложения с GUI".

Перед тем, как перейти к основным приемам работы с графическими объектами и управлению их свойствами, мы обратимся к двум важным вопросам.

Текущий графический объект; указатели на объекты

Предположим, что открыто несколько графических окон, содержащие одну или несколько пар осей. На какую из них произойдет вывод графика, например функцией plot? Оказывается, что на текущие оси, т.е. в последние созданные, или те, которые были сделаны текущими при помощи щелчка мышью по ним. Если Ваше приложение осуществляет вывод на разные оси, то необходим способ, который позволяет делать оси (да и любые объекты: графические окна, линии и поверхности) текущими в ходе работы приложения.

Для создания графического окна служит функция figure. Вызов ее с выходным аргументом приводит не только к появлению графического окна, но и записи в него указателя на созданный объект - графическое окно. Создадим два графических окна, записав указатели на них в переменные hF1 и hF2:

hF1 = figure

hF2 = figure

Теперь для того, чтобы в любом месте приложения сделать текущим графическое окно с указателем hF1, достаточно обратится к функции figure со входным аргументом - указателем на окно:

figure(hF1)

При этом графическое окно не только станет текущим, но и расположится поверх остальных окон.

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

hA1 = axes

Построим теперь на этих осях графики двух функций красным и зеленым цветами, обратившись к plot с выходным аргументом, в который будет записано значение указателя на линию:

x = -3:0.1:3;

f = sin(x.^2);

g = sin(x).^2;

hL1 = plot(x, f, 'r')

hold on

hL2 = plot(x, g, 'g')

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

delete(hL1)

График первой функции удалился.

Для дальнейшего построения графиков на осях c указателем hA1 в любом месте программы достаточно сделать их текущими

axes(hA1)

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

delete(hA1)

Аналогичным образом, удаление графического окна вызовет исчезновение всех объектов, лежащих ниже в иерархии: осей, размещенных в этом окне, и всех принадлежащих им поверхностей и линий. Разумеется, объекты можно не только удалять при помощи delete, но и копировать, или осуществлять поиск одного или нескольких объектов с нужными свойствами.

Мы разобрали, как делать объект текущим, зная указатель на него. Обратная задача - получение указателя на текущий объект - решается с привлечением функции gco (сокращение от get current object):

hCO=gco

Эта функция позволяет определить, какой объект сделан текущим, скажем щелчком мыши. Для получения указателя на текущие оси, и графическое окно служат две функции: gca (сокращение от get current axes) и gcf (сокращение от get current figure), соответственно. Их можно использовать, например, для установки значений свойствам только что созданных осей или графического окна.

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

Доступ к значениям свойств графических объектов

Для задания значений свойствам графических объектов служит функция set, которая вызывается от указателя на объект, и пары 'НазваниеСвойства' - значение:

set(h, 'НазваниеСвойства', значение)

или от нескольких пар для установки значений ряду свойств:

set(h, 'НазваниеСвойства1', значение1, 'НазваниеСвойства2', значение2, :)

 

Приведем простой пример: требуется установить определенную толщину (5пт) линии графика, построенного в некотором месте программы при помощи функции plot:

hL = plot(x,y)

Знание указателя на линию hL и название соответствующего свойства LineWidth позволяет легко решить эту задачу:

set(hL, 'LineWidth',5)

 

Нередко возникает и обратная задача - получить значение того или иного свойства графического объекта. Для этих целей предназначена функция get, которая вызывается от указателя на интересующий объект и названия свойства. Ее выходным аргументом является значение данного свойства.

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

W = get(hL, 'LineWidth')

set(hL, 'LineWidth', W+2)

 

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

 

Свойства осей

Предположим, приложение должно разместить в графическом окне три пары осей так, как показано на рис. 2.

 

Рис. 2. Графическое окно с тремя парами осей

Создадим графическое окно, сохранив указатель на него в переменной hF:

hF = figure

затем первую пару осей

hA1 = axes

Расположим оси с указателем hA1 вверху окна, прибегнув к их свойству Position. Его значением является вектор из четырех чисел [x y width height], где

·   x - абсцисса левого нижнего угла осей;

·   y - ордината левого нижнего угла осей;

·   width - ширина осей;

·   height - высота осей.

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

set(hA1, 'Position', [0.1 0.6 0.8 0.3])

Аналогичным образом создадим еще две пары осей и установим их свойство Position в подходящие значения:

hA2 = axes

set(hA2, 'Position', [0.1 0.1 0.3 0.3]);

hA3 = axes

set(hA3, 'Position', [0.6 0.1 0.3 0.3]);

В результате получаем графическое окно, приведенное на рис. 2, и указатели hF, hA1, hA2, hA3 на все созданные графические объекты. Эти указатели следует использовать перед выводом на оси, делая нужную пару осей текущей, например

axes(hA2)

plot(x, y)

MatLab допускает достаточно гибкое управление положением осей. Так, привлечение свойства OuterPosition позволяет избежать выхода заголовка и подписей к осям за пределы графического окна. Его значением является вектор из четырех элементов [x y width height], смысл которых такой же, как и у свойства Position. Отличие поясняет рис. 4.

 

Рис .4. Отличие Position от OuterPosition

 

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

При изменении размеров графического окна, размеры осей изменяются автоматически. Способ изменения размеров осей может быть основан либо на значении свойства Position, либо OuterPosition - в зависимости от значения свойства ActivePositionProperty: 'outerposition' (по умолчанию), либо 'position'.

 

Примечание

Для быстрого набора приведенных команд в командной строке MatLab 7 Вы можете использовать клавишу Tab, например Вы напечатали set(hA,'P и нажали Tab - появляется всплывающая подсказка с одним из возможных вариантов продолжения команды, в которой стрелками или мышью выбирается нужная строка.

 

Масштабы осей несколько отличаются, но иногда удобно задать равные масштабы, например при рисовании круга. За соотношение масштабов осей отвечают: свойство DataAspectRatio и сопутствующее ему DataAspectRatioMode. Если значением DataAspectRatioMode является 'auto', то соотношение выбирается автоматически так, чтобы оси занимали бόльшую площадь. Установка свойства DataAspectRatioMode в 'manual' означает, что соотношение масштабов будет определятся значением DataAspectRatio. Требуемое соотношение масштабов по осям x, y и z определяется вектором из трех элементов, который задается в качестве значения свойства DataAspectRatio (при этом свойство DataAspectRatioMode автоматически устанавливается в 'manual') При желании, можно вернуться к автоматическому выбору масштаба, установив DataAspectRatioMode в 'auto'. Мы обсудили сейчас характерную ситуацию для тех свойств, которые подбираются автоматически для получения лучшего вида графика с учетом отображаемых данных. Эти свойства снабжены сопутствующими, их имена оканчиваются словом Mode. Таких свойств достаточно много, они отвечают за управление камерой для обзора трехмерных объектов, сетку, разметку координатных осей, их пределы.

Для задания соотношений размеров осей предназначено свойства PlotBoxAspectRatio и PlotBoxAspectRatioMode. Значением свойства PlotBoxAspectRatio должен быть вектор из трех элементов с относительными размерами осей, а PlotBoxAspectRatioMode принимает значение 'auto' либо 'manual'.

Очевидно, что не всегда значения свойств Position (или OuterPosition), DataAspectRatio, PlotBoxAspectRatio и пределы осей будут согласованы. В разделе "Справочник свойств графических объектов" в подразделе "Свойства осей" приведено взаимное согласование этих и других свойств, отвечающих за размеры и положение осей. Кроме того, если ширина и высота, указанные в Position или OuterPosition не согласуются с PlotBoxAspectRatio, то оси занимают максимальную площадь в выделенном для них прямоугольнике с учетом заданных относительных размеров.

Названия ряда свойств осей начинаются с одной из букв X, Y, Z. Эти свойства служат для задания вида каждой оси по отдельности. Наличие сетки на осях определяется значениями свойств XGrid, YGrid и ZGrid. Эти свойства могут принимать только два значения 'on' или 'off' (установлено по умолчанию). Отобразим, в нашем примере (см. рис. 2) на верхних осях линии сетки, перпендикулярные оси y:

set(hA1, 'YGrid', 'on')

Для отображения линий сетки по обеим направлениям в каждой из нижних пар осей последовательно вызваем set:

set(hA2, 'XGrid', 'on', 'YGrid', 'on')

set(hA3, 'XGrid', 'on', 'YGrid', 'on')

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

set([hA2 hA3], 'XGrid', 'on', 'YGrid', 'on')

Линии сетки совпадают с координатами разметки соответствующей оси, которая выбирается автоматически. Для задания координат разметки осей x, y и z служат, соответственно, свойства XTick, YTick и ZTick, значениями которых является вектор возрастающих значений координат, или пустой массив [], если требуется скрыть разметку:

set(hA1, 'XTick', 0:0.05:1)

set(hA1, 'YTick', [])

Как только координаты разметки оси x заданы, автоматический режим их выбора выключается. При этом свойство XTickMode, сопутствующее XTick, принимает значение 'manual'. Для перехода к автоматической разметки осей, следует установить свойству XTickMode значение 'auto' при помощи функции set. Аналогичные свойства YTickMode и ZTickMode связаны со свойствами YTick и ZTick. Числовые подписи к разметке можно заменить на текстовые, задействуя свойства XTickLabel, YTickLabel, ZTickLabel, XTickLabelMode, YTickLabelMode и ZTickLabelMode.

Линии сетки не обязательно должны отображаться штриховыми линиями. Тип линии зависит от значения свойства GridLineStyle: '-' (сплошная), '--' (штриховая), ':' (пунктирная), '-.' (штрихпунктирная) или 'none' (отсутствие линий).

Кроме основной сетки, можно нанести вспомогательную, например так, как на рис. 4. Ее вид определяется свойствами, названия которых отличаются словом Minor от названия соответствующих свойств основной сетки:

hF = figure

hA = axes

set(hA, 'XGrid', 'on', 'YGrid', 'on', 'GridLineStyle', '-')

set(hA, 'XMinorGrid', 'on', 'YMinorGrid', 'on')

 

Рис. 4. Основная и вспомогательная сетки

 

Пределы осей выбираются автоматически в зависимости от границ значений визуализируемых данных, если соответствующее свойство XLimMode, YLimMode, или ZLimMode имеет значение 'auto', либо задаются свойствами XLim, YLim, ZLim. Значениями этих свойств должен быть вектор из двух элементов с пределами соответствующей оси.

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

t = 0:0.01:2*pi;

x = sin(t);

y = cos(t);

hA = axes;

plot(x, y)

set(hA, 'DataAspectRatio', [1 1 1])

set(hA, 'PlotBoxAspectRatio', [1 2 1])

set(hA, 'XLim', [-0.8 0.8])

set(hA, 'YLim', [-0.9 0.9])

 

Бывают случаи, когда требуется осуществить вывод, например поверхности, в графическое окно и не отображать оси так, как на рис. 5. Согласно иерархии объектов, поверхности являются потомками осей и не могут существовать без них. Но оси можно сделать невидимыми, установив их свойство Visible в значение 'off':

u = (-2*pi:0.1*pi:2*pi)';

v = -2*pi:0.1*pi:2*pi;

X = 0.3*u*cos(v);

Y = 0.3*u*sin(v);

Z = 0.3*u*ones(size(v));

hF = figure

hA = axes

surf(X, Y, Z)

set(hA, 'Visible', 'off')

Рис. 5. Использование невидимых осей для вывода в графическое окно

 

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

Мы рассмотрели некоторые свойства осей и установку их значений при помощи set. Если требуется создать оси определенного вида, то пары 'НазваниеСвойства' - значение можно указывать в качестве входных аргументов функции axes, но указатель на оси лучше сохранить - он может понадобиться впоследствии для изменения значений свойств осей:

hA = axes('XGrid', 'on', 'GridLineStyle', '-', 'XMinorGrid', 'on')

Сгруппированные по назначению свойства осей приведены в разделе "Справочник свойств графических объектов". Они предоставляют полный доступ к свойствам осей и позволяют изменять их вид по своему усмотрению, например так, как на рис 6:

 

Рис. 6. Пример изменения свойств осей


Поиск по сайту:

Система Orphus

Яндекс.Метрика