saastn
saastn

Reputation: 6015

How to vectorize a pair-wise point inside rectangle (bounding box) check?

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

Answers (1)

Dan
Dan

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

enter image description here

Upvotes: 1

Related Questions