refactoring of the mapping package
parent
81d818a0c4
commit
60a7d80993
|
@ -2,9 +2,7 @@ package mapping
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
|
||||||
"goposm/element"
|
"goposm/element"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,8 +30,25 @@ type Mapping struct {
|
||||||
Tables Tables `json:"tables"`
|
Tables Tables `json:"tables"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) Mappings() map[string][]string {
|
type ElementFilter func(elem element.OSMElem) bool
|
||||||
return t.Mapping
|
|
||||||
|
type TagTables map[string]map[string][]string
|
||||||
|
|
||||||
|
func NewMapping(filename string) (*Mapping, error) {
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
decoder := json.NewDecoder(f)
|
||||||
|
|
||||||
|
mapping := Mapping{}
|
||||||
|
err = decoder.Decode(&mapping)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping.prepare()
|
||||||
|
return &mapping, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) ExtraTags() map[string]bool {
|
func (t *Table) ExtraTags() map[string]bool {
|
||||||
|
@ -52,12 +67,12 @@ func (m *Mapping) prepare() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mapping) mappings(tableType string, mappings map[string]map[string][]string) {
|
func (m *Mapping) mappings(tableType string, mappings TagTables) {
|
||||||
for name, t := range m.Tables {
|
for name, t := range m.Tables {
|
||||||
if t.Type != tableType {
|
if t.Type != tableType {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for key, vals := range t.Mappings() {
|
for key, vals := range t.Mapping {
|
||||||
for _, v := range vals {
|
for _, v := range vals {
|
||||||
vals, ok := mappings[key]
|
vals, ok := mappings[key]
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -97,8 +112,8 @@ func (m *Mapping) extraTags(tableType string, tags map[string]bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mapping) elemFilters() map[string][]elemFilter {
|
func (m *Mapping) ElementFilters() map[string][]ElementFilter {
|
||||||
result := make(map[string][]elemFilter)
|
result := make(map[string][]ElementFilter)
|
||||||
for name, t := range m.Tables {
|
for name, t := range m.Tables {
|
||||||
if t.Filters == nil {
|
if t.Filters == nil {
|
||||||
continue
|
continue
|
||||||
|
@ -119,227 +134,3 @@ func (m *Mapping) elemFilters() map[string][]elemFilter {
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mapping) NodeTagFilter() *TagFilter {
|
|
||||||
mappings := make(map[string]map[string][]string)
|
|
||||||
m.mappings("point", mappings)
|
|
||||||
tags := make(map[string]bool)
|
|
||||||
m.extraTags("point", tags)
|
|
||||||
return &TagFilter{mappings, tags}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mapping) WayTagFilter() *TagFilter {
|
|
||||||
mappings := make(map[string]map[string][]string)
|
|
||||||
m.mappings("linestring", mappings)
|
|
||||||
m.mappings("polygon", mappings)
|
|
||||||
tags := make(map[string]bool)
|
|
||||||
m.extraTags("linestring", tags)
|
|
||||||
m.extraTags("polygon", tags)
|
|
||||||
return &TagFilter{mappings, tags}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mapping) RelationTagFilter() *RelationTagFilter {
|
|
||||||
mappings := make(map[string]map[string][]string)
|
|
||||||
m.mappings("linestring", mappings)
|
|
||||||
m.mappings("polygon", mappings)
|
|
||||||
tags := make(map[string]bool)
|
|
||||||
m.extraTags("linestring", tags)
|
|
||||||
m.extraTags("polygon", tags)
|
|
||||||
tags["type"] = true // do not filter out type tag
|
|
||||||
return &RelationTagFilter{TagFilter{mappings, tags}}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mapping) PointMatcher() *TagMatcher {
|
|
||||||
mappings := make(map[string]map[string][]string)
|
|
||||||
m.mappings("point", mappings)
|
|
||||||
filters := m.elemFilters()
|
|
||||||
return &TagMatcher{mappings, m.tables("point"), filters}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mapping) LineStringMatcher() *TagMatcher {
|
|
||||||
mappings := make(map[string]map[string][]string)
|
|
||||||
m.mappings("linestring", mappings)
|
|
||||||
filters := m.elemFilters()
|
|
||||||
return &TagMatcher{mappings, m.tables("linestring"), filters}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mapping) PolygonMatcher() *TagMatcher {
|
|
||||||
mappings := make(map[string]map[string][]string)
|
|
||||||
m.mappings("polygon", mappings)
|
|
||||||
filters := m.elemFilters()
|
|
||||||
return &TagMatcher{mappings, m.tables("polygon"), filters}
|
|
||||||
}
|
|
||||||
|
|
||||||
type TagFilter struct {
|
|
||||||
mappings map[string]map[string][]string
|
|
||||||
extraTags map[string]bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type RelationTagFilter struct {
|
|
||||||
TagFilter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *TagFilter) Filter(tags map[string]string) bool {
|
|
||||||
foundMapping := false
|
|
||||||
for k, v := range tags {
|
|
||||||
values, ok := f.mappings[k]
|
|
||||||
if ok {
|
|
||||||
if _, ok := values["__any__"]; ok {
|
|
||||||
foundMapping = true
|
|
||||||
continue
|
|
||||||
} else if _, ok := values[v]; ok {
|
|
||||||
foundMapping = true
|
|
||||||
continue
|
|
||||||
} else if _, ok := f.extraTags[k]; !ok {
|
|
||||||
delete(tags, k)
|
|
||||||
}
|
|
||||||
} else if _, ok := f.extraTags[k]; !ok {
|
|
||||||
delete(tags, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if foundMapping {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *RelationTagFilter) Filter(tags map[string]string) bool {
|
|
||||||
if t, ok := tags["type"]; ok {
|
|
||||||
if t != "multipolygon" && t != "boundary" && t != "land_area" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
f.TagFilter.Filter(tags)
|
|
||||||
// always return true here since we found a matching type
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type elemFilter func(elem element.OSMElem) bool
|
|
||||||
|
|
||||||
type TagMatcher struct {
|
|
||||||
mappings map[string]map[string][]string
|
|
||||||
tables map[string]*TableFields
|
|
||||||
filters map[string][]elemFilter
|
|
||||||
}
|
|
||||||
|
|
||||||
type Match struct {
|
|
||||||
Key string
|
|
||||||
Value string
|
|
||||||
Table string
|
|
||||||
tableFields *TableFields
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Match) Row(elem *element.OSMElem) []interface{} {
|
|
||||||
return m.tableFields.MakeRow(elem, *m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tagMatcher *TagMatcher) Match(elem element.OSMElem) []Match {
|
|
||||||
tables := make(map[string]Match)
|
|
||||||
|
|
||||||
for k, v := range elem.Tags {
|
|
||||||
values, ok := tagMatcher.mappings[k]
|
|
||||||
if ok {
|
|
||||||
if tbls, ok := values["__any__"]; ok {
|
|
||||||
for _, t := range tbls {
|
|
||||||
tables[t] = Match{k, v, t, tagMatcher.tables[t]}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
} else if tbls, ok := values[v]; ok {
|
|
||||||
for _, t := range tbls {
|
|
||||||
tables[t] = Match{k, v, t, tagMatcher.tables[t]}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var matches []Match
|
|
||||||
for t, match := range tables {
|
|
||||||
filters, ok := tagMatcher.filters[t]
|
|
||||||
filteredOut := false
|
|
||||||
if ok {
|
|
||||||
for _, filter := range filters {
|
|
||||||
if !filter(elem) {
|
|
||||||
filteredOut = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !filteredOut {
|
|
||||||
matches = append(matches, match)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matches
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMapping(filename string) (*Mapping, error) {
|
|
||||||
f, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
decoder := json.NewDecoder(f)
|
|
||||||
|
|
||||||
mapping := Mapping{}
|
|
||||||
err = decoder.Decode(&mapping)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
mapping.prepare()
|
|
||||||
return &mapping, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// data := `
|
|
||||||
// {
|
|
||||||
// "tables": {
|
|
||||||
// "roads": {
|
|
||||||
// "mapping": {
|
|
||||||
// "highway": [
|
|
||||||
// "motorway",
|
|
||||||
// "motorway_link",
|
|
||||||
// "trunk",
|
|
||||||
// "trunk_link"
|
|
||||||
// ]
|
|
||||||
// },
|
|
||||||
// "fields": {
|
|
||||||
// "tunnel": {"type": "bool", "key": "tunnel"},
|
|
||||||
// "bridge": {"type": "bool"},
|
|
||||||
// "oneway": {"type": "direction"},
|
|
||||||
// "ref": {"type": "string"},
|
|
||||||
// "z_order": {"type": "wayzorder", "key": "NONE"}
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// `
|
|
||||||
|
|
||||||
// t := Table{map[string][]string{"highway": {"motorway", "trunk"}}}
|
|
||||||
// b, err := json.Marshal(t)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Fatal(err)
|
|
||||||
// }
|
|
||||||
// log.Println(string(b))
|
|
||||||
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
mapping, err := NewMapping(flag.Arg(0))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
// log.Println(mapping.Mappings("point"))
|
|
||||||
// log.Println(mapping.ExtraTags("point"))
|
|
||||||
log.Println(mapping.NodeTagFilter())
|
|
||||||
log.Println(mapping.WayTagFilter())
|
|
||||||
log.Println(mapping.RelationTagFilter())
|
|
||||||
|
|
||||||
// log.Println(mapping)
|
|
||||||
|
|
||||||
// b, err := json.MarshalIndent(mapping, "", " ")
|
|
||||||
// if err != nil {
|
|
||||||
// log.Fatal(err)
|
|
||||||
// }
|
|
||||||
// log.Println(string(b))
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,6 +6,23 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var AvailableFieldTypes map[string]FieldType
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
AvailableFieldTypes = map[string]FieldType{
|
||||||
|
"bool": {"bool", "bool", Bool},
|
||||||
|
"id": {"id", "int64", Id},
|
||||||
|
"string": {"string", "string", String},
|
||||||
|
"direction": {"direction", "int8", Direction},
|
||||||
|
"integer": {"integer", "int32", Integer},
|
||||||
|
"mapping_key": {"mapping_key", "string", Key},
|
||||||
|
"mapping_value": {"mapping_value", "string", Value},
|
||||||
|
"geometry": {"geometry", "geometry", Geometry},
|
||||||
|
"wayzorder": {"wayzorder", "int32", WayZOrder},
|
||||||
|
"pseudoarea": {"pseudoarea", "float32", PseudoArea},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type MakeValue func(string, *element.OSMElem, Match) interface{}
|
type MakeValue func(string, *element.OSMElem, Match) interface{}
|
||||||
|
|
||||||
type FieldSpec struct {
|
type FieldSpec struct {
|
||||||
|
@ -39,7 +56,7 @@ func (t *Table) TableFields() *TableFields {
|
||||||
field := FieldSpec{}
|
field := FieldSpec{}
|
||||||
field.Name = mappingField.Name
|
field.Name = mappingField.Name
|
||||||
|
|
||||||
fieldType, ok := FieldTypes[mappingField.Type]
|
fieldType, ok := AvailableFieldTypes[mappingField.Type]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Println("unhandled type:", mappingField.Type)
|
log.Println("unhandled type:", mappingField.Type)
|
||||||
} else {
|
} else {
|
||||||
|
@ -56,23 +73,6 @@ type FieldType struct {
|
||||||
Func MakeValue
|
Func MakeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
var FieldTypes map[string]FieldType
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
FieldTypes = map[string]FieldType{
|
|
||||||
"bool": {"bool", "bool", Bool},
|
|
||||||
"id": {"id", "int64", Id},
|
|
||||||
"string": {"string", "string", String},
|
|
||||||
"direction": {"direction", "int8", Direction},
|
|
||||||
"integer": {"integer", "int32", Integer},
|
|
||||||
"mapping_key": {"mapping_key", "string", Key},
|
|
||||||
"mapping_value": {"mapping_value", "string", Value},
|
|
||||||
"geometry": {"geometry", "geometry", Geometry},
|
|
||||||
"wayzorder": {"wayzorder", "int32", WayZOrder},
|
|
||||||
"pseudoarea": {"pseudoarea", "float32", PseudoArea},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Bool(val string, elem *element.OSMElem, match Match) interface{} {
|
func Bool(val string, elem *element.OSMElem, match Match) interface{} {
|
||||||
if val == "" || val == "0" || val == "false" || val == "no" {
|
if val == "" || val == "0" || val == "false" || val == "no" {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -1,287 +1,77 @@
|
||||||
package mapping
|
package mapping
|
||||||
|
|
||||||
type TagMap map[string]map[string]bool
|
func (m *Mapping) NodeTagFilter() *TagFilter {
|
||||||
|
mappings := make(map[string]map[string][]string)
|
||||||
|
m.mappings("point", mappings)
|
||||||
|
tags := make(map[string]bool)
|
||||||
|
m.extraTags("point", tags)
|
||||||
|
return &TagFilter{mappings, tags}
|
||||||
|
}
|
||||||
|
|
||||||
var PointTags TagMap
|
func (m *Mapping) WayTagFilter() *TagFilter {
|
||||||
var WayTags TagMap
|
mappings := make(map[string]map[string][]string)
|
||||||
var RelationTags TagMap
|
m.mappings("linestring", mappings)
|
||||||
|
m.mappings("polygon", mappings)
|
||||||
|
tags := make(map[string]bool)
|
||||||
|
m.extraTags("linestring", tags)
|
||||||
|
m.extraTags("polygon", tags)
|
||||||
|
return &TagFilter{mappings, tags}
|
||||||
|
}
|
||||||
|
|
||||||
// default mapping created from imposm defaultmapping.py
|
func (m *Mapping) RelationTagFilter() *RelationTagFilter {
|
||||||
// TODO make configurable
|
mappings := make(map[string]map[string][]string)
|
||||||
func init() {
|
m.mappings("linestring", mappings)
|
||||||
PointTags = TagMap{
|
m.mappings("polygon", mappings)
|
||||||
"aeroway": map[string]bool{
|
tags := make(map[string]bool)
|
||||||
"aerodome": true,
|
m.extraTags("linestring", tags)
|
||||||
"gate": true,
|
m.extraTags("polygon", tags)
|
||||||
"helipad": true,
|
tags["type"] = true // do not filter out type tag
|
||||||
"terminal": true,
|
return &RelationTagFilter{TagFilter{mappings, tags}}
|
||||||
},
|
}
|
||||||
"amenity": map[string]bool{
|
|
||||||
"fire_station": true,
|
type TagFilter struct {
|
||||||
"fuel": true,
|
mappings map[string]map[string][]string
|
||||||
"hospital": true,
|
extraTags map[string]bool
|
||||||
"library": true,
|
}
|
||||||
"police": true,
|
|
||||||
"school": true,
|
type RelationTagFilter struct {
|
||||||
"townhall": true,
|
TagFilter
|
||||||
"university": true,
|
}
|
||||||
},
|
|
||||||
"highway": map[string]bool{
|
func (f *TagFilter) Filter(tags map[string]string) bool {
|
||||||
"bus_stop": true,
|
foundMapping := false
|
||||||
"motorway_junction": true,
|
for k, v := range tags {
|
||||||
"turning_circle": true,
|
values, ok := f.mappings[k]
|
||||||
},
|
if ok {
|
||||||
"name": map[string]bool{
|
if _, ok := values["__any__"]; ok {
|
||||||
"__any__": true,
|
foundMapping = true
|
||||||
},
|
continue
|
||||||
"place": map[string]bool{
|
} else if _, ok := values[v]; ok {
|
||||||
"city": true,
|
foundMapping = true
|
||||||
"country": true,
|
continue
|
||||||
"county": true,
|
} else if _, ok := f.extraTags[k]; !ok {
|
||||||
"hamlet": true,
|
delete(tags, k)
|
||||||
"locality": true,
|
}
|
||||||
"region": true,
|
} else if _, ok := f.extraTags[k]; !ok {
|
||||||
"state": true,
|
delete(tags, k)
|
||||||
"suburb": true,
|
}
|
||||||
"town": true,
|
|
||||||
"village": true,
|
|
||||||
},
|
|
||||||
"population": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"railway": map[string]bool{
|
|
||||||
"crossing": true,
|
|
||||||
"halt": true,
|
|
||||||
"level_crossing": true,
|
|
||||||
"station": true,
|
|
||||||
"subway_entrance": true,
|
|
||||||
"tram_stop": true,
|
|
||||||
},
|
|
||||||
"ref": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
WayTags = map[string]map[string]bool{
|
if foundMapping {
|
||||||
"admin_level": map[string]bool{
|
return true
|
||||||
"__any__": true,
|
} else {
|
||||||
},
|
return false
|
||||||
"aeroway": map[string]bool{
|
|
||||||
"aerodrome": true,
|
|
||||||
"apron": true,
|
|
||||||
"helipad": true,
|
|
||||||
"runway": true,
|
|
||||||
"taxiway": true,
|
|
||||||
"terminal": true,
|
|
||||||
},
|
|
||||||
"amenity": map[string]bool{
|
|
||||||
"cinema": true,
|
|
||||||
"college": true,
|
|
||||||
"fuel": true,
|
|
||||||
"hospital": true,
|
|
||||||
"library": true,
|
|
||||||
"parking": true,
|
|
||||||
"place_of_worship": true,
|
|
||||||
"school": true,
|
|
||||||
"theatre": true,
|
|
||||||
"university": true,
|
|
||||||
},
|
|
||||||
"area": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"boundary": map[string]bool{
|
|
||||||
"administrative": true,
|
|
||||||
},
|
|
||||||
"bridge": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"building": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"highway": map[string]bool{
|
|
||||||
"bridleway": true,
|
|
||||||
"cycleway": true,
|
|
||||||
"footway": true,
|
|
||||||
"living_street": true,
|
|
||||||
"motorway": true,
|
|
||||||
"motorway_link": true,
|
|
||||||
"path": true,
|
|
||||||
"pedestrian": true,
|
|
||||||
"primary": true,
|
|
||||||
"primary_link": true,
|
|
||||||
"residential": true,
|
|
||||||
"road": true,
|
|
||||||
"secondary": true,
|
|
||||||
"secondary_link": true,
|
|
||||||
"service": true,
|
|
||||||
"steps": true,
|
|
||||||
"tertiary": true,
|
|
||||||
"track": true,
|
|
||||||
"trunk": true,
|
|
||||||
"trunk_link": true,
|
|
||||||
"unclassified": true,
|
|
||||||
},
|
|
||||||
"landuse": map[string]bool{
|
|
||||||
"allotments": true,
|
|
||||||
"basin": true,
|
|
||||||
"cemetery": true,
|
|
||||||
"commercial": true,
|
|
||||||
"farm": true,
|
|
||||||
"farmland": true,
|
|
||||||
"farmyard": true,
|
|
||||||
"forest": true,
|
|
||||||
"grass": true,
|
|
||||||
"industrial": true,
|
|
||||||
"meadow": true,
|
|
||||||
"park": true,
|
|
||||||
"quarry": true,
|
|
||||||
"railway": true,
|
|
||||||
"recreation_ground": true,
|
|
||||||
"reservoir": true,
|
|
||||||
"residential": true,
|
|
||||||
"retail": true,
|
|
||||||
"village_green": true,
|
|
||||||
"wood": true,
|
|
||||||
},
|
|
||||||
"leisure": map[string]bool{
|
|
||||||
"common": true,
|
|
||||||
"garden": true,
|
|
||||||
"golf_course": true,
|
|
||||||
"nature_reserve": true,
|
|
||||||
"park": true,
|
|
||||||
"pitch": true,
|
|
||||||
"playground": true,
|
|
||||||
"sports_centre": true,
|
|
||||||
"stadium": true,
|
|
||||||
},
|
|
||||||
"name": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"natural": map[string]bool{
|
|
||||||
"land": true,
|
|
||||||
"scrub": true,
|
|
||||||
"water": true,
|
|
||||||
"wood": true,
|
|
||||||
},
|
|
||||||
"oneway": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"railway": map[string]bool{
|
|
||||||
"funicular": true,
|
|
||||||
"light_rail": true,
|
|
||||||
"monorail": true,
|
|
||||||
"narrow_gauge": true,
|
|
||||||
"preserved": true,
|
|
||||||
"rail": true,
|
|
||||||
"station": true,
|
|
||||||
"subway": true,
|
|
||||||
"tram": true,
|
|
||||||
},
|
|
||||||
"ref": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"tunnel": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"waterway": map[string]bool{
|
|
||||||
"canal": true,
|
|
||||||
"drain": true,
|
|
||||||
"river": true,
|
|
||||||
"riverbank": true,
|
|
||||||
"stream": true,
|
|
||||||
}}
|
|
||||||
|
|
||||||
RelationTags = map[string]map[string]bool{
|
|
||||||
|
|
||||||
"admin_level": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"aeroway": map[string]bool{
|
|
||||||
"aerodrome": true,
|
|
||||||
"apron": true,
|
|
||||||
"helipad": true,
|
|
||||||
"runway": true,
|
|
||||||
"taxiway": true,
|
|
||||||
"terminal": true,
|
|
||||||
},
|
|
||||||
"amenity": map[string]bool{
|
|
||||||
"cinema": true,
|
|
||||||
"college": true,
|
|
||||||
"fuel": true,
|
|
||||||
"hospital": true,
|
|
||||||
"library": true,
|
|
||||||
"parking": true,
|
|
||||||
"place_of_worship": true,
|
|
||||||
"school": true,
|
|
||||||
"theatre": true,
|
|
||||||
"university": true,
|
|
||||||
},
|
|
||||||
"area": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"boundary": map[string]bool{
|
|
||||||
"administrative": true,
|
|
||||||
},
|
|
||||||
"bridge": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"building": map[string]bool{
|
|
||||||
"__any__": true,
|
|
||||||
},
|
|
||||||
"highway": map[string]bool{
|
|
||||||
"bridleway": true,
|
|
||||||
"cycleway": true,
|
|
||||||
"footway": true,
|
|
||||||
"living_street": true,
|
|
||||||
"motorway": true,
|
|
||||||
"motorway_link": true,
|
|
||||||
"path": true,
|
|
||||||
"pedestrian": true,
|
|
||||||
"primary": true,
|
|
||||||
"primary_link": true,
|
|
||||||
"residential": true,
|
|
||||||
"road": true,
|
|
||||||
"secondary": true,
|
|
||||||
"secondary_link": true,
|
|
||||||
"service": true,
|
|
||||||
"steps": true,
|
|
||||||
"tertiary": true,
|
|
||||||
"track": true,
|
|
||||||
"trunk": true,
|
|
||||||
"trunk_link": true,
|
|
||||||
"unclassified": true,
|
|
||||||
},
|
|
||||||
"landuse": map[string]bool{
|
|
||||||
"allotments": true,
|
|
||||||
"basin": true,
|
|
||||||
"cemetery": true,
|
|
||||||
"commercial": true,
|
|
||||||
"farm": true,
|
|
||||||
"farmland": true,
|
|
||||||
"farmyard": true,
|
|
||||||
"forest": true,
|
|
||||||
"grass": true,
|
|
||||||
"industrial": true,
|
|
||||||
"meadow": true,
|
|
||||||
"park": true,
|
|
||||||
"quarry": true,
|
|
||||||
"railway": true,
|
|
||||||
"recreation_ground": true,
|
|
||||||
"reservoir": true,
|
|
||||||
"residential": true,
|
|
||||||
"retail": true,
|
|
||||||
"village_green": true,
|
|
||||||
"wood": true,
|
|
||||||
},
|
|
||||||
"leisure": map[string]bool{
|
|
||||||
"common": true,
|
|
||||||
"garden": true,
|
|
||||||
"golf_course": true,
|
|
||||||
"nature_reserve": true,
|
|
||||||
"park": true,
|
|
||||||
"pitch": true,
|
|
||||||
"playground": true,
|
|
||||||
"sports_centre": true,
|
|
||||||
"stadium": true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *RelationTagFilter) Filter(tags map[string]string) bool {
|
||||||
|
if t, ok := tags["type"]; ok {
|
||||||
|
if t != "multipolygon" && t != "boundary" && t != "land_area" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
f.TagFilter.Filter(tags)
|
||||||
|
// always return true here since we found a matching type
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package mapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"goposm/element"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *Mapping) PointMatcher() *TagMatcher {
|
||||||
|
mappings := make(TagTables)
|
||||||
|
m.mappings("point", mappings)
|
||||||
|
filters := m.ElementFilters()
|
||||||
|
return &TagMatcher{mappings, m.tables("point"), filters}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mapping) LineStringMatcher() *TagMatcher {
|
||||||
|
mappings := make(TagTables)
|
||||||
|
m.mappings("linestring", mappings)
|
||||||
|
filters := m.ElementFilters()
|
||||||
|
return &TagMatcher{mappings, m.tables("linestring"), filters}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mapping) PolygonMatcher() *TagMatcher {
|
||||||
|
mappings := make(TagTables)
|
||||||
|
m.mappings("polygon", mappings)
|
||||||
|
filters := m.ElementFilters()
|
||||||
|
return &TagMatcher{mappings, m.tables("polygon"), filters}
|
||||||
|
}
|
||||||
|
|
||||||
|
type TagMatcher struct {
|
||||||
|
mappings TagTables
|
||||||
|
tables map[string]*TableFields
|
||||||
|
filters map[string][]ElementFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type Match struct {
|
||||||
|
Key string
|
||||||
|
Value string
|
||||||
|
Table string
|
||||||
|
tableFields *TableFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Match) Row(elem *element.OSMElem) []interface{} {
|
||||||
|
return m.tableFields.MakeRow(elem, *m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tagMatcher *TagMatcher) Match(elem element.OSMElem) []Match {
|
||||||
|
tables := make(map[string]Match)
|
||||||
|
|
||||||
|
for k, v := range elem.Tags {
|
||||||
|
values, ok := tagMatcher.mappings[k]
|
||||||
|
if ok {
|
||||||
|
if tbls, ok := values["__any__"]; ok {
|
||||||
|
for _, t := range tbls {
|
||||||
|
tables[t] = Match{k, v, t, tagMatcher.tables[t]}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
} else if tbls, ok := values[v]; ok {
|
||||||
|
for _, t := range tbls {
|
||||||
|
tables[t] = Match{k, v, t, tagMatcher.tables[t]}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var matches []Match
|
||||||
|
for t, match := range tables {
|
||||||
|
filters, ok := tagMatcher.filters[t]
|
||||||
|
filteredOut := false
|
||||||
|
if ok {
|
||||||
|
for _, filter := range filters {
|
||||||
|
if !filter(elem) {
|
||||||
|
filteredOut = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !filteredOut {
|
||||||
|
matches = append(matches, match)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
}
|
Loading…
Reference in New Issue