プラットフォームはラズパイ 4B / 4GB、OSはUbuntu 20.04.1 LTS Serverを使ってみます。
PostgreSQLは12.4がインストール済で、データベースも作成済みとします。
インストールや設定等はこの辺をご参照 ください。
2つのファイルを編集してPostgreSQLに接続できるようにしておきます。
sudo nano /etc/postgresql/12/main/postgresql.conf
以下のコメントアウトを外します。
listen_addresses = ‘localhost’
sudo nano /etc/postgresql/12/main/pg_hba.conf
以下の2行をtrustに修正
#local all all peer
local all all trust
#host all all 127.0.0.1/32 md5
host all all 127.0.0.1 / 32 trust
PostgreSQLを再起動
sudo systemctl restart postgresql
PHP 7.4.3 (cli)をインストール
sudo apt install php7 . 4 - cli
php.iniを修正
sudo nano / etc / php / 7.4 / cli / php . ini
コメントアウトを解除
extension=pgsql
pg_xxxなどのコマンド用に以下をインストール
sudo apt install php7 . 4 - pgsql
接続して簡単なクエリーをテスト(テーブルからデータを10個取得)
【/home/postgresql.php】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
$host = "host=127.0.0.1" ;
$port = "port=5432" ;
$dbname = "dbname=<データベース名>" ;
$credentials = "user=<ユーザー名> password=<パスワード>" ;
$db = pg_connect ( "$host $port $dbname $credentials" ) ;
if ( ! $db ) {
echo "Error : Unable to open database\n" ;
} else {
echo "Opened database successfully<br>" ;
//テーブルから10個データを取得してみます
$result = pg_query ( 'SELECT * FROM <テーブル> limit 10' ) ;
if ( ! $result ) {
die ( 'クエリー失敗' . pg_last_error ( ) ) ;
} else {
print ( 'クエリー成功<br>' ) ;
while ( $row = pg_fetch_row ( $result ) ) {
for ( $i = 0 ; $i < count ( $row ) ; $i ++ ) {
print ( $row [ $i ] . "<br>" ) ;
}
}
print ( '以上<br>' ) ;
}
$close_flag = pg_close ( $db ) ;
if ( $close_flag ) {
print ( '切断しました<br>' ) ;
}
}
?>
上記のコードではpg_query関数を使っています。シンプルですがSQLインジェクションの脆弱性があります。
不安な向きは以下のようにpg_query_params関数に変更。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
$host = "host=127.0.0.1" ;
$port = "port=5432" ;
$dbname = "dbname=<データベース名>" ;
$credentials = "user=<ユーザー名> password=<パスワード>" ;
$db = pg_connect ( "$host $port $dbname $credentials" ) ;
if ( ! $db ) {
echo "Error : Unable to open database\n" ;
} else {
echo "Opened database successfully<br>" ;
//テーブルから10個データを取得してみます
$result = pg_query_params ( $db , 'SELECT * FROM <テーブル> limit $1' , array ( 10 ) ) ;
if ( ! $result ) {
die ( 'クエリー失敗' . pg_last_error ( ) ) ;
} else {
print ( 'クエリー成功<br>' ) ;
while ( $row = pg_fetch_row ( $result ) ) {
for ( $i = 0 ; $i < count ( $row ) ; $i ++ ) {
print ( $row [ $i ] . "<br>" ) ;
}
}
print ( '以上<br>' ) ;
}
$close_flag = pg_close ( $db ) ;
if ( $close_flag ) {
print ( '切断しました<br>' ) ;
}
}
?>
簡単にブラウズするには、phpのビルトインサーバーを起動(例えばIPアドレスは192.168.0.34でポートは8000番を使うとして、ドキュメントルートは/homeだとします)
php - S 192.168.0.34 : 8000 - t / home
他PCからアクセス
http://192.168.0.34:8000/postgresql.php
WebGIS みたいなもんにしたらこんな感じです。
最短経路探索 をやっています。
緑の領域はpgRroutingのデータがロードされてる範囲。
ラズパイ4BでデータベースとSQLのみでやるなら、この範囲で端から端までの探索で4~5秒といった感じです。
背景地図は自前のタイルサーバーからとっています。
Leafletを使っていますがライブラリもスタイルシートもローカルに置いています。
このWebアプリはOpenStreetMapのクレジット表示以外は自前で完結しています。
中心座標と半径で範囲を指定して地物検索
ソースとかはまた次回ということで。
Appendix1
WebサーバーにApacheを使ったり、地図配信に自前のタイルサーバーを使う場合などは以下を参照
ラズパイ(Ubuntu 20.04 LTS Server)にOpenStreetMapのタイルサーバーを構築
Appendix2
経路探索したい!場合は以下を参照
ラズパイ(Ubuntu 20.04.1 LTS Server)でpgRoutingを使って経路探索
Appendix3
XMLHttpRequstでPHP(xxx.php)からデータを受け取る
function get_data ( ) {
var param = "" ;
var xhr = new XMLHttpRequest ( ) ;
xhr . open ( 'GET' , 'http://<IPアドレス>/xxx.php' + param , true ) ;
xhr . responseType = 'text' ;
xhr . onload = function ( e ) {
if ( this . status == 200 ) {
var res = this . responseText ;
//alert(res);
}
} ;
xhr . send ( ) ;
}
PHPのPostgreSQLクエリー
nameカラムとジオメトリ型カラム(geom)で緯度・経度・半径を使って地物検索
$ query = "select name,ST_AsText(geom) from <テーブル> where ST_DWithin(geom, ST_GeomFromText('POINT(<経度> <緯度>)',4326), <半径>,true) order by name;" ; $ result = pg_query ( $ query ) ;
Appendix4
Leafletライブラリを使って緯度・経度を取得
イベントはclickやmousemoveを使います。
スタイルシートやJavaScriptライブラリなどLeaflet一式
自前のタイルサーバーを使う場合はIPアドレスをセット
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html style = "height:100%;margin:0;padding:0;" >
<title> Leaflet page with OSM render server selection </title>
<meta charset = "utf-8" >
<link rel = "stylesheet" href = "./css/leaflet.css" />
<script src = "./js/leaflet.js" > </script>
<script src = "./js/leaflet-hash.js" > </script>
<style type = "text/css" >
.leaflet-tile-container { pointer-events: auto; }
</head>
<body style = "height:100%;margin:0;padding:0;" >
<div id = "map" style = "height:100%;z-index:1;" > </div>
<script>
//<![CDATA[
var map = L . map ( 'map' ) . setView ( [ 34.673791 , 135.511708 ] , 5 ) ;
L . tileLayer ( 'http://<IPアドレス>/hot/{z}/{x}/{y}.png' , { maxZoom : 18 , maxNativeZoom : 17 ,
attribution : '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
} ) . addTo ( map ) ;
var hash = L . hash ( map )
//]]>
map . on ( 'click' , function ( e ) {
//クリック位置経緯度取得
lat = e . latlng . lat ;
lng = e . latlng . lng ;
//経緯度表示
alert ( "lat: " + lat + ", lng: " + lng ) ;
} ) ;
</script>
</body>
</html>
OpenStreetMapのタイルサーバーを使う場合は以下のようになります。
L . tileLayer ( 'https://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png' , { maxZoom : 18 , maxNativeZoom : 17 ,
attribution : '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
} ) . addTo ( map ) ;
Appendix5
国交省などから取得したShapeファイルから施設などの地物のデータベースを作成
ラズパイ(Ubuntu 20.04 LTS Server)で空間データベース(大阪編)
Appendix6
Javascriptで簡易距離計算、単位はm
function distance ( lat1 , lng1 , lat2 , lng2 ) {
lat1 * = Math . PI / 180 ;
lng1 * = Math . PI / 180 ;
lat2 * = Math . PI / 180 ;
lng2 * = Math . PI / 180 ;
var temp = 6371 * Math . acos ( Math . cos ( lat1 ) * Math . cos ( lat2 ) * Math . cos ( lng2 - lng1 ) + Math . sin ( lat1 ) * Math . sin ( lat2 ) ) ;
temp * = 1000 ;
return temp ;
}
Appendix7
ローカルにテキストデータを保存する場合はblobを使います。
保存場所はWindowsの場合はユーザーのダウンロードディレクトリー
ChromeとFirefoxで動作確認
function download_data ( data ) {
if ( data != "" ) {
let blob = new Blob ( [ data ] , { type : "text/plan" } ) ;
let link = document . createElement ( 'a' ) ;
link . href = URL . createObjectURL ( blob ) ;
link . download = 'data.txt' ;
link . click ( ) ;
}
}
Leave a Reply