2013-05-07 12:13:09 +04:00
|
|
|
package mapping
|
|
|
|
|
2013-05-17 18:28:16 +04:00
|
|
|
import (
|
2015-07-17 11:07:55 +03:00
|
|
|
"path"
|
|
|
|
"strings"
|
|
|
|
|
2014-08-04 17:19:35 +04:00
|
|
|
"github.com/omniscale/imposm3/element"
|
2013-05-17 18:28:16 +04:00
|
|
|
)
|
|
|
|
|
2014-06-18 19:18:44 +04:00
|
|
|
func (m *Mapping) NodeTagFilter() TagFilterer {
|
2014-06-19 13:51:15 +04:00
|
|
|
if m.Tags.LoadAll {
|
|
|
|
return newExcludeFilter(m.Tags.Exclude)
|
2014-06-18 19:18:44 +04:00
|
|
|
}
|
2014-04-30 18:33:07 +04:00
|
|
|
mappings := make(map[Key]map[Value][]DestTable)
|
2013-05-17 17:44:50 +04:00
|
|
|
m.mappings("point", mappings)
|
2014-04-30 18:33:07 +04:00
|
|
|
tags := make(map[Key]bool)
|
2013-05-17 17:44:50 +04:00
|
|
|
m.extraTags("point", tags)
|
|
|
|
return &TagFilter{mappings, tags}
|
|
|
|
}
|
2013-05-07 12:13:09 +04:00
|
|
|
|
2014-06-18 19:18:44 +04:00
|
|
|
func (m *Mapping) WayTagFilter() TagFilterer {
|
2014-06-19 13:51:15 +04:00
|
|
|
if m.Tags.LoadAll {
|
|
|
|
return newExcludeFilter(m.Tags.Exclude)
|
2014-06-18 19:18:44 +04:00
|
|
|
}
|
2014-04-30 18:33:07 +04:00
|
|
|
mappings := make(map[Key]map[Value][]DestTable)
|
2013-05-17 17:44:50 +04:00
|
|
|
m.mappings("linestring", mappings)
|
|
|
|
m.mappings("polygon", mappings)
|
2014-04-30 18:33:07 +04:00
|
|
|
tags := make(map[Key]bool)
|
2013-05-17 17:44:50 +04:00
|
|
|
m.extraTags("linestring", tags)
|
|
|
|
m.extraTags("polygon", tags)
|
|
|
|
return &TagFilter{mappings, tags}
|
|
|
|
}
|
2013-05-07 12:13:09 +04:00
|
|
|
|
2014-06-18 19:18:44 +04:00
|
|
|
func (m *Mapping) RelationTagFilter() TagFilterer {
|
2014-06-19 13:51:15 +04:00
|
|
|
if m.Tags.LoadAll {
|
|
|
|
return newExcludeFilter(m.Tags.Exclude)
|
2014-06-18 19:18:44 +04:00
|
|
|
}
|
2014-04-30 18:33:07 +04:00
|
|
|
mappings := make(map[Key]map[Value][]DestTable)
|
2013-05-17 17:44:50 +04:00
|
|
|
m.mappings("linestring", mappings)
|
|
|
|
m.mappings("polygon", mappings)
|
2014-04-30 18:33:07 +04:00
|
|
|
tags := make(map[Key]bool)
|
2013-05-17 17:44:50 +04:00
|
|
|
m.extraTags("linestring", tags)
|
|
|
|
m.extraTags("polygon", tags)
|
2013-05-22 17:26:00 +04:00
|
|
|
// do not filter out type tag
|
2014-04-30 18:33:07 +04:00
|
|
|
mappings["type"] = map[Value][]DestTable{
|
2013-05-27 13:24:22 +04:00
|
|
|
"multipolygon": []DestTable{},
|
|
|
|
"boundary": []DestTable{},
|
|
|
|
"land_area": []DestTable{},
|
2013-05-22 17:26:00 +04:00
|
|
|
}
|
2013-05-17 17:44:50 +04:00
|
|
|
return &RelationTagFilter{TagFilter{mappings, tags}}
|
|
|
|
}
|
|
|
|
|
|
|
|
type TagFilter struct {
|
2014-04-30 18:33:07 +04:00
|
|
|
mappings map[Key]map[Value][]DestTable
|
|
|
|
extraTags map[Key]bool
|
2013-05-17 17:44:50 +04:00
|
|
|
}
|
2013-05-07 12:13:09 +04:00
|
|
|
|
2013-05-17 17:44:50 +04:00
|
|
|
type RelationTagFilter struct {
|
|
|
|
TagFilter
|
|
|
|
}
|
|
|
|
|
2014-06-19 13:51:15 +04:00
|
|
|
type ExcludeFilter struct {
|
2015-07-17 11:07:55 +03:00
|
|
|
keys map[Key]struct{}
|
|
|
|
matches []string
|
2014-06-19 13:51:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func newExcludeFilter(tags []Key) *ExcludeFilter {
|
2015-07-17 11:07:55 +03:00
|
|
|
f := ExcludeFilter{
|
|
|
|
keys: make(map[Key]struct{}),
|
|
|
|
matches: make([]string, 0),
|
|
|
|
}
|
|
|
|
for _, t := range tags {
|
|
|
|
if strings.ContainsAny(string(t), "?*[") {
|
|
|
|
f.matches = append(f.matches, string(t))
|
|
|
|
} else {
|
|
|
|
f.keys[t] = struct{}{}
|
|
|
|
}
|
2014-06-19 13:51:15 +04:00
|
|
|
}
|
|
|
|
return &f
|
|
|
|
}
|
2014-06-18 19:18:44 +04:00
|
|
|
|
2014-06-19 13:51:15 +04:00
|
|
|
func (f *ExcludeFilter) Filter(tags *element.Tags) bool {
|
|
|
|
for k, _ := range *tags {
|
2015-07-17 11:07:55 +03:00
|
|
|
if _, ok := f.keys[Key(k)]; ok {
|
2014-06-19 13:51:15 +04:00
|
|
|
delete(*tags, k)
|
2015-07-17 11:07:55 +03:00
|
|
|
} else if f.matches != nil {
|
|
|
|
for _, exkey := range f.matches {
|
|
|
|
if ok, _ := path.Match(exkey, k); ok {
|
|
|
|
delete(*tags, k)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2014-06-19 13:51:15 +04:00
|
|
|
}
|
|
|
|
}
|
2014-06-18 19:18:44 +04:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
type TagFilterer interface {
|
|
|
|
Filter(tags *element.Tags) bool
|
|
|
|
}
|
|
|
|
|
2013-05-17 18:28:16 +04:00
|
|
|
func (f *TagFilter) Filter(tags *element.Tags) bool {
|
|
|
|
if tags == nil {
|
|
|
|
return false
|
|
|
|
}
|
2013-05-17 17:44:50 +04:00
|
|
|
foundMapping := false
|
2013-05-17 18:28:16 +04:00
|
|
|
for k, v := range *tags {
|
2014-04-30 18:33:07 +04:00
|
|
|
values, ok := f.mappings[Key(k)]
|
2013-05-17 17:44:50 +04:00
|
|
|
if ok {
|
|
|
|
if _, ok := values["__any__"]; ok {
|
|
|
|
foundMapping = true
|
|
|
|
continue
|
2014-04-30 18:33:07 +04:00
|
|
|
} else if _, ok := values[Value(v)]; ok {
|
2013-05-17 17:44:50 +04:00
|
|
|
foundMapping = true
|
|
|
|
continue
|
2014-04-30 18:33:07 +04:00
|
|
|
} else if _, ok := f.extraTags[Key(k)]; !ok {
|
2013-05-17 18:28:16 +04:00
|
|
|
delete(*tags, k)
|
2013-05-17 17:44:50 +04:00
|
|
|
}
|
2014-04-30 18:33:07 +04:00
|
|
|
} else if _, ok := f.extraTags[Key(k)]; !ok {
|
2013-05-17 18:28:16 +04:00
|
|
|
delete(*tags, k)
|
2013-05-17 17:44:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if foundMapping {
|
|
|
|
return true
|
|
|
|
} else {
|
2013-05-17 18:28:16 +04:00
|
|
|
*tags = nil
|
2013-05-17 17:44:50 +04:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2013-05-07 12:13:09 +04:00
|
|
|
|
2013-05-17 18:28:16 +04:00
|
|
|
func (f *RelationTagFilter) Filter(tags *element.Tags) bool {
|
|
|
|
if tags == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if t, ok := (*tags)["type"]; ok {
|
2013-05-17 17:44:50 +04:00
|
|
|
if t != "multipolygon" && t != "boundary" && t != "land_area" {
|
2013-05-17 18:28:16 +04:00
|
|
|
*tags = nil
|
2013-05-17 17:44:50 +04:00
|
|
|
return false
|
|
|
|
}
|
2013-05-27 10:19:22 +04:00
|
|
|
if t == "boundary" {
|
|
|
|
if _, ok := (*tags)["boundary"]; !ok {
|
|
|
|
// a lot of the boundary relations are not multipolygon
|
|
|
|
// only import with boundary tags (e.g. boundary=administrative)
|
|
|
|
*tags = nil
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2013-05-17 17:44:50 +04:00
|
|
|
} else {
|
2013-05-17 18:28:16 +04:00
|
|
|
*tags = nil
|
2013-05-17 17:44:50 +04:00
|
|
|
return false
|
2013-05-07 12:13:09 +04:00
|
|
|
}
|
2013-05-27 10:19:22 +04:00
|
|
|
tagCount := len(*tags)
|
2013-05-17 17:44:50 +04:00
|
|
|
f.TagFilter.Filter(tags)
|
2013-05-27 10:19:22 +04:00
|
|
|
|
|
|
|
// we removed tags...
|
|
|
|
if len(*tags) < tagCount {
|
|
|
|
expectedTags := 0
|
|
|
|
if _, ok := (*tags)["name"]; ok {
|
|
|
|
expectedTags += 1
|
|
|
|
}
|
|
|
|
if _, ok := (*tags)["type"]; ok {
|
|
|
|
expectedTags += 1
|
|
|
|
}
|
|
|
|
if len(*tags) == expectedTags {
|
|
|
|
// but no tags except name and type are left
|
|
|
|
// remove all, otherwise tags from longest
|
|
|
|
// way/ring would be used during MP building
|
|
|
|
*tags = nil
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2013-05-17 17:44:50 +04:00
|
|
|
// always return true here since we found a matching type
|
|
|
|
return true
|
2013-05-07 12:13:09 +04:00
|
|
|
}
|