7 votos

¿Cómo Unsplit/disolver tocar múltiples líneas de corriente de red?

Estoy tratando de disolver varias líneas de flujo de las redes en las características individuales. El conjunto de datos contiene muchos flujo de redes para una completa disolver de todo el conjunto de datos no hacer lo que yo quisiera sólo disuelve los arroyos que se encuentran en la misma red (ilustrado en la imagen de abajo).

He intentado usar el Unsplit Línea de la herramienta y la herramienta de Disolver en ArcGIS 10. La herramienta sólo se unen dos líneas juntas, es decir, líneas que comparten un punto final. Esto se muestra en las capturas de pantalla a continuación.

enter image description here

Aquí es el orignal conjunto de datos con las líneas de división, una sola línea característica de resaltado

enter image description here

Esta es la misma característica resaltada después de usar el unsplit/herramienta de disolver. Como se puede ver que sólo ha unido dos líneas juntas, en lugar de todas las líneas que se están tocando.

Todas las sugerencias son bienvenidas. Estoy utilizando ArcGIS 10, pero estoy abierto para el uso de QGIS (aunque por lo que puedo decir la herramienta de disolver en QGIS hace lo mismo).

Las características de la misma red no tienen un atributo en común.

9voto

hacker hwak Puntos 11

Gracias a todos por sus respuestas.

De hecho, he ideado una forma de hacerlo con trozos de todas las respuestas.

Las secuencias de comandos que @GeoJohn y @FelixIP han creado pueda funcionar bien (si tiene acceso a ArcGIS 10.1 y la base de datos de funciones de acceso), así que si alguien tuvo este problema por favor marque las opciones que fuera así.

Hice lo siguiente al final:

  1. Creó un muy pequeño búfer polígono alrededor de las líneas (0.1 m) para asegurarse de que no se cruce entre las líneas que estaban conectados.

  2. Utilice la herramienta de disolver con la Unsplit opción marcada. Esto crea polígonos individuales para cada uno de la línea conectada grupos.

  3. Crear un IDENTIFICADOR único para cada polígono.

  4. Utilice la herramienta de unión espacial para agregar el único polígono número de identificación a cada línea que interseca o está dentro de los polígonos.

  5. Utilice la herramienta de disolver de nuevo a disolver las líneas basándose en el IDENTIFICADOR único.

Que ha trabajado para mí, pero como he dicho los métodos de scripting puede ser preferible para otras personas.

enter image description here

3voto

RobW Puntos 121

Creo que la mejor manera para hacer esto es en arcpy. El siguiente es un script completo que va a hacer lo que usted necesita. Funciona colocando un pequeño buffer alrededor de todo el flujo de las características y la indexación de los mismos(añade un campo que se utiliza posteriormente en la secuencia de comandos para disolver). El búfer permite que cada parte de una red, si está conectado o no, para ser considerado parte de ella mediante el uso de la distancia de búfer como una "tolerancia". Así que... si las redes sociales están muy cerca se puede establecer la distancia de búfer menor.

import arcpy, os
from arcpy import env

arcpy.env.overwriteOutput = True

inFC = arcpy.GetParameterAsText(0)
outLoc = arcpy.GetParameterAsText(1)
outName = arcpy.GetParameterAsText(2)

newFC = os.path.join(outLoc, outName)

def buildWhereClause(table, field, value):
    fieldDelimited = arcpy.AddFieldDelimiters(table, field)
    fieldType = arcpy.ListFields(table, field)[0].type
    if str(fieldType) == 'String':
        value = "'%s'" % value
    whereClause = "%s = %s" % (fieldDelimited, value)
    return whereClause

bufferClass = os.path.join(outLoc, outName + "_Buffer")
singleClass = os.path.join(outLoc, outName + "_singlePart")

arcpy.Buffer_analysis(inFC, bufferClass, 500, "", "", "ALL")
arcpy.MultipartToSinglepart_management(bufferClass, singleClass)

arcpy.AddField_management(singleClass, "INDEX_ID", "LONG")

fields = arcpy.ListFields(singleClass)
fieldList = []

for nm in fields:
    fieldList.append(nm.name)

for field in fieldList:
    if field == "INDEX_ID":
        fieldCounter = 1
        with arcpy.da.UpdateCursor(singleClass, field) as cursor:
            for row in cursor:
                row[0] = fieldCounter
                cursor.updateRow(row)
                fieldCounter += 1
        del cursor
        del row

arcpy.CreateFeatureclass_management(outLoc, outName + "_Final", "POLYLINE")
finalFC = os.path.join(outLoc, outName + "_Final")

try:
    arcpy.AddField_management(finalFC, "ID_Match", "LONG")
except:
    pass

tempFC = os.path.join(outLoc, "tempFC_SE")
tempFC_2 = os.path.join(outLoc, "tempFC_SE_2")

arcpy.AddField_management(inFC, "ID_Match", "LONG")

fieldMatch = ["INDEX_ID", "OBJECTID"]
inFCMatch = ["ID_Match"]

arcpy.MakeFeatureLayer_management(singleClass, "singleClass_lyr")
arcpy.MakeFeatureLayer_management(inFC, "inFC_lyr")

with arcpy.da.SearchCursor("singleClass_lyr", fieldMatch) as cursor:
    for row in cursor:
        arcpy.SelectLayerByAttribute_management("singleClass_lyr", "CLEAR_SELECTION")
        arcpy.SelectLayerByAttribute_management("inFC_lyr", "CLEAR_SELECTION")
        where = buildWhereClause(singleClass, "OBJECTID", str(row[1]))
        arcpy.SelectLayerByAttribute_management("singleClass_lyr", "NEW_SELECTION", where)
        arcpy.CopyFeatures_management("singleClass_lyr", tempFC_2)
        arcpy.SelectLayerByLocation_management("inFC_lyr", "INTERSECT", tempFC_2)
        arcpy.CopyFeatures_management("inFC_lyr", tempFC)
        with arcpy.da.UpdateCursor(tempFC, inFCMatch) as cursor2:
            for row2 in cursor2:
                row2[0] = row[0]
                cursor2.updateRow(row2)
        del cursor2
        del row2
        arcpy.Append_management(tempFC, finalFC, "NO_TEST")
        arcpy.Delete_management(tempFC)
        arcpy.Delete_management(tempFC_2)
del cursor
del row

arcpy.Dissolve_management(finalFC, newFC, "ID_Match")

arcpy.Delete_management(finalFC)
arcpy.Delete_management(bufferClass)
arcpy.Delete_management(singleClass)

Los resultados no preservar los campos de la original de FC, pero con un poco de ajuste que también es posible.

3voto

FelixIP Puntos 4035

Si entiendo correctamente a la pregunta y esto es lo que te gustaría ver enter image description here la secuencia de comandos a continuación va a hacer

# Import arcpy module
import arcpy, traceback, os, sys
from arcpy import env
infc = r'D:\Scratch\river_cl.shp'
joined = r'D:\Scratch\s_joined.shp'
groupField="GROUP"
arcpy.overwriteoutput=1
try:
    def showPyMessage():
        arcpy.AddMessage(str(time.ctime()) + " - " + message)
    arcpy.SpatialJoin_analysis(infc, infc, joined, "JOIN_ONE_TO_MANY","KEEP_ALL", "", "BOUNDARY_TOUCHES")
    vFT=list(arcpy.da.TableToNumPyArray(joined,("TARGET_FID","JOIN_FID")))
    bigList=[]
    while (True):
        if len(vFT)==0:
            break
        first=list(vFT.pop(0))
        while (True):
            if len(vFT)==0:
                break
            if -1 not in first:
                m=0;toRemove=[]
                for ent in vFT:
                    f,t = ent
                    if f in first or t in first:
                        small = filter(lambda x: x not in first, ent)
                        first+=small
                        toRemove.append(m)
                    m+=1
                if len(toRemove)==0:
                    break
                toRemove.reverse()
                for m in toRemove:
                    vFT.pop(m)
            else:
                break
        bigList.append(first)

    result=arcpy.GetCount_management(infc)
    nStreams=int(result.getOutput(0))
    groups=[-1]*nStreams
    m=0
    for first in bigList:
        small = tuple(filter(lambda x: x not in [-1], first))
        arcpy.AddMessage('Group %i Contains FID(s) in %s' %(m,small))
        for n in small:
            groups[n]=m
        m+=1
    with arcpy.da.UpdateCursor(infc,groupField) as cursor:
        m=0
        for row in cursor:
            row[0]=groups[m]
            cursor.updateRow(row)
            m+=1
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()            

Reemplazar sólo 3 líneas en el principio, empezando con infc=... por shapefile, intermedio de salida y de campo para almacenar Grupo No. Añadir este campo para infc manualmente. Secuencia de comandos de rellenar este campo con el único grupo de números. Puede ser utilizado para disolver

0voto

UnkwnTech Puntos 21942

He encontrado otro método que se describe en una publicación de foro de discusión de ArcGIS que creo que podría funcionar y puede ser más simple:

crear una ruta de la línea shapefile (deshabilitando ignorar diferencias espaciales) y luego explota la ruta resultante.

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