Phil
Phil

Reputation: 53

Finding the smallest distance in a set of points from the origin

I am to find the smallest distance between a given set of points and the origin. I have a matrix with 2 columns and 10 rows. Each row represents coordinates. One point consists of two coordinates and I would like to calculate the smallest distance between each point and to the origin. I would also like to determine which point gave this smallest distance.

In Octave, I calculate this distance by using norm and for each point in my set, I have a distance associated with them and the smallest distance is obviously the one I'm looking for. However, the code I wrote below isn't working the way it should.

function [dist,koor] = bonus4(S)     
 S= [-6.8667,  -44.7967; 
    -38.0136, -35.5284; 
     14.4552, -27.1413; 
     8.4996,   31.7294; 
    -17.2183,  28.4815; 
    -37.5100,  14.1941; 
    -4.2664,  -24.4428; 
    -18.6655,  26.9427; 
    -15.8828,  18.0170; 
     17.8440, -22.9164]; 
    for i=1:size(S) 
        L=norm(S(i, :)) 

     dist=norm(S(9, :)); 
          koor=S(9, :) ; 
end

i = 9 is the correct answer, but I need Octave to put that number in. How do I tell Octave that this is the number I want? Specifically:

 dist=norm(S(9, :));   
 koor=S(9, :);

I cannot use any packages. I found the geometry package online but I am to solve the task without additional packages.

Upvotes: 2

Views: 1599

Answers (1)

rayryeng
rayryeng

Reputation: 104535

I'll work off of your original code. Firstly, you want to compute the norm of all of the points and store them as individual elements in an array. Your current code isn't doing that and is overwriting the variable L which is a single value at each iteration of the loop.

You'll want to make L an array and store the norms at each iteration of the loop. Once you do this, you'll want to find the location as well as the minimum distance itself. That can be done with one call to min where the first output gives you the minimum distance and the second output gives you the location of the minimum. You can use the second output to slice into your S array to retrieve the actual point.

Last but not least, you need to define S first before calling this function. You are defining S inside the function and that will probably give you unintended results if you want to change the input into this function at each invocation. Therefore, define S first, then call the function:

 S= [-6.8667,  -44.7967; 
    -38.0136, -35.5284; 
     14.4552, -27.1413; 
     8.4996,   31.7294; 
    -17.2183,  28.4815; 
    -37.5100,  14.1941; 
    -4.2664,  -24.4428; 
    -18.6655,  26.9427; 
    -15.8828,  18.0170; 
     17.8440, -22.9164];

function [dist,koor] = bonus4(S)             
    %// New - Create an array to store the distances
    L = zeros(size(S,1), 1);

    %// Change to iterate over number of rows
    for i=1:size(S,1) 
        L(i)=norm(S(i, :)); %// Change
    end

    [dist,ind] = min(L); %// Find the minimum distance
    koor = S(ind,:); %// Get the actual point
end

Or, make sure you save the above function in a file called bonus4.m, then do this in the Octave command prompt:

octave:1> S= [-6.8667,  -44.7967; 
>         -38.0136, -35.5284; 
>          14.4552, -27.1413; 
>          8.4996,   31.7294; 
>         -17.2183,  28.4815; 
>         -37.5100,  14.1941; 
>         -4.2664,  -24.4428; 
>         -18.6655,  26.9427; 
>         -15.8828,  18.0170; 
>          17.8440, -22.9164];
octave:2> [dist,koor] = bonus4(S);

Though this code works, I'll debate that it's slow as you're using a for loop. A faster way would be to do this completely vectorized. Because using norm for matrices is different than with vectors, you'll have to compute the distance yourself. Because you are measuring the distance from the origin, you can simply square each of the columns individually then add the columns of each row.

Therefore, you can just do this:

S= [-6.8667,  -44.7967; 
    -38.0136, -35.5284; 
     14.4552, -27.1413; 
     8.4996,   31.7294; 
    -17.2183,  28.4815; 
    -37.5100,  14.1941; 
    -4.2664,  -24.4428; 
    -18.6655,  26.9427; 
    -15.8828,  18.0170; 
     17.8440, -22.9164]; 

function [dist,koor] = bonus4(S)     
    %// New - Computes the norm of each point
    L = sqrt(sum(S.^2, 2));

    [dist,ind] = min(L); %// Find the minimum distance
    koor = S(ind,:); %// Get the actual point

end

The function sum can be used to sum over a dimension independently. As such, by doing S.^2, you are squaring each term in the points matrix, then by using sum with the second parameter as 2, you are summing over all of the columns for each row. Taking the square root of this result computes the distance of each point to the origin, exactly the way the for loop functions. However, this (at least to me) is more readable and I daresay faster for larger sizes of points.

Upvotes: 1

Related Questions