从一组线中查找链的算法

时间:2013-06-17 14:44:22

标签: algorithm geometry

如果两条线有一个共同的端点,则它们属于同一条链。例如,定义为(0,0)的10行 - (Rnd,Rnd)是一个有效链,因为它们都有一个共同的端点。

我开发的算法在某些幸运案例中非常快,在其他情况下非常慢。拥有10,000行,可能需要几秒到几个小时。

我正在寻找加快建议的建议。

链是由这样的循环创建的:

For Each Line in Lines
  If Chain.HasPointInCommonWith(Line) Then
    Chain.Add Line
    Lines.Remove Line
  End If
Next Line

为了避免多次运行测试,我对所有关于XMin的行进行了排序,并在寻找曲线的循环中添加了这个测试:

If Line.XMin > Chain.XMax Then Exit For

当线条代表许多矩形时,此测试很有效,一个在另一个的右边,但如果它们是一个在另一个上面的许多矩形,则无效。

3 个答案:

答案 0 :(得分:1)

将数据建模为图形,其中一条线的每个端点都是一个顶点,每条线是连接两个顶点的边。

然后,您可以使用任何标准Graph Traversal算法访问连接到给定顶点的所有顶点。

修改

定义图形后,选择一个顶点并执行DFS以构建连接顶点的树。

如果此树中没有任何顶点,请选择一个并执行另一个DFS以构建另一个树。

重复,直到所有顶点都已分配给树。

每棵树定义一个“链”。

答案 1 :(得分:1)

如何放置所有线条'线条列表网格中的端点?然后,您只需遍历网格,其中包含两行以上的任何列表都是匹配。

    //Build the list
    For Each Line in Lines
      grid[line.ymin][line.xmin].add(line)
      grid[line.ymax][line.xmax].add(line)
    Next Line

    //find the chains
    For current_x and current_y in grid
      if(grid[current_x][current_y].size() != 1)
        continue
      //start a new chain
      line = grid[current_x][current_y][0]
      chain.add(line)
      grid[current_y][current_x][0].remove(line)
      other_endpoint = line.other_endpoint(current_x, current_y)
      grid[other_endpoint.y][other_endpoint.x].remove(line)
      while(grid[other_endpoint.y][other_endpoint.x].size() >= 1)
        line = grid[other_endpoint.y][other_endpoint.x][0]
        chain.add(line)
        grid[other_endpoint.y][other_endpoint.x][0].remove(line)
        other_endpoint = line.other_endpoint(other_endpoint.y,other_endpoint.x)

第二个循环在网格单元格中找到一个单独的线条,然后检查该线条另一端的网格(在该过程中将其自身从网格中移除)。如果该位置的另一条线将其添加到链中并检查该线的其他端点,依此类推,直到没有其他线路添加到该链。然后你继续寻找下一个开始的链 这将不会捕获闭环(例如A - > B - > C - > A),因为此处的每一行检查grid[current_x][current_y].size() != 1将失败。如果您不在乎保留这些,您可以完全取消支票,否则您将在没有支票的情况下再次通行。

此外,如果这个内存量太高(现在内存量取决于线条所在的范围而不是线条数量)那么你可以扩大每个单元格的大小来保持一个范围每个细胞的位置数。你现在必须循环遍历每个单元格的行,以判断它们是否共享端点,但每个单元格理想情况下所有行都有一个非常小的子集,因此这些循环不会太糟糕,无法处理。

答案 2 :(得分:0)

  1. MPoint

  2. 创建一个空哈希图List<Line>
  3. 对于每个Line L,请在M[L.A]M[L.B]处插入空列表(如果它们尚不存在),然后执行M[L.A].Add(L)M[L.B].Add(L)

  4. M现在是从图节点(点)到事件图边(线)的映射

  5. 使用M在此图表上运行深度优先搜索以发现所有链