www.gusucode.com > mbcexpr 工具箱 matlab 源码程序 > mbcexpr/@cglookup/guiInvertTable.m

    function [Tfill,OK] = guiInvertTable(Tinv,CGP)
%guiInvertTable table inversion dialog
%    OK = guiInvertTable(LT,CGP)

%  Copyright 2013-2013 The MathWorks, Inc. and Ford Global Technologies, Inc.

Tlist = filterbytype(info(CGP), cgtypes.cgtabletype); 
OK = false;
Tfill = [];
[pTableList,TableListString] = InversionFilter(Tinv,Tlist);
% check that there are tables to invert
if ~isempty(pTableList)
    
    % need 'HelpCode'
    d = mbcgui.container.Dialog('Name', 'Table Inversion',...
        'Size', [400, 500],...
        'HelpCode','cgInvertTable',...
        'Buttons', 'OK_CANCEL_HELP');

    pUD = xregGui.RunTimePointer;
    d.Content = createLayout(d.Figure,pUD);
    
    ud = pUD.info;
    set(ud.tableCombo,'String',TableListString,'Value',1);
    ud.pTableList = pTableList;
    ud.Tinv = Tinv;
    ud.Dialog = d;
    pUD.info = ud;
    
    % update the GUI
    update(pUD)
    
    % Does the waitfor
    closeMode = d.showDialog();
    
    % The tag is set to either 'OK' or 'CANCEL'
    switch closeMode
        case 'OK'
            OK = true;
            % get filled table from user data
            ud = pUD.info;
            % update on heap
            xregpointer(ud.TFill);
            Tfill = ud.TFill;
        case 'CANCEL'
    end
    delete(d)
else
    h = errordlg(sprintf('There are no tables to fill with an inversion of %s.', ...
        iTableLabel(Tinv)), 'Inversion Error', 'modal');
    waitfor(h);
end


function lyt = createLayout(Parent,pUD)
%createLayout create dialog layout
%   lyt = createLayout(Parent,pUD)
%   pUD is an xregGui.RunTimePointer to contain user data


% popup for tables
ud.tableCombo = uicontrol('Parent',Parent,...
    'Style','popupmenu',...
    'Callback',{@iCallBack,pUD},...
    'BackgroundColor','w',...
    'Tag','TableSelectCombo');
tableLabel = xregGui.labelcontrol('parent',Parent,...
    'LabelAlignment','left','gap',5,...
    'control', ud.tableCombo ,...
    'ControlSize',180,...
    'string','Table to fill:');
ud.inversionInfo = uicontrol('Parent',Parent,...
    'Style','text',...
    'HorizontalAlignment','left');


%Multiple values
ud.multiCombo = uicontrol('Parent',Parent,...
    'Style','popupmenu',...
    'String',{'Minimum','Maximum','Intermediate','Least squares'},...
    'Value',4,...
    'Callback',{@iCallBack,pUD},...
    'BackgroundColor','w',...
    'Tag','ResolveMethodCombo');
multilabel = xregGui.labelcontrol('parent',Parent,...
    'LabelAlignment','left','gap',5,...
    'control', ud.multiCombo ,...
    'ControlSize',180,...
    'string','Resolve nonunique inverses with:');



% Axes and plot type combo box
complayout = mbcgui.container.layoutpanel(...
    'Parent', Parent, ...
    'Title','Inversion Error',...
    'BorderType', 'beveledin');
ud.ComparisonPane = cgtools.comparisonpane('Parent', complayout);
% display inversion error by default
ud.ComparisonPane.PlotType = 2;
plottypecombo = ud.ComparisonPane.createComboController(...
    'Parent', complayout,...
    'Tag', 'ErrorPlotTypeCombo');
cblabel = xregGui.labelcontrol('parent',complayout,...
    'LabelAlignment','left','gap',5,...
    'control', plottypecombo ,...
    'ControlSize',180,...
    'string','Plot type:');

DisplayLyt = xreggridbaglayout(complayout,...
    'dimension',[2,1],...
    'rowsizes',[20,-1],...
    'gap',2, ...
    'elements',{cblabel, ud.ComparisonPane });
set(complayout, 'LayoutComponent', {DisplayLyt});


lyt = xreggridbaglayout(Parent,...
    'dimension',[4,1],...
    'rowsizes',[20,20,40,-1],...
    'gap',5, ...
    'elements',{tableLabel, multilabel,ud.inversionInfo,complayout});
pUD.info = ud;


function iCallBack(~,~,pUD)
% call back function pass user data to update
update(pUD)

function update(pUD)
%update update table inversion

ud = pUD.info;
% get 
tabNumber = get(ud.tableCombo,'Value');
Tfill = info(ud.pTableList( tabNumber ));
flag = get(ud.multiCombo,'Value');

% always start from base table values
% ud.Tfill.info = ud.BaseTable;

[signal,p1,p2]=commonInputs(Tfill,ud.Tinv);
if ~isscalar(signal)
    
    % perform table inversion for 2D lookup
    [Tfill,err] = tableinversion(Tfill,ud.Tinv,signal(2), signal(1), 1,flag);
else
    % perform table inversion for 1D lookup
    [Tfill,err] = tableinversion(Tfill, ud.Tinv,flag);
end

set(ud.inversionInfo,'String',sprintf('Invert %s: %s to %s',iTableLabel(ud.Tinv),p1.getname, p2.getname))

if ~isempty(err)
    % disable 
    errordlg(err,'Table Inversion Error','modal');
    disableButtons(ud.Dialog,'OK');
else
    enableButtons(ud.Dialog,'OK');
    
    plotInversion(ud,Tfill,ud.Tinv,signal,p2)
    ud.TFill = Tfill;
    pUD.info = ud;
    
end


function [signal,p1,p2]=commonInputs(T1,T2)

p1 = get(T1,'axesptrs');
p2 = get(T2,'axesptrs');
if length(p1)==2
    % determine the common signal for 2D tables
    OK1 = ismember(p1,p2);
    OK2 = ismember(p2,p1);
    % need to invert as axes ptrs are stored as X,Y whereas tables are stored as rows(Y)/cols(X).
    p1 = p1(~OK1);
    p2 = p2(~OK2);
    
    signal = [find(~OK1) find(~OK2)];
else
    signal = 0;
end
function plotInversion(ud,Tfill,Tinv,signal,p2)
%plotInversion update the comparison plot for inversion
%   plotInversion(ud,Tfill,Tinv,signal,p2)
%     Tfill(Tinv(Xinput,Y),Y) -> XOutput
%     Tfill(X,Tinv(X,Yinput)) -> YOutput
%   A perfect inversion should have Xinput = Xoutput. 


TfillVal = get(Tfill,'values');
TinvVal = get(Tinv,'values');

cgm = cgmathsobject;

if isscalar(signal)
    % 1D Table comparison
    
    fLinear1 = gethandle(cgm, 'linear1');
    
    
    % our x axis is the input to the inverted table
    xptr = get(Tinv,'axesptrs');
    xname = xptr.getname;
    
    TfillBP = get(Tfill,'allbreakpoints');
    TinvBP = get(Tinv,'allbreakpoints');
    
    % For the input, use 51 points, evenly covering the range of the inverted table input
    plotX = linspace(TinvBP(1),TinvBP(end),51);
    
    % Our first output is the same as the input.
    Input = plotX;
    
    % Get the output of the inverted table over this range.
    TinvValEx = fLinear1(TinvBP,TinvVal,plotX);
    % Now get the output from the new table from these inputs.  This is our
    % second output.
    Output = fLinear1(TfillBP,TfillVal,TinvValEx);
    
    yname = [];
    plotY = [];
    
else
    % 2D table comparison
    fExtInterp2 = gethandle(cgm,'extinterp2');
    fLinear2 = gethandle(cgm, 'linear2');
    
    
    xptr = get(Tinv,'axesptrs');
    xname = xptr(1).getname;
    yname = xptr(2).getname;
    
    TfillBPx = i_getbreakpoints(Tfill,'x');
    TfillBPy = i_getbreakpoints(Tfill,'y');
    
    TinvBPx = i_getbreakpoints(Tinv,'x');
    TinvBPy = i_getbreakpoints(Tinv,'y');
    
    TinvVal = get(Tinv,'values');
    TinvVal = TinvVal';  % transpose so that it is length(x) * length(y)
    
    % For our input, we'll use 51 points in each direction,
    % evenly covering the ranges of the inverted table inputs
    plotX = linspace(TinvBPx(1),TinvBPx(end),51);
    plotY = linspace(TinvBPy(1),TinvBPy(end),51);
    
    % Get the output of the inverted table over this range
    TinvValEx = fLinear2(TinvBPx,TinvBPy,TinvVal,plotX,plotY);
    
    [X,Y] = ndgrid(plotX,plotY);
    
    % Now calculate the output of the new table over this range, taking care to
    % match up the correct signals.
    if isequal(signal,[2,2])
        % Y = Tfill( X , Tinv )
        Input = Y;
        Output = fExtInterp2(TfillBPx,TfillBPy,TfillVal,X,TinvValEx);
    elseif isequal(signal,[2,1])
        % X = Tfill( Y , Tinv )
        Input = X;
        Output = fExtInterp2(TfillBPx,TfillBPy,TfillVal,Y,TinvValEx);
    elseif isequal(signal,[1,2])
        % Y = Tfill( Tinv , X )
        Input = Y;
        Output = fExtInterp2(TfillBPx,TfillBPy,TfillVal,TinvValEx,X);
    elseif isequal(signal,[1,1])
        % X = Tfill( Tinv , Y )
        Input = X;
        Output = fExtInterp2(TfillBPx,TfillBPy,TfillVal,TinvValEx,Y);
    end
end

% Note transposes to get orientations correct
ud.ComparisonPane.setdata(Input',Output', plotX, xname, plotY, yname);
ud.ComparisonPane.setDataNames([p2.getname,' Input'],[p2.getname,' Output']);



%----------------------------------
function bp = i_getbreakpoints(LT,expr)

normptr = get(LT,expr);
vals = normptr.get('values');
bp = normptr.invert(0:vals(end));





function str = iTableLabel(LT)

pInputs = get(LT,'axesptrs');
str = sprintf('%s(%s)',getname(LT), strjoin( fliplr(pveceval(pInputs,@getname)),',' ));