From e864f2a8af911d708272df9f4e8f5585f0fc4302 Mon Sep 17 00:00:00 2001 From: Jason Hall Date: Thu, 5 Mar 2015 13:25:12 -0500 Subject: [PATCH] Add SnapToRoads which requires API key This uncovered a bug in maps.go where requests would not pass their API key! --- maps.go | 2 +- maps_test.go | 27 +++++++++++++++++++++++ roads.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 roads.go diff --git a/maps.go b/maps.go index 77d8072..5bd015e 100644 --- a/maps.go +++ b/maps.go @@ -58,7 +58,7 @@ func do(ctx context.Context, url string) (*http.Response, error) { enc += "&signature=" + sig } req.URL.RawQuery = enc - return cl.Get(url) + return cl.Do(req) } // See https://developers.google.com/maps/documentation/business/webservices/auth diff --git a/maps_test.go b/maps_test.go index 7e6a21c..346f9b8 100644 --- a/maps_test.go +++ b/maps_test.go @@ -1,6 +1,7 @@ package maps import ( + "flag" "image/color" "net/http" "testing" @@ -8,10 +9,16 @@ import ( ) var ( + apiKey = flag.String("apiKey", "", "Google Maps API key") + ctx = NewContext("key", &http.Client{}) wctx = NewWorkContext("clientID", "privKey", &http.Client{}) ) +func init() { + flag.Parse() +} + func TestDirections(t *testing.T) { orig, dest := Address("111 8th Ave, NYC"), Address("170 E 92nd St, NYC") opts := &DirectionsOpts{ @@ -174,7 +181,27 @@ func TestDistanceMatrix(t *testing.T) { t.Errorf("unexpected error: %v", err) } t.Logf("%v", r) +} +func TestSnapToRoads(t *testing.T) { + ctx = NewContext(*apiKey, &http.Client{}) + + path := []LatLng{{-35.27801, 149.12958}, + {-35.28032, 149.12907}, + {-35.28099, 149.12929}, + {-35.28144, 149.12984}, + {-35.28194, 149.13003}, + {-35.28282, 149.12956}, + {-35.28302, 149.12881}, + {-35.28473, 149.12836}} + opts := &SnapToRoadsOpts{ + Interpolate: true, + } + r, err := SnapToRoads(ctx, path, opts) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + t.Logf("%v", r) } // Based on https://developers.google.com/maps/documentation/business/webservices/auth#signature_examples diff --git a/roads.go b/roads.go new file mode 100644 index 0000000..d06de9c --- /dev/null +++ b/roads.go @@ -0,0 +1,62 @@ +package maps + +import ( + "net/url" + + "code.google.com/p/go.net/context" +) + +const roadsAPIBaseURL = "https://roads.googleapis.com/v1/" + +func SnapToRoads(ctx context.Context, path []LatLng, opts *SnapToRoadsOpts) ([]SnappedPoint, error) { + var d snapToRoadsResponse + if err := doDecode(ctx, roadsAPIBaseURL+snapToRoads(path, opts), &d); err != nil { + return nil, err + } + return d.SnappedPoints, nil +} + +func snapToRoads(path []LatLng, opts *SnapToRoadsOpts) string { + p := url.Values{} + p.Set("path", encodeLatLngs(path)) + opts.update(p) + return "snapToRoads?" + p.Encode() +} + +// SnapToRoadsOpts defines options for SnapToRoads requests. +type SnapToRoadsOpts struct { + // Whether to interpolate a path to include all points forming the full road-geometry. + Interpolate bool +} + +func (o SnapToRoadsOpts) update(p url.Values) { + if o.Interpolate { + p.Set("interpolate", "true") + } +} + +type snapToRoadsResponse struct { + SnappedPoints []SnappedPoint `json:"snappedPoints"` +} + +// SnappedPoint represents a location derived from a SnapToRoads request. +type SnappedPoint struct { + // The latitude and longitude of the snapped location. + Location SnappedLocation `json:"location"` + + // The index of the corresponding value in the original request. + // + // Each value in the request should map to a snapped value in the response. However, if you've set Interpolate to be true, then it's possible that the response will contain more coordinates than the request. Interpolated values will have this value set to nil. + OriginalIndex *int `json:"originalIndex,omitempty"` + + // A unique identifier for a Place corresponding to a road segment. + PlaceID string `json:"placeId"` +} + +// SnappedLocation is equivalent to LatLng +// +// TODO(jasonhall): Reconcile this with LatLng which expects JSON fields lat/lng +type SnappedLocation struct { + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` +}