Skip to content

Commit 682b331

Browse files
committed
Add upport for elevation checking
1 parent 21d6c55 commit 682b331

File tree

2 files changed

+231
-17
lines changed

2 files changed

+231
-17
lines changed

elevation.go

+111-6
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,123 @@
11
package geonames
22

3-
type ElevationSRTM1 struct {
3+
import (
4+
"context"
5+
"fmt"
6+
)
7+
8+
type srtm1Resp struct {
49
Srtm1 int `json:"srtm1"`
510
Lng float64 `json:"lng"`
611
Lat float64 `json:"lat"`
712
}
813

14+
type srtm3Resp struct {
15+
Srtm3 int `json:"srtm3"`
16+
Lng float64 `json:"lng"`
17+
Lat float64 `json:"lat"`
18+
}
19+
20+
type asterResp struct {
21+
Astergdem int `json:"astergdem"`
22+
Lng float64 `json:"lng"`
23+
Lat float64 `json:"lat"`
24+
}
25+
26+
type gtopoResp struct {
27+
Gtopo30 int `json:"gtopo30"`
28+
Lng float64 `json:"lng"`
29+
Lat float64 `json:"lat"`
30+
}
31+
32+
// Elevation holds elevation data expressed in meters npm.
933
type Elevation struct {
10-
Type string
11-
Lat float64
12-
Lng float64
34+
Type string
35+
Lat float64
36+
Lng float64
37+
Value int
38+
}
39+
40+
// GetElevationSRTM1 takes two float numbers representing latitude and longitude
41+
// and returns elevation in meters according to SRMT1. The sample area is ca 30m x 30m.
42+
// Ocean areas returns "no data", and have assigned a value of -32768.
43+
func (c *Client) GetElevationSRTM1(ctx context.Context, lat, lng float64) (Elevation, error) {
44+
path := fmt.Sprintf("/srtm1JSON?lat=%.3f&lng=%.3f&username=%s", lat, lng, c.UserName)
45+
var er srtm1Resp
46+
err := c.get(ctx, c.BaseURL+path, &er)
47+
if err != nil {
48+
return Elevation{}, err
49+
}
50+
e := Elevation{
51+
Type: "srtm1",
52+
Lat: er.Lat,
53+
Lng: er.Lng,
54+
Value: er.Srtm1,
55+
}
56+
return e, nil
1357
}
1458

15-
func GetElevationSRTM1() Elevation {
59+
// GetElevationSRTM3 takes two float numbers representing latitude and longitude
60+
// and returns elevation in meters according to SRMT3.
61+
//
62+
// SRTM data consisted of a specially modified radar system that flew
63+
// onboard the Space Shuttle Endeavour during an 11-day mission in February of 2000.
64+
// The dataset covers land areas between 60 degrees north and 56 degrees south.
65+
// SRTM3 data are data points located every 3-arc-second (approximately 90 meters) on a latitude/longitude grid.
66+
func (c *Client) GetElevationSRTM3(ctx context.Context, lat, lng float64) (Elevation, error) {
67+
path := fmt.Sprintf("/srtm3JSON?lat=%.3f&lng=%.3f&username=%s", lat, lng, c.UserName)
68+
var er srtm3Resp
69+
err := c.get(ctx, c.BaseURL+path, &er)
70+
if err != nil {
71+
return Elevation{}, err
72+
}
73+
e := Elevation{
74+
Type: "srtm3",
75+
Lat: er.Lat,
76+
Lng: er.Lng,
77+
Value: er.Srtm3,
78+
}
79+
return e, nil
80+
}
81+
82+
// GetElevationAstergdem returns elevation in meters according to aster gdem.
83+
//
84+
// Sample are: ca 30m x 30m, between 83N and 65S latitude. Ocean areas have been assigned a value of -32768
85+
func (c *Client) GetElevationAstergdem(ctx context.Context, lat, lng float64) (Elevation, error) {
86+
path := fmt.Sprintf("/astergdemJSON?lat=%.3f&lng=%.3f&username=%s", lat, lng, c.UserName)
87+
var er asterResp
88+
err := c.get(ctx, c.BaseURL+path, &er)
89+
if err != nil {
90+
return Elevation{}, err
91+
}
92+
e := Elevation{
93+
Type: "astergdem",
94+
Lat: er.Lat,
95+
Lng: er.Lng,
96+
Value: er.Astergdem,
97+
}
98+
return e, nil
99+
}
16100

17-
return Elevation{}
101+
// GetElevationGTOPO30 returns elevation data sampled for the area of 1km x 1km.
102+
//
103+
// Ocean areas have assigned value of -9999 indicating no data for the requested lat and lng.
104+
// GTOPO30 is a global digital elevation model (DEM) with a horizontal grid spacing
105+
// of 30 arc seconds (approximately 1 kilometer).
106+
// GTOPO30 is derived from several raster and vector sources of topographic information.
107+
//
108+
// Documentation: http://eros.usgs.gov/#/Find_Data/Products_and_Data_Available/gtopo30_info
109+
func (c *Client) GetElevationGTOPO30(ctx context.Context, lat, lng float64) (Elevation, error) {
110+
path := fmt.Sprintf("/gtopo30JSON?lat=%.3f&lng=%.3f&username=%s", lat, lng, c.UserName)
111+
var er gtopoResp
112+
err := c.get(ctx, c.BaseURL+path, &er)
113+
if err != nil {
114+
return Elevation{}, err
115+
}
116+
e := Elevation{
117+
Type: "gtopo30",
118+
Lat: er.Lat,
119+
Lng: er.Lng,
120+
Value: er.Gtopo30,
121+
}
122+
return e, nil
18123
}

elevation_test.go

+120-11
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,157 @@ package geonames_test
22

33
import (
44
"bytes"
5+
"context"
6+
"fmt"
57
"io"
68
"net/http"
79
"net/http/httptest"
810
"testing"
911

12+
"github.com/google/go-cmp/cmp"
1013
"github.com/qba73/geonames"
1114
)
1215

13-
// ts is a helper func that creates a test server with embedded URI validation.
14-
var testServer = func(reader io.Reader, wantURI string, t *testing.T) *httptest.Server {
16+
// newElevationtestServer creates a test server with embedded URI validation.
17+
func newElevationTestServer(data []byte, wantURI string, t *testing.T) *httptest.Server {
1518
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
1619
gotReqURI := r.RequestURI
1720
verifyURIs(wantURI, gotReqURI, t)
18-
_, err := io.Copy(rw, reader)
21+
_, err := io.Copy(rw, bytes.NewBuffer(data))
1922
if err != nil {
2023
t.Fatal(err)
2124
}
2225
}))
2326
return ts
2427
}
2528

26-
func TestGetElevationReturnsDataOnValidInput(t *testing.T) {
29+
func TestGetElevationSRTM1ReturnsDataOnValidInput(t *testing.T) {
2730
t.Parallel()
2831

29-
resp := new(bytes.Buffer)
30-
resp.Read([]byte(`23`))
32+
lat, lng := 50.0, 50.0
33+
wantReqURI := fmt.Sprintf("/srtm1JSON?lat=%.3f&lng=%.3f&username=DummyUser", lat, lng)
3134

32-
ts := testServer(&resp)
35+
ts := newElevationTestServer(srtm1, wantReqURI, t)
36+
defer ts.Close()
37+
38+
client, err := geonames.NewClient("DummyUser", geonames.WithBaseURL(ts.URL))
39+
if err != nil {
40+
t.Fatal(err)
41+
}
42+
43+
want := geonames.Elevation{
44+
Type: "srtm1",
45+
Lat: 54.166,
46+
Lng: -6.083,
47+
Value: 375,
48+
}
3349

50+
got, err := client.GetElevationSRTM1(context.Background(), lat, lng)
51+
if err != nil {
52+
t.Fatal(err)
53+
}
54+
55+
if !cmp.Equal(want, got) {
56+
t.Error(cmp.Diff(want, got))
57+
}
3458
}
3559

36-
func TestGetElevationValidInput(t *testing.T) {
60+
func TestGetElevationSRTM3ReturnsDataOnValidInput(t *testing.T) {
3761
t.Parallel()
3862

39-
wantReqURI := "/srtm1JSON?lat=50&lng=50&username=DummyUser"
40-
ts := newTestServer(testFile, wantReqURI, t)
63+
lat, lng := 55.166, -6.088
64+
wantReqURI := fmt.Sprintf("/srtm3JSON?lat=%.3f&lng=%.3f&username=DummyUser", lat, lng)
65+
66+
ts := newElevationTestServer(srtm3, wantReqURI, t)
4167
defer ts.Close()
4268

4369
client, err := geonames.NewClient("DummyUser", geonames.WithBaseURL(ts.URL))
4470
if err != nil {
4571
t.Fatal(err)
4672
}
4773

48-
client.GetElevation()
74+
want := geonames.Elevation{
75+
Type: "srtm3",
76+
Lat: 55.166,
77+
Lng: -6.088,
78+
Value: 263,
79+
}
80+
81+
got, err := client.GetElevationSRTM3(context.Background(), lat, lng)
82+
if err != nil {
83+
t.Fatal(err)
84+
}
85+
86+
if !cmp.Equal(want, got) {
87+
t.Error(cmp.Diff(want, got))
88+
}
4989
}
90+
91+
func TestGetElevationAstergdemReturnsDataOnValidInput(t *testing.T) {
92+
t.Parallel()
93+
94+
lat, lng := 50.01, 10.20
95+
wantReqURI := fmt.Sprintf("/astergdemJSON?lat=%.3f&lng=%.3f&username=DummyUser", lat, lng)
96+
97+
ts := newElevationTestServer(astergdem, wantReqURI, t)
98+
defer ts.Close()
99+
100+
client, err := geonames.NewClient("DummyUser", geonames.WithBaseURL(ts.URL))
101+
if err != nil {
102+
t.Fatal(err)
103+
}
104+
105+
want := geonames.Elevation{
106+
Type: "astergdem",
107+
Lat: 50.010,
108+
Lng: 10.200,
109+
Value: 206,
110+
}
111+
112+
got, err := client.GetElevationAstergdem(context.Background(), lat, lng)
113+
if err != nil {
114+
t.Fatal(err)
115+
}
116+
117+
if !cmp.Equal(want, got) {
118+
t.Error(cmp.Diff(want, got))
119+
}
120+
}
121+
122+
func TestGetElevationGTOPO30ReturnsDataOnValidInput(t *testing.T) {
123+
t.Parallel()
124+
125+
lat, lng := 47.01, 10.2
126+
wantReqURI := fmt.Sprintf("/gtopo30JSON?lat=%.3f&lng=%.3f&username=DummyUser", lat, lng)
127+
128+
ts := newElevationTestServer(gtopo30, wantReqURI, t)
129+
defer ts.Close()
130+
131+
client, err := geonames.NewClient("DummyUser", geonames.WithBaseURL(ts.URL))
132+
if err != nil {
133+
t.Fatal(err)
134+
}
135+
136+
want := geonames.Elevation{
137+
Type: "gtopo30",
138+
Lat: 47.01,
139+
Lng: 10.20,
140+
Value: 2632,
141+
}
142+
143+
got, err := client.GetElevationGTOPO30(context.Background(), lat, lng)
144+
if err != nil {
145+
t.Fatal(err)
146+
}
147+
148+
if !cmp.Equal(want, got) {
149+
t.Error(cmp.Diff(want, got))
150+
}
151+
}
152+
153+
var (
154+
srtm1 = []byte(`{"srtm1":375,"lng":-6.083,"lat":54.166}`)
155+
srtm3 = []byte(`{"srtm3":263,"lng":-6.088,"lat":55.166}`)
156+
astergdem = []byte(`{"lng":10.2,"astergdem":206,"lat":50.01}`)
157+
gtopo30 = []byte(`{"lng":10.2,"gtopo30":2632,"lat":47.01}`)
158+
)

0 commit comments

Comments
 (0)