Exemplo n.º 1
0
 def from_handmade(cls, start, middlePoints, destination):
     """Convert hand-made route data to a way """
     if start and destination:
         # route points & message points are generated at once
         # * empty string as message => no message point, just route point
         routePoints = [(start[0], start[1], None)]
         messagePoints = []
         mLength = 0 # in meters
         lastLat, lastLon = start[0], start[1]
         for point in middlePoints:
             lat, lon, elevation, message = point
             mLength += geo.distance(lastLat, lastLon, lat, lon) * 1000
             routePoints.append((lat, lon, elevation))
             if message != "": # is it a message point ?
                 point = TurnByTurnPoint(lat, lon, elevation, message)
                 point.distanceFromStart = mLength
                 messagePoints.append(point)
             lastLat, lastLon = lat, lon
         routePoints.append((destination[0], destination[1], None))
         way = cls(routePoints)
         way.add_message_points(messagePoints)
         # huge guestimation (avg speed 60 km/h = 16.7 m/s)
         seconds = mLength / 16.7
         way.duration = seconds
         way._setLength(mLength)
         # done, return the result
         return way
     else:
         return None
Exemplo n.º 2
0
 def from_handmade(cls, start, middlePoints, destination):
     """Convert hand-made route data to a way """
     if start and destination:
         # route points & message points are generated at once
         # * empty string as message => no message point, just route point
         routePoints = [(start[0], start[1], None)]
         messagePoints = []
         mLength = 0 # in meters
         lastLat, lastLon = start[0], start[1]
         for point in middlePoints:
             lat, lon, elevation, message = point
             mLength += geo.distance(lastLat, lastLon, lat, lon) * 1000
             routePoints.append((lat, lon, elevation))
             if message != "": # is it a message point ?
                 point = TurnByTurnPoint(lat, lon, elevation, message)
                 point.distanceFromStart = mLength
                 messagePoints.append(point)
             lastLat, lastLon = lat, lon
         routePoints.append((destination[0], destination[1], None))
         way = cls(routePoints)
         way.add_message_points(messagePoints)
         # huge guestimation (avg speed 60 km/h = 16.7 m/s)
         seconds = mLength / 16.7
         way.duration = seconds
         way._setLength(mLength)
         # done, return the result
         return way
     else:
         return None
Exemplo n.º 3
0
    def basic_test(self):
        """Test basic TurnByTurn point functionality"""
        point = TurnByTurnPoint(1.0,
                                2.0,
                                elevation=123.45,
                                message="foo message",
                                ssml_message="ssml message",
                                icon="some_icon_id")

        # distances should be None by default
        self.assertIsNone(point.current_distance)
        self.assertIsNone(point.distance_from_start)

        # visited should be False as well
        self.assertFalse(point.visited)

        self.assertEqual(point.ssml_message, "ssml message")
        self.assertEqual(point.icon, "some_icon_id")

        # check if the LLEMI tuple is correct as well
        self.assertEqual(point.llemi,
                         (1.0, 2.0, 123.45, "foo message", "some_icon_id"))

        # try setting the distances
        point.current_distance = 200
        point.distance_from_start = 300
        self.assertEqual(point.current_distance, 200)
        self.assertEqual(point.distance_from_start, 300)
Exemplo n.º 4
0
 def from_valhalla(cls, result):
     """Convert Valhalla routing result json to a way"""
     if result:
         route = []
         turns = []
         for leg in result['trip']['legs']:
             poly = decode_valhalla(leg['shape'])
             maneuvers = []
             for m in leg['maneuvers']:
                 icon_id = VALHALLA_TYPE_ICON_MAP.get(m["type"], constants.DEFAULT_NAVIGATION_STEP_ICON)
                 maneuvers.append(TurnByTurnPoint(poly[m['begin_shape_index']][0],
                                                  poly[m['begin_shape_index']][1],
                                                  message=m['instruction'],
                                                  icon=icon_id)
                                  )
             route.extend(poly)
             turns.extend(maneuvers)
             
         way = cls(route)
         
         way.duration = result['trip']['summary']['time']
         way._setLength(result['trip']["summary"]["length"])
         
         way.add_message_points(turns)
         return way
     else:
         return None
Exemplo n.º 5
0
    def from_osm_scout_json(cls, result):
        """Convert OSM Scout Server routing result JSON to a way.

        :param result: OSM Scout Server processed JSON routing result
        """
        if result:
            routePoints = []
            # get route as (lat, lon, None)
            route_lle_tuples = list(
                itertools.zip_longest(result["lat"], result["lng"], [None]))
            # create a way from the lle tuples
            way = cls(route_lle_tuples)

            way._set_duration(result["summary"]["time"])
            way._set_length(result["summary"]["length"])

            # get turns from the json result
            turns = []
            for maneuver in result.get("maneuvers", []):
                lat = maneuver["lat"]
                lon = maneuver["lng"]
                description = maneuver.get("verbal_pre_transition_instruction",
                                           "")
                turns.append(TurnByTurnPoint(lat, lon, message=description))
            way.add_message_points(turns)
            return way
        else:
            return None
Exemplo n.º 6
0
    def from_google_directions_result(cls, gd_result):
        """Convert Google Directions result to a way object.

        :param gd_result: Google Directions result
        """
        leg = gd_result['routes'][0]['legs'][0]
        steps = leg['steps']

        points = decode_polyline(
            gd_result['routes'][0]['overview_polyline']['points'])
        # length of the route can computed from its metadata
        if 'distance' in leg:  # this field might not be present
            m_length = leg['distance']['value']
        else:
            m_length = None
        # the route also contains the expected duration in seconds
        if 'duration' in leg:  # this field might not be present
            s_duration = leg['duration']['value']
        else:
            s_duration = None

        way = cls(points)
        way._set_length(m_length)
        way._set_duration(s_duration)
        message_points = []

        m_distance_from_start = 0

        for step in steps:
            # TODO: abbreviation filtering
            message = step['html_instructions']
            # as you can see, for some reason,
            # the coordinates in Google Directions steps are reversed:
            lat = step['start_location']['lat']
            lon = step['start_location']['lng']
            #TODO: end location ?
            point = TurnByTurnPoint(lat, lon, message=message)
            point.distance_from_start = m_distance_from_start
            # store point to temporary list
            message_points.append(point)
            # update distance for next point
            mDistanceFromLast = step["distance"]['value']
            m_distance_from_start = m_distance_from_start + mDistanceFromLast

        way.add_message_points(message_points)
        return way
Exemplo n.º 7
0
    def process_and_save_directions(self, route):
        """process and save directions"""

        # apply filters
        route = self.filter_directions(route)

        # add a fake destination step, so there is a "destination reached" message
        if route.point_count > 0:
            (lat, lon) = route.get_point_by_index(-1).getLL()
            dest_step = TurnByTurnPoint(lat, lon)
            dest_step.ssml_message = '<p xml:lang="en">you <b>should</b> be near the destination</p>'
            dest_step.description = 'you <b>should</b> be near the destination'
            dest_step.distance_from_start = route.length
            # TODO: make this multilingual
            # add it to the end of the message point list
            route.add_message_point(dest_step)

        # save
        self._directions = route
Exemplo n.º 8
0
    def from_google_directions_result(cls, gResult):
        """Convert Google Directions result to a way object"""
        leg = gResult['routes'][0]['legs'][0]
        steps = leg['steps']

        points = decode_polyline(gResult['routes'][0]['overview_polyline']['points'])
        # length of the route can computed from its metadata
        if 'distance' in leg: # this field might not be present
            mLength = leg['distance']['value']
        else:
            mLength = None
        # the route also contains the expected duration in seconds
        if 'duration' in leg: # this field might not be present
            sDuration = leg['duration']['value']
        else:
            sDuration = None

        way = cls(points)
        way._setLength(mLength)
        way.duration = sDuration
        messagePoints = []

        mDistanceFromStart = 0

        for step in steps:
            # TODO: abbreviation filtering
            message = step['html_instructions']
            # as you can see, for some reason,
            # the coordinates in Google Directions steps are reversed:
            lat = step['start_location']['lat']
            lon = step['start_location']['lng']
            #TODO: end location ?
            point = TurnByTurnPoint(lat, lon, message=message)
            point.distanceFromStart = mDistanceFromStart
            # store point to temporary list
            messagePoints.append(point)
            # update distance for next point
            mDistanceFromLast = step["distance"]['value']
            mDistanceFromStart = mDistanceFromStart + mDistanceFromLast

        way.add_message_points(messagePoints)
        return way
Exemplo n.º 9
0
def detect_monav_turns(result):
    """Go through the edges and try to detect turns,
       return a list of RoutingPoints for the turns.

       :param result: a Monav offline routing result
       :type result: Monav offline routing result object
       :returns: list of RoutingPoints for turns
       :rtype: list of RoutingPoint instances
    """

    # How to get the corresponding nodes for edges
    # -> edges are ordered and contain the n_segments property
    # -> n_segments describes from how many segments the given edge consists
    # -> by counting n_segments for subsequent edges, we get the node id
    # EXAMPLE:
    # a route with 2 edges, 3 segments each
    # -> firs point has id 0
    # -> the last point od the first edge has id 3
    # -> the last point of the route has id 6

    turns = []

    edges = result.edges
    nodes = result.nodes
    names = result.edge_names

    # need at least two edges for any meaningful routing
    if len(edges) >= 2:
        lastEdge = edges[0]

        nodeId = 0
        maxNodeId = len(nodes) - 1
        for edge in edges[1:]:
            nodeId += lastEdge.n_segments
            edgeId = edge.type_id
            nameId = edge.name_id
            name = names[nameId]

            #      if lastEdge.branching_possible:
            if True:  # looks like branching possible is not needed
                # turn directions are actually needed only
                # when there are some other roads to to turn to
                lastName = names[lastEdge.name_id]
                if lastEdge.type_id != edgeId or lastName != name:
                    # if route type or name changes, it might be a turn
                    node = nodes[nodeId]
                    if nodeId <= maxNodeId:
                        prevNode = nodes[nodeId - 1]
                        nextNode = nodes[nodeId + 1]
                        # NOTE: if the turn consists
                        # from many segments, taking more points into
                        # account might be needed
                        first = prevNode.latitude, prevNode.longitude
                        middle = node.latitude, node.longitude
                        last = nextNode.latitude, nextNode.longitude
                        angle = geo.turnAngle(first, middle, last)

                        turnDescription = _get_turn_description(angle,
                                                                name=name)
                        # get the corresponding node

                        turns.append(
                            TurnByTurnPoint(node.latitude,
                                            node.longitude,
                                            message=turnDescription))
                        # DEBUG
                        # turns.append(TurnByTurnPoint(prevNode.latitude, prevNode.longitude, message="prev"))
                        # turns.append(TurnByTurnPoint(nextNode.latitude, nextNode.longitude, message="next"))

            lastEdge = edge
    return turns