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")
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.
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.