text: !function(f){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=f();else if("function"==typeof define&&define.amd)define([],f);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).ngraphCreateLayout=f()}}((function(){return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,(function(e){var n=t[o][1][e];return s(n||e)}),l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){module.exports=function(graph,physicsSettings){if(!graph)throw new Error("Graph structure cannot be undefined");var physicsSimulator=(physicsSettings&&physicsSettings.createSimulator||require("./lib/createPhysicsSimulator"))(physicsSettings);if(Array.isArray(physicsSettings))throw new Error("Physics settings is expected to be an object");var nodeMass=function(nodeId){var links=graph.getLinks(nodeId);return links?1+links.length/3:1};physicsSettings&&"function"==typeof physicsSettings.nodeMass&&(nodeMass=physicsSettings.nodeMass);var nodeBodies=new Map,springs={},bodiesCount=0,springTransform=physicsSimulator.settings.springTransform||noop;bodiesCount=0,graph.forEachNode((function(node){initBody(node.id),bodiesCount+=1})),graph.forEachLink(initLink),graph.on("changed",onGraphChanged);var wasStable=!1,api={step:function(){if(0===bodiesCount)return updateStableStatus(!0),!0;var lastMove=physicsSimulator.step();api.lastMove=lastMove,api.fire("step");var isStableNow=lastMove/bodiesCount<=.01;return updateStableStatus(isStableNow),isStableNow},getNodePosition:function(nodeId){return getInitializedBody(nodeId).pos},setNodePosition:function(nodeId){var body=getInitializedBody(nodeId);body.setPosition.apply(body,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(linkId){var spring=springs[linkId];if(spring)return{from:spring.from.pos,to:spring.to.pos}},getGraphRect:function(){return physicsSimulator.getBBox()},forEachBody:forEachBody,pinNode:function(node,isPinned){getInitializedBody(node.id).isPinned=!!isPinned},isNodePinned:function(node){return getInitializedBody(node.id).isPinned},dispose:function(){graph.off("changed",onGraphChanged),api.fire("disposed")},getBody:function(nodeId){return nodeBodies.get(nodeId)},getSpring:function(fromId,toId){var linkId;if(void 0===toId)linkId="object"!=typeof fromId?fromId:fromId.id;else{var link=graph.hasLink(fromId,toId);if(!link)return;linkId=link.id}return springs[linkId]},getForceVectorLength:function(){var fx=0,fy=0;return forEachBody((function(body){fx+=Math.abs(body.force.x),fy+=Math.abs(body.force.y)})),Math.sqrt(fx*fx+fy*fy)},simulator:physicsSimulator,graph:graph,lastMove:0};return eventify(api),api;function updateStableStatus(isStableNow){var isStable;wasStable!==isStableNow&&(wasStable=isStableNow,isStable=isStableNow,api.fire("stable",isStable))}function forEachBody(cb){nodeBodies.forEach((function(body,bodyId){cb(body,bodyId)}))}function onGraphChanged(changes){for(var i=0;i<changes.length;++i){var change=changes[i];"add"===change.changeType?(change.node&&initBody(change.node.id),change.link&&initLink(change.link)):"remove"===change.changeType&&(change.node&&releaseNode(change.node),change.link&&releaseLink(change.link))}bodiesCount=graph.getNodesCount()}function initBody(nodeId){var body=nodeBodies.get(nodeId);if(!body){var node=graph.getNode(nodeId);if(!node)throw new Error("initBody() was called with unknown node id");var pos=node.position;if(!pos){var neighbors=function(node){var neighbors=[];if(!node.links)return neighbors;for(var maxNeighbors=Math.min(node.links.length,2),i=0;i<maxNeighbors;++i){var link=node.links[i],otherBody=link.fromId!==node.id?nodeBodies.get(link.fromId):nodeBodies.get(link.toId);otherBody&&otherBody.pos&&neighbors.push(otherBody)}return neighbors}(node);pos=physicsSimulator.getBestNewBodyPosition(neighbors)}(body=physicsSimulator.addBodyAt(pos)).id=nodeId,nodeBodies.set(nodeId,body),updateBodyMass(nodeId),function(node){return node&&(node.isPinned||node.data&&node.data.isPinned)}(node)&&(body.isPinned=!0)}}function releaseNode(node){var nodeId=node.id,body=nodeBodies.get(nodeId);body&&(nodeBodies.delete(nodeId),physicsSimulator.removeBody(body))}function initLink(link){updateBodyMass(link.fromId),updateBodyMass(link.toId);var fromBody=nodeBodies.get(link.fromId),toBody=nodeBodies.get(link.toId),spring=physicsSimulator.addSpring(fromBody,toBody,link.length);springTransform(link,spring),springs[link.id]=spring}function releaseLink(link){var spring=springs[link.id];if(spring){var from=graph.getNode(link.fromId),to=graph.getNode(link.toId);from&&updateBodyMass(from.id),to&&updateBodyMass(to.id),delete springs[link.id],physicsSimulator.removeSpring(spring)}}function updateBodyMass(nodeId){var body=nodeBodies.get(nodeId);if(body.mass=nodeMass(nodeId),Number.isNaN(body.mass))throw new Error("Node mass should be a number")}function getInitializedBody(nodeId){var body=nodeBodies.get(nodeId);return body||(initBody(nodeId),body=nodeBodies.get(nodeId)),body}},module.exports.simulator=require("./lib/createPhysicsSimulator");var eventify=require("ngraph.events");function noop(){}},{"./lib/createPhysicsSimulator":10,"ngraph.events":12}],2:[function(require,module,exports){const getVariableName=require("./getVariableName");module.exports=function(dimension){return function(template,config){let indent=config&&config.indent||0,join=config&&void 0!==config.join?config.join:"\n",indentString=Array(indent+1).join(" "),buffer=[];for(let i=0;i<dimension;++i){let variableName=getVariableName(i),prefix=0===i?"":indentString;buffer.push(prefix+template.replace(/{var}/g,variableName))}return buffer.join(join)}}},{"./getVariableName":9}],3:[function(require,module,exports){module.exports=function(dimension){let code=generateBoundsFunctionBody(dimension);return new Function("bodies","settings","random",code)},module.exports.generateFunctionBody=generateBoundsFunctionBody;const createPatternBuilder=require("./createPatternBuilder");function generateBoundsFunctionBody(dimension){let pattern=createPatternBuilder(dimension);return`\n  var boundingBox = {\n    ${pattern("min_{var}: 0, max_{var}: 0,",{indent:4})}\n  };\n\n  return {\n    box: boundingBox,\n\n    update: updateBoundingBox,\n\n    reset: resetBoundingBox,\n\n    getBestNewPosition: function (neighbors) {\n      var ${pattern("base_{var} = 0",{join:", "})};\n\n      if (neighbors.length) {\n        for (var i = 0; i < neighbors.length; ++i) {\n          let neighborPos = neighbors[i].pos;\n          ${pattern("base_{var} += neighborPos.{var};",{indent:10})}\n        }\n\n        ${pattern("base_{var} /= neighbors.length;",{indent:8})}\n      } else {\n        ${pattern("base_{var} = (boundingBox.min_{var} + boundingBox.max_{var}) / 2;",{indent:8})}\n      }\n\n      var springLength = settings.springLength;\n      return {\n        ${pattern("{var}: base_{var} + (random.nextDouble() - 0.5) * springLength,",{indent:8})}\n      };\n    }\n  };\n\n  function updateBoundingBox() {\n    var i = bodies.length;\n    if (i === 0) return; // No bodies - no borders.\n\n    ${pattern("var max_{var} = Number.MIN_VALUE;",{indent:4})}\n    ${pattern("var min_{var} = Number.MAX_VALUE;",{indent:4})}\n\n    while(i--) {\n      // this is O(n), it could be done faster with quadtree, if we check the root node bounds\n      var bodyPos = bodies[i].pos;\n      ${pattern("if (bodyPos.{var} < min_{var}) min_{var} = bodyPos.{var};",{indent:6})}\n      ${pattern("if (bodyPos.{var} > max_{var}) max_{var} = bodyPos.{var};",{indent:6})}\n    }\n\n    ${pattern("boundingBox.min_{var} = min_{var};",{indent:4})}\n    ${pattern("boundingBox.max_{var} = max_{var};",{indent:4})}\n  }\n\n  function resetBoundingBox() {\n    ${pattern("boundingBox.min_{var} = boundingBox.max_{var} = 0;",{indent:4})}\n  }\n`}},{"./createPatternBuilder":2}],4:[function(require,module,exports){const createPatternBuilder=require("./createPatternBuilder");function generateCreateBodyFunctionBody(dimension,debugSetters){let pattern=createPatternBuilder(dimension),variableList=pattern("{var}",{join:", "}),setters="";return debugSetters&&(setters=""+pattern("\n   var v{var};\nObject.defineProperty(this, '{var}', {\n  set: function(v) { \n    if (!Number.isFinite(v)) throw new Error('Cannot set non-numbers to {var}');\n    v{var} = v; \n  },\n  get: function() { return v{var}; }\n});")),`\nfunction Vector(${variableList}) {\n${setters}\n  if (typeof arguments[0] === 'object') {\n    // could be another vector\n    let v = arguments[0];\n    ${pattern('if (!Number.isFinite(v.{var})) throw new Error("Expected value is not a finite number at Vector constructor ({var})");',{indent:4})}\n    ${pattern("this.{var} = v.{var};",{indent:4})}\n  } else {\n    ${pattern('this.{var} = typeof {var} === "number" ? {var} : 0;',{indent:4})}\n  }\n}\n\nVector.prototype.reset = function () {\n  ${pattern("this.{var} = ",{join:""})}0;\n};\n\nfunction Body(${variableList}) {\n  this.isPinned = false;\n  this.pos = new Vector(${variableList});\n  this.force = new Vector();\n  this.velocity = new Vector();\n  this.mass = 1;\n\n  this.springCount = 0;\n  this.springLength = 0;\n}\n\nBody.prototype.reset = function() {\n  this.force.reset();\n  this.springCount = 0;\n  this.springLength = 0;\n}\n\nBody.prototype.setPosition = function (${variableList}) {\n  ${pattern("this.pos.{var} = {var} || 0;",{indent:2})}\n};\n\nreturn {Body: Body, Vector: Vector};\n`}module.exports=function(dimension,debugSetters){let code=generateCreateBodyFunctionBody(dimension,debugSetters),{Body:Body}=new Function(code)();return Body},module.exports.generateCreateBodyFunctionBody=generateCreateBodyFunctionBody},{"./createPatternBuilder":2}],5:[function(require,module,exports){const createPatternBuilder=require("./createPatternBuilder");function generateCreateDragForceFunctionBody(dimension){return`\n  if (!Number.isFinite(options.dragCoefficient)) throw new Error('dragCoefficient is not a finite number');\n\n  return {\n    update: function(body) {\n      ${createPatternBuilder(dimension)("body.force.{var} -= options.dragCoefficient * body.velocity.{var};",{indent:6})}\n    }\n  };\n`}module.exports=function(dimension){let code=generateCreateDragForceFunctionBody(dimension);return new Function("options",code)},module.exports.generateCreateDragForceFunctionBody=generateCreateDragForceFunctionBody},{"./createPatternBuilder":2}],6:[function(require,module,exports){const createPatternBuilder=require("./createPatternBuilder");function generateCreateSpringForceFunctionBody(dimension){let pattern=createPatternBuilder(dimension);return`\n  if (!Number.isFinite(options.springCoefficient)) throw new Error('Spring coefficient is not a number');\n  if (!Number.isFinite(options.springLength)) throw new Error('Spring length is not a number');\n\n  return {\n    /**\n     * Updates forces acting on a spring\n     */\n    update: function (spring) {\n      var body1 = spring.from;\n      var body2 = spring.to;\n      var length = spring.length < 0 ? options.springLength : spring.length;\n      ${pattern("var d{var} = body2.pos.{var} - body1.pos.{var};",{indent:6})}\n      var r = Math.sqrt(${pattern("d{var} * d{var}",{join:" + "})});\n\n      if (r === 0) {\n        ${pattern("d{var} = (random.nextDouble() - 0.5) / 50;",{indent:8})}\n        r = Math.sqrt(${pattern("d{var} * d{var}",{join:" + "})});\n      }\n\n      var d = r - length;\n      var coefficient = ((spring.coefficient > 0) ? spring.coefficient : options.springCoefficient) * d / r;\n\n      ${pattern("body1.force.{var} += coefficient * d{var}",{indent:6})};\n      body1.springCount += 1;\n      body1.springLength += r;\n\n      ${pattern("body2.force.{var} -= coefficient * d{var}",{indent:6})};\n      body2.springCount += 1;\n      body2.springLength += r;\n    }\n  };\n`}module.exports=function(dimension){let code=generateCreateSpringForceFunctionBody(dimension);return new Function("options","random",code)},module.exports.generateCreateSpringForceFunctionBody=generateCreateSpringForceFunctionBody},{"./createPatternBuilder":2}],7:[function(require,module,exports){const createPatternBuilder=require("./createPatternBuilder");function generateIntegratorFunctionBody(dimension){let pattern=createPatternBuilder(dimension);return`\n  var length = bodies.length;\n  if (length === 0) return 0;\n\n  ${pattern("var d{var} = 0, t{var} = 0;",{indent:2})}\n\n  for (var i = 0; i < length; ++i) {\n    var body = bodies[i];\n    if (body.isPinned) continue;\n\n    if (adaptiveTimeStepWeight && body.springCount) {\n      timeStep = (adaptiveTimeStepWeight * body.springLength/body.springCount);\n    }\n\n    var coeff = timeStep / body.mass;\n\n    ${pattern("body.velocity.{var} += coeff * body.force.{var};",{indent:4})}\n    ${pattern("var v{var} = body.velocity.{var};",{indent:4})}\n    var v = Math.sqrt(${pattern("v{var} * v{var}",{join:" + "})});\n\n    if (v > 1) {\n      // We normalize it so that we move within timeStep range. \n      // for the case when v <= 1 - we let velocity to fade out.\n      ${pattern("body.velocity.{var} = v{var} / v;",{indent:6})}\n    }\n\n    ${pattern("d{var} = timeStep * body.velocity.{var};",{indent:4})}\n\n    ${pattern("body.pos.{var} += d{var};",{indent:4})}\n\n    ${pattern("t{var} += Math.abs(d{var});",{indent:4})}\n  }\n\n  return (${pattern("t{var} * t{var}",{join:" + "})})/length;\n`}module.exports=function(dimension){let code=generateIntegratorFunctionBody(dimension);return new Function("bodies","timeStep","adaptiveTimeStepWeight",code)},module.exports.generateIntegratorFunctionBody=generateIntegratorFunctionBody},{"./createPatternBuilder":2}],8:[function(require,module,exports){const createPatternBuilder=require("./createPatternBuilder"),getVariableName=require("./getVariableName");function generateQuadTreeFunctionBody(dimension){let pattern=createPatternBuilder(dimension),quadCount=Math.pow(2,dimension);return`\n\n/**\n * Our implementation of QuadTree is non-recursive to avoid GC hit\n * This data structure represent stack of elements\n * which we are trying to insert into quad tree.\n */\nfunction InsertStack () {\n    this.stack = [];\n    this.popIdx = 0;\n}\n\nInsertStack.prototype = {\n    isEmpty: function() {\n        return this.popIdx === 0;\n    },\n    push: function (node, body) {\n        var item = this.stack[this.popIdx];\n        if (!item) {\n            // we are trying to avoid memory pressure: create new element\n            // only when absolutely necessary\n            this.stack[this.popIdx] = new InsertStackElement(node, body);\n        } else {\n            item.node = node;\n            item.body = body;\n        }\n        ++this.popIdx;\n    },\n    pop: function () {\n        if (this.popIdx > 0) {\n            return this.stack[--this.popIdx];\n        }\n    },\n    reset: function () {\n        this.popIdx = 0;\n    }\n};\n\nfunction InsertStackElement(node, body) {\n    this.node = node; // QuadTree node\n    this.body = body; // physical body which needs to be inserted to node\n}\n\n\nfunction QuadNode() {\n  // body stored inside this node. In quad tree only leaf nodes (by construction)\n  // contain bodies:\n  this.body = null;\n\n  // Child nodes are stored in quads. Each quad is presented by number:\n  // 0 | 1\n  // -----\n  // 2 | 3\n${assignQuads("  this.")}\n\n  // Total mass of current node\n  this.mass = 0;\n\n  // Center of mass coordinates\n  ${pattern("this.mass_{var} = 0;",{indent:2})}\n\n  // bounding box coordinates\n  ${pattern("this.min_{var} = 0;",{indent:2})}\n  ${pattern("this.max_{var} = 0;",{indent:2})}\n}\n\n\nfunction createQuadTree(options, random) {\n  options = options || {};\n  options.gravity = typeof options.gravity === 'number' ? options.gravity : -1;\n  options.theta = typeof options.theta === 'number' ? options.theta : 0.8;\n\n  var gravity = options.gravity;\n  var updateQueue = [];\n  var insertStack = new InsertStack();\n  var theta = options.theta;\n\n  var nodesCache = [];\n  var currentInCache = 0;\n  var root = newNode();\n\n  return {\n    insertBodies: insertBodies,\n\n    /**\n     * Gets root node if it is present\n     */\n    getRoot: function() {\n      return root;\n    },\n\n    updateBodyForce: update,\n\n    options: function(newOptions) {\n      if (newOptions) {\n        if (typeof newOptions.gravity === 'number') {\n          gravity = newOptions.gravity;\n        }\n        if (typeof newOptions.theta === 'number') {\n          theta = newOptions.theta;\n        }\n\n        return this;\n      }\n\n      return {\n        gravity: gravity,\n        theta: theta\n      };\n    }\n  };\n\n  function newNode() {\n    // To avoid pressure on GC we reuse nodes.\n    var node = nodesCache[currentInCache];\n    if (node) {\n${assignQuads("      node.")}\n      node.body = null;\n      node.mass = ${pattern("node.mass_{var} = ",{join:""})}0;\n      ${pattern("node.min_{var} = node.max_{var} = ",{join:""})}0;\n    } else {\n      node = new QuadNode();\n      nodesCache[currentInCache] = node;\n    }\n\n    ++currentInCache;\n    return node;\n  }\n\n  function update(sourceBody) {\n    var queue = updateQueue;\n    var v;\n    ${pattern("var d{var};",{indent:4})}\n    var r; \n    ${pattern("var f{var} = 0;",{indent:4})}\n    var queueLength = 1;\n    var shiftIdx = 0;\n    var pushIdx = 1;\n\n    queue[0] = root;\n\n    while (queueLength) {\n      var node = queue[shiftIdx];\n      var body = node.body;\n\n      queueLength -= 1;\n      shiftIdx += 1;\n      var differentBody = (body !== sourceBody);\n      if (body && differentBody) {\n        // If the current node is a leaf node (and it is not source body),\n        // calculate the force exerted by the current node on body, and add this\n        // amount to body's net force.\n        ${pattern("d{var} = body.pos.{var} - sourceBody.pos.{var};",{indent:8})}\n        r = Math.sqrt(${pattern("d{var} * d{var}",{join:" + "})});\n\n        if (r === 0) {\n          // Poor man's protection against zero distance.\n          ${pattern("d{var} = (random.nextDouble() - 0.5) / 50;",{indent:10})}\n          r = Math.sqrt(${pattern("d{var} * d{var}",{join:" + "})});\n        }\n\n        // This is standard gravitation force calculation but we divide\n        // by r^3 to save two operations when normalizing force vector.\n        v = gravity * body.mass * sourceBody.mass / (r * r * r);\n        ${pattern("f{var} += v * d{var};",{indent:8})}\n      } else if (differentBody) {\n        // Otherwise, calculate the ratio s / r,  where s is the width of the region\n        // represented by the internal node, and r is the distance between the body\n        // and the node's center-of-mass\n        ${pattern("d{var} = node.mass_{var} / node.mass - sourceBody.pos.{var};",{indent:8})}\n        r = Math.sqrt(${pattern("d{var} * d{var}",{join:" + "})});\n\n        if (r === 0) {\n          // Sorry about code duplication. I don't want to create many functions\n          // right away. Just want to see performance first.\n          ${pattern("d{var} = (random.nextDouble() - 0.5) / 50;",{indent:10})}\n          r = Math.sqrt(${pattern("d{var} * d{var}",{join:" + "})});\n        }\n        // If s / r < θ, treat this internal node as a single body, and calculate the\n        // force it exerts on sourceBody, and add this amount to sourceBody's net force.\n        if ((node.max_${getVariableName(0)} - node.min_${getVariableName(0)}) / r < theta) {\n          // in the if statement above we consider node's width only\n          // because the region was made into square during tree creation.\n          // Thus there is no difference between using width or height.\n          v = gravity * node.mass * sourceBody.mass / (r * r * r);\n          ${pattern("f{var} += v * d{var};",{indent:10})}\n        } else {\n          // Otherwise, run the procedure recursively on each of the current node's children.\n\n          // I intentionally unfolded this loop, to save several CPU cycles.\n${function(){let indent=Array(11).join(" "),code=[];for(let i=0;i<quadCount;++i)code.push(indent+`if (node.quad${i}) {`),code.push(indent+`  queue[pushIdx] = node.quad${i};`),code.push(indent+"  queueLength += 1;"),code.push(indent+"  pushIdx += 1;"),code.push(indent+"}");return code.join("\n")}()}\n        }\n      }\n    }\n\n    ${pattern("sourceBody.force.{var} += f{var};",{indent:4})}\n  }\n\n  function insertBodies(bodies) {\n    ${pattern("var {var}min = Number.MAX_VALUE;",{indent:4})}\n    ${pattern("var {var}max = Number.MIN_VALUE;",{indent:4})}\n    var i = bodies.length;\n\n    // To reduce quad tree depth we are looking for exact bounding box of all particles.\n    while (i--) {\n      var pos = bodies[i].pos;\n      ${pattern("if (pos.{var} < {var}min) {var}min = pos.{var};",{indent:6})}\n      ${pattern("if (pos.{var} > {var}max) {var}max = pos.{var};",{indent:6})}\n    }\n\n    // Makes the bounds square.\n    var maxSideLength = -Infinity;\n    ${pattern("if ({var}max - {var}min > maxSideLength) maxSideLength = {var}max - {var}min ;",{indent:4})}\n\n    currentInCache = 0;\n    root = newNode();\n    ${pattern("root.min_{var} = {var}min;",{indent:4})}\n    ${pattern("root.max_{var} = {var}min + maxSideLength;",{indent:4})}\n\n    i = bodies.length - 1;\n    if (i >= 0) {\n      root.body = bodies[i];\n    }\n    while (i--) {\n      insert(bodies[i], root);\n    }\n  }\n\n  function insert(newBody) {\n    insertStack.reset();\n    insertStack.push(root, newBody);\n\n    while (!insertStack.isEmpty()) {\n      var stackItem = insertStack.pop();\n      var node = stackItem.node;\n      var body = stackItem.body;\n\n      if (!node.body) {\n        // This is internal node. Update the total mass of the node and center-of-mass.\n        ${pattern("var {var} = body.pos.{var};",{indent:8})}\n        node.mass += body.mass;\n        ${pattern("node.mass_{var} += body.mass * {var};",{indent:8})}\n\n        // Recursively insert the body in the appropriate quadrant.\n        // But first find the appropriate quadrant.\n        var quadIdx = 0; // Assume we are in the 0's quad.\n        ${pattern("var min_{var} = node.min_{var};",{indent:8})}\n        ${pattern("var max_{var} = (min_{var} + node.max_{var}) / 2;",{indent:8})}\n\n${function(indentCount){let code=[],indent=Array(indentCount+1).join(" ");for(let i=0;i<dimension;++i)code.push(indent+`if (${getVariableName(i)} > max_${getVariableName(i)}) {`),code.push(indent+`  quadIdx = quadIdx + ${Math.pow(2,i)};`),code.push(indent+`  min_${getVariableName(i)} = max_${getVariableName(i)};`),code.push(indent+`  max_${getVariableName(i)} = node.max_${getVariableName(i)};`),code.push(indent+"}");return code.join("\n")}(8)}\n\n        var child = getChild(node, quadIdx);\n\n        if (!child) {\n          // The node is internal but this quadrant is not taken. Add\n          // subnode to it.\n          child = newNode();\n          ${pattern("child.min_{var} = min_{var};",{indent:10})}\n          ${pattern("child.max_{var} = max_{var};",{indent:10})}\n          child.body = body;\n\n          setChild(node, quadIdx, child);\n        } else {\n          // continue searching in this quadrant.\n          insertStack.push(child, body);\n        }\n      } else {\n        // We are trying to add to the leaf node.\n        // We have to convert current leaf into internal node\n        // and continue adding two nodes.\n        var oldBody = node.body;\n        node.body = null; // internal nodes do not cary bodies\n\n        if (isSamePosition(oldBody.pos, body.pos)) {\n          // Prevent infinite subdivision by bumping one node\n          // anywhere in this quadrant\n          var retriesCount = 3;\n          do {\n            var offset = random.nextDouble();\n            ${pattern("var d{var} = (node.max_{var} - node.min_{var}) * offset;",{indent:12})}\n\n            ${pattern("oldBody.pos.{var} = node.min_{var} + d{var};",{indent:12})}\n            retriesCount -= 1;\n            // Make sure we don't bump it out of the box. If we do, next iteration should fix it\n          } while (retriesCount > 0 && isSamePosition(oldBody.pos, body.pos));\n\n          if (retriesCount === 0 && isSamePosition(oldBody.pos, body.pos)) {\n            // This is very bad, we ran out of precision.\n            // if we do not return from the method we'll get into\n            // infinite loop here. So we sacrifice correctness of layout, and keep the app running\n            // Next layout iteration should get larger bounding box in the first step and fix this\n            return;\n          }\n        }\n        // Next iteration should subdivide node further.\n        insertStack.push(node, oldBody);\n        insertStack.push(node, body);\n      }\n    }\n  }\n}\n\nfunction getChild(node, idx) {\n${function(){let code=[];for(let i=0;i<quadCount;++i)code.push(`  if (idx === ${i}) return node.quad${i};`);return code.join("\n")}()}\n  return null;\n}\n\nfunction setChild(node, idx, child) {\n${function(){let code=[];for(let i=0;i<quadCount;++i){let prefix=0===i?"  ":"  else ";code.push(`${prefix}if (idx === ${i}) node.quad${i} = child;`)}return code.join("\n")}()}\n}\n\nfunction isSamePosition(point1, point2) {\n  ${pattern("var d{var} = Math.abs(point1.{var} - point2.{var});",{indent:2})}\n\n  return ${pattern("d{var} < 1e-8",{join:" && "})};\n}\n\nreturn createQuadTree;\n\n`;function assignQuads(indent){let quads=[];for(let i=0;i<quadCount;++i)quads.push(`${indent}quad${i} = null;`);return quads.join("\n")}}module.exports=function(dimension){let code=generateQuadTreeFunctionBody(dimension);return new Function(code)()},module.exports.generateQuadTreeFunctionBody=generateQuadTreeFunctionBody},{"./createPatternBuilder":2,"./getVariableName":9}],9:[function(require,module,exports){module.exports=function(index){return 0===index?"x":1===index?"y":2===index?"z":"c"+(index+1)}},{}],10:[function(require,module,exports){module.exports=function(settings){var Spring=require("./spring"),merge=require("ngraph.merge"),eventify=require("ngraph.events");if(settings){if(void 0!==settings.springCoeff)throw new Error("springCoeff was renamed to springCoefficient");if(void 0!==settings.dragCoeff)throw new Error("dragCoeff was renamed to dragCoefficient")}settings=merge(settings,{springLength:10,springCoefficient:.8,gravity:-12,theta:.8,dragCoefficient:.9,timeStep:.5,adaptiveTimeStepWeight:0,dimensions:2,debug:!1});var factory=dimensionalCache[settings.dimensions];if(!factory){var dimensions=settings.dimensions;factory={Body:generateCreateBodyFunction(dimensions,settings.debug),createQuadTree:generateQuadTreeFunction(dimensions),createBounds:generateBoundsFunction(dimensions),createDragForce:generateCreateDragForceFunction(dimensions),createSpringForce:generateCreateSpringForceFunction(dimensions),integrate:generateIntegratorFunction(dimensions)},dimensionalCache[dimensions]=factory}var Body=factory.Body,createQuadTree=factory.createQuadTree,createBounds=factory.createBounds,createDragForce=factory.createDragForce,createSpringForce=factory.createSpringForce,integrate=factory.integrate,random=require("ngraph.random").random(42),bodies=[],springs=[],quadTree=createQuadTree(settings,random),bounds=createBounds(bodies,settings,random),springForce=createSpringForce(settings,random),dragForce=createDragForce(settings),forces=[],forceMap=new Map,iterationNumber=0;addForce("nbody",(function(iterationUmber){if(0===bodies.length)return;quadTree.insertBodies(bodies);var i=bodies.length;for(;i--;){var body=bodies[i];body.isPinned||(body.reset(),quadTree.updateBodyForce(body),dragForce.update(body))}})),addForce("spring",(function(){var i=springs.length;for(;i--;)springForce.update(springs[i])}));var publicApi={bodies:bodies,quadTree:quadTree,springs:springs,settings:settings,addForce:addForce,removeForce:function(forceName){var forceIndex=forces.indexOf(forceMap.get(forceName));if(forceIndex<0)return;forces.splice(forceIndex,1)},getForces:function(){return forceMap},step:function(){for(var i=0;i<forces.length;++i)forces[i](iterationNumber);var movement=integrate(bodies,settings.timeStep,settings.adaptiveTimeStepWeight);return iterationNumber+=1,movement},addBody:function(body){if(!body)throw new Error("Body is required");return bodies.push(body),body},addBodyAt:function(pos){if(!pos)throw new Error("Body position is required");var body=(pos=>new Body(pos))(pos);return bodies.push(body),body},removeBody:function(body){if(body){var idx=bodies.indexOf(body);if(!(idx<0))return bodies.splice(idx,1),0===bodies.length&&bounds.reset(),!0}},addSpring:function(body1,body2,springLength,springCoefficient){if(!body1||!body2)throw new Error("Cannot add null spring to force simulator");"number"!=typeof springLength&&(springLength=-1);var spring=new Spring(body1,body2,springLength,springCoefficient>=0?springCoefficient:-1);return springs.push(spring),spring},getTotalMovement:function(){return 0},removeSpring:function(spring){if(spring){var idx=springs.indexOf(spring);return idx>-1?(springs.splice(idx,1),!0):void 0}},getBestNewBodyPosition:function(neighbors){return bounds.getBestNewPosition(neighbors)},getBBox:getBoundingBox,getBoundingBox:getBoundingBox,invalidateBBox:function(){console.warn("invalidateBBox() is deprecated, bounds always recomputed on `getBBox()` call")},gravity:function(value){return void 0!==value?(settings.gravity=value,quadTree.options({gravity:value}),this):settings.gravity},theta:function(value){return void 0!==value?(settings.theta=value,quadTree.options({theta:value}),this):settings.theta}};return function(settings,target){for(var key in settings)augment(settings,target,key)}(settings,publicApi),eventify(publicApi),publicApi;function getBoundingBox(){return bounds.update(),bounds.box}function addForce(forceName,forceFunction){if(forceMap.has(forceName))throw new Error("Force "+forceName+" is already added");forceMap.set(forceName,forceFunction),forces.push(forceFunction)}function augment(source,target,key){if(source.hasOwnProperty(key)&&"function"!=typeof target[key]){var sourceIsNumber=Number.isFinite(source[key]);target[key]=sourceIsNumber?function(value){if(void 0!==value){if(!Number.isFinite(value))throw new Error("Value of "+key+" should be a valid number.");return source[key]=value,target}return source[key]}:function(value){return void 0!==value?(source[key]=value,target):source[key]}}}};var generateCreateBodyFunction=require("./codeGenerators/generateCreateBody"),generateQuadTreeFunction=require("./codeGenerators/generateQuadTree"),generateBoundsFunction=require("./codeGenerators/generateBounds"),generateCreateDragForceFunction=require("./codeGenerators/generateCreateDragForce"),generateCreateSpringForceFunction=require("./codeGenerators/generateCreateSpringForce"),generateIntegratorFunction=require("./codeGenerators/generateIntegrator"),dimensionalCache={}},{"./codeGenerators/generateBounds":3,"./codeGenerators/generateCreateBody":4,"./codeGenerators/generateCreateDragForce":5,"./codeGenerators/generateCreateSpringForce":6,"./codeGenerators/generateIntegrator":7,"./codeGenerators/generateQuadTree":8,"./spring":11,"ngraph.events":12,"ngraph.merge":13,"ngraph.random":14}],11:[function(require,module,exports){module.exports=function(fromBody,toBody,length,coeff){this.from=fromBody,this.to=toBody,this.length=length,this.coeff=coeff}},{}],12:[function(require,module,exports){module.exports=function(subject){!function(subject){if(!subject)throw new Error("Eventify cannot use falsy object as events subject");for(var reservedWords=["on","fire","off"],i=0;i<reservedWords.length;++i)if(subject.hasOwnProperty(reservedWords[i]))throw new Error("Subject cannot be eventified, since it already has property '"+reservedWords[i]+"'")}(subject);var eventsStorage=function(subject){var registeredEvents=Object.create(null);return{on:function(eventName,callback,ctx){if("function"!=typeof callback)throw new Error("callback is expected to be a function");var handlers=registeredEvents[eventName];return handlers||(handlers=registeredEvents[eventName]=[]),handlers.push({callback:callback,ctx:ctx}),subject},off:function(eventName,callback){if(void 0===eventName)return registeredEvents=Object.create(null),subject;if(registeredEvents[eventName])if("function"!=typeof callback)delete registeredEvents[eventName];else for(var callbacks=registeredEvents[eventName],i=0;i<callbacks.length;++i)callbacks[i].callback===callback&&callbacks.splice(i,1);return subject},fire:function(eventName){var fireArguments,callbacks=registeredEvents[eventName];if(!callbacks)return subject;arguments.length>1&&(fireArguments=Array.prototype.splice.call(arguments,1));for(var i=0;i<callbacks.length;++i){var callbackInfo=callbacks[i];callbackInfo.callback.apply(callbackInfo.ctx,fireArguments)}return subject}}}(subject);return subject.on=eventsStorage.on,subject.off=eventsStorage.off,subject.fire=eventsStorage.fire,subject}},{}],13:[function(require,module,exports){module.exports=function merge(target,options){var key;target||(target={});if(options)for(key in options)if(options.hasOwnProperty(key)){var targetHasIt=target.hasOwnProperty(key),optionsValueType=typeof options[key];!targetHasIt||typeof target[key]!==optionsValueType?target[key]=options[key]:"object"===optionsValueType&&(target[key]=merge(target[key],options[key]))}return target}},{}],14:[function(require,module,exports){function random(inputSeed){return new Generator("number"==typeof inputSeed?inputSeed:+new Date)}function Generator(seed){this.seed=seed}function nextDouble(){var seed=this.seed;return seed=4294967295&(3042594569^(seed=(seed=4294967295&((seed=(seed=4294967295&(3345072700^(seed=seed+2127912214+(seed<<12)&4294967295)^seed>>>19))+374761393+(seed<<5)&4294967295)+3550635116^seed<<9))+4251993797+(seed<<3)&4294967295)^seed>>>16),this.seed=seed,(268435455&seed)/268435456}module.exports=random,module.exports.random=random,module.exports.randomIterator=function(array,customRandom){var localRandom=customRandom||random();if("function"!=typeof localRandom.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(callback){var i,j,t;for(i=array.length-1;i>0;--i)j=localRandom.next(i+1),t=array[j],array[j]=array[i],array[i]=t,callback(t);array.length&&callback(array[0])},shuffle:function(){var i,j,t;for(i=array.length-1;i>0;--i)j=localRandom.next(i+1),t=array[j],array[j]=array[i],array[i]=t;return array}}},Generator.prototype.next=function(maxValue){return Math.floor(this.nextDouble()*maxValue)},Generator.prototype.nextDouble=nextDouble,Generator.prototype.uniform=nextDouble,Generator.prototype.gaussian=function(){var r,x,y;do{x=2*this.nextDouble()-1,y=2*this.nextDouble()-1,r=x*x+y*y}while(r>=1||0===r);return x*Math.sqrt(-2*Math.log(r)/r)}},{}]},{},[1])(1)}));