gpt4 book ai didi

Python Tkinter Canvas 获取线的基本方向

转载 作者:太空宇宙 更新时间:2023-11-03 14:45:33 25 4
gpt4 key购买 nike

我在 tkinter Canvas 上有两个点。我需要一个函数来确定它们之间绘制的线最接近哪个基本方向(N、NW、W SW、S 等)(方向很重要)?我该怎么做呢?请注意,在 Canvas 中,左上角是 (0,0)。

我已经尝试过:

def dot_product(self, v, w):
return v[0]*w[0]+v[1]*w[1]
def inner_angle(self, v, w):
cosx=self.dot_product(v,w)/(sqrt(v[0]**2+v[1]**2)*sqrt(w[0]**2+w[1]**2))
rad=acos(cosx)
return rad*180/pi
def getAngle(self, A, B):
inner=self.inner_angle(A,B)
det = A[0]*B[1]-A[1]*B[0]
if det<0:
return inner
else:
return 360-inner

和:

def getBearing(self, pointA, pointB):

if (type(pointA) != tuple) or (type(pointB) != tuple):
raise TypeError("Only tuples are supported as arguments")

lat1 = math.radians(pointA[0])
lat2 = math.radians(pointB[0])

diffLong = math.radians(pointB[1] - pointA[1])

x = math.sin(diffLong) * math.cos(lat2)
y = math.cos(lat1) * math.sin(lat2) - (math.sin(lat1) * math.cos(lat2) * math.cos(diffLong))

initial_bearing = math.atan2(x, y)

initial_bearing = math.degrees(initial_bearing)
compass_bearing = (initial_bearing + 360) % 360

return compass_bearing

(我用这个函数来获取方向(代码不完整,更多的是一个例子))

def findDirection(self, p1, p2):
bearing = self.getBearing(p1, p2) # OR getAngle()
print(bearing)
index = [180, 0]
closest = min(index, key=lambda x:abs(x-bearing))
if closest == 10:
print(str(bearing) + " : UP")
elif closest == 360:
print(str(bearing) + " : DOWN")
elif closest == 0:
print(str(bearing) + " : RIGHT")
elif closest == 180:
print(str(bearing) + " : LEFT")

这些都不起作用。结果似乎不够一致,无法使用。有更好的方法吗?

最佳答案

这是我提出的方法,用于确定与线段所指向的方向最接近的罗盘方向 [A, B]由其端点 point_a 定义和point_b :

  1. 所有计算均在标准笛卡尔坐标系中完成,最后完成屏幕坐标的更改。这简化了方法,并使代码可以在其他地方重用。
  2. 首先将原点更改为point_a
  3. 第二步计算线段与x_轴的角度
  4. 确定最近的方位(采用标准笛卡尔坐标)
  5. 将标准方位角转换为屏幕坐标方位角(水平翻转)

with points defined in screen coordinates (Y axis down), call get_bearings(point_a, point_b)
If the points defined in standard cartesian coordinates (Y axis up), call assign_bearing_to_compass(point_a, point_b)
(The tests underneath the code show the results of using points in standard coordinates, and screen coordinates.)

<小时/>
import math


def _change_origin_of_point_b_to_point_a(point_a, point_b):
# uses standard Y axis orientation, not screen orientation
return (point_b[0] - point_a[0], point_b[1] - point_a[1])

def _calc_angle_segment_a_b_with_x_axis(point_a, point_b):
# uses standard Y axis orientation, not screen orientation
xa, ya = point_a
xb, yb = _change_origin_of_point_b_to_point_a(point_a, point_b)
return math.atan2(yb, xb)

def determine_bearing_in_degrees(point_a, point_b):
"""returns the angle in degrees that line segment [point_a, point_b)]
makes with the horizontal X axis
"""
# uses standard Y axis orientation, not screen orientation
return _calc_angle_segment_a_b_with_x_axis(point_a, point_b) * 180 / math.pi

def assign_bearing_to_compass(point_a, point_b):
"""returns the standard bearing of line segment [point_a, point_b)
"""
# uses standard Y axis orientation, not screen orientation
compass = {'W' : [157.5, -157.5],
'SW': [-157.5, -112.5],
'S' : [-112.5, -67.5],
'SE': [-67.5, -22.5],
'E' : [-22.5, 22.5],
"NE": [22.5, 67.5],
'N' : [67.5, 112.5],
'NW': [112.5, 157.5]}

bear = determine_bearing_in_degrees(point_a, point_b)
for direction, interval in compass.items():
low, high = interval
if bear >= low and bear < high:
return direction
return 'W'

def _convert_to_negative_Y_axis(compass_direction):
"""flips the compass_direction horizontally
"""
compass_conversion = {'E' : 'E',
'SE': 'NE',
'S' : 'N',
'SW': 'NW',
'W' : 'W',
"NW": 'SW',
'N' : 'S',
'NE': 'SE'}
return compass_conversion[compass_direction]

def get_bearings(point_a, point_b):
return _convert_to_negative_Y_axis(assign_bearing_to_compass(point_a, point_b))

测试:

(使用标准三角圆象限)

象限 I:

point_a = (0, 0)
points_b = [(1, 0), (1, 3), (1, 2), (1, 1), (2, 1), (3, 1), (0, 1)]
print("point_a, point_b Y_up Y_down (in screen coordinates)")
for point_b in points_b:
print(point_a, ' ', point_b, ' ', assign_bearing_to_compass(point_a, point_b), ' ', get_bearings(point_a, point_b))

结果:

point_a, point_b     Y_up     Y_down (in screen coordinates)
(0, 0) (1, 0) E E
(0, 0) (1, 3) N S
(0, 0) (1, 2) NE SE
(0, 0) (1, 1) NE SE
(0, 0) (2, 1) NE SE
(0, 0) (3, 1) E E
(0, 0) (0, 1) N S

第二象限:

point_a = (0, 0)
points_b = [(-1, 0), (-1, 3), (-1, 2), (-1, 1), (-2, 1), (-3, 1), (0, 1)]
print("point_a, point_b Y_up Y_down (in screen coordinates)")
for point_b in points_b:
print(point_a, ' ', point_b, ' ', assign_bearing_to_compass(point_a, point_b), ' ', get_bearings(point_a, point_b))

结果:

point_a, point_b     Y_up     Y_down (in screen coordinates)
(0, 0) (-1, 0) W W
(0, 0) (-1, 3) N S
(0, 0) (-1, 2) NW SW
(0, 0) (-1, 1) NW SW
(0, 0) (-2, 1) NW SW
(0, 0) (-3, 1) W W
(0, 0) (0, 1) N S

第三象限:

point_a = (0, 0)
points_b = [(-1, 0), (-1, -3), (-1, -2), (-1, -1), (-2, -1), (-3, -1), (0, -1)]
print("point_a, point_b Y_up Y_down (in screen coordinates)")
for point_b in points_b:
print(point_a, ' ', point_b, ' ', assign_bearing_to_compass(point_a, point_b), ' ', get_bearings(point_a, point_b))

结果:

point_a, point_b     Y_up     Y_down (in screen coordinates)
(0, 0) (-1, 0) W W
(0, 0) (-1, -3) S N
(0, 0) (-1, -2) SW NW
(0, 0) (-1, -1) SW NW
(0, 0) (-2, -1) SW NW
(0, 0) (-3, -1) W W
(0, 0) (0, -1) S N

第四象限:

point_a = (0, 0)
points_b = [(1, 0), (1, -3), (1, -2), (1, -1), (2, -1), (3, -1), (0, -1)]
print("point_a, point_b Y_up Y_down (in screen coordinates)")
for point_b in points_b:
print(point_a, ' ', point_b, ' ', assign_bearing_to_compass(point_a, point_b), ' ', get_bearings(point_a, point_b))

结果:

point_a, point_b     Y_up     Y_down (in screen coordinates)
(0, 0) (1, 0) E E
(0, 0) (1, -3) S N
(0, 0) (1, -2) SE NE
(0, 0) (1, -1) SE NE
(0, 0) (2, -1) SE NE
(0, 0) (3, -1) E E
(0, 0) (0, -1) S N

关于Python Tkinter Canvas 获取线的基本方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46258873/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com