Matlab - необязательный аргумент дескриптора, сначала для функций, подобных графику

Matlab включает в себя множество функций построения графиков, которые принимают необязательный аргумент, являющийся дескриптором оси для построения графика. В Интернете существует множество решений для добавления необязательных аргументов к пользовательским функциям (varargin, inputParser), однако они обычно требуют, чтобы необязательные аргументы приходили только после обязательных аргументов, тогда как функции построения графиков в matlab обычно имеют вид

plot(optional, mandatory, optional)

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

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

x = [1:10];
y = x.^2;
ax(1) = subplot(1, 2, 1);
ax(2) = subplot(1, 2, 2);

myplot(x, y);                 %Mandatory
myplot(x, y, 'r+');           %Mandatory, optional
myplot(ax(1), x, y);          %Optional, mandatory
myplot(ax(2), x, y, 'r+');    %Optional, mandatory, optional

У меня вопрос, какие методы мы можем использовать, чтобы подражать этому поведению?

2 ответа

Решение

Вы можете написать функцию, которая принимает varargin в качестве ввода. Затем вы проверяете количество аргументов. Если это меньше, чем 2 (или что-то еще, в зависимости от вашей функции), приведите ошибку или предупреждение. Затем проверьте class входных параметров.

Если class ваш первый вход 'matlab.graphics.axis.Axes'тогда ваша функция должна вызвать: plot(ax,___), Если это двойной, то это должен быть формат plot(X,Y,LineSpec),

Что-то в этом роде должно работать

function [] = myplot(varargin)

if nargin < 2
   error('Minimum two input must be given'); % You probably want something other than an error. This was just an example.
elseif nargin == 2
    % Code for plotting
    plot(x, y)
elseif nargin == 3
    if strcmp(class(varargin{1}),'matlab.graphics.axis.Axes')
       ax1 = varargin{1};
       x = varargin{2};
       y = varargin{3};
       plot(ax1, x, y)
    elseif isa(varargin{2}, 'double') && isa(varargin{3}, 'double') && isa(varargin{3}, 'char')
       x = varargin{1};
       y = varargin{2};
       LineSpec = varargin{3};
     else ...

PS! Вам не нужно делать x = varargin{1} и т.д., это было только для иллюстрации того, что представляет собой каждый из различных элементов ячейки, если if оценивает true,

Вы можете продолжить с "Аргументы пары имя-значение". Проверьте, является ли класс входного аргумента charи что он не может представлять что-либо, кроме имени параметра. Если это имя параметра, то вы знаете, что следующий аргумент является значением параметра.

Я обычно использую такой шаблон, который также используется многими функциями построения графиков, которые являются частью MATLAB:

function varargout = myplot(obj, varargin)

    % Check the number of output arguments.
    nargoutchk(0,1);

    % Parse possible axes input.
    [ax, args, ~] = axescheck(varargin{:}); %#ok<ASGLU>

    % Get handle to either the requested or a new axis.
    if isempty(ax)
        hax = gca;
    else
        hax = ax;
    end

    % At this point, hax refers either to a specified axis, or
    % to a fresh one if none was specified. args refers to the
    % remainder of any arguments passed in varargin.

    % Parse the rest of args

    % Make the plot in hax

    % Output a handle to the axes if requested.
    if nargout == 1
        varargout{1} = hax;
    end  

end

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

Он проверяет, является ли первый аргумент дескриптором оси. Если это так, то ax это ручка, и args это остальные входные аргументы. Если нет то ax пусто и args содержит все входные аргументы.

Надеюсь, это поможет!


Изменить: Больше информации о axescheck как просили.

Во-первых, вы можете увидеть расположение и исходный код для axescheck набрав which axescheck а также edit axescheck, Таким образом, вы можете увидеть, что именно он делает.

Синтаксис [AX, ARGS, NARGS] = AXESCHECK(ARG1, ARG2, ...),

Во-первых, он проверяет, ARG1 это ручка к оси. Если это так, он возвращается как AXостальные аргументы (ARG2, ...) возвращаются в ARGS, а также NARGS это значение nargin минус 1

Во-вторых, он проверяет, является ли какой-либо из входных аргументов парой параметр-значение с параметром. Parent, Если это так, то все пары параметр-значение с параметром Parent удаляются из списка. Указанная ось возвращается в AXостальные аргументы возвращаются в ARGS, а также NARGS это значение nargin минус количество удаленных аргументов.

Если ни одна из указанных выше осей не указана, то AX пустой, ARGS это только входные аргументы, и NARGS это значение nargin,

axescheck работает как с двойными маркерами старого стиля (Handle Graphics 1), так и с маркерами класса нового стиля (Handle Graphics 2) matlab.graphics.axis.Axes,

Он также проверяет, является ли предоставленный дескриптор дескриптором удаленного объекта, и выдает ошибку, если это так.

Он довольно широко используется во многих встроенных функциях построения графиков MATLAB - см., Например, hist.m, polar.m, surfl.m, bar3.m, comet.m, pie.m и много других.

Другие вопросы по тегам