added missing tests from python/imposm

master
Marcel Radischat 2013-05-24 13:24:02 +02:00
parent 4a19dae36e
commit 90b303afee
2 changed files with 551 additions and 13 deletions

View File

@ -4,6 +4,7 @@ import (
"goposm/element"
"goposm/geom/geos"
"testing"
"math"
)
type coord struct {
@ -12,6 +13,21 @@ type coord struct {
lat float64
}
func Round(x float64, prec int) float64 {
var rounder float64
pow := math.Pow(10, float64(prec))
intermed := x * pow
_, frac := math.Modf(intermed)
if frac >= 0.5 {
rounder = math.Ceil(intermed)
} else {
rounder = math.Floor(intermed)
}
return rounder / pow
}
func makeWay(id int64, tags element.Tags, coords []coord) element.Way {
way := element.Way{}
way.Id = id
@ -24,7 +40,54 @@ func makeWay(id int64, tags element.Tags, coords []coord) element.Way {
return way
}
func TestMultiPolygonWithHole(t *testing.T) {
func TestSimplePolygonWithHole(t *testing.T) {
w1 := makeWay(1, element.Tags{}, []coord{
{1, 0, 0},
{2, 10, 0},
{3, 10, 10},
{4, 0, 10},
{1, 0, 0},
})
w2 := makeWay(1, element.Tags{}, []coord{
{5, 2, 2},
{6, 8, 2},
{7, 8, 8},
{8, 2, 8},
{5, 2, 2},
})
rel := element.Relation{
OSMElem: element.OSMElem{Id: 1, Tags: element.Tags{}}}
rel.Members = []element.Member{
{1, element.WAY, "outer", &w1},
{2, element.WAY, "inner", &w2},
}
BuildRelation(&rel)
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[0].ID != 2 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel.Tags) != 0 {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWKT(rel.Geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100-36 {
t.Fatal("area invalid", area)
}
}
func TestMultiPolygonWithHoleAndRelName(t *testing.T) {
w1 := makeWay(1, element.Tags{"natural": "forest", "name": "Blackwood"}, []coord{
{1, 0, 0},
{2, 10, 0},
@ -48,6 +111,8 @@ func TestMultiPolygonWithHole(t *testing.T) {
}
BuildRelation(&rel)
g := geos.NewGEOS()
defer g.Finish()
if len(rel.Members) != 1 {
t.Fatal("wrong rel members", rel.Members)
@ -63,9 +128,6 @@ func TestMultiPolygonWithHole(t *testing.T) {
t.Fatal("wrong rel tags", rel.Tags)
}
g := geos.NewGEOS()
defer g.Finish()
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWKT(rel.Geom.Geom))
}
@ -76,14 +138,14 @@ func TestMultiPolygonWithHole(t *testing.T) {
}
func TestMultiPolygonWithMultipleHoles(t *testing.T) {
w1 := makeWay(1, element.Tags{"natural": "forest", "name": "Blackwood"}, []coord{
w1 := makeWay(1, element.Tags{"landusage": "forest"}, []coord{
{1, 0, 0},
{2, 10, 0},
{3, 10, 10},
{4, 0, 10},
{1, 0, 0},
})
w2 := makeWay(1, element.Tags{"natural": "water"}, []coord{
w2 := makeWay(1, element.Tags{"water": "basin"}, []coord{
{1, 1, 1},
{2, 2, 1},
{3, 2, 2},
@ -99,7 +161,7 @@ func TestMultiPolygonWithMultipleHoles(t *testing.T) {
})
rel := element.Relation{
OSMElem: element.OSMElem{Id: 1, Tags: element.Tags{"name": "rel"}}}
OSMElem: element.OSMElem{Id: 1, Tags: element.Tags{"landusage": "forest"}}}
rel.Members = []element.Member{
{1, element.WAY, "outer", &w1},
{2, element.WAY, "inner", &w2},
@ -254,3 +316,320 @@ func TestPolygonFromThreeWays(t *testing.T) {
t.Fatal("area invalid", area)
}
}
func TestTouchingPolygonsWithHole(t *testing.T) {
w1 := makeWay(1, element.Tags{"water": "riverbank"}, []coord{
{1, 0, 0},
{2, 10, 0},
{3, 10, 10},
{4, 0, 10},
{1, 0, 0},
})
w2 := makeWay(2, element.Tags{"water": "riverbank"}, []coord{
{2, 10, 0},
{5, 30, 0},
{6, 30, 10},
{3, 10, 10},
{2, 10, 0},
})
w3 := makeWay(3, element.Tags{"landusage": "forest"}, []coord{
{7, 2, 2},
{8, 8, 2},
{9, 8, 8},
{10, 2, 8},
{7, 2, 2},
})
rel := element.Relation{OSMElem: element.OSMElem{Id: 1, Tags: element.Tags{"water": "riverbank"}}}
rel.Members = []element.Member{
{1, element.WAY, "outer", &w1},
{2, element.WAY, "outer", &w2},
{3, element.WAY, "inner", &w3},
}
BuildRelation(&rel)
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)
}
if rel.Tags["water"] != "riverbank" {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWKT(rel.Geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100+200-36 {
t.Fatal("area invalid", area)
}
}
func TestInsertedWaysDifferentTags(t *testing.T) {
w1 := makeWay(1, element.Tags{"landusage": "forest"}, []coord{
{1, 0, 0},
{2, 10, 0},
{3, 10, 10},
})
w2 := makeWay(2, element.Tags{"highway": "secondary"}, []coord{
{3, 10, 10},
{4, 0, 10},
{1, 0, 0},
})
rel := element.Relation{OSMElem: element.OSMElem{Id: 1, Tags: element.Tags{"landusage": "forest"}}}
rel.Members = []element.Member{
{1, element.WAY, "outer", &w1},
{2, element.WAY, "inner", &w2},
}
BuildRelation(&rel)
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)
}
if rel.Tags["landusage"] != "forest" {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWKT(rel.Geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100 {
t.Fatal("area invalid", area)
}
}
func TestInsertMultipleTags(t *testing.T) {
w1 := makeWay(1, element.Tags{"landusage": "forest", "highway", "secondary"}, []coord{
{1, 0, 0},
{2, 10, 0},
{3, 10, 10},
})
w2 := makeWay(2, element.Tags{"highway": "secondary"}, []coord{
{3, 10, 10},
{4, 0, 10},
{1, 0, 0},
})
rel := element.Relation{OSMElem: element.OSMElem{Id: 1, Tags: element.Tags{"landusage": "forest"}}}
rel.Members = []element.Member{
{1, element.WAY, "outer", &w1}, // also highway=secondary
{2, element.WAY, "inner", &w2},
}
BuildRelation(&rel)
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)
}
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWKT(rel.Geom.Geom))
}
if area := rel.Geom.Geom.Area(); area != 100 {
t.Fatal("area invalid", area)
}
}
func TestBrokenPolygonSelfIntersect(t *testing.T) {
// 2##3 6##7
// # # ####
// 1##4____5##8
w1 := makeWay(1, element.Tags{}, []coord{
{1, 0, 0},
{2, 0, 10},
{3, 10, 10},
{4, 10, 0},
{5, 20, 0},
{6, 20, 10},
{7, 30, 10},
{8, 30, 0},
{1, 0, 0}
})
w2 := makeWay(2, element.Tags{}, []coord{
{15, 2, 2},
{16, 8, 2},
{17, 8, 8},
{18, 2, 8},
{15, 2, 2},
})
rel1 := element.Relation{OSMElem: element.OSMElem{Id: 1}}
rel1.Members = []element.Member{
{1, element.WAY, "outer", &w1},
{2, element.WAY, "inner", &w2},
}
BuildRelation(&rel)
g := geos.NewGEOS()
defer g.Finish()
if len(rel1.Members) != 2 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel1.Tags) != 0 {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel1.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWKT(rel.Geom.Geom))
}
if area := rel1.Geom.Geom.Area(); area != 200 - 36 {
t.Fatal("area invalid", area)
}
// 2##3 6##7
// # # ####
// 1##4____5##8
w3 := makeWay(1, element.Tags{}, []coord{
{4, 10, 0},
{1, 0, 0},
{2, 0, 10},
{3, 10, 10},
{4, 10, 0},
{5, 20, 0},
{6, 20, 10},
{7, 30, 10},
{8, 30, 0},
{4, 10, 0},
})
rel2 := element.Relation{OSMElem: element.OSMElem{Id: 1}}
rel2.Members = []element.Member{
{1, element.WAY, "outer", &w3},
{2, element.WAY, "inner", &w2},
}
BuildRelation(&rel)
g := geos.NewGEOS()
defer g.Finish()
if len(rel2.Members) != 2 {
t.Fatal("wrong rel members", rel.Members)
}
if len(rel2.Tags) != 0 {
t.Fatal("wrong rel tags", rel.Tags)
}
if !g.IsValid(rel2.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWKT(rel.Geom.Geom))
}
if area := rel2.Geom.Geom.Area(); area != 200 - 36 {
t.Fatal("area invalid", area)
}
}
func TestBrokenPolygonSelfIntersectTriangle(t *testing.T) {
// 2###
// # ###4
// # ###3
// 1###
// triangle with four points, minor overlapping
w1 := makeWay(1, element.Tags{}, []coord{
{1, 0, 0},
{2, 0, 100},
{3, 100, 50 - 0.00001},
{4, 100, 50 + 0.00001},
{1, 0, 0}
})
w2 := makeWay(2, element.Tags{}, []coord{
{15, 10, 45},
{16, 10, 55},
{17, 20, 55},
{18, 20, 45},
{15, 10, 45},
})
rel := element.Relation{OSMElem: element.OSMElem{Id: 1}}
rel.Members = []element.Member{
{1, element.WAY, "outer", &w1},
{2, element.WAY, "inner", &w2},
}
BuildRelation(&rel)
g := geos.NewGEOS()
defer g.Finish()
if !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWKT(rel.Geom.Geom))
}
area := rel.Geom.Geom.Area();
// as for python assertAlmostEqual(a, b) round(a-b, 7) == 0
if Round((area - (100 * 100 / 2 - 100), 0) != 2 {
t.Fatal("area invalid", area)
}
// larger overlap
w3 := makeWay(1, element.Tags{}, []coord{
{1, 0, 0},
{2, 0, 100},
{3, 100, 50 - 1},
{4, 100, 50 + 1},
{1, 0, 0}
})
w4 := makeWay(2, element.Tags{}, []coord{
{15, 10, 45},
{16, 10, 55},
{17, 20, 55},
{18, 20, 45},
{15, 10, 45},
})
rel := element.Relation{OSMElem: element.OSMElem{Id: 1}}
rel.Members = []element.Member{
{1, element.WAY, "outer", &w3},
{2, element.WAY, "inner", &w4},
}
BuildRelation(&rel)
f !g.IsValid(rel.Geom.Geom) {
t.Fatal("geometry not valid", g.AsWKT(rel.Geom.Geom))
}
area := rel.Geom.Geom.Area();
// as for python assertAlmostEqual(a, b) round(a-b, 7) == 0
if Round((area - (100 * 100 / 2 - 100), 0) != -3 {
t.Fatal("area invalid", area)
}
}

View File

@ -75,13 +75,35 @@ func TestTagFilterNodes(t *testing.T) {
}
stringMapEquals(t, element.Tags{}, tags)
tags = element.Tags{"name": "foo", "place": "unknown"}
if nodes.Filter(&tags) != false {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{}, tags)
tags = element.Tags{"name": "foo", "place": "village"}
if nodes.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "place": "village"}, tags)
// TODO
tags = element.Tags{"name": "foo", "place": "village", "population": "1000"}
if nodes.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "place": "village", "population": "1000"}, tags)
tags = element.Tags{"name": "foo", "place": "village", "highway": "unknown"}
if nodes.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "place": "village"}, tags)
tags = element.Tags{"name": "foo", "place": "village", "highway": "bus_stop"}
if nodes.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "place": "village", "highway": "bus_stop"}, tags)
}
func TestTagFilterWays(t *testing.T) {
@ -106,7 +128,42 @@ func TestTagFilterWays(t *testing.T) {
}
stringMapEquals(t, element.Tags{}, tags)
// TODO
tags = element.Tags{"name": "foo", "highway": "track"}
if ways.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "highway": "track"}, tags)
tags = element.Tags{"name": "foo", "highway": "track", "oneway": "yes", "tunnel": "1"}
if ways.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "highway": "track", "oneway": "yes", "tunnel": "1"}, tags)
tags = element.Tags{"name": "foo", "place": "village", "highway": "track"}
if ways.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "highway": "track"}, tags)
tags = element.Tags{"name": "foo", "railway": "tram", "highway": "secondary"}
if ways.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "railway": "tram", "highway": "secondary"}, tags)
// with __any__ value
tags = element.Tags{"name": "foo", "building": "yes"}
if ways.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "building": "yes"}, tags)
tags = element.Tags{"name": "foo", "building": "whatever"}
if ways.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "building": "whatever"}, tags)
}
func TestTagFilterRelations(t *testing.T) {
@ -118,7 +175,79 @@ func TestTagFilterRelations(t *testing.T) {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{}, tags)
// TODO
tags = element.Tags{"name": "foo", "unknown": "baz"}
if relations.Filter(&tags) != false {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{}, tags)
tags = element.Tags{"name": "foo", "landuse": "unknown"}
if relations.Filter(&tags) != false {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{}, tags)
tags = element.Tags{"name": "foo", "landuse": "farm"}
if relations.Filter(&tags) != false {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{}, tags)
tags = element.Tags{"name": "foo", "landuse": "farm", "type": "multipolygon"}
if relations.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "landuse": "farm", "type": "multipolygon"}, tags)
/* skip multipolygon with filtered tags, otherwise tags from
longest way would be used */
tags = element.Tags{"name": "foo", "landuse": "unknown", "type": "multipolygon"}
if relations.Filter(&tags) != false {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{}, tags)
tags = element.Tags{"name": "foo", "landuse": "park", "type": "multipolygon"}
if relations.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "type": "multipolygon", "landuse": "park"}, tags)
tags = element.Tags{"name": "foo", "landuse": "farm", "boundary": "administrative", "type": "multipolygon"}
if relations.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "landuse": "farm", "boundary": "administrative", "type": "multipolygon"}, tags)
// boundary relation for boundary
tags = element.Tags{"name": "foo", "landuse": "farm", "boundary": "administrative", "type": "boundary"}
if relations.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "landuse": "farm", "boundary": "administrative", "type": "boundary"}, tags)
// boundary relation for non boundary
tags = element.Tags{"name": "foo", "landuse": "farm", "type": "boundary"}
if relations.Filter(&tags) != false {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{}, tags)
/* skip boundary with filtered tags, otherwise tags from longest way would
be used */
tags = element.Tags{"name": "foo", "boundary": "unknown", "type": "boundary"}
if relations.Filter(&tags) != false {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{}, tags)
tags = element.Tags{"name": "foo", "boundary": "administrative", "type": "boundary"}
if relations.Filter(&tags) != true {
t.Fatal("unexpected filter response for", tags)
}
stringMapEquals(t, element.Tags{"name": "foo", "boundary": "administrative", "type": "boundary"}, tags)
}
func TestPointMatcher(t *testing.T) {
@ -134,7 +263,11 @@ func TestPointMatcher(t *testing.T) {
tags = element.Tags{"place": "city"}
matchesEqual(t, []Match{{"place", "city", "places", nil}}, points.Match(&tags))
// TODO
tags = element.Tags{"place": "city", "highway": "unknown"}
matchesEqual(t, []Match{{"place", "city", "places", nil}}, points.Match(&tags))
tags = element.Tags{"place": "city", "highway": "bus_stop"}
matchesEqual(t, []Match{{"place", "city", "places", nil}, {"highway", "bus_stop", "transport_points", nil}}, points.Match(&tags))
}
func TestLineStringMatcher(t *testing.T) {
@ -144,7 +277,20 @@ func TestLineStringMatcher(t *testing.T) {
tags = element.Tags{"unknown": "baz"}
matchesEqual(t, []Match{}, ls.Match(&tags))
// TODO
tags = element.Tags{"highway": "unknown"}
matchesEqual(t, []Match{}, ls.Match(&tags))
tags = element.Tags{"highway": "track"}
matchesEqual(t, []Match{{"highway", "track", "minorroads", nil}}, ls.Match(&tags))
tags = element.Tags{"highway": "secondary", "railway": "tram"}
matchesEqual(t, []Match{{"highway", "secondary", "mainroads", nil}, {"railway", "tram", "railways", nil}}, ls.Match(&tags))
tags = element.Tags{"highway": "footway"}
matchesEqual(t, []Match{{"highway", "footway", "minorroads", nil}, {"highway", "footway", "landusages", nil}}, ls.Match(&tags))
tags = element.Tags{"highway": "footway", "landuse": "park"}
matchesEqual(t, []Match{{"highway", "footway", "minorroads", nil}, {"landuse", "park", "landusages", nil}}, ls.Match(&tags))
}
func TestPolygonMatcher(t *testing.T) {
@ -154,7 +300,20 @@ func TestPolygonMatcher(t *testing.T) {
tags = element.Tags{"unknown": "baz"}
matchesEqual(t, []Match{}, polys.Match(&tags))
// TODO
tags = element.Tags{"landuse": "unknowns"}
matchesEqual(t, []Match{}, polys.Match(&tags))
tags = element.Tags{"landuse": "farm"}
matchesEqual(t, []Match{{"landuse", "farm", "landusages", nil}}, polys.Match(&tags))
tags = element.Tags{"landuse": "farm", "highway": "secondary"}
matchesEqual(t, []Match{{"landuse", "farm", "landusages", nil}}, polys.Match(&tags))
tags = element.Tags{"landuse": "farm", "aeroway": "apron"}
matchesEqual(t, []Match{{"aeroway", "apron", "transport_areas", nil},{"landuse", "farm", "landusages", nil}}, polys.Match(&tags))
tags = element.Tags{"boundary": "administrative", "admin_level": "8"}
matchesEqual(t, []Match{{"boundary", "administrative", "admin", nil}}, polys.Match(&tags))
}
func TestFilterNodes(t *testing.T) {