Apr
29
pgDIJKSTRA 2-way
Filed Under PostGIS | 3 Comments
Dari milis mapserver-id seputar fungsi pgDijkstra untuk routing 2-arah. Udah agak lama juga sih tapi sebenarnya pengen dicoba dulu sebelum diposting di sini. Cuma karena kesibukan yang sangat saat ini, ditumpahkan apa adanya dulu deh ![]()
Sekedar mau menambahkan. pgdijkstra sebenarnya bisa dipakai untuk perhitungan jalan searah.
Caranya field cost dan reverse_cost keduanya diisi.
Untuk arah yang tidak bisa dilalui diberi nilai yang besar, mis. ditambahkan 1000000.
Untuk jelasnya bisa baca di sini
Tutorial dalam link di atas menggunakan pgRouting, tapi cara yang sama bisa diterapkan pada pgdijkstra. Saya sendiri sudah mencoba cara ini pada pgdijkstra. Cuma untuk display pathnya, fungsi shortest_path_as_geometry yang ada pada pgdijkstra perlu sedikit dimodifikasi karena fungsi yang diberikan tidak memperhitungkan reverse_cost untuk menghasilkan pathnya.
Satu hal yg perlu diperhatikan arah arc mengikuti arah digitize. Ini yang agak repot krn adakalanya data jalan tidak di-digitize mengikuti arah jalan sebenarnya. Saya sendiri waktu mau menerapkan jalan 1-arah dg cara di atas, terpaksa mencek arah digitize dari shapefile yang ada. Cukup repot, lebih mudah kalo digitize sendiri datanya mengikuti arah jalan yg benar.
Menyambung posting saya sebelumnya, berikut saya kirimkan fungsi PL/pgSQL untuk menampilkan shortest path dg memperhitungkan reverse_cost. Fungsi-fungsi ini dimodifikasi dari modul pgDijkstra dari Sylvain Pasche. Untuk menampilkan shortest path dg memperhitungkan reverse_cost digunakan fungsi shortest_path_as_geometry_dir(). Penggunaannya sama persis dengan fungsi shortest_path_as_geometry() yang asli (lihat README_dijkstra_pgsq.txt dari paket modul pgDijkstra). Fungsi shortest_path_as_geometry_dir() memanggil fungsi shortest_path_as_geometry_internal_id_dir(), yg merupakan modifikasi dari shortest_path_as_geometry_internal_id(). Di fungsi inilah letak perbedaannya. Dalam fungsi shortest_path_as_geometry_internal_id_dir() fungsi shortest_path(sql text, source_id integer, target_id integer, directed boolean, has_reverse_cost boolean) dipanggil dg argumen directed = true dan has_reverse_cost = true.
Saya rasa cukup penjelasannya. Selanjutnya bisa lihat langsung kedua fungsi di bawah.
Selamat mencoba.
Thanks,
Ardi
-- Function: shortest_path_as_geometry_dir(geom_table “varchar”, geom_source anyelement, geom_target anyelement) CREATE OR REPLACE FUNCTION shortest_path_as_geometry_dir(geom_table “VARCHAR”, geom_source anyelement, geom_target anyelement) RETURNS SETOF geoms AS $BODY$ DECLARE r RECORD; source int4; target int4; path_result RECORD; v_id INTEGER; e_id INTEGER; geom geoms; BEGIN FOR r IN EXECUTE ‘SELECT id FROM ‘ || quote_ident(geom_table) || ‘_vertices WHERE geom_id = ‘ || quote_literal(geom_source) LOOP source = r.id; END LOOP; IF source IS NULL THEN RAISE EXCEPTION ‘Can”t find source edge’; END IF; FOR r IN EXECUTE ‘SELECT id FROM ‘ || quote_ident(geom_table) || ‘_vertices WHERE geom_id = ‘ || quote_literal(geom_target) LOOP target = r.id; END LOOP; IF target IS NULL THEN RAISE EXCEPTION ‘Can”t find target edge’; END IF; FOR geom IN SELECT * FROM shortest_path_as_geometry_internal_id_dir(geom_table, source, target) LOOP RETURN NEXT geom; END LOOP; RETURN; END; $BODY$ LANGUAGE ‘plpgsql’ VOLATILE STRICT; ALTER FUNCTION shortest_path_as_geometry_dir(geom_table “VARCHAR”, geom_source anyelement, geom_target anyelement) OWNER TO postgres;
-- Function: shortest_path_as_geometry_internal_id_dir(geom_table “varchar”, source int4, target int4) CREATE OR REPLACE FUNCTION shortest_path_as_geometry_internal_id_dir(geom_table “VARCHAR”, source int4, target int4) RETURNS SETOF geoms AS $BODY$ DECLARE r RECORD; path_result RECORD; v_id INTEGER; e_id INTEGER; geom geoms; BEGIN FOR path_result IN EXECUTE ‘SELECT vertex_id, edge_id FROM shortest_path(”SELECT id, source, target, cost, reverse_cost FROM ‘ || quote_ident(geom_table) || ‘_edges ”, ‘ || quote_literal(source) || ‘ , ‘ || quote_literal(target) || ‘ , TRUE, TRUE) ‘ LOOP v_id = path_result.vertex_id; e_id = path_result.edge_id; FOR r IN EXECUTE ‘SELECT gid, the_geom FROM ‘ || quote_ident(geom_table) || ‘ WHERE edge_id = ‘ || quote_literal(e_id) LOOP geom.gid := r.gid; geom.the_geom := r.the_geom; RETURN NEXT geom; END LOOP; END LOOP; RETURN; END; $BODY$ LANGUAGE ‘plpgsql’ VOLATILE STRICT; ALTER FUNCTION shortest_path_as_geometry_internal_id_dir(geom_table “VARCHAR”, source int4, target int4) OWNER TO postgres;
Apr
1
Google emang betol-betol gila. Tengok aja Google Apps-nya. Coba dan coba, akhirnya jadilah implementasi Google Apps dengan domain LontongCorp.com ini. Gak perlu yang premium, yang gratisan aja. Agak-agak telat mungkin ya aku nyobain nya, tapi daripada gak pernah sama sekali ![]()
Fasilitasnya keren banget deh pokoknya
Yang paling menarik tentu saja layanan emailnya. Untuk yang versi gratisannya aja disediakan 100 user dengan domain kita (eg. @lontongcorp.com) dengan kapasitas masing-masing 2GB. jadi klo kita total aja bila pemakaian max hampir 200GB. padahal harga 1 hdd segitu berapa coba???
Menariknya lagi, mail aliasnya unlimited (??? — blom nyobain max-nya berapa, red). Jadilah enak klo mo maintain2 milis yang kadang bikin sakit kepala dengan banyak filter di account email. klo mo nyobain boleh2 aja. Buka http://mail.lontongcorp.com terus isi dengan
Username : test
Password : testdemo
Mo di spam, mo diapain kek terserah. lha ke gmail ini kok
huehehehe…
Udah lengkap lagi ganti logo google dengan logo sendiri ![]()

Trus fasilitasnya yang redirect URL tadi. tinggal setting di dns, jadi lah sub untuk domain kita di-CNAME ke google apps. Misalkan ya itu tadi, mail.lontongcorp.com. Trus webpage bisa kita arahin ke www, fasilitas calendar ke sub domain calendar. Juga yang gak kalah menariknya lagi, fasilitas document management-nya. Test aja pake user tadi trus arahin ke http://docs.lontongcorp.com. Kalau menurut dokumentasinya sih, gak akan ada masalah bila 1 file diedit secara bersamaan karena dengan xml async akan diberitahu kepada user yang ngedit dan tidak akan merubah file aslinya hingga disimpan. Ah, tak betol google ini. Control Panelnya pun cukup menarik dan memudahkan kurasa. Help atau Panduannya jangan tanya lagi. Komplit, brur!
Jadilah aku berpindah dari satu control panel ke control panel yang laen. Pertama ke DNSPark. buat settnig domain. Males setting manual lewat console, jadi cari yang gratisan aja hehe…
Trus ke Qwords buat setting registrasi ns yang mengarah ke DNSPark. Selebihnya tinggal DNSPark - Google Apps aja. Semuanya dilakukan dengan Control Panel dan gratis lagi (dasar sukanya yang gratisan
)
Kalau ngambil istilahnya DNSPark:
Simple Tools Managing Complex Technologies
Apr
1
PostGIS Routing (bag.2)
Filed Under MapServer, PostGIS | 4 Comments
Lanjutan tutorial sebelumnya…..
Ketujuh, mapfile dengan menggunakan fungsi
shortest_path_as_geometry(’nama_table’,source_oid,target_oid):
CONNECTIONTYPE postgis CONNECTION "host=localhost dbname=roads user=routing password=password" DATA "the_geom from ( SELECT gid, the_geom from shortest_path_as_geometry('route', 1, 4552) ) as route using unique gid using srid=-1"
Catatan: untuk menampilkan hasil routingnya, hanya dengan memanggil fungsi shortest_path_as_geometry() dengan parameter nama_tabel (dalam hal ini tabel ‘route’) [koma] source_id sebagai titik awal berangkat routing dilihat pada kolom source_id di tabel ‘route’ dan [koma] target_id sebagai titik akhir atau tujuan routing dilihat pada kolom target_id di tabel ‘route’.
Hasilnya seperti di bawah ini:

Dengan hasil zooming untuk melihat lebih detail rute terpendek yang ditempuh:

Kedelapan,, rangkuman perintah sql yang dapat dibuat menjadi satu bentuk file (misalkan routing_full) setelah postgis, dijkstra dan data sql telah Anda masukkan berisi:
CREATE TABLE route (gid int UNIQUE, source_id int, target_id int, edge_id int) WITH OIDS; SELECT AddGeometryColumn('route', 'the_geom', -1, 'MULTILINESTRING', 2 ); INSERT INTO route (gid, the_geom) (SELECT gid, the_geom FROM jalanbandung); SELECT assign_vertex_id('route', 1); SELECT create_graph_tables('route', 'int4'); SELECT update_cost_from_distance('route');
dan jalankan dengan perintah:
C:\PgSQL > psql -U routing -d roads -f routing_full.sqltunggu dan database routing siap digunakan ![]()
Kesembilan, untuk tampilan yang dinamis, Anda dapat merubah source_id dan target_id pada script .map sesuai dengan masukan dari web. Caranya dapat dilihat pada tutorial sebelumnya
Kesepuluh, Selamat Mencoba.
Apr
1
PostGIS Routing (bag.1)
Filed Under MapServer, PostGIS | 2 Comments
Pernah lihat ato nyoba aplikasi yahoo maps?
Saat kita mencari arah atau jalur terpendek dari satu lokasi ke lokasi lainnya, marker jalan muncul sebagai penunjuk arah jalur terpendek yang harus kita tempuh. Aplikasi ini menggunakan metoda Vertex Simplication dengan menghitung jarak terpendek. Sampai saat ini, untuk menangani datanya dari database postgresql yang kita simpan dipakai diprogram pgDIJKSTRA/pgRouting dari PostLBS. Ini sebenarnya hasil oprekan yang sudah cukup lama dan dilakukan di atas Windows menggunakan fungsi pgDijkstra, PostgreSQL 8.1.0 dan tidak berjalan pada PostgreSQL 8.0. Awalnya sih dari melihat dari dokumen yang dibawa oleh Pak Hadi, aku jadi tertarik kenapa ada error di function PostgreSQL-nya.
Kita coba menggunakan database roads dengan database username routing.
Baiklah, catatan yang pertama dimulai dari:
Pertama, pastikan pada database telah terinstall postgis. Bisa dengan installer yang disediakan pada windows atau sistem operasi lainnya.Untuk melihat apakah sudah terinstall, pada database ada table geometry_columns (registrasi data geometry tiap table) dan spatial_ref_sys sebagai projection table-nya.
*update : Bila menggunakan installer windows v8.2.x sudah terinstall otomatis dan sudah terdapat template postgis. Kita hanya membuat database berdasarkan template ini.
Bila belum terinstall ataupun terbuat templatenya, silahkan lihat postingan sebelumnya. Hanya saja secara default, kepimilikan fungsi dan kedua tabel oleh database postgres. Untuk merubahnya kita lakukan perintah:
C:\PgSQL> psql -U postgres -d roads psql> ALTER TABLE geometry_columns OWNER TO routing; psql> ALTER TABLE spatial_ref_sys OWNER TO routing;
Kedua, masukkan data jalan anda. Misalkan jalanbandung.sql
C:\PgSQL > psql -U routing -d roads -f jalanbandung.sqlCatatan: Pada beberapa type mapserver, dibutuhkan OID table yang mengandung data geometri sedangkan default postgresql 8.1 yang dicoba default-nya without oids. Ubah table Anda memakai OIDS dengan mengedit file SQL Anda pada bagian CREATE TABLE namatable ( ….) WITH OIDS;
Ketiga, masukkan fungsi dijkstra:
C:\PgSQL> psql -U postgres -d roads -f dijkstra.sql C:\PgSQL> psql -U postgres -d roads -f dijkstra_postgis.sql
Catatan: Pada dijkstra.sql aku berhasil menemukan bug kecil terhadap fungsi create_graph_tables nantinya.
Oleh karena itu perlu diedit sedikit pada bagian :
"CREATE OR REPLACE FUNCTION create_graph_tables" // temukan di bagian bawahnya yang bertuliskan: EXECUTE 'CREATE TABLE ' || edges_table || ' (id serial, source int, target int, ' || 'cost float8, reverse_cost float8, UNIQUE (source, target))'; // ubah menjadi EXECUTE 'CREATE TABLE ' || edges_table || ' (id serial, source int, target int, ' || 'cost float8, reverse_cost float8) WITH OIDS';
Catatan: Belum dicoba pada fungsi yang terbaru
Keempat, buat satu table baru sebagai tempat hasil routing kita. Misalkan saja dengan nama table route. Caranya dengan membuat satu file sql baru route.sql dengan tabel isian berasal dari jalanbandung. File route.sql berisi:
CREATE TABLE route (gid int UNIQUE, source_id int, target_id int, edge_id int) WITH OIDS; SELECT AddGeometryColumn('route', 'the_geom', -1, 'MULTILINESTRING', 2 ); INSERT INTO route (gid, the_geom) (SELECT gid, the_geom FROM jalanbandung);
atau bisa dilakukan tanpa membuat file route.sql dengan mengetikkan di konsol pgsql dengan mengetikkan terlebih dulu:
C:\PgSQL> psql -U routing roadsdan untuk mengeksekusi route.sql kita berikan perintah:
C:\PgSQL> psql -U postgres -d roads -f route.sqlCatatan: Tabel ini bertujuan untuk menempatkan data gid dan data geometri dari tabel kita yang sebenarnya identik tanpa mengikutkan informasi dari kolom lain.Kita tidak bereksperimen dengan tabel data melainkan pada tabel route ini. Bisa Anda lihat isi tabel ini terdiri dari kolom: || gid || source_id || target_id || the_geom || dengan source_id, target_id dan edge_id masih kosong. Di sinilah peran fungsi dijkstra yang kita install tadi akan bermain.
Kelima, kolom source_id dan target_id pada tabel route dengan mengetikkan perintah sql:
C:\PgSQL> psql -U routing roads psql> SELECT assign_vertex_id('route', 0.000001);
Script ini akan berjalan tergantung ketelitian verteks yang Anda inginkan (di atas menggunakan 0.000001 satuan) dan besarnya banyaknya data Anda. Semakin teliti (misalnya 0.01 satuan) maka script akan berlangsung semakin lama. Hasilnya akan disimpan pada kolom source_id dan target_id tabel route dengan membuat id dan data geometri pada tabel baru vertices_tmp.
Catatan: Berdasarkan hasil percobaan, prosedur ini hanya bisa dijalankan sekali.Apabila Anda merasa gagal melakukannya (source_id,target_id pada tabel route masih kosong begitu juga tabel vertices_tmp) Anda harus menghapus database Anda dan mengulangi dari awal.Ini disebabkan karena saat melakukan assignment antara tabel route dan vertices_tmp, fungsi mencatat oid tabel vertices_tmp yang pertama kali dibuat. Sedangkan apabila prosedur ini diulangi, oid tabel vertices_tmp tentu saja sudah berubah. Namun bila ada saran dan masukan yang lebih berguna, aku sih sangat berterima kasih ![]()
Keenam, kolom edge_id pada tabel route masih kosong. Isikan dengan mengetikkan perintah sql:
C:\PgSQL> psql -U routing roads psql> SELECT create_graph_tables('route', 'int4'); // Script ini selain mengisi kolom edge_id, // juga akan membuat 2 tabel baru: route_edges dan route_vertices. // Sekarang lihat isi dari tabel route_edges. psql> SELECT * FROM route_edges LIMIT 3;
akan menghasilkan kira-kira seperti ini:
id | source | target | cost | reverse_cost ---+-------+-------+------+-------------- 1 | 1 | 2 | | 2 | 3 | 3 | | 4 | 2 | 2 | | (3 rows)
Untuk mengisi kolom cost sebagai hasil perhitungan besar jarak per path, gunakan perintah sql:
SELECT update_cost_from_distance('route'); SELECT * FROM route_edges LIMIT 3;
akan menghasilkan:
id | source | target | cost | reverse_cost ---+-------+-------+-------------------+-------------- 1 | 1 | 2 | 6857.46585793103 | 2 | 3 | 3 | 37349.9592156392 | 4 | 2 | 2 | 14040.5673116933 | (3 rows)
Bersambung biar gak kepanjangan…
