package com.srbenoit.modeling.grid;
import java.util.logging.Level;
import com.srbenoit.geom.Vector2;
/**
* A base class for objects that may be contained in a 2-dimensional grid. Each object has an X and
* Y position, a radius, and a grid address.
*/
public class DynamicGridMember2D extends PointGridMember2 {
/** a type so we can search for neighbors of a single type, ignoring others */
private final EnumElementType type;
/** the radius of the object */
private double radius;
/** the ID of the structure this member belongs to */
private final int structId;
/** the object velocity (r') */
private final Vector2 vel;
/** the object acceleration (r'') */
private final Vector2 accel;
/** the force on the object */
private final Vector2 force;
/** the object mass */
private double mass;
/**
* Constructs a new GridMember2D
.
*
* @param xCoord the X coordinate
* @param yCoord the Y coordinate
* @param rad the radius of the object
* @param theType the element type
* @param structureId the ID of the structure this member belongs to
* @param theMass the mass of the object
*/
public DynamicGridMember2D(final double xCoord, final double yCoord, final double rad,
final EnumElementType theType, final int structureId, final double theMass) {
super(xCoord, yCoord);
this.radius = rad;
this.vel = new Vector2();
this.accel = new Vector2();
this.force = new Vector2();
this.type = theType;
this.structId = structureId;
this.mass = theMass;
}
/**
* Sets the radius of the object.
*
* @param rad the radius
*/
public void setRadius(final double rad) {
this.radius = rad;
}
/**
* Gets the radius of the object.
*
* @return the radius
*/
@Override public double getRadius() {
return this.radius;
}
/**
* Gets the member type.
*
* @return the type
*/
public EnumElementType getType() {
return this.type;
}
/**
* Gets this structure ID of this object.
*
* @return the structure ID
*/
public int getStructId() {
return this.structId;
}
/**
* Updates the object velocity.
*
* @param newX the new X component of velocity
* @param newY the new Y component of velocity
*/
public void setVel(final double newX, final double newY) {
if (Double.isNaN(newX) || Double.isNaN(newY)) {
LOG.log(Level.WARNING, "Attempt to set grid member velocity to NaN", new Exception());
System.exit(1);
}
if (Double.isInfinite(newX) || Double.isInfinite(newX)) {
LOG.log(Level.WARNING, "Attempt to set grid member velocity by Infinity",
new Exception());
System.exit(1);
}
this.vel.setVec(newX, newY);
}
/**
* Adjusts the object velocity by a specified amount.
*
* @param deltaX the change in X component of velocity
* @param deltaY the change in Y component of velocity
*/
public void addVel(final double deltaX, final double deltaY) {
if (Double.isNaN(deltaX) || Double.isNaN(deltaY)) {
LOG.log(Level.WARNING, "Attempt to move grid member velocity by NaN", new Exception());
System.exit(1);
}
if (Double.isInfinite(deltaX) || Double.isInfinite(deltaY)) {
LOG.log(Level.WARNING, "Attempt to move grid member velocity by Infinity",
new Exception());
System.exit(1);
}
this.vel.addVec(deltaX, deltaY);
}
/**
* Gets the current X component of the object velocity.
*
* @return the X component
*/
public double getXVel() {
return this.vel.getVecX();
}
/**
* Gets the current Y component of the object velocity.
*
* @return the Y component
*/
public double getYVel() {
return this.vel.getVecY();
}
/**
* Gets the speed of the particle.
*
* @return the speed
*/
public double getSpeed() {
return this.vel.length();
}
/**
* Gets the acceleration of the particle.
*
* @return the acceleration
*/
public double getAccel() {
return this.accel.length();
}
/**
* Gets the current X component of the object force.
*
* @return the X component
*/
public double getXForce() {
return this.force.getVecX();
}
/**
* Gets the current Y component of the object force.
*
* @return the Y component
*/
public double getYForce() {
return this.force.getVecY();
}
/**
* Gets the magnitude of the object force.
*
* @return the magnitude of the force
*/
public double getForceMag() {
return this.force.length();
}
/**
* Sets the object force.
*
* @param newX the new X component
* @param newY the new Y component
*/
public void setForce(final double newX, final double newY) {
if (Double.isNaN(newX) || Double.isNaN(newY)) {
LOG.log(Level.WARNING, "Attempt to set grid member force to NaN", new Exception());
System.exit(1);
}
if (Double.isInfinite(newX) || Double.isInfinite(newY)) {
LOG.log(Level.WARNING, "Attempt to set grid member force to Infinity",
new Exception());
System.exit(1);
}
this.force.setVec(newX, newY);
}
/**
* Adds velocity components to the current force.
*
* @param deltaX the change in X component
* @param deltaY the change in Y component
*/
public void addForce(final double deltaX, final double deltaY) {
if (Double.isNaN(deltaX) || Double.isNaN(deltaY)) {
LOG.log(Level.WARNING, "Attempt to adjust grid member force by NaN", new Exception());
System.exit(1);
}
if (Double.isInfinite(deltaX) || Double.isInfinite(deltaY)) {
LOG.log(Level.WARNING, "Attempt to adjust grid member force by Infinity",
new Exception());
System.exit(1);
}
this.force.addVec(deltaX, deltaY);
}
/**
* Clears any existing forces and computes the forces on the element due to interactions with
* outside elements. Subclasses should override. This does not include the internal forces of
* the structure to which the element belongs, which should be done after this method is
* called.
*/
public void interactionForce() {
this.vel.setVec(0, 0);
}
/**
* Performs the first step in Velocity Verlet integration. Here, we compute new positions based
* on velocities and accelerations computed in the last step.
*
*
* x(t + dt) = x(t) + v(t) dt + (1/2) a(t) dt^2 ** * @param deltaT the time step */ public void predict(final double deltaT) { double dt2over2; double deltaX; double deltaY; dt2over2 = deltaT * deltaT / 2; deltaX = (deltaT * this.vel.getVecX()) + (dt2over2 * this.accel.getVecX()); deltaY = (deltaT * this.vel.getVecY()) + (dt2over2 * this.accel.getVecY()); move(deltaX, deltaY); } /** * Performs the second step in Velocity Verlet integration, to be done after forces are * computed. * *
* v(t + dt) = v(t) + (1/2)(a(t) + f/m) dt * a(t + dt) = f/m ** * @param deltaT the time step */ public void correct(final double deltaT) { double realAccelX; double realAccelY; realAccelX = this.force.getVecX() / this.mass; realAccelY = this.force.getVecY() / this.mass; // the 0.1 in the next should be 0.5 - testing damping addVel(0.1 * (this.accel.getVecX() + realAccelX) * deltaT, 0.1 * (this.accel.getVecY() + realAccelY) * deltaT); this.accel.setVec(realAccelX, realAccelY); } }