Get the minimum value of a property from an array of objects

Apologies if this is a stupid question, I am relatively new to Matlab.

I have an array of rectangles of class Rectangle with properties minx, miny, maxx, maxy

that represent angular coordinates.

I am trying to get the index of the top left rectangle in an array.

I can loop through objects to get an object that matches the minimum x and y coordinates, but that doesn't seem like a very malabian (maclabian? Doesn't sound nearly as good as pythonic) way of doing 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

      

+3


source to share


2 answers


You don't need to use arrayfun to work with arrays of objects in Matlab. There's a very useful shorthand for getting an array of properties from an array of objects:

[rectangles.minx]

      

This gives the entire rectangle minx

in the array.

So, to find out which point is closer to the origin, I would calculate a good Euclidean distance to the origin. With vectors available it REALLY .

The Euclidean distance is defined as follows:

d(a,b) = sqrt( (a.x - b.x)^2 + (a.y - b.y)^2);

      

to compute it using your vectors:

distances = sqrt([rectangles.minx].^2 + [rectangles.miny].^2)

      

This will give 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 used matlab notation [~, idx]

to indicate that I am not interested in the first return value and the second should be stored in a variable idx

.

I wrote an example where I created my rectangle class just to test it, but it will work with your class too. Below are the codes for class i 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 (except in the Rectangle.m file):

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');

      

+4


source


Your code finds either the rectangle that is further left or the rectangle that is further away. If you are not worried about multiple parchments having the same meaning for minx, you can do

[v i] = min(arrayfun(@(i)rectangles(i).minx, 1:num_objects))
fprintf('Furthest left rectangle is %g\n', i);

      

Alternatively, you can 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 that order. It's slower because it pretends. To get the exact behavior of your algorithm above, you should probably just stick with for loops, I think doing that would be rough, it would be messy.

+2


source







All Articles