如何从点计算角度?

dur*_*ara 42 javascript function angle coordinates

我想得到一个简单的解决方案来计算一条线的角度(就像一个时钟的指针).

我有2分:

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

The result is angle (0 <= a < 360).
Run Code Online (Sandbox Code Playgroud)

哪个功能能够提供这个值?

Chr*_*ann 90

你想要arctangent:

dy = ey - cy
dx = ex - cx
theta = arctan(dy/dx)
theta *= 180/pi // rads to degs
Run Code Online (Sandbox Code Playgroud)

嗯,请注意,上面显然没有编译Javascript代码.您必须查看arctangent函数的文档.

编辑:使用Math.atan2(y,x)将为您处理所有特殊情况和额外逻辑:

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 伙计,我喜欢三角学. (5认同)
  • 注意,为了避免除以0,你应该先测试`dx == 0`; 如果是,则如果`dy> 0则返回90度,如果'dy <0`则返回270度. (5认同)
  • 差不多,它有一点错误:`theta*= 180/Math.PI`是正确的.你也不需要担心零分割,当使用`atan2()`时,它也会返回正确的值为0. (3认同)

TWi*_*Rob 12

Christian的答案的 Runnable版本.

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)
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


aki*_*uri 5

如果您使用的是画布,则会注意到(如果尚未使用的话)画布使用顺时针旋转(MDN)并且y轴已翻转。为了获得一致的结果,您需要调整angle功能。

有时,我需要编写此函数,并且每次都需要查找它,因为我从不深入计算。

虽然建议的解决方案有效,但它们并未考虑画布坐标系。检查以下演示:

从点计算角度-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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我试图理解为什么在结果中添加 90 度适用于我的情况。我刚刚注意到在 @pasx 回答中他有一条评论 `a -= (Math.PI/2); //shift by 90deg`,我在其他地方看到过提到 90deg。 (2认同)