如何快速找到光线和m折线之间最近的2D交点?

时间:2012-10-05 14:02:20

标签: graphics geometry computational-geometry

如何在光线中找到2D中最近的交点:

x = x0 + t * cos(a),y = y0 + t * sin(a)

和m折线:{(x1,y1),(x2,y2),...,(xn,yn)}

快?

我开始循环所有的linesegments和每个linesegment; {(x1,y1),(x2,y2)}求解:

x1 + u *(x2-x1)= x0 + t * cos(a)

y1 + u *(y2-y1)= y0 + t * sin(a)

按照克莱默的规则, 然后在距离上排序交叉点,但这很慢: - (。

BTW:折线恰好在x中单调递增。

提前感谢您的任何答案!

2 个答案:

答案 0 :(得分:2)

坐标系转换

我建议您先将设置转换为更容易坐标的设置:

  1. 请注意p = (x, y)
  2. 将其移动(-x0, -y0),以便光线现在从中心开始。
  3. 将其旋转-a,以便光线现在位于 x 轴上。
  4. 到目前为止,上述操作每个点需要花费四次加法和四次乘法:

    ca = cos(a) # computed only once
    sa = sin(a) # likewise
    
    x' = x - x0
    y' = y - y0
    x'' = x'*ca + y'*sa 
    y'' = y'*ca - x'*sa
    

    检查交叉点

    现在您知道折线的一段只有在其y''值的符号发生变化时才会与光线相交,即y1'' * y2'' < 0。您甚至可以推迟计算x''值,直到此检查为止。此外,如果 x &gt;的段与 x 轴的交点发生,则该段仅与光线相交。 0,只有当任一值大于零时才会发生,即x1'' > 0 or x2'' > 0。如果x''都大于零,那么您知道有一个交集。

    以下段落是可选的,如果您不理解,请不要担心,稍后会有另外一种说法。
    如果一个x''为正,但另一个为负,则您必须进一步检查。假设y''的符号从负变为正,即y1'' < 0 < y2''。从p1''p2''的行将与 x &gt;处的 x 轴相交0当且仅当由p1''p2''和原点形成的三角形逆时针方向时。您可以通过检查行列式x1''*y2'' - x2''*y1''的符号来确定该三角形的方向,对于逆时针三角形,它将为正。如果符号变化的方向不同,则方向也必须不同。所以要把它们放在一起,你可以检查是否

    (x1'' * y2'' - x2'' * y1'') * y2'' > 0
    

    如果是这种情况,那么你有一个交集。请注意,到目前为止还没有涉及昂贵的部门。

    计算交叉点

    由于您不仅要确定是否存在交叉点,而是实际找到特定的交叉点,您现在必须计算该交叉点。我们称之为p3。它必须满足方程式

    (x2'' - x3'')/(y2'' - y3'') = (x1'' - x3'')/(y1'' - y3'') and 
                           y3'' = 0
    

    导致

    x3'' = (x1'' * y1'' - x2'' * y2'')/(y1'' - y2'')
    

    除了上一段中的三角形方向检查外,您始终可以计算此x3''值并丢弃任何结果为负数的结果。更少的代码,但更多的分歧。如果对性能有疑问,则为基准。

    要找到最接近光线原点的点,您可以使用最小x3''值获取结果,然后可以将其转换回原始位置:

    x3 = x3''*ca + x0
    y3 = x3''*sa + y0
    

    你有。

    请注意,以上所有都假设所有数字都是正数或负数。如果您有零,则取决于您实际想要计算的内容的准确解释,以及您希望如何处理这些边界情况。

答案 1 :(得分:1)

为避免检查与所有段的交集,需要一些空间分区,例如QuadtreeBSP tree。对于空间分区,需要检查与空间分区的光线交叉。

在这种情况下,由于点是按x坐标排序的,因此对于折线的部分,可以使用框(min x, min y)-(max x, max y)进行空间分区。根框是所有点的最小 - 最大值,并且它在折线的第一和第二部分分成2个框。部件中的段数相同或一个盒子中还有一个段。这个盒子分割是递归完成的,直到只有一个片段在一个盒子里。

要检查光线交叉点是否以根框开始并检查它是否与光线相交,如果是,则检查2个子框以查找交叉点并首先测试更近的子框然后再进入子框。

检查光线盒交叉点是否检查光线是否穿过2个位置之间的轴对齐线。这是针对4个框边界完成的。