У меня есть алгоритм, в котором мне нужно определить угол со знаком (от -180 до 180) между ребрами на графике.Я провел некоторое исследование и нашел множество конкретных ответов, но не могу понять, как связать их с моей ситуацией (например, этот вопрос, который использует atan2
, однако ОП хотел только положительные углы) IЯ пытался реализовать несколько разных способов (используя atan2 или arccos), но я изо всех сил пытаюсь связать примеры с моей конкретной проблемой.Я пытался рассматривать края как векторы, но получил странные результаты.
Учитывая график с точками (A, B, C, D, E) и средним из этих точек (в среднем) ... какнайти ли знаковый угол между одной из этих точек (например, A) и другими точками (например, B, C, D, E), принимая угол от текущего начала координат (A) к точке 'avg' равным 0градусов.Пример ниже ...
... в этом примере угол против часовой стрелки от (A, avg) до (A, B)будет положительным что-то (между 0 и 180), а угол от (A, avg) до (A, E) будет отрицательным что-то (между 0 и -180).
В идеале я хочу формулу, котораяЯ также мог бы обратиться к определению любой из точек в качестве начала координат, например, взять точку C в качестве начала координат. «Нулевым углом» будет (C, avg) и угол между (C, avg) и (C, A) будет отрицательным (от 0 до -180), а угол между (C, avg) и (C, E) будет положительным (от 0 до 180).
Я не изучал математику за пределами средней школыпоэтому мне трудно расшифровывать уравнения с символами, которые я не понимаю.
ОБНОВЛЕНИЕ: Я подумал, что я бы все очистил, чтобы было более очевидно, к какому выводу пришли.Я сделал два небольших изменения в принятом ответе, приведя следующий фрагмент:
def angle(vertex, start, dest):
AhAB = math.atan2((dest.y - vertex.y), (dest.x - vertex.x))
AhAO = math.atan2((start.y - vertex.y), (start.x - vertex.x))
AB = AhAB - AhAO
# in between 0-math.pi = do nothing, more than math.pi = +(-2 * math.pi), less than zero = do nothing
AB = math.degrees(AB + (-2 * math.pi if AB > math.pi else (2 * math.pi if AB < 0 - math.pi else 0)))
return AB
... окончательный однострочный текст может показаться немного неприятным после нескольких месяцев отсутствия работы над этим,поэтому я превратил его в его собственную функцию, взяв в качестве аргумента результат AB = AhAB - AhAO
...
def calc(ab):
if ab > math.pi:
return ab + (-2 * math.pi)
else:
if ab < 0 - math.pi:
return ab + (2 * math.pi)
else:
return ab + 0
Я подумал, что это немного понятнее, хотя и больше строк.
Последняя функция полностью:
def angle(vertex, start, dest):
"""Calculates the signed angle between two edges with the same origin.
Origin is the 'vertex' argument, 'start' is the bounding point of the edge to calculate the angle from.
Positively signed result means anti-clockwise rotation about the vertex."""
def calc_radians(ab):
if ab > math.pi:
return ab + (-2 * math.pi)
else:
if ab < 0 - math.pi:
return ab + (2 * math.pi)
else:
return ab + 0
AhAB = math.atan2((dest.y - vertex.y), (dest.x - vertex.x))
AhAO = math.atan2((start.y - vertex.y), (start.x - vertex.x))
res = calc_radians(AhAB - AhAO)
return math.degrees(res)
Примечание : функция предполагает, что все три аргумента будут экземплярами типичного класса Point
с атрибутами x
и y
,Кроме того, приведенный выше примерный график имеет только положительные значения, но я вполне уверен, что это работает с графиками, которые также содержат отрицательные значения.