% balls = initialize_balls(n)
% Given the number of desired balls, return a set of balls with proper
% random positions and velocities. The set of balls is represented as
% a structure array, where each structure consists of 6 fields,
%    x (the x coordinate of the color data matrix)
%    y (the y coordinate of the color data matrix)
%    vx (the velocity in the x direction)
%    vy (the velocity in the y direction)
%    r (the radius of the ball)
%    color (the color of the ball as an index value of the colormap)
function balls = initialize_balls(cdata, n) %#codegen

%   Copyright 2010-2013 The MathWorks, Inc.

coder.extrinsic('colormap'); % Use MATLAB runtime to get colormap

% Get the number of colors. We initialize numColors to 0 (a scalar double
% value). This is because the compiler cannot analyze types of extrinsic
% functions.
numColors = 0; %#ok<NASGU>
numColors = size(colormap, 1);

% Limit is the number of balls the system can handle.
% If you enable dynamic memory allocation for this example, you can set this
% value to Inf.
limit = 100; 
assert(n <= limit);

% Initialize the base type of the structure array. Here we define all the
% fields of the base structure type that represents a ball.
ball.x = 0;
ball.y = 0;
ball.vx = 0;
ball.vy = 0;
ball.r = 0;
ball.color = int32(0);

% The compiler is unable to analyze the size of the 'balls' array.
% Therefore we use coder.varsize to specify the upper bound size of this
% array.
coder.varsize('balls', [1 limit]);

% Initially we have no balls
balls = repmat(ball,1,0);
% Add 'n' number of balls
for i = 1:n
    ok = false;
    while ~ok
        % Compute a random ball within the 'cdata' window.
        ball.x = rand() * size(cdata,2);
        ball.y = rand() * size(cdata,1);
        ball.vx = rand() * 5;
        ball.vy = rand() * 5;
        ball.r = rand() * 30 + 5;
        ball.color = int32(rand() * numColors)+1; % Index into color table
        % Add the ball to the set of balls. 
        balls = [balls ball];
        % Check if the ball is outside or overlapping on an existing ball
        ok = ~is_outside(cdata,ball) && ~space_occupied(balls(1:end-1),ball);
        if ~ok
            % Not ok. Remove the ball and try again
            balls = balls(1:end-1);
        end
    end
end
    
% Given a list of balls and a single ball, does the provided ball overlap
% with any of the existing balls?
function y = space_occupied(balls,ball)
y = false;
for i = 1:numel(balls)
    if do_overlap(balls(i), ball)
        y = true;
        return
    end
end

% Return true if ball1 and ball2 spatially overlap.
function y = do_overlap(ball1, ball2)
dx = abs(ball2.x - ball1.x);
dy = abs(ball2.y - ball1.y);
rsum = ball1.r + ball2.r + 3; % 3 units for extra separation
r2 = dx*dx + dy*dy;
y = r2 < rsum*rsum;
