package prefuse.util.force;
/**
* Uses a gravitational force model to act as a circular "wall". Can be used to
* construct circles which either attract or repel items.
*
* @author <a href="http://jheer.org">jeffrey heer</a>
*/
public class CircularWallForce extends AbstractForce {
private static String[] pnames = new String[] { "GravitationalConstant" };
public static final float DEFAULT_GRAV_CONSTANT = -0.1f;
public static final float DEFAULT_MIN_GRAV_CONSTANT = -1.0f;
public static final float DEFAULT_MAX_GRAV_CONSTANT = 1.0f;
public static final int GRAVITATIONAL_CONST = 0;
private float x, y, r;
/**
* Create a new CircularWallForce.
* @param gravConst the gravitational constant to use
* @param x the center x-coordinate of the circle
* @param y the center y-coordinate of the circle
* @param r the radius of the circle
*/
public CircularWallForce(float gravConst,
float x, float y, float r)
{
params = new float[] { gravConst };
minValues = new float[] { DEFAULT_MIN_GRAV_CONSTANT };
maxValues = new float[] { DEFAULT_MAX_GRAV_CONSTANT };
this.x = x; this.y = y;
this.r = r;
}
/**
* Create a new CircularWallForce with default gravitational constant.
* @param x the center x-coordinate of the circle
* @param y the center y-coordinate of the circle
* @param r the radius of the circle
*/
public CircularWallForce(float x, float y, float r) {
this(DEFAULT_GRAV_CONSTANT,x,y,r);
}
/**
* Returns true.
* @see prefuse.util.force.Force#isItemForce()
*/
public boolean isItemForce() {
return true;
}
/**
* @see prefuse.util.force.AbstractForce#getParameterNames()
*/
protected String[] getParameterNames() {
return pnames;
}
/**
* @see prefuse.util.force.Force#getForce(prefuse.util.force.ForceItem)
*/
public void getForce(ForceItem item) {
float[] n = item.location;
float dx = x-n[0];
float dy = y-n[1];
float d = (float)Math.sqrt(dx*dx+dy*dy);
float dr = r-d;
float c = dr > 0 ? -1 : 1;
float v = c*params[GRAVITATIONAL_CONST]*item.mass / (dr*dr);
if ( d == 0.0 ) {
dx = ((float)Math.random()-0.5f) / 50.0f;
dy = ((float)Math.random()-0.5f) / 50.0f;
d = (float)Math.sqrt(dx*dx+dy*dy);
}
item.force[0] += v*dx/d;
item.force[1] += v*dy/d;
//System.out.println(dx/d+","+dy/d+","+dr+","+v);
}
} // end of class CircularWallForce