天神・中州エリアにショッピングなどをする人の為に、道路と鉄道をマージする新鉄道(dummyTrain)をOSMデータを追加する方法
自分の為にだけでも、本にして纒めておくものである、と実感しています。
このメモの内容が分からない人は、上記の本を入手して内容を補完して下さい。
目的は、この本の内容と同じ、「地図を改竄して道路と鉄道を交えた最小コスト経路」を作り出すことだけど、今回は、JOSMを使わないでやってみる。
まずは、各駅のnode(もしドンピシャのノードがなければ、もっとも近いノードを抽出する)
station.csv
西戸崎駅,33.650366,130.358161
海ノ中道駅,33.663892,130.361410
雁ノ巣駅,33.683859,130.403325
奈多駅,33.686735,130.412492
和白駅,33.689151,130.429679
香椎駅,33.659523,130.444108
などを作っておき、
// G:\home\ebata\hakata\src\others\main22
import (
"database/sql"
"encoding/csv"
"fmt"
"log"
"os"
"strconv"
"strings"
_ "github.com/lib/pq"
)
func main() {
// データベース接続設定
connStr := "user=postgres password=password host=127.0.0.1 port=15432 dbname=hakata_db sslmode=disable"
db, err := sql.Open("postgres", connStr)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// CSVファイルを開く
file, err := os.Open("stations.csv")
if err != nil {
log.Fatal(err)
}
defer file.Close()
// CSVリーダーの作成
reader := csv.NewReader(file)
records, err := reader.ReadAll()
if err != nil {
log.Fatal(err)
}
// 出力用CSVファイルの作成
outFile, err := os.Create("stations_with_osm_id.csv")
if err != nil {
log.Fatal(err)
}
defer outFile.Close()
writer := csv.NewWriter(outFile)
defer writer.Flush()
// 各レコードについて最も近いosm_idを取得し、新しいCSVに書き込む
for _, record := range records {
// コメント行をスキップ
if len(record) == 0 || strings.HasPrefix(record[0], "#") {
continue
}
// 緯度と経度をパース(空白をトリム)
latStr := strings.TrimSpace(record[1])
lonStr := strings.TrimSpace(record[2])
lat, err := strconv.ParseFloat(latStr, 64)
if err != nil {
log.Fatalf("Error parsing latitude: %v", err)
}
lon, err := strconv.ParseFloat(lonStr, 64)
if err != nil {
log.Fatalf("Error parsing longitude: %v", err)
}
// 最も近いosm_idを検索
var osmID int64
query := `
SELECT osm_id FROM ways_vertices_pgr
ORDER BY the_geom <-> ST_SetSRID(ST_MakePoint($1, $2), 4326)
LIMIT 1;
`
err = db.QueryRow(query, lon, lat).Scan(&osmID)
if err != nil {
log.Fatal(err)
}
// osm_idをCSVに追加
newRecord := append(record, strconv.FormatInt(osmID, 10))
if err := writer.Write(newRecord); err != nil {
log.Fatal("Error writing record to CSV:", err)
}
}
fmt.Println("CSVファイルに最も近いosm_idを追加しました。")
}
のプログラムで、
stations_with_osm_id.csv
西戸崎駅,33.6794,130.3947,58565
海ノ中道駅,33.6794,130.3816,38065
雁ノ巣駅,33.6747,130.3651,25953
奈多駅,33.6710,130.3533,46806
和白駅,33.6663,130.3514,25944
香椎駅,33.6616,130.4405,29380
香椎神宮駅,33.6615,130.4568,42178
のように、ノード番号を取得します。
で、つぎにhakata.osmに、以下を追加
<!-- Way: Dummy Railway Line -->
<way id="123456789" version="1" timestamp="2024-08-22T06:13:26Z" changeset="99999999" uid="999999" user="kobore.net">
<nd ref="1818760266" /> <!-- 古賀駅 -->
<nd ref="1846875572" /> <!-- ししぶ駅 -->
<nd ref="1971252636" /> <!-- 福工大前駅 -->
<nd ref="440118260" /> <!-- 九産大前駅 -->
<nd ref="1808374554" /> <!-- 香椎駅 -->
<nd ref="1864205708" /> <!-- 千早駅 -->
<nd ref="1252519465" /> <!-- 箱崎駅 -->
<nd ref="1239476659" /> <!-- 吉塚駅 -->
<nd ref="1882462094" /> <!-- 博多駅 -->
<nd ref="1814285264" /> <!-- 竹下駅 -->
<nd ref="6569627454" /> <!-- 笹原駅 -->
<nd ref="1831604260" /> <!-- 南福岡駅 -->
<nd ref="815318744" /> <!-- 春日駅 -->
<nd ref="765561820" /> <!-- 大野城駅 -->
<nd ref="767176221" /> <!-- 水城駅 -->
<tag k="railway" v="dummyrail" />
<tag k="name" v="Dummy Railway Line" />
</way>
</osm>
で、
<way id="123456789" version="1" timestamp="2024-08-22T06:13:26Z" changeset="99999999" uid="999999" user="kobore.net">
の意味ですが、私はローカルで地図の変更をしているだけで、この情報をアップロードする予定がありません(地図を壊す気はない)。
ローカル環境で地図の変更を行い、OSMのデータをアップロードしない場合、`changeset` や `uid` は特に必要ありませんが、OSMファイルの形式として保持する必要がある場合、以下のように適当に値を設定して問題ないそうです。
ただし、way id="123456789" は、衝突しない値にすることに留意します.
これが設定できているかを、JOSMとQGISの両方で確認します。
ん。JOSMについては確認できました。
でもJOSMに表示できても、GIS-DBには落せないことは、以前に多々ありました。で、その時はQGISにも表示されない。逆に考えればQGISに表示されれば、GIS-DBには落せるかもしれない、とは言えます。
とりあえず、OSMをQGISにドラッグして、全部表示させます。
見にくので、lineだけの表示にします。
表示できました。
さらにを路線拡張。ここまでは予定通り(地図を見ながら、駅順番や位置情報を補正(これが結構なテマ)
GISを作っていると、その場所に対しての知見が増えて、都市開発している気持ちになってきます ――
『もう、福岡に遷都でよくね?』という感じになります。