scatter randomized points with circles
12 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
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
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!