def get_elevations_for_flight(flight): cached_elevations = cache.get("elevations_" + flight.__repr__()) if cached_elevations: return cached_elevations """ WITH src AS (SELECT ST_DumpPoints(flights.locations) AS location, flights.timestamps AS timestamps, flights.locations AS locations FROM flights WHERE flights.id = 30000) SELECT timestamps[(src.location).path[1]] AS timestamp, ST_Value(elevations.rast, (src.location).geom) AS elevation FROM elevations, src WHERE src.locations && elevations.rast AND (src.location).geom && elevations.rast; """ # Prepare column expressions location = Flight.locations.ST_DumpPoints() # Prepare cte cte = ( db.session.query( location.label("location"), Flight.locations.label("locations"), Flight.timestamps.label("timestamps") ) .filter(Flight.id == flight.id) .cte() ) # Prepare column expressions timestamp = literal_column("timestamps[(location).path[1]]") elevation = Elevation.rast.ST_Value(cte.c.location.geom) # Prepare main query q = ( db.session.query(timestamp.label("timestamp"), elevation.label("elevation")) .filter(and_(cte.c.locations.intersects(Elevation.rast), cte.c.location.geom.intersects(Elevation.rast))) .all() ) if len(q) == 0: return [] start_time = q[0][0] start_midnight = start_time.replace(hour=0, minute=0, second=0, microsecond=0) elevations = [] for time, elevation in q: if elevation is None: continue time_delta = time - start_midnight time = time_delta.days * 86400 + time_delta.seconds elevations.append((time, elevation)) cache.set("elevations_" + flight.__repr__(), elevations, timeout=3600 * 24) return elevations
def get_elevations_for_flight(flight): cached_elevations = cache.get('elevations_' + flight.__repr__()) if cached_elevations: return cached_elevations ''' WITH src AS (SELECT ST_DumpPoints(flights.locations) AS location, flights.timestamps AS timestamps, flights.locations AS locations FROM flights WHERE flights.id = 30000) SELECT timestamps[(src.location).path[1]] AS timestamp, ST_Value(elevations.rast, (src.location).geom) AS elevation FROM elevations, src WHERE src.locations && elevations.rast AND (src.location).geom && elevations.rast; ''' # Prepare column expressions location = Flight.locations.ST_DumpPoints() # Prepare cte cte = db.session.query(location.label('location'), Flight.locations.label('locations'), Flight.timestamps.label('timestamps')) \ .filter(Flight.id == flight.id).cte() # Prepare column expressions timestamp = literal_column('timestamps[(location).path[1]]') elevation = Elevation.rast.ST_Value(cte.c.location.geom) # Prepare main query q = db.session.query(timestamp.label('timestamp'), elevation.label('elevation')) \ .filter(and_(cte.c.locations.intersects(Elevation.rast), cte.c.location.geom.intersects(Elevation.rast))).all() if len(q) == 0: return [] start_time = q[0][0] start_midnight = start_time.replace(hour=0, minute=0, second=0, microsecond=0) elevations = [] for time, elevation in q: if elevation is None: continue time_delta = time - start_midnight time = time_delta.days * 86400 + time_delta.seconds elevations.append((time, elevation)) cache.set('elevations_' + flight.__repr__(), elevations, timeout=3600 * 24) return elevations
def airspace_image(cache_key, airspace_id): if not mapscript_available: abort(404) # get information from cache... infringements = cache.get('upload_airspace_infringements_' + cache_key) flight_path = cache.get('upload_airspace_flight_path_' + cache_key) # abort if invalid cache key if not infringements \ or not flight_path: abort(404) # Convert the coordinate into a list of tuples coordinates = [(c.location['longitude'], c.location['latitude']) for c in flight_path] # Create a shapely LineString object from the coordinates linestring = LineString(coordinates) # Save the new path as WKB locations = from_shape(linestring, srid=4326) highlight_locations = [] extent_epsg4326 = [180, 85.05112878, -180, -85.05112878] for period in infringements[airspace_id]: # Convert the coordinate into a list of tuples coordinates = [(c['location']['longitude'], c['location']['latitude']) for c in period] # Create a shapely LineString object from the coordinates if len(coordinates) == 1: # a LineString must contain at least two points... linestring = LineString([coordinates[0], coordinates[0]]) else: linestring = LineString(coordinates) highlight_locations.append(linestring) # gather extent (minx, miny, maxx, maxy) = linestring.bounds extent_epsg4326[0] = min(extent_epsg4326[0], minx) extent_epsg4326[1] = min(extent_epsg4326[1], miny) extent_epsg4326[2] = max(extent_epsg4326[2], maxx) extent_epsg4326[3] = max(extent_epsg4326[3], maxy) # Save the new path as WKB highlight_multilinestring = from_shape( MultiLineString(highlight_locations), srid=4326) # increase extent by factor 1.05 width = abs(extent_epsg4326[0] - extent_epsg4326[2]) height = abs(extent_epsg4326[1] - extent_epsg4326[3]) center_x = (extent_epsg4326[0] + extent_epsg4326[2]) / 2 center_y = (extent_epsg4326[1] + extent_epsg4326[3]) / 2 extent_epsg4326[0] = center_x - width / 2 * 1.05 extent_epsg4326[1] = center_y - height / 2 * 1.05 extent_epsg4326[2] = center_x + width / 2 * 1.05 extent_epsg4326[3] = center_y + height / 2 * 1.05 # minimum extent should be 0.3 deg width = abs(extent_epsg4326[0] - extent_epsg4326[2]) height = abs(extent_epsg4326[1] - extent_epsg4326[3]) if width < 0.3: extent_epsg4326[0] = center_x - 0.15 extent_epsg4326[2] = center_x + 0.15 if height < 0.3: extent_epsg4326[1] = center_y - 0.15 extent_epsg4326[3] = center_y + 0.15 # convert extent from EPSG4326 to EPSG3857 epsg4326 = pyproj.Proj(init='epsg:4326') epsg3857 = pyproj.Proj(init='epsg:3857') x1, y1 = pyproj.transform(epsg4326, epsg3857, extent_epsg4326[0], extent_epsg4326[1]) x2, y2 = pyproj.transform(epsg4326, epsg3857, extent_epsg4326[2], extent_epsg4326[3]) extent_epsg3857 = [x1, y1, x2, y2] # load basemap and set size + extent basemap_path = os.path.join( current_app.config.get('SKYLINES_MAPSERVER_PATH'), 'basemap.map') map_object = mapscript.mapObj(basemap_path) map_object.setSize(400, 400) map_object.setExtent(extent_epsg3857[0], extent_epsg3857[1], extent_epsg3857[2], extent_epsg3857[3]) # enable airspace and airports layers num_layers = map_object.numlayers for i in range(num_layers): layer = map_object.getLayer(i) if layer.group == 'Airports': layer.status = mapscript.MS_ON if layer.group == 'Airspace': layer.status = mapscript.MS_ON # get flights layer flights_layer = map_object.getLayerByName('Flights') highlight_layer = map_object.getLayerByName('Flights_Highlight') # set sql query for blue flight one = literal_column('1 as flight_id') flight_query = db.session.query(locations.label('flight_geometry'), one) flights_layer.data = 'flight_geometry FROM (' + query_to_sql(flight_query) + ')' + \ ' AS foo USING UNIQUE flight_id USING SRID=4326' # set sql query for highlighted linestrings highlighted_query = db.session.query( highlight_multilinestring.label('flight_geometry'), one) highlight_layer.data = 'flight_geometry FROM (' + query_to_sql(highlighted_query) + ')' + \ ' AS foo USING UNIQUE flight_id USING SRID=4326' highlight_layer.status = mapscript.MS_ON # get osm layer and set WMS url osm_layer = map_object.getLayerByName('OSM') osm_layer.connection = current_app.config.get('SKYLINES_MAP_TILE_URL') + \ '/service?' # draw map map_image = map_object.draw() # get image mapscript.msIO_installStdoutToBuffer() map_image.write() content = mapscript.msIO_getStdoutBufferBytes() # return to client resp = make_response(content) resp.headers['Content-type'] = map_image.format.mimetype return resp
def airspace_image(cache_key, airspace_id): if not mapscript_available: abort(404) # get information from cache... infringements = cache.get('upload_airspace_infringements_' + cache_key) flight_path = cache.get('upload_airspace_flight_path_' + cache_key) # abort if invalid cache key if not infringements \ or not flight_path: abort(404) # Convert the coordinate into a list of tuples coordinates = [(c.location['longitude'], c.location['latitude']) for c in flight_path] # Create a shapely LineString object from the coordinates linestring = LineString(coordinates) # Save the new path as WKB locations = from_shape(linestring, srid=4326) highlight_locations = [] extent_epsg4326 = [180, 85.05112878, -180, -85.05112878] for period in infringements[airspace_id]: # Convert the coordinate into a list of tuples coordinates = [(c['location']['longitude'], c['location']['latitude']) for c in period] # Create a shapely LineString object from the coordinates if len(coordinates) == 1: # a LineString must contain at least two points... linestring = LineString([coordinates[0], coordinates[0]]) else: linestring = LineString(coordinates) highlight_locations.append(linestring) # gather extent (minx, miny, maxx, maxy) = linestring.bounds extent_epsg4326[0] = min(extent_epsg4326[0], minx) extent_epsg4326[1] = min(extent_epsg4326[1], miny) extent_epsg4326[2] = max(extent_epsg4326[2], maxx) extent_epsg4326[3] = max(extent_epsg4326[3], maxy) # Save the new path as WKB highlight_multilinestring = from_shape(MultiLineString(highlight_locations), srid=4326) # increase extent by factor 1.05 width = abs(extent_epsg4326[0] - extent_epsg4326[2]) height = abs(extent_epsg4326[1] - extent_epsg4326[3]) center_x = (extent_epsg4326[0] + extent_epsg4326[2]) / 2 center_y = (extent_epsg4326[1] + extent_epsg4326[3]) / 2 extent_epsg4326[0] = center_x - width / 2 * 1.05 extent_epsg4326[1] = center_y - height / 2 * 1.05 extent_epsg4326[2] = center_x + width / 2 * 1.05 extent_epsg4326[3] = center_y + height / 2 * 1.05 # minimum extent should be 0.3 deg width = abs(extent_epsg4326[0] - extent_epsg4326[2]) height = abs(extent_epsg4326[1] - extent_epsg4326[3]) if width < 0.3: extent_epsg4326[0] = center_x - 0.15 extent_epsg4326[2] = center_x + 0.15 if height < 0.3: extent_epsg4326[1] = center_y - 0.15 extent_epsg4326[3] = center_y + 0.15 # convert extent from EPSG4326 to EPSG3857 epsg4326 = pyproj.Proj(init='epsg:4326') epsg3857 = pyproj.Proj(init='epsg:3857') x1, y1 = pyproj.transform(epsg4326, epsg3857, extent_epsg4326[0], extent_epsg4326[1]) x2, y2 = pyproj.transform(epsg4326, epsg3857, extent_epsg4326[2], extent_epsg4326[3]) extent_epsg3857 = [x1, y1, x2, y2] # load basemap and set size + extent basemap_path = os.path.join(current_app.config.get('SKYLINES_MAPSERVER_PATH'), 'basemap.map') map_object = mapscript.mapObj(basemap_path) map_object.setSize(400, 400) map_object.setExtent(extent_epsg3857[0], extent_epsg3857[1], extent_epsg3857[2], extent_epsg3857[3]) # enable airspace and airports layers num_layers = map_object.numlayers for i in range(num_layers): layer = map_object.getLayer(i) if layer.group == 'Airports': layer.status = mapscript.MS_ON if layer.group == 'Airspace': layer.status = mapscript.MS_ON # get flights layer flights_layer = map_object.getLayerByName('Flights') highlight_layer = map_object.getLayerByName('Flights_Highlight') # set sql query for blue flight one = literal_column('1 as flight_id') flight_query = db.session.query(locations.label('flight_geometry'), one) flights_layer.data = 'flight_geometry FROM (' + query_to_sql(flight_query) + ')' + \ ' AS foo USING UNIQUE flight_id USING SRID=4326' # set sql query for highlighted linestrings highlighted_query = db.session.query(highlight_multilinestring.label('flight_geometry'), one) highlight_layer.data = 'flight_geometry FROM (' + query_to_sql(highlighted_query) + ')' + \ ' AS foo USING UNIQUE flight_id USING SRID=4326' highlight_layer.status = mapscript.MS_ON # get osm layer and set WMS url osm_layer = map_object.getLayerByName('OSM') osm_layer.connection = current_app.config.get('SKYLINES_MAP_TILE_URL') + \ '/service?' # draw map map_image = map_object.draw() # get image mapscript.msIO_installStdoutToBuffer() map_image.write() content = mapscript.msIO_getStdoutBufferBytes() # return to client resp = make_response(content) resp.headers['Content-type'] = map_image.format.mimetype return resp