Spostamento / compensazione delle posizioni dei punti utilizzando ArcPy o ModelBuilder?


10

Ho un numero di livelli CAD non georeferenziati (vedi questa domanda ) con funzionalità di annotazione del testo. Ho creato un modello per convertire il testo in punti, ma dopo aver convertito l'annotazione in una featureclass Punto, vedo che i punti di ancoraggio del testo CAD non coincidono con il centro del testo CAD (che è dove i punti appartengono).

Pertanto, vorrei programmare (usando ArcPy o ModelBuilder) [spostare] una funzione relativa alla sua posizione corrente (delta x, y) usando un valore misurato X, Y che fornirò.

Ciò mi consentirebbe di spostare nuovamente i punti GIS nel punto in cui appartengono, anziché il punto di ancoraggio CAD offset.

Come posso svolgere questo compito?


@PolyGeo ha dato un'ottima risposta usando SHAPE @ XY IN 10.1, ma attualmente sto eseguendo 10.0. Qualche idea 10.0?

Risposte:


17

Questo codice dovrebbe farlo utilizzando il token SHAPE @ XY fornito con arcpy.da.UpdateCursor in ArcGIS 10.1.

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]])

Il modello di codifica utilizzato qui proveniva da ArcPy Café .


Ugh! Mi ci è voluto fino a stamattina per rendermi conto che SHAPE @ XY è disponibile solo in 10.1, e la mia azienda sta ancora usando 10.0. Questa è un'ottima risposta (andando avanti), ma aspetterò e vedrò se qualcuno ha qualche suggerimento per la 10.0. Grazie!
RyanKDalton,

Maggiori informazioni su un processo simile per chiunque legga questo. Ancora 10.1. arcpy.wordpress.com/2013/06/07/disperse-overlapping-points
theJones

Sta davvero impostando i valori ovunque? Mai usato UpdateCursor in quel modo prima. Di solito faccio + = e quindi aggiorno la riga. Altrimenti l'unica cosa che faccio diversamente nella mia versione è che UpdateCursor usa ['SHAPE @ X', 'SHAPE @ Y'] in modo da poter accedere ad essi come riga [0] e riga [1] invece di dover fare la riga [0 ] [0] e riga [0] [1]. Penso che sia solo un po 'più facile da leggere per me.
eseglem,

Sì, questo è un modo valido per aggiornare le righe. In realtà, non avevo mai visto passare un valore in updateRow () fino a qualche settimana fa. In realtà è stato un esempio per l'aggiornamento della geometria.
Paul,

Grazie mille per la tua risposta PolyGeo! In realtà sono rimasto piuttosto colpito dal fatto che il codice ha funzionato senza modifiche. Sto eseguendo ArcGIS Desktop 10.6
Rie Mino

8

Riconosco @ artwork21 per avermi portato alla mia soluzione finale. In realtà ho trovato uno script quasi completo nell'articolo della guida in linea di ArcGIS 10.0 chiamato " Calcola esempi di campi ", elencato nella sottocategoria " Esempi di codice - geometria " e " Per una classe di caratteristiche punto, sposta la coordinata x di ciascun punto di 100 "

Lo script finale che ho usato nello strumento "Calcola campo" di ModelBuilder era:

Espressione:

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

dove ShiftX e ShiftY sono variabili (come parametri) definite nell'area di disegno di ModelBuilder.

Tipo di espressione:

PYTHON_9.3

Blocco di codice:

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

Poiché tutti i modelli funzionano su un set selezionato, dovresti anche essere in grado di crearlo come uno strumento generico che funzionerà insieme ad altri modelli / strumenti in altre sessioni di modelbuilder. Il modello molto semplice che ho creato (come "plug-in" per altri modelli per spostare i valori delle coordinate) è simile al seguente. In questo modo posso controllare il turno in base al set di selezione (come definito in altri modelli):

Modello ShiftXY

Ha funzionato come un incantesimo, grazie a tutti per il vostro contributo!


è possibile spostare la funzione in base al valore all'interno della tabella, memorizzato nella colonna?
Losbaltica,

1
Dovrebbe essere. Basta assegnare i parametri ShiftX e ShiftY alle colonne appropriate.
RyanKDalton,

Sono confuso da quello che stai passando qui come "forma". Potete aiutarmi per favore?
jbchurchill,

"Expression" mostra i parametri che vengono passati nella funzione di blocco di codice chiamata shiftXYCoordinates (). Quindi il primo parametro è! SHAPE !, che è il campo della forma dal livello.
RyanKDalton,

5

È inoltre possibile utilizzare questo script del calcolatore di campo per spostare le posizioni delle funzioni:

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!)

È possibile includere un metodo Calculate Field aggiuntivo all'interno del modello utilizzando la funzione sopra.


Questo è un modo interessante per farlo, in realtà non sapevo che potresti calcolare il campo sul campo della forma. Questo potrebbe effettivamente essere il modo più semplice per farlo se è un offset impostato per tutti i punti. Probabilmente sarebbe più veloce eseguire point.X + = myMoveX e point.Y + = myMoveY invece di dover passare le coordinate X e Y per questo.
eseglem,

5

Ho adattato la soluzione per spostare / spostare i punti in una determinata direzione (angolo) e una data distanza.

Sembra:

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

ed essere chiamato come shiftXYCoordinates (! SHAPE !,! Angle!, 5000), se si dispone di un campo "angolo" per le caratteristiche dei punti (o con una costante ovviamente). L'angolo dovrebbe essere indicato in gradi decimali. 0 si sposterà "su", 90 "a destra" ecc. Li ho ottenuti dopo aver creato le caratteristiche dell'indice della mappa di spoglia e averle convertite in punti.

Assicurati anche di selezionare Nome campo "Forma" prima di eseguire :)

(Soluzione testata in ArcMap 10.0 SP5)


4

Come puoi vedere, è molto più facile in 10.1 quando accedi ai token cursore.

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

2

Funziona con 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.