Least squares fit of a rectangle to a given shape/boundary - A MATLAB function

function rectangle_t = fit_rectangle(boundary_points)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Author - Onkar Raut, University of North Carolina at Charlotte

% Based on - A simple method for fitting of bounding rectangle to closed regions - D. Chaudhuri a , A. Samal b.

% fit_rectangle -   Function provides a least squares fit to the 

%                   given boundary points of an object of unknown shape. 

% Inputs - Boundary elements that must be a Nx2 array. (atleast 3 required)

% Output -

%       Bounding_points(4x2):

%       Function will return a struct consisting of the bounding points

%       equation_of_diagonals(2x2):

%       Function will return the equation of the diagonal in the form

%       y = mx +c (giving back m and c foreach diagonal). 

%       equation_of_bounding_sides(4x2):

%       Equation of the Bounding sides in the form y = mx +c

%       centroid(1x2): 

%       Location of the centroid in cartesian coordinates

m = boundary_points(:,1);

n = boundary_points(:,2);

centroid = [sum(m)/size(m,1) sum(n)/size(n,1)];

diff = [m n] - (centroid'*ones(1,size(m,1)))';

theta_maj = 0.5*atan(2*sum(diff(:,1).*diff(:,2))/sum(diff(:,1).^2-diff(:,2).^2));

theta_min = theta_maj(1,1)+pi;

class_ud = diff(:,2) - tan(theta_maj(1,1)).*diff(:,1);

class_lr = diff(:,2) - cot(theta_maj(1,1)).*diff(:,1);

max_up = find(class_ud == max(class_ud));

max_down = find(class_ud == min(class_ud));

extremes_ud = [m(max_up,1) n(max_up,1); m(max_down,1) n(max_down,1)];

max_l = find(class_lr == max(class_lr));

max_r = find(class_lr == min(class_lr));

extremes_lr= [m(max_l,1) n(max_l,1); m(max_r,1) n(max_r,1)];

x_1 = extremes_ud(1,1); y_1 = extremes_ud(1,2);

x_2 = extremes_ud(2,1); y_2 = extremes_ud(2,2);

x_3 = extremes_lr(1,1); y_3 = extremes_lr(1,2);

x_4 = extremes_lr(2,1); y_4 = extremes_lr(2,2);

t_lx(1,1) = (x_1*tan(theta_maj(1,1))+x_3*cot(theta_maj(1,1))+y_3-y_1)/(tan(theta_maj(1,1))+cot(theta_maj(1,1)));

t_ly(1,1) = (y_1*cot(theta_maj(1,1))+y_3*tan(theta_maj(1,1))+x_3-x_1)/(tan(theta_maj(1,1))+cot(theta_maj(1,1)));

t_rx(1,1) = (x_1*tan(theta_maj(1,1))+x_4*cot(theta_maj(1,1))+y_4-y_1)/(tan(theta_maj(1,1))+cot(theta_maj(1,1)));

t_ry(1,1) = (y_1*cot(theta_maj(1,1))+y_4*tan(theta_maj(1,1))+x_4-x_1)/(tan(theta_maj(1,1))+cot(theta_maj(1,1)));

    

b_lx(1,1) = (x_2*tan(theta_maj(1,1))+x_3*cot(theta_maj(1,1))+y_3-y_2)/(tan(theta_maj(1,1))+cot(theta_maj(1,1)));

b_ly(1,1) = (y_2*cot(theta_maj(1,1))+y_3*tan(theta_maj(1,1))+x_3-x_2)/(tan(theta_maj(1,1))+cot(theta_maj(1,1)));

b_rx(1,1) = (x_2*tan(theta_maj(1,1))+x_4*cot(theta_maj(1,1))+y_4-y_2)/(tan(theta_maj(1,1))+cot(theta_maj(1,1)));

b_ry(1,1) = (y_2*cot(theta_maj(1,1))+y_4*tan(theta_maj(1,1))+x_4-x_2)/(tan(theta_maj(1,1))+cot(theta_maj(1,1)));

bounding_points = [t_lx,t_ly;

        t_rx,t_ry;

        b_lx,b_ly;

        b_rx,b_ry];

m_1 = (t_ly-b_ry)/(t_lx-b_rx);

m_2 = (t_ry-b_ly)/(t_rx-b_lx);

equation_of_diagonals = [ m_1 -m_1*b_rx+b_ry;

                          m_2 -m_2*b_lx+b_ly     ];

m_1 = (t_ly-t_ry)/(t_lx-t_rx);

m_2 = (b_ly-b_ry)/(b_lx-b_rx);

m_3 = (t_ry-b_ry)/(t_rx-b_rx);

m_4 = (t_ly-b_ly)/(t_lx-b_lx);

equation_of_bounding_sides = [ m_1 -m_1*t_rx+t_ry

                               m_2 -m_2*b_rx+b_ry

                               m_3 -m_3*b_rx+b_ry

                               m_4 -m_4*b_lx+b_ly ];

rectangle_t = struct( ...

    'bounding_points', bounding_points, ...

    'equation_of_diagonals',equation_of_diagonals, ...

    'equation_of_bounding_sides',equation_of_bounding_sides, ...

    'centroid',centroid);

end