2022/05,江端さんの技術メモ

(まとめ)地図DBの作り方

「OpenStreetMapから鉄道路線データを落とせない」と愚痴っていたら、社内の人から「OSMに鉄道データ入っていますよ」と言われて、愕然とした件

ところが、問題は、

/usr/share/osm2pgrouting/mapconfig_for_bicycles.xml(自転車)

/usr/share/osm2pgrouting/mapconfig_for_cars.xml(自動車)

/usr/share/osm2pgrouting/mapconfig_for_pedestrian.xml(歩行者)

の3つしか、準備されておらず、鉄道のテンプレートがありませんでした

本当に鉄道を使ったDBはつくれないのかな? と思い、ちょっと試してみました。

こちらに、mapconfig_for_cars.xml があるので、それを見てみました。

私の場合、芳賀・宇都宮LRT と、一般の道路を交えたダイクストラを実現することが目的でしたが、まずは、(道路のことは忘れて)芳賀・宇都宮LRTの情報だけを取り出すことに注力しました。

で、こんなの(mapconfig_for_train.xml)を作ってみました。

ちなみに、"tram"とは路上電車のことで、要するにLRTのことです。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <tag_name name="railway" id="1">
    <tag_value name="tram"              id="101" priority="1.0" maxspeed="40" />
  </tag_name> 
</configuration>

id="1"> とか、 id="101" priority="1.0" maxspeed="40" /> は、適当に付けました(多分、この辺は適当で良いと思います)。

で、これで何が出てくるかを見ていたのですが、

<tag_name name="railway" id="1">
<tag_value name="tram" id="101" priority="1.0" maxspeed="40" />
</tag_name>
</configuration>

この結果、分かったことは、osmデータの中にある、<tag k="railway" v="tram"/> が含まれている、<way>のタグが取り出されることでした。

<way id="678320671" version="2" timestamp="2021-08-04T10:06:56Z" changeset="0">
		<nd ref="6351482006"/>
		<nd ref="5948014189"/>
		<nd ref="5558816378"/>
		<nd ref="5948014109"/>
		<tag k="bridge" v="yes"/>
		<tag k="railway" v="tram"/>
		<tag k="electrified" v="contact_line"/>
		<tag k="frequency" v="0"/>
		<tag k="gauge" v="1067"/>
		<tag k="maxspeed" v="40"/>
		<tag k="name" v="(仮称)宇都宮ライトレール"/>
		<tag k="railway" v="construction"/>
		<tag k="voltage" v="750"/>
	</way>

 

「OpenStreetMapのデータから鉄道だけを抽出してGeoJSONで出力する方法」を試してみた件

osm.pbfファイルを、osmファイルに変換する方法

で作った、utunomiya-railway-latest.osm を使って、テスト用のDB (test_db)を作っておいて、

osm2pgrouting -f utunomiya-railway-latest.osm -c mapconfig_for_train.xml -d test_db -U postgres

をやってみました(実は、芳賀・宇都宮LRTの情報は、工事中の情報が入っていて、utunomiya-railway-latest.osmには、<tag k="construction" v="tram"/>と記載されていましたので、これを、強制的に<tag k="railway" v="tram"/>に置換しました)。

test_dbをQGISで表示したら、こんな感じで出てきました。

出発点のid = 1 と、

終着点のid = 6 を使って、

ダイクストラ計算を実施してみました。

root@a2b2f7061d88:/tmp# psql -U postgres
psql (12.5 (Debian 12.5-1.pgdg100+1))
Type "help" for help.

postgres=# \c test_db
You are now connected to database "test_db" as user "postgres".
test_db=# SELECT seq, node, edge, cost, agg_cost FROM pgr_dijkstra('SELECT gid as id, source, target,length_m as cost FROM ways',1, 6, false);
 seq | node | edge |        cost        |      agg_cost
-----+------+------+--------------------+--------------------
   1 |    1 |  112 |  968.5677557470831 |                  0
   2 |  105 |    1 |  401.6831070639031 |  968.5677557470831
   3 |    2 |   40 | 1932.1157045557927 | 1370.2508628109863
   4 |   36 |   43 |  91.90138904387848 | 3302.3665673667792
   5 |   39 |   65 | 111.55679510881248 |  3394.267956410658
   6 |   63 |   67 | 159.06195161851494 | 3505.8247515194703
   7 |   65 |   10 | 45.988089536965845 |  3664.886703137985
   8 |    9 |   74 |  25.50249632394143 |  3710.874792674951
   9 |   71 |    8 |  83.08385331794597 | 3736.3772889988927
  10 |    7 |   12 | 27.274859434129702 | 3819.4611423168385
  11 |   10 |   36 |  55.83052462128617 |  3846.736001750968
  12 |   32 |   37 |  48.05528375189372 | 3902.5665263722544
  13 |   33 |    2 |    700.36313814633 |  3950.621810124148
  14 |    3 |   69 | 13.830090594515813 |  4650.984948270478
  15 |   67 |   57 |  269.7483878007764 |  4664.815038864994
  16 |   55 |   13 | 243.90865759717457 |   4934.56342666577
  17 |   11 |   14 |  592.4332460936212 |  5178.472084262944
  18 |   12 |   30 | 197.95743212114834 |  5770.905330356565
  19 |   26 |   44 | 230.11474397115853 |  5968.862762477714
  20 |   40 |   32 |  32.15748444428291 |  6198.977506448872
  21 |   28 |   34 | 128.30514459608628 |  6231.134990893155
  22 |   30 |   46 | 292.51977773825814 |  6359.440135489242
  23 |   42 |   47 |  42.00097102860326 |    6651.9599132275
  24 |   43 |   51 |  317.7487966492082 |  6693.960884256103
  25 |   48 |    3 | 24.366299209335182 |  7011.709680905311
  26 |    4 |    6 |  35.05578311994414 |  7036.075980114646
  27 |   46 |   62 |  269.6784973606185 |   7071.13176323459
  28 |   60 |   71 |  261.6741520558861 |  7340.810260595208
  29 |   69 |   20 | 1312.5430898908662 |  7602.484412651094
  30 |   18 |   72 |  86.31512692490578 |  8915.027502541961
  31 |   70 |    4 |  962.8503750491366 |  9001.342629466868
  32 |    5 |   60 | 131.65329169122384 |  9964.193004516004
  33 |   58 |   59 |  129.1237292961209 | 10095.846296207228
  34 |   57 |   53 |  93.77398873447196 |  10224.97002550335
  35 |   50 |   55 |  200.4322777934951 | 10318.744014237822
  36 |   52 |    7 |  4122.794957245806 | 10519.176292031318
  37 |    6 |   -1 |                  0 | 14641.971249277123
(37 rows)

芳賀・宇都宮LRTの全長は、15kmと聞いていましので、ほぼドンピシャ(14641.971249277123メートル)が算出されていることが分かります。

ただ、現在のnodeの位置は、駅の場所に対応していないので、鉄道情報のosmファイルを手動で作り直す必要はあります(nodeとgeomの変更等)が、その前に、とりあえず今のままの方式で、道路ー鉄道混在のダイクストラができるか、試してみます。

(2時間経過)

こんなのを作って試してみました。

mapconfig_for_cars_tram.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <tag_name name="highway" id="1">
    <tag_value name="motorway"          id="101" priority="1.0" maxspeed="130" />
    <tag_value name="motorway_link"     id="102" priority="1.0" maxspeed="130" />
    <tag_value name="motorway_junction" id="103" priority="1.0" maxspeed="130" />
    <tag_value name="trunk"             id="104" priority="1.05" maxspeed="110" />
    <tag_value name="trunk_link"        id="105" priority="1.05" maxspeed="110" />    
    <tag_value name="primary"           id="106" priority="1.15" maxspeed="90" />
    <tag_value name="primary_link"      id="107" priority="1.15" maxspeed="90" />    
    <tag_value name="secondary"         id="108" priority="1.5" maxspeed="90" />
    <tag_value name="secondary_link"    id="109" priority="1.5" maxspeed="90"/>  
    <tag_value name="tertiary"          id="110" priority="1.75" maxspeed="90" />
    <tag_value name="tertiary_link"     id="111" priority="1.75" maxspeed="90" />  
    <tag_value name="residential"       id="112" priority="2.5" maxspeed="50" />
    <tag_value name="living_street"     id="113" priority="3" maxspeed="20" />
    <tag_value name="service"           id="114" priority="2.5" maxspeed="50" />
    <tag_value name="unclassified"      id="117" priority="3" maxspeed="90"/>
    <tag_value name="road"              id="100" priority="5" maxspeed="50" />
  </tag_name> 
  <tag_name name="railway" id="1">
    <tag_value name="tram"              id="101" priority="1.0" maxspeed="40" />
  </tag_name> 
</configuration>

osm2pgrouting -f utsunomiya.osm -c mapconfig_for_cars_tram.xml -d test_db2 -U postgres

(<tag k="construction" v="tram"/>の<tag k="railway" v="tram"/>の強制置換を忘れずに)

QGISで表示してみたところ、ちゃんとLRTの架橋ができていました。

ただノード接続ができているか不明なので、これから調べてみます(経路が繋がっていないと、ダイクストラ計算はできないはずなので)。駅を手動で作るしかないかな・・・

2022/05,江端さんの技術メモ

pgRoutingのデータベース構成ファイル
/usr/share/osm2pgrouting/mapconfig_for_cars.xml(自動車)
で作った、DBのレコードの意味が混乱してきたので、ちょっと整理

utsu_db=# select * from ways limit 1;
gid | osm_id | tag_id | length | length_m | name | source | target | source_osm | target_osm | cost | reverse_cost | cost_s | reverse_cost_s | rule | one_way | oneway | x1 | y1 | x2 | y2 | maxspeed_forward | maxspeed_backward | priority | the_geom
30797 | 547468496 | 112 | 0.002103460902954004 | 194.17417410447345| | 23363 | 7527 | 5289963314 | 1937141869 | 0.002103460902954004 | 0.002103460902954004 | 13.980540535522088 | 13.980540535522088 | | 0 | UNKNOWN|139.9512784 | 36.5577371 | 139.9532349 | 36.5573415 | 50 | 50 | 2.5 | 0102000020E610000004000000852C66DF707E61400822E6ED6347424033EE17FD727E61403F41182E61474240AD2C76A0737E6140B41D537765474240FD1C7AE6807E61400F9A5DF756474240

sourceとtargetの違いが分からかなったけど、wayの両端の番号、ということで良さそう。

で、今度はnodeの方だけど

utsu_db=# select * from ways_vertices_pgr limit 1;
id | osm_id | eout | lon | lat | cnt | chk | ein | the_geom
----+-----------+------+--------------+-------------+-----+-----+-----+----------------------------------------------------
4 | 264184195 | | 139.95960820 | 36.60870170 | | | | 0101000020E6100000267F411CB57E61408242F3EFE94D4240

が、nodeの情報が書かれているものらしい。

で、ここが重要。

ways_vertices_pgr の"id"  は、waysの"source" または"targetに対応しています。

2022/05,江端さんの忘備録

業務連絡が、転送メールで送られてきます。

Sometimes, business orders come to us by forwarded mail.

普通に、サブジェクトの記載をコピペして、

Many people are support to copy and paste the message of mail subject, like

「今期、明細書執筆予定者への注意点を展開します」

"Please remained to people who plan to write patent application at this quarter"

とだけ記載して転載されてくるメールが多いです。

and they just forward the mail to us.

―― で、これらのメールは、ほとんどの人間にスルーされる、と

"As a result, these mails will be ignored by most readers"

-----

分かります。面倒くさいですからね。

I can understand it, because they are troublesome.

しかも、管理部門のメールは、『悪意でもあるのか』と思えるほど、文面が分かりにくです。

In addition, the mails from management departments are difficult to understand, as if they are malice.

「何をして欲しいのか、さっぱり分からん」という内容です。

The contents are "I don't know at all what on earth do they expect?"

まあ、管理部門の立場としては、そういう文面にならざるを得ないのも分かります。

Well, I might understand that they have to make the contents like that.

恣意的な内容を記載すると、業務内容を誤解されて、後でつっこまれる恐れがあるからです(面倒ごとになる)。

If they try to write the contents on their subjection, it might make the readers trouble.

-----

私も、面倒なので、基本的にはコピペ&スルーをしますが、例外があります。

I also copy, paste and forward the mail to avoid the troublesome, however I have an exception.

『これは、後で、自分に面倒が振りかかってくるな』と直感したものに関してだけは、丁寧に解説をします。

If I feel that "if I do that, another trouble comes to me", I will explain it by my words carefully.

概要を、江端の文言で解説し、該当者をby nameで指定し、締切の日時を強調して記載します。

I am going to write outline of the mail and explain it by my words and indicate the person by name, and emphasize the deadline.

こんな感じです。

As follows

====== メール文面例(ここから) ======

====== Example of the mail (From here) ======

知財部が激怒しています。

The IT department is furious.

『何度説明しても、書式を間違えて提出している』とのことです。

The reason is "we submit the patent application with wrong formats, even they have already had to explain it to us again and again".

本件に関しては、AさんとBさんが、この対象者のようです。

About this mail, I am afraid that Mr.A and Ms.B are objects.

「今月末までに修正を出せ」と言われています。

We have been ordered to re-submit the modification version.

ご希望があれば、私(江端)の方で、ざっくりレビューします

If you hope. I (ebata) will check it roughly.

レビューを希望しない人のことは知りません。その場合は「自力」で知財部と闘って下さい

I don't care people who don't want it. If so, fight the IT department on your own.

江端

Ebata

====== メール文面例(ここまで) ======

====== Example of the mail (To here) ======

まあ、こういう風に書いておけば、ほぼ100%の対応を得られます。

I know that I can get almost 100% responses, if I write the above.

2022/05,江端さんの技術メモ

私が知らないだけなのかもしれませんが(知っている人は教えて欲しいでです)、OpenStreetMapの鉄道のデータは、nodeとwayに変換できません ―― というか、変換する方法を、私には知りません(散々探したんだけど、見つからない)。

#でも、絶対にあると思うんだよなぁ。だって、鉄道と車を融合させる研究、腐るほどあるもん。これらの研究が全部、商用のGISシミュレータ使っているとは思えないんだけどな。

ちなみに私は、PostgreSQL + PostGISを使って、GISのシミュレータを作っています。

で、鉄道を路線の上で走らせたいのですが、鉄道の情報は、進行方向の順番通りには表示してくれません。

ですので、一路線を作る為には、geomをLINESTRINGで、座標単位にバラバラにする必要がありますが、問題は、geomが順番通りに表示れない、ということです。

なので、QGISとかを使って、始点・終点を探して、SQLの結果から、順番を探す、という面倒なことをやらざるを得ません。

QGIS弄っていたら、LINESTRINGの座標を得られる方法をたまたま見つけてしまったので、私の為に記録しておきます。

まず、前提はこの内容です。

「OpenStreetMapのデータから鉄道だけを抽出してGeoJSONで出力する方法」を試してみた件

OpenStreetMapのデータからosmiumを使って鉄道だけを抽出しPostGISに入力する方法(宇都宮周辺の鉄道データを使った例)を試してみた件

まず地物表示のボタンを押します。

次に、LRTの路線の最初の部分をクリックします。

次に、(派生した属性)を右クリックして、「地物をコピー」を選択します。

で、これをエディタなどに、コピペすると

wkt_geom tags
LineString (139.89970149999999194 36.55948450000000349, 139.89955630000000042 36.55885789999999957, 139.8995482999999922 36.55877879999999891, 139.89956340000000523 36.55872629999999646, 139.8996118000000024 36.55866100000000074, 139.89968200000001275 36.55861320000000347, 139.8997737999999913 36.55858750000000157, 139.89987840000000574 36.55857249999999681, 139.90136459999999374 36.55845939999999672, 139.90222030000001041 36.55839509999999848, 139.90252409999999372 36.55837619999999788, 139.90541809999999145 36.55817369999999755, 139.90668009999998844 36.55808119999999661, 139.90870390000000612 36.55791560000000118, 139.90887219999999047 36.55789959999999894, 139.90931180000001177 36.55786609999999826)

てな感じで、geomに含まれる座標がでてきます。

これを、出発地から到着地まで、間断なく続ければ、路線の連続の座標が得られる、という訳です(そこそこ面倒ですが、selectのダンプから探すよりはマシです)。

まあ、それぞれのgeomの先頭と終端は、重複する座標となるので、これを消すなどの処理は必要ですが、取り敢えず、これで鉄道の連続する座標は得られます。

この後、これらの座標をDBに放り込むなり、プログラムにベタ書きするなり、煮るなり焼くなり、色々できると思います。

とりあえず、(emacs使い倒して)csvファイルにしました。

ここからpostgreSQLにインポートするのは ―― 多分、なんかの手段があるだろう、と思う。

ここにありました。

[付録B] 地図の上に100人ほど配置してみる(メモ)

私はPostgreSQLをdockerコンテナの中に作っているので、"docker cp"でコンテナ内にcsvファイルを送り込む必要がありました。

utsu_rail_db=# CREATE TABLE "lrt"(
utsu_rail_db(# seq integer,
utsu_rail_db(# x1 float,
utsu_rail_db(# y1 float,
utsu_rail_db(# distance_m float
utsu_rail_db(# );
CREATE TABLE
utsu_rail_db=# \dt
              List of relations
 Schema |      Name       | Type  |  Owner
--------+-----------------+-------+----------
 public | lrt             | table | postgres
 public | spatial_ref_sys | table | postgres
 public | utunomiya       | table | postgres
(3 rows)
utsu_rail_db=# \copy lrt from '/tmp/lrt.csv' with csv
COPY 286
utsu_rail_db=# select * from lrt;
 seq |     x1      |     y1      | distance_m
-----+-------------+-------------+-------------
   1 | 139.8997015 |  36.5594845 |           0
   2 | 139.8995563 |  36.5588579 | 55.68730112
   3 | 139.8995483 |  36.5587788 | 6.785051714
   4 | 139.8995634 |  36.5587263 | 4.769494948
   5 | 139.8996118 |   36.558661 | 7.734168448
   6 |  139.899682 |  36.5586132 | 8.800865673
   7 | 139.8997738 |  36.5585875 | 10.43856664
   8 | 139.8998784 |  36.5585725 | 11.70055883
285 | 140.0145241 | 36.572845 | 28.22469677
286 | 140.0117433 | 36.57920089 | 623.5656217
(286 rows)
以上

2022/05,江端さんの技術メモ

どうせ、また、いずれ、同じ内容で探し回ることになると思うので、今、記載しておきます

utsu_db=# SELECT seq, node, edge, cost, agg_cost FROM pgr_dijkstra('SELECT gid as id, source, target, length as cost FROM
ways',100, 600, false);
seq | node | edge | cost | agg_cost
-----+-------+-------+------------------------+-----------------------
1 | 100 | 41 | 0.0002983579226385357 | 0
2 | 18996 | 21479 | 0.0006788280602488493 | 0.0002983579226385357
3 | 6119 | 24518 | 0.00019027162164538517 | 0.000977185982887385
4 | 19331 | 6766 | 0.0010928248868793096 | 0.0011674576045327702
5 | 18976 | 21474 | 0.0003135978634977571 | 0.00226028249141208
6 | 6120 | 24519 | 0.00014212958875406848 | 0.0025738803549098374
7 | 2595 | 29737 | 0.00012339732574262452 | 0.002716009943663906
8 | 6137 | 30391 | 0.00016648675622455585 | 0.0028394072694065305

このcostの単位って何なの? 私は距離が知りたいだけなんだけど? と探し回ったら、なんのことはない、単に"length"→"length_m"にすればよかっただけでした。

utsu_db=# SELECT seq, node, edge, cost, agg_cost FROM pgr_dijkstra('SELECT gid as id, source, target, length_m as cost FROM ways',100, 600, false);
seq | node | edge | cost | agg_cost
-----+-------+-------+--------------------+--------------------
1 | 100 | 41 | 27.7006591508524 | 0
2 | 18996 | 21479 | 63.36986127215735 | 27.7006591508524
3 | 6119 | 24518 | 17.68514641657604 | 91.07052042300975
4 | 19331 | 6766 | 102.22241800670713 | 108.75566683958579
5 | 18976 | 21474 | 30.189796472672 | 210.97808484629292
6 | 6120 | 24519 | 14.342809731736027 | 241.16788131896493
7 | 2595 | 29737 | 13.438709335725413 | 255.51069105070096

ちなみに、agg_costは、距離の足し算の合計値を出してくれるので、便利です。

いちおう、GoogleマップとQGISつかって、大体の距離も合っていたので、大丈夫でしょう。

 

 

2022/05,江端さんの技術メモ

// go get github.com/lib/pq を忘れずに
// go run main6.go

/*
	前提は、https://ebata-books.booth.pm/items/3351408 の環境

	(1)スタート地点  139.91804656152837 36.57246810341353,
	(2)ゴール地点 139.93515104919825 36.55883778950532
	(3)とした時、この2点に最も近いノードを探し出して、
	(4)その2点をダイクストラ法で、最短距離探索をするプログラム

	分かったこと
	上記(3)のノードが、孤立ノードになっている場合があり、この場合(4)が実施できないので、
	ダイクストラに失敗する場合は、別のノードでトライアルする必要あり 
	(このコードでは展開しないけど)
*/

package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/lib/pq"
)

var source int
var longitude float64
var latitude float64
var dist float64

func main() {
	db, err := sql.Open("postgres",
		"user=postgres password=password host=localhost port=15432 dbname=utsu_db sslmode=disable")
	if err != nil {
		log.Fatal("OpenError: ", err)
	}
	defer db.Close()

	// スタート地点  139.91804656152837 36.57246810341353
	rows, err := db.Query("SELECT source, x1 as longitude, y1 as latitude, ST_Distance('SRID=4326;POINT(139.91804656152837 36.57246810341353)'::GEOGRAPHY, the_geom) as dist FROM ways WHERE ST_DWithin(the_geom, ST_GeographyFromText('SRID=4326;POINT(139.91804656152837 36.57246810341353)'), 300.0) ORDER BY dist LIMIT 1")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {

		if err := rows.Scan(&source, &longitude, &latitude, &dist); err != nil {
			fmt.Println(err)
		}
		fmt.Println(source, longitude, latitude, dist)
	}

	o_source := source

	// ゴール地点 139.93515104919825 36.55883778950532
	rows, err = db.Query("SELECT source, x1 as longitude, y1 as latitude, ST_Distance('SRID=4326;POINT(139.93515104919825 36.55883778950532)'::GEOGRAPHY, the_geom) as dist FROM ways WHERE ST_DWithin(the_geom, ST_GeographyFromText('SRID=4326;POINT(139.93515104919825 36.55883778950532)'), 300.0) ORDER BY dist LIMIT 1")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {

		if err := rows.Scan(&source, &longitude, &latitude, &dist); err != nil {
			fmt.Println(err)
		}
		fmt.Println(source, longitude, latitude, dist)
	}

	d_source := source

	fmt.Println(o_source, d_source)

	// これが基本形
	// rows, err = db.Query("SELECT seq, node, edge, cost FROM pgr_dijkstra('SELECT gid as id, source, target,length as cost FROM ways',8889, 22848, false)")

	// この bigint なるものは、https://wp.kobore.net/%E6%B1%9F%E7%AB%AF%E3%81%95%E3%82%93%E3%81%AE%E6%8A%80%E8%A1%93%E3%83%A1%E3%83%A2/error-function-pgr_dijkstraunknown-start_vid-bigint-end_vid-bigint-directed-boolean-does-not-exist-line-7-pgr_dijkstra-hint-no-function-matches-the-given-name/ に記載がある
	rows, err = db.Query("SELECT seq, node, edge, cost FROM pgr_dijkstra('SELECT gid as id, source, target,length as cost FROM ways', $1::bigint , $2::bigint , false)", o_source, d_source)

	// こっちも稼動します
	// str := "SELECT seq, node, edge, cost FROM pgr_dijkstra('SELECT gid as id, source, target,length as cost FROM ways'," + strconv.Itoa(o_source) + "," + strconv.Itoa(d_source) + ", false)"
	// fmt.Println(str)
	// rows, err = db.Query(str)

	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var seq int
		var node int
		var edge int
		var cost float64

		if err := rows.Scan(&seq, &node, &edge, &cost); err != nil {
			fmt.Println(err)
		}
		fmt.Println(seq, node, edge, cost)
	}

	if err := db.Ping(); err != nil {
		log.Fatal("PingError: ", err)
	}
}

2022/05,江端さんの技術メモ

// go get github.com/lib/pq を忘れずに
// go run main5.go
package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/lib/pq"
)

func main() {
	db, err := sql.Open("postgres", "user=postgres password=password host=localhost port=15432 dbname=utsu_db sslmode=disable")
	if err != nil {
		log.Fatal("OpenError: ", err)
	}
	defer db.Close()

	rows, err := db.Query("SELECT gid,tag_id,x1 FROM ways")
	if err != nil {
		log.Fatal(err)
	}

	// 139.9182893339256, 36.573831584767085

	defer rows.Close()

	for rows.Next() {
		var gid int
		var tag_id int
		var x1 float64
		if err := rows.Scan(&gid, &tag_id, &x1); err != nil {
			fmt.Println(err)
		}
		fmt.Println(gid, tag_id, x1)
	}

	if err := db.Ping(); err != nil {
		log.Fatal("PingError: ", err)
	}
}

さて

http://www.kobore.net/diary_techno/?date=20181101

の中の、点(139.9182893339256 36.573831584767085)から半径300メートル以内の全部のノードを、近い順に出せ

を、psqlで出力させると、こんな感じになります。

Golangで実施するとなると、こんなコードになります(select文のコピペで足ります)。

// go get github.com/lib/pq を忘れずに
// go run main5.go
package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/lib/pq"
)

func main() {
	db, err := sql.Open("postgres",
		"user=postgres password=password host=localhost port=15432 dbname=utsu_db sslmode=disable")
	if err != nil {
		log.Fatal("OpenError: ", err)
	}
	defer db.Close()

	rows, err := db.Query("SELECT source, x1 as longitude, y1 as latitude, ST_Distance('SRID=4326;POINT(139.9182893339256 36.573831584767085)'::GEOGRAPHY, the_geom) as dist FROM ways WHERE ST_DWithin(the_geom, ST_GeographyFromText('SRID=4326;POINT(139.9182893339256 36.573831584767085)'), 300.0) ORDER BY dist")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var source int
		var longitude float64
		var latitude float64
		var dist float64

		if err := rows.Scan(&source, &longitude, &latitude, &dist); err != nil {
			fmt.Println(err)
		}
		fmt.Println(source, longitude, latitude, dist)
	}

	if err := db.Ping(); err != nil {
		log.Fatal("PingError: ", err)
	}
}

出力結果は同じものになります。