【问题标题】:Matlab - Optional handle argument first for plot like functionsMatlab - 可选句柄参数首先用于类似函数的绘图
【发布时间】:2017-01-14 21:54:15
【问题描述】:

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

我的问题是,我们可以使用哪些技术来模拟这种行为?

【问题讨论】:

    标签: matlab plot optional-arguments


    【解决方案1】:

    您可以编写一个以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,并且它不能代表参数名称以外的其他内容。如果它是参数名称,那么您知道下一个参数是参数值。

    【讨论】:

    • 我有一种感觉,这将是它的完成方式,但希望可以有更优雅的东西。
    • @bhillam 我看不出这有什么不雅之处? MATLAB 不允许函数重载。无论如何,这将要求您编写 2 个函数。
    • 如果可能有大量的参数组合,会有一些代码重复会很快变得混乱。不幸的是,无论使用何种技术,这似乎都是一个问题。我接受了这个答案,因为它解决了如何在强制参数之前包含可选参数,与内置绘图函数一样徒劳无功,尽管 Sam Roberts 答案的某些元素也很有用。
    【解决方案2】:

    我通常使用这样的模式,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 的更多信息。

    首先,您可以通过键入which axescheckedit axescheck 来查看axescheck 的位置和源代码。通过这种方式,您可以准确地看到它的作用。

    语法是[AX, ARGS, NARGS] = AXESCHECK(ARG1, ARG2, ...)

    首先,它检查ARG1 是否是轴的句柄。如果是,则返回为AX,其余参数(ARG2, ...)在ARGS 中返回,NARGSnargin 的值减1。

    其次,它检查任何输入参数是否是带有参数Parent 的参数值对。如果是这样,则从列表中删除所有带有参数Parent 的参数-值对。指定轴在AX中返回,其余参数在ARGS中返回,NARGSnargin的值减去被移除的参数个数。

    如果以上两种方式都没有指定轴,则AX为空,ARGS只是输入参数,NARGSnargin的值。

    axescheck 可与 matlab.graphics.axis.Axes 类的旧式(句柄图形 1)双句柄和新式(句柄图形 2)句柄一起使用。

    它还检查提供的句柄是否是已删除对象的句柄,如果是则抛出错误。

    它在许多内置的 MATLAB 绘图函数中得到广泛使用 - 例如,请参阅 hist.m, polar.m, surfl.m, bar3.m, comet.m, pie.m 和许多其他函数。

    【讨论】:

    • 这个答案似乎很有希望,但可以通过有关未记录的 axescheck 功能的其他信息来改进 - 粗略的谷歌搜索没有出现任何结果。例如axescheck(varargin{:}) 与 isa(varargin{1}, 'matlab.graphics.axis.Axes') 有何不同?
    • 我总是很难选择一个答案 - 我希望我能再次投票给你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多