def trip(coords, steps=False, output="full", geometry='polyline', overview="simplified", roundtrip=True, source="any", destination="any", annotations="false", url_config=RequestConfig, send_as_polyline=True): """ Function wrapping OSRM 'trip' function and returning the JSON reponse with the route_geometry decoded (in WKT or WKB) if needed. Parameters ---------- coord_origin : list/tuple of two floats (x ,y) where x is longitude and y is latitude steps : bool, default False output : str, default 'full' Define the type of output (full response or only route(s)) geometry : str, optional Format in which decode the geometry, either "polyline" (ie. not decoded), "geojson", "WKT" or "WKB" (default: "polyline"). overview : str, optional Query for the geometry overview, either "simplified", "full" or "false" (Default: "simplified") roundtrip : bool, optional source : str, optional destination : str, optional annotations : str, optional url_config : osrm.RequestConfig, optional Parameters regarding the host, version and profile to use Returns ------- - if 'only_index' : a dict containing respective indexes of trips and waypoints - if 'raw' : the original json returned by OSRM - if 'WKT' : the json returned by OSRM with the 'route_geometry' converted in WKT format - if 'WKB' : the json returned by OSRM with the 'route_geometry' converted in WKB format """ if geometry.lower() not in ('wkt', 'well-known-text', 'text', 'polyline', 'wkb', 'well-known-binary', 'geojson'): raise ValueError("Invalid output format") else: geom_request = "geojson" if "geojson" in geometry.lower() \ else "polyline" host = check_host(url_config.host) coords_request = \ "".join(['Polyline(', quote(polyline_encode([(c[1], c[0]) for c in coords])), ')']) \ if send_as_polyline \ else ';'.join([','.join([str(c[0]), str(c[1])]) for c in coords]) url = ''.join([ host, '/trip/', url_config.version, '/', url_config.profile, '/', coords_request, '?steps={}'.format(str(steps).lower()), '&geometries={}'.format(geom_request), '&overview={}'.format(overview), '&roundtrip={}'.format(str(roundtrip).lower()), '&source={}'.format(source), '&destination={}'.format(destination), '&annotations={}'.format(annotations) ]) req = Request(url) if url_config.auth: req.add_header("Authorization", url_config.auth) rep = urlopen(req) parsed_json = json.loads(rep.read().decode('utf-8')) if "Ok" in parsed_json['code']: if "only_index" in output: return [{ "waypoint": i["waypoint_index"], "trip": i["trips_index"] } for i in parsed_json['waypoints']] if geometry in ("polyline", "geojson") and output == "full": return parsed_json elif geometry in ("polyline", "geojson") and output == "trip": return parsed_json["trips"] else: func = Geometry.ExportToWkb if geometry == "wkb" \ else Geometry.ExportToWkt for trip_route in parsed_json["trips"]: trip_route["geometry"] = func( decode_geom(trip_route["geometry"])) return parsed_json if output == "full" else parsed_json["routes"] else: raise ValueError( 'Error - OSRM status : {} \n Full json reponse : {}'.format( parsed_json['code'], parsed_json))
def table(coords_src, coords_dest=None, ids_origin=None, ids_dest=None, output='np', minutes=False, url_config=RequestConfig, send_as_polyline=True): """ Function wrapping OSRM 'table' function in order to get a matrix of time distance as a numpy array or as a DataFrame Parameters ---------- coords_src : list A list of coord as (lat, long) , like : list_coords = [(21.3224, 45.2358), (21.3856, 42.0094), (20.9574, 41.5286)] (coords have to be float) coords_dest : list, optional A list of coord as (lat, long) , like : list_coords = [(21.3224, 45.2358), (21.3856, 42.0094), (20.9574, 41.5286)] (coords have to be float) ids_origin : list, optional A list of name/id to use to label the source axis of the result `DataFrame` (default: None). ids_dest : list, optional A list of name/id to use to label the destination axis of the result `DataFrame` (default: None). output : str, optional The type of durations matrice to return (DataFrame or numpy array) 'raw' for the (parsed) json response from OSRM 'pandas', 'df' or 'DataFrame' for a DataFrame 'numpy', 'array' or 'np' for a numpy array (default is "np") url_config: osrm.RequestConfig, optional Parameters regarding the host, version and profile to use Returns ------- - if output=='raw' : a dict, the parsed json response. - if output=='np' : a numpy.ndarray containing the time in minutes, a list of snapped origin coordinates, a list of snapped destination coordinates. - if output=='pandas' : a labeled DataFrame containing the time matrix in minutes, a list of snapped origin coordinates, a list of snapped destination coordinates. """ if output.lower() in ('numpy', 'array', 'np'): output = 1 elif output.lower() in ('pandas', 'dataframe', 'df'): output = 2 else: output = 3 host = check_host(url_config.host) url = ''.join( [host, '/table/', url_config.version, '/', url_config.profile, '/']) if not send_as_polyline: if not coords_dest: url = ''.join([ url, ';'.join([ ','.join([str(coord[0]), str(coord[1])]) for coord in coords_src ]) ]) else: src_end = len(coords_src) dest_end = src_end + len(coords_dest) url = ''.join([ url, ';'.join([ ','.join([str(coord[0]), str(coord[1])]) for coord in _chain(coords_src, coords_dest) ]), '?sources=', ';'.join([str(i) for i in range(src_end)]), '&destinations=', ';'.join([str(j) for j in range(src_end, dest_end)]) ]) else: if not coords_dest: url = ''.join([ url, "polyline(", quote(polyline_encode([(c[1], c[0]) for c in coords_src])), ")" ]) else: src_end = len(coords_src) dest_end = src_end + len(coords_dest) url = ''.join([ url, "polyline(", quote( polyline_encode([ (c[1], c[0]) for c in _chain(coords_src, coords_dest) ])), ")", '?sources=', ';'.join([str(i) for i in range(src_end)]), '&destinations=', ';'.join([str(j) for j in range(src_end, dest_end)]) ]) req = Request(url) if url_config.auth: req.add_header("Authorization", url_config.auth) rep = urlopen(req) parsed_json = json.loads(rep.read().decode('utf-8')) if "code" not in parsed_json or "Ok" not in parsed_json["code"]: raise ValueError('No distance table return by OSRM instance') elif output == 3: return parsed_json else: durations = np.array(parsed_json["durations"], dtype=float) new_src_coords = [ft["location"] for ft in parsed_json["sources"]] new_dest_coords = None if not coords_dest \ else [ft["location"] for ft in parsed_json["destinations"]] if minutes: # Conversion in minutes with 2 decimals: durations = np.around((durations / 60), 2) if output == 2: if not ids_origin: ids_origin = [i for i in range(len(coords_src))] if not ids_dest: ids_dest = ids_origin if not coords_dest \ else [i for i in range(len(coords_dest))] durations = DataFrame(durations, index=ids_origin, columns=ids_dest, dtype=float) return durations, new_src_coords, new_dest_coords
def simple_route(coord_origin, coord_dest, coord_intermediate=None, alternatives=False, steps=False, output="full", geometry='polyline', overview="simplified", annotations='true', continue_straight='default', url_config=RequestConfig, send_as_polyline=True): """ Function wrapping OSRM 'viaroute' function and returning the JSON reponse with the route_geometry decoded (in WKT or WKB) if needed. Parameters ---------- coord_origin : list/tuple of two floats (x ,y) where x is longitude and y is latitude coord_dest : list/tuple of two floats (x ,y) where x is longitude and y is latitude coord_intermediate : list of 2-floats list/tuple [(x ,y), (x, y), ...] where x is longitude and y is latitude alternatives : bool, optional Query (and resolve geometry if asked) for alternatives routes (default: False) output : str, optional Define the type of output (full response or only route(s)), default : "full". geometry : str, optional Format in which decode the geometry, either "polyline" (ie. not decoded), "geojson", "WKT" or "WKB" (default: "polyline"). annotations : str, optional continue_straight : str, optional overview : str, optional Query for the geometry overview, either "simplified", "full" or "false" (Default: "simplified") url_config : osrm.RequestConfig, optional Parameters regarding the host, version and profile to use Returns ------- result : dict The result, parsed as a dict, with the geometry decoded in the format defined in `geometry`. """ if geometry.lower() not in ('wkt', 'well-known-text', 'text', 'polyline', 'wkb', 'well-known-binary', 'geojson'): raise ValueError("Invalid output format") else: geom_request = "geojson" if "geojson" in geometry.lower() \ else "polyline" host = check_host(url_config.host) if not send_as_polyline: url = [ host, "/route/", url_config.version, "/", url_config.profile, "/", "{},{}".format(coord_origin[0], coord_origin[1]), ';' ] if coord_intermediate: url.append(";".join( [','.join([str(i), str(j)]) for i, j in coord_intermediate])) url.extend([ '{},{}'.format(coord_dest[0], coord_dest[1]), "?overview={}&steps={}&alternatives={}&geometries={}&annotations={}&continue_straight={}" .format(overview, str(steps).lower(), str(alternatives).lower(), geom_request, annotations, continue_straight) ]) else: coords = [ pt[::-1] for pt in _chain([coord_origin], coord_intermediate if coord_intermediate else [], [coord_dest]) ] url = [ host, "/route/", url_config.version, "/", url_config.profile, "/", "polyline(", quote(polyline_encode(coords)), ")", "?overview={}&steps={}&alternatives={}&geometries={}&annotations={}&continue_straight={}" .format(overview, str(steps).lower(), str(alternatives).lower(), geom_request, annotations, continue_straight) ] req = Request("".join(url)) if url_config.auth: req.add_header("Authorization", url_config.auth) rep = urlopen(req) parsed_json = json.loads(rep.read().decode('utf-8')) if "Ok" in parsed_json['code']: if geometry in ("polyline", "geojson") and output == "full": return parsed_json elif geometry in ("polyline", "geojson") and output == "routes": return parsed_json["routes"] else: if geometry == "wkb": func = Geometry.ExportToWkb elif geometry == "wkt": func = Geometry.ExportToWkt for route in parsed_json["routes"]: route["geometry"] = func(decode_geom(route["geometry"])) return parsed_json if output == "full" else parsed_json["routes"] else: raise ValueError( 'Error - OSRM status : {} \n Full json reponse : {}'.format( parsed_json['code'], parsed_json))
def trip(coords, steps=False, output="full", geometry='polyline', overview="simplified", roundtrip=True, source="any", destination="any", annotations="false", url_config=RequestConfig, send_as_polyline=True): """ Function wrapping OSRM 'trip' function and returning the JSON reponse with the route_geometry decoded (in WKT or WKB) if needed. Parameters ---------- coord_origin : list/tuple of two floats (x ,y) where x is longitude and y is latitude steps : bool, default False output : str, default 'full' Define the type of output (full response or only route(s)) geometry : str, optional Format in which decode the geometry, either "polyline" (ie. not decoded), "geojson", "WKT" or "WKB" (default: "polyline"). overview : str, optional Query for the geometry overview, either "simplified", "full" or "false" (Default: "simplified") roundtrip : bool, optional source : str, optional destination : str, optional annotations : str, optional url_config : osrm.RequestConfig, optional Parameters regarding the host, version and profile to use Returns ------- - if 'only_index' : a dict containing respective indexes of trips and waypoints - if 'raw' : the original json returned by OSRM - if 'WKT' : the json returned by OSRM with the 'route_geometry' converted in WKT format - if 'WKB' : the json returned by OSRM with the 'route_geometry' converted in WKB format """ if geometry.lower() not in ('wkt', 'well-known-text', 'text', 'polyline', 'wkb', 'well-known-binary', 'geojson'): raise ValueError("Invalid output format") else: geom_request = "geojson" if "geojson" in geometry.lower() \ else "polyline" host = check_host(url_config.host) coords_request = \ "".join(['polyline(', quote(polyline_encode([(c[1], c[0]) for c in coords])), ')']) \ if send_as_polyline \ else ';'.join([','.join([str(c[0]), str(c[1])]) for c in coords]) url = ''.join([ host, '/trip/', url_config.version, '/', url_config.profile, '/', coords_request, '?steps={}'.format(str(steps).lower()), '&geometries={}'.format(geom_request), '&overview={}'.format(overview), '&roundtrip={}'.format(str(roundtrip).lower()), '&source={}'.format(source), '&destination={}'.format(destination), '&annotations={}'.format(annotations) ]) req = Request(url) if url_config.auth: req.add_header("Authorization", url_config.auth) rep = urlopen(req) parsed_json = json.loads(rep.read().decode('utf-8')) if "Ok" in parsed_json['code']: if "only_index" in output: return [ {"waypoint": i["waypoint_index"], "trip": i["trips_index"]} for i in parsed_json['waypoints'] ] if geometry in ("polyline", "geojson") and output == "full": return parsed_json elif geometry in ("polyline", "geojson") and output == "trip": return parsed_json["trips"] else: func = Geometry.ExportToWkb if geometry.lower() == "wkb" \ else Geometry.ExportToWkt for trip_route in parsed_json["trips"]: trip_route["geometry"] = func(decode_geom( trip_route["geometry"])) return parsed_json if output == "full" else parsed_json["routes"] else: raise ValueError( 'Error - OSRM status : {} \n Full json reponse : {}' .format(parsed_json['code'], parsed_json))
def table(coords_src, coords_dest=None, ids_origin=None, ids_dest=None, output='np', minutes=False, annotations='duration', url_config=RequestConfig, send_as_polyline=True): """ Function wrapping OSRM 'table' function in order to get a matrix of time distance as a numpy array or as a DataFrame Parameters ---------- coords_src : list A list of coord as (longitude, latitude) , like : list_coords = [(21.3224, 45.2358), (21.3856, 42.0094), (20.9574, 41.5286)] (coords have to be float) coords_dest : list, optional A list of coord as (longitude, latitude) , like : list_coords = [(21.3224, 45.2358), (21.3856, 42.0094), (20.9574, 41.5286)] (coords have to be float) ids_origin : list, optional A list of name/id to use to label the source axis of the result `DataFrame` (default: None). ids_dest : list, optional A list of name/id to use to label the destination axis of the result `DataFrame` (default: None). output : str, optional The type of annotated matrice to return (DataFrame or numpy array) 'raw' for the (parsed) json response from OSRM 'pandas', 'df' or 'DataFrame' for a DataFrame 'numpy', 'array' or 'np' for a numpy array (default is "np") annotations : str, optional Either 'duration' (default) or 'distance' url_config: osrm.RequestConfig, optional Parameters regarding the host, version and profile to use Returns ------- - if output=='raw' : a dict, the parsed json response. - if output=='np' : a numpy.ndarray containing the time in minutes, a list of snapped origin coordinates, a list of snapped destination coordinates. - if output=='pandas' : a labeled DataFrame containing the time matrix in minutes, a list of snapped origin coordinates, a list of snapped destination coordinates. """ if output.lower() in ('numpy', 'array', 'np'): output = 1 elif output.lower() in ('pandas', 'dataframe', 'df'): output = 2 else: output = 3 host = check_host(url_config.host) url = ''.join( [host, '/table/', url_config.version, '/', url_config.profile, '/']) if not send_as_polyline: if not coords_dest: url = ''.join([ url, ';'.join([','.join([str(coord[0]), str(coord[1])]) for coord in coords_src]), '?annotations={}'.format(annotations) ]) else: src_end = len(coords_src) dest_end = src_end + len(coords_dest) url = ''.join([ url, ';'.join([','.join([str(coord[0]), str(coord[1])]) for coord in _chain(coords_src, coords_dest)]), '?sources=', ';'.join([str(i) for i in range(src_end)]), '&destinations=', ';'.join([str(j) for j in range(src_end, dest_end)]), '&annotations={}'.format(annotations) ]) else: if not coords_dest: url = ''.join([ url, "polyline(", quote(polyline_encode([(c[1], c[0]) for c in coords_src])), ")", '?annotations={}'.format(annotations) ]) else: src_end = len(coords_src) dest_end = src_end + len(coords_dest) url = ''.join([ url, "polyline(", quote(polyline_encode( [(c[1], c[0]) for c in _chain(coords_src, coords_dest)])), ")", '?sources=', ';'.join([str(i) for i in range(src_end)]), '&destinations=', ';'.join([str(j) for j in range(src_end, dest_end)]), '&annotations={}'.format(annotations) ]) req = Request(url) if url_config.auth: req.add_header("Authorization", url_config.auth) rep = urlopen(req) parsed_json = json.loads(rep.read().decode('utf-8')) if "code" not in parsed_json or "Ok" not in parsed_json["code"]: raise ValueError('No distance table return by OSRM instance') elif output == 3: return parsed_json else: annoted = np.array(parsed_json['{}s'.format(annotations)], dtype=float) new_src_coords = [ft["location"] for ft in parsed_json["sources"]] new_dest_coords = None if not coords_dest \ else [ft["location"] for ft in parsed_json["destinations"]] if minutes and annotations == 'duration': # Conversion in minutes with 2 decimals: annoted = np.around((annoted / 60), 2) if output == 2: if not ids_origin: ids_origin = [i for i in range(len(coords_src))] if not ids_dest: ids_dest = ids_origin if not coords_dest \ else [i for i in range(len(coords_dest))] annoted = DataFrame(annoted, index=ids_origin, columns=ids_dest, dtype=float) return annoted, new_src_coords, new_dest_coords
def simple_route(coord_origin, coord_dest, coord_intermediate=None, alternatives=False, steps=False, output="full", geometry='polyline', overview="simplified", annotations='true', continue_straight='default', url_config=RequestConfig, send_as_polyline=True): """ Function wrapping OSRM 'viaroute' function and returning the JSON reponse with the route_geometry decoded (in WKT or WKB) if needed. Parameters ---------- coord_origin : list/tuple of two floats (x ,y) where x is longitude and y is latitude coord_dest : list/tuple of two floats (x ,y) where x is longitude and y is latitude coord_intermediate : list of 2-floats list/tuple [(x ,y), (x, y), ...] where x is longitude and y is latitude alternatives : bool, optional Query (and resolve geometry if asked) for alternatives routes (default: False) output : str, optional Define the type of output (full response or only route(s)), default : "full". geometry : str, optional Format in which decode the geometry, either "polyline" (ie. not decoded), "geojson", "WKT" or "WKB" (default: "polyline"). annotations : str, optional continue_straight : str, optional overview : str, optional Query for the geometry overview, either "simplified", "full" or "false" (Default: "simplified") url_config : osrm.RequestConfig, optional Parameters regarding the host, version and profile to use Returns ------- result : dict The result, parsed as a dict, with the geometry decoded in the format defined in `geometry`. """ if geometry.lower() not in ('wkt', 'well-known-text', 'text', 'polyline', 'wkb', 'well-known-binary', 'geojson'): raise ValueError("Invalid output format") else: geom_request = "geojson" if "geojson" in geometry.lower() \ else "polyline" host = check_host(url_config.host) if not send_as_polyline: url = [host, "/route/", url_config.version, "/", url_config.profile, "/", "{},{}".format(coord_origin[0], coord_origin[1]), ';'] if coord_intermediate: url.append(";".join( [','.join([str(i), str(j)]) for i, j in coord_intermediate])) url.append(";") url.extend([ '{},{}'.format(coord_dest[0], coord_dest[1]), "?overview={}&steps={}&alternatives={}&geometries={}&annotations={}&continue_straight={}".format( overview, str(steps).lower(), str(alternatives).lower(), geom_request, annotations, continue_straight) ]) else: coords = [ pt[::-1] for pt in _chain( [coord_origin], coord_intermediate if coord_intermediate else [], [coord_dest]) ] url = [ host, "/route/", url_config.version, "/", url_config.profile, "/", "polyline(", quote(polyline_encode(coords)), ")", "?overview={}&steps={}&alternatives={}&geometries={}&annotations={}&continue_straight={}".format( overview, str(steps).lower(), str(alternatives).lower(), geom_request, annotations, continue_straight) ] req = Request("".join(url)) if url_config.auth: req.add_header("Authorization", url_config.auth) rep = urlopen(req) parsed_json = json.loads(rep.read().decode('utf-8')) if "Ok" in parsed_json['code']: if geometry in ("polyline", "geojson") and output == "full": return parsed_json elif geometry in ("polyline", "geojson") and output == "routes": return parsed_json["routes"] else: if geometry.lower() == "wkb": func = Geometry.ExportToWkb elif geometry.lower() == "wkt": func = Geometry.ExportToWkt for route in parsed_json["routes"]: route["geometry"] = func(decode_geom(route["geometry"])) return parsed_json if output == "full" else parsed_json["routes"] else: raise ValueError( 'Error - OSRM status : {} \n Full json reponse : {}'.format( parsed_json['code'], parsed_json))