非重叠随机定位的圆圈

时间:2016-03-23 11:39:42

标签: matlab

我需要生成固定数量的随机定位的非重叠圆圈。我可以用这段代码随机显示圈子,在这种情况下为20,

  for i =1:20
  x=0 + (5+5)*rand(1)
  y=0 + (5+5)*rand(1)
  r=0.5
  circle3(x,y,r)
  hold on 
  end

然而圆圈重叠,我想避免这种情况。以前的用户使用Mathematica https://mathematica.stackexchange.com/questions/69649/generate-nonoverlapping-random-circles实现了这一点,但我使用的是MATLAB,我想坚持下去。

为了重现性,这是我用来绘制圆圈的函数circle3

function h = circle3(x,y,r)
 d = r*2;
 px = x-r;
 py = y-r;
 h = rectangle('Position',[px py d d],'Curvature',[1,1]);
 daspect([1,1,1])

谢谢。

4 个答案:

答案 0 :(得分:1)

您可以保存以前绘制的所有圈子的列表。后 随机化一个新圆圈,检查它是否与先前绘制的圆相交。

代码示例:

nCircles = 20;
circles = zeros(nCircles ,2);
r = 0.5;

for i=1:nCircles
    %Flag which holds true whenever a new circle was found
    newCircleFound = false;

    %loop iteration which runs until finding a circle which doesnt intersect with previous ones
    while ~newCircleFound
        x = 0 + (5+5)*rand(1);
        y = 0 + (5+5)*rand(1);

        %calculates distances from previous drawn circles
        prevCirclesY = circles(1:i-1,1);
        prevCirclesX = circles(1:i-1,2);
        distFromPrevCircles = ((prevCirclesX-x).^2+(prevCirclesY-y).^2).^0.5;

        %if the distance is not to small - adds the new circle to the list
        if i==1 || sum(distFromPrevCircles<=2*r)==0
            newCircleFound = true;
            circles(i,:) = [y x];
            circle3(x,y,r)
        end

    end
    hold on
end

*请注意,如果圆的数量相对于绘制x和y坐标的范围太大,则循环可以无限运行。 为了避免它 - 相应地定义这个范围(它可以定义为nCircles的函数)。

output example

答案 1 :(得分:1)

如果您对暴力破解感到满意,请考虑以下解决方案:

N = 60;                        % number of circles
r = 0.5;                       % radius
newpt = @() rand([1,2]) * 10;  % function to generate a new candidate point

xy = newpt();  % matrix to store XY coordinates
fails = 0;     % to avoid looping forever
while size(xy,1) < N
    % generate new point and test distance
    pt = newpt();
    if all(pdist2(xy, pt) > 2*r)
        xy = [xy; pt];  % add it
        fails = 0;      % reset failure counter
    else
        % increase failure counter,
        fails = fails + 1;
        % give up if exceeded some threshold
        if fails > 1000
            error('this is taking too long...');
        end
    end
end

% plot
plot(xy(:,1), xy(:,2), 'x'), hold on
for i=1:size(xy,1)
    circle3(xy(i,1), xy(i,2), r);
end
hold off

enter image description here

答案 2 :(得分:0)

略微修改代码@drorco以确保绘制我想要的确切圆圈

nCircles = 20;
circles = zeros(nCircles ,2);
r = 0.5;
c=0; 

for i=1:nCircles
%Flag which holds true whenever a new circle was found
newCircleFound = false;

%loop iteration which runs until finding a circle which doesnt intersect with     previous ones
while ~newCircleFound & c<=nCircles
    x = 0 + (5+5)*rand(1);
    y = 0 + (5+5)*rand(1);

    %calculates distances from previous drawn circles
    prevCirclesY = circles(1:i-1,1);
    prevCirclesX = circles(1:i-1,2);
    distFromPrevCircles = ((prevCirclesX-x).^2+(prevCirclesY-y).^2).^0.5;

    %if the distance is not to small - adds the new circle to the list
    if i==1 || sum(distFromPrevCircles<=2*r)==0
        newCircleFound = true;
        c=c+1
        circles(i,:) = [y x];
        circle3(x,y,r)
    end

end
hold on

答案 3 :(得分:0)

尽管这是一篇过时的文章,并且因为在我想共享使用匿名函数的解决方案之前遇到了相同的问题,所以该解决方案使用了https://github.com/davidnsousa/mcsd/blob/master/mcsd/cells.m匿名函数。该代码允许根据用户定义的单元半径分布创建1、2或3D单元环境。目的是为生物组织中的扩散的蒙特卡罗模拟创建一个复杂的环境:https://www.mathworks.com/matlabcentral/fileexchange/67903-davidnsousa-mcsd

此代码的一个更简单但不太灵活的版本是2-D环境的简单情况。以下内容创建了N个随机分布且半径不为R且与其他单元格的距离为D不重叠的不重叠圆的空间分布。全部打包在长度为S的正方形区域中。

function C = cells(N, R, D, S)
  C = @(x, y, r) 0;
  for n=1:N
    o = randi(S-R,1,2);
    while C(o(1),o(2),2 * R + D) ~= 0
      o = randi(S-R,1,2);
    end
    f = @(x, y) sqrt ((x - o(1)) ^ 2 + (y - o(2)) ^ 2);
    c = @(x, y, r) f(x, y) .* (f(x, y) < r);
    C = @(x, y, r) + C(x, y, r) + c(x, y, r);
  end
  C = @(x, y) + C(x, y, R);
end

其中返回C是所有圈子的组合匿名函数。我认为,尽管这是一种蛮力解决方案,但它又快速又优雅。