Comments (5)
(To preempt "Why not just use docker?", mostly it's because docker is a monster to install on Windows. Any project that you can run without needing Docker is a sigh of relief)
from open-elevation.
Example rewrite without gunicorn (obviously not polished, but good enough for my needs):
import configparser
import json
import os
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs, urlparse
from gdal_interfaces import GDALTileInterface
class InternalException(ValueError):
"""
Utility exception class to handle errors internally and return error codes to the client
"""
pass
print('Reading config file ...')
parser = configparser.ConfigParser()
parser.read('config.ini')
HOST = '127.0.0.1'
PORT = 9000
DATA_FOLDER = parser.get('server', 'data-folder')
OPEN_INTERFACES_SIZE = parser.getint('server', 'open-interfaces-size')
interface = GDALTileInterface(
DATA_FOLDER, '%s/summary.json' % DATA_FOLDER, OPEN_INTERFACES_SIZE)
interface.create_summary_json()
def get_elevation(lat, lng):
"""
Get the elevation at point (lat,lng) using the currently opened interface
:param lat:
:param lng:
:return:
"""
try:
elevation = interface.lookup(lat, lng)
except:
return {
'latitude': lat,
'longitude': lng,
'error': 'No such coordinate (%s, %s)' % (lat, lng)
}
return {
'latitude': lat,
'longitude': lng,
'elevation': elevation
}
def lat_lng_from_location(location_with_comma):
"""
Parse the latitude and longitude of a location in the format "xx.xxx,yy.yyy" (which we accept as a query string)
:param location_with_comma:
:return:
"""
try:
lat, lng = [float(i) for i in location_with_comma.split(',')]
return lat, lng
except:
raise InternalException(json.dumps(
{'error': 'Bad parameter format "%s".' % location_with_comma}))
def query_to_locations(query):
"""
Grab a list of locations from the query and turn them into [(lat,lng),(lat,lng),...]
:return:
"""
locations = query['locations'][0] if 'locations' in query else None
if not locations:
raise InternalException(json.dumps(
{'error': '"Locations" is required.'}))
return [lat_lng_from_location(l) for l in locations.split('|')]
def body_to_locations(payload):
"""
Grab a list of locations from the body and turn them into [(lat,lng),(lat,lng),...]
:return:
"""
try:
locations = payload.get('locations', None)
except Exception:
raise InternalException(json.dumps({'error': 'Invalid JSON.'}))
if not locations:
raise InternalException(json.dumps(
{'error': '"Locations" is required in the body.'}))
latlng = []
for l in locations:
try:
latlng += [(l['latitude'], l['longitude'])]
except KeyError:
raise InternalException(json.dumps(
{'error': '"%s" is not in a valid format.' % l}))
return latlng
def do_lookup(locations):
"""
Generic method which gets the locations in [(lat,lng),(lat,lng),...] format by calling get_locations_func
and returns an answer ready to go to the client.
:return:
"""
return {'results': [get_elevation(lat, lng) for (lat, lng) in locations]}
class OpenElevationServer(BaseHTTPRequestHandler):
def set_headers(self):
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Cache-Control', 'no-cache')
self.send_header('Content-type', 'application/json')
self.end_headers()
def log_request(self, code='-', size='-'):
# Don't log regular requests, only error
return
def do_GET(self):
"""
GET method. Uses query_to_locations.
:return:
"""
if self.path == '/favicon.ico':
return self.send_response(404)
query = parse_qs(urlparse(self.path).query)
try:
data = do_lookup(query_to_locations(query))
response = json.dumps(data).encode('utf-8')
self.set_headers()
self.wfile.write(response)
except :
self.send_response(400)
def do_OPTIONS(self):
self.send_response(200)
self.send_header('Access-Control-Allow-Credentials', 'true')
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header("Access-Control-Allow-Headers", "X-Requested-With, Content-type")
self.end_headers()
def do_POST(self):
"""
GET method. Uses body_to_locations.
:return:
"""
payload = json.loads(self.rfile.read(
int(self.headers['Content-Length'])))
try:
data = do_lookup(body_to_locations(payload))
response = json.dumps(data).encode('utf-8')
self.set_headers()
self.wfile.write(response)
except:
self.send_response(400)
def run():
try:
webServer = HTTPServer((HOST, PORT), OpenElevationServer)
print(f'Server started http://{HOST}:{PORT}')
webServer.serve_forever()
except KeyboardInterrupt:
webServer.server_close()
print('Server stopped')
os._exit(1)
if __name__ == "__main__":
run()
from open-elevation.
Mind you, when I run this, things mostly work fine, but not when I'm working with coordinates in New Zealand. Calling http://localhost:9000/?locations=-44.9856891,168.321971 yields an error index 14551 is out of bounds for axis 1 with size 10081
in the terminal.
Is there a simple or clever way to check which tiles cover which part of the planet, to see if there's any gaps?
from open-elevation.
Perfect, this was very helpful for what I'm doing. Thanks!
from open-elevation.
Hi where i can get meshes.py?
from open-elevation.
Related Issues (20)
- How can I make a javascript call?
- Public API is down HOT 1
- TLS certificate for `open-elevation.com` has expired HOT 1
- geojson format in the requests
- Issued certificate has expired. To connect to srtm.csi.cgiar.org insecurely, use `--no-check-certificate'.
- Public api does not work HOT 11
- Expired certificate
- Docker installation help HOT 3
- Elevation=0 HOT 1
- Public POST API not working HOT 1
- latitude, logitude reversed HOT 1
- SSL crt and key files
- Is the elevation value from mean sea level or from the ellipsoid or ?
- TLS certificate for open-elevation.com has expired
- Multiple Access-Control-Allow-Origin headers causing CORS error HOT 1
- Dead repository - Maintained fork available! HOT 4
- WKT
- Altitudes above 60 not working
- Extending API for LandXML input type
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from open-elevation.