Können Beschriftungen für überlappende Punkte zu einer Beschriftung zusammengefasst werden?


12

Ich habe Punkte, die Beispielorte darstellen. Oft werden mehrere Proben an demselben Ort genommen: mehrere Punkte mit demselben Ort, aber unterschiedlichen Proben-IDs und anderen Attributen. Ich möchte alle Punkte, die sich zusammen mit einem einzelnen Etikett befinden, mit gestapeltem Text kennzeichnen, in dem alle Beispiel-IDs aller Punkte an diesem Punkt aufgelistet sind.

Ist dies in ArcGIS entweder mit der regulären Beschriftungsengine oder mit Maplex möglich? Ich weiß, dass ich das umgehen könnte, indem ich einen neuen Layer mit allen Beispiel-IDs für jede Position in einem Attributwert erstelle, aber ich möchte vermeiden, neue Daten nur zum Beschriften zu erstellen.

Grundsätzlich möchte ich davon ausgehen:

Bildbeschreibung hier eingeben

Dazu (für den obersten Punkt):

Bildbeschreibung hier eingeben

Ohne manuelle Bearbeitung der Etiketten.


Wie viele Punkte enthält Ihr Datensatz?
Hornbydd

Antworten:


11

Eine Möglichkeit besteht darin, die Ebene zu klonen, Definitionsabfragen zu verwenden und sie separat zu kennzeichnen, wobei für die erste Ebene nur die Beschriftungsposition oben links und für die zweite Ebene die Beschriftungsposition unten links verwendet wird.

Fügen Sie der Ebene eine Ganzzahl vom Typ THEFIELD hinzu und füllen Sie sie mit dem folgenden Ausdruck:

aList=[]
def FirstOrOthers(shp):
 global aList
 key='%s%s' %(round(shp.firstPoint.X,3),round(shp.firstPoint.Y,3))
 if key in aList:
  return 2   
 aList.append(key)
 return 1

Nennen Sie es durch:

FirstOrOthers( !Shape! )

Erstellen Sie eine Kopie des Layers im Inhaltsverzeichnis und wenden Sie die Definitionsabfrage THEFIELD = 1 an.

Wenden Sie die Definitionsabfrage THEFIELD = 2 für die ursprüngliche Ebene an.

Wenden Sie eine andere feste Etikettenposition an

Bildbeschreibung hier eingeben

UPDATE basierend auf Kommentaren zur ursprünglichen Lösung:

Fügen Sie das Feld COORD hinzu und füllen Sie es mit

'%s %s' %(round( !Shape!.firstPoint.X,2),round( !Shape!.firstPoint.Y,2))

Fassen Sie dieses Feld mit first und last for label zusammen. Verbinden Sie diese Tabelle wieder mit dem COORD-Feld. Wählen Sie Datensätze aus, bei denen zuerst <> als letztes angezeigt wird, und verknüpfen Sie das erste und das letzte Etikett in einem neuen Feld mit

'%s\n%s' %(!Sum_Output_4.First_MUID!, !Sum_Output_4.Last_MUID!)

Verwenden Sie Count_COORD und THEFIELD, um zwei "verschiedene Ebenen" und Felder zu definieren, um sie zu kennzeichnen:

Bildbeschreibung hier eingeben

Update Nr. 2 inspiriert von der @ Hornbydd-Lösung:

import arcpy
def FindLabel ([FID],[MUID]):
  f,m=int([FID]),[MUID]
  mxd = arcpy.mapping.MapDocument("CURRENT")
  dFids={}
  dLabels={}
  lyr = arcpy.mapping.ListLayers(mxd,"centres")[0]
  with arcpy.da.SearchCursor(lyr,["FID","SHAPE@","MUID"]) as cursor:
    for row in cursor:
       FD,shp,LABEL=row
       XY='%s %s' %(round(shp.firstPoint.X,2),round( shp.firstPoint.Y,2))
       if f == FD:
         aKey=XY
       try:
          L=dFids[XY]
          L+=[FD]
          dFids[XY]=L
          L=dLabels[XY]
          L=L+'\n'+LABEL
          dLabels[XY]=L
       except:
          dFids[XY]=[FD]
          dLabels[XY]=LABEL
  Labels=dLabels[aKey]
  Fids=dFids[aKey]
  if f == Fids[0]:
    return Labels
  return ""

UPDATE November 2016, hoffentlich zuletzt.

Der folgende Ausdruck, der an 2000 Duplikaten getestet wurde, wirkt wie Charme:

mxd = arcpy.mapping.MapDocument("CURRENT")
lyr = arcpy.mapping.ListLayers(mxd,"centres")[0]
dFids={}
dLabels={}
fidKeys={}
with arcpy.da.SearchCursor(lyr,["FID","SHAPE@","MUID"]) as cursor:
 for FD,shp,LABEL in cursor:
  XY='%s %s' %(round(shp.firstPoint.X,2),round( shp.firstPoint.Y,2))
  fidKeys[FD]=XY
  if XY in dLabels:
   dLabels[XY]+=('\n'+LABEL)
   dFids[XY]+=[FD]
  else:
   dLabels[XY]=LABEL
   dFids[XY]=[FD]

def FindLabel ([FID]):
  f=int([FID])
  aKey=fidKeys[f]
  Fids=dFids[aKey]
  if f == Fids[0]:
    return dLabels[aKey]
  return "

Hey du hast es geknackt! Nett! Ich wusste, dass da draußen jemand verrückt ist! Wie ich erwartet hatte, ist es ein sehr iterativer Prozess, also führen Sie ihn auf einem großen Datensatz aus und die Beschriftungen müssen für immer gezeichnet werden. Ich habe Ihren Codestil durch Erweitern einiger Zeilen optimiert. Ich finde es schwierig, dem Minimalisten auf einer Linie zu folgen.
Hornbydd

1
@Hornbydd danke für die bearbeitungen. Diese Mutter war aufgrund des Kennzeichnungsverhaltens (Motor?) Schwer zu knacken. Alle Funktionsparameter werden als Zeichenfolgen behandelt! Aus diesem Grund hat der erste IF ohne f = int ([FID]) nicht funktioniert. In Bezug auf die Geschwindigkeit würde ich es nie bei einem Satz verwenden, der größer als 50 Punkte ist. Es muss in ein Skript konvertiert werden, das neue Felder auffüllt, indem der Datensatz nur zweimal durchsucht wird: 1) Suchcursor zum Kompilieren beider Wörterbücher, 2) Aktualisierungscursor zum Lesen der Wörterbücher HINWEIS: Die ersten drei Zeilen nach der try-Anweisung sind veraltet, nachdem Lösung I veröffentlicht wurde erkannte, dass sie sicher entfernt werden können.
FelixIP

Zu Ihrer Information: Ich hatte keine Chance, darauf zurückzukommen, aber ich plane, Ihre Lösung in der nächsten Woche oder so zu verbessern. Es gibt auch eine andere Problemumgehung (die, die ich in diesem Fall verwendet habe) ohne Python. Darüber werde ich auch eine Antwort veröffentlichen.
Dan C

Kam über diese Seite auf Geonet. Ich mochte die clevere Verwendung globaler Wörterbücher, dachte dann über diese Fragen und Antworten nach und fügte einen Link dazu hinzu.
Hornbydd

@Hornbydd ja, es ist sehr schlau und detailliert wie alles von Richard und wird einen großen Unterschied zu meiner (unserer) Lösung machen. Man kann weiter verbessern, indem man einige Zeilen entfernt, die die allererste enthalten. Aufgrund der Antwortzeit von OP scheint er das Interesse verloren zu haben, ich
kümmere

4

Unten ist eine Teillösung.

Dies geht in den Advance-Label-Ausdruck ein. Es ist nicht sehr effizient, daher frage ich nach der Anzahl der Punkte in Ihrem Datensatz. Für jede Zeile, die beschriftet wird, werden 2 Wörterbücher erstellt, in ddenen der Schlüssel das XY und der Wert der Text und d2die objectID und das XY sind. Mit dieser Kombination von Wörterbüchern kann ein einzelnes Label zurückgegeben werden, bei dem es sich um eine Verkettung mit Zeilenumbrüchen handelt, in meinem Beispiel um die Verkettung von TARGET_FID. "sj" ist der Ebenenname im Inhaltsverzeichnis.

import arcpy
def FindLabel ( [OBJECTID] ):
  ob = str([OBJECTID])
  mxd = arcpy.mapping.MapDocument("CURRENT")
  d ={}
  d2 = {}
  lyr = arcpy.mapping.ListLayers(mxd,"sj")[0]
  with arcpy.da.SearchCursor(lyr,["OID@","SHAPE@XY","TARGET_FID"]) as cursor:
    for row in cursor:
      objID = str(row[0])
      temp = row[1]
      tup = str(temp[0]) + "," + str(temp[1])
      d2[objID] = tup
      txt = str(row[2])
      if tup in d:
        v = d[tup] 
        v = v + "\n" + txt
        d[tup] = v
      else:
        d[tup] = txt  
  temp = d2[ob]
  return d[temp]

Warum dies eine Teillösung ist, ist, dass dies für jeden Punkt durchgeführt wird. Ich war nicht in der Lage zu überlegen, wie Sie alle anderen gestapelten Punkte deaktivieren würden. Aus diesem Grund denke ich, ist die ultimative Lösung ein Python, der eine neue Ebene von einzelnen Punkten mit einer einzelnen Beschriftung aus dem Punktestapel erstellt.

Unten sehen Sie die Ausgabe von 3 gestapelten Punkten. Sie sehen, dass die Beschriftung für jeden Punkt erstellt wird, da alle an derselben Position vorhanden sind.

Beispiel

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.