Location of a point within the arc range

Asked

Viewed 581 times

4

I’m looking for a Javascript function that returns a random value within a range in the area of a circle. The interval would be along the radius with distances equivalent to the center point and the end point of the radius, also considering an interval of degrees within this circle.

inserir a descrição da imagem aqui

Given the image. The blue area: distance from the center point to the beginning of the interval and distance from the edge to the end of the interval; orange area: range allowed to the random function.

2 answers

4


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:

  1. Calculate the distance from the generated point to the center (cx, cy):
    • d = raiz((px - cx)² + (py - cy)²)
  2. Check if the distance d is within the smallest and largest radius allowed (r1, r2):
    • r1 < d < r2
  3. To check if the generated point is in the desired quadrant, check if the coordinates are bigger* that the coordinates of the centre:
    • px > cx
    • py > cy

* 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.

  1. Calculate a radius r random between the smallest and largest radius allowed (r1, r2):
    • r = r1 + (r2 - r1) * rand
  2. Calculate an angle a within the desired circle quadrant:
    • a = pi / 2 * rand *
  3. 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>

  • 2

    Nice example :)

  • 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?

  • @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 between 0 and PI/2, which corresponds to the first quadrant. whereas 2*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.

3

With a possible error of off-by-one in my random numbers, I think this is it:

// Ângulos mínimo e máximo no círculo, em radianos
var minDeg = Math.PI;
var maxDeg = Math.PI * 5/4;
// Ângulo sorteado
var ang = minDeg + ((maxDeg - minDeg) * Math.random());

// Valor do raio onde começa a área laranja
var minRaio = 10;
// Valor do raio onde termina a área laranja
var maxRaio = 20;
// Trecho sorteado do raio
var raio = minRaio + ((maxRaio - minRaio) * Math.random());

// Posição calculada
var x = raio * Math.cos(ang);
var y = raio * Math.sin(ang);

Note: this solution is based on the inverted coordinate system and is an implementation of the second method explained in the @utluiz response.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.