web-dev-qa-db-de.com

Wie berechnet man einen Winkel aus Punkten?

Ich möchte eine einfache Lösung, um den Winkel einer Linie zu berechnen (wie ein Zeiger einer Uhr).

Ich habe 2 punkte:

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

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

Welche Funktion kann diesen Wert liefern?

37
durumdara

Sie wollen den Arkustangens:

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

Bitte beachten Sie, dass der obige Code offensichtlich keinen Javascript-Code kompiliert. Sie müssen die Dokumentation für die Funktion arctangent durchsehen.

Edit: Mit Math.atan2 (y, x) werden alle Sonderfälle und Zusatzlogik für Sie erledigt:

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;
}
82
Christian Mann

Lauffähige Version von Christians Antwort .

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>

11
TWiStErRob

Wenn Sie Leinwand verwenden, werden Sie feststellen (falls Sie dies nicht bereits getan haben), dass die Leinwand im Uhrzeigersinn gedreht wird(MDN) und y Achse ist umgedreht. Um konsistente Ergebnisse zu erhalten, müssen Sie Ihre angle-Funktion anpassen.

Von Zeit zu Zeit muss ich diese Funktion schreiben und jedes Mal muss ich nachsehen, da ich der Berechnung nie auf den Grund gehe.

Während die vorgeschlagenen Lösungen funktionieren, berücksichtigen sie nicht das Leinwandkoordinatensystem. Untersuchen Sie die folgende Demo:

Winkel aus Punkten berechnen - 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;
}
0
akinuri

Sie finden hier zwei Formeln, eine aus der positiven Achse x und gegen den Uhrzeigersinn

und eine von Norden und im Uhrzeigersinn.

Es gibt x = x2-x1 und y = y2 = y1. Es gibt E = E2-E1 und N = N2-N1.

Die Formeln funktionieren für jeden Wert von x, y, E und N.

Für x = y = 0 oder E = N = 0 ist das Ergebnis undefiniert.

f(x,y)=pi()-pi()/2*(1+sign(x))*(1-sign(y^2))

     -pi()/4*(2+sign(x))*sign(y)

     -sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))

f(E,N)=pi()-pi()/2*(1+sign(N))*(1-sign(E^2))

     -pi()/4*(2+sign(N))*sign(E)

     -sign(E*N)*atan((abs(N)-abs(E))/(abs(N)+abs(E)))
0

Ein Problem bei der Ermittlung des Winkels zwischen zwei Punkten oder einem beliebigen Winkel ist die von Ihnen verwendete Referenz.

In der Mathematik verwenden wir einen trigonometrischen Kreis mit dem Ursprung rechts vom Kreis (ein Punkt in x = Radius, y = 0) und zählen den Winkel gegen den Uhrzeigersinn von 0 bis 2PI.

In der Geographie ist der Ursprung im Norden bei 0 Grad und wir gehen im Uhrzeigersinn von bis zu 360 Grad.

Der folgende Code (in C #) ermittelt den Winkel im Bogenmaß und konvertiert ihn in einen geografischen Winkel:

    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
pasx