Apologies if this is a stupid question, I'm relatively new to Matlab.
I've got an array of rectangles of class Rectangle with properties minx, miny, maxx, maxy, which represent the corner coordinates.
I'm trying to get the index of the top-left rectangle in the array.
I can loop through the objects to get the object that corresponds to the minimum x and y coordinates, but this doesn't seem like a very matlabic (matlabian? doesn't sound nearly as good as pythonic) way to do it.
minx = -1
miny = -1
tl_rect_id = 0
for id = 1:num_objects
if ((rectangles(id).minx < minx || minx == -1) && (rectangles(id).miny < miny || miny == -1))
tl_rect_id = id
minx = rectangles(id).minx
miny = rectangles(id).miny
end
% plot coordinates of top left corners
plot(rectangles(id).minx,rectangles(id).miny,'+r')
end
You don't need to use arrayfun to operate on arrays of objects in matlab. There's a very useful shorthand for getting an array of properties out of an array of objects:
[rectangles.minx]
That yields all rectangle's minx in an array.
So to know which is the point closest to the origin, I would calculate the good ol' euclidean distance to the origin. With the vectors at hand, that's REALLY simple.
The euclidean distance is defined as follows:
d(a,b) = sqrt( (a.x - b.x)^2 + (a.y - b.y)^2);
to calculate it with your vectors:
distances = sqrt([rectangles.minx].^2 + [rectangles.miny].^2)
This will yield a vector with the distances of all points. Finding the minimum is trivial:
[~, idx] = min(distances);
The min function returns a 1x2 array, the first position is the minimum value, the second is the index. I've used the matlab notation [~, idx] to state that I'm not interested in the first return value, and the second should be stored on the variable idx.
I've written an example in which I have created my rectangle class only to test it, but it will work with your class as well. Below are the codes for the class I've defined and the code that calculates the point closest to (0,0).
Run it to play with the idea and adapt it to your needs :)
Test Class definition (save that in a file called Rectangle.m):
classdef Rectangle
properties
minx;
miny;
end
methods
function obj = Rectangle(v1,v2)
if nargin > 1
obj.minx = v1;
obj.miny = v2;
end
end
end
end
Code
clear all;
numRect = 100;
rect_array = Rectangle(numRect);
% initialize rectangles
for n=1:numRect
r = Rectangle;
r.minx = 100*rand(1,1);
r.miny = 100*rand(1,1);
rect_array(n) = r;
end
% find point closest to the origin
[~, idx] = min(sqrt([rect_array.minx].^2 + [rect_array.miny].^2));
close all;
figure;
% plot the points in blue
plot([rect_array.minx],[rect_array.miny],'b.');
hold on;
% mark a red cross on the point closest to the origin
plot(rect_array(idx).minx, rect_array(idx).miny, 'rx');
Your code is finding either the rectangle that is further left, or the rectangle that it furthest up. If you aren't worried about multiple retangles having the same value for minx, you could do
[v i] = min(arrayfun(@(i)rectangles(i).minx, 1:num_objects))
fprintf('Furthest left rectangle is %g\n', i);
Alternatively, you could do:
[v i] = sortrows(cell2mat(arrayfun(@(i)[rectangles(i).minx; rectangles(i).miny], 1:num_objects, 'uniformoutput', 0))');
fprintf('Furthest left rectangle is %g\n', i(1));
which will sort by X and then Y, and then take the first in this ordering. This is slower because it does a sort. To get the exact behaviour of your algorithm above, you should probably just stick with the for loops, I think doing it concisely would be messy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With