예제 #1
0
func TestSelectRelationPolygonsMultiple(t *testing.T) {
	mapping, err := NewMapping("test_mapping.json")
	if err != nil {
		t.Fatal(err)
	}
	r := element.Relation{}
	r.Tags = element.Tags{"landuse": "park"}
	r.Members = []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"}),
	}
	filtered := SelectRelationPolygons(
		mapping.PolygonMatcher(),
		&r,
	)
	if len(filtered) != 3 {
		t.Fatal(filtered)
	}
	if filtered[0].Id != 0 || filtered[1].Id != 2 || filtered[2].Id != 4 {
		t.Fatal(filtered)
	}
}
예제 #2
0
func TestMatcherMappingOrder(t *testing.T) {
	elem := element.Relation{}
	polys := mapping.PolygonMatcher()

	/*
		landusages mapping has the following order,
		check that XxxMatcher always uses the first

		amenity:
		- university
		landuse:
		- forest
		leisure:
		- park
		landuse:
		- park
	*/

	elem.Tags = element.Tags{"landuse": "forest", "leisure": "park"}
	matchesEqual(t, []Match{{"landuse", "forest", DestTable{Name: "landusages"}, nil}}, polys.MatchRelation(&elem))

	elem.Tags = element.Tags{"landuse": "park", "leisure": "park"}
	matchesEqual(t, []Match{{"leisure", "park", DestTable{Name: "landusages"}, nil}}, polys.MatchRelation(&elem))

	elem.Tags = element.Tags{"landuse": "park", "leisure": "park", "amenity": "university"}
	matchesEqual(t, []Match{{"amenity", "university", DestTable{Name: "landusages"}, nil}}, polys.MatchRelation(&elem))
}
예제 #3
0
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, 3857)
	g := geos.NewGeos()
	defer g.Finish()

	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)
	}
}
예제 #4
0
func TestMultiPolygonWithMultipleHoles(t *testing.T) {
	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{"water": "basin"}, []coord{
		{1, 1, 1},
		{2, 2, 1},
		{3, 2, 2},
		{4, 1, 2},
		{1, 1, 1},
	})
	w3 := makeWay(3, element.Tags{"landusage": "scrub"}, []coord{
		{1, 3, 3},
		{2, 4, 3},
		{3, 4, 4},
		{4, 3, 4},
		{1, 3, 3},
	})

	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},
		{3, element.WAY, "inner", &w3},
	}

	geom, err := buildRelation(&rel, 3857)
	if err != nil {
		t.Fatal(err)
	}
	g := geos.NewGeos()
	defer g.Finish()

	//	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(geom.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
	}

	if area := geom.Geom.Area(); area != 100-1-1 {
		t.Fatal("area invalid", area)
	}
}
예제 #5
0
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},
	}
	geom, err := buildRelation(&rel, 3857)
	if err != nil {
		t.Fatal(err)
	}
	g := geos.NewGeos()
	defer g.Finish()

	//	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(geom.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
	}

	if area := geom.Geom.Area(); area != 100+200-36 {
		t.Fatal("area invalid", area)
	}
}
예제 #6
0
func BenchmarkTagMatch(b *testing.B) {
	m, err := NewMapping("matcher_test_mapping.json")
	if err != nil {
		b.Fatal(err)
	}
	matcher := m.PolygonMatcher()
	for i := 0; i < b.N; i++ {
		e := element.Relation{}
		e.Tags = element.Tags{"landuse": "forest", "name": "Forest", "source": "bling", "tourism": "zoo"}
		if m := matcher.MatchRelation(&e); len(m) != 1 {
			b.Fatal(m)
		}
	}
}
예제 #7
0
func TestMultiPolygonWithHoleAndRelName(t *testing.T) {
	w1 := makeWay(1, element.Tags{"natural": "forest", "name": "Blackwood"}, []coord{
		{1, 0, 0},
		{2, 10, 0},
		{3, 10, 10},
		{4, 0, 10},
		{1, 0, 0},
	})
	w2 := makeWay(1, element.Tags{"landusage": "scrub"}, []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{"name": "rel"}}}
	rel.Members = []element.Member{
		{1, element.WAY, "outer", &w1},
		{2, element.WAY, "inner", &w2},
	}

	geom, err := buildRelation(&rel, 3857)
	if err != nil {
		t.Fatal(err)
	}
	g := geos.NewGeos()
	defer g.Finish()

	//	if len(rel.Tags) != 2 {
	//		t.Fatal("wrong rel tags", rel.Tags)
	//	}
	//	if rel.Tags["natural"] != "forest" || rel.Tags["name"] != "Blackwood" {
	//		t.Fatal("wrong rel tags", rel.Tags)
	//	}

	if !g.IsValid(geom.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
	}

	if area := geom.Geom.Area(); area != 64 {
		t.Fatal("aread not 64", area)
	}
}
예제 #8
0
func TestPolygonFromThreeWays(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{"landusage": "water"}, []coord{
		{3, 10, 10},
		{4, 0, 10},
	})
	w3 := makeWay(3, element.Tags{"landusage": "forest"}, []coord{
		{4, 0, 10},
		{1, 0, 0},
	})

	rel := element.Relation{OSMElem: element.OSMElem{Id: 1}}
	rel.Members = []element.Member{
		{1, element.WAY, "outer", &w1},
		{2, element.WAY, "inner", &w2},
		{3, element.WAY, "inner", &w3},
	}

	geom, err := buildRelation(&rel, 3857)
	if err != nil {
		t.Fatal(err)
	}
	g := geos.NewGeos()
	defer g.Finish()

	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(geom.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
	}

	if area := geom.Geom.Area(); area != 100 {
		t.Fatal("area invalid", area)
	}
}
예제 #9
0
// PrepareRelation is the first step in building a (multi-)polygon of a Relation.
// It builds rings from all ways and returns an error if there are unclosed rings.
// It also merges the Relation.Tags with the Tags of the outer way.
func PrepareRelation(rel *element.Relation, srid int, maxRingGap float64) (PreparedRelation, error) {
	rings, err := buildRings(rel, maxRingGap)
	if err != nil {
		return PreparedRelation{}, err
	}

	rel.Tags = relationTags(rel.Tags, rings[0].ways[0].Tags)

	return PreparedRelation{rings, rel, srid}, nil
}
예제 #10
0
func PrepareRelation(rel *element.Relation, srid int) (*preparedRelation, error) {
	rings, err := BuildRings(rel)
	if err != nil {
		return nil, err
	}

	rel.Tags = relationTags(rel.Tags, rings[0].ways[0].Tags)

	return &preparedRelation{rings, rel, srid}, nil
}
예제 #11
0
func TestOpenRing(t *testing.T) {
	w1 := makeWay(1, element.Tags{}, []coord{
		{1, 0, 0},
		{2, 10, 0},
		{3, 10, 10},
		{4, 0, 10},
	})

	rel := element.Relation{
		OSMElem: element.OSMElem{Id: 1, Tags: element.Tags{}}}
	rel.Members = []element.Member{
		{1, element.WAY, "outer", &w1},
	}

	_, err := buildRelation(&rel, 3857)
	if err == nil {
		t.Fatal("no error from open ring")
	}
}
예제 #12
0
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(2, 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},
	}

	geom, err := buildRelation(&rel, 3857)
	if err != nil {
		t.Fatal(err)
	}
	g := geos.NewGeos()
	defer g.Finish()

	if len(rel.Tags) != 0 {
		t.Fatal("wrong rel tags", rel.Tags)
	}

	if !g.IsValid(geom.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
	}

	if area := geom.Geom.Area(); area != 100-36 {
		t.Fatal("area invalid", area)
	}
}
예제 #13
0
// PrepareRelation is the first step in building a (multi-)polygon of a Relation.
// It builds rings from all ways and returns an error if there are unclosed rings.
// It also merges the Relation.Tags with the Tags of the outer way.
func PrepareRelation(rel *element.Relation, srid int, maxRingGap float64) (PreparedRelation, error) {
	rings, err := buildRings(rel, maxRingGap)
	if err != nil {
		return PreparedRelation{}, err
	}

	if rel.Tags["type"] == "multipolygon" && len(rel.Tags) == 1 {
		rel.Tags = relationTags(rel.Tags, rings[0].ways[0].Tags) //merge the Relation.Tags with the Tags of the outer way was removed
	}
	return PreparedRelation{rings, rel, srid}, nil
}
예제 #14
0
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},
	}

	geom, err := buildRelation(&rel, 3857)
	if err != nil {
		t.Fatal(err)
	}
	g := geos.NewGeos()
	defer g.Finish()

	//	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(geom.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
	}

	if area := geom.Geom.Area(); area != 100 {
		t.Fatal("area invalid", area)
	}
}
예제 #15
0
func TestSelectRelationPolygonsMultipleTags(t *testing.T) {
	mapping, err := NewMapping("test_mapping.json")
	if err != nil {
		t.Fatal(err)
	}
	r := element.Relation{}
	r.Tags = element.Tags{"landuse": "forest", "natural": "scrub"}
	r.Members = []element.Member{
		makeMember(0, element.Tags{"natural": "scrub"}),
		makeMember(1, element.Tags{"landuse": "forest"}),
	}
	filtered := SelectRelationPolygons(
		mapping.PolygonMatcher(),
		&r,
	)
	// TODO both should be filterd out, but we only get one,
	// because we match only one tag per table
	if len(filtered) != 1 {
		t.Fatal(filtered)
	}
}
예제 #16
0
func TestSelectRelationPolygonsUnrelatedTags(t *testing.T) {
	mapping, err := NewMapping("test_mapping.json")
	if err != nil {
		t.Fatal(err)
	}
	r := element.Relation{}
	r.Tags = element.Tags{"landuse": "park"}
	r.Members = []element.Member{
		makeMember(0, element.Tags{"landuse": "park", "layer": "2", "name": "foo"}),
		makeMember(1, element.Tags{"landuse": "forest"}),
	}
	filtered := SelectRelationPolygons(
		mapping.PolygonMatcher(),
		&r,
	)
	if len(filtered) != 1 {
		t.Fatal(filtered)
	}
	if filtered[0].Id != 0 {
		t.Fatal(filtered)
	}
}
예제 #17
0
func TestClosedAndOpenRing(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(2, element.Tags{}, []coord{
		{5, 0, 0},
		{6, -5, -2},
	})
	rel := element.Relation{
		OSMElem: element.OSMElem{Id: 1, Tags: element.Tags{}}}
	rel.Members = []element.Member{
		{1, element.WAY, "outer", &w1},
		{2, element.WAY, "outer", &w2},
	}

	prep, err := PrepareRelation(&rel, 3857, 0.1)
	if err != nil {
		t.Fatal(err)
	}
	// open ring is excluded
	if len(prep.rings) != 1 {
		t.Fatal("expected single ring")
	}
	geom, err := prep.Build()
	if err != nil {
		t.Fatal(err)
	}

	g := geos.NewGeos()
	defer g.Finish()

	if !g.IsValid(geom.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
	}
}
예제 #18
0
func BuildRelation(rel *element.Relation, srid int) error {
	rings, err := BuildRings(rel)
	if err != nil {
		return err
	}

	rel.Tags = relationTags(rel.Tags, rings[0].ways[0].Tags)

	_, err = BuildRelGeometry(rel, rings, srid)
	if err != nil {
		return err
	}
	return nil
}
예제 #19
0
func TestSelectRelationPolygonsSimple(t *testing.T) {
	mapping, err := NewMapping("test_mapping.json")
	if err != nil {
		t.Fatal(err)
	}
	r := element.Relation{}
	r.Tags = element.Tags{"landuse": "park"}
	r.Members = []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"}),
	}
	filtered := SelectRelationPolygons(
		mapping.PolygonMatcher(),
		&r,
	)
	if len(filtered) != 1 {
		t.Fatal(filtered)
	}
	if filtered[0].Id != 1 {
		t.Fatal(filtered[0])
	}
}
예제 #20
0
func TestSelectRelationPolygonsMultipleTagsOnWay(t *testing.T) {
	mapping, err := NewMapping("test_mapping.json")
	if err != nil {
		t.Fatal(err)
	}
	r := element.Relation{}
	r.Tags = element.Tags{"waterway": "riverbank"}
	r.Members = []element.Member{
		makeMemberRole(0, element.Tags{"waterway": "riverbank", "natural": "water"}, "outer"),
		makeMemberRole(1, element.Tags{"natural": "water"}, "inner"),
		makeMemberRole(2, element.Tags{"place": "islet"}, "inner"),
	}
	filtered := SelectRelationPolygons(
		mapping.PolygonMatcher(),
		&r,
	)

	if len(filtered) != 1 {
		t.Fatal(filtered)
	}
	if filtered[0].Id != 0 {
		t.Fatal(filtered)
	}
}
예제 #21
0
func TestMultiPolygonWithNeastedHoles(t *testing.T) {
	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(2, element.Tags{"landusage": "scrub"}, []coord{
		{1, 1, 1},
		{2, 9, 1},
		{3, 9, 9},
		{4, 1, 9},
		{1, 1, 1},
	})
	w3 := makeWay(3, element.Tags{}, []coord{
		{1, 2, 2},
		{2, 8, 2},
		{3, 8, 8},
		{4, 2, 8},
		{1, 2, 2},
	})
	w4 := makeWay(4, element.Tags{"landusage": "scrub"}, []coord{
		{1, 3, 3},
		{2, 7, 3},
		{3, 7, 7},
		{4, 3, 7},
		{1, 3, 3},
	})
	w5 := makeWay(5, element.Tags{"landusage": "forest"}, []coord{
		{1, 4, 4},
		{2, 6, 4},
		{3, 6, 6},
		{4, 4, 6},
		{1, 4, 4},
	})

	rel := element.Relation{OSMElem: element.OSMElem{Id: 1}}
	rel.Members = []element.Member{
		{1, element.WAY, "outer", &w1},
		{2, element.WAY, "inner", &w2},
		{3, element.WAY, "inner", &w3},
		{4, element.WAY, "inner", &w4},
		{5, element.WAY, "inner", &w5},
	}

	geom, err := buildRelation(&rel, 3857)
	if err != nil {
		t.Fatal(err)
	}
	g := geos.NewGeos()
	defer g.Finish()

	//	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(geom.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
	}

	if area := geom.Geom.Area(); area != 100-64+36-16+4 {
		t.Fatal("area invalid", area)
	}
}
예제 #22
0
// BuildRelGeometry builds the geometry of rel by creating a multipolygon of all rings.
// rings need to be sorted by area (large to small).
func BuildRelGeometry(rel *element.Relation, rings []*Ring, srid int) (*geos.Geom, error) {
	g := geos.NewGeos()
	g.SetHandleSrid(srid)
	defer g.Finish()

	totalRings := len(rings)
	shells := map[*Ring]bool{rings[0]: true}
	for i := 0; i < totalRings; i++ {
		testGeom := g.Prepare(rings[i].geom)
		if testGeom == nil {
			return nil, errors.New("Error while preparing geometry")
		}
		for j := i + 1; j < totalRings; j++ {
			if g.PreparedContains(testGeom, rings[j].geom) {
				if rings[j].containedBy != -1 {
					// j is inside a larger ring, remove that relationship
					// e.g. j is hole inside a hole (i)
					delete(rings[rings[j].containedBy].holes, rings[j])
					delete(shells, rings[j])
				}
				// remember parent
				rings[j].containedBy = i
				// add ring as hole or shell
				if ringIsHole(rings, j) {
					rings[i].holes[rings[j]] = true
				} else {
					shells[rings[j]] = true
				}
			}
		}
		if rings[i].containedBy == -1 {
			// add as shell if it is not a hole
			shells[rings[i]] = true
		}
		g.PreparedDestroy(testGeom)
	}

	var polygons []*geos.Geom
	for shell, _ := range shells {
		var interiors []*geos.Geom
		for hole, _ := range shell.holes {
			hole.MarkInserted(rel.Tags)
			ring := g.Clone(g.ExteriorRing(hole.geom))
			g.Destroy(hole.geom)
			if ring == nil {
				return nil, errors.New("Error while getting exterior ring.")
			}
			interiors = append(interiors, ring)
		}
		shell.MarkInserted(rel.Tags)
		exterior := g.Clone(g.ExteriorRing(shell.geom))
		g.Destroy(shell.geom)
		if exterior == nil {
			return nil, errors.New("Error while getting exterior ring.")
		}
		polygon := g.Polygon(exterior, interiors)
		if polygon == nil {
			return nil, errors.New("Error while building polygon.")
		}
		polygons = append(polygons, polygon)
	}
	var result *geos.Geom

	if len(polygons) == 1 {
		result = polygons[0]
	} else {
		result = g.MultiPolygon(polygons)
		if result == nil {
			return nil, errors.New("Error while building multi-polygon.")
		}
	}
	if !g.IsValid(result) {
		buffered := g.Buffer(result, 0)
		if buffered == nil {
			return nil, errors.New("Error while fixing geom with buffer(0)")
		}
		g.Destroy(result)
		result = buffered
	}

	g.DestroyLater(result)

	insertedWays := make(map[int64]bool)
	for _, r := range rings {
		for id, _ := range r.inserted {
			insertedWays[id] = true
		}
	}

	wkb := g.AsEwkbHex(result)
	if wkb == nil {
		return nil, errors.New("unable to create WKB for relation")
	}
	rel.Geom = &element.Geometry{Geom: result, Wkb: wkb}

	return result, nil
}
예제 #23
0
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},
	}

	geom1, err := buildRelation(&rel1, 3857)
	if err != nil {
		t.Fatal(err)
	}
	g := geos.NewGeos()
	defer g.Finish()

	//	if len(rel1.Tags) != 0 {
	//		t.Fatal("wrong rel tags", rel1.Tags)
	//	}

	if !g.IsValid(geom1.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom1.Geom))
	}

	if area := geom1.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},
	}

	geom2, err := buildRelation(&rel2, 3857)
	if err != nil {
		t.Fatal(err)
	}

	g = geos.NewGeos()
	defer g.Finish()

	//	if len(rel2.Tags) != 0 {
	//		t.Fatal("wrong rel tags", rel2.Tags)
	//	}

	if !g.IsValid(geom2.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom2.Geom))
	}

	if area := geom2.Geom.Area(); area != 200-36 {
		t.Fatal("area invalid", area)
	}
}
예제 #24
0
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},
	}

	geom, err := buildRelation(&rel, 3857)
	if err != nil {
		t.Fatal(err)
	}

	g := geos.NewGeos()
	defer g.Finish()

	if !g.IsValid(geom.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
	}

	area := geom.Geom.Area()
	// as for python assertAlmostEqual(a, b)	round(a-b, 7) == 0
	if math.Abs(area-(100*100/2-100)) > 0.01 {
		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},
	}

	geom, err = buildRelation(&rel, 3857)
	if err != nil {
		t.Fatal(err)
	}

	if !g.IsValid(geom.Geom) {
		t.Fatal("geometry not valid", g.AsWkt(geom.Geom))
	}

	area = geom.Geom.Area()
	if math.Abs((area - (100*98/2 - 100))) > 10 {
		t.Fatal("area invalid", area)

	}
}
예제 #25
0
func TestPolygonMatcher(t *testing.T) {
	elem := element.Relation{}
	polys := mapping.PolygonMatcher()

	elem.Tags = element.Tags{"unknown": "baz"}
	matchesEqual(t, []Match{}, polys.MatchRelation(&elem))

	elem.Tags = element.Tags{"landuse": "unknowns"}
	matchesEqual(t, []Match{}, polys.MatchRelation(&elem))

	elem.Tags = element.Tags{"building": "yes"}
	matchesEqual(t, []Match{{"building", "yes", DestTable{"buildings", ""}, nil}}, polys.MatchRelation(&elem))
	elem.Tags = element.Tags{"building": "residential"}
	matchesEqual(t, []Match{{"building", "residential", DestTable{"buildings", ""}, nil}}, polys.MatchRelation(&elem))

	elem.Tags = element.Tags{"building": "shop"}
	matchesEqual(t, []Match{
		{"building", "shop", DestTable{"buildings", ""}, nil},
		{"building", "shop", DestTable{"amenity_areas", ""}, nil}},
		polys.MatchRelation(&elem))

	elem.Tags = element.Tags{"landuse": "farm"}
	matchesEqual(t, []Match{{"landuse", "farm", DestTable{"landusages", ""}, nil}}, polys.MatchRelation(&elem))

	elem.Tags = element.Tags{"landuse": "farm", "highway": "secondary"}
	matchesEqual(t, []Match{{"landuse", "farm", DestTable{"landusages", ""}, nil}}, polys.MatchRelation(&elem))

	elem.Tags = element.Tags{"landuse": "farm", "aeroway": "apron"}
	matchesEqual(t,
		[]Match{
			{"aeroway", "apron", DestTable{"transport_areas", ""}, nil},
			{"landuse", "farm", DestTable{"landusages", ""}, nil}},
		polys.MatchRelation(&elem))

	elem.Tags = element.Tags{"highway": "footway"}
	matchesEqual(t, []Match{{"highway", "footway", DestTable{"landusages", ""}, nil}}, polys.MatchRelation(&elem))

	elem.Tags = element.Tags{"boundary": "administrative", "admin_level": "8"}
	matchesEqual(t, []Match{{"boundary", "administrative", DestTable{"admin", ""}, nil}}, polys.MatchRelation(&elem))
}