imposm3/parser/pbf/pbf.go

245 lines
5.9 KiB
Go
Raw Normal View History

package pbf
2013-02-12 22:45:49 +04:00
import (
2014-08-04 17:19:35 +04:00
"github.com/omniscale/imposm3/element"
"github.com/omniscale/imposm3/parser/pbf/osmpbf"
2013-02-12 22:45:49 +04:00
"log"
)
2013-07-05 11:57:03 +04:00
type Block struct {
2013-02-12 22:45:49 +04:00
filename string
offset int64
2013-07-05 11:57:03 +04:00
size int32
2013-02-12 22:45:49 +04:00
}
2013-07-05 11:57:03 +04:00
const coord_factor float64 = 11930464.7083 // ((2<<31)-1)/360.0
2013-02-12 22:45:49 +04:00
func coordToInt(coord float64) uint32 {
2013-07-05 11:57:03 +04:00
return uint32((coord + 180.0) * coord_factor)
2013-02-12 22:45:49 +04:00
}
func intToCoord(coord uint32) float64 {
2013-07-05 11:57:03 +04:00
return float64((float64(coord) / coord_factor) - 180.0)
2013-02-12 22:45:49 +04:00
}
2013-07-05 11:57:03 +04:00
func readDenseNodes(
2013-02-12 22:45:49 +04:00
dense *osmpbf.DenseNodes,
block *osmpbf.PrimitiveBlock,
2013-07-05 11:57:03 +04:00
stringtable stringTable) (coords []element.Node, nodes []element.Node) {
2013-02-12 22:45:49 +04:00
var lastId int64
var lastLon, lastLat int64
coords = make([]element.Node, len(dense.Id))
nodes = make([]element.Node, 0, len(dense.Id)/8)
2013-02-12 22:45:49 +04:00
granularity := int64(block.GetGranularity())
latOffset := block.GetLatOffset()
lonOffset := block.GetLonOffset()
coordScale := 0.000000001
lastKeyValPos := 0
for i := range coords {
2013-02-12 22:45:49 +04:00
lastId += dense.Id[i]
lastLon += dense.Lon[i]
lastLat += dense.Lat[i]
coords[i].Id = lastId
coords[i].Long = (coordScale * float64(lonOffset+(granularity*lastLon)))
coords[i].Lat = (coordScale * float64(latOffset+(granularity*lastLat)))
2013-05-06 12:50:55 +04:00
if stringtable != nil && len(dense.KeysVals) > 0 {
if dense.KeysVals[lastKeyValPos] != 0 {
2013-07-05 11:57:03 +04:00
tags := parseDenseNodeTags(stringtable, &dense.KeysVals, &lastKeyValPos)
if tags != nil {
if _, ok := tags["created_by"]; ok && len(tags) == 1 {
// don't add nodes with only created_by tag to nodes cache
} else {
nd := coords[i]
nd.Tags = tags
nodes = append(nodes, nd)
}
}
} else {
lastKeyValPos += 1
}
2013-02-12 22:45:49 +04:00
}
}
return coords, nodes
2013-02-12 22:45:49 +04:00
}
2013-07-05 11:57:03 +04:00
func parseDenseNodeTags(stringtable stringTable, keysVals *[]int32, pos *int) map[string]string {
2013-06-03 13:03:19 +04:00
// make map later if needed
var result map[string]string
2013-02-12 22:45:49 +04:00
for {
if *pos >= len(*keysVals) {
return result
}
key := (*keysVals)[*pos]
*pos += 1
if key == 0 {
return result
}
val := (*keysVals)[*pos]
*pos += 1
2013-06-03 13:03:19 +04:00
if result == nil {
result = make(map[string]string)
}
result[stringtable[key]] = stringtable[val]
}
}
2013-05-13 12:55:08 +04:00
2013-07-05 11:57:03 +04:00
func parseTags(stringtable stringTable, keys []uint32, vals []uint32) map[string]string {
2013-06-03 13:03:19 +04:00
if len(keys) == 0 {
return nil
}
tags := make(map[string]string)
for i := 0; i < len(keys); i++ {
key := stringtable[keys[i]]
val := stringtable[vals[i]]
tags[key] = val
}
return tags
}
2013-07-05 11:57:03 +04:00
func readNodes(
nodes []*osmpbf.Node,
block *osmpbf.PrimitiveBlock,
2013-07-05 11:57:03 +04:00
stringtable stringTable) ([]element.Node, []element.Node) {
coords := make([]element.Node, len(nodes))
nds := make([]element.Node, 0, len(nodes)/8)
granularity := int64(block.GetGranularity())
latOffset := block.GetLatOffset()
lonOffset := block.GetLonOffset()
coordScale := 0.000000001
for i := range nodes {
id := *nodes[i].Id
lon := *nodes[i].Lon
lat := *nodes[i].Lat
coords[i].Id = id
coords[i].Long = (coordScale * float64(lonOffset+(granularity*lon)))
coords[i].Lat = (coordScale * float64(latOffset+(granularity*lat)))
if stringtable != nil {
2013-07-05 11:57:03 +04:00
tags := parseTags(stringtable, nodes[i].Keys, nodes[i].Vals)
if tags != nil {
if _, ok := tags["created_by"]; ok && len(tags) == 1 {
// don't add nodes with only created_by tag to nodes cache
} else {
nd := coords[i]
nd.Tags = tags
nds = append(nds, nd)
}
}
}
}
return coords, nds
}
2013-07-05 11:57:03 +04:00
func parseDeltaRefs(refs []int64) []int64 {
result := make([]int64, len(refs))
var lastRef int64
for i, refDelta := range refs {
lastRef += refDelta
result[i] = lastRef
}
return result
}
2013-07-05 11:57:03 +04:00
func readWays(
ways []*osmpbf.Way,
block *osmpbf.PrimitiveBlock,
2013-07-05 11:57:03 +04:00
stringtable stringTable) []element.Way {
result := make([]element.Way, len(ways))
for i := range ways {
id := *ways[i].Id
result[i].Id = id
2013-07-05 11:57:03 +04:00
result[i].Tags = parseTags(stringtable, ways[i].Keys, ways[i].Vals)
result[i].Refs = parseDeltaRefs(ways[i].Refs)
}
return result
}
2013-07-05 11:57:03 +04:00
func parseRelationMembers(rel *osmpbf.Relation, stringtable stringTable) []element.Member {
result := make([]element.Member, len(rel.Memids))
var lastId int64
for i := range rel.Memids {
lastId += rel.Memids[i]
result[i].Id = lastId
result[i].Role = stringtable[rel.RolesSid[i]]
result[i].Type = element.MemberType(rel.Types[i])
}
return result
}
2013-07-05 11:57:03 +04:00
func readRelations(
relations []*osmpbf.Relation,
block *osmpbf.PrimitiveBlock,
2013-07-05 11:57:03 +04:00
stringtable stringTable) []element.Relation {
result := make([]element.Relation, len(relations))
for i := range relations {
id := *relations[i].Id
result[i].Id = id
2013-07-05 11:57:03 +04:00
result[i].Tags = parseTags(stringtable, relations[i].Keys, relations[i].Vals)
result[i].Members = parseRelationMembers(relations[i], stringtable)
2013-02-12 22:45:49 +04:00
}
return result
}
2013-07-05 11:57:03 +04:00
type stringTable []string
2013-02-12 22:45:49 +04:00
2013-07-05 11:57:03 +04:00
func newStringTable(source *osmpbf.StringTable) stringTable {
result := make(stringTable, len(source.S))
2013-02-12 22:45:49 +04:00
for i, bytes := range source.S {
result[i] = string(bytes)
}
return result
}
2013-07-05 11:57:03 +04:00
func Blocks(filename string) chan Block {
pbf, err := Open(filename)
if err != nil {
log.Fatal(err)
}
return pbf.BlockPositions()
2013-02-12 22:45:49 +04:00
}
2013-07-05 11:57:03 +04:00
func (pos *Block) Parse(coords chan []element.Node, nodes chan []element.Node, ways chan []element.Way, relations chan []element.Relation) {
block := readPrimitiveBlock(*pos)
stringtable := newStringTable(block.GetStringtable())
2013-04-08 23:45:13 +04:00
for _, group := range block.Primitivegroup {
dense := group.GetDense()
if dense != nil {
2013-07-05 11:57:03 +04:00
parsedCoords, parsedNodes := readDenseNodes(dense, block, stringtable)
if len(parsedCoords) > 0 {
coords <- parsedCoords
}
2013-04-20 18:50:23 +04:00
if len(parsedNodes) > 0 {
nodes <- parsedNodes
}
2013-04-08 23:45:13 +04:00
}
2013-07-05 11:57:03 +04:00
parsedCoords, parsedNodes := readNodes(group.Nodes, block, stringtable)
if len(parsedCoords) > 0 {
coords <- parsedCoords
}
2013-04-20 18:50:23 +04:00
if len(parsedNodes) > 0 {
nodes <- parsedNodes
}
2013-07-05 11:57:03 +04:00
parsedWays := readWays(group.Ways, block, stringtable)
2013-04-20 18:50:23 +04:00
if len(parsedWays) > 0 {
ways <- parsedWays
}
2013-07-05 11:57:03 +04:00
parsedRelations := readRelations(group.Relations, block, stringtable)
2013-04-20 18:50:23 +04:00
if len(parsedRelations) > 0 {
relations <- parsedRelations
2013-04-08 23:45:13 +04:00
}
}
}