All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sim.app.woims3d.Woim3D Maven / Gradle / Ivy

Go to download

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