Apakah ada alat ArcPy untuk mengubah ukuran poligon seperti alat Skala toolbar Pengeditan Tingkat Lanjut di ArcMap?

17

Saya menulis skrip python untuk ArcGIS 10.3. Saya tahu tentang Scale toolantarmuka ArcGIS tetapi saya tidak dapat menemukan perintah arcpy tersebut. Itu ada?

Seperti yang Anda lihat pada gambar, Scale toolkarya - karya berbeda dari Buffer tool- itu mengubah bentuk poligon asli. Jadi pertanyaannya adalah:

Bisakah saya menggunakan Scale tool(tersedia dari antarmuka ArcGIS) menggunakan arcpy?

masukkan deskripsi gambar di sini

Tuan Che
sumber
2
Bagaimana dengan buffering dan menghapus poligon lama !? buffer dapat digunakan dengan nilai positif dan negatif!
Farid Cheraghi
Pertanyaannya adalah tentang alat arcpy yang ada, bukan tentang cara mengubah ukuran poligon.
Tn. Che
Judul, pertanyaan, dan komentar Anda tampaknya saling bertentangan. Jika pertanyaan duplikat yang disediakan tidak menjawab pertanyaan Anda, bisakah Anda mengedit pertanyaan Anda untuk memperjelas apa yang Anda cari?
Aaron
1
@ Alat Buffer Mr.Che dapat digunakan dalam skrip python melalui arcpy.Buffer_analysis (...)
Farid Cheraghi
Ini super! Bagaimana saya bisa memperbarui setiap kelas fitur dengan angka dalam tabel daripada skala semua fitur dengan 0,5 misalnya? Terima kasih
user1655130

Jawaban:

27

Saya tidak mengetahui apa pun di arcpy API yang akan melakukan penskalaan untuk Anda, tetapi menulis fungsi untuk melakukannya akan relatif sederhana.

Kode di bawah ini melakukan penskalaan untuk fitur 2D, dan tidak memperhitungkan nilai M atau Z akun:

import arcpy
import math

def scale_geom(geom, scale, reference=None):
    """Returns geom scaled to scale %"""
    if geom is None: return None
    if reference is None:
        # we'll use the centroid if no reference point is given
        reference = geom.centroid

    refgeom = arcpy.PointGeometry(reference)
    newparts = []
    for pind in range(geom.partCount):
        part = geom.getPart(pind)
        newpart = []
        for ptind in range(part.count):
            apnt = part.getObject(ptind)
            if apnt is None:
                # polygon boundaries and holes are all returned in the same part.
                # A null point separates each ring, so just pass it on to
                # preserve the holes.
                newpart.append(apnt)
                continue
            bdist = refgeom.distanceTo(apnt)

            bpnt = arcpy.Point(reference.X + bdist, reference.Y)
            adist = refgeom.distanceTo(bpnt)
            cdist = arcpy.PointGeometry(apnt).distanceTo(bpnt)

            # Law of Cosines, angle of C given lengths of a, b and c
            angle = math.acos((adist**2 + bdist**2 - cdist**2) / (2 * adist * bdist))

            scaledist = bdist * scale

            # If the point is below the reference point then our angle
            # is actually negative
            if apnt.Y < reference.Y: angle = angle * -1

            # Create a new point that is scaledist from the origin 
            # along the x axis. Rotate that point the same amount 
            # as the original then translate it to the reference point
            scalex = scaledist * math.cos(angle) + reference.X
            scaley = scaledist * math.sin(angle) + reference.Y

            newpart.append(arcpy.Point(scalex, scaley))
        newparts.append(newpart)

    return arcpy.Geometry(geom.type, arcpy.Array(newparts), geom.spatialReference)

Anda dapat menyebutnya dengan objek geometri, faktor skala (1 = ukuran yang sama, 0,5 = ukuran setengah, 5 = 5 kali lebih besar, dll.), Dan titik referensi opsional:

scale_geom(some_geom, 1.5)

Gunakan ini bersama dengan kursor untuk skala seluruh kelas fitur, dengan asumsi kelas fitur tujuan sudah ada:

incur = arcpy.da.SearchCursor('some_folder/a_fgdb.gdb/orig_fc', ['OID@','SHAPE@'])
outcur = arcpy.da.InsertCursor('some_folder/a_fgdb.gdb/dest_fc', ['SHAPE@'])

for row in incur:
    # Scale each feature by 0.5 and insert into dest_fc
    outcur.insertRow([scale_geom(row[1], 0.5)])
del incur
del outcur

sunting: inilah contoh menggunakan perkiraan geometri pengujian Anda, untuk 0,5 dan 5 kali: masukkan deskripsi gambar di sini

Juga diuji dengan poligon multi-cincin (lubang)! masukkan deskripsi gambar di sini

Penjelasan, seperti yang diminta:

scale_geommengambil satu poligon dan loop melalui setiap titik, mengukur jarak dari itu ke titik referensi (secara default, centroid dari poligon).
Jarak itu kemudian diskalakan oleh skala yang diberikan untuk membuat titik 'skala' baru.

Penskalaan dilakukan dengan menggambar garis pada dasarnya pada skala panjang dari titik referensi melalui titik asli, dengan ujung garis menjadi titik skala.
Sudut dan benda rotasi ada di sana karena lebih lurus ke depan untuk menghitung posisi ujung garis sepanjang sumbu tunggal dan kemudian memutarnya 'ke tempatnya.'

Genius Jahat
sumber
1
Saya menguji skrip ini dan berfungsi dengan baik. Anda Jenius sialan! =) Terima kasih banyak. Saya akan meninggalkan pertanyaan ini tanpa harapan sehingga lebih banyak orang akan melihatnya di "pertanyaan masa depan".
Tn. Che
1
Saya menemukan bahwa ketika saya mencoba untuk memproses poligon dengan lubang - itu menghasilkan skrip yang sejalan bdist = refgeom.distanceTo(apnt). Bisakah Anda menguji dan memperbaikinya?
Tn. Che
@ Mr.Che Ups, saya lupa bahwa ArcPy mengembalikan semua dering bagian poligon dalam array yang sama. Cincin dipisahkan oleh titik nol. Ini perbaikan yang mudah, silakan lihat hasil edit.
Evil Genius
Halo. Apakah ini mungkin untuk mendapatkan penjelasan kecil tentang cara kerja skrip, saya buruk dalam pengodean, dan tidak mendapatkan semua baris, jadi itu tidak bekerja untuk saya, tolong?
peter
@ Peter Tentu, saya telah menambahkan penjelasan singkat tentang apa yang terjadi. Ini tidak dimaksudkan untuk menjadi skrip yang berdiri sendiri, tetapi sesuatu untuk diintegrasikan ke dalam skrip Anda sendiri. Cuplikan kode bawah menunjukkan contoh cara menggunakannya.
Evil Genius