Example #1
0
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))
Example #2
0
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
Example #3
0
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))
Example #4
0
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))
Example #5
0
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
Example #6
0
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))