2012-03-08 19 views
32

Voglio ottenere una soluzione semplice per calcolare l'angolo di una linea (come un puntatore di un orologio).Come calcolare un angolo dai punti?

Ho 2 punti:

cX, cY - the center of the line. 
eX, eY - the end of the line. 

The result is angle (0 <= a < 360). 

quale funzione è in grado di fornire questo valore?

+0

necessari almeno tre punti per calcolare un angolo. Qual è il tuo terzo? L'asse x o l'asse y? – Sirko

+2

Assumendo asse x –

+0

Riga a 2 dimensioni. – durumdara

risposta

72

si desidera che l'arcotangente:

dy = ey - cy 
dx = ex - cx 
theta = arctan(dy/dx) 
theta *= 180/pi // rads to degs 

Ehm, si noti che il codice Javascript di cui sopra non è ovviamente la compilazione. Dovrai consultare la documentazione per la funzione arctangent.

Edit: Utilizzando Math.atan2(y,x) gestirà tutti i casi particolari e la logica in più per voi:

function angle(cx, cy, ex, ey) { 
    var dy = ey - cy; 
    var dx = ex - cx; 
    var theta = Math.atan2(dy, dx); // range (-PI, PI] 
    theta *= 180/Math.PI; // rads to degs, range (-180, 180] 
    //if (theta < 0) theta = 360 + theta; // range [0, 360) 
    return theta; 
} 
+5

Uomo, ho adorato la trigonometria. – Purag

+5

Si noti che per evitare la divisione per 0, si dovrebbe verificare se 'dx == 0' prima; se lo è, quindi restituire 90 gradi se 'dy> 0' e 270 gradi se' dy <0'. –

+0

@EtiennePerot: ho ricordato un'altra funzione utile e ho aggiornato la mia risposta per utilizzarla. –

8

versione Runnable di Christian's answer.

function angle(cx, cy, ex, ey) { 
 
    var dy = ey - cy; 
 
    var dx = ex - cx; 
 
    var theta = Math.atan2(dy, dx); // range (-PI, PI] 
 
    theta *= 180/Math.PI; // rads to degs, range (-180, 180] 
 
    return theta; 
 
} 
 
function angle360(cx, cy, ex, ey) { 
 
    var theta = angle(cx, cy, ex, ey); // range (-180, 180] 
 
    if (theta < 0) theta = 360 + theta; // range [0, 360) 
 
    return theta; 
 
} 
 

 
show("right", 0, 0, 1, 0); 
 
show("top right", 0, 0, 1, 1); 
 
show("top", 0, 0, 0, 1); 
 
show("top left", 0, 0, -1, 1); 
 
show("left", 0, 0, -1, 0); 
 
show("bottom left", 0, 0, -1, -1); 
 
show("bottom", 0, 0, 0, -1); 
 
show("bottom right", 0, 0, 1, -1); 
 

 
// IGNORE BELOW HERE (all presentational stuff)
table { 
 
    border-collapse: collapse; 
 
} 
 
table, th, td { 
 
    border: 1px solid black; 
 
    padding: 2px 4px; 
 
} 
 
tr > td:not(:first-child) { 
 
    text-align: center; 
 
} 
 
tfoot { 
 
    font-style: italic; 
 
}
<table> 
 
    <thead> 
 
    <tr><th>Direction*</th><th>Start</th><th>End</th><th>Angle</th><th>Angle 360</th></tr> 
 
    </thead> 
 
    <tfoot> 
 
    <tr><td colspan="5">* Cartesian coordinate system<br>positive x pointing right, and positive y pointing up.</td> 
 
    </tfoot> 
 
    <tbody id="angles"> 
 
    </tbody> 
 
</table> 
 
<script> 
 
function show(label, cx, cy, ex, ey) { 
 
    var row = "<tr>"; 
 
    row += "<td>" + label + "</td>"; 
 
    row += "<td>" + [cx, cy] + "</td>"; 
 
    row += "<td>" + [ex, ey] + "</td>"; 
 
    row += "<td>" + angle(cx, cy, ex, ey) + "</td>"; 
 
    row += "<td>" + angle360(cx, cy, ex, ey) + "</td>"; 
 
    row += "</tr>"; 
 
    document.getElementById("angles").innerHTML += row; 
 
} 
 
</script>

0

Uno del problema con ottenere l'angolo tra due punti o qualsiasi angolo è il riferimento che si usa.

In matematica si utilizza un cerchio trigonometrico con l'origine a destra del cerchio (un punto in x = raggio, y = 0) e conteggia l'angolo in senso antiorario da 0 a 2PI.

In geografia l'origine è il Nord a 0 gradi e andiamo in senso orario da a 360 gradi.

Il codice qui sotto (in C#) ottiene l'angolo in radianti poi si trasforma in un angolo di geografica:

public double GetAngle() 
    { 
     var a = Math.Atan2(YEnd - YStart, XEnd - XStart); 
     if (a < 0) a += 2*Math.PI; //angle is now in radians 

     a -= (Math.PI/2); //shift by 90deg 
     //restore value in range 0-2pi instead of -pi/2-3pi/2 
     if (a < 0) a += 2*Math.PI; 
     if (a < 0) a += 2*Math.PI; 
     a = Math.Abs((Math.PI*2) - a); //invert rotation 
     a = a*180/Math.PI; //convert to deg 

     return a; 
    } 
0

Se stai usando tela, si noterà (se non l'hai già fatto) che tela utilizza la rotazione in senso orario (MDN) e l'asse viene capovolto. Per ottenere risultati coerenti, è necessario modificare la funzione angle.

Di tanto in tanto, ho bisogno di scrivere questa funzione e ogni volta ho bisogno di cercarlo, perché non arrivo mai in fondo al calcolo.

Mentre le soluzioni suggerite funzionano, non prendono in considerazione il sistema di coordinate del canvas. Esaminare il seguente demo:

Calculate angle from points - JSFiddle

function angle(originX, originY, targetX, targetY) { 
    var dx = originX - targetX; 
    var dy = originY - targetY; 

    // var theta = Math.atan2(dy, dx); // [0, Ⲡ] then [-Ⲡ, 0]; clockwise; 0° = west 
    // theta *= 180/Math.PI;   // [0, 180] then [-180, 0]; clockwise; 0° = west 
    // if (theta < 0) theta += 360;  // [0, 360]; clockwise; 0° = west 

    // var theta = Math.atan2(-dy, dx); // [0, Ⲡ] then [-Ⲡ, 0]; anticlockwise; 0° = west 
    // theta *= 180/Math.PI;   // [0, 180] then [-180, 0]; anticlockwise; 0° = west 
    // if (theta < 0) theta += 360;  // [0, 360]; anticlockwise; 0° = west 

    // var theta = Math.atan2(dy, -dx); // [0, Ⲡ] then [-Ⲡ, 0]; anticlockwise; 0° = east 
    // theta *= 180/Math.PI;   // [0, 180] then [-180, 0]; anticlockwise; 0° = east 
    // if (theta < 0) theta += 360;  // [0, 360]; anticlockwise; 0° = east 

    var theta = Math.atan2(-dy, -dx); // [0, Ⲡ] then [-Ⲡ, 0]; clockwise; 0° = east 
    theta *= 180/Math.PI;   // [0, 180] then [-180, 0]; clockwise; 0° = east 
    if (theta < 0) theta += 360;  // [0, 360]; clockwise; 0° = east 

    return theta; 
} 
Problemi correlati