You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
4.4 KiB
128 lines
4.4 KiB
3 years ago
|
function out = lineSegmentIntersect(XY1,XY2)
|
||
|
%LINESEGMENTINTERSECT Intersections of line segments.
|
||
|
% OUT = LINESEGMENTINTERSECT(XY1,XY2) finds the 2D Cartesian Coordinates of
|
||
|
% intersection points between the set of line segments given in XY1 and XY2.
|
||
|
%
|
||
|
% XY1 and XY2 are N1x4 and N2x4 matrices. Rows correspond to line segments.
|
||
|
% Each row is of the form [x1 y1 x2 y2] where (x1,y1) is the start point and
|
||
|
% (x2,y2) is the end point of a line segment:
|
||
|
%
|
||
|
% Line Segment
|
||
|
% o--------------------------------o
|
||
|
% ^ ^
|
||
|
% (x1,y1) (x2,y2)
|
||
|
%
|
||
|
% OUT is a structure with fields:
|
||
|
%
|
||
|
% 'intAdjacencyMatrix' : N1xN2 indicator matrix where the entry (i,j) is 1 if
|
||
|
% line segments XY1(i,:) and XY2(j,:) intersect.
|
||
|
%
|
||
|
% 'intMatrixX' : N1xN2 matrix where the entry (i,j) is the X coordinate of the
|
||
|
% intersection point between line segments XY1(i,:) and XY2(j,:).
|
||
|
%
|
||
|
% 'intMatrixY' : N1xN2 matrix where the entry (i,j) is the Y coordinate of the
|
||
|
% intersection point between line segments XY1(i,:) and XY2(j,:).
|
||
|
%
|
||
|
% 'intNormalizedDistance1To2' : N1xN2 matrix where the (i,j) entry is the
|
||
|
% normalized distance from the start point of line segment XY1(i,:) to the
|
||
|
% intersection point with XY2(j,:).
|
||
|
%
|
||
|
% 'intNormalizedDistance2To1' : N1xN2 matrix where the (i,j) entry is the
|
||
|
% normalized distance from the start point of line segment XY1(j,:) to the
|
||
|
% intersection point with XY2(i,:).
|
||
|
%
|
||
|
% 'parAdjacencyMatrix' : N1xN2 indicator matrix where the (i,j) entry is 1 if
|
||
|
% line segments XY1(i,:) and XY2(j,:) are parallel.
|
||
|
%
|
||
|
% 'coincAdjacencyMatrix' : N1xN2 indicator matrix where the (i,j) entry is 1
|
||
|
% if line segments XY1(i,:) and XY2(j,:) are coincident.
|
||
|
|
||
|
% Version: 1.00, April 03, 2010
|
||
|
% Version: 1.10, April 10, 2010
|
||
|
% Author: U. Murat Erdem
|
||
|
|
||
|
% CHANGELOG:
|
||
|
%
|
||
|
% Ver. 1.00:
|
||
|
% -Initial release.
|
||
|
%
|
||
|
% Ver. 1.10:
|
||
|
% - Changed the input parameters. Now the function accepts two sets of line
|
||
|
% segments. The intersection analysis is done between these sets and not in
|
||
|
% the same set.
|
||
|
% - Changed and added fields of the output. Now the analysis provides more
|
||
|
% information about the intersections and line segments.
|
||
|
% - Performance tweaks.
|
||
|
|
||
|
% I opted not to call this 'curve intersect' because it would be misleading
|
||
|
% unless you accept that curves are pairwise linear constructs.
|
||
|
% I tried to put emphasis on speed by vectorizing the code as much as possible.
|
||
|
% There should still be enough room to optimize the code but I left those out
|
||
|
% for the sake of clarity.
|
||
|
% The math behind is given in:
|
||
|
% http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
|
||
|
% If you really are interested in squeezing as much horse power as possible out
|
||
|
% of this code I would advise to remove the argument checks and tweak the
|
||
|
% creation of the OUT a little bit.
|
||
|
|
||
|
%%% Argument check.
|
||
|
%-------------------------------------------------------------------------------
|
||
|
|
||
|
validateattributes(XY1,{'numeric'},{'2d','finite'});
|
||
|
validateattributes(XY2,{'numeric'},{'2d','finite'});
|
||
|
|
||
|
[n_rows_1,n_cols_1] = size(XY1);
|
||
|
[n_rows_2,n_cols_2] = size(XY2);
|
||
|
|
||
|
if n_cols_1 ~= 4 || n_cols_2 ~= 4
|
||
|
error('Arguments must be a Nx4 matrices.');
|
||
|
end
|
||
|
|
||
|
%%% Prepare matrices for vectorized computation of line intersection points.
|
||
|
%-------------------------------------------------------------------------------
|
||
|
X1 = repmat(XY1(:,1),1,n_rows_2);
|
||
|
X2 = repmat(XY1(:,3),1,n_rows_2);
|
||
|
Y1 = repmat(XY1(:,2),1,n_rows_2);
|
||
|
Y2 = repmat(XY1(:,4),1,n_rows_2);
|
||
|
|
||
|
XY2 = XY2';
|
||
|
|
||
|
X3 = repmat(XY2(1,:),n_rows_1,1);
|
||
|
X4 = repmat(XY2(3,:),n_rows_1,1);
|
||
|
Y3 = repmat(XY2(2,:),n_rows_1,1);
|
||
|
Y4 = repmat(XY2(4,:),n_rows_1,1);
|
||
|
|
||
|
X4_X3 = (X4-X3);
|
||
|
Y1_Y3 = (Y1-Y3);
|
||
|
Y4_Y3 = (Y4-Y3);
|
||
|
X1_X3 = (X1-X3);
|
||
|
X2_X1 = (X2-X1);
|
||
|
Y2_Y1 = (Y2-Y1);
|
||
|
|
||
|
numerator_a = X4_X3 .* Y1_Y3 - Y4_Y3 .* X1_X3;
|
||
|
numerator_b = X2_X1 .* Y1_Y3 - Y2_Y1 .* X1_X3;
|
||
|
denominator = Y4_Y3 .* X2_X1 - X4_X3 .* Y2_Y1;
|
||
|
|
||
|
u_a = numerator_a ./ denominator;
|
||
|
u_b = numerator_b ./ denominator;
|
||
|
|
||
|
% Find the adjacency matrix A of intersecting lines.
|
||
|
INT_X = X1+X2_X1.*u_a;
|
||
|
INT_Y = Y1+Y2_Y1.*u_a;
|
||
|
INT_B = (u_a >= 0) & (u_a <= 1) & (u_b >= 0) & (u_b <= 1);
|
||
|
% PAR_B = denominator == 0;
|
||
|
% COINC_B = (numerator_a == 0 & numerator_b == 0 & PAR_B);
|
||
|
|
||
|
|
||
|
% Arrange output.
|
||
|
out.intAdjacencyMatrix = INT_B;
|
||
|
out.intMatrixX = INT_X .* INT_B;
|
||
|
out.intMatrixY = INT_Y .* INT_B;
|
||
|
% out.intNormalizedDistance1To2 = u_a;
|
||
|
% out.intNormalizedDistance2To1 = u_b;
|
||
|
% out.parAdjacencyMatrix = PAR_B;
|
||
|
% out.coincAdjacencyMatrix= COINC_B;
|
||
|
|
||
|
end
|
||
|
|