优化用于LineStrings交集的python代码

时间:2018-01-20 15:50:25

标签: python shapely multilinestring

我正在尝试查找列表中多个LineStrings的交叉点。你知道我怎么能优化这个吗?我不确定如何让它变得更快(提供一个小例子):

from shapely.geometry import LineString
l1 = LineString([Point(-122.238615,37.78376699999999), Point(-122.237455,37.78220799999999)])
l2 = LineString([Point(-122.236899, 37.77980199999999), Point(-122.232146, 37.77611)])
l3 = LineString([Point(-122.232452, 37.775956), Point(-122.236212, 37.775573)])
l4 = LineString([Point(-122.234843, 37.77336199999999), Point(-122.231641, 37.77664699999999)])
l5 = LineString([Point(-121.908187, 37.67754099999999),Point(-121.908409, 37.67810899999999)])

linestrings = [l1,l2,l3,l4,l5,l1,l2,l3,l4,l5,l1,l2,l3,l4,l5,l1,l2,l3,l4,l5,l1,l2,l3,l4,l5,l1,l2,l3,l4,l5]

import time
the_time = time.time()
[ x.intersection(y) for idx1,x in enumerate(linestrings) for idx2,y in enumerate(linestrings) if idx1<idx2 and x.intersects(y)]
print("TIME:",time.time()-the_time)

输出:

TIME: 0.026987314224243164

这是一个小例子,但我有更多的数据,任何想法如何让它更快?

1 个答案:

答案 0 :(得分:1)

使用空间索引可能是有用的,这样LineStrings上的内部循环可以简化为仅在与外部循环中迭代的LineString的边界框相交的边界框上循环,即,只考虑那些有可能交叉的LineStrings。

为此,有rtree包:

#!/usr/bin/env python
import time

from shapely.geometry import LineString, Point
import rtree

def main():
    l1 = LineString([Point(-122.238615,37.78376699999999), Point(-122.237455,37.78220799999999)])
    l2 = LineString([Point(-122.236899, 37.77980199999999), Point(-122.232146, 37.77611)])
    l3 = LineString([Point(-122.232452, 37.775956), Point(-122.236212, 37.775573)])
    l4 = LineString([Point(-122.234843, 37.77336199999999), Point(-122.231641, 37.77664699999999)])
    l5 = LineString([Point(-121.908187, 37.67754099999999),Point(-121.908409, 37.67810899999999)])

    linestrings = [l1,l2,l3,l4,l5]

    the_time = time.time()
    L = [ x.intersection(y) for idx1,x in enumerate(linestrings) for idx2,y in enumerate(linestrings) if idx1<idx2 and x.intersects(y) ]
    print("TIME: ", time.time() - the_time)

    the_time = time.time()
    index = rtree.index.Index()
    for idx, l in enumerate(linestrings):
        index.insert(idx, l.bounds)

    K = []
    for i1, l1 in enumerate(linestrings):
        for i2 in index.intersection(l1.bounds):
            if i2 >= i1: continue

            omega = l1.intersection(linestrings[i2])
            if omega.is_empty: continue

            K.append(omega)

    print("TIME: ", time.time() - the_time)

if __name__ == '__main__':
    main()