/* Copyright 2006 by Sean Luke and George Mason University Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package sim.app.crowd3d; import sim.util.*; import sim.engine.*; public class Agent implements Steppable, Stoppable { private static final long serialVersionUID = 1; public final static double SIGHT = 5; public final static double SPEED = .05; public final static double WALL_AVERSION = 4.0; public final static double CROWD_AVERSION = 1.0;//more is better// public final static double FORCE_MIN_THRESHOLD = 0.75; MutableDouble3D direction = new MutableDouble3D(); static MutableDouble3D tmpSumOfCrowdForces = new MutableDouble3D(); static MutableDouble3D tmpSumOfWallForces = new MutableDouble3D(); static MutableDouble3D tmpSumOfForces = new MutableDouble3D(); static MutableDouble3D tmpMyPosition = new MutableDouble3D(); public void step( final SimState state ) { CrowdSim hb = (CrowdSim)state; Double3D myPositionD3D = hb.boidSpace.getObjectLocation(this); tmpMyPosition.x = myPositionD3D.x; tmpMyPosition.y = myPositionD3D.y; tmpMyPosition.z = myPositionD3D.z; Bag neighbors = hb.boidSpace.getNeighborsWithinDistance(myPositionD3D, SIGHT); tmpSumOfCrowdForces.x = tmpSumOfCrowdForces.y = tmpSumOfCrowdForces.z = 0; tmpSumOfWallForces.x = tmpSumOfWallForces.y = tmpSumOfWallForces.z = 0; //I run from neighbors for(int i=0;i<neighbors.numObjs; ++i) { if(neighbors.objs[i] == this) continue; Double3D nPosition = hb.boidSpace.getObjectLocation(neighbors.objs[i]); tmpSumOfCrowdForces.x += fn(hb, myPositionD3D.x-nPosition.x); tmpSumOfCrowdForces.y += fn(hb, myPositionD3D.y-nPosition.y); tmpSumOfCrowdForces.z += fn(hb, myPositionD3D.z-nPosition.z); } tmpSumOfCrowdForces.multiplyIn(CROWD_AVERSION); if(myPositionD3D.x < SIGHT/*+0*/) tmpSumOfWallForces.x += fn(hb, myPositionD3D.x/*-0*/); if(myPositionD3D.x> hb.spaceWidth-SIGHT) tmpSumOfWallForces.x -= fn(hb, hb.spaceWidth-myPositionD3D.x); if(myPositionD3D.y< SIGHT/*+0*/) tmpSumOfWallForces.y += fn(hb, myPositionD3D.y/*-0*/); if(myPositionD3D.y> hb.spaceHeight-SIGHT) tmpSumOfWallForces.y -= fn(hb, hb.spaceHeight-myPositionD3D.y); if(myPositionD3D.z< SIGHT/*+0*/) tmpSumOfWallForces.z += fn(hb, myPositionD3D.z/*-0*/); if(myPositionD3D.z> hb.spaceDepth-SIGHT) tmpSumOfWallForces.z -= fn(hb, hb.spaceDepth-myPositionD3D.z); tmpSumOfWallForces.multiplyIn(WALL_AVERSION); tmpSumOfForces.add(tmpSumOfCrowdForces, tmpSumOfWallForces); if(tmpSumOfForces.length()>FORCE_MIN_THRESHOLD) { tmpSumOfForces.normalize(); tmpSumOfForces.multiplyIn(SPEED); tmpMyPosition.addIn(tmpSumOfForces); clamp(tmpMyPosition, hb); Double3D newLocation = new Double3D(tmpMyPosition.x,tmpMyPosition.y,tmpMyPosition.z); hb.boidSpace.setObjectLocation(this,newLocation); } } private void clamp(MutableDouble3D position, CrowdSim hb) { position.x = Math.min(Math.max(position.x, 0), hb.spaceWidth); position.y = Math.min(Math.max(position.y, 0), hb.spaceHeight); position.z = Math.min(Math.max(position.z, 0), hb.spaceDepth); } private double fn(CrowdSim hb, double d) { return Math.min(hb.maxFnVal, 1.0/d); } private Stoppable stopper = null; public void setStopper(Stoppable stopper) {this.stopper = stopper;} public void stop(){stopper.stop();} }