我正在尝试使用MATLAB为立方体中的非均匀尺寸球体(非重叠)生成随机位置。以下代码中的for循环似乎永远不会结束。我不知道代码中缺少什么。我没有运行代码。球体(n)= 10; dims = [10 10 10]
function [ c r ] = randomSphere( dims )
% creating one sphere at random inside [0..dims(1)]x[0..dims(2)]x...
% radius and center coordinates are sampled from a uniform distribution
% over the relevant domain.
% output: c - center of sphere (vector cx, cy,... )
% r - radius of sphere (scalar)
r = rand(1); % you might want to scale this w.r.t dims or other consideration
c = r + rand( size(dims) )./( dims - 2*r ); % make sure sphere does not exceed boundaries
function ovlp = nonOverlapping( centers, rads )
% check if several spheres with centers and rads overlap or not
ovlp = false;
if numel( rads ) == 1
return; % nothing to check for a single sphere
end
dst = sqrt( sum( bsxfun( @minus, permute( centers, [1 3 2] ),...
permute( centers, [3 1 2] ) ).^2, 3) );
ovlp = dst >= bsxfun( @plus, rads, rads.' ); %' all distances must be smaller than r1+r2
ovlp = any( ovlp(:) ); % all must not overlap
function [centers rads] = sampleSpheres( dims, n )
% dims is assumed to be a row vector of size 1-by-ndim
% preallocate
ndim = numel(dims);
centers = zeros( n, ndim );
rads = zeros( n, 1 );
ii = 1;
while ii <= n
[centers(ii,:), rads(ii) ] = randomSphere( dims );
if nonOverlapping( centers(1:ii,:), rads(1:ii) )
ii = ii + 1; % accept and move on
end
end
答案 0 :(得分:1)
如果不编写一行代码,我会提出以下想法: 在精细网格中(使用网格网格)将3d空间分散。现在,您将不再使用rand()作为坐标,而是随机为您的球体选择一个有效的预定义坐标元组。因此,首先选择当前球体的半径,然后从所有可能的坐标中过滤出有效的坐标,即带有半径的球体不会与边界或另一个球体相交。
Best,Nras。
答案 1 :(得分:0)
您可以迭代添加新的随机球体,检查它们是否有效(不与其他球体相交,不超过边界等),并接受有效的随机球体,直到您有足够的随机球体。
function [ c r ] = randomSphere( dims )
% creating one sphere at random inside [0..dims(1)]x[0..dims(2)]x...
% radius and center coordinates are sampled from a uniform distribution
% over the relevant domain.
%
% output: c - center of sphere (vector cx, cy,... )
% r - radius of sphere (scalar)
r = rand(1); % you might want to scale this w.r.t dims or other consideration
c = r + rand( size(dims) )./( dims - 2*r ); % make sure sphere does not exceed boundaries
既然我们知道如何生成单个随机球体,我们想知道如何检查几个球体是否重叠
function ovlp = nonOverlapping( centers, rads )
% check if several spheres with centers and rads overlap or not
ovlp = false;
if numel( rads ) == 1
return; % nothing to check for a single sphere
end
dst = sqrt( sum( bsxfun( @minus, permute( centers, [1 3 2] ),...
permute( centers, [3 1 2] ) ).^2, 3 );
ovlp = dst >= bsxfun( @plus, rads, rads.' ); %' all distances must be smaller than r1+r2
ovlp = any( ovlp(:) ); % all must not overlap
最后,我们可以按顺序开始生成几个球体,检查每个球体之后的重叠:
function [centers rads] = sampleSpheres( dims, n )
% dims is assumed to be a row vector of size 1-by-ndim
% preallocate
ndim = numel(dims);
centers = zeros( n, ndim );
rads = zeros( n, 1 );
ii = 1;
while ii <= n
[centers(ii,:), rads(ii) ] = randomSphere( dims );
if nonOverlapping( centers(1:ii,:), rads(1:ii) )
ii = ii + 1; % accept and move on
end
end
请注意,这种方法可能会让您陷入无限循环,以防您要求n
较小的dims
- {填充'所有空间的n
球体少于n
然后你无法生成新的。请谨慎选择dims
和r
,您可能还希望更好地控制采样{{1}}的分布。