TheodorBecker
TheodorBecker

Reputation: 249

Matlab: Avoid for-loop by using clever matrix indexing & find? How?

I've been getting into Matlab more and more lately and another question came up during my latest project. I generate several rectangles (or meshs) within an overall boundary. These meshs can have varying spacings/intervals.

I do so, because I want to decrease the mesh/pixel resolution of certain areas of a digital elevation model. So far, everything works fine. But because the rectangles can be chosen in a GUI, it might happen that the rectangles overlap. This overlap is what I want to find, and remove. Would they have the same spacing, e.g. rectangle 1&2 would look something like this:

[t1x, t1y] = meshgrid(1:1:9,1:1:9);
[t2x, t2y] = meshgrid(7:1:15,7:1:15);
[t3x, t3y] = meshgrid(5:1:17,7:1:24);

In this case, I could just use unique, to find the overlapping areas. However, they look more like this:

[t1x, t1y] = meshgrid(1:2:9,1:2:9);
[t2x, t2y] = meshgrid(7:3:15,7:3:15);
[t3x, t3y] = meshgrid(5:4:17,7:4:24);

Therefore, unique cannot be applied, because mesh 1 might very well overlap with mesh 2 without having the same nodes. For convenience and further processing, all rectangles / meshes are brought into column notation and put in one result matrix within my code:

result = [[t1x(:), t1y(:)]; [t2x(:), t2y(:)]; [t3x(:), t3y(:)]];

Now I was thinking about using 2 nested for-loops to solve this problem, sth like this (which does not quite work yet):

res = zeros(length(result),1);
for i=1:length(result)
    currX = result(i,1);
    currY = result(i,2);
    for j=1:length(result)
        if result(j,1)< currX < result(j+1,1) && result(j,2)< currY < result(j+1,2)
              res(j) = 1;
        end
    end
end

BUT: First of all, this does not quite work yet, because I get an out of bounds error due to length(result)=j+1 and moreover, res(j) = 1 seems to get overwritten by the loop. But this was just for testing and demonstratin anyway. Because the meshes shown here are just examples, and the ones I use are fairly big, the result Matrix contains up to 2000x2000 = 4 mio nodes --> lenght(result) ~4mio. Putting this into a nested for-loop running over the entire length will most likely kill my memory.

Therefore I was hoping to find a sophisticade solution which does not require a nested loop, but takes advantage of Matlabs find and clever matrix indexing. I am not able to think of something, but was hoping to get help here.

Discussions and help is very much appreciated!

Cheers,

Theo

Upvotes: 0

Views: 1954

Answers (1)

Oleg
Oleg

Reputation: 10686

Here follows a quick stab (not extensively tested):

% Example meshes
[t1x, t1y] = meshgrid(1:2:9,1:2:9);
[t2x, t2y] = meshgrid(7:3:15,7:3:15);

% Group points for convenience
A = [t1x(:), t1y(:)];
B = [t2x(:), t2y(:)];

% Compare which points of A within edges of B (and viceversa)
idxA = A(:,1) >= B(1,1) & A(:,1) <= B(end,1) & A(:,2) >= B(1,2) & A(:,2) <= B(end,2);
idxB = B(:,1) >= A(1,1) & B(:,1) <= A(end,1) & B(:,2) >= A(1,2) & B(:,2) <= A(end,2);

% Plot result of identified points
plot(A(:,1),A(:,2), '*r')
hold on
plot(B(:,1),B(:,2), '*b')
plot([A(idxA,1); B(idxB,1)], [A(idxA,2); B(idxB,2)], 'sk')

I squared the points that were identified as overlapping:

Overlapping meshes

Also, related to your question is this Puzzler: overlapping rectangles by Doug Hull of TMW.

Upvotes: 1

Related Questions