function [x, y] = sticksafe(x0, y0, theLength, theAngle) % sticksafe -- Intelligent, oriented sticks. % sticksafe('demo') demonstrates itself with sticks centered % on the origin, each one-unit long. % sticksafe(N) demonstrates itself with N sticks. % sticksafe(x0, y0, theLength, theAngle) draws sticks that % start at (x0, y0), with theLength (in y-axis units), and % theAngle (degrees, counter-clockwise from +x). The % variables should be the same size, but any can be a scalar, % just so long as the x0 and/or y0 array is the full size. % The "ResizeFcn" of the figure is set to update the sticks % automatically. The "Tag" of each stick is the mfilename. % Properties of the arrows, such as "color", can be adjusted % at any time. The arrows are Matlab "patch" objects. % h = sticksafe(...) draws the sticks and returns the handle. % [x, y] = sticksafe(...) returns the (x, y) data for such % sticks, one row per arrow, but does not draw them. % sticksafe (no argument) redraws existing sticks. This is % useful whenever the window is resized or the x or y limits % change. (Recall that printing causes the "ResizeFcn" to % be called twice.) % % Note: this routine leaves the axes in "manual" mode. Use % "axis auto" to revert to automatic axis limits. % % Calls: none % Copyright (C) 2000 Dr. Charles R. Denham, ZYDECO. % All Rights Reserved. % Disclosure without explicit written consent from the % copyright owner does not constitute publication. % Version of 12-Jan-2000 14:22:59. % Updated 27-Jul-2001 15:01:56. RCF = 180 / pi; % Resize. if nargin < 1 oldGCA = gca; h = findobj(gcf, 'Type', 'line', 'Tag', mfilename); for i = 1:length(h) p = get(h(i), 'Parent'); axes(p) u = get(h(i), 'UserData'); [xx, yy] = feval(mfilename, u(:, 1), u(:, 2), u(:, 3), u(:, 4)); set(h(i), 'XData', xx(:), 'YData', yy(:)); end axes(oldGCA) return end % Demonstration. if nargin == 1 if isequal(x0, 'demo') help(mfilename) x0 = 16; elseif ischar(x0) x0 = eval(x0); end theName = [mfilename ' demo']; f = findobj('Type', 'figure', 'Name', theName); if ~any(f) f = figure('Name', theName); end figure(max(f)) delete(get(f, 'Children')) n = max(1, round(x0)); x0 = zeros(1, n); ang = linspace(0, 360, length(x0)+1); ang(end) = []; h = feval(mfilename, x0, 0, 1, ang); set(gca, 'Xlim', [-n n], 'YLim', [-2 2]) feval(mfilename) set(gcf, 'WindowButtonDownFcn', ... ['if zoomsafe(''down''), ' mfilename ', end']) if nargout > 0, x = h; end return end % Initialize. if nargin > 1 if nargout == 2, x = []; y = []; end if length(x0) == 1 x0 = x0 * ones(size(y0)); elseif length(y0) == 1 y0 = y0 * ones(size(x0)); end x0 = reshape(x0, [1 prod(size(x0))]); y0 = reshape(y0, size(x0)); if nargin < 3, theLength = 1; end if nargin < 4, theAngle = 0; end if length(theLength) == 1 theLength = theLength * ones(size(x0)); end if length(theAngle) == 1 theAngle = theAngle * ones(size(x0)); end theLength = reshape(theLength, size(x0)); theAngle = reshape(theAngle, size(x0)); axes(gca) oldUnits = get(gca, 'Units'); set(gca, 'Units', 'pixels') thePosition = get(gca, 'Position'); set(gca, 'Units', oldUnits) theWidth = thePosition(3); % pixels. theHeight = thePosition(4); % pixels. axis('manual') dx = diff(get(gca, 'XLim')); dy = diff(get(gca, 'YLim')); dydx = dy / dx; % Not used. dxdp = dx / theWidth; % sci/pixel. dydp = dy / theHeight; % sci/pixel. scale = dxdp / dydp; zz = exp(sqrt(-1) .* theAngle ./ RCF) .* theLength; xx = zeros(3, prod(size(x0))); xx(1, :) = x0; xx(2, :) = x0 + real(zz)*scale; xx(3, :) = NaN; yy = zeros(size(xx)); yy(1, :) = y0; yy(2, :) = y0 + imag(zz); yy(3, :) = NaN; if nargout < 2 h = line(xx(:), yy(:), ... 'Tag', mfilename, ... 'UserData', [x0(:) y0(:) theLength(:) theAngle(:)]); if nargout > 1, x = h; end elseif nargout == 2 x = xx; y = yy; end set(gcf, 'ResizeFcn', mfilename) if nargout == 1, x = h; end end