Erstellen von Polygonen, die Endpunkte mehrerer Linien mit ArcPy verbinden?


10

Ich versuche herauszufinden, wie ein Polygon erstellt wird, das alle Endpunkte eines Shapefiles, das eine Reihe von Polyilnen enthält, mit PythonScript in ArcGIS verbindet. Ich habe Probleme damit, da die Reihenfolge der Knoten im Polygon wichtig ist. Ich möchte das graue Polygon im Bild aus den grünen Linien erreichen

Ich möchte die Endpunkte der grünen Linien verbinden, um das graue Polygon zu erstellen, ohne dies manuell tun zu müssen


Haben Ihre Zeilen ein Attribut für die Bestellung?
Ian Turton

Zuerst muss die als @iant definierte Reihenfolge gefragt werden, dann muss die Regel festgelegt werden, ob der Endpunkt mit dem nächsten Startpunkt verbunden oder auf andere Weise ausgeführt werden soll
Matej

3
Gelingt das nicht vielleicht eine Art Alpha-Rumpf an den Endpunkten?
Ian Turton

Die Linie hat bis zu einem gewissen Grad Attribute, um ihnen Ordnung zu geben. Sie haben eine ID-Nummer, aber für das obige Beispiel hat der rechte Zweig die ID 1-7, die linke 15-21 und nachdem sie verbunden sind, sind die IDs 22-27
Amanda

1
Sie können sehr nahe kommen, indem Sie a) TIN mithilfe von Linien erstellen, b) TIN in Dreiecke konvertieren, c) Dreiecke auswählen, die eine Grenze mit Linien teilen. Sie müssen nur 1 Polygon oben löschen
FelixIP

Antworten:


11

SCHRITTE:

Berechnen Sie die Mittelpunkte der Abschnitte: Geben Sie hier die Bildbeschreibung ein

Bauen Sie ihren euklidischen minimalen Spannbaum auf, lösen Sie ihn auf und berechnen Sie den Puffer. Der Abstand entspricht der Hälfte der kürzesten Abschnittslänge: Geben Sie hier die Bildbeschreibung ein

Erstellen Sie Abschnittsendpunkte und berechnen Sie deren Verkettung (Abstand entlang der Linie) an der Grenze des Puffers (geschlossene Polylinienversion des Puffers): Geben Sie hier die Bildbeschreibung ein

Sortieren Sie die Endpunkte in aufsteigender Reihenfolge mithilfe des Verkettungsfelds. Punkte unten gekennzeichnet durch ihre FID:

Geben Sie hier die Bildbeschreibung ein

Erstellen Sie ein Polygon aus einer geordneten Menge von Punkten: Geben Sie hier die Bildbeschreibung ein

Skript:

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()

Ich weiß, dass es ein Fahrrad ist, aber es ist mein eigenes und ich mag es


2

Ich poste diese Lösung für QGIS hier, weil sie freie Software ist und einfach zu implementieren ist. Ich habe nur den richtigen "Zweig" der Polylinienvektorschicht betrachtet. wie es auf dem nächsten Bild zu sehen ist (12 Merkmale in der Attributtabelle):

Geben Sie hier die Bildbeschreibung ein

Der Code (Algorithmus in einem einzeiligen Python-Listenverständnis) für die Ausführung in der Python-Konsole von QGIS lautet:

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()

Nach dem Ausführen des Codes:

Geben Sie hier die Bildbeschreibung ein

Es wurde eine Polygon-Speicherebene erstellt (mit 11 Merkmalen in der Attributtabelle). Es funktioniert gut.


1

Sie können die Endpunkte auswählen, die an einem Polygon teilnehmen sollen, und nur aus diesen Punkten eine TIN erstellen. Konvertieren Sie die TIN in Polygone, lösen Sie die Polygone auf. Der Trick zur Automatisierung dieses Prozesses besteht darin, zu entscheiden, welche Punkte zu jedem Polygon beitragen sollen. Wenn Sie Linien mit gültigen Richtungen haben und diese Linien alle ein gemeinsames Attribut haben, können Sie eine Abfrage zum Exportieren schreiben, z. B. die Endscheitelpunkte mithilfe von Linienscheitelpunkten zu Punkten, und dann nach Attributen die Punkte auswählen, die den gemeinsamen Attributwert haben.
Besser wäre es, die Punkte zu extrahieren / auszuwählen, die x, y-Werte mit einem Cursor zu lesen und mit den x, y-Werten ein neues Polygon zu schreiben. Ich kann kein angehängtes Bild in Ihrem Beitrag sehen, aber wenn die Punktreihenfolge wichtig ist, sortieren Sie sie, sobald Sie die x-, y-Werte in einer Python-Liste gespeichert haben. http://resources.arcgis.com/EN/HELP/MAIN/10.1/index.html#//002z0000001v000000


1

Wenn Sie den Kommentar @iant erweitern, ist die Alpha-Form (Alpha-Rumpf) der Endpunkte die Ihrem Snapshot am nächsten liegende Geometrie. Glücklicherweise wurden viele gut aufgenommene Threads bereits auf GIS SE beantwortet. Beispielsweise:

Um Ihr Problem zu lösen, verwenden Sie zuerst Feature To Point , um die Endpunkte zu extrahieren. Verwenden Sie dann das Python-Tool aus diesem Link , um den konkaven Rumpf zu berechnen.


Ihr erster Link scheint defekt zu sein.
PolyGeo
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.