Split ways between linestrings / polygons correctly (so one object cannot be a linestring and a polygon at the same time)

master
Vitaliy Filippov 2018-09-29 02:47:19 +03:00
parent 013e395f5c
commit 8e1da67b3d
2 changed files with 43 additions and 64 deletions

View File

@ -275,7 +275,7 @@ type elementFilter func(tags element.Tags, key Key, closed bool) bool
type tableElementFilters map[string][]elementFilter
func (m *Mapping) addTypedFilters(tableType TableType, filters tableElementFilters) {
func (m *Mapping) getAreaTags() (map[Key]struct{}, map[Key]struct{}) {
var areaTags map[Key]struct{}
var linearTags map[Key]struct{}
if m.Conf.Areas.AreaTags != nil {
@ -290,42 +290,7 @@ func (m *Mapping) addTypedFilters(tableType TableType, filters tableElementFilte
linearTags[Key(tag)] = struct{}{}
}
}
for name, t := range m.Conf.Tables {
if TableType(t.Type) != GeometryTable && TableType(t.Type) != tableType {
continue
}
if TableType(t.Type) == LineStringTable && areaTags != nil {
f := func(tags element.Tags, key Key, closed bool) bool {
if closed {
if tags["area"] == "yes" {
return false
}
if tags["area"] != "no" {
if _, ok := areaTags[key]; ok {
return false
}
}
}
return true
}
filters[name] = append(filters[name], f)
}
if TableType(t.Type) == PolygonTable && linearTags != nil {
f := func(tags element.Tags, key Key, closed bool) bool {
if closed && tags["area"] == "no" {
return false
}
if tags["area"] != "yes" {
if _, ok := linearTags[key]; ok {
return false
}
}
return true
}
filters[name] = append(filters[name], f)
}
}
return areaTags, linearTags
}
func (m *Mapping) addRelationFilters(tableType TableType, filters tableElementFilters) {

View File

@ -10,13 +10,11 @@ func (m *Mapping) pointMatcher() (NodeMatcher, error) {
m.mappings(PointTable, mappings)
filters := make(tableElementFilters)
m.addFilters(filters)
m.addTypedFilters(PointTable, filters)
tables, err := m.tables(PointTable)
return &tagMatcher{
mappings: mappings,
filters: filters,
tables: tables,
matchAreas: false,
}, err
}
@ -25,12 +23,15 @@ func (m *Mapping) lineStringMatcher() (WayMatcher, error) {
m.mappings(LineStringTable, mappings)
filters := make(tableElementFilters)
m.addFilters(filters)
m.addTypedFilters(LineStringTable, filters)
areaTags, linearTags := m.getAreaTags()
tables, err := m.tables(LineStringTable)
return &tagMatcher{
mappings: mappings,
filters: filters,
tables: tables,
areaTags: areaTags,
linearTags: linearTags,
matchLines: true,
matchAreas: false,
}, err
}
@ -40,7 +41,7 @@ func (m *Mapping) polygonMatcher() (RelWayMatcher, error) {
m.mappings(PolygonTable, mappings)
filters := make(tableElementFilters)
m.addFilters(filters)
m.addTypedFilters(PolygonTable, filters)
areaTags, linearTags := m.getAreaTags()
relFilters := make(tableElementFilters)
m.addRelationFilters(PolygonTable, relFilters)
tables, err := m.tables(PolygonTable)
@ -49,6 +50,9 @@ func (m *Mapping) polygonMatcher() (RelWayMatcher, error) {
filters: filters,
tables: tables,
relFilters: relFilters,
areaTags: areaTags,
linearTags: linearTags,
matchLines: false,
matchAreas: true,
}, err
}
@ -58,8 +62,6 @@ func (m *Mapping) relationMatcher() (RelationMatcher, error) {
m.mappings(RelationTable, mappings)
filters := make(tableElementFilters)
m.addFilters(filters)
m.addTypedFilters(PolygonTable, filters)
m.addTypedFilters(RelationTable, filters)
relFilters := make(tableElementFilters)
m.addRelationFilters(RelationTable, relFilters)
tables, err := m.tables(RelationTable)
@ -68,7 +70,6 @@ func (m *Mapping) relationMatcher() (RelationMatcher, error) {
filters: filters,
tables: tables,
relFilters: relFilters,
matchAreas: true,
}, err
}
@ -77,7 +78,6 @@ func (m *Mapping) relationMemberMatcher() (RelationMatcher, error) {
m.mappings(RelationMemberTable, mappings)
filters := make(tableElementFilters)
m.addFilters(filters)
m.addTypedFilters(RelationMemberTable, filters)
relFilters := make(tableElementFilters)
m.addRelationFilters(RelationMemberTable, relFilters)
tables, err := m.tables(RelationMemberTable)
@ -86,7 +86,6 @@ func (m *Mapping) relationMemberMatcher() (RelationMatcher, error) {
filters: filters,
tables: tables,
relFilters: relFilters,
matchAreas: true,
}, err
}
@ -127,6 +126,9 @@ type tagMatcher struct {
tables map[string]*rowBuilder
filters tableElementFilters
relFilters tableElementFilters
areaTags map[Key]struct{}
linearTags map[Key]struct{}
matchLines bool
matchAreas bool
}
@ -135,23 +137,7 @@ func (tm *tagMatcher) MatchNode(node *element.Node) []Match {
}
func (tm *tagMatcher) MatchWay(way *element.Way) []Match {
if tm.matchAreas { // match way as polygon
if way.IsClosed() {
if way.Tags["area"] == "no" {
return nil
}
return tm.match(way.Tags, true, false)
}
} else { // match way as linestring
if way.IsClosed() {
if way.Tags["area"] == "yes" {
return nil
}
return tm.match(way.Tags, true, false)
}
return tm.match(way.Tags, false, false)
}
return nil
return tm.match(way.Tags, way.IsClosed(), false)
}
func (tm *tagMatcher) MatchRelation(rel *element.Relation) []Match {
@ -205,7 +191,35 @@ func (tm *tagMatcher) match(tags element.Tags, closed bool, relation bool) []Mat
for t, match := range tables {
filters, ok := tm.filters[t.Name]
filteredOut := false
if ok {
if !relation && (tm.matchLines || tm.matchAreas) {
if !closed {
// open way is always a linestring
filteredOut = tm.matchLines == false
} else {
// allow to include closed ways as linestrings if explicitly marked
// default -> area
// area=no or linear tags -> line
// area=yes or area tags -> area
filteredOut = tm.matchAreas && tags["area"] == "no" || !tm.matchAreas && tags["area"] != "no"
for k, _ := range tm.linearTags {
if _, ok := tags[string(k)]; ok {
filteredOut = tm.matchAreas
break
}
}
// but area=yes or area tag means it shouldn't be a linestring
if tags["area"] == "yes" {
filteredOut = tm.matchAreas
}
for k, _ := range tm.areaTags {
if _, ok := tags[string(k)]; ok {
filteredOut = !tm.matchAreas
break
}
}
}
}
if ok && !filteredOut {
for _, filter := range filters {
if !filter(tags, Key(match.Key), closed) {
filteredOut = true