I have a given area (let's say 1000 x 1000), and I want to place circles in this area with the following requirements:
- The number of circles is arbitrary, but fixed after it was chosen at the begin of the algorithm. The number should be so that most of the area is covered by the circles.
- The circles shall have in general different radii, and the sizes of the radii shall be in a certain interval (e. g. between 20 and 80).
- The circles shall not overlap.
I want to implement a code which does this with matlab. So far I have accomplished this code, which contains for simplicity only one value for the radius:
%% Area
perix=1000;
periy=1000;
%Number of circles
numbercircles=100;
radii(1:numbercircles)=70
%% Placing Circles
%first circle
xi=rand*perix; % array for storing x-values of circle centers
yi=radii(1); %array for storing y-values of circle centers
radiusarray=[radii(1)] ; %array for storing radii
plot(sin(linspace(0,2*pi,100))*radii(1)+xi,cos(linspace(0,2*pi,100))*radii(1)+yi);
hold on
axis([0 perix 0 perix])
% Idea:
%* Step 1: Random x coordinate for each circle middle point, y-coordinate at
% the top of the area, y_init=periy, and given radius.
%* Step 2: Lower y coordinate with constant x-coordinate until the distance to
%neighbour spheres is lower than the combined radii of those spheres.
%* Step 3: Move sphere on the x-axis to decrease the distance and further
%decrease the y-value if possible.
for lauf=2:numbercircles;
disp(numbercircles-lauf)
deltaz=10;
%% Step 1
% random x coordinate of sphere
x1=rand*100;
% y coordinate of circle is on the edge of the area and will be
% lower in the following
y1=periy;
Radnew=radii(lauf);
%% Step 2
%distance to other circle
d=min([sqrt((xi-x1).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi+perix)-x1).^2+(yi-y1).^2-(Radnew+radiusarray)) sqrt(((xi-perix)-x1).^2+(yi-y1).^2)-(Radnew+radiusarray)]);
while deltaz > 1e-4
%lower till y1=Radnew or distance to other spheres < 2*Rad
while ((y1>Radnew) & (d > deltaz))
%number=number+1
% lower y1
% if a<2
% deltaz
% end
y1=y1-deltaz;
% recalculate distance to all other spheres
d=min([sqrt((xi-x1).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi+perix)-x1).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi-perix)-x1).^2+(yi-y1).^2)-(Radnew+radiusarray)]);
end;
dmaxakt=d;
%adjust position in x direction and y direction: Increasing
%x coordinate iteratively in small steps
if (y1>Radnew)
xz(1)=x1+deltaz*rand;
if xz(1)>perix
xz(1)=x1-perix;
elseif xz(1)<0
xz(1)=x1+perix;
end;
dz(1)=min([sqrt((xi-xz(1)).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi+perix)-xz(1)).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi-perix)-xz(1)).^2+(yi-y1).^2)-(Radnew+radiusarray)]);
xz(2)=x1-deltaz*rand;
if xz(2)>perix
xz(2)=x1-perix;
elseif xz(1)<0
xz(2)=x1+perix;
end;
dz(2)=min([sqrt((xi-xz(2)).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi+perix)-xz(2)).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi-perix)-xz(2)).^2+(yi-y1).^2)-(Radnew+radiusarray)]);
%determine which distance z is the largest
vmax=find(max(dz)==dz);
%set the x-value to the value which belongs to the largest
%distance
x1=xz(vmax(1));
end;
%calculate new distance
d=min([sqrt((xi-x1).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi+perix)-x1).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi-perix)-x1).^2+(yi-y1).^2)-(Radnew+radiusarray)]);
if ((d>dmaxakt) & (y1>Radnew))
dmaxakt=d;
else
deltaz=deltaz*1e-1;
end;
end;
% if (y1<1e-5)
% y1=rand;
% end;
%last check: test if y-coordinate is still in the area
if (y1<periy-Radnew)
%Assembling the arrays for the circle places
xi=[xi x1];
yi=[yi y1];
radiusarray=[radiusarray Radnew];
end;
%Plotting
%zeit(lauf)=cputime-t;
plot(sin(linspace(0,2*pi,20))*Radnew+x1,cos(linspace(0,2*pi,20))*Radnew+y1);
%plot(sin(linspace(0,2*pi,20))*Rad1+x1+perix,cos(linspace(0,2*pi,20))*Rad1+y1);
%plot(sin(linspace(0,2*pi,20))*Rad1+x1-perix,cos(linspace(0,2*pi,20))*Rad1+y1);
hold on
axis([0 perix 0 perix])
pause(0.0001);
saveas(gcf, 'circle.png')
end;
The code basically assumes an initial x-coordinate and the maximum y-coordinate and lowers the y-coordinate until overlap is detected. Then the x-coordinate and the y-coordinate are modified to achieve high density of the circles. The problem of this code is, that it is very slow, because the distance of lowering the y-coordinate is decreasing in every while-loop, which means that the time of lowering the spheres can be very long. I would appreciate if somebody could come up with an idea how to increase the speed of this code.