8

I have a basic JSFiddle whereby I want to have random points plotted inside a circle.

But I do not know how to limit the points to be inside the circle.

This is what I currently have:

var ctx = canvas.getContext('2d'), count = 1000, // number of random points cx = 150, cy = 150, radius = 148; ctx.beginPath(); ctx.moveTo(cx, cy); ctx.arc(canvas.width/2, canvas.height/2, radius, 0, 2*Math.PI); ctx.closePath(); ctx.fillStyle = '#00000'; ctx.fill(); // create random points ctx.fillStyle = '#ffffff'; while(count) { // randomise x:y ctx.fillRect(x + canvas.width/2, y + canvas.height/2, 2, 2); count--; } 

How would i go about generating random (x,y) coordinates to plot random points inside the circle?

My current fiddle: http://jsfiddle.net/e8jqdxp3/

4 Answers 4

17

To plot points randomly in a circle, you can pick a random value from the radius squared, then square root it, pick a random angle, and convert the polar coordinate to rectangular. The square / square root step ensures that we get a uniform distribution (otherwise most points would be near the center of the circle).

So the formula to plot a random point in the circle is the following, where r' is a random value between 0 and r2, and θ is a random value between 0 and :

Equation

Screenshot of result:

Screenshot of result

Live Demo:

var canvas = document.getElementById("thecanvas"); var ctx = canvas.getContext('2d'), count = 1000, // number of random points cx = 150, cy = 150, radius = 148; ctx.fillStyle = '#CCCCCC'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#000000'; ctx.beginPath(); ctx.moveTo(cx, cy); ctx.arc(canvas.width / 2, canvas.height / 2, radius, 0, 2 * Math.PI); ctx.closePath(); ctx.fill(); // create random points ctx.fillStyle = '#ffffff'; while (count) { var pt_angle = Math.random() * 2 * Math.PI; var pt_radius_sq = Math.random() * radius * radius; var pt_x = Math.sqrt(pt_radius_sq) * Math.cos(pt_angle); var pt_y = Math.sqrt(pt_radius_sq) * Math.sin(pt_angle); ctx.fillRect(pt_x + canvas.width / 2, pt_y + canvas.width / 2, 2, 2); count--; }
<canvas id="thecanvas" width="400" height="400"></canvas>

JSFiddle Version: https://jsfiddle.net/qc735bqw/

Sign up to request clarification or add additional context in comments.

7 Comments

Nice, You can avoid square / squareRoot with: r=Math.random()*radius then x = cx + r * Math.cos(pt_angle); and y = cy + r * Math.sin(pt_angle); and then fillRect(x,y,2,2). Also note that if the full radius is randomly selected, a 2px rect can escape the boundary of the circle because rects are defined with their x,y at top-left. A simple fix is to use (radius-2) or a lengthier fix is to trap that edge case when the angle is between -PI/2 and PI/2.
Thanks for this i was wondering if there is a simple way to do the same for an ellipse?
@Dave A simple way is to just scale the output when you draw it. So if you want a horizontal elipse, just instead of drawing x and y, draw x and y/2 (or maybe Math.floor(y/2)).
So i just divide the final y calculation by the given scale.
@Dave Yup. (minimum comment length filler text here)
|
3

Randomly pick dSquared (0..radius^2) and theta (0..2pi), then

x = sqrt(dSquared) cos(theta) y = sqrt(dSquared) sin(theta) 

Comments

1

This worked for me:

const getRandomCoordinateInCircle = radius => { var angle = Math.random() * Math.PI * 2; const x = Math.cos(angle) * radius * Math.random(); const y = Math.sin(angle) * radius * Math.random(); return { x, y }; }; console.log(getRandomCoordinateInCircle(1000); // { x: 118.35662725763385, y: -52.60516556856313 } 

Returns a random point with { x: 0, y: 0} as the centre of the circle.

Comments

0

JSFiddle

var ctx = canvas.getContext('2d'), count = 1000, // number of random points cx = canvas.width/2, cy = canvas.height/2, radius = 148; ctx.beginPath(); ctx.moveTo(cx, cy); ctx.arc(0+canvas.width/2, 0+canvas.height/2, radius, 0, 2*Math.PI); ctx.closePath(); ctx.fillStyle = '#00000'; ctx.fill(); ctx.fillStyle = '#ffffff'; while(count) { var x = Math.random() * canvas.width; var y = Math.random() * canvas.height; var xDiff = cx - x; var yDiff = cy - y; if(Math.sqrt(xDiff*xDiff+yDiff*yDiff)<radius) { ctx.fillRect(x, y, 2, 2); count--; } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.