diff --git a/geom/geojson/geojson.go b/geom/geojson/geojson.go index 5518cb2..9a57911 100644 --- a/geom/geojson/geojson.go +++ b/geom/geojson/geojson.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "imposm3/geom/geos" + "imposm3/proj" "io" ) @@ -39,6 +40,10 @@ func newPointFromCoords(coords []interface{}) (point, error) { if !ok { return p, errors.New("invalid lat") } + + if p.long >= -180.0 && p.long <= 180.0 && p.lat >= -90.0 && p.lat <= 90.0 { + p.long, p.lat = proj.WgsToMerc(p.long, p.lat) + } return p, nil } diff --git a/geom/geojson/geojson_test.go b/geom/geojson/geojson_test.go index 6b972c2..d55614c 100644 --- a/geom/geojson/geojson_test.go +++ b/geom/geojson/geojson_test.go @@ -7,7 +7,7 @@ import ( ) func TestParsePolygon(t *testing.T) { - r := bytes.NewBufferString(`{"type": "Polygon", "coordinates": [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]]}`) + r := bytes.NewBufferString(`{"type": "Polygon", "coordinates": [[[1000, 1000], [2000, 1000], [2000, 2000], [1000, 2000], [1000, 1000]]]}`) geoms, err := ParseGeoJson(r) if err != nil { @@ -18,12 +18,12 @@ func TestParsePolygon(t *testing.T) { t.Fatal(geoms) } - if math.Abs(geoms[0].Area()-100) > 0.00001 { + if math.Abs(geoms[0].Area()-1000000) > 0.00001 { t.Fatal(geoms[0].Area()) } // ignore z values - r = bytes.NewBufferString(`{"type": "Polygon", "coordinates": [[[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0], [0, 0, 0]]]}`) + r = bytes.NewBufferString(`{"type": "Polygon", "coordinates": [[[1000, 1000, 1000], [2000, 1000, 1000], [2000, 2000, 1000], [1000, 2000, 1000], [1000, 1000, 1000]]]}`) geoms, err = ParseGeoJson(r) if err != nil { @@ -34,11 +34,11 @@ func TestParsePolygon(t *testing.T) { t.Fatal(geoms) } - if math.Abs(geoms[0].Area()-100) > 0.00001 { + if math.Abs(geoms[0].Area()-1000000) > 0.00001 { t.Fatal(geoms[0].Area()) } - r = bytes.NewBufferString(`{"type": "Polygon", "coordinates": [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], [[5, 5], [6, 5], [6, 6], [5, 6], [5, 5]]]}`) + r = bytes.NewBufferString(`{"type": "Polygon", "coordinates": [[[1000, 1000], [2000, 1000], [2000, 2000], [1000, 2000], [1000, 1000]], [[500, 500], [600, 500], [600, 600], [500, 600], [500, 500]]]}`) geoms, err = ParseGeoJson(r) if err != nil { @@ -49,7 +49,7 @@ func TestParsePolygon(t *testing.T) { t.Fatal(geoms) } - if math.Abs(geoms[0].Area()-99) > 0.00001 { + if math.Abs(geoms[0].Area()-990000) > 0.00001 { t.Fatal(geoms[0].Area()) } @@ -57,8 +57,8 @@ func TestParsePolygon(t *testing.T) { func TestParseMultiPolygon(t *testing.T) { r := bytes.NewBufferString(`{"type": "MultiPolygon", "coordinates": - [[[[0, 0], [10, 0], [10, 10], [0, 0]]], - [[[0, 0], [10, 0], [10, 10], [0, 0]]]] + [[[[1000, 1000], [2000, 1000], [2000, 2000], [1000, 1000]]], + [[[1000, 1000], [2000, 1000], [2000, 2000], [1000, 1000]]]] }`) geoms, err := ParseGeoJson(r) @@ -73,7 +73,7 @@ func TestParseMultiPolygon(t *testing.T) { func TestParseFeature(t *testing.T) { r := bytes.NewBufferString(`{"type": "Feature", "geometry": { - "type": "Polygon", "coordinates": [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]] + "type": "Polygon", "coordinates": [[[1000, 1000], [2000, 1000], [2000, 2000], [1000, 2000], [1000, 1000]]] }}`) geoms, err := ParseGeoJson(r) @@ -84,7 +84,7 @@ func TestParseFeature(t *testing.T) { if len(geoms) != 1 { t.Fatal(geoms) } - if math.Abs(geoms[0].Area()-100) > 0.00001 { + if math.Abs(geoms[0].Area()-1000000) > 0.00001 { t.Fatal(geoms[0].Area()) } } @@ -92,10 +92,10 @@ func TestParseFeature(t *testing.T) { func TestParseFeatureCollection(t *testing.T) { r := bytes.NewBufferString(`{"type": "FeatureCollection", "features": [ {"type": "Feature", "geometry": - {"type": "Polygon", "coordinates": [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]]} + {"type": "Polygon", "coordinates": [[[1000, 1000], [2000, 1000], [2000, 2000], [1000, 2000], [1000, 1000]]]} }, {"type": "Feature", "geometry": - {"type": "Polygon", "coordinates": [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]]} + {"type": "Polygon", "coordinates": [[[1000, 1000], [2000, 1000], [2000, 2000], [1000, 2000], [1000, 1000]]]} } ]}`) geoms, err := ParseGeoJson(r) @@ -107,7 +107,54 @@ func TestParseFeatureCollection(t *testing.T) { if len(geoms) != 2 { t.Fatal(geoms) } - if math.Abs(geoms[0].Area()-100) > 0.00001 { + if math.Abs(geoms[0].Area()-1000000) > 0.00001 { + t.Fatal(geoms[0].Area()) + } +} + +func TestParseGeoJson(t *testing.T) { + r := bytes.NewBufferString(`{"type": "FeatureCollection", "features": [ + {"type": "Feature", "geometry": + {"type": "Polygon", "coordinates": [[[1000, 1000], [2000, 1000], [2000, 2000], [1000, 2000], [1000, 1000]]]} + }, + {"type": "Feature", "geometry": + {"type": "Polygon", "coordinates": [[[1000, 1000], [2000, 1000], [2000, 2000], [1000, 2000], [1000, 1000]]]} + } + ]}`) + geoms, err := ParseGeoJson(r) + + if err != nil { + t.Fatal(err) + } + + if len(geoms) != 2 { + t.Fatal(geoms) + } + if math.Abs(geoms[0].Area()-1000000) > 0.00001 { + t.Fatal(geoms[0].Area()) + } +} + +func TestParseGeoJsonTransform(t *testing.T) { + // automatically transforms WGS84 to webmercator + r := bytes.NewBufferString(`{"type": "FeatureCollection", "features": [ + {"type": "Feature", "geometry": + {"type": "Polygon", "coordinates": [[[8, 53], [9, 53], [9, 54], [8, 54], [8, 53]]]} + }, + {"type": "Feature", "geometry": + {"type": "Polygon", "coordinates": [[[9, 53], [10, 53], [10, 54], [9, 54], [9, 53]]]} + } + ]}`) + geoms, err := ParseGeoJson(r) + + if err != nil { + t.Fatal(err) + } + + if len(geoms) != 2 { + t.Fatal(geoms) + } + if math.Abs(geoms[0].Area()-20834374847.98027) > 0.01 { t.Fatal(geoms[0].Area()) } } diff --git a/proj/proj.go b/proj/proj.go index 8157efa..1406428 100644 --- a/proj/proj.go +++ b/proj/proj.go @@ -7,13 +7,13 @@ import ( const pole = 6378137 * math.Pi // 20037508.342789244 -func wgsToMerc(long, lat float64) (x, y float64) { +func WgsToMerc(long, lat float64) (x, y float64) { x = long * pole / 180.0 y = math.Log(math.Tan((90.0+lat)*math.Pi/360.0)) / math.Pi * pole return x, y } -func mercToWgs(x, y float64) (long, lat float64) { +func MercToWgs(x, y float64) (long, lat float64) { long = 180.0 * x / pole lat = 180.0 / math.Pi * (2*math.Atan(math.Exp((y/pole)*math.Pi)) - math.Pi/2) return long, lat @@ -21,10 +21,10 @@ func mercToWgs(x, y float64) (long, lat float64) { func NodesToMerc(nodes []element.Node) { for i, nd := range nodes { - nodes[i].Long, nodes[i].Lat = wgsToMerc(nd.Long, nd.Lat) + nodes[i].Long, nodes[i].Lat = WgsToMerc(nd.Long, nd.Lat) } } func NodeToMerc(node *element.Node) { - node.Long, node.Lat = wgsToMerc(node.Long, node.Lat) + node.Long, node.Lat = WgsToMerc(node.Long, node.Lat) } diff --git a/proj/proj_test.go b/proj/proj_test.go index b56613e..a612997 100644 --- a/proj/proj_test.go +++ b/proj/proj_test.go @@ -6,23 +6,23 @@ import ( ) func TestWgsToMerc(t *testing.T) { - x, y := wgsToMerc(0, 0) + x, y := WgsToMerc(0, 0) if x != 0 || y != 0 { t.Fatalf("%v %v", x, y) } - x, y = wgsToMerc(8, 53) + x, y = WgsToMerc(8, 53) if math.Abs(x-890555.9263461898) > 1e-6 || math.Abs(y-6982997.920389788) > 1e-6 { t.Fatalf("%v %v", x, y) } } func TestMercToWgs(t *testing.T) { - long, lat := mercToWgs(0, 0) + long, lat := MercToWgs(0, 0) if long != 0 || lat != 0 { t.Fatalf("%v %v", long, lat) } - long, lat = mercToWgs(890555.9263461898, 6982997.920389788) + long, lat = MercToWgs(890555.9263461898, 6982997.920389788) if math.Abs(long-8) > 1e-6 || math.Abs(lat-53) > 1e-6 { t.Fatalf("%v %v", long, lat) }