【问题标题】:Non overlapping randomly located circles非重叠随机定位的圆圈
【发布时间】:2016-03-23 11:39:41
【问题描述】:

我需要随机生成固定数量的非重叠圆圈。我可以显示圆圈,在本例中为 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])

谢谢。

【问题讨论】:

  • 请显示您尝试检查重叠的内容。
  • 不一样,但让我想起了这一点:stackoverflow.com/q/7833534/97160
  • 我认为您可以使用 Tiles into Squares 将您的区域切割成正方形,然后在其中填充圆圈

标签: matlab


【解决方案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 的函数)。

【讨论】:

    【解决方案2】:

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

    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
    

    【讨论】:

      【解决方案3】:

      稍微修改了代码@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
      

      结束

      【讨论】:

        【解决方案4】:

        虽然这是一篇旧帖子,并且因为我在分享我的解决方案之前遇到了同样的问题,它使用匿名函数:https://github.com/davidnsousa/mcsd/blob/master/mcsd/cells.m。此代码允许从用户定义的单元半径分布创建 1、2 或 3-D 单元环境。目的是为生物组织中扩散的蒙特卡罗模拟创建一个复杂的环境:https://www.mathworks.com/matlabcentral/fileexchange/67903-davidnsousa-mcsd

        此代码的更简单但不太灵活的版本是二维环境的简单情况。下面创建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 是所有圈子的组合匿名函数。我相信,尽管它是一种蛮力解决方案,但它既快速又优雅。

        【讨论】:

          猜你喜欢
          • 2018-03-24
          • 1970-01-01
          • 1970-01-01
          • 2019-04-14
          • 2021-03-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-03-16
          相关资源
          最近更新 更多