确定一个点是否位于中心点的两个方位角之间

Determining if a point lies between two bearings from a central point

我正在尝试确定一个点是否位于距中心点的两个方位角之间。

下图试图解释事情

还有一些similar questions & answers 但是就我而言,我对将搜索限制在圆的半径内不感兴趣。在顺时针与逆时针方面,角度大小和点的位置似乎存在一些实现问题

理论上看起来很简单,但我的数学显然不合格:(

任何建议或伪代码将不胜感激。

这是我的方法:

  1. 计算第一个方位角X
  2. 计算第二方位角Y
  3. 计算点 D 的角度 Z
  4. 如果 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