4 votos

Actualizar la geometría de la característica con arcpy

Tengo un shapefile de edificios y carreteras. Estoy creando los centroides de los edificios y los conecto a la característica de la carretera más cercana como se muestra en la figura 1.

Código para trazar una línea entre el centro del edificio y la carretera:

import arcpy
road = r"...\road.shp"
buildings = r"...\building.shp"

arcpy.env.workspace =  arcpy.Describe(buildings).path
centroid = os.path.join(arcpy.env.workspace, "centroid.shp") 
connectingLines = os.path.join(arcpy.env.workspace, "connectingLines.shp")

arcpy.FeatureToPoint_management(buildings, centroid, "CENTROID")

arcpy.AddXY_management(centroid) #Adding POINT_X and POINT_Y
arcpy.Near_analysis(centroid, rd, "", "LOCATION", "NO_ANGLE" ) #Adding NEAR_X and NEAR_Y
arcpy.XYToLine_management(centroid, connectingLines, "POINT_X", "POINT_Y", "NEAR_X", "NEAR_Y")

enter image description here

Sin embargo, lo que quiero es lo que se muestra en la figura 2. Si la línea que conecta la carretera con el centro de un edificio pasa a través de otro edificio, la línea de conexión debería conectar con el centro de un edificio más cercano y no con la carretera.

enter image description here

Solución posible pero no completa : Dibuja la línea entre el centroide y la carretera como se muestra en la figura 1. Elimine todas las líneas que pasen por más de un edificio. Divida los puntos del centroide en conectados y desconectados. Una los puntos desconectados con los puntos conectados más cercanos. De nuevo, elimine las líneas que pasan por más de dos edificios y repita el proceso hasta que todos los puntos estén conectados.

Limitación El sistema de control de calidad: no conecta los centros de los edificios que tienen que cruzar más de 2 edificios antes de conectarse al punto más cercano.

 import arcpy,os, math
 from os.path import basename, dirname, exists, join

 rd = r"...\road.shp"
 buildings = r"...\building.shp"

 arcpy.env.workspace =  arcpy.Describe(buildings).path

 # remove lines that intersect with more than one/two buildings 
 def RemoveLine(fc, cnt):
    arcpy.AddField_management(fc, "count", "INTEGER" )

    with arcpy.da.UpdateCursor(fc, ['count', 'SHAPE@']) as cursor:
         for row in cursor:        
            arcpy.Delete_management("layer")
            arcpy.MakeFeatureLayer_management(buildings, "layer")
            arcpy.SelectLayerByLocation_management("layer", 'INTERSECT', row[1])
            result = arcpy.GetCount_management("layer")
            row[0] = int(result.getOutput(0))             
            cursor.updateRow(row)

    arcpy.Delete_management("tempLayer")        
    if cnt == 1:    
       arcpy.MakeFeatureLayer_management(fc, "tempLayer")
       arcpy.SelectLayerByAttribute_management("tempLayer",  "NEW_SELECTION", '"count" > 1')
       arcpy.DeleteFeatures_management("tempLayer")

    else:    
       arcpy.MakeFeatureLayer_management(fc, "tempLayer")
       arcpy.SelectLayerByAttribute_management("tempLayer",  "NEW_SELECTION", '"count" > 2')
       arcpy.DeleteFeatures_management("tempLayer")

 centroid = os.path.join(arcpy.env.workspace, "b_centroid.shp")

 arcpy.FeatureToPoint_management(buildings, centroid, "CENTROID")

 centroidToRd = os.path.join(arcpy.env.workspace, "centroidToRd.shp")
 arcpy.AddXY_management(centroid) # Adding POINT_X and POINT_Y
 arcpy.Near_analysis(centroid, rd, "", "LOCATION", "NO_ANGLE" ) # Adding NEAR_X and NEAR_Y
 arcpy.XYToLine_management(centroid, centroidToRd, "POINT_X", "POINT_Y", "NEAR_X", "NEAR_Y")

 RemoveLine(centroidToRd, 1)

 connectingLines = os.path.join(arcpy.env.workspace, "ConnectingLines.shp")
 arcpy.CopyFeatures_management(centroidToRd, connectingLines)

 cnt = 1
 itr = 0
 arr = [centroidToRd]

 #iterate through centroid points until each one is connected to closest centroid or directly to road

 while (cnt > 0  and itr < 5):

     itr +=1

     unique_name = arcpy.CreateUniqueName("feeder.shp")
     arcpy.Delete_management("connected")  
     arcpy.MakeFeatureLayer_management(centroid, "connected")
     arcpy.SelectLayerByLocation_management("connected", 'INTERSECT',    connectingLines, invert_spatial_relationship = "NOT_INVERT")

     arcpy.Delete_management("disconnected") 
     arcpy.MakeFeatureLayer_management(centroid, "disconnected")
     arcpy.SelectLayerByLocation_management("disconnected", 'INTERSECT', connectingLines, invert_spatial_relationship = "INVERT")
     cnt = arcpy.GetCount_management("disconnected")
     #print cnt

     arcpy.AddXY_management("disconnected") # Adding POINT_X and POINT_Y
     arcpy.Near_analysis("disconnected", "connected", "", "LOCATION", "NO_ANGLE" ) # Adding NEAR_X and NEAR_Y
     arcpy.XYToLine_management("disconnected", unique_name, "POINT_X", "POINT_Y", "NEAR_X", "NEAR_Y")

     RemoveLine(unique_name, 2)

     arr.append(unique_name)
    #print arr

     arcpy.Delete_management("ConnectingLines.shp")
     connectingLines = os.path.join(arcpy.env.workspace, "ConnectingLines.shp")
     arcpy.Merge_management(arr, connectingLines)

0 votos

Tendrá que utilizar un UpdateCursor (DA, por supuesto) para despertar cada característica para determinar si un centroide está más cerca (y en la dirección correcta).

1 votos

La línea más corta es la que hay que mantener, ya que todas las demás se alimentan de ella en la fig2. Además, el centroide más cercano significará que los dos edificios más pequeños se unirán entre sí, en cuyo caso querrás unirte a otro centroide que esté más cerca de la carretera.

2voto

Anton8000 Puntos 165

Puedes probar esta herramienta: SpanningTreeTools :

Herramientas para la creación de diversas variantes del árbol de extensión mínima euclidiano así como líneas de deseo.

He probado la herramienta EMST con ArcMap 10.5 en una capa de puntos de los centroides del edificio y la carretera más cercana. Tal vez no es exactamente lo que usted está buscando, pero vale la pena intentarlo. Está escrito en Python.

enter image description here

Lo he utilizado en un modelo con Iterate Feature Selection.

0 votos

Una herramienta interesante. El modelo es bastante lento para un gran número de puntos, pero la herramienta en sí podría ser útil para varios propósitos. Probaré a integrarla con el resto de mi programa. Gracias.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X