Skip to content

Commit de7798f

Browse files
arnesetzerajnisbet
andauthored
Feature: Output as geojson Feature Collection (#86)
* Add support for geojson output * Fix failed tests * Change to correct geojson syntax * formatting * documentation geojson * Fix lon lat order --------- Co-authored-by: arnsetzer <[email protected]> Co-authored-by: Andrew Nisbet <[email protected]>
1 parent 0b64919 commit de7798f

File tree

2 files changed

+84
-9
lines changed

2 files changed

+84
-9
lines changed

docs/api.md

+58
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@ Latitudes and longitudes should be in `EPSG:4326` (also known as WGS-84 format),
2424
* The default option `null` makes NODATA indistinguishable from a location outside the dataset bounds.
2525
* `NaN` (not a number) values aren't valid in json and will break some clients. The `nan` option was default before version 1.4 and is provided only for backwards compatibility.
2626
* When querying multiple datasets, this NODATA replacement only applies to the last dataset in the stack.
27+
* `geojson`: If set to `True` the response will be in geojson according to RFC7946.
2728

2829

2930

3031

3132
### Response
3233

34+
#### Default
35+
3336
A json object, compatible with the Google Maps Elevation API.
3437

3538
* `status`: Will be `OK` for a successful request, `INVALID_REQUEST` for an input (4xx) error, and `SERVER_ERROR` for anything else (5xx). Required.
@@ -46,8 +49,21 @@ Some notes about the elevation value:
4649
* If the request location isn't covered by any raster in the dataset, Open Topo Data will return `null`.
4750
* Unless the `nodata_value` parameter is set, a `null` elevation could either mean the location is outside the dataset bounds, or a NODATA within the raster bounds.
4851

52+
#### Geojson
4953

54+
A json object, fulfilling the RFC 7946 or an error message
55+
* `type`: FeatureCollection
56+
* `features`: An array of provided points
57+
* `type`: Feature
58+
* `geometry`
59+
* `type`: Point
60+
* `coordinates`: Longitude, latitude and Elevation
61+
* `properties`
62+
* `dataset`: Name of the dataset
5063

64+
In case of an error:
65+
* `status`: Will be `OK` for a successful request, `INVALID_REQUEST` for an input (4xx) error, and `SERVER_ERROR` for anything else (5xx). Required.
66+
* `error`: Description of what went wrong, when `status` isn't `OK`.
5167
### Example
5268

5369
`GET` <a href="https://api.opentopodata.org/v1/srtm90m?locations=-43.5,172.5|27.6,1.98&interpolation=cubic">api.opentopodata.org/v1/srtm90m?locations=-43.5,172.5|27.6,1.98&interpolation=cubic</a>
@@ -79,6 +95,48 @@ Some notes about the elevation value:
7995
}
8096
```
8197

98+
#### With geojson
99+
100+
`GET` <a href="https://api.opentopodata.org/v1/srtm90m?locations=-43.5,172.5|27.6,1.98&interpolation=cubic&geojson=True">api.opentopodata.org/v1/srtm90m?locations=-43.5,172.5|27.6,1.98&interpolation=cubic&geojson=True</a>
101+
102+
103+
104+
105+
```json
106+
{
107+
"features": [
108+
{
109+
"geometry": {
110+
"coordinates": [
111+
172.5,
112+
-43.5,
113+
45
114+
],
115+
"type": "Point"
116+
},
117+
"properties": {
118+
"dataset": "srtm90m"
119+
},
120+
"type": "Feature"
121+
},
122+
{
123+
"geometry": {
124+
"coordinates": [
125+
1.98,
126+
27.6,
127+
402
128+
],
129+
"type": "Point"
130+
},
131+
"properties": {
132+
"dataset": "srtm90m"
133+
},
134+
"type": "Feature"
135+
}
136+
],
137+
"type": "FeatureCollection"
138+
}
139+
```
82140
---
83141

84142

opentopodata/api.py

+26-9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
LON_MIN = -180
2020
LON_MAX = 180
2121
VERSION_PATH = "VERSION"
22+
DEFAULT_GEOJSON_VALUE = False
2223

2324

2425
# Memcache is used to store the latlon -> filename lookups, which can take a
@@ -524,6 +525,10 @@ def get_elevation(dataset_name):
524525
_find_request_argument(request, "locations"),
525526
_load_config()["max_locations_per_request"],
526527
)
528+
try:
529+
geojson = _find_request_argument(request, "geojson")
530+
except:
531+
geojson = DEFAULT_GEOJSON_VALUE
527532

528533
# Check if need to do sampling.
529534
n_samples = _parse_n_samples(
@@ -541,15 +546,27 @@ def get_elevation(dataset_name):
541546

542547
# Build response.
543548
results = []
544-
for z, dataset_name, lat, lon in zip(elevations, dataset_names, lats, lons):
545-
results.append(
546-
{
547-
"elevation": z,
548-
"dataset": dataset_name,
549-
"location": {"lat": lat, "lng": lon},
550-
}
551-
)
552-
data = {"status": "OK", "results": results}
549+
# Return the results in geojson format. Default false to keep API consistancy
550+
if geojson:
551+
for z, dataset_name, lat, lon in zip(elevations, dataset_names, lats, lons):
552+
results.append(
553+
{
554+
"type": "Feature",
555+
"geometry": {"type": "Point", "coordinates": [lon, lat, z]},
556+
"properties": {"dataset": dataset_name},
557+
},
558+
)
559+
data = {"type": "FeatureCollection", "features": results}
560+
else:
561+
for z, dataset_name, lat, lon in zip(elevations, dataset_names, lats, lons):
562+
results.append(
563+
{
564+
"elevation": z,
565+
"dataset": dataset_name,
566+
"location": {"lat": lat, "lng": lon},
567+
}
568+
)
569+
data = {"status": "OK", "results": results}
553570
return jsonify(data)
554571

555572
except (ClientError, backend.InputError) as e:

0 commit comments

Comments
 (0)