📄 curveintersect.m
字号:
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. H鰈z, 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -