2016-03-23 11 views
2

Ich brauche eine feste Anzahl von nicht überlappenden Kreisen nach dem Zufallsprinzip zu generieren. Ich kann Kreise angezeigt werden, in diesem Fall 20, befindet sich zufällig mit diesem Stück Code,Nicht überlappende zufällig angeordnete Kreise

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 

jedoch Kreise überlappen, und ich möchte, dies vermeiden. Dies wurde von früheren Benutzern mit Mathematica https://mathematica.stackexchange.com/questions/69649/generate-nonoverlapping-random-circles erreicht, aber ich benutze MATLAB und ich würde gerne dabei bleiben.

Für Reproduzierbarkeit, ist dies die Funktion, circle3, ich bin mit dem Kreis

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]) 

Danke zu ziehen.

+0

Bitte zeigen Sie, was Sie versucht haben, auf Überlappungen zu überprüfen. – SpamBot

+0

nicht das gleiche, aber erinnert mich daran: http://Stackoverflow.com/q/7833534/97160 – Amro

+0

Ich denke, Sie können Ihre Region mit Fliesen in Quadrate schneiden, und füllen Sie den Kreis dort – GameOfThrows

Antwort

1

Sie können eine Liste aller zuvor gezeichneten Kreise speichern. Nach Randomisierung eines neuen Kreises überprüfen, dass es die zuvor gezeichneten Kreise nicht schneidet.

Code-Beispiel:

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 

* Beachten Sie, dass, wenn die Menge von Kreisen zu groß ist relativ zu dem Bereich, in dem die x- und y-Koordinaten aus gezogen werden, die Schleife unendlich laufen kann. um es zu vermeiden - definieren Sie diesen Bereich entsprechend (es kann als eine Funktion von nCircles definiert werden).

output example

1

Wenn Sie mit zufrieden sind Brute-Forcing, betrachten diese Lösung:

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

0

leicht geänderten Code @drorco um sicherzustellen, dass genaue Anzahl der Kreise zu machen Ich möchte sind gezeichnet

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 

Ende

+0

@drorco, danke Sie und sehen Sie meine kleine Änderung. – Matilde