From 8e1da67b3d4221aa16469cba53c8097ddbe78cb8 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sat, 29 Sep 2018 02:47:19 +0300 Subject: [PATCH] Split ways between linestrings / polygons correctly (so one object cannot be a linestring and a polygon at the same time) --- mapping/mapping.go | 39 ++------------------------ mapping/matcher.go | 68 ++++++++++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 64 deletions(-) diff --git a/mapping/mapping.go b/mapping/mapping.go index 4f48658..7e58a93 100644 --- a/mapping/mapping.go +++ b/mapping/mapping.go @@ -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) { diff --git a/mapping/matcher.go b/mapping/matcher.go index 2c58446..346782c 100644 --- a/mapping/matcher.go +++ b/mapping/matcher.go @@ -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