package sim.app.geo.haiti;
import java.util.ArrayList;
import java.util.PriorityQueue;
import sim.field.grid.IntGrid2D;
import sim.field.grid.ObjectGrid2D;
import sim.util.Bag;
public class Utilities
{
int maxCost = 10000;
static public void gridReplace(IntGrid2D grid, int from, int to)
{
for (int i = 0; i < grid.getWidth(); i++)
{
for (int j = 0; j < grid.getHeight(); j++)
{
if ( grid.get(i, j) == from )
{
grid.set(i, j, to);
}
}
}
}
public IntGrid2D constructGradient(Center c, IntGrid2D roads, ObjectGrid2D locations,
int gridWidth, int gridHeight)
{
// set up initially with everything as expensive as possible
IntGrid2D result = new IntGrid2D(gridWidth, gridHeight, maxCost);
Location center = c.loc;
result.set(center.x, center.y, 0); // the origin!
// initialize the mechanism to search
PriorityQueue<TileWrapper> queue = new PriorityQueue<TileWrapper>();
ArrayList<Location> doNotAdd = new ArrayList<Location>();
Bag neighbors = new Bag();
// process neighbors of the original center
locations.getNeighborsHamiltonianDistance(
center.x, center.y, 1, false, neighbors, null, null);
// we don't ever need to check the center again: we know its cost
doNotAdd.add(center);
// check the neighbors and start building the list of tiles to reset
for (Object o : neighbors)
{
Location l = (Location) o;
if (l == center)
{
continue; // don't recheck the center
}
int cost = roadCost(l, roads); // set up its cost
result.set(l.x, l.y, cost);
// the immediate neighbors of the center need never be checked
doNotAdd.add(l);
// ...but THEIR neighbors should be checked
Bag neighborsNeighbors = new Bag();
locations.getNeighborsHamiltonianDistance(
l.x, l.y, 1, false, neighborsNeighbors, null, null);
for (Object p : neighborsNeighbors)
{
Location n = (Location) p;
if (n == l)
{
continue; // don't recheck this tile!
}
// if the location has already been found at this point, it's
// either the center or one of its neighbors. Don't consider it.
if (doNotAdd.contains(n))
{
continue;
}
// otherwise establish its base cost and save it
int nCost = cost + roadCost(n, roads);
result.set(n.x, n.y, nCost);
// insert it into the queue so that it gets considered again
queue.add(new TileWrapper(n, nCost));
doNotAdd.add(n); // it's in the queue: don't have multiple copies there
}
}
// start at center. Push out, expanding along the "cheapest" route
while (queue.size() > 0)
{
// take cheapest node in the queue and get its info
TileWrapper t = queue.remove();
int myCost = result.get(t.l.x, t.l.y);
int myType = roadCost(t.l, roads);
// check its neighbors: is there a cheaper path for it?
neighbors = new Bag();
locations.getNeighborsHamiltonianDistance(
t.l.x, t.l.y, 1, false, neighbors, null, null);
// ...find the CHEAPEST neighbor
int bestCost = myCost;
Location bestNeighbor = null;
for (Object p : neighbors)
{
Location n = (Location) p;
if (n == t.l)
{
continue; // don't recheck!
}
int hisCost = result.get(n.x, n.y);
// if the neighbor offers a better path, take it!
if (hisCost + myType < bestCost)
{
bestCost = hisCost + myType;
bestNeighbor = n;
}
}
// if there was such a cheapest neighbor, reset our cost!
if (bestNeighbor != null)
{ // we have found a better path
result.set(t.l.x, t.l.y, bestCost);
myCost = bestCost;
}
// check to see if any neighbors should route this THIS tile
for (Object p : neighbors)
{
Location n = (Location) p;
if (n == t.l)
{
continue; // don't recheck!
}
int hisCost = result.get(n.x, n.y);
int hisType = roadCost(n, roads);
// if this tile offers a better path for the neighbor, tell the neighbor
// and submit it so it rechecks its neighbors and options
if (myCost + hisType < hisCost)
{
int hisNewCost = bestCost + hisType;
result.set(n.x, n.y, hisNewCost);
if (!doNotAdd.contains(n))
{
queue.add(new TileWrapper(n, hisNewCost));
doNotAdd.add(n);
}
}
}
}
return result;
}
int roadCost(Location l, IntGrid2D roads)
{
if (roads.get(l.x, l.y) > 0)
{
return (int) Agent.ENERGY_TO_WALK_PAVED;
}
return (int) Agent.ENERGY_TO_WALK_UNPAVED;
}
class TileWrapper implements Comparable
{
Location l;
int value;
public TileWrapper(Location l, int value)
{
this.l = l;
this.value = value;
}
@Override
public int compareTo(Object arg0)
{
TileWrapper t = (TileWrapper) arg0;
if (value < t.value)
{
return 1;
} else if (value > t.value)
{
return -1;
}
return 0;
}
}
}