确定一个点是否位于中心点的两个方位角之间
Determining if a point lies between two bearings from a central point
我正在尝试确定一个点是否位于距中心点的两个方位角之间。
下图试图解释事情
- 我有一个标记为 A 的中心点
- 我有两个点(标记为 B 和 C)提供了搜索区域的边界(仅基于方位 - 不需要距离元素)。
- 我正在尝试确定 D 点是否在 A-B 和 A-C 形成的扇区内
- 我计算了从 A 到每个 B 和 C 的方位角
- 在我的真实场景中,轴承之间形成的角度可以是 0 到 360 之间的任意角度。
还有一些similar questions & answers
但是就我而言,我对将搜索限制在圆的半径内不感兴趣。在顺时针与逆时针方面,角度大小和点的位置似乎存在一些实现问题
理论上看起来很简单,但我的数学显然不合格:(
任何建议或伪代码将不胜感激。
这是我的方法:
- 计算第一个方位角X
- 计算第二方位角Y
- 计算点 D 的角度 Z
- 如果 X < Z < Y,return 为真;否则,return false
在您的示例中,您似乎会计算 Z ~ 90deg 并找到 45 < 90 < 135(您的图片有误吗?说的是 315)。
您可以在您使用的任何语言中使用类似 "atan2" 的功能。这是基本反正切函数的扩展,它不仅采用斜率,还采用上升和 运行,而不是 return 仅从 180 度范围计算角度,它 return这是 360 度范围内的真实角度。所以
Z = atan2(Dy, Dx)
应该给你角度(可能以弧度为单位;小心),你可以将其与你的方位进行比较,以判断你是否在搜索范围内。请注意,X 和 Y 的顺序很重要,因为该顺序定义了搜索区域中的两个部分中的哪一个(X 到 Y 在您的图片中给出了 ~90 度,但 Y 到 X 给出了~270 度)。
您可以计算和比较向量 (AB X BD) 和 (AC X CD) 的叉积。
if (AB X BD) > 0
,你有一个逆时针转弯
if (AC X CD) < 0
,你有一个顺时针转弯
如果以上两个测试都为真,则点 D 在扇区 BAC
这使您可以完全避免使用昂贵的三角函数。
class Point:
"""small class for point arithmetic convenience
"""
def __init__(self, x: float = 0, y: float = 0) -> None:
self.x = x
self.y = y
def __sub__(self, other: 'Point') -> 'Vector':
return Vector(self.x - other.x, self.y - other.y)
class Vector:
"""small class for vector arithmetic convenience
"""
def __init__(self, x: float = 0, y: float = 0) -> None:
self.x = x
self.y = y
def cross(self, other: 'Vector') -> float:
return (self.x * other.y) - (self.y * other.x)
def in_sector(A: Point, B: Point, C: Point, D: Point) -> bool:
# construct vectors:
ab = B - A
bd = D - B
ac = C - A
cd = D - C
print(f'ab x bc = {ab.cross(bd)}, ac x cd = {ac.cross(cd)}')
return ab.cross(bd) > 0 and ac.cross(cd) < 0
if __name__ == '__main__':
A = Point(0, 0)
B = Point(1, 1)
C = Point(-1, 1)
D = Point(0, 1)
print(f'D in sector ABC: {in_sector(A, B, C, D)}', end='\n\n')
print(f'D in sector ACB: {in_sector(A, C, B, D)}') # inverting the sector definition so D is now outside
输出:
ab x bc = 1, ac x cd = -1
D in sector ABC: True
ab x bc = -1, ac x cd = 1
D in sector ACB: False
我正在尝试确定一个点是否位于距中心点的两个方位角之间。
下图试图解释事情
- 我有一个标记为 A 的中心点
- 我有两个点(标记为 B 和 C)提供了搜索区域的边界(仅基于方位 - 不需要距离元素)。
- 我正在尝试确定 D 点是否在 A-B 和 A-C 形成的扇区内
- 我计算了从 A 到每个 B 和 C 的方位角
- 在我的真实场景中,轴承之间形成的角度可以是 0 到 360 之间的任意角度。
还有一些similar questions & answers 但是就我而言,我对将搜索限制在圆的半径内不感兴趣。在顺时针与逆时针方面,角度大小和点的位置似乎存在一些实现问题
理论上看起来很简单,但我的数学显然不合格:(
任何建议或伪代码将不胜感激。
这是我的方法:
- 计算第一个方位角X
- 计算第二方位角Y
- 计算点 D 的角度 Z
- 如果 X < Z < Y,return 为真;否则,return false
在您的示例中,您似乎会计算 Z ~ 90deg 并找到 45 < 90 < 135(您的图片有误吗?说的是 315)。
您可以在您使用的任何语言中使用类似 "atan2" 的功能。这是基本反正切函数的扩展,它不仅采用斜率,还采用上升和 运行,而不是 return 仅从 180 度范围计算角度,它 return这是 360 度范围内的真实角度。所以
Z = atan2(Dy, Dx)
应该给你角度(可能以弧度为单位;小心),你可以将其与你的方位进行比较,以判断你是否在搜索范围内。请注意,X 和 Y 的顺序很重要,因为该顺序定义了搜索区域中的两个部分中的哪一个(X 到 Y 在您的图片中给出了 ~90 度,但 Y 到 X 给出了~270 度)。
您可以计算和比较向量 (AB X BD) 和 (AC X CD) 的叉积。
if (AB X BD) > 0
,你有一个逆时针转弯
if (AC X CD) < 0
,你有一个顺时针转弯
如果以上两个测试都为真,则点 D 在扇区 BAC
这使您可以完全避免使用昂贵的三角函数。
class Point:
"""small class for point arithmetic convenience
"""
def __init__(self, x: float = 0, y: float = 0) -> None:
self.x = x
self.y = y
def __sub__(self, other: 'Point') -> 'Vector':
return Vector(self.x - other.x, self.y - other.y)
class Vector:
"""small class for vector arithmetic convenience
"""
def __init__(self, x: float = 0, y: float = 0) -> None:
self.x = x
self.y = y
def cross(self, other: 'Vector') -> float:
return (self.x * other.y) - (self.y * other.x)
def in_sector(A: Point, B: Point, C: Point, D: Point) -> bool:
# construct vectors:
ab = B - A
bd = D - B
ac = C - A
cd = D - C
print(f'ab x bc = {ab.cross(bd)}, ac x cd = {ac.cross(cd)}')
return ab.cross(bd) > 0 and ac.cross(cd) < 0
if __name__ == '__main__':
A = Point(0, 0)
B = Point(1, 1)
C = Point(-1, 1)
D = Point(0, 1)
print(f'D in sector ABC: {in_sector(A, B, C, D)}', end='\n\n')
print(f'D in sector ACB: {in_sector(A, C, B, D)}') # inverting the sector definition so D is now outside
输出:
ab x bc = 1, ac x cd = -1
D in sector ABC: True
ab x bc = -1, ac x cd = 1
D in sector ACB: False