我有一条光线,我需要找到它击中的最近的线段。如果我先对行段进行排序,我认为可以在O(log n)时间内执行此操作,但我不记得如何对它们进行排序...我认为某种树最适合,但我如何排序它们的起点和终点都是?如果可能的话,我还想快速插入这个数据结构。
一条光线与一条线段有很多代码,但我需要一条光线对比很多线段...我不知道google的条款。
指向相应文章的链接很好,C ++代码甚至更好。谢谢! :)
PS:线段实际上是非自相交多边形的边缘,按CCW顺序排序......但我认为以不同的方式对它们进行排序可能有一些优势吗?
这都是2D。
第二个想法,我不完全确定 是否可能。某种空间分区可能有所帮助,但除此之外,我无法想出任何方式对线进行排序,以便可以将它们与任意光线进行比较。
答案 0 :(得分:7)
您可以使用多边形的边界框(min-max x,y坐标)并在框内构建网格。然后,对于每个单元格,记住穿过单元格的所有行。
找到这样的部分:
您还可以使网格分层(即。quadtree - 您要求的树),然后使用相同的算法进行操作。 This is done in raytracing in 3D,时间复杂度为O(sqrt(N))。
或者,使用我在光线跟踪器中执行的方法:
收集光线击中的四叉树的所有叶节点:
为根计算光线矩形交叉(不是硬)。如果根被光线击中,则递归地继续其子项。
关于这一点很酷的是,当一个树节点不命中时,你已经跳过处理整个子树(可能是一个大的矩形区域)。
最后,这相当于遍历网格 - 您收集光线路径上的最小单元格,然后测试其中的所有对象以进行交叉。您只需测试所有这些并选择最近的交叉点(这样您就可以探索光线路径上的所有线条)。
这是O(sqrt(N))。
在网格遍历中,当您找到交叉点时,可以停止搜索。要通过四叉树遍历实现这一目标,您必须以正确的顺序搜索子项 - 按距离对4个矩形交叉点进行排序,或者巧妙地遍历4个单元格网格(我们回到遍历)。
这只是一种不同的方法,我认为相对难以实现,而且效果很好(我在实际数据上测试了它 - O(sqrt(N)))。再次,如果你至少有几行,你只会受益于这种方法,当多边形有10条边时,与仅仅测试它们的好处相比,我认为很少。
答案 1 :(得分:1)
你怎么确定你会击中他们中的任何一个?如果它们是线条,则不太可能。
如果它确实是你试图测试的多边形(即平面),那么通常的方法就是首先与平面相交,然后在内部/外部测试该点(在2d坐标中)多边形。
也许我误解了你的确在做什么。
一般情况下,通过空间分区(以及邮箱等技术,如果您的测试费用昂贵),可以加速复杂数字的交叉点。
[更新:我误读了原始意图]你仍然可以使用(2d)空间分区,但开销可能不值得。个人测试很便宜,如果你的多边形不复杂,走路可能会更便宜。很难从描述中说出来。
答案 2 :(得分:1)
您在寻找基于扫描线/基于活动边缘表的方法吗?您可以查看Scanline Rendering的Wikipedia条目,或在Graphics Gems目录中搜索算法(主要是C,但也有一些C ++代码)。
答案 3 :(得分:1)
请记住,排序最多只能进行O(n log n)操作。你可能最好单独检查一下。
答案 4 :(得分:0)
要求澄清,这是正确的吗?
所以点(x,y)没有修复? (可能是任何一点,任何方向?)