geocode: if Google returns a whole-world geometry, use its viewport instead

Change-Id: Iec4abf2ad117ab37a3f23fedc12e6e7b3943fc4e
This commit is contained in:
Brad Fitzpatrick 2014-01-25 09:26:18 -08:00
parent 9abba638a0
commit 466f166817
2 changed files with 98 additions and 16 deletions

View File

@ -89,6 +89,7 @@ type googleResult struct {
type googleGeometry struct {
Bounds *Rect `json:"bounds"`
Viewport *Rect `json:"viewport"`
}
func decodeGoogleResponse(r io.Reader) (rects []Rect, err error) {
@ -98,7 +99,17 @@ func decodeGoogleResponse(r io.Reader) (rects []Rect, err error) {
}
for _, res := range resTop.Results {
if res.Geometry != nil && res.Geometry.Bounds != nil {
rects = append(rects, *res.Geometry.Bounds)
r := res.Geometry.Bounds
if r.NorthEast.Lat == 90 && r.NorthEast.Long == 180 &&
r.SouthWest.Lat == -90 && r.SouthWest.Long == -180 {
// Google sometimes returns a "whole world" rect for large addresses (like "USA")
// so instead use the viewport in that case.
if res.Geometry.Viewport != nil {
rects = append(rects, *res.Geometry.Viewport)
}
} else {
rects = append(rects, *r)
}
}
}
return

View File

@ -24,11 +24,15 @@ import (
)
func TestDecodeGoogleResponse(t *testing.T) {
rects, err := decodeGoogleResponse(strings.NewReader(googleRes))
if err != nil {
t.Fatal(err)
}
want := []Rect{
tests := []struct {
name string
res string
want []Rect
}{
{
name: "moscow",
res: googleMoscow,
want: []Rect{
Rect{
NorthEast: LatLong{pf("56.009657"), pf("37.945661")},
SouthWest: LatLong{pf("55.48992699999999"), pf("37.319329")},
@ -37,9 +41,28 @@ func TestDecodeGoogleResponse(t *testing.T) {
NorthEast: LatLong{pf("46.758882"), pf("-116.962068")},
SouthWest: LatLong{pf("46.710912"), pf("-117.039698")},
},
},
},
{
name: "usa",
res: googleUSA,
want: []Rect{
Rect{
NorthEast: LatLong{pf("49.38"), pf("-66.94")},
SouthWest: LatLong{pf("25.82"), pf("-124.39")},
},
},
},
}
for _, tt := range tests {
rects, err := decodeGoogleResponse(strings.NewReader(tt.res))
if err != nil {
t.Errorf("Decoding %s: %v", tt.name, err)
continue
}
if !reflect.DeepEqual(rects, tt.want) {
t.Errorf("Test %s: wrong rects\n Got %#v\nWant %#v", tt.name, rects, tt.want)
}
if !reflect.DeepEqual(rects, want) {
t.Errorf("wrong rects\n Got %#v\nWant %#v", rects, want)
}
}
@ -52,7 +75,7 @@ func pf(s string) float64 {
return v
}
var googleRes = `
var googleMoscow = `
{
"results" : [
{
@ -165,3 +188,51 @@ var googleRes = `
"status" : "OK"
}
`
// Response for "usa".
// Note the geometry bounds covering the whole world. In this case, use the viewport instead.
var googleUSA = `
{
"results" : [
{
"address_components" : [
{
"long_name" : "United States",
"short_name" : "US",
"types" : [ "country", "political" ]
}
],
"formatted_address" : "United States",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 90,
"lng" : 180
},
"southwest" : {
"lat" : -90,
"lng" : -180
}
},
"location" : {
"lat" : 37.09024,
"lng" : -95.712891
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 49.38,
"lng" : -66.94
},
"southwest" : {
"lat" : 25.82,
"lng" : -124.39
}
}
},
"types" : [ "country", "political" ]
}
],
"status" : "OK"
}
`