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
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