Mengedit Poin Akhir di Polyline menggunakan ArcPy?

8

Saya mencoba untuk membuat alat gertakan titik akhir polyline di Python menggunakan ArcGIS 10. menggunakan kursor pencarian Saya membaca nilai-nilai ke array objek garis (yang berisi id fitur garis, dan dua objek "EndPoint" - pertama dan terakhir - yang berisi koordinat X dan Y masing-masing), lalu proses beberapa interpolasi data dari poin untuk memberikan semua poin nilai yang benar.

Sejauh ini, bagian itu berfungsi dengan sempurna. Namun, ketika saya mencoba untuk kembali dan mengedit shapefile, saya dapat melihat data yang saya ubah, tetapi sepertinya saya tidak dapat mengeditnya.

Berikut adalah kode untuk memperbarui bidang:

# --------------------------
#
# Update the file with the new EPs
#
# --------------------------

# Create update cursor
#
rows = arcpy.UpdateCursor(outputDirectory + "\\" + trails_fc + ".shp")

# Enter for loop for each feature/row
#
i = 0
for row in rows:
    # Create the geometry object
    #
    feat = row.getValue(shapefieldname)

    partnum = 0

    if feat.getPart(partnum)[0].X != allLines[i].startEP.x:
        arcpy.AddMessage("Change: " + str(feat.getPart(partnum)[0].X) + " to " + str(allLines[i].startEP.x) )
        feat.getPart(partnum)[0].X = allLines[i].startEP.x

    rows.updateRow(row)

    arcpy.AddMessage("Now is: " + str(feat.getPart(partnum)[0].X))

    i+=1

Pembacaan saya terdiri dari pernyataan seperti ini:

Ubah: -105.512166832 menjadi -105.699533165 Sekarang adalah: -105.512166832

Untuk beberapa alasan, baris tidak diperbarui. Dan untuk kehidupan saya, saya tidak dapat menemukan tutorial atau instruksi tentang cara mengedit titik tertentu dalam polyline. Saya hanya dapat menemukan cara mengedit titik sebagai bidang dalam titik pembentukan.

Adakah yang punya ide?

Kivak Wolf
sumber
1
Apakah Anda hanya memiliki lisensi ArcView? Jika Anda memiliki ArcEditor / ArcInfo, apa yang ingin Anda capai dengan membangun alat snap Anda sendiri yang tidak dapat dicapai oleh alat geoproses SNAP Arc10 (ArcToolbox> Alat Pengeditan)? ( help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//… )
RyanKDalton
Mungkin ada cara lain, tetapi saya mencoba memahami cara memanipulasi koordinat apakah alat tersebut asli atau tidak. Ini lebih banyak pengalaman daripada untuk fungsionalitas.
Kivak Wolf

Jawaban:

6

Sayangnya, Anda tidak dapat secara langsung menetapkan nilai baru ke geometri fitur yang ada - alih-alih, Anda harus membuat objek geometri baru, dan memperbarui bidang bentuk fitur dengan objek baru itu. Untungnya, objek array memiliki replacemetode. Jadi, alih-alih mencoba langsung memodifikasi koordinat X dari titik di dalam array, Anda perlu:

  • Buat arcpy.Pointobjek baru dengan koordinat yang benar (sepertinya Anda sudah melakukan ini)
  • Dapatkan salinan objek array yang tersimpan di bidang Bentuk baris
  • Gunakan replacemetode untuk mengatur titik yang diinginkan dalam array Anda dengan titik Anda yang dimodifikasi
  • Buat objek Polyline baru dengan array itu
  • Gunakan metode objek baris setValueuntuk memperbarui bidang Shape dengan Polyline baru Anda yang benar
  • Gunakan metode objek kursor updateRowuntuk menyisipkan baris yang diubah ke dalam dataset.

Secara konkret:

for r in cur:
    ary = r.getValue("SHAPE").getPart(0)
    ary.replace(0,correct_point_object) # first arg 0 replaces the first point in the line
    newLine = arcpy.Polyline(ary)
    r.setValue("SHAPE",newLine)
    cur.updateRow(r)

Perhatikan bahwa replacemetode ini mengambil indeks dan nilai. Sayangnya itu tidak menerima mis -1 sebagai indeks ke titik terakhir dalam array. Namun Anda bisa mengatakannya my_array[my_array.count].

Sepertinya Anda mengkomputasi koordinat X di tempat lain dan mengambilnya nanti. Jika ini masalahnya, saya mungkin akan pergi ke seluruh babi dan membuat objek Polyline baru dengan poin yang benar untuk setiap baris saat Anda menghitung koordinat yang benar. Ini kemungkinan akan lebih mudah & bersih. Dengan begitu kode Anda bisa lebih seperti

row_num = 0
    for r in cur:
        r.setValue(shapeField,correct_geometry_list[row_num])
        cur.updateRow(r)
        row_num += 1

Yang, setidaknya bagi saya, sedikit lebih jelas ... tapi itu gaya!

Edit untuk ditambahkan:

Saya tidak bisa memasukkan ini dalam komentar. Tanpa melihat kode Anda, sulit untuk mengatakan di mana kode itu jatuh. Inilah skrip teruji lengkap yang berfungsi untuk saya. Semoga ini bisa dijadikan referensi. Perhatikan bahwa di sini saya menghitung geometri baru langsung dari yang lama, daripada melakukan dua lintasan; itu mungkin atau mungkin tidak mungkin tergantung pada bagaimana Anda melakukan perhitungan posisi snap Anda. Juga kali ini saya membangun array baru berdasarkan yang lama daripada menggunakan replacemetode, jika itu diperlukan.

import arcpy

def offsetPoint(old_point,X_distance,Y_distance):
    """Trivial function to offset a point - replace with what you're
actually doing."""
    new_point = arcpy.Point(old_point.X+X_distance,
                            old_point.Y+Y_distance)
    return new_point

def offsetFirstPointInLine(line_geom,X_distance,Y_distance):
    """Takes a Polyline geometry object and returns a new Polyline with
the first point of the first part offset by the distance given."""
    array = line_geom.getPart(0)
    first_point = array[0]
    new_point = offsetPoint(first_point,X_distance,Y_distance)

    # Build a new array with your new point in the 0th position, and
    # the rest of the points from the old array.
    new_array = arcpy.Array([new_point]+
                            [array.getObject(x) for x in range(1,array.count)])

    # Then make a new Polyline object with that array.
    new_line = arcpy.Polyline(new_array)
    return new_line

fc = r"C:\Users\student\Documents\ArcGIS\Default.gdb\SomeStorms"

cur = arcpy.UpdateCursor(fc)

for r in cur:
    geom = r.getValue("SHAPE")
    r.setValue("SHAPE",offsetFirstPointInLine(geom,-45000,-5000))
    cur.updateRow(r)

del r,cur

Semoga itu membantu menjernihkannya.

ThomM
sumber
Saya punya perasaan tenggelam yang mungkin terjadi. Terima kasih banyak untuk menjelaskan cara melakukannya! Saya pikir saya hanya akan membuat seluruh polyline seperti yang Anda katakan. Dengan begitu saya memiliki kontrol lebih besar atas itu jika saya ingin kembali dan menyesuaikan sesuatu yang lain.
Kivak Wolf
Yah, sayangnya saya tidak berhasil. Sesuatu yang sangat aneh sedang terjadi. Jika saya menggunakan "ary = r.getValue (" SHAPE "). GetPart (0)" dan kemudian segera membuat polyline dari ary dan mengatur nilainya, shapefile terlihat sangat berbeda. Ini seharusnya tidak terjadi, bukan?
Kivak Wolf
Sulit mengatakan apa yang salah sebenarnya; Saya memperbarui jawabannya dengan solusi yang lebih lengkap jika itu membantu. Sebenarnya - sepertinya Anda membuat array, lalu memodifikasi intinya; alih-alih, Anda harus membuat titik baru, lalu memodifikasi array untuk memasukkan titik itu (atau membuat array baru dengan titik seperti di atas).
ThomM
ThomM: Terima kasih atas penjelasan yang diperluas! Saya sangat menghargai itu! Seperti yang saya temukan kemarin, saya membuat arcpy.Array (), arcpy.Point () s, dan menggunakan kelas arcpy.Ployline () dengan benar. Tetapi tampaknya ada bug dalam pemrograman aktual dari konstruktor kelas arcpy.Ployline (). Saya telah mengirimkan laporan bug, tetapi tampaknya konstruktor untuk arcpy.Polyline () adalah 'membuang' atau mengabaikan arcpy.Point () dengan nilai yang sama namun masih unik. Jadi sementara saya pikir masalah saya adalah kurangnya pemahaman tentang cara kerjanya, sepertinya itu adalah bug.
Kivak Wolf