Reputation: 6015
P
is an m*2
matrix of m
points([X Y]
), and R
is an n*4
matrix of n
rectangles ([X1 Y1 X2 Y2]
). I want to form an m*n
matrix, C
, in a way that C(i, j)
indicates if i-th point in P
lies inside j-th rectangle in R
.
Single point single rect:
This is the way I check if the point lies inside the rectangle:
c = (P(1)>=R(1))&(P(1)<=R(3))&(P(2)>=R(2))&(P(2)<=R(4));
for more readability:
c = (Px>=Rxmin)&(Px<=Rxmax))&(Py>=Rymin)&(Py<=Rymax);
In the code above I’m sure that R(1)<=R(3)
and R(2)<=R(4)
:
R(:, [1 3]) = sort(R(:, [1 3]), 2);
R(:, [2 4]) = sort(R(:, [2 4]), 2);
Multiple points multiple rects:
It's easy to mange m*1
and 1*n
cases (like second answer here). But I don't know how to vectorize m*n
case. I’m currently doing it using for loops:
m = size(P, 1);
n = size(R, 1);
C = false(m, n);
for i=1:n
C(:, i) = (P(:, 1)>=R(i, 1))&(P(:, 1)<=R(i, 3))& ...
(P(:, 2)>=R(i, 2))&(P(:, 2)<=R(i, 4));
end
How can I vectorize it for more efficiency?
Upvotes: 1
Views: 914
Reputation: 45752
I suggest you work with each column of P
and R
individually and then bitwise &
them at the end:
Px = P(:,1);
Rx1 = R(:,1).';
Rx2 = R(:,3).';
X1 = bsxfun(@ge, Px, Rx1);
X2 = bsxfun(@le, Px, Rx2);
Py = P(:,2);
Ry1 = R(:,2).';
Ry2 = R(:,4).';
Y1 = bsxfun(@ge, Py, Ry1);
Y2 = bsxfun(@le, Py, Ry2);
C = X1 & X2 & Y1 & Y2
Or if you prefer:
C = bsxfun(@ge, P(:,1), R(:,1).')& ... % X lower bound
bsxfun(@le, P(:,1), R(:,3).')& ... % X upper bound
bsxfun(@ge, P(:,2), R(:,2).')& ... % Y lower bound
bsxfun(@le, P(:,2), R(:,4).'); % Y upper bound
OP has provided this timing comparison
Upvotes: 1