2016-06-27 3 views
1

У меня есть данную область (скажем, 1000 х 1000), и я хочу, чтобы поместить круги в этой области с учетом следующих требований:Размещение кругов в данной области

  • Количество кругов произвольно, но фиксированный после его выбора в начале алгоритма. Номер должен быть таким, чтобы большая часть области была покрыта кругами.
  • Круги должны иметь в целом разные радиусы, а размеры радиусов должны быть в определенном интервале (например, между 20 и 80).
  • Кружки не должны пересекаться.

Я хочу реализовать код, который делает это с помощью matlab. До сих пор я достиг этого кода, который содержит для простоты только одно значение для радиуса:

%% Area 
perix=1000; 
periy=1000; 

%Number of circles 
numbercircles=100; 
radii(1:numbercircles)=70 

%% Placing Circles 

%first circle 
xi=rand*perix; % array for storing x-values of circle centers 
yi=radii(1);   %array for storing y-values of circle centers 
radiusarray=[radii(1)] ; %array for storing radii 
plot(sin(linspace(0,2*pi,100))*radii(1)+xi,cos(linspace(0,2*pi,100))*radii(1)+yi); 
hold on 
axis([0 perix 0 perix]) 

% Idea: 
%* Step 1: Random x coordinate for each circle middle point, y-coordinate at 
% the top of the area, y_init=periy, and given radius. 
%* Step 2: Lower y coordinate with constant x-coordinate until the distance to 
%neighbour spheres is lower than the combined radii of those spheres. 
%* Step 3: Move sphere on the x-axis to decrease the distance and further 
%decrease the y-value if possible. 

for lauf=2:numbercircles; 
    disp(numbercircles-lauf) 
    deltaz=10; 

    %% Step 1 
    % random x coordinate of sphere 
    x1=rand*100; 
    % y coordinate of circle is on the edge of the area and will be 
    % lower in the following 
    y1=periy; 
    Radnew=radii(lauf); 

    %% Step 2 
    %distance to other circle 
    d=min([sqrt((xi-x1).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi+perix)-x1).^2+(yi-y1).^2-(Radnew+radiusarray)) sqrt(((xi-perix)-x1).^2+(yi-y1).^2)-(Radnew+radiusarray)]); 

    while deltaz > 1e-4 
    %lower till y1=Radnew or distance to other spheres < 2*Rad 
     while ((y1>Radnew) & (d > deltaz)) 
        %number=number+1   
      % lower y1 
%    if a<2 
%    deltaz 
%    end 
       y1=y1-deltaz; 
      % recalculate distance to all other spheres 
      d=min([sqrt((xi-x1).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi+perix)-x1).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi-perix)-x1).^2+(yi-y1).^2)-(Radnew+radiusarray)]); 
     end; 
     dmaxakt=d; 
     %adjust position in x direction and y direction: Increasing 
     %x coordinate iteratively in small steps 
     if (y1>Radnew) 
      xz(1)=x1+deltaz*rand; 
      if xz(1)>perix 
       xz(1)=x1-perix; 
      elseif xz(1)<0 
       xz(1)=x1+perix; 
      end; 
      dz(1)=min([sqrt((xi-xz(1)).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi+perix)-xz(1)).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi-perix)-xz(1)).^2+(yi-y1).^2)-(Radnew+radiusarray)]); 

      xz(2)=x1-deltaz*rand; 
      if xz(2)>perix 
       xz(2)=x1-perix; 
      elseif xz(1)<0 
       xz(2)=x1+perix; 
      end; 
      dz(2)=min([sqrt((xi-xz(2)).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi+perix)-xz(2)).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi-perix)-xz(2)).^2+(yi-y1).^2)-(Radnew+radiusarray)]); 

      %determine which distance z is the largest 
      vmax=find(max(dz)==dz); 

      %set the x-value to the value which belongs to the largest 
      %distance 
      x1=xz(vmax(1)); 

     end; 
      %calculate new distance 
      d=min([sqrt((xi-x1).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi+perix)-x1).^2+(yi-y1).^2)-(Radnew+radiusarray) sqrt(((xi-perix)-x1).^2+(yi-y1).^2)-(Radnew+radiusarray)]); 
     if ((d>dmaxakt) & (y1>Radnew)) 
      dmaxakt=d; 
     else 
      deltaz=deltaz*1e-1; 
     end; 

    end; 
%  if (y1<1e-5) 
%   y1=rand;    
%  end; 
    %last check: test if y-coordinate is still in the area 
    if (y1<periy-Radnew) 
     %Assembling the arrays for the circle places 
     xi=[xi x1]; 
     yi=[yi y1]; 
     radiusarray=[radiusarray Radnew]; 
    end; 

    %Plotting 
    %zeit(lauf)=cputime-t; 
    plot(sin(linspace(0,2*pi,20))*Radnew+x1,cos(linspace(0,2*pi,20))*Radnew+y1); 
    %plot(sin(linspace(0,2*pi,20))*Rad1+x1+perix,cos(linspace(0,2*pi,20))*Rad1+y1); 
    %plot(sin(linspace(0,2*pi,20))*Rad1+x1-perix,cos(linspace(0,2*pi,20))*Rad1+y1); 
    hold on 
    axis([0 perix 0 perix]) 
    pause(0.0001); 
    saveas(gcf, 'circle.png') 
end; 

Код основном предполагает начальные координаты х, а максимальное у-координаты и понижает у-координата до перекрытия не обнаружено. Затем координаты x и y-координаты изменяются для достижения высокой плотности окружностей. Проблема этого кода заключается в том, что он очень медленный, потому что расстояние опускания y-координаты уменьшается в каждом цикле while, что означает, что время опускания сфер может быть очень большим. Я был бы признателен, если бы кто-нибудь мог придумать, как увеличить скорость этого кода.

+0

Вы посмотрели [это] (http://stackoverflow.com/questions/36177195/неперекрывающиеся-случайно расположенные круги) или [это] (http://stackoverflow.com/questions/36130596/matlab-how-to-generate-non-uniform-and-non-overlap-circle- прямоугольник-в-круге)? – beaker

+0

Это, вероятно, лучше подходит для [Code Review] (http://codereview.stackexchange.com/) TBH – excaza

+0

Я видел эти два вопроса, но в обоих случаях расстояние между кругами не минимизировано, поэтому это не подходит для моя проблема. Я не знал Code Review, я опубликую вопрос и там. – Tornado

ответ

0

Не уверен, если это поможет, но я проверил свой код, как вы разместили ее с профилировщика, и он говорит 98% времени сохраняет файл .png

Порядковый номер 111/SaveAs (ГКМ, «круг .png ')/99/47.741s/98.4%

Вы хотите изображение каждый раз, когда новый круг нарисован или только последний? В случае с лестницей просто положите «saveas (...)» за последний конец, а caluclation - до 1% времени.

+0

Это очень помогает, большое спасибо! :) – Tornado

Смежные вопросы