scatter randomized points with circles
    5 views (last 30 days)
  
       Show older comments
    
Hello,
How we can draw circles of radius R on randomized points in a area100*100? Knowing that its points are located in the following way:
The minimum distance between all points> 6 meters.
do you have an idea ?
Thank you
1 Comment
  Jan
      
      
 on 14 Feb 2017
				What is the difference to your question https://www.mathworks.com/matlabcentral/answers/322431-randompoints-condition-distance? Do you have the coordinates of the points already and only want to draw the circles?
Accepted Answer
  John BG
      
 on 20 Feb 2017
        Hi Marwen
Here are 2 functions that solve the question, not randomly guessing points from the entire area, but excluding gradually the area sized by already allocated points:
    function [X,Y,Nmax,Dmatrix,delay]=scatter_points7(void)
    % given H and W size of 2D rectangle scatter_points7.m does the following:
    % 1. calculate Nmax, the maximum amount of circles radius R0 that orderly fit in rectangle HxW
    % 2. scatter Ap random points with spatial resolution dx =- 0.1 and dy=0.1
    %           and spaced at least distance R0
    %           if requested amount Ap>Nmax rand2Dpoints breaks because there
    %           is no space to fit in so many random points complying with min
    %           distance R0
    % 3. calculate distance matrix Dmatrix among all points
    % 4. return the coordinates of all generated points in X and Y, along with Dmatrix and Nmax
    % 5. plot points
    % 6. plot safety circles to visually verify 
    % 
    % the amount of generated points is numel(X) and cannot be larger than Nmax 
    % because of the request for the points to be randomly generated.
    % 
    % in this initial version, only manual input through message box.
    % 
    % call examples:
    % 1.
    % [X,Y,Dmatrix,Nmax]=scatter_points7
    % 
    % 2.
    % [X,Y,Nmax]=scatter_points7
    % 2 examples how to verify distance values and check distances meet requirement > R0
    % 1.
    % L=combinator(Ap,2,'c'); 
    % relD2=((X(L(:,2))-X(L(:,1))).^2+(Y(L(:,2))-Y(L(:,1))).^2).^.5
    % find(relD2<R0)
    % 
    % 2.
    % L2=combinator(Ap,2);  
    % Dmatrix=reshape(((X(L2(:,2))-X(L2(:,1))).^2+(Y(L2(:,2))-Y(L2(:,1))).^2).^.5,[Ap Ap]);
    % Dmatrix([1:21:end])=NaN ;
    % Dmatrix(Dmatrix<6)
    % 
    % February 10th 2017
    % version: 1.0
    % author: John Bofarull Guix, any feedback to build next version is welcome at
    % jgb2012@sky.com or through the Mathworks website
    % this script was inspired by Mr Marwen Tarhoumi marwentarhoumi@rocketmail.com
    % and Matt Fig's popkenai@yahoo.com mighty function combinator.m available
    % from Mathworks File exchange
    clear all;clc;close all
    format bank
    rng('Shuffle')
    prompt = {'rectangle width W: ','rectange height H: ','amount points to scatter: ','safety distance Radius: '};
    dlg_title = 'Input';
    num_lines = 1;
    defaultans = {'100','100','20','3'};
    input_answer = inputdlg(prompt,dlg_title,num_lines,defaultans);
    Diam0=2*str2double(input_answer{4});
    W=str2double(input_answer{1})+Diam0;
    H=str2double(input_answer{2})+Diam0;
    Ap=str2double(input_answer{3});
    Ap=floor(Ap);
    Nmax=calc_amount_circles(W-Diam0,H-Diam0,Diam0/2);
    fprintf('\nRectangle %f x %f has\n max capacity: %i circles radius %f\n',W-Diam0,H-Diam0,Nmax,Diam0/2);
    if Nmax<Ap 
        fprintf('\nCannot fit in more than %i circles.\n',Nmax);
        X=0;Y=0;Nmax=0;Dmatrix=0;
        return; 
    end                                                         % error message in case requested amount points above Nmax
    As=21;                                                   % amount sides polygon approximating circles
    a=linspace(0,2*pi,As);                       % angle for  circles
    dx=1;dy=1;refine=0;
    X=zeros(1,Ap);Y=zeros(1,Ap);
    if W*H>=900^2
    dx=1;dy=1;
    refine=1;
    else
        dx=.1;dy=.1;
        refine=0;
    end
    x_grid=[(-W+Diam0)/2:dx:(W-Diam0)/2];y_grid=[(-H+Diam0)/2:dy:(H-Diam0)/2];       % avoid circles hitting frame
    [X_grid,Y_grid]=meshgrid(x_grid,y_grid);
    P=[X_grid(:)';Y_grid(:)'];[sz1P,sz2P]=size(P);
    if refine==0
    xc2_base=Diam0/2*cos(a);yc2_base=Diam0/2*sin(a); 
    elseif refine==1
        xc2_base=(Diam0/2+1)*cos(a);yc2_base=(Diam0/2+1)*sin(a); 
    end
    figure;ax=gca;ax.DataAspectRatio=[1 1 1];
    ax.XLim=[-W/2 W/2];ax.YLim=[-H/2 H/2];
    ax.XTick=[(-W+Diam0)/2:10:(W-Diam0)/2];ax.YTick=[(-H+Diam0)/2:10:(H-Diam0)/2];grid on;hold all;
    perimeter=[(-W+Diam0)/2-.25 (W-Diam0)/2+.25 (W-Diam0)/2+.25 (-W+Diam0)/2-.25 (-W+Diam0)/2-.25;
                         (-H+Diam0)/2-.25 (-H+Diam0)/2-.25 (H-Diam0)/2+.25 (H-Diam0)/2+.25 (-H+Diam0)/2-.25];
    plot(perimeter(1,:),perimeter(2,:),'Color',[.3 .3 .3]);
    tic;
    for k=1:1:Ap
       [sz1P,sz2P]=size(P);
       if sz2P>0
           nP = randi(sz2P,1,1);
           else
                break
       end
       if refine==0
           X(k)=P(1,nP);Y(k)=P(2,nP);
           elseif refine==1
                dec_xP=randi([0 499],1,1);dec_xP=dec_xP/1e3;  % worst case added jitter bringing 2 points on crash course
                dec_yP=randi([0 499],1,1);dec_yP=dec_yP/1e3;
                X(k)=P(1,nP)+dec_xP;Y(k)=P(2,nP);Y(k)=P(2,nP)+dec_yP;
       end
       xc2=xc2_base+X(k);yc2=yc2_base+Y(k);
       in=inpolygon(P(1,:),P(2,:),xc2,yc2);
       P(:,find(in>0))=[];                                                                          % exclude area already busy
        figure(1);plot(X(k),Y(k),'r*');                                                         % centre circles
        figure(1);plot(xc2,yc2,'Color',[0.8 0.8 1]);                                % circles radius Diam0/2
    end
    L2=combinator(Ap,2);  % test 2
    Dmatrix=reshape(((X(L2(:,2))-X(L2(:,1))).^2+(Y(L2(:,2))-Y(L2(:,1))).^2).^.5,[Ap Ap]);
    Dmatrix([1:Ap+1:end])=NaN ;
    hold off
    delay=toc;
    end
    function Anxny=calc_amount_circles(H_,L_,D_)
    % calculates 1. amount of circles in hex pattern that fit within 2D rectangle L (columns) x H (tall, lines or rows)
    % used graph from http://www.engineeringtoolbox.com/circles-within-rectangle-d_1905.html to calibrate
    R_=D_/2;
    if L_<(2*R_) 
        Nx=0; 
        else Nx=floor(L_/(2*R_));
    end;
    if H_<(2*R_) 
        Ny=0;
    else
        s=1;
        while H_/(2*R_+s*R_*3^.5)>1;
            s=s+1; 
        end
        Ny=s;
    end;
    if rem(L_,2*R_)>=R_
       min1_evenlines=0;
       else min1_evenlines=1; 
    end;
    Anxny=Nx*Ny-floor(Ny/2)*min1_evenlines;
    end
    % 
    % function handling_input_errors
    % % input checks
    % narginchk(5,5);nargoutchk(4,4);
    % 
    % err_message={'error input type W';'error input type H';'error input type R0';'error input type R0';'error input saturate'};
    % 
    % if(~isreal(H) || ~isscalar(W) || W<=0 )    
    %     error(err_message{1}); 
    % end
    % if(~isreal(H) || ~isscalar(H) || H<=0 )    
    %     error(err_message{2}); 
    % end
    % if(~isreal(R0) || ~isscalar(R0) || R0<=0 )    
    %     error(err_message{3});
    % end
    % 
    % if(~isreal(Ap) || ~isscalar(Ap) || Ap<=0 )    
    %     error(err_message{3}); 
    % end
    % if(~isreal(saturate) || ~isscalar(saturate) || saturate<0 || saturate>1)    
    %     error(err_message{3}); 
    % end
    % end
and the saturation:
function [X,Y,Nmax,Dmatrix]=scatter_points_saturate(W0,H0,R0)
% scatter_points_saturate.m
% given H and W size of 2D rectangle scatter_points7.m does the following:
% 1. calculate Nmax, the maximum amount of circles radius R0 that orderly fit in rectangle HxW
% 2. scatter as many random points as possible with spatial resolution dx =- 0.1 and dy=0.1
%           and spaced at least distance R0
% 3. calculate distance matrix Dmatrix among all points
% 4. return the coordinates of all generated points in X and Y, along with Dmatrix and Nmax
% 5. plot points
% 6. plot safety circles to visually verify 
% 
% the amount of generated points is numel(X) and cannot be larger than Nmax 
% 
% 
% call examples:
% 1.
% [X,Y,Dmatrix,Nmax]=scatter_points_saturate(100,100,3)
% 
% 2.
% [X,Y,Nmax]=scatter_points7
% 2 examples how to verify distance values and check distances meet requirement > R0
% 1.
% L=combinator(Ap,2,'c'); 
% relD2=((X(L(:,2))-X(L(:,1))).^2+(Y(L(:,2))-Y(L(:,1))).^2).^.5
% find(relD2<R0)
% 
% 2.
% L2=combinator(Ap,2);  
% Dmatrix=reshape(((X(L2(:,2))-X(L2(:,1))).^2+(Y(L2(:,2))-Y(L2(:,1))).^2).^.5,[Ap Ap]);
% Dmatrix([1:21:end])=NaN ;
% Dmatrix(Dmatrix<6)
% 
% February 10th 2017
% version: 1.0
% author: John Bofarull Guix, any feedback to build next version is welcome at
% jgb2012@sky.com or through the Mathworks website
% this script was inspired by Mr Marwen Tarhoumi marwentarhoumi@rocketmail.com
% and Matt Fig's popkenai@yahoo.com mighty function combinator.m available
% from Mathworks File exchange
% clear all;clc;close all
% format bank
% rng('Shuffle')
% R0=35
Diam0=2*R0;                                                                                      % distance requirement among adjacent points not to be closer than
% W0=50
% H0=70
W=W0+Diam0;                                                                                    % rectangle width, columns
H=H0+Diam0;                                                                                     % rectangle tall, row
   Nmax=calc_amount_circles(W0,H0,Diam0/2)
   Ap=20
As=21; a=linspace(0,2*pi,As);xc=Diam0*cos(a);yc=Diam0*sin(a);
dx=1;dy=1;
X=zeros(1,Ap);Y=zeros(1,Ap);
if W*H>=1e6
dx=1;dy=1;
else dx=.1;dy=.1;
end
X=zeros(1,Ap);Y=zeros(1,Ap);
x_grid=[-W0/2:dx:W0/2];y_grid=[-H0/2:dy:H0/2];                              % avoid circles hitting frame
[X_grid,Y_grid]=meshgrid(x_grid,y_grid);
% X_grid0=X_grid;Y_grid0=Y_grid;
P=[X_grid(:)';Y_grid(:)'];[sz1P sz2P]=size(P);
xc2_base=Diam0/2*cos(a);yc2_base=Diam0/2*sin(a); 
% xc1_base=Diam0*cos(a);yc1_base=Diam0*sin(a);
figure;ax=gca;ax.DataAspectRatio=[1 1 1]
ax.XLim=[-W/2 W/2];ax.YLim=[-H/2 H/2];
ax.XTick=[(-W+Diam0)/2:10:(W-Diam0)/2];ax.YTick=[(-H+Diam0)/2:10:(H-Diam0)/2];grid on;hold all;
perimeter=[(-W+Diam0)/2-.25 (W-Diam0)/2+.25 (W-Diam0)/2+.25 (-W+Diam0)/2-.25 (-W+Diam0)/2-.25;
                     (-H+Diam0)/2-.25 (-H+Diam0)/2-.25 (H-Diam0)/2+.25 (H-Diam0)/2+.25 (-H+Diam0)/2-.25];
plot(perimeter(1,:),perimeter(2,:),'Color',[.3 .3 .3]);
k=1
while sz2P>Diam0*.2
   k=k+1;
   [sz1P sz2P]=size(P);
   if sz2P>0
   nP = randi(sz2P,1,1);
   else
       break
   end
   X(k)=P(1,nP);Y(k)=P(2,nP);
%    xc1=xc1_base+X(k);yc1=yc1_base+Y(k);
   xc2=xc2_base+X(k);yc2=yc2_base+Y(k);
   in=inpolygon(P(1,:),P(2,:),xc2,yc2);
   in=in(:)';P(:,find(in>0))=[];                                                               % exclude area already busy
   figure(1);plot(X(k),Y(k),'g*');                                                             % centre circles
   figure(1);plot(xc2,yc2,'Color',[0.7 .9 0.7]);                                    % circles radius Diam0/2
end
L2=combinator(Ap,2);  % test 2
Dmatrix=reshape(((X(L2(:,2))-X(L2(:,1))).^2+(Y(L2(:,2))-Y(L2(:,1))).^2).^.5,[Ap Ap]);
Dmatrix([1:Ap+1:end])=NaN ;
end
function Anxny=calc_amount_circles(H_,L_,D_)
% calculates 1. amount of circles in hex pattern that fit within 2D rectangle L (columns) x H (tall, lines or rows)
% used graph from http://www.engineeringtoolbox.com/circles-within-rectangle-d_1905.html to calibrate
R_=D_/2;
if L_<(2*R_) 
    Nx=0; 
    else Nx=floor(L_/(2*R_)); 
end;
if H_<(2*R_) Ny=0;
else
    s=1;
    while H_/(2*R_+s*R_*3^.5)>1;
        s=s+1;  
    end
    Ny=s;
end;
if rem(L_,2*R_)>=R_
   min1_evenlines=0;
   else min1_evenlines=1; 
end;
Anxny=Nx*Ny-floor(Ny/2)*min1_evenlines;
end
function handling_input_errors
narginchk(5,5);nargoutchk(4,4);
err_message={'error input type W';'error input type H';'error input type R0';'error input type R0';'error input saturate'}
if(~isreal(H) || ~isscalar(W) || W<=0 )    error(err_message{1}); end
if(~isreal(H) || ~isscalar(H) || H<=0 )    error(err_message{2}); end
if(~isreal(R0) || ~isscalar(R0) || R0<=0 )    error(err_message{3}); end
Ap=floor(Ap); if(~isreal(Ap) || ~isscalar(Ap) || Ap<=0 )    error(err_message{3}); end
if(~isreal(saturate) || ~isscalar(saturate) || saturate<0 || saturate>1)    error(err_message{3}); end
end
the function combinator is available from here
attached scatter_points7.m and scatter_points_saturate.m
Appreciating time and attention
John Bofarull Guix
0 Comments
More Answers (2)
  Jan
      
      
 on 14 Feb 2017
        
      Edited: Jan
      
      
 on 20 Feb 2017
  
      You can obtain the coordinates from the solution posted here: https://www.mathworks.com/matlabcentral/answers/142322-find-n-random-points-with-a-minimum-distance-r-inside-a-2d-rectangular-box#answer_254413. Then to draw the circles:
nWant  = 20;
Dist   = 6;
[X, Y] = GetPointsRandom(nWant, 100, 100, Dist);
alpha = linspace(0, 2*pi, 32).';
% cx = X.' + 0.5 * Dist * cos(alpha);  % Matlab >= 2016b
% cy = Y.' + 0.5 * Dist * sin(alpha);  % Matlab >= 2016b
cx = bsxfun(@plus, X.', 0.5 * Dist * cos(alpha));
cy = bsxfun(@plus, Y.', 0.5 * Dist * sin(alpha));
figure;
AxesH = axes('NextPlot', 'add');
plot(cx, cy, 'b', 'Parent', AxesH);
axis equal
set(AxesH, 'XLim', [0, 100], 'YLim', [0, 100]);
7 Comments
  John BG
      
 on 23 Feb 2017
				the centre points are not 'a detail' but the utmost important point, it's the first thing you should plot when considering visual presentation of anything attempting to answer this and similar questions.
John BG
  Jan
      
      
 on 24 Feb 2017
				@John: The question was:
 How we can draw circles of radius R on randomized points in
 a area 100*100?
Then the center is "a detail [which] has not been mentioned".
See Also
Categories
				Find more on Descriptive Statistics and Visualization in Help Center and File Exchange
			
	Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!



