function [dist, partials] = linkage(params, pt)
% function [dist, partials] = linkage(params, pt)
% parameters for a linkage are:
% [basposx, baseposy, theta1, len1, theta2, len2, theta3, len3, ...]
% thetas are relative to the origin, not the previous link.
% leni is the length of the ith linkage.

% This function is not optimized at all.  In fact, this is probably
% the slowest way to compute distances and partials.
%
% The correct way would be to compute edge equations, with partials,
% for each link.  The equations and partials could then be applied to
% matrices of points, rather than a point-at-a-time, as it does in
% this version.


% Search linkage for closest point

x = params(1);
y = params(2);
mindist = Inf;
mini = 0;

% check each link
for i=3:2:length(params)
  theta = params(i);
  len = params(i+1);
  basept = [x y];
  d = distlink(basept, theta, pt);
  if abs(d) < abs(mindist),
    mindist = d;
    mini = i;
    bestbase = basept;
  end
  x = x + len * cos(theta);
  y = y + len * sin(theta);
end

dist=mindist;


% compute partials relative for the edge equation of the closest link
partials = zeros(size(params));
theta = params(mini);

% partial wrt base x, y
partials(1) = - sin(theta);
partials(2) = cos(theta);

% partial wrt thetai and leni for links before the closest one
for i=3:2:mini-1,
  % angle
  partials(i) = params(i+1) * (sin(theta) * sin(params(i)) + cos(theta) * cos(params(i)));
  % len
  partials(i+1) = -sin(theta)*cos(params(i))+cos(theta)*sin(params(i));
end

% partial for the final link's theta
partials(mini) = cos(theta) * (pt(1) - bestbase(1)) + ...
    sin(theta) * (pt(2) - bestbase(2));


% edge equation.  See also Pineda's article in SIGGRAPH 1988.
function d = distlink(basept, theta, pt)
d = [pt - basept] * [sin(theta); -cos(theta)];

