Suite

Distance (linéaire) par paires entre les points du même fichier de formes

Distance (linéaire) par paires entre les points du même fichier de formes


Étant donné un ensemble de points représentant des villages stockés dans un fichier .shp, existe-t-il un moyen de calculer la distance par paire (euclidienne) entre eux ? Ce que je voudrais proposer, c'est une sorte de matrice symétrique à analyser plus en détail statistiquement.

J'utilise ArcGIS 10.1 avec une licence Advanced.


Vous pouvez également utiliser l'outil Générer une table proche pour faire la même chose que la suggestion de GISGe, mais avec quelques attributs supplémentaires (tels que xy de l'entité proche et l'angle entre les entités source et proche) si ceux-ci seraient utiles dans votre étude. Il vous permet également de spécifier un nombre de correspondances les plus proches afin que ce ne soit pas tout ou juste le plus proche.


Utilisez l'outil Distance de point pour ce faire, avec votre fichier de formes de points en tant qu'entités en entrée et paramètres d'entités proches.


Je suis désolé, je répondrais aux commentaires précédents mais je n'ai pas 50 points sur mon profil (nouveau membre) et je suis bloqué. Étant donné que vos classes d'entités « Input » et « Near » sont identiques, pourquoi ne pas créer une copie de votre FC d'origine et utilisez l'original comme "Entrée" et la copie comme "Proche" pour l'outil ? Cela peut contourner les problèmes que vous rencontrez avec l'utilisation de la même classe d'entités que Input/Near.

Les outils de proximité et les outils de distance de point nécessitent une licence avancée, il semble donc que vous ayez le niveau de licence nécessaire. Pour ceux qui ont Basic/Standard, l'algorithme Near d'ESRI n'est pas trop difficile à implémenter vous-même en Python. Cette réponse est similaire à celle que j'ai publiée dans Calculer la distance la plus proche dans ArcView, coordonnées XY. Mais puisque tu veux tous comparaisons par paires (pas seulement l'entité la plus proche), l'outil créera un tableau avec toutes les comparaisons par paires. Il créera également une classe d'entités "lignes à plomb" qui connecte toutes les paires et a les mêmes informations que la table (cette sortie est plus utile IMO). Pour les champs Target et Source ID, vous pouvez utiliser "OBJECTID" ou tout autre identifiant unique de votre choix. Il fonctionnera à n'importe quel niveau de licence. Si vous n'avez pas de chance avec les suggestions ci-dessus, essayez ce script.

__author__ = "John K. Tran" __contact__ = "[email protected]" __version__ = "1.0" __created__ = "7/1/15" """Compare toutes les entités ponctuelles cibles à toutes les entités ponctuelles source et renseigne l'ID et la distance de toutes les comparaisons par paires entre chaque cible et chaque source. Peut éventuellement créer des lignes à plomb pour visualiser les liens entre les fonctionnalités source et cible. """ import arcpy import os import math import random arcpy.SetProgressor("Default", "Firing up script… ") # Configurez les paramètres initiaux pour le script. source = arcpy.GetParameterAsText(0) # Classe d'entités ponctuelles. target = arcpy.GetParameterAsText(1) # Classe d'entités ponctuelles. outputtable = arcpy.GetParameterAsText(2) # Classe d'entités de table qui stocke les informations de distance et d'ID. sourceIDfield = arcpy.GetParameterAsText(3) # Champ pour identifier l'ID unique des valeurs Source. targetIDfield = arcpy.GetParameterAsText(4) # Champ pour identifier l'ID unique des valeurs cibles. createplumblines = arcpy.GetParameterAsText(5) # Emplacement de sortie facultatif pour les lignes à plomb. Je vous suggère FORTEMENT de spécifier un chemin pour cela ! arcpy.env.parallelProcessingFactor = "100%" #Convertir les types de champs arcpy pour l'argument "Field Type" dans AddField_management. fieldtypedict = {"Blob":"BLOB", "Date":"DATE", "Double":"DOUBLE", "Guid":"GUID", "Integer":"LONG", "Raster":"RASTER" , "Single":"FLOAT", "SmallInteger":"SHORT", "String":"TEXT", "OID":"LONG"} # Récupère le type de champ pour le champ ID source, afin que nous puissions créer un champ analogue pour NearID dans la cible. sourcefields = arcpy.ListFields(source) targetfields = arcpy.ListFields(target) sourceIDfieldtype = fieldtypedict[[field.type for field in sourcefields if field.name == sourceIDfield].pop()] targetIDfieldtype = fieldtypedict[[field.type for field in targetfields if field.name == targetIDfield].pop()] # Obtenez les références spatiales pour la source et la cible et assurez-vous qu'elles sont identiques. sourcespatialref = arcpy.Describe(source).spatialReference targetspatialref = arcpy.Describe(target).spatialReference assert sourcespatialref.name == targetspatialref.name, "La source et la cible doivent avoir le même système de coordonnées. Assurez-vous que les deux données sont dans un système de coordonnées." # Créez une classe Point avec une méthode de distance. Plus efficace que la classe arcpy.Geometry native. class Point(object): def __init__(self, x, y, ID): """Créez le constructeur pour initialiser le point.""" self.x = x self.y = y self.ID = ID def GetDist( self, OtherPoint): """ Détermine la distance entre deux points à l'aide du théorème de Pythagore.""" return math.sqrt((self.x-OtherPoint.x)**2+(self.y-OtherPoint.y)** 2) # Créez une liste de points sources à comparer avec chaque point cible. scount = 0 sourcepoints = list() avec arcpy.da.SearchCursor(source, ["[email protected]", sourceIDfield]) comme sourcecursor : pour la ligne dans sourcecursor : arcpy.SetProgressorLabel("Recueil de points source : {0} fonctionnalités terminées" .format(str(scount))) sourcepoint = Point(row[0][0], row[0][1], row[1]) sourcepoints.append(sourcepoint) scount += 1 del sourcecursor # Créer plusieurs démarrage variables si la création de lignes à plomb était activée. if createplumblines : arcpy.SetProgressorLabel("Créer une classe d'entités de ligne à plomb") plumblines = list() arcpy.CreateFeatureclass_management(os.path.dirname(createplumblines), os.path.basename(createplumblines), "POLYLINE", None, "DISABLED ", "DISABLED", targetspatialref) arcpy.AddField_management(createplumblines, "SourceID", sourceIDfieldtype) arcpy.AddField_management(createplumblines, "TargetID", targetIDfieldtype) # Crée une table pour stocker les informations de distance. arcpy.SetProgressorLabel("Making Distance Table") arcpy.CreateTable_management(os.path.dirname(outputtable), os.path.basename(outputtable)) arcpy.AddField_management(outputtable, "SourceID", sourceIDfieldtype) arcpy.AddField_management(outputtable, "TargetID", targetIDfieldtype) arcpy.AddField_management(outputtable, "Distance", "DOUBLE") # Crée une liste pour stocker chaque comparaison, afin que nous puissions l'ajouter dans le tableau par la suite. distlist = [] # Parcourez chaque cible et comparez avec chaque source et remplissez les champs ID et Distance dans le tableau. count = 0 avec arcpy.da.SearchCursor(target, ["[email protected]", targetIDfield]) comme targetcursor : pour la ligne dans targetcursor : arcpy.SetProgressorLabel("Computing Distance : {0} features complete".format(str(count ))) targetpoint = Point(row[0][0], row[0][1], row[1]) pour sourcepoint dans sourcepoints : currentdist = targetpoint.GetDist(sourcepoint) distlist.append((sourcepoint.ID, targetpoint.ID, currentdist)) si createplumblines: plumblines.append((sourcepoint, targetpoint)) count = count + 1 del targetcursor # Mettre à jour la table avec les informations de la distlist. tnum = 0 avec arcpy.da.InsertCursor(outputtable, ["SourceID", "TargetID", "Distance"]) comme tablecursor : pour la ligne dans distlist : arcpy.SetProgressorLabel("Ajout de distances à la table : {0} features complete" .format(str(tnum))) tablecursor.insertRow(row) del tablecursor # Crée les fils à plomb si l'option a été activée. si createplumblines : plnum = 0 plumbcursor = arcpy.da.InsertCursor(createplumblines, ["[email protected]", "SourceID", "TargetID"]) pour sourcepnt, targetpnt dans les aplombs : arcpy.SetProgressorLabel("Génération de lignes à plomb : {0} fonctionnalités complètes".format(str(plnum))) plumbarray = arcpy.Array([arcpy.Point(sourcepnt.x, sourcepnt.y), arcpy.Point(targetpnt.x, targetpnt.y)]) plumbline = arcpy. Polyline(plumbarray) plumbcursor.insertRow((plombline, sourcepnt.ID, targetpnt.ID)) plnum += 1 del plumbcursor # Terminé ! arcpy.ResetProgressor()

Faites-moi savoir si vous rencontrez des problèmes lors de l'exécution du script. Cela fonctionne pour les comparaisons de géométrie point à point. Un exercice plus difficile consiste à écrire un algorithme pour comparer les types de géométrie supérieurs les uns aux autres.

Bonne chance!


Voir la vidéo: Pisteen etäisyys suorasta