我需要生成固定数量的随机定位的非重叠圆圈。我可以用这段代码随机显示圈子,在这种情况下为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])
谢谢。
答案 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的函数)。
答案 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
答案 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
是所有圈子的组合匿名函数。我认为,尽管这是一种蛮力解决方案,但它又快速又优雅。