diff --git a/geom/geom.go b/geom/geom.go
index 13b4b05..9e9cb29 100644
--- a/geom/geom.go
+++ b/geom/geom.go
@@ -4,6 +4,7 @@ import (
"errors"
"imposm3/element"
"imposm3/geom/geos"
+ "math"
)
type GeomError struct {
@@ -37,7 +38,43 @@ func Point(g *geos.Geos, node element.Node) (*geos.Geom, error) {
return geom, nil
}
+func nodesEqual(a, b element.Node) bool {
+ if d := a.Long - b.Long; math.Abs(d) < 1e-9 {
+ if d := a.Lat - b.Lat; math.Abs(d) < 1e-9 {
+ return true
+ }
+ }
+ return false
+}
+
+func unduplicateNodes(nodes []element.Node) []element.Node {
+ if len(nodes) < 2 {
+ return nodes
+ }
+ foundDup := false
+ for i := 1; i < len(nodes); i++ {
+ if nodesEqual(nodes[i-1], nodes[i]) {
+ foundDup = true
+ break
+ }
+ }
+ if !foundDup {
+ return nodes
+ }
+
+ result := make([]element.Node, 0, len(nodes))
+ result = append(result, nodes[0])
+ for i := 1; i < len(nodes); i++ {
+ if nodesEqual(nodes[i-1], nodes[i]) {
+ continue
+ }
+ result = append(result, nodes[i])
+ }
+ return result
+}
+
func LineString(g *geos.Geos, nodes []element.Node) (*geos.Geom, error) {
+ nodes = unduplicateNodes(nodes)
if len(nodes) < 2 {
return nil, ErrorOneNodeWay
}
@@ -60,6 +97,11 @@ func LineString(g *geos.Geos, nodes []element.Node) (*geos.Geom, error) {
}
func Polygon(g *geos.Geos, nodes []element.Node) (*geos.Geom, error) {
+ nodes = unduplicateNodes(nodes)
+ if len(nodes) < 4 {
+ return nil, ErrorNoRing
+ }
+
coordSeq, err := g.CreateCoordSeq(uint32(len(nodes)), 2)
if err != nil {
return nil, err
diff --git a/geom/geom_test.go b/geom/geom_test.go
index fc8b1a1..55e0b04 100644
--- a/geom/geom_test.go
+++ b/geom/geom_test.go
@@ -90,3 +90,57 @@ func BenchmarkLineString(b *testing.B) {
LineString(g, nodes)
}
}
+
+func TestUnduplicateNodes(t *testing.T) {
+ var nodes []element.Node
+
+ nodes = []element.Node{
+ element.Node{Lat: 0, Long: 0},
+ }
+ if res := unduplicateNodes(nodes); len(res) != 1 {
+ t.Fatal(res)
+ }
+ nodes = []element.Node{
+ element.Node{Lat: 47.0, Long: 80.0},
+ element.Node{Lat: 47.0, Long: 80.0},
+ }
+ if res := unduplicateNodes(nodes); len(res) != 1 {
+ t.Fatal(res)
+ }
+
+ nodes = []element.Node{
+ element.Node{Lat: 0, Long: -10},
+ element.Node{Lat: 0, Long: -10},
+ element.Node{Lat: 0, Long: -10},
+ element.Node{Lat: 10, Long: 10},
+ element.Node{Lat: 10, Long: 10},
+ element.Node{Lat: 10, Long: 10},
+ }
+ if res := unduplicateNodes(nodes); len(res) != 2 {
+ t.Fatal(res)
+ }
+
+ nodes = []element.Node{
+ element.Node{Lat: 10, Long: 10},
+ element.Node{Lat: 0, Long: 10},
+ element.Node{Lat: 10, Long: 10},
+ element.Node{Lat: 10, Long: 10},
+ element.Node{Lat: 0, Long: 10},
+ element.Node{Lat: 0, Long: 10},
+ }
+ if res := unduplicateNodes(nodes); len(res) != 4 {
+ t.Fatal(res)
+ }
+
+ nodes = []element.Node{
+ element.Node{Lat: 0, Long: 0},
+ element.Node{Lat: 0, Long: -10},
+ element.Node{Lat: 10, Long: -10},
+ element.Node{Lat: 10, Long: 0},
+ element.Node{Lat: 0, Long: 0},
+ }
+ if res := unduplicateNodes(nodes); len(res) != 5 {
+ t.Fatal(res)
+ }
+
+}
diff --git a/test/imposm_system_test.py b/test/imposm_system_test.py
index 6cece26..b9f0bb9 100644
--- a/test/imposm_system_test.py
+++ b/test/imposm_system_test.py
@@ -230,6 +230,23 @@ def test_relation_way_inserted():
assert park['name'] == 'rel 8001'
assert query_row(db_conf, 'osm_roads', 8009)["type"] == 'residential'
+def test_single_node_ways_not_inserted():
+ """Ways with single/duplicate nodes are not inserted."""
+ assert not query_row(db_conf, 'osm_roads', 30001)
+ assert not query_row(db_conf, 'osm_roads', 30002)
+ assert not query_row(db_conf, 'osm_roads', 30003)
+
+def test_polygon_with_duplicate_nodes_is_valid():
+ """Polygon with duplicate nodes is valid."""
+ geom = query_row(db_conf, 'osm_landusages', 30005)['geometry']
+ assert geom.is_valid
+ assert len(geom.exterior.coords) == 4
+
+def test_incomplete_polygons():
+ """Non-closed/incomplete polygons are not inserted."""
+ assert not query_row(db_conf, 'osm_landusages', 30004)
+ assert not query_row(db_conf, 'osm_landusages', 30006)
+
#######################################################################
def test_update():
diff --git a/test/test.osm b/test/test.osm
index 82440a7..3854106 100644
--- a/test/test.osm
+++ b/test/test.osm
@@ -302,6 +302,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+