Предположим, что я хочу обновить график новыми данными. Какой метод выбрать?
XDataSource
какое-то имя, обновите переменную и вызовите refreshdata
plot
и снова вызовите команду plot
.Set('Xdata',...')
Короткий ответ: всегда используйте Set('Xdata',...')
.
Пример кода:
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
y = sin(x.^3);
set(h,'XData',x,'YData',y);
end
Длинный ответ:
Существуют три релевантные меры, по которым следует выбрать лучший метод.
Теперь проанализируем возможные методы.
Метод (1) - refreshdatastrong >
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
set(h,'YDataSource','y')
set(h,'XDataSource','x')
y = sin(x.^3);
refreshdata(h,'caller');
end
M-lint немедленно выдает предупреждение в строке y=sin(x.^3)
The value assigned to variable `y` might be unused
Почему это происходит? refreshdata
использует eval
и m-lint
не может знать, что вы будете использовать y
. Кто-то, читающий ваш код, может также полностью удалить эту строку. Это произошло потому, что вы нарушили принцип инкапсуляции. refreshdata
обращается к переменным из рабочей области вызывающего. Другой способ взглянуть на это, предположим, что вы передаете дескриптор сюжета другой функции. Читатель не знает, почему на самом деле вы написали y = sin(x.^3);
и как это будет связано с обновлением сюжета.
Теперь давайте обсудим скорость/время выполнения. Взглянув на исходный код refreshdata
, вы заметите два уродливых for-loops, которые проходят через все графики, обрабатывая переменные в вашем пространстве. Вот первый:
% gather up all the objects to refresh
objs = {};
for k = 1:length(h)
obj = h(k);
objfields = fields(obj);
for k2 = 1:length(objfields)
% search for properties ending in DataSource
if strncmpi(fliplr(objfields{k2}),'ecruoSataD',10)
objs = {objs{:},obj, objfields{k2}};
end
end
end
Представьте, что у вас нет ни одного сюжета, а всего 100 сюжетов, и вы хотите обновить только первый. Это будет очень медленно, потому что для каждого из сюжетов вы пытаетесь найти тот, который вам нужен! (Я оставляю в качестве упражнения для читателя, чтобы выяснить, что такое ecruoSataD
, и как он используется.)
Даже если вы даете соответствующий сюжет в качестве аргумента, у вас все еще есть второй цикл, который выполняется eval
несколько раз. Не совсем эффективно. В конце я покажу сравнение времени.
Заключение: трудно понять, трудно рефакторировать, медленное время выполнения
Метод (2) - Удалить и переделать
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
set(h,'YDataSource','y')
set(h,'XDataSource','x')
y = sin(x.^3);
delete(h);
h = plot(x,y);
end
Этот метод совершенно понятен читателю. Вы удалили сюжет и нарисовали новый. Однако, как мы увидим из сравнения времени в конце, это самый медленный метод.
Заключение: легко понять, легко рефакторировать, очень медленное время выполнения
Метод (3) - set ('XData',..., 'YData')
Код действительно ясен. Вы хотите изменить два свойства вашего графика, XData
и YData
. И это именно то, что вы делаете. Кроме того, код работает очень быстро, как вы можете видеть из приведенного ниже сравнения.
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
y = sin(x.^3);
set(h,'XData',x,'YData',y);
end
Поскольку новый графический движок hg2 (R2014b и выше), вы также можете использовать синтаксис свойств для указания данных, если вы предпочитаете эти обозначения:
function PlotUpdate()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
y = sin(x.^3);
h.XData = x;
h.YData = y;
end
Заключение: легко понять, легко рефакторировать, быстро выполнить
Вот код сравнения времени
function PlotUpdateTimeCompare()
x = 0:.1:8;
y = sin(x);
h = plot(x,y);
set(h,'YDataSource','y')
set(h,'XDataSource','x')
y = sin(x.^3);
tic
for i=1:100
refreshdata(h,'caller');
end
toc
tic
for i=1:100
delete(h);
h = plot(x,y);
end
toc
tic
for i=1:100
set(h,'XData',x,'YData',y);
end
toc
end
И результаты:
Истекшее время - 0.075515 секунд.
Истекшее время - 0,179954 секунд.
Истекшее время составляет 0.002820 секунд.
refreshdata
работает в R2012b
Вы можете вызвать функцию drawnow
и сделать что-то вроде этого:
h = plot(nan);
for i = 1:n
y = ...
set(h,'YData',y);
drawnow %update the graph
end
Предположим, что я хочу обновить график новыми данными. Какой метод выбрать?
Если у вас есть несколько объектов линии в заданных осях, тогда Method:
- Установите для свойства XDataSource какое-то имя, обновите переменную и вызовите
refreshdata
генерирует ошибку в MATLAB R2012b. Соответствующий пример приведен в ответе Андрея.
В Mathworks была отправлена ошибка.