Intersection of line segments using complex variables in Matlab
NOTE: Sep. 2, 2011, this is a substantial edit of my previous post to explain more details.
A
post by Loren Shure of Mathworks, reminded me of a function, PolylineIntersectSegment.m, that I wrote to compute the intersection of a polyline with a line segment. This function nicely combines the topics of my last two posts,
use of complex variables as vectors and
lines, so I will discuss it in more detail. The use of complex variables simplifies the code and makes it easier to understand and modify.
A polyline
[1] is a set of connected line segments. Line segments are naturally specified by their start and end points instead of the
n and ŝ vectors described in my last post. An example is shown in Fig. 1↓
In a polyline, as shown in Fig.
3↓, the end point of one segment is the start point of the next. The four points (
1 − 4) define a three segment polyline (shown in blue). A polyline is in general not closed although it can be. In addition, the segments of the polyline can cross.
The PolylineIntersectSegment.m function code is based on the intersection between two segments
L1 and
L2 determined by their end points (see Fig.
2↓)
L1: P11, P12
L2: P21, P22
.
Letting the vectors
dk = Pk2 − Pk1, k = 1, 2 be the vectors from the start to the end points of the two segments, points on the segments are
r1 = P11 + sd1 and
r2 = P21 + td2 with
0 ≤ s < 1 and
0 ≤ t < 1. At the point of intersection,
r1 and r2 are equal
r1 = P11 + sd1 = r2 = P21 + td2
Rearranging terms
Now let
nk be vectors perpendicular to
dk, k = 1, 2.
If we use complex numbers to represent the vectors, we can compute the perpendicular vectors by multiplying by eiπ ⁄ 2 = i so nk = idk. Taking the dot product of both sides of Eq. 1↑, we can solve for sint and tint. Dotting first with n2 and solving
sint = (D⋅n2)/(d1⋅n2)
and then with n1
tint = − (D⋅n1)/(d2⋅n1).
We can then test that 0 ≤ s < 1 and 0 ≤ t < 1 for intersection points. I use open intervals to avoid duplicate hits when segments intersect at end points. You can change this test depending on how inclusive you want to make your definition of intersection to be. This will depend on your application so I do not think there is a single correct answer. The test in the code is shown below and it easy to change. If the segments are parallel or have zero length, then there will be a division by zero. Matlab will return a NaN for sint or tint and the logical test will return false indicating no intersection. You can also modify the code to test for these and do something different.
% test for intersection in PolylineIntersectSegment
intersectsOK = (s>=0)&(s<1)&(t>=0)&(t<1);
The actual point of intersection will be
Pintersect = P11 + sintd1
The code of PolylineIntersectSegment.m (see the
zip file for this post) shows how the use of complex variables simplifies things. As noted above, to find a perpendicular vector, multiply the vector by
i, which rotates it by
90 degrees. All the Matlab functions like
diff work with complex variables. The code is a straightforward implementation of the equations. Some examples are given with the
zip file and are shown in the box. The polyline in the third example is shown in Fig.
3↓.
%% intersect of 2 lines
zseg = [0 1i]; % line along the y axis
p1 = [-.5 .5] + 0.5*1i; % line segment parallel to x-axis at y=0.5
zi = PolylineIntersectSegment(zseg,p1);
disp(zi)
%% add another segment along same direction as first one but of zero length
% only chooses the intersection with the correct segment
p1null = [p1, p1(end)];
zi = PolylineIntersectSegment(zseg,p1null);
disp(zi)
%% add another segment along same direction as first one
% only chooses the intersection with the correct segment
p2 = [p1, (1.5+0.5i)];
zi = PolylineIntersectSegment(zseg,p2);
disp(zi)
%% add segment parallel to test segment in y-direction
% ignores segments to test segment
p3 = [p2,(1.5+2i)];
zi = PolylineIntersectSegment(zseg,p3);
disp(zi)
%% display results
fh = figure;
plot(p3,’-xb’)
hold on
plot(zseg,’-rd’)
plot(zi,’ok’)
hold off
axis([-2 2 -2 2])
The code uses the zdot function for the dot product of two vectors represented as complex variables.
function d = zdot(z1,z2) % dot product for complex vectors
d = real( z1(:) .* conj(z2(:)));
Last edited Sep. 1, 2011
© 2011 by Aprend Technology and Robert E. Alvarez
Linking is allowed but reposting or mirroring is expressly forbidden.
References
[1] Philip Schneider, David H. Eberly: Geometric Tools for Computer Graphics. Morgan Kaufmann, 2002.