我有一个多边形和一个给定的点。我需要在多边形上找到与给定点具有相同Y坐标的点。请参阅附件:给定点是红点,蓝点是我要寻找的点(与给定点具有相同Y的点)。
此时,我知道要通过遍历多边形部分来解决它,并检查给定的点Y值是否在该部分内进行中继。在找到包含的部分之后,我只是运行一个简单的等式来找到交叉点。然而!我希望找到一种更好,更简单的方法来解决它,也许是现有的公式?
谢谢!
答案 0 :(得分:2)
以下解决方案使用O(n log n)
时间进行预处理,每个查询使用O((log n)^2 + cnt)
,其中cnt
是多个交叉点。它适用于任何多边形。
1)预处理:将每个段存储为一对(low_y, high_y)
。按low_y
排序。现在可以构建二维分段树,其中第一个维度为low_y
,第二个维度为high_y
。如果正确完成,可能需要O(n log n)
空间和时间(可以为每个包含那些{1}}值的vector
值保留已排序的high_y
high_y
个值low_y <= query_y <= high_y
对应于这个特定的节点)。
2)查询:它可以通过以下方式重新表述:找到满足[min(low_y), query_y]
条件的所有这些段(即,对)。要查找所有此类段,可以遍历段树并将范围O(log n)
分解为最多high_y
个节点的并集(此处仅考虑第一个维度)。对于固定节点,可以对已排序的vector
low_y <= query_y <= high_y
应用二进制搜索,以仅提取满足high_y
条件的那些段(由于树的方式,第一个不等式为真遍历,所以我们只需要检查O(log n)
。这里我们有O(log n)
个节点(由于段树的属性),二进制搜索需要O((log n)^2
时间。因此,此步骤的时间复杂度为high_y
。在使用二分搜索找到最小vector
之后,很明显O(cnt)
的尾部(从此位置到末尾)包含那些并且仅包含与查询行相交的那些段。因此,人们可以简单地迭代它们并找到交叉点。此步骤需要cnt
时间,因为当且仅当它与行(O((log n)^2 + cnt)
- 与行和多边形之间的交叉点的总数量相交)时才会检查该段。因此,整个查询的时间复杂度为{{1}}。
3)这里实际上至少有两个角落情况:
i)交叉点是两个相邻多边形部分的公共点,而ii)是一个水平部分,所以它们应该根据它们的期望输出小心处理(例如,可以完全忽略水平边缘或假设整个边缘是交叉点)。
答案 1 :(得分:0)
我认为允许预处理。
首先在单调链中分解多边形:依次考虑所有边并链接所有沿相同方向(向上或向下)的方向。你可以忽略水平边。
如果你真的那么,最多会有两个链(凸多边形总是两个),最差的N-1
或N
(取决于N
上的奇偶校验)不走运。平均四个左右。
请注意,链中的顶点是通过增加或减少Y
(排序&#34;免费&#34;)来排序的。
现在,对于给定的测试点,请在Y
上通过二分法找到它,例如在Yi
和Yi+1
之间。然后交叉点由X = Xi + (Y - Yi).(Xi+1 - Xi) / (Yi+1 - Yi)
给出。
此过程需要O(N)
预处理时间,最差O(N)
存储;查询时间为O(K.LgL)
,其中K
是链的数量,LgL
是链长的平均对数。
这不是最佳的,也不是各向同性的,但是编程非常简单并且开销很小。