如何在光线中找到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中单调递增。提前感谢您的任何答案!
答案 0 :(得分:2)
我建议您先将设置转换为更容易坐标的设置:
p = (x, y)
。(-x0, -y0)
,以便光线现在从中心开始。-a
,以便光线现在位于 x 轴上。到目前为止,上述操作每个点需要花费四次加法和四次乘法:
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)
为避免检查与所有段的交集,需要一些空间分区,例如Quadtree,BSP tree。对于空间分区,需要检查与空间分区的光线交叉。
在这种情况下,由于点是按x坐标排序的,因此对于折线的部分,可以使用框(min x, min y)-(max x, max y)
进行空间分区。根框是所有点的最小 - 最大值,并且它在折线的第一和第二部分分成2个框。部件中的段数相同或一个盒子中还有一个段。这个盒子分割是递归完成的,直到只有一个片段在一个盒子里。
要检查光线交叉点是否以根框开始并检查它是否与光线相交,如果是,则检查2个子框以查找交叉点并首先测试更近的子框然后再进入子框。
检查光线盒交叉点是否检查光线是否穿过2个位置之间的轴对齐线。这是针对4个框边界完成的。