【问题标题】:Placing Circles into a given area将圆圈放入给定区域
【发布时间】: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坐标的距离都在减小,这意味着降低球体的时间可能很长。如果有人能提出如何提高此代码速度的想法,我将不胜感激。

【问题讨论】:

  • 你看过thisthis吗?
  • 这可能更适合Code Review TBH
  • 我看到了这两个问题,但是在这两个问题中,圆圈之间的距离都没有最小化,所以这不适合我的问题。我不知道代码审查,我也会在那里发布问题。

标签: matlab optimization geometry


【解决方案1】:

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

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

每次绘制一个新圆时您都想要一张图片还是只画最后一个?在梯形图的情况下,只需将 'saveas(...)' 放在最后一端,计算时间减少到 1%

【讨论】:

    猜你喜欢
    • 2013-07-16
    • 2013-02-02
    • 1970-01-01
    • 2014-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多