Generating a uniform random distribution of points in a circle

Average rating
(0 votes)

In case anyone wants this simple code snippet. Plenty of examples on the web in python, mathematica etc. none in Igor. It generates points within a circle of radius 1, about the origin. It doesn't work by exclusion (generate random point and then delete those that fall outside the circle), which is a method that apparently saves some computation time.

////	@param	num	number of points to be generated
Function UniformCircle(num)
	Variable num
	Make/O/N=(num) xw,yw
	Variable tt,uu,rr
	Variable i
	for(i = 0; i < num; i += 1)
		tt = 2 * pi * (0.5 + enoise(0.5))
		uu = (0.5 + enoise(0.5)) + (0.5 + enoise(0.5))
		if(uu > 1)
			rr = 2 - uu
			rr = uu
		xw[i] = rr * cos(tt)
		yw[i] = rr * sin(tt)
	DoWindow/K resultPlot
	Display/N=resultPlot yw vs xw
	ModifyGraph/W=resultPlot mode=3,marker=8
	ModifyGraph/W=resultPlot width={Plan,1,bottom,left}

This snippet works because

This snippet works because of a subtlety in the code that is not immediately apparent. At first glance, it might appear that 'rr' has a uniformly distributed probability density function (pdf). If this were the case, then the 2D randomly distributed points would not have a uniform areal density. However, the random part of 'rr' is composed of the sum of two uniform independent 'enoise' pdfs. The sum for the total variable with mean offset 1 has a convolved pdf with a linear increase from rr =0 to 1, and gives the correct areal density. I point this out to those interested in extending or understanding the snippet, and are as lazy as I am to search out references.

Take a closer look at that

Take a closer look at that radial component. Compare a straightforward enoise() assignment and the code in the OP.

Function test(num)
Variable num
    make/o/n=(num) r1,r2
    Variable i,uu
	uu = (0.5 + enoise(0.5)) + (0.5 + enoise(0.5))
	if(uu > 1)
	        r2[i] = 2 - uu
		r2[i] = uu

Run the this code with e.g., 1e6 samples and execute the following commands:

wavestats/w r1
duplicate/o M_wavestats rs1
wavestats/w r2
duplicate/o M_wavestats rs2
Edit/K=0 root:rs1.ld,root:rs2.ld

Now compare the avg, sdev, rms, adev and skew between the two...

The OP did not state explicitly what is meant by "uniform". My own guess would be: density that is independent of location inside the circle. One can verify angular uniformity using StatsCircularMoments with the /KUPR, but clearly if the radial distribution was also strictly uniform then the density of points per unit area would be higher closer to the origin. A joint histogram for xw and yw can help display the results:

JointHistogram xw,yw
NewImage M_JointHistogram 

Back to top