Состояние неперекрывающейся сферы

Я хочу проверить условие, чтобы две сферы не пересекались. Это означало бы, что расстояние между двумя сферами должно быть больше (r1 + r2). Я разместил полный код ниже, кажется, что-то не так со второй функцией, которая проверяет условие неперекрытия. Я могу запустить код без этого условия, но когда я включаю его, он не выполняется. Значение переменных равно dims = [ 10 10 10 ] и n = 25; Дайте мне знать, что вы думаете, есть ли другой лучший способ сформулировать это условие?

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
disp (centers);
disp (rads);

person skonda2    schedule 21.08.2014    source источник
comment
whos информация о centers и rads?. Может быть, привести их пример?   -  person Divakar    schedule 21.08.2014
comment
Привет! Я просто добавил более подробное объяснение проблемы.   -  person skonda2    schedule 21.08.2014


Ответы (2)


По сути, вы добавляете новые сферы на основе расстояния между центрами сфер и их радиусов. Итак, вам нужно сравнить все сферы с последним дополнением, которое будет centers(end,:) и rads(end).

Вот что делает эта функция -

function not_ovlp = nonOverlapping( centers, rads )

if numel( rads ) == 1
    not_ovlp = true;
    return; % nothing to check for a single sphere
end

center_dist = sqrt(sum(bsxfun(@minus,centers(1:end-1,:),centers(end,:)).^2,2));
radsum = rads(end) + rads(1:end-1);
not_ovlp = all(center_dist > radsum);

return;

Он выдает результат как true, когда есть not an overlap.


Пояснение с примером

Предположим, вы начинаете добавлять сферы в этот список непересекающихся сфер. Итак, вы выбираете первую сферу с центром (1,2,1) и радиусом 2. Затем для следующего у вас есть (3,4,2) в качестве центра с радиусом 0.5.

Таким образом, у вас есть -

centers =[
    1 2 1;
    3 4 2]

rads = [2;0.5]

Теперь вам нужно проверить, перекрывается ли эта последняя сфера с ранее выбранной сферой (сферами) или нет, что вы можете узнать с помощью ранее указанной функции -

nonOverlapping( centers, rads )

Это дает 1, предполагая, что это новое дополнение не перекрывается и может быть включено в список.

person Divakar    schedule 21.08.2014
comment
Привет! Это немного сложнее. Я разместил полный код, который пытаюсь запустить. Так что если две сферы перекрываются, то она должна разрываться и искать другие случайные координаты центров и рад и так далее. Вся цель кода состоит в том, чтобы сгенерировать случайную непересекающуюся сферу, упаковываемую в куб. - person skonda2; 21.08.2014
comment
Функция @ skonda2 nonOverlapping должна возвращать true, если она не перекрывается? - person Divakar; 21.08.2014
comment
Да! Поэтому, когда он возвращает true, центры и радиусы становятся спецификацией для одной сферы... таким образом, мы добавим 25 сфер, у которых будут уникальные центры и радиусы. - person skonda2; 21.08.2014
comment
Я предполагаю, что что-то не так, потому что, когда я вызываю основную функцию sampleSpheres, которая в основном выполняет распределение центра и радиуса для всех 25 сфер. Он не идет вперед в цикле while. - person skonda2; 21.08.2014
comment
@ skonda2 В качестве эксперимента попробуйте с меньшими радиусами (что дает больше шансов найти непересекающиеся), например, r = rand(1)/10 или r = rand(1)/20 внутри randomSphere, может быть? - person Divakar; 21.08.2014
comment
Я получаю следующую ошибку Ошибка в nonOver (строка 3), если numel( rads ) == 1 Выходной аргумент not_ovlp (и, возможно, другие) не назначен во время вызова C:\Users\Konda\Documents\MATLAB\nonOver.m›nonOver . В идентификаторе неперекрывающейся функции чего-то не хватает. - person skonda2; 21.08.2014
comment
@skonda2 Добавлено not_ovlp = true;, когда numel(rads) is 1 пропустить первое добавление. Проверьте отредактированный код. - person Divakar; 21.08.2014
comment
Ага! В этом была проблема. Вроде работает. Я попробую некоторые крайние случаи, чтобы сделать весь код немного надежным, и визуализирую случайные сферы в коробке, чтобы убедиться, что с упаковкой все в порядке. - person skonda2; 21.08.2014
comment
@ skonda2 Точно, их визуализация сделает решение конкретным! Дайте мне знать, как это происходит! - person Divakar; 21.08.2014

Или просто перебирайте все возможные комбинации сфер, пока не пройдут все или одна из них.

ovlp = false;

% assume centers is mx3 matrix for m sphere centres
numSpheres = size(centers,1);

for k=1: numSpheres
    for m=k+1:numSpheres
        dist = sqrt((centers(k,1)-centers(m,1))^2 + (centers(k,2)-centers(m,2))^2 ...
                    + (centers(k,3)-centers(m,3))^2);
        if dist <= (rads(k)+rads(m))
            ovlp = true;
            break;
        end
     end
     if ovlp
         break;
     end
end

Разве что вам нужно знать, какие сферы пересекаются, а какие нет.

EDIT ошибка во внутреннем цикле for выше. Следует выполнять итерацию от k+1 до numSpheres, а не от 2.

person Geoff    schedule 21.08.2014
comment
Я разместил полный код. Таким образом, основной алгоритм randomSphere выдает случайный радиус и центр. Затем функция nonOverlapping проверяет, перекрываются ли центр и радиусы с первой сферой. Если выдает true, то у нас в коробке две сферы. Если он возвращает false, то ломается и проверяет другие центры и радиус. Так продолжается до тех пор, пока в коробке не окажется 25 сфер. - person skonda2; 21.08.2014