Sympy中迭代交叉的线段......有更好的方法吗?

时间:2015-06-03 16:37:03

标签: python geometry networkx sympy

行。我有包含多边形边框的点。我想(a)使用Sympy的几何模块从任何一对点之间的所有可能的线段中确定哪些段不穿过周边。该结果将是允许在(b)Networkx中的shortest_distance分析中使用的“边缘”。我的最终目标是通过许多形状迭代这个过程,但在这个例子中我只对1个形状的坐标进行了硬编码。

import numpy
import networkx as nx
from sympy import geometry
from itertools import combinations
from matplotlib import pyplot as plot
arr_bou = numpy.array([[-542.62545014,  961.34455209],
   [-544.45425379,  961.34455209],
   [-544.45425379,  962.25895392],
   [-547.19745928,  962.25895392],
   [-547.19745928,  963.17335575],
   [-549.02626294,  963.17335575],
   [-549.02626294,  964.08775758],
   [-550.85506659,  964.08775758],
   [-550.85506659,  961.34455209],
   [-552.68387025,  961.34455209],
   [-552.68387025,  962.25895392],
   [-553.59827208,  962.25895392],
   [-553.59827208,  965.91656123],
   [-552.68387025,  965.91656123],
   [-552.68387025,  967.7453649 ],
   [-551.76946842,  967.7453649 ],
   [-551.76946842,  968.65976672],
   [-550.85506659,  968.65976672],
   [-550.85506659,  967.7453649 ],
   [-548.11186111,  967.7453649 ],
   [-548.11186111,  965.91656123],
   [-547.19745928,  965.91656123],
   [-547.19745928,  964.08775758],
   [-546.28305745,  964.08775758],
   [-546.28305745,  965.00215941],
   [-543.53985197,  965.00215941],
   [-543.53985197,  963.17335575],
   [-542.62545014,  963.17335575],
   [-542.62545014,  964.08775758],
   [-540.79664648,  964.08775758],
   [-540.79664648,  963.17335575],
   [-539.88224465,  963.17335575],
   [-539.88224465,  962.25895392],
   [-542.62545014,  962.25895392],
   [-542.62545014,  961.34455209]])

boundXY = []
for i in arr_bou:
    boundXY.append((i[0],i[1]))

points     = [geometry.Point(i) for i in boundXY]
poly       = geometry.Polygon(*points) # use the * first to unpack the points (necessary to avoid errors)


G          = nx.Graph()
positions  = {}                                  # build a dictionary
for i in xrange(len(boundXY)):                   # that contains coordinates
    positions[i] = boundXY[i]                    # of each node on the graph's perimeter
G.add_path(positions.keys())# add nodes to graph w/ boundary edges
G.add_path([min(G.nodes()),max(G.nodes())])    combos_o   = list(combinations(positions.keys(),2))
combos     = [i for i in combos_o if i not in G.edges()]

keepcombos = []
for combo in combos:
    pt1 = positions[combo[0]]
    pt2 = positions[combo[1]]
    line = geometry.Polygon(pt1,pt2)
    # there are 4 polygon sides that do not count as intersections
    # because 2 sides will intersect a point on each end
    test = True
    for side in poly.sides:
        if side.p1 != geometry.Point(pt1) and side.p1 != geometry.Point(pt2):
            if side.p2 != geometry.Point(pt1) and side.p2 != geometry.Point(pt2):
                if geometry.intersection(line,side):
                    test = False
                    break
                else:
                    try:
                        if poly.encloses(line.midpoint):
                            pass
                        else:
                            test = False
                            break
                    except NotImplementedError:
                        pass
    if test == True:
        keepcombos.append(combo)
G.add_edges_from(keepcombos)

我已经得到这个用于小多边形(14个顶点),但即使只有35个顶点,这也需要FOREVER,而其他多边形仍将大于此。

是否有更有效的方法来查找所有多边形内的节点对?

谢谢!

2 个答案:

答案 0 :(得分:0)

如果凸包是定义包含所有其他的凸多边形的点的集合

>>> coords = [[-542.62545014,  961.34455209],
...    [-544.45425379,  961.34455209],
...    [-544.45425379,  962.25895392],
...    [-547.19745928,  962.25895392],

...    [-542.62545014,  962.25895392],
...    [-542.62545014,  961.34455209]]
>>> from sympy import *
>>> pts = [Point(*i) for i in coords]
>>> h = convex_hull(*pts)
那么你是否只对所有不在外围的点感兴趣?一旦你知道这些点,那么你只想生成这些点的所有成对组合吗?

inside = [p for p in pts if p not in h.vertices]
from sympy.utilities.iterables import combinations
pairs = combinations(inside, 2)

https://www.desmos.com/calculator/up4k2qkxy9我看到有几点似乎落在了边缘,所以也许他们不应该被包括在内外#34;内部"点。但希望你能得到我的回答。

答案 1 :(得分:0)

我找到了一个解决方案,将处理速度提高了大约13倍(对于具有35个点的多边形(如上面列出的数据),问题代码中的旧方法花了大约4小时来查找多边形内的所有线段这种新方法需要18分钟。)

上面我通过点迭代,并在每次迭代时分别查看每个边界(“边”)以查看线是否相交。我将其更改为将线与整个多边形相交。如果它在内部或边缘上划线,那么它应该只有2个点相交,所以如果交叉点的长度> 2,我会抛出组合

Started GET "/users/confirmation?confirmation_token=3DHJTJ34o1XKEL-EFn8B4j" for 46.193.138.19 at 2015-06-07 16:22:53 +0200
Processing by ConfirmationsController#show as HTML
  Parameters: {"confirmation_token"=>"3DHJTJ34o1XKEL-EFn8B4j"}
  MOPED: 127.0.0.1:27017 COMMAND      database=admin command={:ismaster=>1} runtime: 0.5095ms
  MOPED: 127.0.0.1:27017 QUERY        database=intranet_rails_development collection=users selector={"$query"=>{"confirmation_token"=>"31cd2ab688b1fd94e6327856603b68873eff7031acc69137cc7d4a527360856b"}, "$orderby"=>{:_id=>1}} flags=[] limit=-1 skip=0 batch_size=nil fields=nil runtime: 0.4650ms

此列表“keepcombos”现在具有我希望包含在Dijkstra路径分析中的所有行(或networkx“edge”)