LoginSignup
7

More than 1 year has passed since last update.

Golang で OpenStreetMap ファイル(osm.pbf)の読み込み(osmpbf 利用)

Last updated at Posted at 2015-07-01

こんにちは。
Golang で osm.pbf フォーマットの OpenStreetMap データファイルの読み込みを行ないました。qedus/osmpbf (を小修正したもの)を利用しました1 2 3pbf-parser-comparison (GitHub) にもあるように確かに処理速度が速いように見えます。

  • ただしこれは、読込む osm.pbf ファイルには注意が必要で、osmconvert でクリッピングして作ったファイル(例えばbbbike.orgの extraction 機能で作られたファイル)を読み込むとメモリ消費量が大きいです。osmosisosmium-toolで作られたファイルではこの問題は無いように見えます。

$ wget https://gist.github.com/AlekSi/d4369aa13cf1fc5ddfac3e91b67b2f7b/raw/8604f36a7357adfbd6b5292c2ea4972d9d0bfd3d/greater-london-140324.osm.pbf 
$ ls -ldh greater-london-140324.osm.pbf 
-rw-r--r--  1 kkdd  staff    33M 10 10 10:10 greater-london-140324.osm.pbf
$
$ go run osmpbf_progressbar.go -ncpu 4 greater-london-140324.osm.pbf 
33728 / 33728 [====================================================] 100.00 % 1s
Nodes: 2,729,006, Ways: 459,055, Relations: 12,833
$ go run osmpbf_progressbar.go -ncpu 1 greater-london-140324.osm.pbf 
33728 / 33728 [====================================================] 100.00 % 4s
Nodes: 2,729,006, Ways: 459,055, Relations: 12,833
osmpbf_progressbar.go
package main

import (
    "os"
    "io"
    "fmt"
    "log"
    "flag"
    "runtime"
    "github.com/cheggaaa/pb"
    "github.com/dustin/go-humanize"
    "github.com/kkdd/osmpbf"
)

func main() {
    ncpu := flag.Int("ncpu", 1, "number of CPU")
    flag.Parse()
    runtime.GOMAXPROCS(*ncpu)
    for _, file := range flag.Args() {
        worker(file)
    }
}

func worker(file string) { 
    f, err := os.Open(file)
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()
    stat, _ := f.Stat()
    filesiz := int(stat.Size()/1024)

    d := osmpbf.NewDecoder(f)
    err = d.Start(runtime.GOMAXPROCS(-1))
    if err != nil {
        log.Fatal(err)
    }

    var nc, wc, rc, i int64
    progressbar := pb.New(filesiz).SetUnits(pb.U_NO)
    progressbar.Start()
    for i = 0; ; i++ {
        if v, err := d.Decode(); err == io.EOF {
            break
        } else if err != nil {
            log.Fatal(err)
        } else {
            switch v := v.(type) {
            case *osmpbf.Node:
                nc++
            case *osmpbf.Way:
                wc++
            case *osmpbf.Relation:
                rc++
            default:
                log.Fatalf("unknown type %T\n", v)
            }
        }
        if i % 131072 == 0 {
            progressbar.Set(int(d.GetTotalReadSize()/1024))
        }
    }
    progressbar.Set(filesiz)
    progressbar.Finish()
    fmt.Printf("Nodes: %s, Ways: %s, Relations: %s\n", humanize.Comma(nc), humanize.Comma(wc), humanize.Comma(rc))
}
  1. 他にも Go 用ライブラリがあるようです。例えば、paulmach/osm/osmpbf, thomersch/gosmparse, maguro/pbf, omniscale/imposm3, qedus/osmpbf, missinglink/pbf。処理速度とメモリ消費量を実験して選ぶと良いかもしれません。

  2. C++ 用には、osmcode/libosmium (Python 用バインディングもあります)、CanalTP/libosmpbfreader があるようです。

  3. Rust 用には、b-r-u/osmpbf, TeXitoi/osmpbfreader-rs, crate/osmpbfreader, oleksandromelchuk/rust-osm-reader があるようです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7