Added cdb_dataservices_server functions

This commit is contained in:
Antonio
2017-12-29 14:07:51 +01:00
parent af07def7fc
commit c46174210d
9 changed files with 6883 additions and 29 deletions

View File

@@ -1,5 +1,5 @@
from routing import MapboxRouting, MapboxRoutingResponse
from geocoder import MapboxGeocoder
from isolines import MapboxIsolines
from isolines import MapboxIsolines, MapboxIsochronesResponse
from matrix_client import MapboxMatrixClient
from exceptions import ServiceException

View File

@@ -54,8 +54,15 @@ class MapboxGeocoder(Traceable):
return [longitude, latitude]
@qps_retry(qps=10)
def geocode(self, address, country=None):
response = self._geocoder.forward(address=address,
def geocode(self, searchtext, city=None, state_province=None,
country=None):
address = [searchtext]
if city:
address.append(city)
if state_province:
address.append(state_province)
response = self._geocoder.forward(address=', '.join(address),
country=country,
limit=1)

View File

@@ -60,22 +60,28 @@ class MapboxIsolines():
return costs
def calculate_isochrone(self, origin, time_range,
def calculate_isochrone(self, origin, time_ranges,
profile=DEFAULT_PROFILE):
validate_profile(profile)
max_speed = MAX_SPEEDS[profile]
upper_rmax = max_speed * time_range # an upper bound for the radius
return self.calculate_isoline(origin=origin,
isorange=time_range,
upper_rmax=upper_rmax,
cost_method=self._calculate_matrix_cost,
profile=profile,
unit_factor=UNIT_FACTOR_ISOCHRONE,
number_of_angles=MATRIX_NUM_ANGLES,
max_iterations=MATRIX_MAX_ITERS,
tolerance=MATRIX_TOLERANCE)
isochrones = []
for time_range in time_ranges:
upper_rmax = max_speed * time_range # an upper bound for the radius
coordinates = self.calculate_isoline(origin=origin,
isorange=time_range,
upper_rmax=upper_rmax,
cost_method=self._calculate_matrix_cost,
profile=profile,
unit_factor=UNIT_FACTOR_ISOCHRONE,
number_of_angles=MATRIX_NUM_ANGLES,
max_iterations=MATRIX_MAX_ITERS,
tolerance=MATRIX_TOLERANCE)
isochrones.append(MapboxIsochronesResponse(coordinates,
time_range))
return isochrones
def calculate_isodistance(self, origin, distance_range,
profile=DEFAULT_PROFILE):
@@ -85,7 +91,7 @@ class MapboxIsolines():
time_range = distance_range / max_speed
return self.calculate_isochrone(origin=origin,
time_range=time_range,
time_ranges=[time_range],
profile=profile)
def calculate_isoline(self, origin, isorange, upper_rmax,
@@ -145,3 +151,18 @@ class MapboxIsolines():
location_estimates_filtered.append(location_estimates[i])
return location_estimates_filtered
class MapboxIsochronesResponse:
def __init__(self, coordinates, duration):
self._coordinates = coordinates
self._duration = duration
@property
def coordinates(self):
return self._coordinates
@property
def duration(self):
return self._duration

View File

@@ -1,3 +1,6 @@
import plpy
class Coordinate:
"""Class that represents a generic form of coordinates to be used
by the services """
@@ -34,6 +37,26 @@ def validate_coordinates(coordinates,
min=num_coordinates_min,
max=num_coordinates_max))
def marshall_coordinates(coordinates):
return ';'.join([str(coordinate).replace(' ', '')
for coordinate in coordinates])
def coordinates_to_polygon(coordinates):
"""Convert a Coordinate array coordinates to a PostGIS polygon"""
coordinates.append(coordinates[0]) # Close the ring
result_coordinates = []
for coordinate in coordinates:
result_coordinates.append("%s %s" % (coordinate.longitude,
coordinate.latitude))
wkt_coordinates = ','.join(result_coordinates)
try:
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MakePolygon(ST_GeomFromText('LINESTRING({0})', 4326))),3) as geom".format(wkt_coordinates)
geometry = plpy.execute(sql, 1)[0]['geom']
except BaseException as e:
plpy.warning("Can't generate POLYGON from coordinates: {0}".format(e))
geometry = None
return geometry

View File

@@ -1,5 +1,4 @@
from itertools import tee, izip
from math import trunc
import plpy
class PolyLine:
@@ -46,3 +45,22 @@ class PolyLine:
coordinate |= c << (i * 5)
return coordinate
def polyline_to_linestring(polyline):
"""Convert a Mapzen polyline shape to a PostGIS multipolygon"""
coordinates = []
for point in polyline:
# Divide by 10 because mapzen uses one more decimal than the
# google standard (https://mapzen.com/documentation/turn-by-turn/decoding/)
coordinates.append("%s %s" % (point[1]/10, point[0]/10))
wkt_coordinates = ','.join(coordinates)
try:
sql = "SELECT ST_GeomFromText('LINESTRING({0})', 4326) as geom".format(wkt_coordinates)
geometry = plpy.execute(sql, 1)[0]['geom']
except BaseException as e:
plpy.warning("Can't generate LINESTRING from polyline: {0}".format(e))
geometry = None
return geometry

View File

@@ -19,11 +19,11 @@ class MapboxIsolinesTestCase(unittest.TestCase):
self.mapbox_isolines = MapboxIsolines(matrix_client, logger=Mock())
def test_calculate_isochrone(self):
time_range = 10 * 60 # 10 minutes
time_ranges = [300, 900]
solution = self.mapbox_isolines.calculate_isochrone(
origin=VALID_ORIGIN,
profile=DEFAULT_PROFILE,
time_range=time_range)
time_ranges=time_ranges)
assert solution