Memotret titik awal dan akhir dari garis ke baris lain di PostGIS

9

Ada banyak contoh yang menunjukkan cara mengambil garis ke titik, tapi saya belum bisa menemukan cara (cepat!) Untuk menjepret simpul awal dan akhir dari string baris ke node dari garis lain.

Pada dasarnya saya ingin "membersihkan" lapisan saya di postgis (2.0), memindahkan titik-titik yang hampir sama, dan menjahit celah kecil di antara string garis.

Tidak masalah apakah saya menambahkan node lain, memindahkan node pertama / terakhir dari kedua baris, atau memindahkan kedua titik ke tengah.

Saya telah menemukan dua opsi, tetapi saya tidak yakin bagaimana memulainya dengan keduanya:

Opsi kedua kedengarannya layak, tetapi bantuan apa pun tentang cara mengikuti metode ini akan sangat dihargai.

Jelmer Baas
sumber

Jawaban:

6

Saya sudah berhasil menyelesaikan ini, tanpa menggunakan alat GRASS yang disebutkan atau fungsi topologi.

Pada dasarnya saya mengambil semua start dan endnodes, meletakkannya di tabel sementara yang baru, meletakkan buffer di sekitar mereka, menyatukan objek buffer, dan memindahkan semua node yang ditemukan di setiap buffer ke centroid buffer.

Setelah selesai, saya memindahkan titik awal dan akhir yang asli ke lokasi baru.

Lebih mudah dari yang diharapkan, dan masih cepat, tetapi saya berharap PostGIS memiliki beberapa fungsi bawaan untuk ini - itu akan lebih cepat.

Sunting: untuk kepentingan memberikan kembali kepada komunitas, ini adalah kode saya (cukup jelek) untuk saat ini.

drop table if exists nodes;
drop table if exists nodes2;
drop table if exists buffers;

-- Get Start and End nodes
select ST_StartPoint(wkb_geometry) startnode,  ST_EndPoint(wkb_geometry) endnode,    ogc_fid into nodes  from sourceTable;
-- Combine all nodes into one table for easier queries
select startnode node, ogc_fid into nodes2 from nodes;
insert into nodes2 select endnode node, ogc_fid from nodes;

-- Some indexes to speed everything up
CREATE INDEX nodesstart_idx ON nodes USING gist  (startnode);
CREATE INDEX nodesend_idx ON nodes USING gist  (endnode);
CREATE INDEX nodes2_idx ON nodes2 USING gist  (node);
CREATE INDEX nodes_ogcfid_idx ON nodes USING btree (ogc_fid ASC NULLS LAST);

-- Create buffers, combine them, split combined objects again
select (ST_Dump(ST_Union(ST_Buffer(node, 1)))).geom geom into buffers from nodes2;
CREATE INDEX buffers_idx ON buffers USING gist  (geom);

-- Update start/end nodes table
UPDATE nodes SET startnode = ST_Centroid((select geom from buffers WHERE geom && startnode));
UPDATE nodes SET endnode = ST_Centroid((select geom from buffers WHERE geom && endnode));
-- Update original points
update sourceTable set wkb_geometry = ST_SetPoint(
ST_SetPoint(wkb_geometry, 0, (select startnode from nodes where ogc_fid=sourceTable.ogc_fid)), 
ST_NumPoints(wkb_geometry) - 1, (select endnode from nodes where ogc_fid=sourceTable.ogc_fid));

DROP TABLE nodes;
DROP TABLE nodes2;
DROP TABLE buffers;
Jelmer Baas
sumber
Jawaban ini agak mirip dengan saran "non-topologis" dari jawaban saya. Akan lebih baik jika Anda memberi jawaban atau memilih jawabannya. Itulah yang memberi makan komunitas di sini :)
katahdin 8'13
Kamu benar. Saya telah meningkatkan jawaban Anda, dan akan mengedit respons saya untuk memasukkan kode saya.
Jelmer Baas
4

Berikut ini tiga opsi. Semoga orang akan membantu.

v.clean

Menggunakan alat GRASS di QGIS Anda dapat membersihkan topologi objek spasial. Pengguna @RK memberikan serangkaian instruksi yang baik tentang bagaimana melakukan ini dalam jawaban untuk pertanyaan yang berbeda . Keuntungan yang diberikan GRASS adalah ia akan menyimpulkan topologi shapefile. Kerugian untuk situasi Anda adalah bahwa data Anda tidak ada dalam shapefile. Tentu saja Anda dapat mengekspor data dari Postgres ke shapefile menggunakan alat "Add PostGIS Layer", tapi itu langkah tambahan.

Fungsi PostGIS non-topologis

Di PostGIS Anda dapat menggunakan fungsi ST_EndPoint dan ST_StartPoint untuk mendapatkan titik akhir dan mulai untuk linestring. Kemudian, menggunakan kombinasi ST_DWithi dan ST_Distance , Anda dapat menemukan titik awal atau akhir terdekat pada geometri terdekat. Jika Anda memiliki banyak poin maka ST_DWithin akan mempercepat permintaan banyak - dengan asumsi Anda memiliki indeks di tempat. Dari sana, Anda perlu membuat aturan yang menentukan titik mana yang harus dimodifikasi, dan mana yang diperbaiki.

Keuntungannya di sini adalah Anda tidak perlu mengirim data ke GRASS untuk dibersihkan, tetapi ada beberapa perangkap yang harus diperhatikan.

Fungsi PostGIS topologis

Pertanyaan itu merujuk fungsi topologi PostGIS. Ini berfungsi dengan baik, tetapi, seperti yang dijelaskan oleh wiki , Anda harus secara eksplisit menentukan tepi, simpul dan wajah. Jelas ini akan menjadi masalah untuk set data Anda karena Anda telah mengetahui masalah dengan topologi.

katahdin
sumber
1

PostGIS memiliki fungsi gertakan .. mungkin mereka akan membantu?

ST_Snap: Segmen snap dan simpul geometri input ke simpul geometri referensi.

ST_SnapToGrid: Pasang semua titik geometri input ke kisi biasa.

Jordan Arseno
sumber
1
Terima kasih, saya mengetahui fungsi-fungsi ini. ST_Snap menjepret SEMUA node, saya hanya ingin simpul start dan end. ST_SnapToGrid tidak benar-benar cocok karena memodifikasi semua geometri yang ada, dan memiliki peluang untuk memindahkan node yang berada lebih dekat, karena mereka hampir tidak jatuh ke segmen lain.
Jelmer Baas