Location of a point within the range of an arc

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 radius endpoint, also considering a range of degrees within this circle.

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

    
asked by anonymous 21.01.2015 / 18:27

2 answers

4

There are two ways to do this.

1. Kicking

The simplest way is to kick (px, py) coordinates and check if they are within the desired area.

To do this, do so:

  • Calculate the distance of the generated point from the center (cx, cy) :
    • d = raiz((px - cx)² + (py - cy)²)
  • Check that the d distance is within the smallest and largest allowed radius ( r1 , r2 ):
    • r1 < d < r2
  • To check if the generated point is in the desired quadrant, verify that the coordinates are larger * than the center coordinates:
    • px > cx
    • py > cy
  • * In the case of the y axis, considering that the original Cartesian plane, the correct one would be py < cy . However, generally this axis is inverted in the graphic systems that we use in the computers.

    2. Calculating radius and angle

    The second form is a bit more complicated at first, but will result in a point known to be within the desired area.

  • Calculate a random% radius between the smallest and the largest allowed radius (% with%,% with%):
    • r
  • Calculate an angle r1 within the desired quadrant of the circumference:
    • r2 *
  • Calculate the resulting r = r1 + (r2 - r1) * rand coordinates:
    • a
    • a = pi / 2 * rand
  • * Formula using the inverted coordinate system

    Putting Scenario # 2 into practice

    The script below implements method # 2 above. The calculation of the coordinate 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>
        
    21.01.2015 / 19:27
    3

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

    // Â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.     

    21.01.2015 / 19:26