arrow

arrow is a plot function for drawing arrows. Input is either in vector components or angular.

function arrow(varargin)

% function arrow(x0, y0, r, angle, arrowheadsize, arrowheadangle, colorvec, linestyle, linewidth)
% function arrow(x_comp, y_comp, arrowheadsize, arrowheadangle, colorvec, linestyle, linewidth)
%
% x_comp and y_comp must contain two values.
% Trailing plotting parameters may be ommitted. Any plotting parameter can be specified as [] for defaults.

axes0 = gca;
if length(varargin{1}) == 1,
    x0 = varargin{1};
    y0 = varargin{2};
    r = varargin{3};
    angle = varargin{4};
    x_comp = [x0 x0 + r * cos(angle)];
    y_comp = [x0 x0 + r * sin(angle)];
    plotParIndex = 5;
else,
    x_comp = varargin{1};
    y_comp = varargin{2};
    r = sqrt(diff(x_comp) .^ 2 + diff(y_comp) .^ 2);
    angle = atan2(diff(y_comp), diff(x_comp));
    plotParIndex = 3;
end;

if length(varargin) >= plotParIndex,
    headSize = varargin{plotParIndex} * r;
    if isempty(headSize ),
        headSize = 0.1 * r;
    end;
else,
    headSize = 0.1 * r;
end;
if length(varargin) >= plotParIndex + 1,
    headAngle = varargin{plotParIndex + 1};
    if isempty(headAngle),
        headAngle = pi / 8;
    end;
else,
    headAngle = pi / 8;
end;
if length(varargin) >= plotParIndex + 2,
    color = varargin{plotParIndex + 2};
    if isempty(color),
        color = [0 0 0];
    end;
else,
    color = [0 0 0];
end;
if length(varargin) >= plotParIndex + 3,
    linestyle = varargin{plotParIndex + 3};
    if isempty(linestyle),
        linestyle = '-';
    end;
else,
    linestyle = '-';
end;
if length(varargin) >= plotParIndex + 4,
    linewidth = varargin{plotParIndex + 4};
    if isempty(linewidth),
        linewidth = 0.1;
    end;
else,
    linewidth = 0.1;
end;

holding = get(axes0, 'NextPlot');
if strcmp(holding, 'replace') == 1,
    cla;
end;
%set(axes0, 'NextPlot', 'add');

% The main line
drawLine(x_comp, y_comp, color, linestyle, linewidth);

% The head: draw on origin on a lying arrow, then rotate and translate.
headPoint = getHeadPoint(angle, headSize, headAngle, x_comp, y_comp);
drawLine([x_comp(2) headPoint(1)], [y_comp(2) headPoint(2)], color, linestyle, linewidth);
headPoint = getHeadPoint(angle, headSize, -headAngle, x_comp, y_comp);
drawLine([x_comp(2) headPoint(1)], [y_comp(2) headPoint(2)], color, linestyle, linewidth);

% whitespace if necessary
xlim1 = [min(x_comp - headSize) max(x_comp + headSize)];
ylim1 = [min(y_comp - headSize) max(y_comp + headSize)];
xlim0 = get(gca, 'XLim');
ylim0 = get(gca, 'YLim');
xlim2 = [min([xlim0(1); xlim1(1)]) max([xlim0(2); xlim1(2)])];
ylim2 = [min([ylim0(1); ylim1(1)]) max([ylim0(2); ylim1(2)])];
set(gca, 'XLim', xlim2);
set(gca, 'YLim', ylim2);

%set(axes0, 'NextPlot', holding);

function line0 = drawLine(x_comp, y_comp, color, linestyle, linewidth);
line0 = line(x_comp, y_comp);
set(line0, 'Color', color);
set(line0, 'LineStyle', linestyle);
set(line0, 'LineWidth', linewidth);

function headPoint = getHeadPoint(angle, headSize, headAngle, x_comp, y_comp)
headPoint = headSize * [-cos(headAngle); sin(headAngle)];
rotation_matrix = [cos(angle) -sin(angle); sin(angle) cos(angle)];
headPoint = rotation_matrix * headPoint + [x_comp(2); y_comp(2)];