pathfinder.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. '''
  2. Created on 17 déc. 2015
  3. Implement the A* algorithm
  4. @author: olivier.massot
  5. '''
  6. from core.geometry import cube_coords
  7. def distance(coord1, coord2):
  8. """distance between 1 and 2"""
  9. x1, y1 = coord1
  10. xu1, yu1, zu1 = cube_coords.cv_off_cube(x1, y1)
  11. x2, y2 = coord2
  12. xu2, yu2, zu2 = cube_coords.cv_off_cube(x2, y2)
  13. return max(abs(xu1 - xu2), abs(yu1 - yu2), abs(zu1 - zu2))
  14. def square_distance(coord1, coord2):
  15. """distance between 1 and 2 (quicker than distance)"""
  16. return (coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2
  17. class Path(object):
  18. def __init__(self):
  19. self._cells = []
  20. self._costs = []
  21. self._modes = []
  22. self._val = []
  23. class Node():
  24. def __init__(self, coord):
  25. self.parent = None # coords of the previous node
  26. self.coord = coord
  27. self.k_dep = 1
  28. self.g_cost = 0
  29. self.h_cost = 0
  30. self.cost = 0
  31. def create(self, parent, target, k_dep):
  32. self.parent = parent
  33. self.k_dep = k_dep
  34. self.h_cost = self.distance(self.coord, target)
  35. self.g_cost = self.parent.g_cost + self.k_dep
  36. self.cout = self.g_cost + self.h_cost
  37. def parent(self):
  38. return self.parent
  39. def distance(self, coord1, coord2):
  40. """distance (en cases) entre deux coordonnees"""
  41. x1, y1 = coord1
  42. x2, y2 = coord2
  43. return cube_coords.distance_off(x1, y1, x2, y2)
  44. def path(grid, origin, target, abilities = None):
  45. """return the shorter path from origin to target on the Grid object
  46. the path is estimated following:
  47. - geometry of the grid
  48. - altitudes of the cells
  49. - land use of the cells
  50. - type of moves allowed on the cells
  51. - moving abilities
  52. origin and target should be Cell objects
  53. """
  54. nodes = {} # coord: node
  55. nO = Node(origin)
  56. nO.parent = None
  57. nO.cost = 0
  58. # kept = [nO]
  59. path = []
  60. position = nO
  61. while position.coord != target:
  62. # we could avoid the re-computing
  63. neighbours = grid.cell(position.coord).neighbours
  64. for coord in [coord for coord in neighbours if not coord in nodes.keys()]:
  65. # !!! need a calculate cost function !!!
  66. cost = 1
  67. if cost < 0:
  68. continue
  69. node = Node(coord)
  70. node.create(position, target, cost)
  71. try:
  72. existing = nodes[coord]
  73. if existing.cout <= node.cout:
  74. continue
  75. except KeyError:
  76. pass
  77. nodes[coord] = node
  78. if len(nodes) == 0:
  79. print("No path found")
  80. return []
  81. best = min(nodes.values(), key=lambda x: x.cout)
  82. # retenus.append(meilleur)
  83. del nodes[best.coord]
  84. position = best
  85. else:
  86. # build the result
  87. while position.coord != origin:
  88. path.insert(0, (position.coord, position.k_dep))
  89. position = position.parent
  90. return path