refactoring of the mapping package
parent
81d818a0c4
commit
60a7d80993
|
@ -2,9 +2,7 @@ package mapping
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"goposm/element"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
@ -32,8 +30,25 @@ type Mapping struct {
|
|||
Tables Tables `json:"tables"`
|
||||
}
|
||||
|
||||
func (t *Table) Mappings() map[string][]string {
|
||||
return t.Mapping
|
||||
type ElementFilter func(elem element.OSMElem) bool
|
||||
|
||||
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 {
|
||||
|
@ -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 {
|
||||
if t.Type != tableType {
|
||||
continue
|
||||
}
|
||||
for key, vals := range t.Mappings() {
|
||||
for key, vals := range t.Mapping {
|
||||
for _, v := range vals {
|
||||
vals, ok := mappings[key]
|
||||
if ok {
|
||||
|
@ -97,8 +112,8 @@ func (m *Mapping) extraTags(tableType string, tags map[string]bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func (m *Mapping) elemFilters() map[string][]elemFilter {
|
||||
result := make(map[string][]elemFilter)
|
||||
func (m *Mapping) ElementFilters() map[string][]ElementFilter {
|
||||
result := make(map[string][]ElementFilter)
|
||||
for name, t := range m.Tables {
|
||||
if t.Filters == nil {
|
||||
continue
|
||||
|
@ -119,227 +134,3 @@ func (m *Mapping) elemFilters() map[string][]elemFilter {
|
|||
}
|
||||
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"
|
||||
)
|
||||
|
||||
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 FieldSpec struct {
|
||||
|
@ -39,7 +56,7 @@ func (t *Table) TableFields() *TableFields {
|
|||
field := FieldSpec{}
|
||||
field.Name = mappingField.Name
|
||||
|
||||
fieldType, ok := FieldTypes[mappingField.Type]
|
||||
fieldType, ok := AvailableFieldTypes[mappingField.Type]
|
||||
if !ok {
|
||||
log.Println("unhandled type:", mappingField.Type)
|
||||
} else {
|
||||
|
@ -56,23 +73,6 @@ type FieldType struct {
|
|||
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{} {
|
||||
if val == "" || val == "0" || val == "false" || val == "no" {
|
||||
return false
|
||||
|
|
|
@ -1,287 +1,77 @@
|
|||
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
|
||||
var WayTags TagMap
|
||||
var RelationTags TagMap
|
||||
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}
|
||||
}
|
||||
|
||||
// default mapping created from imposm defaultmapping.py
|
||||
// TODO make configurable
|
||||
func init() {
|
||||
PointTags = TagMap{
|
||||
"aeroway": map[string]bool{
|
||||
"aerodome": true,
|
||||
"gate": true,
|
||||
"helipad": true,
|
||||
"terminal": true,
|
||||
},
|
||||
"amenity": map[string]bool{
|
||||
"fire_station": true,
|
||||
"fuel": true,
|
||||
"hospital": true,
|
||||
"library": true,
|
||||
"police": true,
|
||||
"school": true,
|
||||
"townhall": true,
|
||||
"university": true,
|
||||
},
|
||||
"highway": map[string]bool{
|
||||
"bus_stop": true,
|
||||
"motorway_junction": true,
|
||||
"turning_circle": true,
|
||||
},
|
||||
"name": map[string]bool{
|
||||
"__any__": true,
|
||||
},
|
||||
"place": map[string]bool{
|
||||
"city": true,
|
||||
"country": true,
|
||||
"county": true,
|
||||
"hamlet": true,
|
||||
"locality": true,
|
||||
"region": true,
|
||||
"state": true,
|
||||
"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,
|
||||
},
|
||||
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}}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
WayTags = 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,
|
||||
},
|
||||
"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,
|
||||
},
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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