Suite

Annuler la division/dissoudre plusieurs lignes de contact dans Stream Network à l'aide d'ArcGIS Desktop ?

Annuler la division/dissoudre plusieurs lignes de contact dans Stream Network à l'aide d'ArcGIS Desktop ?


J'essaie de dissoudre plusieurs lignes pour les réseaux de flux en fonctionnalités individuelles. L'ensemble de données contient de nombreux réseaux de flux, donc une dissolution complète de l'ensemble de données ne suffira pas, car je voudrais uniquement dissoudre les flux qui se trouvent dans le même réseau (illustrés dans les images ci-dessous).

J'ai essayé d'utiliser l'outil Ligne non divisée et l'outil Dissoudre dans ArcGIS 10. L'outil ne joindra que deux lignes, c'est-à-dire des lignes qui partagent un point final commun. Ceci est illustré dans les captures d'écran ci-dessous.

Voici le jeu de données d'origine avec les lignes divisées, une seule entité linéaire est mise en surbrillance

Il s'agit de la même fonctionnalité mise en évidence après avoir utilisé l'outil unsplit/dissolve. Comme vous pouvez le voir, il n'a joint que deux lignes plutôt que toutes les lignes qui se touchent.

Les entités d'un même réseau n'ont pas non plus d'attribut commun.


J'ai conçu un moyen de le faire avec de petits morceaux de toutes les autres réponses.

Les scripts créés par @GeoJohn et @FelixIP peuvent très bien fonctionner (si vous avez accès à ArcGIS 10.1 et aux fonctions d'accès à la base de données), donc si quelqu'un d'autre a eu ce problème, veuillez également vérifier ces options.

J'ai fait ce qui suit au final :

  1. Création d'un très petit polygone tampon autour des lignes (0,1 mètre) pour s'assurer qu'il y avait un croisement entre les lignes qui étaient connectées.

  2. Utilisez l'outil de dissolution avec l'option Unsplit cochée. Cela a créé des polygones individuels pour chacun des groupes de lignes connectés.

  3. Créez un identifiant unique pour chaque polygone.

  4. Utilisez l'outil de jointure spatiale pour ajouter les identifiants de polygone uniques à chaque ligne qui coupe ou se trouve à l'intérieur des polygones.

  5. Utilisez à nouveau l'outil de dissolution pour dissoudre les lignes en fonction de l'ID unique.

Cela a fonctionné pour moi, mais comme je l'ai dit, les méthodes de script peuvent être préférables pour d'autres personnes.


Je pense que la meilleure façon de le faire est dans arcpy. Ce qui suit est un script complet qui fera ce dont vous avez besoin. Cela fonctionne en plaçant un petit tampon autour de toutes les fonctionnalités du flux et en les indexant (ajoute un champ qui est utilisé plus tard dans le script pour dissoudre). La mémoire tampon permet à chaque partie d'un réseau, qu'elle soit connectée ou non, d'être considérée comme faisant partie de celui-ci en utilisant la distance de la mémoire tampon comme une "tolérance". Donc… si les réseaux sont vraiment proches les uns des autres, vous pouvez réduire la distance tampon.

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, champ, valeur): fieldDelimited = arcpy.AddFieldDelimiters(table, champ) fieldType = arcpy.ListFields(table, champ)[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") champs = arcpy.ListFields(singleClass) fieldList = [] pour nm dans les champs : fieldList.append(nm.name) pour le champ dans fieldList : if field == "INDEX_ID": fieldCounter = 1 avec arcpy.da.UpdateCursor(singleClass, fie ld) en tant que curseur : pour la ligne dans le curseur : ligne[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") essayez : arcpy.AddField_management(finalFC, "ID_Match", "LONG") sauf : 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") avec arcpy.da.SearchCursor("singleClass_lyr", fieldMatch) comme curseur : pour la ligne du curseur : arcpy.SelectLayerByAttribute_management("singleClass_lyr", "CLEAR_SELECTION") arcpy.SelectLayerByFCAttribute ", "CLEAR_SELECTION") où = buildWhereClause(singleClass, "OBJECTID", str(row[1])) arcpy.SelectLayerByAttribute_management("singleClass_lyr", "NE W_SELECTION", où) arcpy.CopyFeatures_management("singleClass_lyr", tempFC_2) arcpy.SelectLayerByLocation_management("inFC_lyr", "INTERSECT", tempFC_2) arcpy.CopyFeatures_management("inFC_lyr", tempFC) avec arcpy.da.UpdateCursor(tempFC, inFC en tant que curseur2 : pour la ligne2 dans le curseur2 : ligne2[0] = ligne[0] curseur2.updateRow(ligne2) del curseur2 del ligne2 arcpy.Append_management(tempFC, finalFC, "NO_TEST") arcpy.Delete_management(tempFC) arcpy.Delete_management(tempFC_2 ) du curseur de la ligne arcpy.Dissolve_management(finalFC, newFC, "ID_Match") arcpy.Delete_management(finalFC) arcpy.Delete_management(bufferClass) arcpy.Delete_management(singleClass)

Les résultats ne conserveront pas les champs du FC d'origine mais avec un petit ajustement qui est également possible.


Si je comprends bien la question et c'est ce que vous aimeriez voir le script ci-dessous fera l'affaire

# Importer le module arcpy import arcpy, traceback, os, sys from arcpy import env infc = r'D:Scratch
iver_cl.shp' join = r'D:Scratchs_joined.shp' groupField="GROUP" arcpy.overwriteoutput =1 essai : def showPyMessage() : arcpy.AddMessage(str(time.ctime()) + " - " + message) arcpy.SpatialJoin_analysis(infc, infc, joint, "JOIN_ONE_TO_MANY", "KEEP_ALL", "", " BOUNDARY_TOUCHES") vFT=list(arcpy.da.TableToNumPyArray(jointed,("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 ou t en premier : 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 pour le premier dans bigList : small = tuple(filter(lambda x: x not in [-1], f irst)) arcpy.AddMessage('Groupe %i Contient FID(s) dans %s' %(m,small)) pour n dans small : groups[n]=m m+=1 avec arcpy.da.UpdateCursor(infc, groupField) comme curseur : m=0 pour la ligne dans le curseur : row[0]=groups[m] cursor.updateRow(row) m+=1 sauf : message = "
*** PYTHON ERRORS *** " ; showPyMessage() message = "Informations de suivi Python : " + traceback.format_tb(sys.exc_info()[2])[0] ; showPyMessage() message = "Informations d'erreur Python : " + str(sys.exc_type)+ " : " + str(sys.exc_value) + "
" ; showPyMessage()

Remplacez simplement 3 lignes au début, en commençant par infc=… par votre fichier de formes, la sortie intermédiaire et le champ pour stocker le numéro de groupe. Ajoutez ce champ à infc manuellement. Le script remplira ce champ avec des numéros de groupe uniques. Il peut être utilisé pour dissoudre


J'ai trouvé une autre méthode décrite dans une publication sur le forum de discussion ArcGIS qui, à mon avis, fonctionnerait et pourrait être plus simple :

créer un itinéraire à partir du fichier de formes de ligne (en décochant ignorer les écarts spatiaux), puis exploser l'itinéraire résultant.


Voir la vidéo: Peut-on annuler la dette?