/* * 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.nearbyworld; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.util.AffineTransformation; import ec.util.MersenneTwisterFast; import sim.engine.SimState; import sim.engine.Steppable; import sim.util.Bag; import sim.util.geo.MasonGeometry; /** * Simple agent for the NearbyWorld GeoMASON example. The agent wanders randomly around the field, * and at every step, prints out the all objects that are within <i>DISTANCE</i> units. * */ public class Agent implements Steppable { private static final long serialVersionUID = -7366623247320036818L; // point that denotes agent's position private MasonGeometry location; // How much to move the agent by in each step() private static double moveRate = 2.0; // DISTANCE for determining if objects are close public static double DISTANCE = 20.0; private static GeometryFactory fact = new GeometryFactory(); public Agent() { this(25, 25); } public Agent(int x, int y) { location = new MasonGeometry( fact.createPoint(new Coordinate(x,y)) ); // System.out.println("agent: " + location); } // return geometry representing agent location public MasonGeometry getGeometry() { return location; } public void step(SimState state) { NearbyWorld world = (NearbyWorld) state; // Clear out any objects previously identififed as being near world.nearbyField.clear(); // Move the agent to a random valid location within the field. move(state.random); // Now determine if we're near something in objects Bag nearbyObjects = world.objects.getObjectsWithinDistance(location, Agent.DISTANCE); if (nearbyObjects.isEmpty()) { // System.out.println("Nothing nearby"); } else { // System.out.println("# nearby objects: " + nearbyObjects.numObjs); for (int i = 0; i < nearbyObjects.size(); i++) { // System.out.println(nearbyObjects.objs[i] + " is near me"); world.nearbyField.addGeometry((MasonGeometry) nearbyObjects.objs[i]); } // nearbyField.clear() and all the addGeometry() will have reset the MBR // to something that doesn't match the MBR of the other layers; // if we leave it alone then the nearbyField objects won't be // rendered in their proper place in the display. We must sync // the MBR with that of the other layers. You can // comment out the following line to see the effect of not // synchronizing the MBR. world.nearbyField.setMBR(world.objects.getMBR()); } } // returns false if the given point is outside the bounds, else true private boolean isValidMove(final Coordinate c) { // Uses magic numbers. :( if (c.x < 0.0 || c.x > NearbyWorld.WIDTH || c.y < 0.0 || c.y > NearbyWorld.HEIGHT) { return false; } return true; } // move the agent in a random direction within a bounds private void move(MersenneTwisterFast random) { Coordinate coord = (Coordinate) location.geometry.getCoordinate().clone(); int direction = random.nextInt(8); AffineTransformation translate = null; switch (direction) { case 0 : // move up translate = AffineTransformation.translationInstance(0.0, moveRate); coord.y += Agent.moveRate; break; case 1 : // move down translate = AffineTransformation.translationInstance(0.0, -moveRate); coord.y -= Agent.moveRate; break; case 2 : // move right translate = AffineTransformation.translationInstance(moveRate, 0.0); coord.x += Agent.moveRate; break; case 3 : // move left translate = AffineTransformation.translationInstance(- moveRate, 0.0); coord.x -= Agent.moveRate; break; case 4 : // move upper left translate = AffineTransformation.translationInstance(- moveRate,moveRate); coord.x -= Agent.moveRate; coord.y += Agent.moveRate; break; case 5 : // move upper right translate = AffineTransformation.translationInstance( moveRate, moveRate ); coord.x += Agent.moveRate; coord.y += Agent.moveRate; break; case 6 : // move lower left translate = AffineTransformation.translationInstance(- moveRate, - moveRate); coord.x -= Agent.moveRate; coord.y -= Agent.moveRate; break; case 7 : // move lower right translate = AffineTransformation.translationInstance( moveRate, - moveRate); coord.x += Agent.moveRate; coord.y -= Agent.moveRate; break; default : // Ummm, what? break; } if (isValidMove(coord)) { location.geometry.apply(translate); // System.out.println("agent:" + location); } } }