generateIntegrator.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. const createPatternBuilder = require('./createPatternBuilder');
  2. module.exports = generateIntegratorFunction;
  3. module.exports.generateIntegratorFunctionBody = generateIntegratorFunctionBody;
  4. function generateIntegratorFunction(dimension) {
  5. let code = generateIntegratorFunctionBody(dimension);
  6. return new Function('bodies', 'timeStep', 'adaptiveTimeStepWeight', code);
  7. }
  8. function generateIntegratorFunctionBody(dimension) {
  9. let pattern = createPatternBuilder(dimension);
  10. let code = `
  11. var length = bodies.length;
  12. if (length === 0) return 0;
  13. ${pattern('var d{var} = 0, t{var} = 0;', {indent: 2})}
  14. for (var i = 0; i < length; ++i) {
  15. var body = bodies[i];
  16. if (body.isPinned) continue;
  17. if (adaptiveTimeStepWeight && body.springCount) {
  18. timeStep = (adaptiveTimeStepWeight * body.springLength/body.springCount);
  19. }
  20. var coeff = timeStep / body.mass;
  21. ${pattern('body.velocity.{var} += coeff * body.force.{var};', {indent: 4})}
  22. ${pattern('var v{var} = body.velocity.{var};', {indent: 4})}
  23. var v = Math.sqrt(${pattern('v{var} * v{var}', {join: ' + '})});
  24. if (v > 1) {
  25. // We normalize it so that we move within timeStep range.
  26. // for the case when v <= 1 - we let velocity to fade out.
  27. ${pattern('body.velocity.{var} = v{var} / v;', {indent: 6})}
  28. }
  29. ${pattern('d{var} = timeStep * body.velocity.{var};', {indent: 4})}
  30. ${pattern('body.pos.{var} += d{var};', {indent: 4})}
  31. ${pattern('t{var} += Math.abs(d{var});', {indent: 4})}
  32. }
  33. return (${pattern('t{var} * t{var}', {join: ' + '})})/length;
  34. `;
  35. return code;
  36. }