Skip to content

Commit

Permalink
Add new add_cost_to_multiple_grids method
Browse files Browse the repository at this point in the history
  • Loading branch information
raspersc2 committed May 4, 2021
1 parent 829d08a commit 6baedc0
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 5 deletions.
55 changes: 55 additions & 0 deletions MapAnalyzer/MapData.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,65 @@ def add_cost(self, position: Tuple[float, float], radius: float, grid: ndarray,
Warning:
When ``safe=False`` the Pather will not adjust illegal values below 1 which could result in a crash`
See Also:
* :meth:`.MapData.add_cost_to_multiple_grids`
"""
return self.pather.add_cost(position=position, radius=radius, arr=grid, weight=weight, safe=safe,
initial_default_weights=initial_default_weights)

def add_cost_to_multiple_grids(
self,
position: Tuple[float, float],
radius: float,
grids: List[ndarray],
weight: float = 100,
safe: bool = True,
initial_default_weights: float = 0,
) -> List[ndarray]:
"""
:rtype: List[numpy.ndarray]
Like ``add_cost``, will add cost to a `circle-shaped` area with a center ``position`` and radius ``radius``
Use this one for performance reasons if adding identical cost to multiple grids, so that the disk is only
calculated once.
Example:
>>> MARINE_RANGE: int = 5
>>> air_grid = self.get_clean_air_grid()
>>> ground_grid = self.get_pyastar_grid()
>>> # start / goal could be any tuple / Point2
>>> enemy_marine = self.enemy_units.by_tag(self.enemy_marine_tag)
>>> air_grid, ground_grid = self.add_cost_to_multiple_grids(
>>> position=enemy_marine.position, radius=MARINE_RANGE, grids=[air_grid, ground_grid], weight=10)
Warning:
When ``safe=False`` the Pather will not adjust illegal values below 1 which could result in a crash`
Tip:
Performance against using `add_cost` for multiple grids, averaged over 1000 iterations
For `add_cost` the method was called once per grid
2 grids `add_cost_to_multiple_grids`: 188.18 µs ± 12.73 ns per loop
2 grids `add_cost` : 229.95 µs ± 37.53 ns per loop
3 grids `add_cost_to_multiple_grids`: 199.15 µs ± 21.86 ns per loop
3 grids `add_cost` : 363.44 µs ± 80.89 ns per loop
4 grids `add_cost_to_multiple_grids`: 222.34 µs ± 26.79 ns per loop
4 grids `add_cost` : 488.94 µs ± 87.64 ns per loop
"""
return self.pather.add_cost_to_multiple_grids(
position=position,
radius=radius,
arrays=grids,
weight=weight,
safe=safe,
initial_default_weights=initial_default_weights,
)


"""Utility methods"""

def save(self, filename):
Expand Down
57 changes: 52 additions & 5 deletions MapAnalyzer/Pather.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,14 +394,60 @@ def pathfind_with_nyduses(self, start: Tuple[float, float], goal: Tuple[float, f
logger.debug(f"No Path found s{start}, g{goal}")
return None

@staticmethod
def add_cost(position: Tuple[float, float], radius: float, arr: ndarray, weight: float = 100,
safe: bool = True, initial_default_weights: float = 0) -> ndarray:
def add_cost(
self,
position: Tuple[float, float],
radius: float,
arr: ndarray,
weight: float = 100,
safe: bool = True,
initial_default_weights: float = 0,
) -> ndarray:
disk = tuple(draw_circle(position, radius, arr.shape))

arr: ndarray = self._add_disk_to_grid(
position, arr, disk, weight, safe, initial_default_weights
)

return arr

def add_cost_to_multiple_grids(
self,
position: Tuple[float, float],
radius: float,
arrays: List[ndarray],
weight: float = 100,
safe: bool = True,
initial_default_weights: float = 0,
) -> List[ndarray]:
"""
Add the same cost to multiple grids, this is so the disk is only calculated once
"""
disk = tuple(draw_circle(position, radius, arrays[0].shape))

for i, arr in enumerate(arrays):
arrays[i] = self._add_disk_to_grid(
position, arrays[i], disk, weight, safe, initial_default_weights
)

return arrays

@staticmethod
def _add_disk_to_grid(
position: Tuple[float, float],
arr: ndarray,
disk: Tuple,
weight: float = 100,
safe: bool = True,
initial_default_weights: float = 0,
) -> ndarray:
# if we don't touch any cell origins due to a small radius, add at least the cell
# the given position is in
if len(disk[0]) == 0 and 0 <= position[0] < arr.shape[0] and 0 <= position[1] < arr.shape[1]:
if (
len(disk[0]) == 0
and 0 <= position[0] < arr.shape[0]
and 0 <= position[1] < arr.shape[1]
):
disk = (int(position[0]), int(position[1]))

if initial_default_weights > 0:
Expand All @@ -410,7 +456,8 @@ def add_cost(position: Tuple[float, float], radius: float, arr: ndarray, weight:
arr[disk] += weight
if safe and np.any(arr[disk] < 1):
logger.warning(
"You are attempting to set weights that are below 1. falling back to the minimum (1)")
"You are attempting to set weights that are below 1. falling back to the minimum (1)"
)
arr[disk] = np.where(arr[disk] < 1, 1, arr[disk])

return arr

0 comments on commit 6baedc0

Please sign in to comment.