I'm having trouble to speed up the following function and reading through various "How to vectorize in Matlab/Octave" unfortunatelly has not helped me on this specific topic.
Here is what I want to achieve: I have a set of 2d sample points (given as x-y-coordinate pairs) and a set of line segments (also x-y-coordinate pairs). The points are approximately near the lines and I want to get the distance from each of the sample points to the nearest line segment, BUT only if I can project the sample perpendicular onto the line segment.
So while I have managed to put the algorithm into a nested for-loop and it gives me the correct result for the appended example, it is incredibly slow (as expected) for real datasets (about 4000 sample points and 6000 line segments) and besides, looks really ugly.
Can anyone help me to create a more sophisticated version of this piece of code?
Edit: The mathematics used in this algorithm can be looked up here: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
clc;
clear all;
close all;
ptsx = [0.5 3 5];
ptsy= [1 -1.5 0.5];
points = [ptsx; ptsy];
linesx = [0 2 4 6];
linesy = [0 0 0 0];
lines = [linesx; linesy];
% for each point in the sample dataset
for k=1:1:length(points(1,:))
clear 'distvec'
% calculate the distance to each line segment in the model dataset
for l=1:1:length(lines(1,:))-1
% vector of the line segment
a = [lines(1,l+1)-lines(1,l), lines(2,l+1)-lines(2,l)];
% vector from the start of the line segment to the sample point
b = [points(1,k) - lines(1,l), points(2,k) - lines(2,l)];
% check if the sample point can be projected onto the line segment
if norm(a) ~= 0
lba = dot(a,b)/norm(a)^2;
else
lba = -1;
end
if (lba >= 0) && (lba <= 1)
% calculate distance from sample point to single line segment
x1 = [lines(1,l) lines(2,l)];
x2 = [lines(1,l+1) lines(2,l+1)];
x0 = [points(1,k) points(2,k)];
dist = abs(det([x2-x1; x1-x0]))/norm(x2-x1);
distvec(end+1) = dist;
end
end
dist(end+1) = min(distvec);
end
figure;
hold on;
plot(ptsx, ptsy, 'bo');
plot(linesx, linesy, 'r-o');
xlim([-1 7]);
ylim([-2 2]);