📄 zoomsafe.m
字号:
function theResult = zoomsafe(varargin)
% zoomsafe -- Safe zooming with the mouse.
% zoomsafe('demo') demonstrates itself with an interactive
% line. Zooming occurs with clicks that are NOT on the line.
% zoomsafe('on') initiates safe-zooming in the current window.
% Zooming occurs with each click in the current-figure, except
% on a graphical object whose "ButtonDownFcn" is active.
% zoomsafe('on', 'all') applies any new axis limits to all the
% axes in the figure. For companion axes having exactly the
% same 'XLim' range as the one that was clicked, the 'YLim'
% range remains intact. The same synchronization is invoked
% for corresponding 'YLim' situations as well.
% zoomsafe('all') same as zoomsafe('on', 'all').
% zoomsafe (no argument) same as zoomsafe('on').
% zoomsafe('off') turns it off.
% zoomsafe('out') zooms fully out.
% zoomsafe(theAmount, theDirection) applies theAmount of zooming
% to theDirection: 'x', 'y', or 'xy' (default).
% Note: when zooming actually occurs, this routine returns
% logical(1); otherwise, logical(0).
%
% "Click-Mode" (Macintosh Action) Result
% "normal" (click) Zoom out x2, centered on click.
% "extend" (shift-click) Zoom in x2, centered on click.
% "alt" (option-click) Center on click without zooming.
% "open" (double-click) Revert to unzoomed state.
% (Use click-down-and-drag to invoke a rubber-rectangle.)
%
% Use click-drag to map the zooming to a rubber-rectangle.
% Copyright (C) 1997 Dr. Charles R. Denham, ZYDECO.
% All Rights Reserved.
% Disclosure without explicit written consent from the
% copyright owner does not constitute publication.
% Version of 19-Jun-1997 08:42:57.
% Updated 02-Aug-1999 14:40:31.
result = logical(0);
if nargin < 1, varargin = {'on'}; end
if isstr(varargin{1}) & ~isempty(varargin{1}) & ...
any(varargin{1}(1) == '0123456789.')
varargin{1} = eval(varargin{1});
end
if ~isstr(varargin{1})
theAmount = varargin{1};
varargin{1} = 'manual';
end
theFlag = logical(0);
isAll = logical(0);
theOldXLim = get(gca, 'XLim');
theOldYLim = get(gca, 'YLim');
switch varargin{1}
case 'manual'
isAll = (nargin > 2);
theDirection = 'xy';
if nargin > 1, theDirection = varargin{2}; end
theXLim = get(gca, 'XLim');
theYLim = get(gca, 'YLim');
if theAmount == 0
axis tight
switch theDirection
case 'x'
set(gca, 'YLim', theYLim)
case 'y'
set(gca, 'XLim', theXLim)
case 'xy'
otherwise
end
theAmount = 1;
theXLim = get(gca, 'XLim');
theYLim = get(gca, 'YLim');
end
cx = mean(theXLim);
cy = mean(theYLim);
dx = diff(theXLim) ./ 2;
dy = diff(theYLim) ./ 2;
switch theDirection
case 'x'
theXLim = cx + [-dx dx] ./ theAmount;
case 'y'
theYLim = cy + [-dy dy] ./ theAmount;
case 'xy'
theXLim = cx + [-dx dx] ./ theAmount;
theYLim = cy + [-dy dy] ./ theAmount;
otherwise
end
set(gca, 'XLim', theXLim, 'YLim', theYLim);
theFlag = 1;
case 'demo'
x = (0:30) ./ 30;
y = rand(size(x)) - 0.5;
for i = 2:-1:1
subplot(1, 2, i)
theLine = plot(x, y, '-o');
set(theLine, 'ButtonDownFcn', 'disp(''## hello'')')
set(gcf, 'Name', 'zoomsafe Demo')
end
result = zoomsafe('on', 'all');
case 'all'
result = zoomsafe('on', 'all');
case 'on'
isAll = (nargin > 1);
if ~isAll
set(gcf, 'WindowButtonDownFcn', 'if zoomsafe(''down''), end')
else
set(gcf, 'WindowButtonDownFcn', 'if zoomsafe(''down'', ''all''), end')
end
case 'down'
isAll = (nargin > 1);
dozoom = 0;
switch get(gcbo, 'Type')
case {'figure'} % "axes" not needed.
switch switchsafe(get(gco, 'Type'))
case {'figure'}
dozoom = 1;
otherwise
if isempty(get(gco, 'ButtonDownFcn'))
dozoom = 1;
end
end
otherwise
end
switch dozoom
case 1
thePointer = get(gcf, 'Pointer');
set(gcf, 'Pointer', 'watch')
theRBRect = rbrect;
x = sort(theRBRect([1 3]));
y = sort(theRBRect([2 4]));
theXLim = get(gca, 'XLim');
theYLim = get(gca, 'YLim');
theLimRect = [theXLim(1) theYLim(1) theXLim(2) theYLim(2)];
d = doubleclick; % Trap any double-click.
if any(d) % Valid double-click.
if ~isAll
result = zoomsafe('out');
else
result = zoomsafe('out', 'all');
end
set(gcf, 'Pointer', 'arrow')
if nargout > 0, theResult = result; end
return
elseif isempty(d) % Ignore initial-click of double.
if nargout > 0, theResult = result; end
return
else % Not a double-click.
end
switch get(gcf, 'SelectionType')
case 'normal'
theFlag = 1;
theAmount = [2 2]; % Zoom-in by factor of 2.
case 'extend'
theFlag = 1;
theAmount = [0.5 0.5];
case 'open' % Pre-empted by "doubleclick" above.
if ~isAll
result = zoomsafe('out');
else
result = zoomsafe('out', 'all');
end
set(gcf, 'Pointer', 'arrow')
if nargout > 0, theResult = result; end
return
otherwise
theAmount = [1 1];
x = [mean(x) mean(x)];
y = [mean(y) mean(y)];
end
if diff(x) == 0 | diff(y) == 0
cx = mean(x);
cy = mean(y);
dx = diff(theXLim) ./ 2;
dy = diff(theYLim) ./ 2;
x = cx + [-dx dx] ./ theAmount(1);
y = cy + [-dy dy] ./ theAmount(2);
else
r1 = theLimRect;
r2 = theRBRect;
switch get(gcf, 'SelectionType')
case 'normal'
r4 = maprect(r1, r2, r1);
case 'extend'
r4 = maprect(r2, r1, r1);
otherwise
r4 = r1;
end
x = r4([1 3]);
y = r4([2 4]);
end
set(gca, 'XLim', sort(x), 'YLim', sort(y))
theFlag = 1;
result = logical(1);
switch thePointer
case {'watch', 'circle'}
thePointer = 'arrow';
otherwise
end
set(gcf, 'Pointer', thePointer)
set(gcf, 'Pointer', 'arrow')
otherwise
end
case 'motion'
case 'up'
case 'off'
set(gcf, 'WindowButtonDownFcn', '');
case 'out'
isAll = (nargin > 1);
theFlag = 1;
axis tight
result = logical(1);
otherwise
temp = eval(varargin{1});
switch class(temp)
case 'double'
if ~isAll
result = zoomsafe(temp);
else
result = zoomsafe(temp, 'all');
end
otherwise
warning('## Unknown option')
end
end
% Synchronize the other axes.
if isAll & theFlag & 1
theGCA = gca;
theXLim = get(theGCA, 'XLim');
theYLim = get(theGCA, 'YLim');
theAxes = findobj(gcf, 'Type', 'axes');
for i = 1:length(theAxes)
if theAxes(i) ~= theGCA
axes(theAxes(i))
x = get(gca, 'XLim');
y = get(gca, 'YLim');
if all(x == theOldXLim)
set(theAxes(i), 'XLim', theXLim)
end
if all(y == theOldYLim)
set(theAxes(i), 'YLim', theYLim)
end
end
end
axes(theGCA)
end
if nargout > 0, theResult = result; end
% legend % Causes excessive flashing.
function theResult = rbrect(onMouseUp, onMouseMove, onMouseDown)
% rbrect -- Rubber rectangle tracking (Matlab-4 and Matlab-5).
% rbrect('demo') demonstrates itself.
% rbrect('onMouseUp', 'onMouseMove', 'onMouseDown') conducts interactive
% rubber-rectangle tracking, presumably because of a mouse button press
% on the current-callback-object (gcbo). The 'on...' callbacks are
% automatically invoked with: "feval(theCallback, theInitiator, theRect)"
% after each window-button event, using the object that started this
% process, plus theRect as [xStart yStart xEnd yEnd] for the current
% rubber-rect. The callbacks default to ''. The coordinates of the
% rectangle are returned as [xStart yStart xEnd yEnd].
% Private interface:
% rbrect(1) is automatically called on window-button-motions.
% rbrect(2) is automatically called on window-button-up.
% Copyright (C) 1997 Dr. Charles R. Denham, ZYDECO.
% All Rights Reserved.
% Disclosure without explicit written consent from the
% copyright owner does not constitute publication.
% Version of 03-Jun-1997 15:54:39.
% Version of 11-Jun-1997 15:17:22.
% Version of 17-Jun-1997 16:52:46.
global RBRECT_HANDLE
global RBRECT_INITIATOR
global RBRECT_ON_MOUSE_MOVE
if nargin < 1, onMouseUp = 0; end
if strcmp(onMouseUp, 'demo')
help rbrect
x = cumsum(rand(200, 1) - 0.45);
y = cumsum(rand(200, 1) - 0.25);
h = plot(x, y, '-r');
set(h, 'ButtonDownFcn', 'disp(rbrect)')
figure(gcf), set(gcf, 'Name', 'RBRECT Demo')
return
elseif isstr(onMouseUp)
theMode = 0;
else
theMode = onMouseUp;
onMouseUp = '';
end
if theMode == 0 % Mouse down.
if nargin < 3, onMouseDown = ''; end
if nargin < 2, onMouseMove = ''; end
if nargin < 1, onMouseUp = ''; end
theVersion = version;
isVersion5 = (theVersion(1) == '5');
if isVersion5
theCurrentObject = 'gcbo';
else
theCurrentObject = 'gco';
end
RBRECT_INITIATOR = eval(theCurrentObject);
switch get(RBRECT_INITIATOR, 'Type')
case 'line'
theColor = get(RBRECT_INITIATOR, 'Color');
otherwise
theColor = 'black';
end
RBRECT_ON_MOUSE_MOVE = onMouseMove;
pt = mean(get(gca, 'CurrentPoint'));
x = [pt(1) pt(1)]; y = [pt(2) pt(2)];
RBRECT_HANDLE = line(x, y, ...
'EraseMode', 'xor', ...
'LineStyle', '--', ...
'LineWidth', 2.5, ...
'Color', theColor, ...
'Marker', '+', 'MarkerSize', 13, ...
'UserData', 1);
set(gcf, 'WindowButtonMotionFcn', 'rbrect(1);')
set(gcf, 'WindowButtonUpFcn', 'rbrect(2);')
theRBRect = [x(1) y(1) x(2) y(2)];
if ~isempty(onMouseDown)
feval(onMouseDown, RBRECT_INITIATOR, theRBRect)
end
thePointer = get(gcf, 'Pointer');
set(gcf, 'Pointer', 'circle');
if isVersion5 & 0 % Disable for rbrect()..
eval('waitfor(RBRECT_HANDLE, ''UserData'', [])')
else
set(RBRECT_HANDLE, 'Visible', 'off') % Invisible.
eval('rbbox') % No "waitfor" in Matlab-4.
end
set(gcf, 'Pointer', thePointer);
set(gcf, 'WindowButtonMotionFcn', '')
set(gcf, 'WindowButtonUpFcn', '')
x = get(RBRECT_HANDLE, 'XData');
y = get(RBRECT_HANDLE, 'YData');
delete(RBRECT_HANDLE)
theRBRect = [x(1) y(1) x(2) y(2)]; % Scientific.
if ~isempty(onMouseUp)
feval(onMouseUp, RBRECT_INITIATOR, theRBRect)
end
elseif theMode == 1 % Mouse move.
pt2 = mean(get(gca, 'CurrentPoint'));
x = get(RBRECT_HANDLE, 'XData');
y = get(RBRECT_HANDLE, 'YData');
x(2) = pt2(1); y(2) = pt2(2);
set(RBRECT_HANDLE, 'XData', x, 'YData', y)
theRBRect = [x(1) y(1) x(2) y(2)];
if ~isempty(RBRECT_ON_MOUSE_MOVE)
feval(RBRECT_ON_MOUSE_MOVE, RBRECT_INITIATOR, theRBRect)
end
elseif theMode == 2 % Mouse up.
pt2 = mean(get(gca, 'CurrentPoint'));
x = get(RBRECT_HANDLE, 'XData');
y = get(RBRECT_HANDLE, 'YData');
x(2) = pt2(1); y(2) = pt2(2);
set(RBRECT_HANDLE, 'XData', x, 'YData', y, 'UserData', [])
else
end
if nargout > 0, theResult = theRBRect; end
function rect4 = maprect(rect1, rect2, rect3)
% maprect -- Map rectangles.
% maprect(rect1, rect2, rect3) returns the rectangle
% that is to rect3 what rect1 is to rect2. Each
% rectangle is given as [x1 y1 x2 y2].
% maprect('demo') demonstrates itself by showing
% that maprect(r1, r2, r1) ==> r2.
% Copyright (C) 1997 Dr. Charles R. Denham, ZYDECO.
% All Rights Reserved.
% Disclosure without explicit written consent from the
% copyright owner does not constitute publication.
% Version of 19-Jun-1997 08:33:39.
if nargin < 1, help(mfilename), rect1 = 'demo'; end
if strcmp(rect1, 'demo')
rect1 = [0 0 3 3];
rect2 = [1 1 2 2];
rect3 = rect1;
r4 = maprect(rect1, rect2, rect3);
begets(mfilename, 3, rect1, rect2, rect3, r4)
return
end
if nargin < 3, help(mfilename), return, end
r4 = zeros(1, 4);
i = [1 3];
for k = 1:2
r4(i) = polyval(polyfit(rect1(i), rect2(i), 1), rect3(i));
i = i + 1;
end
if nargout > 0
rect4 = r4;
else
disp(r4)
end
function theResult = doubleclick
% doubleclick -- Trap for double-clicks.
% doubleclick (no argument) returns TRUE if a click
% is detected during its execution; otherwise, FALSE.
% Call "doubleclick" during a "WindowButtonDown" or
% "ButtonDown" callback, preferably at the top of
% procedure. The 'Interruptible' property of the
% callback-object must be 'on'. The double-click
% time is 0.5 sec. A valid double-click causes
% two values to be returned: first, a logical(1),
% then an empty-matrix []. The latter signifies
% the single-click that initiated the process.
% For a valid single-click, only logical(0) is
% returned.
% Copyright (C) 1997 Dr. Charles R. Denham, ZYDECO.
% All Rights Reserved.
% Disclosure without explicit written consent from the
% copyright owner does not constitute publication.
% Version of 25-Jul-1998 09:47:16.
global CLICK_COUNT
DOUBLE_CLICK_TIME = 1/2; % Seconds.
if isempty(CLICK_COUNT), CLICK_COUNT = 0; end
CLICK_COUNT = CLICK_COUNT + 1;
if CLICK_COUNT == 1
tic
while isequal(CLICK_COUNT, 1) & toc < DOUBLE_CLICK_TIME, end
end
drawnow % Process the event-cue.
% Note:
% Despite the "drawnow" seen above, Matlab does not
% update the "SelectionType" in timely fashion, so
% it cannot be used to trap a double-click properly.
result = (CLICK_COUNT > 1);
CLICK_COUNT = [];
if nargout > 0
theResult = result;
else
disp(result)
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -