相交线以使用带有QGIS的Python进行交叉?


10

我有一组代表公交线路的线路。一些线重叠并且走相同的路。

在此处输入图片说明

我能够提取节点。 在此处输入图片说明

但是我对仅提取这样的交叉点感兴趣: 在此处输入图片说明

我怎样才能做到这一点?我正在寻找QGIS或Python的方法。

我尝试了GDAL Python 的交集方法,但这基本上只返回了顶点。

如果有两条线交叉,则QGIS的“ 线交叉点”方法会返回交叉点。但是,如果两条公交线路在同一条道路上走得很远,这并不能给我他们指向合并的位置。


您是否尝试过QGIS中的线相交工具:矢量分析工具>线相交...它不会为您提供线的终点和起点,而是所有相交。
雅各布2015年

是的,我在问题中写了这个。
ustroetz 2015年

我不清楚您要问的是什么,部分是因为所有行在图像中都以相同的方式符号化-我无法说出不同的路线来理解您正在查看的节点,或者为什么其中有这么多节点第二张图片。路线在道路上重合吗?它们都是两点线段还是连续多段线?我注意到,您描述的行为与ArcGIS的“相交”工具相同-带有线输出的线/线使您重叠,但是带点输出的线/线仅使交叉。
克里斯·W

基于此,要获得我认为想要的功能,可能必须同时使用这两种方法。获取交叉(线/线=点),然后获取重叠(线/线=线),并提取这些重叠线的起点/终点。这些应该是您要查找的所有点/节点。
克里斯W

Answers:


20

节点:

您需要两件事,即折线的端点(无中间节点)和交点。还有一个问题,某些折线端点也是交点:

在此处输入图片说明

一个解决方案是使用Python以及ShapelyFiona模块

1)读取shapefile:

from shapely.geometry import Point, shape
import fiona
lines = [shape(line['geometry']) for line in fiona.open("your_shapefile.shp")]

2)找到线的终点(如何获得折线的终点?):

endpts = [(Point(list(line.coords)[0]), Point(list(line.coords)[-1])) for line  in lines]
# flatten the resulting list to a simple list of points
endpts= [pt for sublist in endpts  for pt in sublist] 

在此处输入图片说明

3)计算相交(使用itertools模块通过层中的几何对进行迭代)。一些交点的结果是多点,我们需要一个点列表:

import itertools
inters = []
for line1,line2 in  itertools.combinations(lines, 2):
  if  line1.intersects(line2):
    inter = line1.intersection(line2)
    if "Point" == inter.type:
        inters.append(inter)
    elif "MultiPoint" == inter.type:
        inters.extend([pt for pt in inter])
    elif "MultiLineString" == inter.type:
        multiLine = [line for line in inter]
        first_coords = multiLine[0].coords[0]
        last_coords = multiLine[len(multiLine)-1].coords[1]
        inters.append(Point(first_coords[0], first_coords[1]))
        inters.append(Point(last_coords[0], last_coords[1]))
    elif "GeometryCollection" == inter.type:
        for geom in inter:
            if "Point" == geom.type:
                inters.append(geom)
            elif "MultiPoint" == geom.type:
                inters.extend([pt for pt in geom])
            elif "MultiLineString" == geom.type:
                multiLine = [line for line in geom]
                first_coords = multiLine[0].coords[0]
                last_coords = multiLine[len(multiLine)-1].coords[1]
                inters.append(Point(first_coords[0], first_coords[1]))
                inters.append(Point(last_coords[0], last_coords[1]))

在此处输入图片说明

4)消除端点和交点之间的重复项(如您在图中看到的)

result = endpts.extend([pt for pt in inters  if pt not in endpts])

5)保存生成的shapefile

from shapely.geometry import mapping
# schema of the shapefile
schema = {'geometry': 'Point','properties': {'test': 'int'}}
# creation of the shapefile
with fiona.open('result.shp','w','ESRI Shapefile', schema) as output:
    for i, pt in enumerate(result):
        output.write({'geometry':mapping(pt), 'properties':{'test':i}})

最后结果:

在此处输入图片说明

线段

如果你也想在节点之间的段,你需要“平面化”(平面图形,没有棱角相互交叉)的shape文件。这可以通过Shapely 的unary_union函数完成

from shapely.ops import unary_union
graph = unary_union(lines)

在此处输入图片说明


感谢@gene提供详细答案。我编辑了它涉及不同几何类型的零件。在我的情况下,交点还返回线,几何体集合等。但这取决于输入数据。我的问题还不够清楚。
ustroetz 2015年

好答案。我可能会补充说,没有必要执行以下操作:result = endpts.extend([pt for pt in inters if pt not in endpts])由于似乎.extend方法已修改endpt。就我而言result = None,那是手术之后。它endpts最终包含结果
sett
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.