Как рассчитать угол от точек?
Я хочу получить простое решение для вычисления угла линии (например, указателя часов).
У меня есть 2 очка:
cX, cY - the center of the line.
eX, eY - the end of the line.
The result is angle (0 <= a < 360).
Какая функция может предоставить это значение?
Ответы
Ответ 1
Вы хотите арктангенс:
dy = ey - cy
dx = ex - cx
theta = arctan(dy/dx)
theta *= 180/pi // rads to degs
Erm, обратите внимание, что выше, очевидно, не компилируется 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;
}
Ответ 2
Бегущая версия христианского ответа.
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>
Ответ 3
Одна из проблем с получением угла между двумя точками или любым углом - это ссылка, которую вы используете.
В математике мы используем тригонометрический круг с началом справа от круга (точка в x = радиус, y = 0) и подсчитываем угол против часовой стрелки от 0 до 2PI.
В географии происхождение - это Север на 0 градусов, и мы идем по часовой стрелке от до 360 градусов.
Код ниже (в С#) получает угол в радианах, затем преобразуется в географический угол:
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;
}
Ответ 4
Если вы используете холст, вы заметите (если вы еще этого не сделали), что холст использует вращение по часовой стрелке (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;
}