MATLAB Answers

Generate N random uniformly distributed points in a specific area

85 ビュー (過去 30 日間)
Nick Josh
Nick Josh 2019 年 5 月 4 日
編集済み: John D'Errico 2019 年 5 月 4 日
I want to generate N random uniformly distributed points in the area between a circle of radius 1 and a square of side 2, both centered at origin like in the picture above.
How can I do that?
  1 件のコメント
John D'Errico
John D'Errico 2019 年 5 月 4 日
Like in the picture above? No picture shown.

サインインしてコメントする。

採用された回答

ytzhak goussha
ytzhak goussha 2019 年 5 月 4 日
Here's a simple way (edited)
Randomly distributed:
N=100; %number of points
n=1; %Iterator
x_range=[-1 1]; %Range of width
mid_point=[mean(x_range),mean(x_range)]; %Center of box
radius=1; %Radius of circle
point_arr=zeros(N,2); %This will hold the point
while n<=N
temp_xy = (x_range(2)-x_range(1)).*rand(1,2) + x_range(1); %Generate 2 random numbers x and y
d = pdist([temp_xy;mid_point],'euclidean'); %Find distance between the point generated and the middle
if d>radius %If the distance is smaller than the radius, discard it, else accept it
point_arr(n,:)=temp_xy;
n=n+1;
end
end
scatter (point_arr(:,1),point_arr(:,2))

その他の回答 (2 件)

ytzhak goussha
ytzhak goussha 2019 年 5 月 4 日
編集済み: ytzhak goussha 2019 年 5 月 4 日
Here's a different solution:
This one is evenly distributed and spaced. however it created 108 points or 92 point
x_range=[-1 1];
x=x_range(2)-x_range(1);
r=1;
N=100;
mid_point=[mean(x_range),mean(x_range)];
Ssq=x^2;
Sc=pi*1^2;
Sd=Ssq/Sc;
tot=100*Sd;
tot_x=round(sqrt(tot));
check=0;
while check<N
x_p=linspace(x_range(1),x_range(2),tot_x);
[X,Y] = meshgrid(x_p,x_p);
points_to_del=[];
for i1=1:tot_x
for j1=1:tot_x
temp_xy=[X(i1,j1),Y(i1,j1)];
d=pdist([temp_xy;mid_point],'euclidean');
if d<=r
points_to_del=[points_to_del;[i1,j1]];
end
end
end
for i1=1:size(points_to_del,1)
X(points_to_del(i1,1),points_to_del(i1,2))=nan;
Y(points_to_del(i1,1),points_to_del(i1,2))=nan;
end
X(isnan(X))=[];
Y(isnan(Y))=[];
check=size(X,2);
tot_x=tot_x+1;
end
scatter(X(:),Y(:))
xlim(x_range);
ylim(x_range);

John D'Errico
John D'Errico 2019 年 5 月 4 日
編集済み: John D'Errico 2019 年 5 月 4 日
+1 to ytzhak goussha for the correct solution of course. A rejection method is really the logical way to solve it. What I'll point out are some issues that you can consider, and some alternative methods.
The rejection fraction here is moderately large.
(4 - pi)/4*100
ans =
21.4601836602552
So 78.5% of the points will be rejected. That is not massively bad. You might want to do it all in one large, essentially unlooped approach. So instead generate more points than you need, but do it all at once.
nreq = 1000;
% an extra 20% in case we reject too many.
rejectfrac = (4 - pi)/4;
oversample = 0.2;
xy = [];
nxy = 0;
center = [0, 0];
rad = 1;
while nxy < nreq
% assume we have a circle incribed in a square. So the square has edge length of 2*rad.
nsample = ceil((1 + oversample)*(nreq - nxy)/rejectfrac);
% this mext line uses a feature found in R2016b or later.
xypoints = (rand(nsample,2)*2 - 1)*rad + center;
% delete points inside the circle.
xypoints(sum((xypoints - center).^2,2) <= rad^2,:) = [];
% were there enough points
xy = [xy;xypoints];
nxy = size(xy,1);
if nxy > nreq
xy = xy(1:nreq,:);
end
end
plot(xy(:,1),xy(:,2),'.')
axis equal
grid on
yline(0);
xline(0);
But, still we rejected 78.5% of the points. Could I have done better? Perhaps. One idea is to generate points initially that are less likely to have been rejected. So don't bother to generate points that are known to be fully inside the circle. I can think of several such ways off the top of my head. I might choose a smaller polygonal region that describes the region(s) of interest, then generate points randomly and uniformly inside the indicated polygon.
However, the extra work might be more effort to code than the cost of the CPU cycles to reject too many points. Computers are fast, and programmer time is costly. Code that is more complex to write is also more complex to debug and to maintain.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by