/
geocoder.go
100 lines (88 loc) · 2.42 KB
/
geocoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Package tomtom is a geo-golang based TomTom geocode/reverse geocode client
package tomtom
import (
"fmt"
"strings"
geo "github.com/codingsince1985/geo-golang"
)
type (
baseURL string
geocodeResponse struct {
Summary struct {
Query string
}
Results []struct {
Position struct {
Lat float64
Lon float64
}
}
// Reverse Geocoding response
Addresses []struct {
Address struct {
BuildingNumber string
StreetNumber string
Street string
StreetName string
StreetNameAndNumber string
CountryCode string
CountrySubdivision string // state code
CountrySecondarySubdivision string
CountryTertiarySubdivision string
Municipality string // city
PostalCode string
Country string
CountryCodeISO3 string
FreeformAddress string
CountrySubdivisionName string
}
}
}
)
// Geocoder constructs TomTom geocoder
func Geocoder(key string, baseURLs ...string) geo.Geocoder {
return geo.HTTPGeocoder{
EndpointBuilder: baseURL(getUrl(key, baseURLs...)),
ResponseParserFactory: func() geo.ResponseParser { return &geocodeResponse{} },
}
}
func getUrl(key string, baseURLs ...string) string {
if len(baseURLs) > 0 {
return baseURLs[0]
}
return "https://api.tomtom.com/search/2/*?key=" + key
}
func (b baseURL) GeocodeURL(address string) string {
params := fmt.Sprintf("geocode/%s.json", address)
return strings.Replace(string(b), "*", params, 1)
}
func (b baseURL) ReverseGeocodeURL(l geo.Location) string {
params := fmt.Sprintf("reverseGeocode/%f,%f", l.Lat, l.Lng)
return strings.Replace(string(b), "*", params, 1)
}
func (r *geocodeResponse) Location() (*geo.Location, error) {
if len(r.Results) > 0 {
p := r.Results[0].Position
return &geo.Location{
Lat: p.Lat,
Lng: p.Lon,
}, nil
}
return nil, nil
}
func (r *geocodeResponse) Address() (*geo.Address, error) {
if len(r.Addresses) > 0 {
a := r.Addresses[0].Address
return &geo.Address{
FormattedAddress: a.FreeformAddress,
Street: a.StreetName,
HouseNumber: a.StreetNumber,
City: a.Municipality,
Postcode: a.PostalCode,
State: a.CountrySubdivision,
Country: a.Country,
CountryCode: a.CountryCode,
}, nil
}
return nil, nil
}