当前位置: 首页 > 工具软件 > Node Osmosis > 使用案例 >

osmosis抽取PBF矢量数据,导出xml格式数据

方建明
2023-12-01

osmosis

用于处理OSM数据的Java命令行应用程序,包括许多插件式的组件。比如读写数据库和文件的组件、继承和修改数据源的组件、对数据排序管理的组件等,避免了实现常用功能而重复性编写代码。

目前主要功能有:

  • 从数据库中生成指定区域的osm数据
  • 导入区域的osm数据到数据库
  • 生成变化数据集数据库更新记录表
  • 应用变化数据集到本地数据库
  • 比较区域osm数据生成变化数据集
  • 区域osm数据重排序
  • 抽取指定矩形或多边形范围内数据
https://wiki.openstreetmap.org/wiki/Osmosis/Examples
https://wiki.openstreetmap.org/wiki/Zh-hans:Osmosis

安装

sudo apt-get update
sudo apt-get install osmosis

使用案例

从 PBF 提取中提取火车站数据导出xml格式数据

osmosis --read-pbf china.osm.pbf --node-key-value keyValueList="railway.station" --write-xml station.osm.xml

解析xml数据形成sqlite数据

package main

import (
	"encoding/json"
	"fmt"
	xj "github.com/basgys/goxml2json"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"
	"test_project/global"
	"test_project/initialize"
)

type Station struct {
	Id        int     `json:"id" gorm:"primary_key;auto_increment"`
	Name      string  `json:"name"`
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
}

func (s *Station) TableName() string {
	return "station"
}

func (s *Station) Insert(stations []Station) (err error) {
	table := global.GVA_DB
	err = table.Create(&stations).Error
	return
}

// RegisterTables 注册数据库表专用
// Author SliverHorn
func RegisterTables() {
	err := global.GVA_DB.AutoMigrate(
		&Station{},
	)
	if err != nil {
		fmt.Println("register table failed", err)
		os.Exit(0)
	}
	fmt.Println("register table success", err)
}

func main() {
	global.GVA_DB = initialize.GormSqlite()
	RegisterTables()
	bytes, err := ioutil.ReadFile("station.osm.xml")
	if err != nil {
		fmt.Println(err)
	}
	xml := strings.NewReader(string(bytes))

	xmlData, err := xj.Convert(xml)
	if err != nil {
		panic("That's embarrassing...")
	}
	//xml转JSON
	var scenarioInfo map[string]interface{}
	err = json.Unmarshal(xmlData.Bytes(), &scenarioInfo)
	if err != nil {
		log.Println(err)
	}
	//获取所有的node
	nodes := scenarioInfo["osm"].(map[string]interface{})["node"].([]interface{})
	//所有车站信息
	stations := make([]Station, 0)
	for _, node := range nodes {
		nodeInfo := node.(map[string]interface{})
		lat := nodeInfo["-lat"].(string)
		latitude, err := strconv.ParseFloat(lat, 64)
		if err != nil {
			log.Println(err)
		}
		lon := nodeInfo["-lon"].(string)
		longitude, err := strconv.ParseFloat(lon, 64)
		if err != nil {
			log.Println(err)
		}
		tags := nodeInfo["tag"]
		flag := true
		stationName := ""
		switch tags.(type) {
		case map[string]interface{}:
			tagInfo := tags.(map[string]interface{})
			if key, ok := tagInfo["-k"]; ok {
				if key == "name" {
					fmt.Printf("车站名称:%v 纬度:%v 经度:%v \n", tagInfo["-v"], latitude, longitude)
				}
			}
		case []interface{}:
			for _, tag := range tags.([]interface{}) {
				tagInfo := tag.(map[string]interface{})
				if key, ok := tagInfo["-k"]; ok {
					if key == "name" {
						stationName = tagInfo["-v"].(string)
						fmt.Printf("车站名称:%v 纬度:%v 经度:%v \n", tagInfo["-v"], latitude, longitude)
					}
					if key == "subway" {
						flag = true
					}
				}
			}
		default:
			fmt.Println("未找到类型")
		}
		//创建车站数据
		if flag {
			if len(stations) > 5000 {
				station := Station{}
				err := station.Insert(stations)
				if err != nil {
					log.Panic(err)
				}
				stations = make([]Station, 0)
			}
			station := Station{Latitude: latitude, Longitude: longitude, Name: stationName}
			stations = append(stations, station)
		}
	}
	fmt.Println(len(stations))
}
 类似资料: