Más

¿Creando polígono que conecta puntos finales de múltiples líneas usando ArcPy?

¿Creando polígono que conecta puntos finales de múltiples líneas usando ArcPy?


Estoy tratando de averiguar cómo crear un polígono que conecte todos los puntos finales de un shapefile que contiene un conjunto de polilinas con pythonscript en ArcGIS, tengo problemas para hacer esto ya que el orden de los nodos en el polígono es importante. Quiero lograr el polígono gris en la imagen a partir de las líneas verdes.


PASOS:

Calcular los puntos centrales de las secciones:

Construyó su árbol de expansión mínimo euclidiano, disuélvalo y calcule el búfer, la distancia es igual a la mitad de la longitud de la sección más corta:

Cree puntos finales de sección y calcule su PK (distancia a lo largo de la línea) en el límite de la zona de influencia (versión de polilínea cerrada de la zona de influencia):

Ordene los puntos finales en orden ascendente utilizando el campo de PK. Puntos a continuación etiquetados por su FID:

Crear polígono a partir de un conjunto ordenado de puntos:

Texto:

importar arcpy, traceback, os, sys, tiempo desde heapq importar * desde matemáticas importar sqrt importar itertools como de colecciones importar defaultdict try: def showPyMessage (): arcpy.AddMessage (str (time.ctime ()) + "-" + message) # MST por PRIM's def prim (nodos, bordes): conn = defaultdict (lista) para n1, n2, c en bordes: 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 ) si n2 no está en uso: used.add (n2) mst.append ((n1, n2, cost)) para e en conn [n2]: si e [2] no está en uso: heappush (usable_edges, e) return mst mxd = arcpy.mapping.MapDocument ("ACTUAL") SECCIONES = arcpy.mapping.ListLayers (mxd, "SECCIÓN") [0] PGONS = arcpy.mapping.ListLayers (mxd, "RESULTADO") [0] d = arcpy. Describe (SECTIONS) SR = d.spatialReference cPoints, endPoints, lMin = [], [], 1000000 con arcpy.da.SearchCursor (SECTIONS, "Shape @") como cursor: # crea puntos centrales y finales para r ujo en el cursor: dote = fila [0] l = dote.longitud lMin = min (lMin, dote.longitud) theP = feat.positionAlongLine (l / 2) .firstPoint cPoints.append (theP) theP = feat.firstPoint endPoints. append (theP) theP = feat.lastPoint endPoints.append (theP) arcpy.AddMessage ('Cálculo del árbol de expansión mínimo') m = len (cPoints) nodos = [str (i) para i en el rango (m)] p = lista (itt.combinations (rango (m), 2)) aristas = [] para f, t en p: p1 = cPuntos [f] p2 = cPuntos [t] dX = p2.X-p1.X; dY = p2. Y-p1.Y lenV = sqrt (dX * dX + dY * dY) bordes.append ((str (f), str (t), lenV)) MST = prim (nodos, bordes) mLine = [] para el borde en MST: p1 = cPoints [int (edge ​​[0])] p2 = cPoints [int (edge ​​[1])] mLine.append ([p1, p2]) pLine = arcpy.Polyline (arcpy.Array (mLine), SR ) # crear búfer y calcular PK buf = pLine.buffer (lMin / 2) outLine = buf.boundary () chainage = [] para p en endPoints: medida = outLine.measureOnLine (p) chainage.append ([medida, p] ) chainage.sort (key = lambda x: x [0]) # polígono construido pGon = arcpy.Array () para par en chainage: pGon.add (par [1]) pGon = arcpy.Polygon (pGon, SR) curT = arcpy.da.InsertCurso r (PGONS, "SHAPE @") curT.insertRow ((pGon,)) del curT excepto: message = " n *** PYTHON ERRORS ***"; showPyMessage () message = "Información de seguimiento de Python:" + traceback.format_tb (sys.exc_info () [2]) [0]; showPyMessage () message = "Información de error de Python:" + str (sys.exc_type) + ":" + str (sys.exc_value) + " n"; showPyMessage ()

Sé que es una bicicleta, pero es mía y me gusta


Publico esta solución para QGIS aquí porque es un software gratuito y fácil de implementar. Solo consideré la "rama" derecha de la capa vectorial de polilínea; como se puede observar en la siguiente imagen (12 características en la tabla de atributos):

El código (algoritmo en una comprensión de lista de Python de una línea), para ejecutarse en la consola Python de QGIS, es:

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 formas cerradas multilíneas = [[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]) #creación de una capa de memoria para múltiples polígonos 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 atributos valores feature [i] .setAttributes ([i]) mem_layer.addFeature (feature [i ], True) #detenga la edición y guarde los cambios mem_l ayer.commitChanges ()

Después de ejecutar el código:

se produjo una capa de memoria poligonal (con 11 entidades en su tabla de atributos). Funciona muy bien.


Puede seleccionar los puntos finales que participarán en un polígono, crear un TIN solo a partir de esos puntos. Convierta el TIN en polígonos, disuelva los polígonos. El truco para automatizar este proceso es decidir qué puntos contribuir a cada polígono. Si tiene líneas con direcciones válidas, y todas esas líneas comparten algún atributo común, puede escribir una consulta para exportar, por ejemplo, los vértices finales usando vértices de línea a puntos, luego seleccione por atributo aquellos puntos que tienen el valor de atributo común.
Mejor sería extraer / seleccionar los puntos, leer los valores x, y usando un cursor, usar los valores x, y para escribir un nuevo polígono. No puedo ver una imagen adjunta en su publicación, pero si el orden de los puntos es importante, una vez que tenga los valores x, y almacenados en una lista de Python, ordénelos. http://resources.arcgis.com/EN/HELP/MAIN/10.1/index.html#//002z0000001v000000


Ampliando el comentario @iant, la geometría más cercana a su instantánea es la forma alfa (casco alfa) de los puntos finales. Afortunadamente, muchos hilos bien recibidos ya han sido respondidos en GIS SE. Por ejemplo:

  • Cree un polígono complejo a partir de una capa de puntos utilizando solo puntos de contorno en ArcGIS

  • ¿Qué son la definición, los algoritmos y las soluciones prácticas para el casco cóncavo?

Para resolver su problema, primero use Característica a punto para extraer los puntos finales. Luego use la herramienta Python de este Enlace para calcular el casco cóncavo.