【发布时间】:2016-06-27 14:48:06
【问题描述】:
我有一个给定的区域(比如 1000 x 1000),我想在这个区域放置圆圈,并满足以下要求:
- 圆的数量是任意的,但在算法开始时选择后是固定的。该数字应使圆圈覆盖大部分区域。
- 圆一般应有不同的半径,半径的大小应在一定的区间内(例如在 20 到 80 之间)。
- 圆圈不得重叠。
我想用 matlab 实现一个代码。到目前为止,我已经完成了这段代码,为简单起见,它只包含一个半径值:
%% 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;
代码基本上假定初始 x 坐标和最大 y 坐标并降低 y 坐标直到检测到重叠。然后修改 x 坐标和 y 坐标以实现高密度的圆。 这段代码的问题是,它非常慢,因为在每个while循环中降低y坐标的距离都在减小,这意味着降低球体的时间可能很长。如果有人能提出如何提高此代码速度的想法,我将不胜感激。
【问题讨论】:
-
这可能更适合Code Review TBH
-
我看到了这两个问题,但是在这两个问题中,圆圈之间的距离都没有最小化,所以这不适合我的问题。我不知道代码审查,我也会在那里发布问题。
标签: matlab optimization geometry