Créer un polygone reliant les points d'extrémité de plusieurs lignes à l'aide d'ArcPy?

10

J'essaie de comprendre comment créer un polygone qui relie tous les points de terminaison d'un fichier de formes contenant un ensemble de polyilnes avec pythonscript dans ArcGIS, j'ai du mal à le faire car l'ordre des nœuds dans le polygone est important. Je veux réaliser le polygone gris dans l'image à partir des lignes vertes

Je veux connecter les extrémités des lignes vertes pour créer le polygone gris sans avoir à le faire manuellement

Amanda
la source
vos lignes ont-elles un attribut pour donner la commande?
Ian Turton
d'abord, vous avez besoin de l'ordre défini comme @iant demandé, puis vous avez besoin de la règle pour connecter le point de terminaison au prochain point de départ ou le faire d'une autre manière
Matej
3
à défaut, peut-être une sorte de coque alpha sur les extrémités?
Ian Turton
La ligne a dans une certaine mesure des attributs pour leur donner de l'ordre. Ils ont un numéro d'identification, mais pour l'exemple ci-dessus, la branche de droite a l'ID 1-7, la gauche 15-21 et après avoir été connectés, les identifiants sont 22-27
Amanda
1
Vous pouvez vous en approcher de très près en a) créant un TIN à l'aide de lignes, b) convertissant le TIN en triangles c) sélectionnant des triangles qui partagent une frontière avec des lignes. Vous n'aurez qu'un seul polygone à supprimer en haut
FelixIP

Réponses:

11

PAS:

Calculer les points centraux des sections: entrez la description de l'image ici

Construit leur arbre couvrant minimum euclidien, le dissout et le tampon de calcul, la distance égale à la moitié de la longueur de section la plus courte: entrez la description de l'image ici

Créez des points d'extrémité de section et calculez leur chaînage (distance le long de la ligne) à la limite du tampon (version polyligne fermée du tampon): entrez la description de l'image ici

Triez les points finaux dans l'ordre croissant à l'aide du champ de chaînage. Points ci-dessous étiquetés par leur FID:

entrez la description de l'image ici

Créez un polygone à partir d'un ensemble ordonné de points: entrez la description de l'image ici

Scénario:

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

Je sais que c'est un vélo, mais c'est le mien et j'aime ça

FelixIP
la source
2

Je poste cette solution pour QGIS ici car c'est un logiciel gratuit et facile à implémenter. Je n'ai considéré que la «branche» droite de la couche vectorielle polyligne; comme cela peut être observé à l'image suivante (12 caractéristiques à la table des attributs):

entrez la description de l'image ici

Le code (algorithme dans une compréhension de liste python d'une ligne), à ​​exécuter sur la console Python de QGIS, est:

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

Après avoir exécuté le code:

entrez la description de l'image ici

il a été produit une couche de mémoire de polygone (avec 11 entités à sa table d'attributs). Ça marche bien.

xunilk
la source
1

Vous pouvez sélectionner les points d'extrémité qui participeront à un polygone, créer un TIN à partir de ces points uniquement. Convertissez le TIN en polygones, dissolvez les polygones. L'astuce pour automatiser ce processus consiste à décider quels points contribuer à chaque polygone. Si vous avez des lignes avec des directions valides et que ces lignes partagent toutes un attribut commun, vous pouvez écrire une requête à exporter, par exemple les sommets d'extrémité en utilisant des sommets de ligne vers des points, puis sélectionnez par attribut les points qui ont la valeur d'attribut commune.
Mieux serait d'extraire / sélectionner les points, de lire les valeurs x, y à l'aide d'un curseur, d'utiliser les valeurs x, y pour écrire un nouveau polygone. Je ne peux pas voir une image jointe dans votre message, mais si l'ordre des points est important, une fois que les valeurs x, y sont stockées dans une liste Python, triez-les. http://resources.arcgis.com/EN/HELP/MAIN/10.1/index.html#//002z0000001v000000

GBG
la source
1

En développant le commentaire @iant, la géométrie la plus proche de votre instantané est la forme alpha (coque alpha) des extrémités. Heureusement, de nombreux sujets bien reçus ont déjà reçu une réponse sur GIS SE. Par exemple:

Pour résoudre votre problème, utilisez d'abord Feature To Point pour extraire les points finaux. Utilisez ensuite l'outil python de ce lien pour calculer la coque concave.

Farid Cheraghi
la source
Votre premier lien semble rompu.
PolyGeo