There are two ways to do this.
1. Kicking
The simplest way is to kick coordinates (px, py)
and check that they are within the desired area.
To make this check, do so:
- Calculate the distance from the generated point to the center
(cx, cy)
:
d = raiz((px - cx)² + (py - cy)²)
- Check if the distance
d
is within the smallest and largest radius allowed (r1
, r2
):
- To check if the generated point is in the desired quadrant, check if the coordinates are bigger* that the coordinates of the centre:
* In the case of the axle y
, whereas the original Cartesian plan, the correct one would be py
< cy
. However, usually this axis is reversed in the graphic systems we use in computers.
2. Calculating radius and angle
The second form is a little more complicated at first, but will result in a point that is known to be within the desired area.
- Calculate a radius
r
random between the smallest and largest radius allowed (r1
, r2
):
r = r1 + (r2 - r1) * rand
- Calculate an angle
a
within the desired circle quadrant:
- Calculate the coordinates
(px, py)
resulting:
px = r * cosseno(a)
py = r * seno(a)
* Formula using inverted coordinate system
Setting in motion Scenario #2
The script below implements the #2 method presented above. The coordinate calculation is basically what @bfavaretto implemented, but with a visual presentation of the results.
var data = {
cx: 150,
cy: 150,
r: 100,
r1: 40,
r2: 70
};
function desenharAlvo(ctx) {
//alvo completo
ctx.beginPath();
ctx.fillStyle = '#DDEEFF';
ctx.arc(data.cx, data.cy, data.r, 0, Math.PI * 2, false);
ctx.fill();
ctx.closePath();
//coordenadas
ctx.beginPath();
ctx.strokeStyle = '#000';
ctx.moveTo(data.cx, data.cy - data.r);
ctx.lineTo(data.cx, data.cy + data.r);
ctx.moveTo(data.cx - data.r, data.cy);
ctx.lineTo(data.cx + data.r, data.cy);
ctx.stroke();
ctx.closePath();
//raio menor
ctx.beginPath();
ctx.strokeStyle = '#8899AA';
ctx.arc(data.cx, data.cy, data.r1, 0, Math.PI * 2, false);
ctx.stroke();
ctx.closePath();
//raio maior
ctx.beginPath();
ctx.strokeStyle = '#8899AA';
ctx.arc(data.cx, data.cy, data.r2, 0, Math.PI * 2, false);
ctx.stroke();
ctx.closePath();
}
function desenharDardo(ctx, x, y) {
//alvo completo
ctx.beginPath();
ctx.fillStyle = '#F00';
ctx.arc(data.cx + x, data.cy + y, 1, 0, Math.PI * 2, false);
ctx.fill();
ctx.closePath();
}
function aremessarDardo() {
//passo 1
var r = data.r1 + (data.r2 - data.r1) * Math.random();
//passo 2
var a = Math.PI / 2 * Math.random();
//passo 3
var x = r * Math.cos(a);
var y = r * Math.sin(a);
desenharDardo(ctx, x, y);
}
var canvas = document.getElementById('alvo');
var ctx = canvas.getContext('2d');
desenharAlvo(ctx);
setInterval(aremessarDardo, 250);
<canvas id="alvo" width="300" height="300"></canvas>
Nice example :)
– bfavaretto
The Scenario of the example was brilliant, for sure, but it still lacks a question... The areas are not exactly divided into quadrants, they can vary, for example, in the image of the question the arc was divided into four, but what if it was divided, for example, into 20? How would it be to use only a segment of this circle with its equation?
– Gabriel Maia
@Gabrielmaia to vary in relation to the arc, you need to adjust only one line of code, namely the line that calculates the angle
a
. In this case, I value between0
andPI/2
, which corresponds to the first quadrant. whereas2*PI
corresponds to the entire circumference, you just need to define what is the initial and final angle, then calculating a random value between these two values.– utluiz