imposm3/cache/binary/tags.go

315 lines
10 KiB
Go

package binary
// Serialize tags to a array of interleaved key and value strings.
// Common tags like building=yes are serialized to a single unicode
// char to save a few bytes. Common keys to a single ASCII ctrl char.
// Common tags are encoded as a single unicode char from the Unicode
// Private Use Area http://en.wikipedia.org/wiki/Private_Use_(Unicode)
// between U+E000 and U+F8FF. They take three bytes in UTF-8 encoding.
//
// For example: building=yes will need 4 bytes instead of 13 bytes.
// (building=8 + yes=3 + 2x1 for string length, vs. 3+1)
// The most common tag kays with variable values (name, addr:street,
// etc.) are converted to a single ASCII control char (0x01-0x1f)
import (
"github.com/omniscale/imposm3/element"
"unicode/utf8"
)
type codepoint rune
type tag struct {
Key string
Value string
}
var tagsToCodePoint = map[string]map[string]codepoint{}
var codePointToTag = map[codepoint]tag{}
var commonKeys = map[string]codepoint{}
var codePointToCommonKey = map[uint8]string{}
var nextKeyCodePoint = codepoint(1)
var maxKeyCodePoint = codepoint(31)
const minCodePoint = codepoint('\uE000')
const maxCodePoint = codepoint('\uF8FF')
var nextCodePoint = codepoint('\uE000')
func addTagCodePoint(key, value string) {
if nextCodePoint > maxCodePoint {
panic("all codepoints used!")
}
valMap, ok := tagsToCodePoint[key]
if !ok {
tagsToCodePoint[key] = map[string]codepoint{value: nextCodePoint}
} else {
if _, ok := valMap[value]; ok {
panic("duplicate entry for tag codepoints: " + key + " " + value)
}
valMap[value] = nextCodePoint
}
codePointToTag[nextCodePoint] = tag{key, value}
nextCodePoint += 1
}
func addCommonKey(key string) {
if nextKeyCodePoint > maxKeyCodePoint {
panic("all codepoints used!")
}
commonKeys[key] = nextKeyCodePoint
codePointToCommonKey[uint8(nextKeyCodePoint)] = key
nextKeyCodePoint += 1
}
func tagsFromArray(arr []string) element.Tags {
if len(arr) == 0 {
return element.Tags{}
}
result := make(element.Tags)
for i := 0; i < len(arr); i += 1 {
if r, size := utf8.DecodeRuneInString(arr[i]); size >= 3 &&
codepoint(r) >= minCodePoint &&
codepoint(r) < nextCodePoint {
tag, ok := codePointToTag[codepoint(r)]
if !ok {
panic("missing tag for codepoint")
}
result[tag.Key] = tag.Value
} else if len(arr[i]) > 0 && arr[i][0] < 32 {
result[codePointToCommonKey[arr[i][0]]] = arr[i][1:]
} else {
result[arr[i]] = arr[i+1]
i++
}
}
return result
}
func tagsAsArray(tags element.Tags) []string {
if len(tags) == 0 {
return nil
}
result := make([]string, 0, 2*len(tags))
for key, val := range tags {
if valMap, ok := tagsToCodePoint[key]; ok {
if codePoint, ok := valMap[val]; ok {
result = append(result, string(codePoint))
continue
}
}
if codepoint, ok := commonKeys[key]; ok {
result = append(result, string(codepoint)+val)
continue
}
result = append(result, key, val)
}
return result
}
func init() {
//
// DO NOT EDIT, REMOVE, REORDER ANY OF THE FOLLOWING LINES!
//
// most common keys with variable values
// there are only 31 code points for common keys
addCommonKey("name")
addCommonKey("addr:street")
addCommonKey("addr:place")
addCommonKey("addr:city")
addCommonKey("addr:postcode")
addCommonKey("addr:housenumber")
// most used tags for ways
//
addTagCodePoint("building", "yes")
addTagCodePoint("highway", "residential")
addTagCodePoint("highway", "service")
addTagCodePoint("wall", "no")
addTagCodePoint("highway", "unclassified")
addTagCodePoint("waterway", "stream")
addTagCodePoint("highway", "track")
addTagCodePoint("natural", "water")
addTagCodePoint("oneway", "yes")
addTagCodePoint("highway", "footway")
addTagCodePoint("highway", "tertiary")
addTagCodePoint("access", "private")
addTagCodePoint("highway", "path")
addTagCodePoint("highway", "secondary")
addTagCodePoint("landuse", "forest")
addTagCodePoint("building", "house")
addTagCodePoint("bridge", "yes")
addTagCodePoint("surface", "asphalt")
addTagCodePoint("natural", "wood")
addTagCodePoint("foot", "yes")
addTagCodePoint("landuse", "residential")
addTagCodePoint("surface", "paved")
addTagCodePoint("highway", "primary")
addTagCodePoint("surface", "unpaved")
addTagCodePoint("landuse", "grass")
addTagCodePoint("building", "residential")
addTagCodePoint("service", "parking_aisle")
addTagCodePoint("oneway", "no")
addTagCodePoint("railway", "rail")
addTagCodePoint("bicycle", "yes")
addTagCodePoint("service", "driveway")
addTagCodePoint("amenity", "parking")
addTagCodePoint("area", "yes")
addTagCodePoint("barrier", "fence")
addTagCodePoint("tracktype", "grade2")
addTagCodePoint("natural", "coastline")
addTagCodePoint("tracktype", "grade3")
addTagCodePoint("intermittent", "yes")
addTagCodePoint("landuse", "farmland")
addTagCodePoint("building", "hut")
addTagCodePoint("boundary", "administrative")
addTagCodePoint("lit", "yes")
addTagCodePoint("highway", "cycleway")
addTagCodePoint("landuse", "meadow")
addTagCodePoint("waterway", "river")
addTagCodePoint("natural", "wetland")
addTagCodePoint("highway", "trunk")
addTagCodePoint("surface", "gravel")
addTagCodePoint("tracktype", "grade1")
addTagCodePoint("barrier", "wall")
addTagCodePoint("building", "garage")
addTagCodePoint("highway", "living_street")
addTagCodePoint("highway", "motorway")
addTagCodePoint("tracktype", "grade4")
addTagCodePoint("landuse", "farm")
addTagCodePoint("leisure", "pitch")
addTagCodePoint("surface", "ground")
addTagCodePoint("tunnel", "yes")
addTagCodePoint("highway", "motorway_link")
addTagCodePoint("bicycle", "no")
addTagCodePoint("highway", "road")
addTagCodePoint("natural", "scrub")
addTagCodePoint("highway", "steps")
addTagCodePoint("foot", "designated")
addTagCodePoint("waterway", "ditch")
addTagCodePoint("admin_level", "8")
addTagCodePoint("tracktype", "grade5")
addTagCodePoint("access", "yes")
addTagCodePoint("building", "apartments")
addTagCodePoint("leisure", "swimming_pool")
addTagCodePoint("junction", "roundabout")
addTagCodePoint("highway", "pedestrian")
addTagCodePoint("barrier", "hedge")
addTagCodePoint("bicycle", "designated")
addTagCodePoint("leisure", "park")
addTagCodePoint("service", "alley")
addTagCodePoint("landuse", "farmyard")
addTagCodePoint("building", "industrial")
addTagCodePoint("waterway", "riverbank")
addTagCodePoint("building", "roof")
addTagCodePoint("surface", "dirt")
addTagCodePoint("waterway", "drain")
addTagCodePoint("surface", "grass")
addTagCodePoint("amenity", "school")
addTagCodePoint("power", "line")
addTagCodePoint("landuse", "industrial")
addTagCodePoint("landuse", "reservoir")
addTagCodePoint("water", "intermittent")
addTagCodePoint("highway", "trunk_link")
addTagCodePoint("segregated", "no")
addTagCodePoint("horse", "no")
addTagCodePoint("wood", "deciduous")
addTagCodePoint("highway", "primary_link")
addTagCodePoint("foot", "no")
addTagCodePoint("lit", "no")
addTagCodePoint("surface", "concrete")
addTagCodePoint("building", "garages")
addTagCodePoint("amenity", "place_of_worship")
addTagCodePoint("religion", "christian")
addTagCodePoint("waterway", "canal")
addTagCodePoint("landuse", "orchard")
addTagCodePoint("surface", "paving_stones")
addTagCodePoint("leisure", "garden")
addTagCodePoint("service", "spur")
addTagCodePoint("living_street", "yes")
addTagCodePoint("access", "permissive")
addTagCodePoint("sport", "soccer")
addTagCodePoint("frequency", "0")
addTagCodePoint("landuse", "cemetery")
addTagCodePoint("wood", "mixed")
addTagCodePoint("motorcar", "no")
addTagCodePoint("access", "no")
addTagCodePoint("man_made", "pier")
addTagCodePoint("oneway", "-1")
addTagCodePoint("sport", "tennis")
addTagCodePoint("noexit", "yes")
addTagCodePoint("service", "yard")
addTagCodePoint("wood", "coniferous")
addTagCodePoint("natural", "cliff")
addTagCodePoint("leisure", "playground")
addTagCodePoint("cycleway", "lane")
addTagCodePoint("surface", "cobblestone")
addTagCodePoint("landuse", "vineyard")
addTagCodePoint("frequency", "16.7")
//
// most used tags for nodes
//
addTagCodePoint("power", "tower")
addTagCodePoint("natural", "tree")
addTagCodePoint("highway", "bus_stop")
addTagCodePoint("power", "pole")
addTagCodePoint("place", "locality")
addTagCodePoint("highway", "turning_circle")
addTagCodePoint("highway", "crossing")
addTagCodePoint("place", "village")
addTagCodePoint("place", "hamlet")
addTagCodePoint("highway", "traffic_signals")
addTagCodePoint("barrier", "gate")
// addTagCodePoint("admin_level", "8")
// addTagCodePoint("amenity", "place_of_worship")
// addTagCodePoint("amenity", "school")
// addTagCodePoint("religion", "christian")
addTagCodePoint("amenity", "bench")
addTagCodePoint("man_made", "survey_point")
addTagCodePoint("amenity", "restaurant")
// addTagCodePoint("amenity", "parking")
addTagCodePoint("natural", "peak")
addTagCodePoint("railway", "level_crossing")
addTagCodePoint("type", "broad_leaved")
// addTagCodePoint("building", "yes")
// addTagCodePoint("foot", "yes")
// addTagCodePoint("bicycle", "yes")
addTagCodePoint("highway", "street_lamp")
addTagCodePoint("tourism", "information")
addTagCodePoint("wheelchair", "yes")
addTagCodePoint("building", "entrance")
addTagCodePoint("public_transport", "stop_position")
addTagCodePoint("amenity", "fuel")
// addTagCodePoint("noexit", "yes")
addTagCodePoint("barrier", "bollard")
addTagCodePoint("amenity", "post_box")
addTagCodePoint("natural", "rock")
// addTagCodePoint("landuse", "forest")
addTagCodePoint("shelter", "yes")
addTagCodePoint("emergency", "fire_hydrant")
addTagCodePoint("public_transport", "platform")
addTagCodePoint("amenity", "grave_yard")
addTagCodePoint("shop", "convenience")
addTagCodePoint("power", "generator")
addTagCodePoint("shop", "supermarket")
addTagCodePoint("amenity", "bank")
addTagCodePoint("amenity", "fast_food")
addTagCodePoint("amenity", "cafe")
//
// most used tags for rels
//
addTagCodePoint("type", "multipolygon")
addTagCodePoint("type", "route")
// addTagCodePoint("boundary", "administrative")
addTagCodePoint("type", "restriction")
addTagCodePoint("type", "boundary")
addTagCodePoint("type", "site")
// addTagCodePoint("admin_level", "8")
addTagCodePoint("type", "associatedStreet")
// addTagCodePoint("natural", "water")
}