/*
* Copyright 2011 by Mark Coletti, Keith Sullivan, Sean Luke, and
* George Mason University Mason University Licensed under the Academic
* Free License version 3.0
*
* See the file "LICENSE" for more information
*
* $Id$
*/
package sim.app.geo.campusworld;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.planargraph.Node;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import sim.engine.SimState;
import sim.engine.Steppable;
import sim.field.geo.GeomVectorField;
import sim.io.geo.ShapeFileExporter;
import sim.io.geo.ShapeFileImporter;
import sim.util.Bag;
import sim.util.geo.GeomPlanarGraph;
import sim.util.geo.MasonGeometry;
/**
* This simple example shows how to setup GeomVectorFields and run agents around the fields. The simulation has
* multiple agents following the walkways at George Mason University. GIS information about the walkways, buildings,
* and roads provides the environment for the agents. During the simulation, the agents wander randomly on the walkways.
*/
public class CampusWorld extends SimState
{
private static final long serialVersionUID = -4554882816749973618L;
public static final int WIDTH = 300;
public static final int HEIGHT = 300;
/** How many agents in the simulation */
public int numAgents = 1000;
/** Fields to hold the associated GIS information */
public GeomVectorField walkways = new GeomVectorField(WIDTH, HEIGHT);
public GeomVectorField roads = new GeomVectorField(WIDTH, HEIGHT);
public GeomVectorField buildings = new GeomVectorField(WIDTH,HEIGHT);
// where all the agents live
public GeomVectorField agents = new GeomVectorField(WIDTH, HEIGHT);
// Stores the walkway network connections. We represent the walkways as a PlanarGraph, which allows
// easy selection of new waypoints for the agents.
public GeomPlanarGraph network = new GeomPlanarGraph();
public GeomVectorField junctions = new GeomVectorField(WIDTH, HEIGHT); // nodes for intersections
public CampusWorld(long seed)
{
super(seed);
try
{
System.out.println("reading buildings layer");
// this Bag lets us only display certain fields in the Inspector, the non-masked fields
// are not associated with the object at all
Bag masked = new Bag();
masked.add("NAME");
masked.add("FLOORS");
masked.add("ADDR_NUM");
// System.out.println(System.getProperty("user.dir"));
// read in the buildings GIS file
URL bldgGeometry = CampusWorld.class.getResource("data/bldg.shp");
ShapeFileImporter.read(bldgGeometry, buildings, masked);
// We want to save the MBR so that we can ensure that all GeomFields
// cover identical area.
Envelope MBR = buildings.getMBR();
System.out.println("reading roads layer");
URL roadGeometry = CampusWorld.class.getResource("data/roads.shp");
ShapeFileImporter.read(roadGeometry, roads);
MBR.expandToInclude(roads.getMBR());
System.out.println("reading walkways layer");
URL walkWayGeometry = CampusWorld.class.getResource("data/walk_ways.shp");
ShapeFileImporter.read(walkWayGeometry, walkways);
MBR.expandToInclude(walkways.getMBR());
System.out.println("Done reading data");
// Now synchronize the MBR for all GeomFields to ensure they cover the same area
buildings.setMBR(MBR);
roads.setMBR(MBR);
walkways.setMBR(MBR);
network.createFromGeomField(walkways);
addIntersectionNodes(network.nodeIterator(), junctions);
} catch (Exception ex)
{
Logger.getLogger(CampusWorld.class.getName()).log(Level.SEVERE, null, ex);
}
}
public int getNumAgents() { return numAgents; }
public void setNumAgents(int n) { if (n > 0) numAgents = n; }
/**
* Add agents to the simulation and to the agent GeomVectorField. Note that
* each agent does not have any attributes.
*/
void addAgents()
{
for (int i = 0; i < numAgents; i++)
{
Agent a = new Agent(this);
agents.addGeometry(a.getGeometry());
schedule.scheduleRepeating(a);
// we can set the userData field of any MasonGeometry. If the userData is inspectable,
// then the inspector will show this information
//if (i == 10)
// buildings.getGeometry("CODE", "JC").setUserData(a);
}
}
@Override
public void finish()
{
super.finish();
// Save the agents layer, which has no corresponding originating
// shape file.
ShapeFileExporter.write("agents", agents);
}
@Override
public void start()
{
super.start();
agents.clear(); // clear any existing agents from previous runs
addAgents();
agents.setMBR(buildings.getMBR());
// Ensure that the spatial index is made aware of the new agent
// positions. Scheduled to guaranteed to run after all agents moved.
schedule.scheduleRepeating( agents.scheduleSpatialIndexUpdater(), Integer.MAX_VALUE, 1.0);
}
/** adds nodes corresponding to road intersections to GeomVectorField
*
* @param nodeIterator Points to first node
* @param intersections GeomVectorField containing intersection geometry
*
* Nodes will belong to a planar graph populated from LineString network.
*/
private void addIntersectionNodes(Iterator nodeIterator, GeomVectorField intersections)
{
GeometryFactory fact = new GeometryFactory();
Coordinate coord = null;
Point point = null;
int counter = 0;
while (nodeIterator.hasNext())
{
Node node = (Node) nodeIterator.next();
coord = node.getCoordinate();
point = fact.createPoint(coord);
junctions.addGeometry(new MasonGeometry(point));
counter++;
}
}
public static void main(String[] args)
{
doLoop(CampusWorld.class, args);
System.exit(0);
}
}