refactored filtering of inserted_ways

master
Oliver Tonnhofer 2013-12-16 16:54:42 +01:00
parent 3affe43808
commit eb216b4392
6 changed files with 290 additions and 97 deletions

View File

@ -40,9 +40,9 @@ type Inserter interface {
InsertPoint(element.OSMElem, interface{})
InsertLineString(element.OSMElem, interface{})
InsertPolygon(element.OSMElem, interface{})
// MatchEquals returns true if two interface{}s from ProbeXxx
// share the same destination.
MatchEquals(interface{}, interface{}) bool
// FilterRelationPolygons returns a slice of all members that are already
// imported with a relation with tags.
FilterRelationPolygons(element.Tags, []element.Member) []element.Member
}
type Deployer interface {
@ -102,18 +102,18 @@ func Open(conf Config, m *mapping.Mapping) (DB, error) {
// nullDb is a dummy database that imports into /dev/null
type nullDb struct{}
func (n *nullDb) Init() error { return nil }
func (n *nullDb) Begin() error { return nil }
func (n *nullDb) End() error { return nil }
func (n *nullDb) Close() error { return nil }
func (n *nullDb) Abort() error { return nil }
func (n *nullDb) InsertPoint(element.OSMElem, interface{}) {}
func (n *nullDb) InsertLineString(element.OSMElem, interface{}) {}
func (n *nullDb) InsertPolygon(element.OSMElem, interface{}) {}
func (n *nullDb) ProbePoint(element.OSMElem) (bool, interface{}) { return true, nil }
func (n *nullDb) ProbeLineString(element.OSMElem) (bool, interface{}) { return true, nil }
func (n *nullDb) ProbePolygon(element.OSMElem) (bool, interface{}) { return true, nil }
func (n *nullDb) MatchEquals(interface{}, interface{}) bool { return false }
func (n *nullDb) Init() error { return nil }
func (n *nullDb) Begin() error { return nil }
func (n *nullDb) End() error { return nil }
func (n *nullDb) Close() error { return nil }
func (n *nullDb) Abort() error { return nil }
func (n *nullDb) InsertPoint(element.OSMElem, interface{}) {}
func (n *nullDb) InsertLineString(element.OSMElem, interface{}) {}
func (n *nullDb) InsertPolygon(element.OSMElem, interface{}) {}
func (n *nullDb) ProbePoint(element.OSMElem) (bool, interface{}) { return true, nil }
func (n *nullDb) ProbeLineString(element.OSMElem) (bool, interface{}) { return true, nil }
func (n *nullDb) ProbePolygon(element.OSMElem) (bool, interface{}) { return true, nil }
func (n *nullDb) FilterRelationPolygons(element.Tags, []element.Member) []element.Member { return nil }
func newNullDb(conf Config, m *mapping.Mapping) (DB, error) {
return &nullDb{}, nil

View File

@ -476,12 +476,22 @@ func (pg *PostGIS) ProbePolygon(elem element.OSMElem) (bool, interface{}) {
return false, nil
}
func (pq *PostGIS) MatchEquals(a interface{}, b interface{}) bool {
matchesA, okA := a.([]mapping.Match)
matchesB, okB := b.([]mapping.Match)
if !okA && !okB {
return false
func (pg *PostGIS) FilterRelationPolygons(tags element.Tags, members []element.Member) []element.Member {
relMatches := pg.polygonTagMatcher.Match(&tags)
result := []element.Member{}
for _, m := range members {
if m.Type != element.WAY {
continue
}
memberMatches := pg.polygonTagMatcher.Match(&m.Way.Tags)
if matchEquals(relMatches, memberMatches) {
result = append(result, m)
}
}
return result
}
func matchEquals(matchesA, matchesB []mapping.Match) bool {
for _, matchA := range matchesA {
for _, matchB := range matchesB {
if matchA.Key == matchB.Key &&

View File

@ -0,0 +1,102 @@
package postgis
import (
"testing"
"imposm3/database"
"imposm3/element"
"imposm3/mapping"
)
func makeMember(id int64, tags element.Tags) element.Member {
way := &element.Way{element.OSMElem{id, tags, nil}, nil, nil}
return element.Member{Id: id, Type: element.WAY, Role: "outer", Way: way}
}
func testDb(t *testing.T) *PostGIS {
mapping, err := mapping.NewMapping("test_mapping.json")
if err != nil {
t.Fatal(err)
}
conf := database.Config{
ConnectionParams: "postgis://localhost",
Srid: 3857,
ImportSchema: "",
ProductionSchema: "",
BackupSchema: "",
}
db, err := New(conf, mapping)
if err != nil {
t.Fatal(err)
}
return db.(*PostGIS)
}
func TestFilterRelationPolygonsSimple(t *testing.T) {
db := testDb(t)
filtered := db.FilterRelationPolygons(element.Tags{"landuse": "park"},
[]element.Member{
makeMember(0, element.Tags{"landuse": "forest"}),
makeMember(1, element.Tags{"landuse": "park"}),
makeMember(2, element.Tags{"waterway": "riverbank"}),
makeMember(4, element.Tags{"foo": "bar"}),
})
if len(filtered) != 1 {
t.Fatal(filtered)
}
if filtered[0].Id != 1 {
t.Fatal(filtered[0])
}
}
func TestFilterRelationPolygonsUnrelatedTags(t *testing.T) {
db := testDb(t)
filtered := db.FilterRelationPolygons(element.Tags{"landuse": "park"},
[]element.Member{
makeMember(0, element.Tags{"landuse": "park", "layer": "2", "name": "foo"}),
makeMember(1, element.Tags{"landuse": "forest"}),
})
if len(filtered) != 1 {
t.Fatal(filtered)
}
if filtered[0].Id != 0 {
t.Fatal(filtered)
}
}
func TestFilterRelationPolygonsMultiple(t *testing.T) {
db := testDb(t)
filtered := db.FilterRelationPolygons(element.Tags{"landuse": "park"},
[]element.Member{
makeMember(0, element.Tags{"landuse": "park"}),
makeMember(1, element.Tags{"natural": "forest"}),
makeMember(2, element.Tags{"landuse": "park"}),
makeMember(3, element.Tags{"highway": "pedestrian"}),
makeMember(4, element.Tags{"landuse": "park", "layer": "2", "name": "foo"}),
})
if len(filtered) != 3 {
t.Fatal(filtered)
}
if filtered[0].Id != 0 || filtered[1].Id != 2 || filtered[2].Id != 4 {
t.Fatal(filtered)
}
}
func TestFilterRelationPolygonsMultipleTags(t *testing.T) {
db := testDb(t)
filtered := db.FilterRelationPolygons(element.Tags{"landuse": "forest", "natural": "scrub"},
[]element.Member{
makeMember(0, element.Tags{"natural": "scrub"}),
makeMember(1, element.Tags{"landuse": "forest"}),
})
// TODO both should be filterd out, but we only get the first one,
// because we match only one tag per table
if len(filtered) != 1 {
t.Fatal(filtered)
}
if filtered[0].Id != 0 {
t.Fatal(filtered)
}
}

View File

@ -0,0 +1,154 @@
{
"tables": {
"landusages": {
"fields": [
{
"type": "id",
"name": "osm_id",
"key": null
},
{
"type": "geometry",
"name": "geometry",
"key": null
},
{
"type": "string",
"name": "name",
"key": "name"
},
{
"type": "mapping_value",
"name": "type",
"key": null
}
],
"type": "polygon",
"mapping": {
"amenity": [
"university",
"school",
"college",
"library",
"fuel",
"parking",
"cinema",
"theatre",
"place_of_worship",
"hospital"
],
"barrier": [
"hedge"
],
"leisure": [
"park",
"garden",
"playground",
"golf_course",
"sports_centre",
"pitch",
"stadium",
"common",
"nature_reserve"
],
"tourism": [
"zoo"
],
"natural": [
"wood",
"land",
"scrub",
"wetland",
"heath"
],
"man_made": [
"pier"
],
"aeroway": [
"runway",
"taxiway"
],
"place": [
"island"
],
"military": [
"barracks"
],
"landuse": [
"park",
"forest",
"residential",
"retail",
"commercial",
"industrial",
"railway",
"cemetery",
"grass",
"farmyard",
"farm",
"farmland",
"orchard",
"vineyard",
"wood",
"meadow",
"village_green",
"recreation_ground",
"allotments",
"quarry"
],
"highway": [
"pedestrian",
"footway"
]
}
},
"waterareas": {
"fields": [
{
"type": "id",
"name": "osm_id",
"key": null
},
{
"type": "geometry",
"name": "geometry",
"key": null
},
{
"type": "string",
"name": "name",
"key": "name"
},
{
"type": "mapping_value",
"name": "type",
"key": null
},
{
"type": "pseudoarea",
"name": "area",
"key": null
}
],
"type": "polygon",
"mapping": {
"waterway": [
"riverbank"
],
"landuse": [
"basin",
"reservoir"
],
"natural": [
"water"
],
"amenity": [
"swimming_pool"
],
"leisure": [
"swimming_pool"
]
}
}
}
}

View File

@ -52,13 +52,6 @@ func TestSimplePolygonWithHole(t *testing.T) {
g := geos.NewGeos()
defer g.Finish()
if len(rel.Members) != 2 {
t.Fatal("wrong rel members", rel.Members)
}
if rel.Members[0].Id != 1 || rel.Members[1].Id != 2 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel.Tags) != 0 {
t.Fatal("wrong rel tags", rel.Tags)
}
@ -99,13 +92,6 @@ func TestMultiPolygonWithHoleAndRelName(t *testing.T) {
g := geos.NewGeos()
defer g.Finish()
if len(rel.Members) != 1 {
t.Fatal("wrong rel members", rel.Members)
}
if rel.Members[0].Id != 1 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel.Tags) != 2 {
t.Fatal("wrong rel tags", rel.Tags)
}
@ -157,13 +143,6 @@ func TestMultiPolygonWithMultipleHoles(t *testing.T) {
g := geos.NewGeos()
defer g.Finish()
if len(rel.Members) != 1 {
t.Fatal("wrong rel members", rel.Members)
}
if rel.Members[0].Id != 1 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel.Tags) != 1 {
t.Fatal("wrong rel tags", rel.Tags)
}
@ -230,13 +209,6 @@ func TestMultiPolygonWithNeastedHoles(t *testing.T) {
g := geos.NewGeos()
defer g.Finish()
if len(rel.Members) != 3 {
t.Fatal("wrong rel members", rel.Members)
}
if rel.Members[0].Id != 1 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel.Tags) != 1 {
t.Fatal("wrong rel tags", rel.Tags)
}
@ -279,13 +251,6 @@ func TestPolygonFromThreeWays(t *testing.T) {
g := geos.NewGeos()
defer g.Finish()
if len(rel.Members) != 2 {
t.Fatal("wrong rel members", rel.Members)
}
if rel.Members[0].Id != 1 || rel.Members[1].Id != 3 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel.Tags) != 1 {
t.Fatal("wrong rel tags", rel.Tags)
}
@ -335,14 +300,6 @@ func TestTouchingPolygonsWithHole(t *testing.T) {
g := geos.NewGeos()
defer g.Finish()
if len(rel.Members) != 2 {
t.Fatal("wrong rel members", rel.Members)
}
if rel.Members[0].Id != 1 || rel.Members[1].Id != 2 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel.Tags) != 1 {
t.Fatal("wrong rel tags", rel.Tags)
}
@ -382,14 +339,6 @@ func TestInsertedWaysDifferentTags(t *testing.T) {
g := geos.NewGeos()
defer g.Finish()
if len(rel.Members) != 1 {
t.Fatal("wrong rel members", rel.Members)
}
if rel.Members[0].Id != 1 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel.Tags) != 1 {
t.Fatal("wrong rel tags", rel.Tags)
}
@ -429,14 +378,6 @@ func TestInsertMultipleTags(t *testing.T) {
g := geos.NewGeos()
defer g.Finish()
if len(rel.Members) != 0 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel.Tags) != 1 {
t.Fatal("wrong rel tags", rel.Tags)
}
if rel.Tags["landusage"] != "forest" {
t.Fatal("wrong rel tags", rel.Tags)
}
@ -486,10 +427,6 @@ func TestBrokenPolygonSelfIntersect(t *testing.T) {
g := geos.NewGeos()
defer g.Finish()
if len(rel1.Members) != 2 {
t.Fatal("wrong rel members", rel1.Members)
}
if len(rel1.Tags) != 0 {
t.Fatal("wrong rel tags", rel1.Tags)
}
@ -532,10 +469,6 @@ func TestBrokenPolygonSelfIntersect(t *testing.T) {
g = geos.NewGeos()
defer g.Finish()
if len(rel2.Members) != 2 {
t.Fatal("wrong rel members", rel2.Members)
}
if len(rel2.Tags) != 0 {
t.Fatal("wrong rel tags", rel2.Tags)
}

View File

@ -126,16 +126,10 @@ NextRel:
rw.inserter.InsertPolygon(rel.OSMElem, matches)
}
for _, m := range r.Members {
if m.Type != element.WAY {
continue
}
ok, memberMatches := rw.inserter.ProbePolygon(m.Way.OSMElem)
if ok && rw.inserter.MatchEquals(matches, memberMatches) {
err = rw.osmCache.InsertedWays.PutWay(m.Way)
if err != nil {
log.Warn(err)
}
for _, m := range rw.inserter.FilterRelationPolygons(r.Tags, r.Members) {
err = rw.osmCache.InsertedWays.PutWay(m.Way)
if err != nil {
log.Warn(err)
}
}
if rw.diffCache != nil {