Algorithm “优雅”;左撇子;多段线测试

Algorithm “优雅”;左撇子;多段线测试,algorithm,math,geometry,Algorithm,Math,Geometry,给定: (X,Y)坐标,即车辆的位置 (X,Y)的数组,它们是多段线中的顶点。请注意,多段线仅由直线段组成,没有圆弧 我想要什么: 计算车辆是在多段线的左侧还是右侧(当然是在顶部) 我的方法: 迭代所有线段,并计算到每个线段的距离。然后对最近的一段进行一个简单的左偏测试(例如解释) 可能的问题: 当三个点形成小于90度的角度时(如图中所示),会出现更复杂的情况。当车辆处于如下所示的红色区段时,最近的区段可以是两个区段之一。但是,如果选择第一个段作为最近的段,则测试左侧将向右屈服,否

给定:

  • (X,Y)坐标,即车辆的位置
  • (X,Y)的数组,它们是多段线中的顶点。请注意,多段线仅由直线段组成,没有圆弧
我想要什么:

  • 计算车辆是在多段线的左侧还是右侧(当然是在顶部)
我的方法:

  • 迭代所有线段,并计算到每个线段的距离。然后对最近的一段进行一个简单的左偏测试(例如解释)
可能的问题:

  • 当三个点形成小于90度的角度时(如图中所示),会出现更复杂的情况。当车辆处于如下所示的红色区段时,最近的区段可以是两个区段之一。但是,如果选择第一个段作为最近的段,则测试左侧将向右屈服,否则左侧屈服。我们可以很容易地看到(至少,我希望),正确的结果应该是车辆位于多段线的左侧

我的问题:

  • 我如何才能优雅而高效地处理这种特殊情况
我目前的解决方案:

  • 为两条线段计算该线段上的一个点,从顶点开始
  • 使用欧几里德距离计算车辆到两个点的距离
  • 保留计算点最接近的线段
我对这个补丁不太满意,因为我觉得我错过了一个更优雅的解决方案,我的补丁感觉相当“黑”。但效率是关键,因为它用于实时嵌入式系统

现有的代码库是C++,所以如果你想用特定的语言编写,C++有我的偏好。 谢谢

[编辑]
我将我的定位从一个垂直点更改为一个平行点,因为我认为跟随线段比计算外法线更容易。

简单一点:是否可以连接多段线的最后一个和第一个顶点,使其成为多边形?然后你可以做一个简单的内部/外部检查,确定车辆是否在直线的左/右(这当然取决于多边形的方向)


但是,此方法确实假设多边形在连接最后一个顶点和第一个顶点后仍然不自交。

让无穷大=M,其中M足够大。你可以认为所有的东西都在方块[-m,m ] x[-m,m ]中,用你的折线来分割正方形,现在你有两个多边形。然后,检查汽车是否在给定的多边形中可以非常简单地通过角度来完成

我认为你的第一个点和最后一个点有坐标。您可能需要添加这些点中的一些点来创建多边形:(-M,-M),(M,-M),(M,M)和(-M,M)


在多段线左侧有一个多边形后,求和角度OĈp,其中O是一个固定点,C是汽车,p是多边形的一个点。如果总和为0,则汽车在多边形外,否则它在多边形内。

这是计算几何中的标准问题。由于要测试点(x0,y0)是否位于给定曲面(多段线)的左侧,因此需要根据其高度确定要测试的线段。一个简单的方法是建立一个每个段的较低点的树,并在其中搜索测试点的前一个。一旦有了该段,就可以直接执行左边的测试:如果它在两个端点的左边,或者在它们之间的适当一侧,则返回true

我在这里假设您保证多段线的垂直范围大于您可能找到查询点的位置,并且该线不会垂直重叠。后一种假设可能相当糟糕

针对OP的评论进行的扩展:

请注意,问题中的角度示例与第一个假设相矛盾-多段线未达到搜索点的高度

对我的方法进行概念化的一种方法是,对线段进行垂直排序,然后对它们进行迭代,将点的y坐标与线段进行比较,直到点位于较低端点上方和较高端点下方。然后,使用线段的端点计算出给定y处的x截距。如果该点的x坐标较低,则该点位于左侧,如果该点的x坐标较大,则该点位于右侧

有两种方法可以在实际实现中改进此解释,其中一种是我提到的:

  • 使用平衡搜索树查找正确的段,而不是遍历排序列表,以将时间从
    O(n)
    带到
    O(logn)
  • 将搜索重新定义为通过搜索点查找多段线和水平线y=y0的交点。然后将交点的x值与搜索点进行比较

  • 这个话题已经沉寂太久了,我相信它已经死了。不过我有一个解决办法

    但是,如果第一个段为 选择为最近的线段,否则向左

    你使用了一些模棱两可的语言。我将用线段来表示多段线中的线段,用象限来表示由它们分隔的区域。在你的例子中,你会有一个红色的象限,它似乎在一段的右边,另一段的左边

    如果测试的左边为不同的段生成不同的答案,您应该对这些段本身重新进行测试。在您的情况下,您将有:

    • 象限位于第一段的右侧
    • 象限位于第二段的左侧
    两段