Staging
v0.5.0
v0.5.0
https://repo1.maven.org/maven2/org/prefuse/prefuse
RungeKuttaIntegrator.java
package prefuse.util.force;
import java.util.Iterator;
/**
* Updates velocity and position data using the 4th-Order Runge-Kutta method.
* It is slower but more accurate than other techniques such as Euler's Method.
* The technique requires re-evaluating forces 4 times for a given timestep.
*
* @author <a href="http://jheer.org">jeffrey heer</a>
*/
public class RungeKuttaIntegrator implements Integrator {
/**
* @see prefuse.util.force.Integrator#integrate(prefuse.util.force.ForceSimulator, long)
*/
public void integrate(ForceSimulator sim, long timestep) {
float speedLimit = sim.getSpeedLimit();
float vx, vy, v, coeff;
float[][] k, l;
Iterator iter = sim.getItems();
while ( iter.hasNext() ) {
ForceItem item = (ForceItem)iter.next();
coeff = timestep / item.mass;
k = item.k;
l = item.l;
item.plocation[0] = item.location[0];
item.plocation[1] = item.location[1];
k[0][0] = timestep*item.velocity[0];
k[0][1] = timestep*item.velocity[1];
l[0][0] = coeff*item.force[0];
l[0][1] = coeff*item.force[1];
// Set the position to the new predicted position
item.location[0] += 0.5f*k[0][0];
item.location[1] += 0.5f*k[0][1];
}
// recalculate forces
sim.accumulate();
iter = sim.getItems();
while ( iter.hasNext() ) {
ForceItem item = (ForceItem)iter.next();
coeff = timestep / item.mass;
k = item.k;
l = item.l;
vx = item.velocity[0] + .5f*l[0][0];
vy = item.velocity[1] + .5f*l[0][1];
v = (float)Math.sqrt(vx*vx+vy*vy);
if ( v > speedLimit ) {
vx = speedLimit * vx / v;
vy = speedLimit * vy / v;
}
k[1][0] = timestep*vx;
k[1][1] = timestep*vy;
l[1][0] = coeff*item.force[0];
l[1][1] = coeff*item.force[1];
// Set the position to the new predicted position
item.location[0] = item.plocation[0] + 0.5f*k[1][0];
item.location[1] = item.plocation[1] + 0.5f*k[1][1];
}
// recalculate forces
sim.accumulate();
iter = sim.getItems();
while ( iter.hasNext() ) {
ForceItem item = (ForceItem)iter.next();
coeff = timestep / item.mass;
k = item.k;
l = item.l;
vx = item.velocity[0] + .5f*l[1][0];
vy = item.velocity[1] + .5f*l[1][1];
v = (float)Math.sqrt(vx*vx+vy*vy);
if ( v > speedLimit ) {
vx = speedLimit * vx / v;
vy = speedLimit * vy / v;
}
k[2][0] = timestep*vx;
k[2][1] = timestep*vy;
l[2][0] = coeff*item.force[0];
l[2][1] = coeff*item.force[1];
// Set the position to the new predicted position
item.location[0] = item.plocation[0] + 0.5f*k[2][0];
item.location[1] = item.plocation[1] + 0.5f*k[2][1];
}
// recalculate forces
sim.accumulate();
iter = sim.getItems();
while ( iter.hasNext() ) {
ForceItem item = (ForceItem)iter.next();
coeff = timestep / item.mass;
k = item.k;
l = item.l;
float[] p = item.plocation;
vx = item.velocity[0] + l[2][0];
vy = item.velocity[1] + l[2][1];
v = (float)Math.sqrt(vx*vx+vy*vy);
if ( v > speedLimit ) {
vx = speedLimit * vx / v;
vy = speedLimit * vy / v;
}
k[3][0] = timestep*vx;
k[3][1] = timestep*vy;
l[3][0] = coeff*item.force[0];
l[3][1] = coeff*item.force[1];
item.location[0] = p[0] + (k[0][0]+k[3][0])/6.0f + (k[1][0]+k[2][0])/3.0f;
item.location[1] = p[1] + (k[0][1]+k[3][1])/6.0f + (k[1][1]+k[2][1])/3.0f;
vx = (l[0][0]+l[3][0])/6.0f + (l[1][0]+l[2][0])/3.0f;
vy = (l[0][1]+l[3][1])/6.0f + (l[1][1]+l[2][1])/3.0f;
v = (float)Math.sqrt(vx*vx+vy*vy);
if ( v > speedLimit ) {
vx = speedLimit * vx / v;
vy = speedLimit * vy / v;
}
item.velocity[0] += vx;
item.velocity[1] += vy;
}
}
} // end of class RungeKuttaIntegrator