gusucode.com > 信号处理工具箱 - signal源码程序 > signal\signal\siggui\private\fvzoom.m

    function fvzoom(action,varargin)
%FVZOOM  Filter Viewer zoom function.
%  Contains callbacks for Zoom button group of Filter Viewer.
%    mousezoom
%    zoomout
%   Copyright (c) 1988-98 by The MathWorks, Inc.
%       $Revision: 1.1 $

if nargin < 3
    fig = gcf;
else
    fig = varargin{2};
end
ud = get(fig,'userdata');

if ud.pointer==2   % help mode
    if strcmp(action,'mousezoom')
        state = btnstate(fig,'zoomgroup',1);
        if state
              btnup(fig,'zoomgroup',1)  % toggle button state back to
                                        % the way it was
        else
              btndown(fig,'zoomgroup',1) 
        end
    end
    spthelp('exit','fvzoom',action)
    return
end

switch action

case 'mousezoom'
    state = btnstate(fig,'zoomgroup','mousezoom');
    if state == 1   % button is currently down
        set(fig,'windowbuttondownfcn','sbswitch(''fvzoom'',''mousedown'')')
        ud.pointer = 1;  
        set(fig,'userdata',ud)
        setptr(fig,'arrow')
    else   % button is currently up - turn off zoom mode
        set(fig,'windowbuttondownfcn','')
        ud.pointer = 0;
        set(fig,'userdata',ud)
        setptr(fig,'arrow')
    end

%--------
%  call will be either
%     fvzoom('zoomout')   - "Full View" button callback - zooms out all axes
%     fvzoom('zoomout',plots) - plots is a 6 element binary vector, containing
%                               a '1' in each location for which to zoom out
%           1 - magnitude
%           2 - phase
%           3 - group delay
%           4 - zeros & poles
%           5 - impulse response
%           6 - step response
%     fvzoom('zoomout',plots,fig) - same as above except with input figure

case 'zoomout'
    if nargin > 1
        plots = varargin{1};
    else
        plots = ones(6,1);
    end
    if nargin > 2
        fig = varargin{2};
    end
    Fs = evalin('base',ud.prefs.Fs,'1');

    if strcmp(ud.prefs.freqscale,'log')
        xlim1 = Fs/ud.prefs.nfft;
    else
        xlim1 = 0;
    end

    switch ud.prefs.freqrange
    case 1
       xlim = [xlim1 Fs/2];
    case 2
       xlim = [xlim1 Fs];
    case 3
       xlim = [-Fs/2 Fs/2];
    end

    plotIndex = find(ud.mainaxes == ud.ht.a);    
    if ud.prefs.tool.ruler & plots(plotIndex)
        % don't allow rulers to affect maximum axes limits computations
        ruler('hidelines',fig,'all')
    end

    for i=1:2
        if plots(i)
            set(ud.ht.a(i),'ylimmode','auto','xlim',xlim);
        end
    end

    if plots(3) & strcmp(get(ud.ht.a(3),'visible'),'on')
        gd_ylim = filtview('gd_ylim',ud.filt);
        set(ud.ht.a(3),'ylim',gd_ylim)
        set(ud.ht.a(3),'xlim',xlim)
    end
 
    if plots(4)
        set(ud.ht.a(4),'ylimmode','auto','xlimmode','auto');
        apos = get(ud.ht.a(4),'Position');
        set(ud.ht.a(4),'DataAspectRatio',[1 1 1],...
            'PlotBoxAspectRatio',apos([3 4 4]))

        if  ~isempty(ud.filt) 
            [xlim1,xlim2,ylim1,ylim2] = filtview('zeropolePlotLims',ud.filt);
            set(get(ud.ht.a(4),'xlabel'),'userdata',[xlim1 xlim2 ylim1 ylim2]);
        else
            set(get(ud.ht.a(4),'xlabel'),'userdata',[-1 1 -1 1]);
        end
    end

    if any(plots([5 6])) & ~isempty(ud.filt)
        tmax = -inf;
        for i = 1:length(ud.filt)
            if ~isempty(ud.filt(i).t)
                tmax = max([tmax; ud.filt(i).t(end)]);
            else
                tmax = max([tmax; 0]);
            end
        end
        xlim = [-1/Fs tmax+1/Fs];
    else
        xlim = [0 1/Fs];
    end
    if plots(5),set(ud.ht.a(5),'ylimmode','auto','xlim',xlim), end
    if plots(6),set(ud.ht.a(6),'ylimmode','auto','xlim',xlim), end

    visPlots = find(strcmp(get(ud.ht.a,'visible'),'on'));
    if ~isempty(visPlots)
        ud = filtview('setudlimits',ud,ud.ht.a,visPlots);
        set(fig,'userdata',ud)
    end

    if ud.prefs.tool.ruler & plots(plotIndex)
        ruler('showlines',fig,ud.focusline)
        ruler('newlimits',fig,plotIndex)
    end

%-------------- these are self callbacks:
case 'mousedown'

    ud.justzoom = get(fig,'currentpoint');
    set(fig,'userdata',ud)
    Fs = evalin('base',ud.prefs.Fs,'1');

    pstart = get(fig,'currentpoint');

    % don't do anything if click is outside mainaxes_port
    fp = get(fig,'position');   % in pixels already
    sz = ud.sz;
    toolbar_ht = ud.resize.topheight;
    left_width = ud.resize.leftwidth;
    mp = [left_width 0 ...
          fp(3)-left_width-sz.rw*ud.prefs.tool.ruler fp(4)-toolbar_ht];

    %click is outside of main panel:
    if ~pinrect(pstart,[mp(1) mp(1)+mp(3) mp(2) mp(2)+mp(4)])
        if ~ud.prefs.tool.zoompersist
            % if click was on Mouse Zoom button, don't turn off button
            % because it will get turned off by its own callback  
            zg = findobj(fig,'type','axes','tag','zoomgroup');
            zgPos = get(zg,'position');
            if ~pinrect(pstart,[zgPos(1) zgPos(1)+zgPos(3)/2 ...
                                zgPos(2) zgPos(2)+zgPos(4)])
                btnup(fig,'zoomgroup','mousezoom');
                fvzoom('mousezoom')
            end
        end
        return
    end

    r = rbbox([pstart 0 0],pstart);

    % Find out which axes was clicked in according to rules:
    % rule 1: click inside an axes - zoom in that axes
    % rule 2: current point is not in any axes - zoom in on axes most
    %         overlapping dragged rectangle
    open_axes = ud.ht.a(find(ud.prefs.plots));
    rects = [];
    target_axes = [];
    for i=1:length(open_axes)
        rects = [rects; get(open_axes(i),'position')];
        if pinrect(pstart,rects(i,[1 1 2 2])+[0 rects(i,3) 0 rects(i,4)])
            target_axes = open_axes(i);
        end
    end
    
    if isempty(open_axes)  % no visible plots
        return   % stay in zoom mode and return
    elseif isempty(target_axes)
        overlap = rectint(r,rects);
        overlap = overlap(:)...
              ./ (rects(:,3).*rects(:,4));
            % what percentage of the area of the axis is 
            %  covered by the dragged out rectangle?
        [maxoverlap,k] = max(overlap);
        if maxoverlap > 0
            target_axes = open_axes(k);
        end
    end

    if isempty(target_axes)
        return   % stay in zoom mode and return
    end
    oldxlim = get(target_axes,'xlim');
    oldylim = get(target_axes,'ylim');
    
    if all(r([3 4])==0)
        % just a click - zoom about that point
        p1 = get(target_axes,'currentpoint');

        xlim = get(target_axes,'xlim');
        ylim = get(target_axes,'ylim');

        switch get(fig,'selectiontype')
        case 'normal'     % zoom in
            xlim = p1(1,1) + [-.25 .25]*diff(xlim);
            ylim = p1(1,2) + [-.25 .25]*diff(ylim);
        otherwise    % zoom out
            % first do a full zoom out so we know 
            % the bounding rect (stored in ud.limits.xlim, .ylim)
            fvzoom('zoomout',ud.ht.a == target_axes,fig)
            ud = get(fig,'userdata');
            xlim = p1(1,1) + [-1 1]*diff(xlim);
            ylim = p1(1,2) + [-1 1]*diff(ylim);
        end
        
    elseif any(r([3 4])==0)  
        % zero width or height - stay in zoom mode and 
        % try again
        return

    else 
        % zoom to the rectangle dragged
        set(fig,'currentpoint',[r(1) r(2)])
        p1 = get(target_axes,'currentpoint');
        set(fig,'currentpoint',[r(1)+r(3) r(2)+r(4)])
        p2 = get(target_axes,'currentpoint');
        
        xlim = [p1(1,1) p2(1,1)];
        ylim = [p1(1,2) p2(1,2)];
    end

    axesIndex = find(target_axes == ud.ht.a);
    newxlim = inbounds(xlim,ud.limits(axesIndex).xlim);
    newylim = inbounds(ylim,ud.limits(axesIndex).ylim);
    
    switch target_axes
    
    case {ud.ht.a(1), ud.ht.a(2), ud.ht.a(3)}
        xdiff = Fs / (4*ud.prefs.nfft);
    case ud.ht.a(4)
        xdiff = 0;
    case {ud.ht.a(5), ud.ht.a(6)}
        xdiff = .1/Fs;
    end

    if target_axes ~= ud.ht.a(4)
        if diff(xlim) > xdiff
           set(target_axes,'xlim',newxlim)
        end
        if diff(ylim) > 0
           set(target_axes,'ylim',newylim)
        end
    else		% Pole-zero
        apos = get(target_axes,'Position');
        set(get(ud.ht.a(4),'xlabel'),'userdata',[newxlim newylim]);
        [newxlim,newylim] = newlims(apos,newxlim,newylim);
          set(target_axes,'xlim',newxlim,'ylim',newylim)
    end
    ud.limits(axesIndex).xlim = newxlim;
    ud.limits(axesIndex).ylim = newylim;
    set(fig,'userdata',ud)    
    
    if ~ud.prefs.tool.zoompersist
        setptr(fig,'arrow')
        set(fig,'windowbuttondownfcn','')
        btnup(fig,'zoomgroup','mousezoom');
        ud.pointer = 0;  
        set(fig,'userdata',ud)
    end
    if ud.prefs.tool.ruler & (ud.mainaxes == target_axes)
        ruler('newlimits',fig,find(ud.mainaxes == ud.ht.a),ud.focusline)
    end
    set(fig,'currentpoint',ud.justzoom)
end


%================================================================

function [newxlim,newylim] = newlims(apos,xlim,ylim);

dx = diff(xlim);
dy = diff(ylim);

if dx * apos(4)/apos(3) >= dy   % Snap to the requested x limits, expand y to fit
   newxlim = xlim;
   newylen = apos(4)/apos(3) * dx;
   newylim = mean(ylim) + [-newylen/2 newylen/2];
else
   newylim = ylim;
   newxlen = apos(3)/apos(4) * dy;
   newxlim = mean(xlim) + [-newxlen/2 newxlen/2];
end

if diff(newxlim) <= 0
   newxlim = xlim;
end
if diff(newylim) <= 0
   newylim = ylim;
end