2016-09-07 33 views
7

Matlab包含許多繪圖函數,它們將可選參數作爲要繪製的軸的句柄。在線向用戶定義的函數(varargin,inputParser)添加可選參數的方法很多,但通常要求可選參數僅在強制參數之後出現,而matlab中的繪圖函數通常採用以下形式: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 

我的問題是,我們可以用什麼方法來模擬這種行爲?

回答

4

您可以編寫一個函數,將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,並且它不能代表參數名稱以外的內容。如果它是一個參數名稱,那麼你知道下一個參數是一個參數值。

+0

我有一種感覺,這將是它的方式,但希望更優雅的東西是可能的。 – bhillam

+0

@bhillam我不明白這有什麼不雅之處? MATLAB不允許函數超載。無論如何,這需要你編寫2個函數。 – patrik

+0

如果可能有大量的參數組合,將會有一些代碼重複會非常快速地變得混亂。不幸的是,無論使用何種技術,這似乎都是一個問題。 我已經接受了這個答案,因爲它解決了如何在強制性參數之前包含可選參數,與內置劇情函數相同,儘管Sam Roberts的答案的一些元素也很有用。 – bhillam

7

我通常使用這樣的圖案,其也被許多的繪圖功能,這些功能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適用於舊式(Handle Graphics 1)雙手柄以及matlab.graphics.axis.Axes類的新式(Handle Graphics 2)手柄。

它還會檢查提供的句柄是否爲已刪除對象的句柄,如果是則拋出錯誤。

它在很多內置的MATLAB繪圖功能中有相當廣泛的應用 - 例如參見hist.m, polar.m, surfl.m, bar3.m, comet.m, pie.m等等。

+0

這個答案看起來很有希望,但可以通過關於無證axischeck函數的附加信息加以改進 - 粗略的googling沒有找到任何結果。例如axescheck(varargin {:})與isa(varargin {1},'matlab.graphics.axis.Axes')有什麼區別? – bhillam

+1

@bhillam請參閱我的編輯瞭解'axescheck'的更多信息。 –

+0

我總是感到不好,只能選擇一個答案 - 我希望我能再次讚揚你的。 – bhillam