Di sini kita akan mempertimbangkan metode untuk membagi permukaan bola dari planet yang dihasilkan secara prosedural dengan ubin tidak teratur, dan sebagai konsekuensinya, membagi lautan dan benua menjadi bagian-bagian (sektor) yang terpisah. Kami berasumsi bahwa di permukaan planet ini, struktur area lahan telah ditetapkan menggunakan beberapa SIG dan dimungkinkan untuk mengekspor data vektor ke ESRI shapefile atau langsung ke database PostgreSQL dengan ekstensi
PostGIS . Proses pembuatan sektor dilakukan menggunakan PostGIS.
Lihat tautan ke skrip dengan kode SQL di bagian bawah posting, di sini penjelasannya akan lebih di-jari. Penjelasan ini menyediakan fungsi dasar dari skrip, dan juga mengasumsikan ketersediaan data untuk benua dan sungai planet yang dihasilkan secara prosedural yang diambil dari
forgedmaps.com .
Pilihan ubin yang tidak teratur memungkinkan kita untuk membagi permukaan planet dengan akurat
ke sektor, umumnya tidak mencampur wilayah laut dan daratan di mana saja. Danau dan Laut Pedalaman
kami menganggapnya bagian dari tanah. Kita juga akan melihat bagaimana sungai dapat digunakan sebagai batas alami sektor. Sektor-sektor itu sendiri akan dibangun atas dasar beberapa pembagian dasar bola oleh poligon.
Ketika datang untuk membagi wilayah datar, mereka biasanya menggunakan
diagram Voronoi untuk mendapatkan ubin yang tidak teratur. Menggunakan juga
algoritma Lloyd , kita bisa sampai pada bentuk poligon cembung yang menarik secara visual yang tidak jauh berbeda ukurannya (Centroidal Voronoi tessellation). Inti dari algoritma Lloyd adalah mengulangi konstruksi diagram Voronoi, pada setiap iterasi berikutnya, dengan mengambil pusat-pusat poligon yang diperoleh pada iterasi sebelumnya sebagai titik-titik penghasil.
Kami akan memberlakukan persyaratan tertentu pada pembagian dasar dengan poligon bola:
cembung poligon bola dan penyimpangan mereka tidak terlalu besar dari ukuran rata-rata yang diberikan.
Sektor nama digunakan sebagai pengganti
ubin karena fakta bahwa ubin biasanya memiliki makna dasar, misalnya, sebagai bagian unit kartu ubin permainan strategis, atau sebagai bagian unit dari permukaan tertentu. Di dalam sektor ini ada struktur internal: relief dan berbagai objek geografis di dalamnya. Sektor-sektor, pada gilirannya, juga dapat berfungsi sebagai ubin dasar: membangun grafik kemungkinan transisi antar sektor untuk tujuan ini.
Pembagian dasar bola dan segmen lautan.
PostGIS memiliki fungsi yang
ST_VoronoiPolygons
, yang membangun diagram Voronoi di area persegi. Mari kita lihat bagaimana kita dapat menggunakannya untuk tujuan kita.
Apa yang terjadi jika Anda mencoba menggunakan pendekatan langsung? Proyeksi persegi panjang dari planet ini dapat dikonversi menjadi bujur sangkar dengan koordinat, membuat poligon di sana dan melakukan transformasi koordinat terbalik. Tetapi, persegi panjang yang dibangun dengan cara ini akan direntangkan dalam satu arah, yang tidak diinginkan. Dan, jika Anda mencoba menerapkan algoritma Lloyd, maka persegi panjang yang dekat dengan kutub bola akan secara signifikan lebih kecil di area (di bola) daripada dekat dengan garis khatulistiwa.
Mari kita coba untuk mengadaptasi metode ini dengan menghilangkan kerugian. Titik awal acak dari diagram Voronoi dipilih sehingga mereka didistribusikan secara merata di bola. Dalam proyeksi Mercator, ini berarti bahwa ke kutub mereka harus muncul lebih jarang dengan probabilitas sebanding dengan kosinus lintang. Kami sedang membangun diagram Voronoi dalam poligon “dunia” - ini adalah seluruh proyeksi persegi panjang planet ini atau hanya sebagian saja. Fungsi
ST_VoronoiPolygons
itu sendiri melengkapi persegi panjang menjadi persegi, kita hanya perlu memotong diagram yang dihasilkan sesuai dengan poligon "dunia".
Kami melihat gambar poligon Voronoi yang diperoleh dengan cara yang disesuaikan. Berikut adalah sebagian dari peta planet uji dari ekuator di tepi atas hingga 73 derajat lintang selatan di tepi bawah. (Di sini area tanah sudah tidak ditimbun.)

Seperti yang dapat dilihat pada proyeksi Mercator, poligon biasanya lebih besar ketika mendekati kutub, tetapi mereka akan didistribusikan secara merata di atas bola dalam hal ukuran area. Inilah yang kami butuhkan. Tetapi, juga terlihat bahwa poligon memiliki penyebaran area yang sangat besar dan gambaran keseluruhannya agak tidak sedap dipandang.
Mari kita coba terapkan beberapa iterasi dari algoritma Lloyd. Sebagai poin baru
untuk iterasi selanjutnya dari diagram Voronoi, kita akan memilih pusat dari yang sudah dipangkas
Poligon Voronoi "Dunia". Dan untuk mencegah pengurangan terlalu banyak pada area poligon dekat kutub, kita hanya melakukan sedikit iterasi (3 atau lebih).
Untuk mendapatkan segmen laut, area yang ditempati tidak termasuk dalam tempat pembuangan akhir yang diperoleh. Sebagai hasilnya, poligon kecil dapat dibentuk, yang diinginkan untuk dilampirkan ke yang tetangga. Juga, poligon kecil mungkin berada di dekat perbatasan poligon “dunia”. Kami menghubungkan poligon sedemikian rupa untuk memilih tetangga "terdekat" dan tidak merusak gambaran besar.
Setelah menerapkan algoritma yang dimodifikasi tersebut, kami memperoleh gambar berikut, yang mungkin sudah dapat diterima. Segmen merah pada gambar menunjukkan penggabungan poligon yang diinginkan.

Pemilihan poligon untuk penggabungan dapat dilakukan dengan berbagai cara. Dalam skrip yang disebutkan, 2 metode diterapkan: di perbatasan terpanjang dan di pusat terdekat. Gambar berikut menunjukkan hasil merger dengan cara kedua.

Secara umum, kami telah mencapai apa yang diinginkan dari sektor laut. Daerah mereka kira-kira sama (di bola), dan mereka cembung atau dengan penyimpangan kecil dari cembung.
Fungsi utama untuk menghasilkan sektor laut:
map.makeOceanSectors( world Geometry, avg_vp_areaKM Double Precision, merging_ratio Double Precision, merging_method Int ) RETURNS Void
world
- tempat pelatihan "dunia" yang berfungsi sebagai perbatasan dunia.
avg_vp_areaKM
- area rata-rata (km
2 ) poligon dari mana sektor laut dibuat.
merging_ratio
- bagikan
avg_vp_areaKM
, sehingga jika area sektor kurang dari itu, maka itu akan dilampirkan ke yang tetangga.
merging_method
- metode penggabungan ('1' atau '2').
Sebuah contoh Kami sedang membangun sektor-sektor di TPA “dunia” tertentu dengan luas rata-rata tempat pembuangan akhir 1.000.000 km
2 . Sektor-sektor yang luasnya lebih kecil dari setengah ukuran ini akan bergabung dengan yang lain. Metode penggabungan kedua digunakan - di pusat terdekat.
SELECT * FROM map.makeOceanSectors( ST_GeomFromText( 'POLYGON((-75 -85, 75 -85, 75 85, -75 85, -75 -85))', 4326 ), 1000000, 0.5, 2 );
Segmen dari benua.
Di daratan, Anda dapat memasuki divisi yang lebih menarik, berdasarkan, di satu sisi, pada totalitas poligon dasar kecil, dan di sisi lain, pada benda-benda alami seperti sungai dan daerah aliran sungai. Struktur yang diperoleh sangat mirip dengan peta negara bagian dan provinsi di dalamnya. Yaitu, ini adalah proses
menghasilkan peta politik dunia secara prosedural .
Tidak seperti segmen laut, tonjolan menjadi sepenuhnya opsional.
Belum ada daerah aliran sungai di forgedmaps.com, tetapi sudah ada sungai. Menggunakan sungai dalam skrip membutuhkan representasi mereka dalam
MultiLineString . Mereka memiliki ide ini di shapefile
riversz . Saat mengimpor ke database, Anda dapat segera menyingkirkan kelebihan koordinat z dalam proses ini. Data lain yang diperlukan, yaitu batas-batas wilayah tanah, ada di dalam shapefile
tanah . Setiap area daratan memiliki pengidentifikasi (ID area) bantuan dan dapat terdiri dari benua dan pulau-pulau terdekat, atau hanya pulau-pulau kecil yang berada di dekatnya.
Sebagai contoh, kami memilih ukuran sektor rata-rata 40.000 km
2 dan ukuran rata-rata poligon dasar 5.000 km
2 . Ini adalah ukuran yang cukup besar, dipilih untuk ilustrasi saja. Ukuran yang lebih kecil juga dapat diterima (hingga beberapa m
2 ), tetapi perhatikan waktu perhitungan dan gunakan konfigurasi basis data yang sesuai.
Dalam gambar ini, contoh bagaimana poligon dasar terlihat di dalam area tanah.

Langkah selanjutnya adalah menggabungkan poligon dasar menjadi sektor. Untuk melakukan ini, pilih secara acak dari poligon dasar sebanyak sektor yang ingin kita buat dan secara bertahap menempelkan poligon tetangga ke sektor yang terakumulasi.

Sekarang saatnya untuk memperhitungkan sungai. Kami menggunakannya untuk membagi sektor menjadi
pisahkan bagian dengan fungsi
ST_Split
. Pembagian seperti itu dapat dilakukan tergantung pada beberapa kondisi: aliran sungai akhir atau area bagian yang terpisah.
Sekarang kita bisa melihat bagaimana beberapa perbatasan melewati sungai.

Kami menghubungkan sebagian kecil sektor ke sektor besar. Tetapi kita harus berusaha
Jangan pasang bagian ke sektor yang sama dengan tempat mereka terputus.

Dengan lahan yang luas kami kelola, tetapi masih pulau-pulau kecil. Kami menjadikan mereka yang memiliki area yang dekat dengan area rata-rata sektor ini sebagai sektor yang terpisah dengan segera. Tetapi dengan mereka yang wilayahnya jauh lebih kecil dari sektor rata-rata, kami melakukan dua hal.
1. Jika pulau-pulau tersebut terletak relatif jauh dari sektor yang ada, maka kami membuatnya menjadi sektor yang terpisah. “Farness” di sini tergantung pada area rata-rata yang diberikan sektor ini: semakin kecil area ini, semakin besar kemungkinan pulau tersebut akan menjadi sektor yang terpisah.
2. Jika pulau itu dekat dengan sektor lain yang sudah dibuat, maka itu dikombinasikan dengan salah satunya. Yaitu, dengan yang memiliki area terbesar dalam poligon tertentu yang diperoleh menggunakan
ST_Buffer
dari pulau ini.

Di sini empat pulau jatuh ke dalam dua sektor yang berbeda. Jika Anda meningkatkan area sektor rata-rata yang ditetapkan, cepat atau lambat semua pulau akan jatuh ke dalam satu sektor tunggal.
Fungsi utama untuk menghasilkan sektor di darat:
map.makeLandSectors( aid BigInt, avg_vp_areaKM Double Precision, avg_sector_areaKM Double Precision, max_sector_cut_area_ratio Float, pref_min_island_area_ratio Float, min_streamflow Int ) RETURNS Void
aid
- pengidentifikasi plot tanah.
avg_vp_areaKM
- area rata-rata (km
2 ) poligon dasar.
avg_sector_areaKM
- rata-rata area (km
2 ) sektor.
max_sector_cut_area_ratio
- bagian dari
avg_sector_areaKM
, yang menentukan area maksimum yang dapat dipotong oleh sungai.
pref_min_island_area_ratio
- bagian dari
avg_sector_areaKM
, yang menentukan area minimum, yang menjadikan pulau itu segera menjadi sektor yang terpisah.
streamflow
- jika sungai memiliki aliran terakhir setidaknya nilai ini, maka ia berpartisipasi dalam sektor pemotongan.
Pada contoh berikut, menggunakan fungsi akan membuat sektor pada sebidang tanah dengan bantuan = 5. Dalam hal ini, poligon dasar dengan luas rata-rata 5.000 km
2 akan digunakan untuk membuat sektor dengan luas rata-rata 40.000 km
2 . Juga, pada saat yang sama, wilayah maksimum yang terputus oleh sungai adalah 0,125 * 40.000 km
2 , dan 0,25 * 40.000 km
2 adalah area minimum di mana pulau-pulau tersebut segera menjadi sektor. Untuk memotong sektor dengan sungai, sungai dengan limpasan akhir minimum 2 digunakan.
SELECT * FROM map.makeLandSectors(5, 5000, 40000, 0.125, 0.25, 2);
Referensi
Tersedia kode skrip SQL yang mengerjakan semua pekerjaan, termasuk membuat sektor dan membuat grafik transisi antara sektor-sektor yang bertetangga. Data GIS dari planet yang dihasilkan secara prosedural dapat diambil dari
forgedmaps.com . Anda dapat menggunakan
data GIS Earth , mengarahkannya ke struktur serupa. Anda juga dapat, menggunakan
GIS modern , membuat data secara manual dari awal atau memperoleh data baru dengan mengonversi data yang diterima dari sumber lain. Instruksi yang lebih lengkap untuk skrip dapat ditemukan dalam
manual .