Прошу прощения, за 20 с лишним лет не довелось воспользоваться тригонометрией ни разу, так что всё поистёрлось в памяти.
Можно представить, что машина расположена в координатах[0: 0] и она направлена на север, обозначая свой угол по отношению к началу отсчёта равным 90 градусов. Навигатору поступила команда прибыть в точку [-2: -1], для чего он вычисляет имеющимися средствами угол поворота(116.56505117707799) и дистанцию(2.23606797749979). Для наблюдателя рисунка, очевидно, что к текущему углу нужно прибавить положительное значение угла, чтобы поворот оказался верным. Вот только до точки [2: -1] возвращается тот же угол и дистанция.
Несколько упростил код расчёта угла между векторами отсюда.
class Point {
__New(x, y) {
this.x := x
this.y := y
}
Dot(other_point) { ; -> float
return this.x * other_point.x + this.y * other_point.y
}
Distance(other_point) { ; -> float
diff_x := this.x - other_point.x
diff_y := this.y - other_point.y
return Sqrt(diff_x**2 + diff_y**2)
}
}
class Vec {
__New(start_point, end_point) {
this.start := start_point
this.end := end_point
}
DiffPoint() { ; -> Point
s := this.start
e := this.end
return new Point(e.x - s.x, e.y - s.y)
}
Angle(other_vec) { ; -> float
dp1 := this.DiffPoint()
dp2 := other_vec.DiffPoint()
return ACos(dp1.Dot(dp2) / dp1.Dot(dp1)**0.5 / dp2.Dot(dp2)**0.5) * 57.29578
}
}
src_point := new Point(0, 0)
dest_point := new Point(-2, -1)
anotnter_same_point := new Point(2, -1)
perpendicular_point := new Point(-2, 0)
; Вектор произвольной длины по оси Y в текущем направлении
vec1 := new Vec(src_point, new Point(0, 1))
vec2 := new Vec(src_point, dest_point)
vec3 := new Vec(src_point, anotnter_same_point)
vec4 := new Vec(src_point, perpendicular_point)
MsgBox % "Угол: " . vec1.Angle(vec2) . " | расстояние: " . src_point.Distance(dest_point)
MsgBox % "Угол: " . vec1.Angle(vec3) . " | расстояние: " . src_point.Distance(anotnter_same_point)
MsgBox % "Угол: " . vec1.Angle(vec4) . " | расстояние: " . src_point.Distance(perpendicular_point)
Madmer пишет:Чтобы определить направление поворота из точки A в точку B, вам нужно сравнить угол между вектором от A до B и вектором от A до положительной оси X (которая имеет угол 90 градусов по отношению к A). Если угол между двумя векторами находится в диапазоне [0,90], то поворот происходит вправо. ...
Но потом, например, вектор будет иметь направление A -> B и находиться в точке B и для следующей произвольной точки, например в [-3: 2], это уже не сработает.
Madmer пишет:Также можно использовать скалярное произведение. Скалярное произведение двух векторов будет положительным, если угол между ними против часовой стрелки, и отрицательным по часовой.
Простите, если путаю, но при гуглении, под векторами мне всё время предстают последовательности чисел, аля [1, 3, 5] и так далее и скалярное произведение двух векторов выглядит как сумма последовательно перемноженных членов этих векторов. А тут вектор — это последовательность точек. Если я правильно понимаю "Скалярное произведение векторов, заданных координатами", то метод Point.Dot() делает как раз это. Но для двух разных точек они эквивалентны:
p1 := new Point(0, 0)
p2 := new Point(0, 1) ; Произвольная точка на векторе
p3 := new Point(2, -1)
p4 := new Point(-2, -1)
MsgBox % p2.Dot(p3)
MsgBox % p2.Dot(p4)
Я несомненно что-то упускаю и не могу понять, что.