检查2D平面上两点之间的连接

时间:2013-09-27 09:56:17

标签: algorithm graph complexity-theory

SO,

问题

我有一个关于确定两个点是否连接在2D平面上的算法的问题。我有:

  • 2D线阵列。每条线都以其起始端2D点限制。每个点都是两个元素[x,y]的简单数组 - 即每一行看起来像['start'=>[X0, Y0], 'end'=>[X1, Y1]]这个行设置为L。线条可以彼此相依(即一条线可以是另一条线的一部分),它们只能与e.t.c中的一个点相交。 - 即在2D平面上有无限制。但是行不能成为一个点 - 即行的起点不能等于行尾。
  • 两个点SE,即数组[Xs, Ys][Xe, Ye]

现在,来自L的所有行都在平面上绘制。然后,SE也被绘制出来,我需要回答这个问题 - 可以从S到达而没有L 中的任何行的交叉点吗?而且,更具体一点 - 哪种算法最优?可以到达'我的意思是从SE的飞机上有一种方式,没有来自L的任何一条线 - 而且,原因是,这种方式可以是任何东西,而不仅仅是线。

示例

enter image description here

- 如您所见,示例SE未连接。同样在样本中有一条线完全属于另一条线(灰线和紫线) - 以及一条线在另一条线(绿线和玫瑰线)上有一个开始/结束的情况。

我的方法

目前,我有非确定性多项式(NP)算法来做到这一点。它的步骤是:

  • 查找每对线的所有交叉点。
  • 从第一步的点创建新的一组线。如果两条线有一个交叉点,则每条新线的起点将有4条新线与交叉点 - 或者如果第一条线在第二条线上有它的开始/结束,它可以是3条新线 - 或者它如果第一行有它的开始/结束与第二行的开始/结束完全匹配,则可以是2个新行。即:
  

Five general cases for two lines

因此,第一种情况将导致4个新行,3个新行中的2-4个案例和2个新行中的5个案例。 (行[A, B][C, D]

  • 接下来,在从第2步开始的步骤中,我搜索所有多边形。多边形是一个闭合线组(即它保持封闭的区域部分)
  • 我确定包含S的此类多边形的S子集。要做到这一点,我使用简单的算法 - 计算具有多边形边的交点的数量和从S到外平面的一些线(如果它是奇数,那么{{1}在多边形内部,如果它是偶数 - 那么在外面)。这是ray-casting算法。然后我为S
  • 执行此操作
  • 现在,当我为ES设置多边形时,我只是比较两个集合。如果它们相等,那么E可以从E到达,而不能 - 否则。

为什么这是NP?

答案很简单:在第3步中,我在2D图中搜索所有循环。由于在NP中找到最大/最小循环长度的问题,因此我也是(因为我可以简单地通过排序结果循环设置获得最大/最小循环长度)。关于此的良好信息位于here

问题

由于我目前的解决方案是NP,我想知道 - 可能我的解决方案是一个矫枉过正?即可能有更简单的解决方案会导致多项式时间?

5 个答案:

答案 0 :(得分:9)

基本上问题归结为:
1)确定包含一些不包含任何其他多边形的空间的所有多边形。在上面的示例中,您有3个不包含任何其他形状/周期/多边形:包含S的四边形,包含E的四边形和在其中2个下方的三角形。
2)确定S和E是否在任何这些多边形的内侧/外侧相反。

对于第1部分,您必须构建一个图表:

创建给定线的交叉点数组,这是N ^ 2。记住每个交叉点来自哪两条线。这些交叉点是图形的顶点。

如果两个顶点来自同一条线并且它们之间没有其他交叉点,则它们是“连接的”。显然,不要依赖浮点的准确性来确定这一点。

现在您希望在布局中找到多边形。图形通常可以包含指数个循环。但是,每条边可能只边界2个“内”多边形,所以我们只对周期的多项式子集感兴趣。因此,选择一条边,然后找到多边形中的下一条边,并继续重复,直到您回到开始的位置或确定第一条边不是多边形的一部分。

假设您来自边E =(U,V),并且想要找到多边形中的下一条边(共享相同的顶点V)。
1)创建一个矢量T为U - V.
2)创建与顶点V相邻的边A集。从该集中删除E. 3)如果集合为空,则边缘不是多边形的一部分 4)对于A中的每个边(Q,V),将矢量R构造为Q - V.(记住Q和V表示2D平面中的点)。
5)归一化R:除以它的长度以创建长度为1的向量 6)确定CrossProductValue(T,R) 7)具有最小CrossProductValue的A中的边是相邻多边形中的下一个边。具有最大CrossProductValue的A中的边是另一个多边形中的下一个边。

CrossProductChecker(2D T, 2D R) {
  return (T.x*R.y - T.y*R.x); // cross product for 2 dimensions
}

所以用它来找到你的多边形。查看交叉乘积和正弦曲线之间的关系,以了解其工作原理。

============

现在你拥有了所有的多边形,所有要做的就是检查是否有一个S在里面而E在外面,或者反过来。

执行此操作的简单方法是从S到E绘制一条直线。如果它与任何多边形(从上面循环)相交偶数次,它们都在多边形内部或两者之外,因此请继续检查。

如果这条线与一个循环相交一个奇数次,那么一个在多边形内,一个在外面,所以你可以说没有路径。

答案 1 :(得分:6)

你可以构造一个所谓的"Visibility graph",它连接两个障碍物顶点,如果它们是直接可见的。此图中的最短路径(添加了S和E)将是配置空间中S和E之间的最短无障碍路径。关于可见性图的算法和优化是众所周知的并且被广泛描述。

您遇到的主要困难是处理角落情况,因此您不能在段的另一侧(共享段,端点作为交叉点等)的某个不正确的交叉点“泄漏”。处理这种极端情况在算法上并不困难,但需要耐心。

修改

因此,让我更正式:构建图表G(Ver, Edg),其中Ver包含所有细分的端点,SE;并且Edg包含所有直接可见的顶点对(包括在段之后)。

答案 2 :(得分:4)

该算法有两个步骤。

1. Find out the maximum polyogn encompassing S and E 
    (which could possibly be an open polygon, so convex hull algorithm needs 
    to be modified)
2. E can be reached from S if
    (Case 1) The polygons are the same
    (Case 2) Both are open polygons.

说明:

步骤1:找到点P

的最大包围多边形
Form a set of points by adding the end-points and all possible 
    intersections. (O(n^2))
Eliminate points that can only be reached from P by crossing another line. 
    This can be done by finding the intersection of the line joining P to each 
    point with all other lines (O (n^3)).
Form a convex hull of the remaining points. 
    Here it should be noted that the resulting polygon may not be closed. 
    So, the convex hull algorithm needs to be modified to get rid of 
    those possible edges which don't have a direct connection. 
    This can be efficiently done by an appropriate data structure 
    like a graph (O(n^2) in worst case)

步骤2:比较需要对多边形顶点进行某种排序。这将是最大O(n long n)

因此得到的算法复杂度将为O(n ^ 3)

See the diagram

答案 3 :(得分:2)

  1. 找到线段之间的所有交叉点
  2. 删除所有排名为1的点;即它是一个终点,只有一个线段连接到这一点
  3. 找到最靠近S点的线段
  4. 使用以下方法找到其一边是先前找到的线段的多边形:
    1. 给出了起始线段
    2. 标记起始段的两端,起始= lsS,结尾= lsE
    3. 找到与lsE相关联的所有线段,不包括起始段
    4. 从找到的段中选择最接近点S最近线的段是一个,其中心可以与点S连接而不与任何被检查的线相交
    5. 从问题空间中删除所有其他已检查的线段
    6. 重复,直到您有完整的多边形
  5. 如果完整多边形包含点E和S,那么它们是连接的
  6. 这与深度优先搜索有点类似。

    Very bad illustration of my idea.

    在每个步骤中,您只能与成功解决的最后一点的直接邻居一起工作。

答案 4 :(得分:2)

计算由线段形成的平面直线图并定位S和E所属的面。当且仅当S和E属于同一面时,才有路径。前两个步骤是来自计算几何的标准多项式时间算法,有许多描述和实现。