Saat ini saya bekerja di bidang isochrones dan algoritma yang mendasarinya. Apa yang sekarang menyebabkan masalah bukanlah perhitungan jika isochrone itu sendiri, tetapi visualisasi hasilnya.
Hasil algoritma isochrone saya adalah titik dan ujung. Sebenarnya saya punya solusi yang berfungsi, tetapi untuk 3873 edge dan 1529 node sepertinya butuh waktu lama (sekitar 2,0 detik pada laptop Lenovo T440s saya yang berisi CPU Core i7 2015 dan SSD yang cukup cepat). Alih-alih detik saya ingin sesuatu yang lebih seperti msec :-).
Mungkin seseorang dapat membantu saya mengurangi waktu perhitungan yang dibutuhkan untuk membangun poligon yang memvisualisasikan area yang dapat dijangkau.
Tapi tunggu ... hal pertama yang pertama!
Berikut adalah visualisasi tepi yang saya adalah hasil perhitungan isochrone saya:
Tepi ini disimpan dalam tabel database PostGIS dan merupakan linestrings sederhana.
Apa yang ingin saya perlihatkan kepada pengguna terlihat seperti ini: Perhatikan area yang terputus di bagian paling selatan dan paling timur gambar. Ini harus digambar sebagai area terpisah (jadi tidak boleh ada penggabungan di sini :-))
Saat ini saya menggunakan permintaan ini:
SELECT ST_AsGeoJson(St_Transform(ST_Multi(ST_Collect(polygons)), 4326)) AS coverage FROM (
SELECT ST_MakePolygon(ST_ExteriorRing(ST_GeometryN(segments, generate_series(1, ST_NumGeometries(segments))))) AS polygons FROM (
SELECT ST_Union(ST_Buffer("GEOMETRY", 20, 'quad_segs=2')) AS segments FROM my_edges AS a
) AS b
) AS c
Saya sudah melakukan beberapa percobaan dan saya juga membaca banyak dokumentasi, tetapi saya tidak dapat menemukan solusi yang lebih baik.
Di mata saya masalah besar adalah penggunaan ST_Union (seperti yang dinyatakan dalam dokumen fungsi ini bisa lambat). Hal yang sangat menarik adalah bahwa menggantinya dengan ST_Collect tampaknya memperlambat perhitungan ST_Buffer sehingga semua-dalam-semua permintaan berikut bahkan lebih lama, meskipun tidak mengisi area di antara tepi (hanya membuat buffer di sekitar garis ):
SELECT ST_AsGeoJson(St_Transform(ST_Multi(ST_Collect(polygons)), 4326)) AS coverage FROM (
SELECT ST_Buffer(ST_Collect(ST_LineMerge("GEOMETRY")), 20, 'quad_segs=2') AS polygons FROM my_edges AS a
) AS b
Ini membutuhkan sekitar 3,8 detik di sistem saya (jadi hampir dua kali lipat waktu). Kesimpulan pertama saya dari tolok ukur kecil ini adalah bahwa ST_Buffer tiba-tiba lambat ketika menyangkut MultiLineStrings (bahkan lebih lambat daripada saat membuat buffer untuk setiap baris dan menggabungkan buffer - yang menurut saya aneh)
Saya juga mencoba menggunakan alpha-bentuk (menggunakan implementasi dari pgRouting), tetapi karena tidak ada nilai alpha untuk mengatur (dan sebenarnya saya tidak akan benar-benar sekarang ke nilai yang mengatur nilai seperti itu) Saya hanya mendapatkan satu poligon hebat ( jadi saya akan kehilangan daerah di bagian paling selatan dan timur sebagai wilayah terpisah yang bukan yang saya inginkan).
ST_Polygonize (yang merupakan hal pertama yang muncul di pikiran saya) tidak menghasilkan hasil yang dapat digunakan, tapi mungkin saya melewatkan sesuatu di sini ...
Apakah ada cara yang lebih baik untuk membuat area yang diperlihatkan di PostGIS? Mungkin juga dengan menggunakan kode java (jts) atau kode javascript sisi klien (jsts)? Sebenarnya saya bisa hidup dengan kehilangan beberapa detail selama area yang ditunjukkan dalam hasil saya tetap terpisah dan perhitungannya menjadi (jauh) lebih cepat.
sumber
Jawaban:
Menyingkirkan serialisasi GeoJSON, yang berikut ini memakan waktu sekitar 6,3 detik pada laptop saya:
Melihat data di OpenJUMP, saya perhatikan sedikit detail di segmen jalan, relatif terhadap tingkat detail yang diinginkan dalam output. Tampaknya bahkan penyederhanaan on-the-fly dari baris-baris ini dapat menghasilkan percepatan besar di PostGIS:
yang membawa segalanya ke 2,3 detik. Saya pikir saya mungkin bisa melakukan lebih baik dengan menyimpan geometri umum dalam kolom terpisah, daripada menghitungnya dengan cepat, tetapi itu sebenarnya tidak memberikan manfaat tambahan.
Tergantung pada seberapa banyak kode yang ingin Anda tulis, Anda hampir dapat dipastikan melakukan yang lebih baik di Jawa, jika tidak ada yang lain karena Anda dapat memanfaatkan banyak inti. (Untuk apa nilainya, JTS melakukan operasi di atas dalam 2,8 detik). Salah satu pendekatan mungkin untuk memperluas
CascadedPolygonUnion
untuk membuat beberapa operasi serikat terjadi secara paralel. (pembaruan - di sini adalah ParallelCascadedPolygonUnion )Saya perhatikan dalam data sampel bahwa ujung-ujungnya disimpan dengan referensi ke titik awal dan akhir, yaitu, Anda memiliki grafik yang dibuat sebelumnya. Saya menduga Anda dapat menghasilkan poligon ini jauh lebih cepat jika Anda bekerja dari grafik daripada menggunakan operasi geometri generik. Misalnya, saya pikir Anda dapat melakukannya seperti ini:
sumber
ST_ClusterIntersecting
tetapi saya pikir Anda akan menginginkan segala jenis pemrosesan grafik terjadi di luar basis data, jadi ini mungkin tidak berguna).