예제 #1
0
    def computeRoute(self, src, dest): # uses A*
        pm = self

        origin_area= self.getContainingArea(src)
        target_area = self.getContainingArea(dest)

        if origin_area is None or target_area is None:
            return None

        origin_area_id = origin_area.getFreeAreaId()
        target_area_id = target_area.getFreeAreaId()

        search_front_queue = SortedList()
        h = 0#origin_area.distanceTo(target_area) # A* heuristic distance value

        search_front_queue.add((h,h,origin_area_id))
        search_front_p = {}
        frozen = set()

        loops = 0

        while search_front_queue:
            loops += 1
            d,old_h,a = search_front_queue.pop(0)
            if a in frozen: # ignore duplicates
                continue


            # target found
            if a == target_area_id:
                break

            frozen.add(a)

            area = pm.getArea(a)

            for adj, portal in area.getAdjacencies():
                if adj in frozen: # don't try to even check nodes that have been already frozen
                    continue

                dg = area.distanceTo(pm.getArea(adj))

                new_h = area.distanceTo(target_area)

                new_d = d+dg-old_h+new_h

                # route to adj through a is longer than what we already had. Dismiss
                if adj in search_front_p and new_d > search_front_p[adj][0]:
                    continue

                search_front_p[adj] = (new_d, a, portal)
                # this might add duplicate adj items (ideally we would delete any previous insertion)
                # because we can't easily erase from the queue.
                search_front_queue.add((new_d, h, adj))

        p = target_area_id
        route = [(p,None)] # stores tuples: area_number, exit portal
        while p in search_front_p:
            _,prev,portal = search_front_p[p]
            route.append((prev, portal))
            p = prev

        route.reverse()

        return route
예제 #2
0
    def computeDistances(self, src, dest_list): # uses Dijkstra

        pm = self

        origin_area= self.getContainingArea(src)

        target_areas = [self.getContainingArea(dest) for dest in dest_list]
        target_area_ids = set([a.getFreeAreaId() if a is not None else -1 for a in target_areas ])

        if origin_area is None or not any(target_areas):
            return [None]*len(dest_list)

        search_front_queue = SortedList()

        search_front_queue.add((0,origin_area.getFreeAreaId()))
        search_front_p = {}
        target_distances = {}
        frozen = set()

        loops = 0

        while search_front_queue:
            loops += 1
            d,a = search_front_queue.pop(0)
            if a in frozen: # ignore duplicates
                continue

            # target found
            if a == target_area_ids:
                target_distances[a] = d
                target_area_ids.remove(a)
                if len(target_area_ids) == 0:
                    break

            frozen.add(a)

            area = pm.getArea(a)

            for adj, portal in area.getAdjacencies():
                if adj in frozen: # don't try to even check nodes that have been already frozen
                    continue

                new_d = d + area.distanceTo(pm.getArea(adj))

                # route to adj through a is longer than what we already had. Dismiss
                if adj in search_front_p and new_d > search_front_p[adj]:
                    continue

                search_front_p[adj] = new_d
                # this might add duplicate adj items (ideally we would delete any previous insertion)
                # because we can't easily erase from the queue.
                search_front_queue.add((new_d, adj))

        distances = []
        for t in target_area_ids:
            try:
                distances.append(target_distances[t])
            except:
                distances.append(None)

        return distances