Menghitung orientasi setiap sisi poligon menggunakan ArcPy?


9

Saya ingin memeriksa orientasi setiap baris dalam poligon sehingga saya dapat menghitung paparan matahari mereka. Setiap poligon mewakili bangunan, dan memiliki tinggi terkait. Untuk saat ini, saya hanya ingin mempertimbangkan orientasinya, dan nantinya akan mempertimbangkan masalah naungan.

Satu pendekatan yang saya pikir adalah untuk membagi poligon menjadi garis-garis, dan untuk menghitung orientasi setiap garis, tetapi kesulitannya adalah saya kemudian harus mengidentifikasi wajah luar garis itu. Meskipun sebagian besar poligon adalah angka empat sisi sederhana dengan garis lurus, ada sejumlah kecil di mana ini tidak terjadi (masalah yang saya hanya ingin mempertimbangkan, tetapi belum harus menyelesaikan).

Saya terbiasa dengan python dan berencana melakukan ini semua dari sebuah skrip.


1
Apakah jawaban untuk pertanyaan ini membantu: gis.stackexchange.com/questions/1886/…
Sean

@Sean - terima kasih, ya itu memang membantu secara umum. Saya tidak terbiasa dengan perintah ArcGIS spesifik yang dapat digunakan untuk melakukan ini. Juga, masalah mengetahui apa sisi dalam / luar garis dalam poligon masih ada.
djq

Ketika Anda mengatakan 'orientasi', Anda belum mendefinisikannya dengan cukup baik untuk saya --- apa orientasi segi enam yang sempurna, misalnya?
Dan S.

@Dan S. Saya baru saja mengedit jawaban saya untuk memasukkan orientasi setiap baris dalam poligon.
djq

penjawab maaf - Saya tidak berhasil menetapkan karunia dengan benar kemarin.
djq

Jawaban:


6

Jika Anda hanya menginginkan orientasi mayoritas, periksa jawaban @Mapperz di atas.

Jika tidak, seperti yang Anda katakan, Anda dapat membagi poligon menjadi garis-garis menggunakan alat Polygon To Line . Ini menambahkan bidang FID kiri dan kanan, di mana bidangnya -1 jika tidak ada poligon luar - ini dapat menyebabkan sedikit penyedotan tentang jika bangunan Anda berdekatan atau tumpang tindih.

Dari sana Anda dapat membagi garis di setiap titik (mungkin menggunakan Split menjadi garis-garis COGO ), dan kemudian menghitung sudut pada setiap garis (berpotensi dengan Memperbarui atribut COGO ).

Dengan asumsi Anda memiliki bidang sudut Anda dihitung dari Utara aspek akan benar di mana left_FID adalah -1, dan untuk mendapatkan aspek ketika right_FID adalah -1 cukup tambahkan 180 °. Kemudian berdasarkan FID asli yang dapat Anda himpun, dapatkan aspek mayoritas berdasarkan panjang, dll.

Alat Polygon to line bisa skrip, (sejauh yang saya tahu) alat COGO tidak, jadi Anda harus membuat sendiri sesuatu di sana.

Semoga ini membantu!


2
Steker yang tidak tahu malu, dan komentar: Pertama, jika Anda tidak memiliki lisensi Info, code.google.com/p/boundary-generator melakukan hal yang kurang lebih sama dengan alat Polygon to Line. Kedua - ini memberi Anda lebih banyak informasi daripada hanya melihat semacam orientasi umum poligon keseluruhan ... misalnya Anda dapat menggunakan tabel yang dihasilkan untuk melakukan perhitungan paparan sinar matahari yang jauh lebih tepat, dengan mempertimbangkan setiap aspek dinding masing-masing .
Dan S.


5

Menemukan orientasi

Dalam skrip, poligon akan tersedia sebagai satu set cincin - satu cincin luar dan nol atau lebih cincin dalam - dengan masing-masing cincin diwakili oleh tuple vektor yang dipesan secara siklikal (v [0], v 1 , ... , v [m-1], v [m] = v [0]). Setiap vektor memberikan koordinat suatu simpul (tanpa ada dua simpul yang berturutan bertepatan). Dari sini mudah, seperti yang telah ditunjukkan orang lain, untuk mendapatkan vektor normal (yaitu, vektor tegak lurus terhadap arah tepi):

n [i] = t (v [i + 1] - v [i]).

Operasi "t" memutar vektor 90 derajat berlawanan arah jarum jam :

t ((x, y)) = (y, -x).

Hanya arah dari vektor normal ini yang penting, jadi skala ulang mereka untuk memiliki panjang satuan: vektor (x, y) diubah menjadi (x / s, y / s) di mana s = Sqrt (x ^ 2 + y ^ 2) (yang adalah panjang dari tepi yang sesuai). Mulai sekarang, mari kita asumsikan ini telah dilakukan. Tulis komponen-komponen dari vektor normal satuan yang dihasilkan sebagai

n [i] = (u [i], v [i]), i = 0, 1, ..., m-1.

Mendiskriminasi dari luar dari dalam

Seperti yang Anda katakan, ini meninggalkan ambiguitas terarah: haruskah kita menggunakan n [i] atau -n [i]? Yang mana yang menunjuk keluar? Pertanyaan ini setara dengan menemukan tingkat dari peta Gauss . Untuk menghitungnya, Anda perlu menjumlahkan sudut dengan mana arah normal berubah saat Anda berbaris di sekitar cincin. Karena vektor normal memiliki panjang satuan, cosinus sudut antara dua tepi berturut-turut adalah

Cos (q_i) = n [i]. n [i + 1] = u [i] * u [i + 1] + v [i] * v [i + 1], i = 0, 1, ..., m-1.

(Tentukan n [m] = n [0].)

Sinus sudut antara dua sisi yang berurutan adalah

Dosa (q_i) = n [i]. t (n [i + 1]) = u [i] * v [i + 1] - v [i] * u [i + 1].

(Perhatikan bahwa perhitungan ini hanya memerlukan penjumlahan, perbedaan, dan produk sejauh ini.) Menerapkan fungsi tangen terbalik utama (ATan2) untuk pasangan (cosinus, sinus) tersebut memberikan sudut q_i antara -180 dan 180 derajat. Menjumlahkan sudut-sudut ini untuk i = 0, 1, ..., n-1 menghasilkan (hingga kesalahan floating point) total kelengkungan cincin, yang harus kelipatan 360 derajat; untuk cincin non-self-berpotongan tertutup itu akan menjadi +360 atau -360. Dalam kasus pertama derajatnya adalah 1 dan dalam kasus kedua derajatnya adalah -1. Normalnya semua berorientasi ke luar ketika tingkat cincin luar adalah +1 dan derajat cincin dalam adalah -1. Ubah orientasi mereka cincin demi cincin, sesuai kebutuhan, sesuai dengan aturan ini. Yaitu, jika derajat cincin apa pun adalah kebalikan dari yang diperlukan, meniadakan semua normal untuk cincin itu. Sekarang Anda dapat melanjutkan dengan perhitungan insolation Anda.


Terima kasih atas jawaban yang sangat komprehensif. Ketika Anda berkata, 'Dalam skrip, poligon akan tersedia sebagai serangkaian cincin' bagaimana poligon tersedia? Meskipun akrab dengan beberapa skrip python saya tidak tahu bagaimana menafsirkan poligon dengan cara ini. Saya membaca ini perlahan-lahan dan berusaha memahaminya, tetapi saya mengalami kesulitan menerjemahkan beberapa penjelasan menjadi pseudocode yang dapat saya tulis.
djq

Beberapa catatan tentang jawaban ini: GIS API biasanya akan selalu menyajikan bagian luar poligon dalam urutan berlawanan, IIRC, yang berarti Anda tidak harus melakukan itu dengan suka membedakan di luar dari dalam - cukup gunakan rotasi searah jarum jam pada cincin luar dan berlawanan arah jarum jam pada lubang. Klarifikasi untuk celenius: bit 'set of rings' adalah bagaimana sebagian besar API, termasuk python ArcGIS, memungkinkan Anda untuk menguraikan poligon menjadi segmen garis penyusunnya - sebuah cincin adalah kurva tertutup dari mereka. Karena poligon dapat mendukung pulau dan lubang, Anda dapat memiliki beberapa cincin ...
Dan S.

@Dan saya berharap itu adalah kasus bahwa GIS mempertahankan representasi yang konsisten. Selama bertahun-tahun, perangkat lunak ESRI berfluktuasi bolak-balik di antara poligon yang berorientasi negatif dan positif dan hanya membiarkannya tidak berorientasi. Pada titik ini saya tidak yakin saya akan mengandalkan pernyataan yang didokumentasikan mengenai pendekatan mereka saat ini: Saya akan berhati-hati. Biayanya kecil untuk memeriksa orientasi setelah Anda memproses semua sisi dalam sebuah cincin.
Whuber

.. yah, saya memang meletakkan disclaimer IIRC kecil itu, untungnya. ;) Tidak semua yang sering saya lakukan hal-hal tingkat-geometri pada tumpukan ESRI lagi.
Dan S.

@Dan S. - Saya masih sedikit tidak jelas tentang bagaimana ini dapat diprogram dengan python. Apakah ada pedoman untuk ini?
djq

1

Bisakah ini membantu?


Itu kertas menarik yang Anda gali. Namun, tidak ada metode yang dijelaskan ada yang relevan dengan perhitungan paparan matahari (kecuali perhitungan dimaksudkan untuk perkiraan kasar, yang tampaknya tidak terjadi di sini).
whuber

1

/ * Mungkin ini membantu:

Azimuth - pi / 2 adalah orientasi sisi yang menghadap ke luar dari poligon RHR:

Berikut ini adalah contoh PostGIS, Anda dapat membuat tabel bldg117862 menggunakan pernyataan di akhir. SRID adalah EPSG 2271 (PA StatePlane North Feet) dan geometrinya adalah Multipolygon. Untuk memvisualisasikan di ArcGIS 10, rekatkan kueri / subqueries ke dalam koneksi Query Layer ke postgis setelah membuat tabel bldg117862. * /

- === MULAI QUERY ===

/ * Kueri luar memberikan orientasi ortogonal luar, dan menciptakan garis ortogonal luar dengan panjang yang sama dengan sisi-sisi dari titik tengah sisi.

Arah menghadap dominan adalah jumlah panjang, dikelompokkan berdasarkan orientasi, dalam urutan menurun * /

SELECT line_id sebagai side_id, panjang, derajat (ortoaz) sebagai orientasi, st_makeline (st_setsrid (st_line_interpolate_point (geom, .5), 2271), st_setsrid (st_makepoint (st_x (st_line_interpolate_point (geom, panjang (+5)) orthoaz))), st_y (st_line_interpolate_point (geom, .5)) + (panjang * (cos (orthoaz)))), 2271)) sebagai geom dari

- subquery luar berikutnya membuat garis dari pasangan titik sisi, menghitung azimuth (ortoaz) ortogonal luar untuk setiap segmen

(PILIH bldg2009gid, line_id, st_length (st_makeline (titik awal, titik akhir)) :: numeric (10,2) panjangnya, azimuth (titik awal, titik akhir), azimuth (titik awal, titik akhir) - pi () / 2 sebagai orthoaz, st_makeline ( titik awal, titik akhir) sebagai geom dari

/ * subquery terdalam - gunakan gener_series () untuk mendekomposisi poligon bangunan menjadi pasangan titik awal / titik akhir sisi - note1 - memaksa tangan kanan untuk memastikan orientasi umum semua sisi poligon note2 - contoh menggunakan multipoligon, untuk poligon geometri () dapat dihapus * /

(SELECT generate_series (1, npoints (exteriorring (geometryn (st_forceRHR (geom), 1)) - 1) sebagai line_id, gid sebagai bldg2009gid, pointn (exteriorring (geometryn (st_forceRHR (geom), 1)), generate_series (1, npoints (exteriorring (geometryn (st_forceRHR (geom), 1))) - 1)) sebagai titik awal, pointn (exteriorring (geometryn (st_forceRHR (geom), 1)), menghasilkan_series (2, npoints (exteriorring (geometryn (st_forceRHR (geom) ), 1))))) sebagai titik akhir dari bldg117862) sebagai t1) sebagai t2

- === AKHIR QUERY ===

- tabel bldg117862 membuat / menyisipkan pernyataan

SET STANDARD_CONFORMING_STRINGS TO ON; SELECT DropGeometryColumn ('', 'bldg117862', 'geom'); DROP TABLE "bldg117862"; MULAI; CREATE TABLE "bldg117862" (gid serial PRIMARY KEY, "motherpin" varchar (14), "taxpin" varchar (14), "status" varchar (15), "area" numeric, "prev_area" numeric, "pct_change" numeric, "picture" varchar (133), "mappage" varchar (6), "sref_gid" int4, "e_address" varchar (19), "a_address" varchar (19), "perim" numeric, "card" int4, "a_addnum" int4, "e_street" varchar (50), "a_street" varchar (50), "e_hsnum" varchar (10)); SELECT AddGeometryColumn ('', 'bldg117862', 'geom', '2271', 'MULTIPOLYGON', 2); 0106000020DF080000010000000103000020DF080000010000000B0000008C721D6C98AC34415E2C5BB9D3E32541AE56DE17BEAC34410613E5A0A0E325411AB6C794AEAC3441BA392FE372E32541C89C38429DAC3441643857628AE325418C299A9095AC3441F66C29B573E32541983F02087EAC34413080AA9F93E325419BAC3C0A86AC3441AC1F3B3DABE32541803A40B974AC3441E8CF3DB9C2E325413E3758C186AC3441D0AAB0E7F7E325410AAAA5429BAC3441BA971217DCE325418C721D6C98AC34415E2C5BB9D3E32541' ); CREATE INDEX "bldg117862_geom_gist" ON "bldg117862" menggunakan inti ("geom" gist_geometry_ops); AKHIR;


0

Dengan asumsi bahwa orientasi segmen garis adalah konstan dalam poligon, Anda dapat menghitung bantalan (heading) dari vektor yang tegak lurus terhadap setiap segmen garis. Saya tidak punya waktu sekarang untuk bash out ke kode tetapi jika Anda perlu matematika, dapat dengan mudah diberikan :-)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.