generateBounds.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. module.exports = generateBoundsFunction;
  2. module.exports.generateFunctionBody = generateBoundsFunctionBody;
  3. const createPatternBuilder = require('./createPatternBuilder');
  4. function generateBoundsFunction(dimension) {
  5. let code = generateBoundsFunctionBody(dimension);
  6. return new Function('bodies', 'settings', 'random', code);
  7. }
  8. function generateBoundsFunctionBody(dimension) {
  9. let pattern = createPatternBuilder(dimension);
  10. let code = `
  11. var boundingBox = {
  12. ${pattern('min_{var}: 0, max_{var}: 0,', {indent: 4})}
  13. };
  14. return {
  15. box: boundingBox,
  16. update: updateBoundingBox,
  17. reset: resetBoundingBox,
  18. getBestNewPosition: function (neighbors) {
  19. var ${pattern('base_{var} = 0', {join: ', '})};
  20. if (neighbors.length) {
  21. for (var i = 0; i < neighbors.length; ++i) {
  22. let neighborPos = neighbors[i].pos;
  23. ${pattern('base_{var} += neighborPos.{var};', {indent: 10})}
  24. }
  25. ${pattern('base_{var} /= neighbors.length;', {indent: 8})}
  26. } else {
  27. ${pattern('base_{var} = (boundingBox.min_{var} + boundingBox.max_{var}) / 2;', {indent: 8})}
  28. }
  29. var springLength = settings.springLength;
  30. return {
  31. ${pattern('{var}: base_{var} + (random.nextDouble() - 0.5) * springLength,', {indent: 8})}
  32. };
  33. }
  34. };
  35. function updateBoundingBox() {
  36. var i = bodies.length;
  37. if (i === 0) return; // No bodies - no borders.
  38. ${pattern('var max_{var} = -Infinity;', {indent: 4})}
  39. ${pattern('var min_{var} = Infinity;', {indent: 4})}
  40. while(i--) {
  41. // this is O(n), it could be done faster with quadtree, if we check the root node bounds
  42. var bodyPos = bodies[i].pos;
  43. ${pattern('if (bodyPos.{var} < min_{var}) min_{var} = bodyPos.{var};', {indent: 6})}
  44. ${pattern('if (bodyPos.{var} > max_{var}) max_{var} = bodyPos.{var};', {indent: 6})}
  45. }
  46. ${pattern('boundingBox.min_{var} = min_{var};', {indent: 4})}
  47. ${pattern('boundingBox.max_{var} = max_{var};', {indent: 4})}
  48. }
  49. function resetBoundingBox() {
  50. ${pattern('boundingBox.min_{var} = boundingBox.max_{var} = 0;', {indent: 4})}
  51. }
  52. `;
  53. return code;
  54. }