sim.app.woims3d.Woim3D Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mason Show documentation
Show all versions of mason Show documentation
MASON is a fast discrete-event multiagent simulation library core in Java, designed to be the foundation for large custom-purpose Java simulations, and also to provide more than enough functionality for many lightweight simulation needs. MASON contains both a model library and an optional suite of visualization tools in 2D and 3D.
The newest version!
/*
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.woims3d;
import sim.util.*;
import sim.engine.*;
import sim.portrayal3d.*;
import sim.portrayal3d.simple.*;
import javax.media.j3d.*;
import javax.vecmath.*;
/**
This class demonstrates that it is perfectly POSSIBLE to create a SimplePortrayal3D
which is also a Steppable in the model -- but it's not a good idea, because it's not serializable
and so you can't save your model out to a checkpoint. In 3D, you should make separate portrayals
from model objects.
*/
public class Woim3D extends SimplePortrayal3D implements Steppable
{
private static final long serialVersionUID = 1;
public static final double CENTROID_DISTANCE = 20 * WoimsDemo3D.DIAMETER;
public static final double AVOID_DISTANCE = 16 * WoimsDemo3D.DIAMETER;
public static final double COPY_SPEED_DISTANCE = 40 * WoimsDemo3D.DIAMETER;
public static final double OBSTACLE_AVOID_COEF = 1.05;
public static final double OBSTACLE_FAST_AVOID_COEF = 1.5;
public static final double MAX_DISTANCE = Math.max( CENTROID_DISTANCE, Math.max( AVOID_DISTANCE, COPY_SPEED_DISTANCE ) );
public static final double ADJUSTMENT_RATE = 0.025;
public static final double MIN_VELOCITY = 0.25;
public static final double MAX_VELOCITY = 0.75;
public Woim3D()
{
ond = Math.random()*2*Math.PI;
ondSpeed = 0.05 + Math.random()*0.15;
for( int i = 0 ; i < colors.length ; i++ )
colors[i] = new java.awt.Color(63 + (int)(192*(colors.length-i)/colors.length),0,0);
//((float)(63f+(192.0*(colors.length-i))/colors.length)/255.0f, 0f, 0f );
velocity = new Vector3D(0.05,0.05, 0.05);
computePositions();
}
public final double distanceSquared( final Vector3D loc1, final Vector3D loc2 )
{
return( (loc1.x-loc2.x)*(loc1.x-loc2.x)+(loc1.y-loc2.y)*(loc1.y-loc2.y)+(loc1.z-loc2.z)*(loc1.z-loc2.z) );
}
public final double distanceSquared( final Vector3D loc1, final Double3D loc2 )
{
return( (loc1.x-loc2.x)*(loc1.x-loc2.x)+(loc1.y-loc2.y)*(loc1.y-loc2.y)+(loc1.z-loc2.z)*(loc1.z-loc2.z) );
}
public final double distanceSquared( final double x1, final double y1, final double z1, final double x2, final double y2, final double z2 )
{
return ((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2));
}
Bag nearbyWoims;
double[] distSqrTo;
void preprocessWoims( final WoimsDemo3D state, Double3D pos, double distance )
{
nearbyWoims = state.woimEnvironment.getNeighborsWithinDistance( pos, distance );
/*
if( nearbyWoims == null )
return;
*/
distSqrTo = new double[nearbyWoims.numObjs];
for( int i = 0 ; i < nearbyWoims.numObjs ; i++ )
{
Woim3D p = (Woim3D)(nearbyWoims.objs[i]);
distSqrTo[i] = distanceSquared(
pos.x,pos.y,pos.z,p.x,p.y,p.z);
}
}
public Vector3D towardsFlockCenterOfMass( final WoimsDemo3D state )
{
if( nearbyWoims == null )
return new Vector3D( 0, 0, 0 );
Vector3D mean = new Vector3D( 0, 0, 0 );
int n = 0;
for( int i = 0 ; i < nearbyWoims.numObjs ; i++ )
{
if( nearbyWoims.objs[i] != this &&
distSqrTo[i] <= CENTROID_DISTANCE * CENTROID_DISTANCE &&
distSqrTo[i] > AVOID_DISTANCE * AVOID_DISTANCE )
{
Woim3D p = (Woim3D)(nearbyWoims.objs[i]);
mean = mean.add(new Double3D(p.x,p.y,p.z));
n++;
}
}
if( n == 0 )
return new Vector3D( 0, 0, 0 );
else
{
mean = mean.amplify( 1.0 / n );
mean = mean.subtract( woimPosition );
return mean.normalize();
}
}
public Vector3D awayFromCloseBys( final WoimsDemo3D state )
{
if( nearbyWoims == null )
return new Vector3D( 0, 0, 0 );
Vector3D away = new Vector3D( 0, 0, 0 );
for( int i = 0 ; i < nearbyWoims.numObjs ; i++ )
{
if( nearbyWoims.objs[i] != this &&
distSqrTo[i] <= AVOID_DISTANCE * AVOID_DISTANCE )
{
Woim3D p = (Woim3D)(nearbyWoims.objs[i]);
Vector3D temp = woimPosition.subtract(new Double3D(p.x,p.y,p.z));
temp = temp.normalize();
away = away.add( temp );
}
}
return away.normalize();
}
public Vector3D matchFlockSpeed( final SimState state )
{
if( nearbyWoims == null )
return new Vector3D( 0, 0, 0 );
Vector3D mean = new Vector3D( 0, 0, 0 );
int n = 0;
for( int i = 0 ; i < nearbyWoims.numObjs ; i++ )
{
if( nearbyWoims.objs[i] != this &&
distSqrTo[i] <= COPY_SPEED_DISTANCE * COPY_SPEED_DISTANCE &&
distSqrTo[i] > AVOID_DISTANCE * AVOID_DISTANCE )
{
mean = mean.add( ((Woim3D)(nearbyWoims.objs[i])).velocity );
n++;
}
}
if( n == 0 )
return new Vector3D( 0, 0, 0 );
else
{
mean = mean.amplify( 1.0 / n );
return mean.normalize();
}
}
public Vector3D randomDirection( final SimState state )
{
Vector3D temp = new Vector3D( 1.0 - 2.0 * state.random.nextDouble(),
1.0 - 2.0 * state.random.nextDouble(),
1.0 - 2.0 * state.random.nextDouble() );
return temp.setLength( MIN_VELOCITY + state.random.nextDouble()*(MAX_VELOCITY-MIN_VELOCITY) );
}
double ond;
double ondSpeed;
public Vector3D niceUndulation( final SimState state )
{
ond += ondSpeed;
if( ond > 7 )
ond -= 2*Math.PI;
double angle = Math.cos( ond );
Vector3D temp = velocity;
double velA = Math.atan2( temp.y, temp.x );
velA = velA + (Math.PI / 2)*angle;
return new Vector3D( Math.cos(velA), Math.sin(velA), 0 );
}
public Vector3D avoidObstacles( final SimState state )
{
double[][] info = WoimsDemo3D.obstInfo;
if( info == null || info.length == 0 )
return new Vector3D( 0, 0, 0 );
Vector3D away = new Vector3D( 0, 0, 0 );
for( int i = 0 ; i < info.length ; i++ )
{
double dist = Math.sqrt( (woimPosition.x-info[i][1])*(woimPosition.x-info[i][1]) +
(woimPosition.y-info[i][2])*(woimPosition.y-info[i][2]) +
(woimPosition.z-info[i][3])*(woimPosition.z-info[i][3]) );
if( dist <= info[i][0]+AVOID_DISTANCE )
{
Vector3D temp = woimPosition.subtract( new Vector3D( info[i][1], info[i][2], info[i][3] ) );
temp = temp.normalize();
away = away.add( temp );
}
}
return away.normalize();
}
protected Vector3D woimPosition = new Vector3D( 0, 0, 0 );
public void step( final SimState state )
{
WoimsDemo3D bd = (WoimsDemo3D)state;
{
Double3D temp = new Double3D(x,y,z);
woimPosition.x = x;
woimPosition.y = y;
woimPosition.z = z;
preprocessWoims( bd, temp, MAX_DISTANCE );
}
Vector3D vel = new Vector3D( 0, 0, 0 );
vel = vel.add( avoidObstacles(bd).amplify( 1.5 ) );
vel = vel.add( towardsFlockCenterOfMass(bd).amplify(0.5) );
vel = vel.add( matchFlockSpeed(bd).amplify(0.5) );
vel = vel.add( awayFromCloseBys(bd).amplify(1.5) );
if( vel.length() <= 1.0 )
{
vel = vel.add( niceUndulation(bd).amplify(0.5) );
vel = vel.add( randomDirection(bd).amplify(0.25) );
}
double vl = vel.length();
if( vl < MIN_VELOCITY )
vel = vel.setLength( MIN_VELOCITY );
else if( vl > MAX_VELOCITY )
vel = vel.setLength( MAX_VELOCITY );
vel = new Vector3D( (1-ADJUSTMENT_RATE)*velocity.x + ADJUSTMENT_RATE*vel.x,
(1-ADJUSTMENT_RATE)*velocity.y + ADJUSTMENT_RATE*vel.y,
(1-ADJUSTMENT_RATE)*velocity.z + ADJUSTMENT_RATE*vel.z );
velocity = vel;
Double3D desiredPosition = new Double3D( woimPosition.x+vel.x*WoimsDemo3D.TIMESTEP,
woimPosition.y+vel.y*WoimsDemo3D.TIMESTEP,
woimPosition.z+vel.z*WoimsDemo3D.TIMESTEP );
bd.setObjectLocation( this, desiredPosition );
}
public double x;
public double y;
public double z;
final static int numLinks = 12;
Vector3d[] lastPos = new Vector3d[numLinks];
Vector3d[] lastPosRel = new Vector3d[numLinks];
java.awt.Color[] colors = new java.awt.Color[numLinks];
protected double orientation;
protected Vector3D velocity = new Vector3D( 0, 0, 0 );
protected Vector3D acceleration = new Vector3D( 0, 0, 0 );
public static final float SKIP = 4.0f;
public void computePositions()
{
double centerx, centery, centerz;
// the head!
centerx = x + 1.0/2.0;
centery = y + 1.0/2.0;
centerz = z + 1.0/2.0;
lastPos[0] = new Vector3d( centerx, centery, centerz );
Vector3d temp = new Vector3d();
Vector3d velocity3d = new Vector3d(velocity.x, velocity.y, velocity.z);
for( int i = 1 ; i < numLinks ; i++ )
{
if( lastPos[i] == null )
{
temp.scale(-1.0, velocity3d);
temp.normalize();
centerx = lastPos[i-1].x+temp.x;
centery = lastPos[i-1].y+temp.y;
centerz = lastPos[i-1].z+temp.z;
lastPos[i] = new Vector3d( centerx, centery, centerz );
}
else
{
temp.sub(lastPos[i-1], lastPos[i] );
temp.scale(SKIP/temp.length());
temp.sub(lastPos[i-1], temp);
lastPos[i] = new Vector3d( temp.x, temp.y, temp.z );
}
}
for( int i = 0 ; i < lastPosRel.length ; i++ )
{
lastPosRel[i] = new Vector3d( lastPos[i].x-lastPos[0].x,
lastPos[i].y-lastPos[0].y,
lastPos[i].z-lastPos[0].z );
}
}
public TransformGroup createModel(Object obj)
{
TransformGroup globalTG = new TransformGroup();
for(int i=0; i< numLinks; ++i)
{
// we set the number of divisions to 6 and it's quite a bit faster and
// less memory-hungry. The default is 15. This is a sort of goofy way of
// doing things.
SpherePortrayal3D s = new SpherePortrayal3D(colors[i], 4.0f , 6);
s.setCurrentFieldPortrayal(getCurrentFieldPortrayal());
TransformGroup localTG = s.getModel(obj, null);
localTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
globalTG.addChild(localTG);
}
globalTG.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
return globalTG;
}
public TransformGroup getModel(Object obj, TransformGroup transf)
{
computePositions();
if(transf==null) return createModel(obj);
for(int i=0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy