给定直线形状,如何有效地检查它是否有效 并指出无效的部分?
这里的有效性是指宽度约束,即形状的每个部分 应该有一个不小于某个值d的宽度。从形式上看, 如果你从形状的顶部到底部垂直扫过一条线,那就是全部 线和形状之间的交叉点应该具有不小于d的长度。 垂直情况类似。 (请注意,形状内可能有孔。但为简单起见, 我们可以先忽略它。)
任何人都可以建议一个有效的算法或向我展示一些指向这个问题的指针吗?
答案 0 :(得分:1)
我认为您可以使用相当典型的扫描线方法来解决这个问题。
首先考虑水平扫描线,从图的顶部扫到底部。观察到扫描线穿过的宽度只能在穿过垂直线段的端点时发生变化。
因此,对于水平扫描线,您可以忽略水平线段。获取垂直线段的所有端点,并按垂直位置对它们进行排序。 (每个端点都知道它是“顶部”端点还是其段的“底部”端点。)
处理排序列表以模拟扫描线。保持“活动集”S,初始化为空。当您点击“顶部”端点时,将其段添加到S.当您点击“底部”端点时,从S中删除其段。确认活动集的宽度始终满足您的约束,并且您已完成。
使用平衡二叉树(如C ++ std::set
)来表示活动集,使用比较函数的水平位置。这允许O(1)检索集合中最左边和最右边的段,因此宽度计算是O(1)。它还允许插入和删除O(log n),并且由于您只插入和删除每个垂直段一次,因此整个扫描需要O(n log n)。
对称垂直扫描线重复。
每种排序为O(n log n),每次扫描为O(n log n),每个方向乘以两次......因此整体算法为O(n log n)。
答案 1 :(得分:0)
这是一种关于O(n ^ 2)的强力方法。
首先检查是否有自我交叉。多边形中的交叉点的宽度为0,因此会自动失败。
解决方案的其余部分分为两部分,具体取决于您的约束是否仅为水平和垂直,或者是否为任何角度。对于任何一种情况,首先迭代多边形的每个点。
如果约束是水平/垂直,请检查多边形的每个部分,以查看它是否与通过该点的x或y绘制的直线相交。如果它相交,则计算从交点到该点的距离;如果它小于约束,那你就失败了。
如果约束是任何角度,请检查与该点不相邻的多边形的每个部分,并计算从该部分到该点的最近距离;你可以从这个问题Shortest distance between a point and a line segment得到帮助。如果距离小于约束,则表示失败。