Вычисление угла между двумя линиями в питоне

Я пытаюсь вычислить угол между двумя линиями в Python. Я искал в интернете и нашел уравнение, как это сделать. Но я не всегда получаю точный результат. Некоторые результаты явно ложны, когда другие кажутся правильными. Мой код приведен ниже:

def angle(pt1,pt2):
    m1 = (pt1.getY() - pt1.getY())/1
    m2 = (pt2.getY() - pt1.getY())/(pt2.getX()-pt1.getX())

    tnAngle = (m1-m2)/(1+(m1*m2))
    return math.atan(tnAngle)

def calculate(pt,ls):
    i=2
    for x in ls:
        pt2 = point(x,i)
        i=i+1
        ang = angle(pt,pt2)*180/math.pi
        ang = ang * (-1)
        print ang


pt = point(3,1)
ls = [1,7,0,4,9,6,150]

calculate(pt,ls)

результат, который это производит:

45.0
0.0
45.0
-75.9637565321
0.0
-63.4349488229
0.0

Проблема в том, что я не понимаю, почему второй результат, пятый и последний обнуляются, они пересекаются, так как они разделяют точку, а другая точка не дублируется, так как значение в массиве отличается.

3 ответа

Решение

Похоже, вы используете Python2, где / будет делать целочисленное деление, если оба аргумента являются int. Чтобы получить поведение Python3, вы можете поместить это в начало файла

from __future__ import division

Ваша формула угла потерпит неудачу, если

pt2.getX() == pt1.getX()

(то есть, если pt1 и pt2 лежат на вертикальной линии), потому что вы не можете делить на ноль. (m2уклон был бы бесконечным.)

Также

m1 = (pt1.getY() - pt1.getY())/1

всегда будет ноль. Так что, по крайней мере, ваша формула может быть упрощена до арктана склона. Однако я бы не стал беспокоиться, так как формула не работает для всех возможных точек.

Вместо этого, более надежный метод (в действительности, стандартный метод) для вычисления угла между двумя векторами (направленными отрезками) состоит в использовании формулы точечного произведения:

где если a = (x1, y1), b = (x2, y2), затем <a,b> равняется x1*x2 + y1*y2, а также||a|| длина вектора aт.е. sqrt(x1**2 + y1**2),


import math
def angle(pt1, pt2):
    x1, y1 = pt1
    x2, y2 = pt2
    inner_product = x1*x2 + y1*y2
    len1 = math.hypot(x1, y1)
    len2 = math.hypot(x2, y2)
    return math.acos(inner_product/(len1*len2))

def calculate(pt, ls):
    i = 2
    for x in ls:
        pt2 = (x, i)
        i = i+1
        ang = angle(pt, pt2)*180/math.pi
        ang = ang * (-1)
        print ang

pt = (3, 1)
ls = [1,7,0,4,9,6,150]

calculate(pt, ls)

Вот то, что я в конечном итоге использовал, все с использованием NumPy и диапазон между - до

import numpy as np
def get_angle(p0, p1=np.array([0,0]), p2=None):
    ''' compute angle (in degrees) for p0p1p2 corner
    Inputs:
        p0,p1,p2 - points in the form of [x,y]
    '''
    if p2 is None:
        p2 = p1 + np.array([1, 0])
    v0 = np.array(p0) - np.array(p1)
    v1 = np.array(p2) - np.array(p1)

    angle = np.math.atan2(np.linalg.det([v0,v1]),np.dot(v0,v1))
    return np.degrees(angle)
Другие вопросы по тегам