使用ArcPy创建连接多条线的端点的多边形吗?


10

我试图弄清楚如何创建一个多边形,以在ArcGIS中用pythonscript连接一个包含一组polyilnes的shapefile的所有端点,但是这样做很麻烦,因为多边形中节点的顺序很重要。我想从绿线获得图片中的灰色多边形

我想连接绿线的端点以创建灰色多边形,而无需手动执行


您的行是否具有某些属性以进行排序?
伊恩·特顿

首先,您需要按@iant要求的顺序进行定义,然后需要使用规则将端点连接到下一个起点还是以其他方式进行
Matej 2015年

3
是否在端点上没有某种alpha外壳?
伊恩·特顿

该行在某种程度上确实具有赋予它们顺序的属性。他们有一个ID号,但对于右分支上方的示例,其ID为1-7,左边为15-21,并且在连接后,ID为22-27
Amanda

1
通过a)使用线创建TIN,b)将TIN转换为三角形c)选择与线共享边界的三角形,您可以非常接近。您只有1个要删除的多边形在顶部
FelixIP 2015年

Answers:


11

脚步:

计算剖面中心点: 在此处输入图片说明

建立了他们的欧几里得最小生成树,将其分解并计算缓冲区,距离等于最短部分长度的一半: 在此处输入图片说明

在缓冲区(封闭的折线版本)的边界上创建截面端点并计算其桩号(沿线的距离): 在此处输入图片说明

使用桩号字段按升序对端点进行排序。以下由其FID标记的点:

在此处输入图片说明

从一组有序点创建多边形: 在此处输入图片说明

脚本:

import arcpy, traceback, os, sys,time
from heapq import *
from math import sqrt
import itertools as itt
from collections import defaultdict

try:
    def showPyMessage():
        arcpy.AddMessage(str(time.ctime()) + " - " + message)
    # MST by PRIM's
    def prim( nodes, edges ):
        conn = defaultdict( list )
        for n1,n2,c in edges:
            conn[ n1 ].append( (c, n1, n2) )
            conn[ n2 ].append( (c, n2, n1) )
        mst = []
        used = set( nodes[ 0 ] )
        usable_edges = conn[ nodes[0] ][:]
        heapify( usable_edges )

        while usable_edges:
            cost, n1, n2 = heappop( usable_edges )
            if n2 not in used:
                used.add( n2 )
                mst.append( ( n1, n2, cost ) )

                for e in conn[ n2 ]:
                    if e[ 2 ] not in used:
                        heappush( usable_edges, e )
        return mst        


    mxd = arcpy.mapping.MapDocument("CURRENT")
    SECTIONS=arcpy.mapping.ListLayers(mxd,"SECTION")[0]
    PGONS=arcpy.mapping.ListLayers(mxd,"RESULT")[0]
    d=arcpy.Describe(SECTIONS)
    SR=d.spatialReference

    cPoints,endPoints,lMin=[],[],1000000
    with arcpy.da.SearchCursor(SECTIONS, "Shape@") as cursor:
        # create centre and end points
        for row in cursor:
            feat=row[0]
            l=feat.length
            lMin=min(lMin,feat.length)
            theP=feat.positionAlongLine (l/2).firstPoint
            cPoints.append(theP)
            theP=feat.firstPoint
            endPoints.append(theP)
            theP=feat.lastPoint
            endPoints.append(theP)

        arcpy.AddMessage('Computing minimum spanning tree')
        m=len(cPoints)
        nodes=[str(i) for i in range(m)]
        p=list(itt.combinations(range(m), 2))
        edges=[]
        for f,t in p:
            p1=cPoints[f]
            p2=cPoints[t]
            dX=p2.X-p1.X;dY=p2.Y-p1.Y
            lenV=sqrt(dX*dX+dY*dY)
            edges.append((str(f),str(t),lenV))
        MST=prim(nodes,edges)

        mLine=[]
        for edge in MST:
            p1=cPoints[int(edge[0])]
            p2=cPoints[int(edge[1])]
            mLine.append([p1,p2])
        pLine=arcpy.Polyline(arcpy.Array(mLine),SR)

        # create buffer and compute chainage
        buf=pLine.buffer(lMin/2)
        outLine=buf.boundary()
        chainage=[]
        for p in endPoints:
            measure=outLine.measureOnLine(p)
            chainage.append([measure,p])
        chainage.sort(key=lambda x: x[0])

        # built polygon
        pGon=arcpy.Array()
        for pair in chainage:
            pGon.add(pair[1])
        pGon=arcpy.Polygon(pGon,SR)
        curT = arcpy.da.InsertCursor(PGONS,"SHAPE@")
        curT.insertRow((pGon,))
        del curT
except:
    message = "\n*** PYTHON ERRORS *** "; showPyMessage()
    message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
    message = "Python Error Info: " +  str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()

我知道这是一辆自行车,但它是我自己的,我喜欢


2

我在此发布了用于QGIS的解决方案,因为它是免费软件,易于实现。我只考虑了折线矢量层的正确“分支”。如在下一张图片中可以看到的(属性表中的12个特征):

在此处输入图片说明

在QGIS的Python控制台上运行的代码(单行python列表推导中的算法)为:

layer = iface.activeLayer()

features = layer.getFeatures()

features = [feature for feature in features]

n = len(features)

geom = [feature.geometry().asPolyline() for feature in features ]

#multi lines as closed shapes
multi_lines = [[geom[i][0], geom[i][1], geom[i+1][1], geom[i+1][0], geom[i][0]]
               for i in range(n-1)]

#multi polygons
mult_pol = [[] for i in range(n-1)]

for i in range(n-1):
    mult_pol[i].append(multi_lines[i])

#creating a memory layer for multi polygon
crs = layer.crs()
epsg = crs.postgisSrid()

uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           "polygon",
                           "memory")

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

mem_layer.startEditing()

#Set features
feature = [QgsFeature() for i in range(n-1)]

for i in range(n-1):
    #set geometry
    feature[i].setGeometry(QgsGeometry.fromPolygon(mult_pol[i]))
    #set attributes values
    feature[i].setAttributes([i])
    mem_layer.addFeature(feature[i], True)

#stop editing and save changes
mem_layer.commitChanges()

运行代码后:

在此处输入图片说明

它产生了一个多边形存储层(在其属性表中具有11个要素)。效果很好。


1

您可以选择将参与多边形的端点,仅从这些点创建TIN。将TIN转换为多边形,溶解多边形。自动执行此过程的技巧是确定对每个多边形有贡献的点。如果您的线具有正确的方向,并且这些线都共享某些公共属性,则可以编写查询以使用线顶点到点来导出说出最终顶点的查询,然后按属性选择具有公共属性值的那些点。
更好的方法是提取/选择点,使用光标读取x,y值,使用x,y值编写新的多边形。我看不到帖子中的附件图片,但是如果点顺序很重要,那么一旦将x,y值存储在Python列表中,就可以对其进行排序。 http://resources.arcgis.com/CN/HELP/MAIN/10.1/index.html#//002z0000001v000000


1

在@iant注释上展开,最接近快照的几何是端点的alpha形状(alpha外壳)。幸运的是,在GIS SE上已经回答了许多受欢迎的线程。例如:

要解决您的问题,请首先使用“ 要素到点”来提取端点。然后使用此链接中的python工具计算凹壳。


您的第一个链接似乎已断开。
PolyGeo
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.