将圈子放入给定区域

时间:2016-06-27 14:48:07

标签: matlab optimization geometry

我有一个给定的区域(让我们说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坐标以实现高密度的圆。 该代码的问题在于它非常慢,因为在每个循环中降低y坐标的距离减小,这意味着降低球体的时间可能非常长。如果有人能想出如何提高此代码的速度,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

不确定这是否有帮助,但我在您使用探查器发布时检查了您的代码,它说98%的时间是保存.png文件

第111行/ saveas(gcf,'circle.png')/ 99 / 47.741s / 98.4%

每次绘制新圆圈或只是最后一个圆圈时,您想要一张照片吗?在梯形情况下,只需将'saveas(...)'放在最后一端,并且caluclation降低到1%的时间