Code covered by the BSD License  

Highlights from
Minimum distance between two polygons

image thumbnail
from Minimum distance between two polygons by Guillaume JACQUENOT
This function computes the minimum euclidean distance between two polygons P1 & P2.

curveintersect(varargin)
function [x,y] = curveintersect(varargin)
%
% Curve Intersections.
% [X,Y]=CURVEINTERSECT(H1,H2) or [X,Y]=CURVEINTERSECT([H1 H2]) finds the
% intersection points of the two curves on the X-Y plane identified
% by the line or lineseries object handles H1 and H2.
%
% [X,Y]=CURVEINTERSECT(X1,Y1,X2,Y2) finds the intersection points of the
% two curves described by the vector data pairs (X1,Y1) and (X2,Y2).
%
% X and Y are empty if no intersection exists.
%
% Example
% -------
% x1=rand(10,1); y1=rand(10,1); x2=rand(10,1); y2=rand(10,1);
% [x,y]=curveintersect(x1,y1,x2,y2); 
% plot(x1,y1,'k',x2,y2,'b',x,y,'ro')
%
% Original Version (-> curveintersect_local)
% ---------------------------------------
% D.C. Hanselman, University of Maine, Orono, ME 04469
% Mastering MATLAB 7
% 2005-01-06
%
% Improved Version (-> this function)
% -----------------------------------
% S. Hlz, TU Berlin, Germany
% v 1.0: October 2005
% v 1.1: April   2006     Fixed some minor bugs in function 'mminvinterp'

x=[]; y=[];
[x1,y1,x2,y2]=local_parseinputs(varargin{:});
ind_x1=sign(diff(x1)); ind_x2=sign(diff(x2));

ind1=1;
while ind1<length(x1)
    ind_max = ind1+min(find(ind_x1(ind1:end)~=ind_x1(ind1)))-1;
    if isempty(ind_max) | ind_max==ind1; ind_max=length(x1); end
    ind1=ind1:ind_max;
    
    ind2=1;
    while ind2<length(x2)
        ind_max = ind2+min(find(ind_x2(ind2:end)~=ind_x2(ind2)))-1;
        if isempty(ind_max) | ind_max==ind2; ind_max=length(x2); end
        ind2=ind2:ind_max;
        
        % Fallunterscheidung
        if ind_x1(ind1(1))==0 & ind_x2(ind2(1))~=0 
            x_loc=x1(ind1(1));
            y_loc=interp1(x2(ind2),y2(ind2),x_loc);
            if ~(y_loc>=min(y1(ind1)) && y_loc<=max(y1(ind1))); y_loc=[]; x_loc=[]; end
            
        elseif ind_x2(ind2(1))==0 & ind_x1(ind1(1))~=0
            x_loc=x2(ind2(1));
            y_loc=interp1(x1(ind1),y1(ind1),x_loc);
            if ~(y_loc>=min(y2(ind2)) && y_loc<=max(y2(ind2))); y_loc=[]; x_loc=[]; end

        elseif ind_x2(ind2(1))~=0 & ind_x1(ind1(1))~=0
            [x_loc,y_loc]=curveintersect_local(x1(ind1),y1(ind1),x2(ind2),y2(ind2));
            
        elseif ind_x2(ind2(1))==0 & ind_x1(ind1(1))==0
            [x_loc,y_loc]=deal([]);
            
        end
        x=[x; x_loc(:)];
        y=[y; y_loc(:)];
        ind2=ind2(end);
    end
    ind1=ind1(end);
end
    


% ----------------------------------------------
function [x,y]=curveintersect_local(x1,y1,x2,y2)

if ~isequal(x1,x2)
   xx=unique([x1 x2]); % get unique data points
   xx=xx(xx>=max(min(x1),min(x2)) & xx<=min(max(x1),max(x2)));
   if numel(xx)<2
      x=[];
      y=[];
      return
   end
   yy=interp1(x1,y1,xx)-interp1(x2,y2,xx);
else
   xx=x1;
   yy=y1-y2;
end
x=mminvinterp(xx,yy,0); % find zero crossings of difference
if ~isempty(x)
   y=interp1(x1,y1,x);
else
   x=[];
   y=[];
end

%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function [xo,yo]=mminvinterp(x,y,yo)
%MMINVINTERP 1-D Inverse Interpolation. From the text "Mastering MATLAB 7"
% [Xo, Yo]=MMINVINTERP(X,Y,Yo) linearly interpolates the vector Y to find
% the scalar value Yo and returns all corresponding values Xo interpolated
% from the X vector. Xo is empty if no crossings are found. For
% convenience, the output Yo is simply the scalar input Yo replicated so
% that size(Xo)=size(Yo).
% If Y maps uniquely into X, use INTERP1(Y,X,Yo) instead.
%
% See also INTERP1.

if nargin~=3
   error('Three Input Arguments Required.')
end
n = numel(y);
if ~isequal(n,numel(x))
   error('X and Y Must have the Same Number of Elements.')
end
if ~isscalar(yo)
   error('Yo Must be a Scalar.')
end

x=x(:); % stretch input vectors into column vectors
y=y(:);

if yo<min(y) || yo>max(y) % quick exit if no values exist
   xo = [];
   yo = [];
else                      % find the desired points
   
   below = y<yo;          % True where below yo 
   above = y>yo;          % True where above yo
   on    = y==yo;         % True where on yo
   
   kth = (below(1:n-1)&above(2:n)) | (above(1:n-1)&below(2:n));     % point k
   kp1 = [false; kth];                                              % point k+1
   
   xo = [];                                                         % distance between x(k+1) and x(k) 
   if any(kth);                                                     
       alpha = (yo - y(kth))./(y(kp1)-y(kth));
       xo = alpha.*(x(kp1)-x(kth)) + x(kth);
   end         
   xo = sort([xo; x(on)]);                                          % add points, which are directly on line

   yo = repmat(yo,size(xo));                                        % duplicate yo to match xo points found
end 
%--------------------------------------------------------------------------
function [x1,y1,x2,y2]=local_parseinputs(varargin)

if nargin==1 % [X,Y]=CURVEINTERSECT([H1 H2])
   arg=varargin{1};
   if numel(arg)==2 && ...
      all(ishandle(arg)) && all(strcmp(get(arg,'type'),'line'))
      data=get(arg,{'XData','YData'});
      [x1,x2,y1,y2]=deal(data{:});
   else
      error('Input Must Contain Two Handles to Line Objects.')
   end
elseif nargin==2 % [X,Y]=CURVEINTERSECT(H1,H2)
   arg1=varargin{1};
   arg2=varargin{2};
   if numel(arg1)==1 && ishandle(arg1) && strcmp(get(arg1,'type'),'line')...
   && numel(arg2)==1 && ishandle(arg2) && strcmp(get(arg2,'type'),'line')
      
      data=get([arg1;arg2],{'XData','YData'});
      [x1,x2,y1,y2]=deal(data{:});
   else
      error('Input Must Contain Two Handles to Line Objects.')
   end
elseif nargin==4
   [x1,y1,x2,y2]=deal(varargin{:});
   if ~isequal(numel(x1),numel(y1))
      error('X1 and Y1 Must Contain the Same Number of Elements.')
   elseif ~isequal(numel(x2),numel(y2))
      error('X2 and Y2 Must Contain the Same Number of Elements.')
   end
   x1=reshape(x1,1,[]); % make data into rows
   x2=reshape(x2,1,[]);
   y1=reshape(y1,1,[]);
   y2=reshape(y2,1,[]);
       
else
   error('Incorrect Number of Input Arguments.')
end
if min(x1)>max(x2) | min(x2)>max(x1) | min(y2)>max(y1) | min(y1)>max(y2) % Polygons can not have intersections
    x1=[]; y1=[]; x2=[]; y2=[]; return
end
if numel(x1)<2 || numel(x2)<2 || numel(y1)<2 || numel(y2)<2
   error('At Least Two Data Points are Required for Each Curve.')
end


Contact us at files@mathworks.com