Verschieben / Versetzen von Punktpositionen mit ArcPy oder ModelBuilder?

10

Ich habe eine Reihe nicht georeferenzierter CAD-Ebenen (siehe diese Frage ) mit Textanmerkungsfunktionen. Ich habe ein Modell zum Konvertieren des Texts in Punkte erstellt, aber nach dem Konvertieren der Anmerkung in eine Punkt-Feature-Class sehe ich, dass die CAD-Textankerpunkte nicht mit der Mitte des CAD-Textes übereinstimmen (wo die Punkte hingehören).

Daher möchte ich ein Feature programmgesteuert (mit ArcPy oder ModelBuilder) relativ zu seiner aktuellen Position (Delta x, y ) [verschieben] , indem ich einen gemessenen X, Y-Wert verwende, den ich bereitstellen werde.

Auf diese Weise könnte ich die GIS-Punkte anstelle des versetzten CAD-Ankerpunkts wieder dorthin verschieben, wo sie hingehören.

Wie kann ich diese Aufgabe erfüllen?


@PolyGeo hat mit SHAPE @ XY IN 10.1 eine hervorragende Antwort gegeben , aber derzeit verwende ich 10.0. Irgendwelche 10.0 Ideen?

RyanKDalton
quelle

Antworten:

17

Dieser Code sollte dies mit dem SHAPE @ XY-Token tun, das mit arcpy.da.UpdateCursor in ArcGIS 10.1 geliefert wurde.

import arcpy
# Set some variables
fc = r"C:\temp\test.gdb\testFC"
fc2 = r"C:\temp\test.gdb\testFCcopy"
xOffset = 0.001
yOffset = 0.001
# Code to make a copy which will have its coordinates moved (and can be compared with original)
if arcpy.Exists(fc2):
    arcpy.Delete_management(fc2)
arcpy.Copy_management(fc,fc2)
# Perform the move
with arcpy.da.UpdateCursor(fc2, ["SHAPE@XY"]) as cursor:
    for row in cursor:
        cursor.updateRow([[row[0][0] + xOffset,row[0][1] + yOffset]])

Das hier verwendete Codierungsmuster stammt von ArcPy Café .

PolyGeo
quelle
Pfui! Ich habe bis heute Morgen gebraucht, um festzustellen , dass SHAPE @ XY nur in 10.1 verfügbar ist und mein Unternehmen immer noch 10.0 verwendet. Dies ist eine großartige Antwort (in Zukunft), aber ich werde abwarten, ob jemand Vorschläge für 10.0 hat. Vielen Dank!
RyanKDalton
Weitere Informationen zu einem ähnlichen Vorgang für alle, die dies lesen. Immer noch 10.1. arcpy.wordpress.com/2013/06/07/disperse-overlapping-points
theJones
Setzt dies tatsächlich irgendwo die Werte? Ich habe den UpdateCursor noch nie so benutzt. Normalerweise mache ich + = und aktualisiere dann die Zeile. Ansonsten mache ich in meiner Version nur etwas anderes, als dass der UpdateCursor ['SHAPE @ X', 'SHAPE @ Y'] verwendet, sodass Sie als Zeile [0] und Zeile [1] darauf zugreifen können, anstatt die Zeile [0] ausführen zu müssen ] [0] und Zeile [0] [1]. Ich denke, es ist ein bisschen einfacher für mich zu lesen.
Eseglem
Ja, dies ist eine gültige Methode zum Aktualisieren der Zeilen. Eigentlich hatte ich bis vor einigen Wochen noch nie einen in updateRow () übergebenen Wert gesehen. Es war tatsächlich ein Beispiel für die Aktualisierung der Geometrie.
Paul
Vielen Dank für Ihre Antwort PolyGeo! Ich war tatsächlich ziemlich beeindruckt, dass der Code ohne Änderungen funktionierte. Ich verwende ArcGIS Desktop 10.6
Rie Mino
8

Ich verdanke @ artist21, dass er mich zu meiner endgültigen Lösung geführt hat. Im Online-Hilfeartikel von ArcGIS 10.0 mit dem Titel " Feldbeispiele berechnen ", der unter den Unterkategorien " Codebeispiele - Geometrie " und " Verschieben Sie für eine Punkt-Feature-Class die x-Koordinate jedes Punkts um 100 " aufgeführt ist, habe ich tatsächlich ein fast vollständiges Skript gefunden.

Das letzte Skript, das ich im ModelBuilder-Tool "Feld berechnen" verwendet habe, war:

Ausdruck:

shiftXYCoordinates(!SHAPE!,%ShiftX%,%ShiftY%)

Dabei sind ShiftX und ShiftY Variablen (als Parameter), die auf der ModelBuilder-Zeichenfläche definiert sind.

Ausdruckstyp:

PYTHON_9.3

Codeblock:

def shiftXYCoordinates(shape,x_shift,y_shift):
   point = shape.getPart(0)
   point.X += float(x_shift)
   point.Y += float(y_shift)
   return point

Da alle Modelle an einem ausgewählten Satz arbeiten, sollten Sie dies auch als generisches Tool erstellen können, das in Verbindung mit anderen Modellen / Tools in anderen Modelbuilder-Sitzungen funktioniert. Das sehr einfache Modell, das ich erstellt habe (als "Plugin" für andere Modelle zum Verschieben von Koordinatenwerten), sieht folgendermaßen aus. Auf diese Weise kann ich die Verschiebung pro Auswahlsatz steuern (wie in anderen Modellen definiert):

ShiftXY-Modell

Es hat wie ein Zauber funktioniert, ich danke Ihnen allen für Ihre Beiträge!

RyanKDalton
quelle
Ist es möglich, das Feature um den Wert in der Tabelle zu verschieben, der in der Spalte gespeichert ist?
Losbaltica
1
Es sollte sein. Weisen Sie einfach die Parameter ShiftX und ShiftY den entsprechenden Spalten zu.
RyanKDalton
Ich bin verwirrt von dem, was Sie hier als "Form" eingeben. Können Sie mir bitte helfen?
Jbchurchill
Der "Ausdruck" zeigt die Parameter an, die an die Codeblockfunktion shiftXYCoordinates () übergeben werden. Der erste Parameter ist also! SHAPE!, Das Formfeld der Ebene.
RyanKDalton
5

Sie können dieses Feldrechnerskript auch verwenden , um Feature-Positionen zu verschieben:

def XYsetVALUE( shape, X_value, Y_value): 
  myMoveX = 0.001
  myMoveY = 0.001
  point = shape.getPart(0) 
  point.X = X_value + myMoveX
  point.Y = Y_value + myMoveY
  return point 

XYsetVALUE (! SHAPE!,! X_COORD!,! Y_COORD!)

Mit der obigen Funktion können Sie eine zusätzliche Methode zum Berechnen von Feldern in Ihr Modell aufnehmen.

Artwork21
quelle
Das ist eine interessante Möglichkeit, ich wusste nicht, dass Sie das Feld auf dem Formfeld berechnen können. Dies kann tatsächlich der einfachste Weg sein, wenn es sich um einen festgelegten Versatz für alle Punkte handelt. Es wäre wahrscheinlich schneller, point.X + = myMoveX und point.Y + = myMoveY auszuführen, anstatt dafür X- und Y-Koordinaten übergeben zu müssen.
Eseglem
5

Ich habe die Lösung so angepasst, dass Punkte in eine bestimmte Richtung (Winkel) und eine bestimmte Entfernung verschoben / verschoben werden.

Sieht aus wie:

def shiftXYCoordinates(shape,angle,distance):
point = shape.getPart(0)
point.Y += distance * math.cos(math.radians(angle))
point.X += distance * math.sin(math.radians(angle))
return point

und werden wie shiftXYCoordinates (! SHAPE!,! Angle !, 5000) aufgerufen, wenn Sie ein Feld "Winkel" für Ihre Punktmerkmale haben (oder natürlich mit einer Konstanten). Der Winkel sollte in Dezimalgraden angegeben werden. 0 verschiebt sich nach oben, 90 nach rechts usw. Ich habe sie erhalten, nachdem ich Strip-Map-Index-Features erstellt und diese in Punkte konvertiert habe.

Stellen Sie außerdem sicher, dass Sie vor dem Ausführen den Feldnamen „Form“ auswählen :)

(Lösung in ArcMap 10.0 SP5 getestet)

kgl
quelle
4

Wie Sie sehen können, ist es in 10.1 viel einfacher, wenn Sie Zugriff auf Cursortoken erhalten.

import arcpy
# Code to move features in copy of same dataset
fc = r"C:\temp\test.gdb\testFC"
fc2 = r"C:\temp\test.gdb\testFCcopy"
xOffset = 0.001
yOffset = 0.001
if arcpy.Exists(fc2):
    arcpy.Delete_management(fc2)
arcpy.Copy_management(fc, fc2)

shape = arcpy.Describe(fc2).ShapeFieldName

cursor = arcpy.UpdateCursor(fc2)
for row in cursor:    
    point = row.getValue(shape).getPart()
    row.setValue(shape, arcpy.Point(point.X + xOffset, point.Y + yOffset))
    cursor.updateRow(row) 

del point, row, cursor
Paul
quelle
2

Dies funktioniert für 10.0:

# Featureclass here
FC = r'featureclass'

fcount = 0
shapefield = arcpy.Describe(FC).shapeFieldName
featureUpdate = arcpy.UpdateCursor(FC)
for f in featureUpdate:
    # Hard coded shifts but easy enough to set up a lookup function if needed
    sLon = 0.001
    sLat = 0.001
    # Optional but I like to count to see where it is at in the process
    if fcount % 1000 == 0:
        print('Updating feature %s...' %(fcount))
    # Get the original value
    cF = f.getValue(shapefield)
    cPNT = cF.getPart()
    # Create a new point with the shifted value
    sPNT = arcpy.Point(cPNT.X - sLon, cPNT.Y - sLAT)
    # Set the shapefield to the new point and update feature
    f.setValue(shapefield, sPNT)
    featureUpdate.updateRow(f)
    fcount += 1
del featureUpdate
eseglem
quelle