MATLAB: Generate random (biased) points lying on two circumferences

circumferencedistributiongaussiannot uniformpointsrandomuniform

Hi, I need to generate an artificial data set as a test set for a machine learning program.
This dataset must consist in two circumferences, with the smaller one completely contained inside the larger one. Thus I need a way to randomly generate points lying in one of these two circumferences, also adding some noise on both X and Y coordinates to make things more realistic.
So I tried to code a very simple algorithm exploiting the circumference equation to get the Y coordinate after fixing the radius and generating a random X. I tried out many slightly different versions and the best I could came out gives me this result (with 1000 points):
It's easy to see that the distribution is far from being uniform, and this is due to the fact that I ignore the imaginary part for those points whose X is greater than the radius, which leads to those strange "bubbles" on the far left and right extremities of the circumferences. Does anyone have an algorithm that gives a better distribution?
I'm pretty sure there's something that can be done with a Gaussian, but I didn't figure it out correctly yet.
By the way this is my code:
function [ dataSet ] = innerCircleDataSet( n )
% Perturbation on the inner circumference
p = 0.125;
% Radius of the inner circumference
radius = 0.5;
half = ceil(n/2);
if (half == n/2)
half = half + 1;
end
dataSet = zeros(n,3);
% Random generation of point Xs.
dataSet(1:n/2,1) = -radius - p/2 + rand(floor(n/2),1) * (2*radius + p);
dataSet(half:n1) = -2*radius - p + rand(n-half+1,1) * (4*radius + 2*p);
% Random perturbation on the Ys.
r = - p/2 + rand(n,1) * p;
% Exploits circumference equation (x^2 + y^2 = r^2) to compute Y.
y(1:n/2,2) = real(sqrt((radius)^2 - dataSet(1:n/2,1).^2)) + r(1: n/2);
y(half:n,2)=real(sqrt((2*radius)^2-dataSet(half:n,1).^2))+2*r(half:n);
y = y(:,2);
% Array of 0s and 1s, multiplied by -2 and added 1 to get all -1 and 1.
sign = -2 * round(rand(n,1)) + 1;
% Randomly chooses between the positive and the negative real solution.
dataSet(:, 2) = sign .* y;
end
Thanks in advance for your help!

Best Answer

How about something based on this:
n = 500;
angles = 2*pi*rand(1,n);
r1 = 0.5 + 0.01 * randn(1,n/2);
r2 = 1 + 0.02 * randn(1, n/2);
[x y] = pol2cart(angles, [r1 r2]);
plot(x,y,'b+');