'use strict';

var coseBase$1 = require('../../../../../_virtual/cose-base2.js');
var layoutBase = require('../../../layout-base@1.0.2/node_modules/layout-base/layout-base.js');

var coseBase = coseBase$1.__module.exports;

var hasRequiredCoseBase;

function requireCoseBase () {
	if (hasRequiredCoseBase) return coseBase$1.__module.exports;
	hasRequiredCoseBase = 1;
	(function (module, exports) {
		(function webpackUniversalModuleDefinition(root, factory) {
			module.exports = factory(layoutBase.__require());
		})(coseBase, function(__WEBPACK_EXTERNAL_MODULE_0__) {
		return /******/ (function(modules) { // webpackBootstrap
		/******/ 	// The module cache
		/******/ 	var installedModules = {};
		/******/
		/******/ 	// The require function
		/******/ 	function __webpack_require__(moduleId) {
		/******/
		/******/ 		// Check if module is in cache
		/******/ 		if(installedModules[moduleId]) {
		/******/ 			return installedModules[moduleId].exports;
		/******/ 		}
		/******/ 		// Create a new module (and put it into the cache)
		/******/ 		var module = installedModules[moduleId] = {
		/******/ 			i: moduleId,
		/******/ 			l: false,
		/******/ 			exports: {}
		/******/ 		};
		/******/
		/******/ 		// Execute the module function
		/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
		/******/
		/******/ 		// Flag the module as loaded
		/******/ 		module.l = true;
		/******/
		/******/ 		// Return the exports of the module
		/******/ 		return module.exports;
		/******/ 	}
		/******/
		/******/
		/******/ 	// expose the modules object (__webpack_modules__)
		/******/ 	__webpack_require__.m = modules;
		/******/
		/******/ 	// expose the module cache
		/******/ 	__webpack_require__.c = installedModules;
		/******/
		/******/ 	// identity function for calling harmony imports with the correct context
		/******/ 	__webpack_require__.i = function(value) { return value; };
		/******/
		/******/ 	// define getter function for harmony exports
		/******/ 	__webpack_require__.d = function(exports, name, getter) {
		/******/ 		if(!__webpack_require__.o(exports, name)) {
		/******/ 			Object.defineProperty(exports, name, {
		/******/ 				configurable: false,
		/******/ 				enumerable: true,
		/******/ 				get: getter
		/******/ 			});
		/******/ 		}
		/******/ 	};
		/******/
		/******/ 	// getDefaultExport function for compatibility with non-harmony modules
		/******/ 	__webpack_require__.n = function(module) {
		/******/ 		var getter = module && module.__esModule ?
		/******/ 			function getDefault() { return module['default']; } :
		/******/ 			function getModuleExports() { return module; };
		/******/ 		__webpack_require__.d(getter, 'a', getter);
		/******/ 		return getter;
		/******/ 	};
		/******/
		/******/ 	// Object.prototype.hasOwnProperty.call
		/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
		/******/
		/******/ 	// __webpack_public_path__
		/******/ 	__webpack_require__.p = "";
		/******/
		/******/ 	// Load entry module and return exports
		/******/ 	return __webpack_require__(__webpack_require__.s = 7);
		/******/ })
		/************************************************************************/
		/******/ ([
		/* 0 */
		/***/ (function(module, exports) {

		module.exports = __WEBPACK_EXTERNAL_MODULE_0__;

		/***/ }),
		/* 1 */
		/***/ (function(module, exports, __webpack_require__) {


		var FDLayoutConstants = __webpack_require__(0).FDLayoutConstants;

		function CoSEConstants() {}

		//CoSEConstants inherits static props in FDLayoutConstants
		for (var prop in FDLayoutConstants) {
		  CoSEConstants[prop] = FDLayoutConstants[prop];
		}

		CoSEConstants.DEFAULT_USE_MULTI_LEVEL_SCALING = false;
		CoSEConstants.DEFAULT_RADIAL_SEPARATION = FDLayoutConstants.DEFAULT_EDGE_LENGTH;
		CoSEConstants.DEFAULT_COMPONENT_SEPERATION = 60;
		CoSEConstants.TILE = true;
		CoSEConstants.TILING_PADDING_VERTICAL = 10;
		CoSEConstants.TILING_PADDING_HORIZONTAL = 10;
		CoSEConstants.TREE_REDUCTION_ON_INCREMENTAL = false; // make this true when cose is used incrementally as a part of other non-incremental layout

		module.exports = CoSEConstants;

		/***/ }),
		/* 2 */
		/***/ (function(module, exports, __webpack_require__) {


		var FDLayoutEdge = __webpack_require__(0).FDLayoutEdge;

		function CoSEEdge(source, target, vEdge) {
		  FDLayoutEdge.call(this, source, target, vEdge);
		}

		CoSEEdge.prototype = Object.create(FDLayoutEdge.prototype);
		for (var prop in FDLayoutEdge) {
		  CoSEEdge[prop] = FDLayoutEdge[prop];
		}

		module.exports = CoSEEdge;

		/***/ }),
		/* 3 */
		/***/ (function(module, exports, __webpack_require__) {


		var LGraph = __webpack_require__(0).LGraph;

		function CoSEGraph(parent, graphMgr, vGraph) {
		  LGraph.call(this, parent, graphMgr, vGraph);
		}

		CoSEGraph.prototype = Object.create(LGraph.prototype);
		for (var prop in LGraph) {
		  CoSEGraph[prop] = LGraph[prop];
		}

		module.exports = CoSEGraph;

		/***/ }),
		/* 4 */
		/***/ (function(module, exports, __webpack_require__) {


		var LGraphManager = __webpack_require__(0).LGraphManager;

		function CoSEGraphManager(layout) {
		  LGraphManager.call(this, layout);
		}

		CoSEGraphManager.prototype = Object.create(LGraphManager.prototype);
		for (var prop in LGraphManager) {
		  CoSEGraphManager[prop] = LGraphManager[prop];
		}

		module.exports = CoSEGraphManager;

		/***/ }),
		/* 5 */
		/***/ (function(module, exports, __webpack_require__) {


		var FDLayoutNode = __webpack_require__(0).FDLayoutNode;
		var IMath = __webpack_require__(0).IMath;

		function CoSENode(gm, loc, size, vNode) {
		  FDLayoutNode.call(this, gm, loc, size, vNode);
		}

		CoSENode.prototype = Object.create(FDLayoutNode.prototype);
		for (var prop in FDLayoutNode) {
		  CoSENode[prop] = FDLayoutNode[prop];
		}

		CoSENode.prototype.move = function () {
		  var layout = this.graphManager.getLayout();
		  this.displacementX = layout.coolingFactor * (this.springForceX + this.repulsionForceX + this.gravitationForceX) / this.noOfChildren;
		  this.displacementY = layout.coolingFactor * (this.springForceY + this.repulsionForceY + this.gravitationForceY) / this.noOfChildren;

		  if (Math.abs(this.displacementX) > layout.coolingFactor * layout.maxNodeDisplacement) {
		    this.displacementX = layout.coolingFactor * layout.maxNodeDisplacement * IMath.sign(this.displacementX);
		  }

		  if (Math.abs(this.displacementY) > layout.coolingFactor * layout.maxNodeDisplacement) {
		    this.displacementY = layout.coolingFactor * layout.maxNodeDisplacement * IMath.sign(this.displacementY);
		  }

		  // a simple node, just move it
		  if (this.child == null) {
		    this.moveBy(this.displacementX, this.displacementY);
		  }
		  // an empty compound node, again just move it
		  else if (this.child.getNodes().length == 0) {
		      this.moveBy(this.displacementX, this.displacementY);
		    }
		    // non-empty compound node, propogate movement to children as well
		    else {
		        this.propogateDisplacementToChildren(this.displacementX, this.displacementY);
		      }

		  layout.totalDisplacement += Math.abs(this.displacementX) + Math.abs(this.displacementY);

		  this.springForceX = 0;
		  this.springForceY = 0;
		  this.repulsionForceX = 0;
		  this.repulsionForceY = 0;
		  this.gravitationForceX = 0;
		  this.gravitationForceY = 0;
		  this.displacementX = 0;
		  this.displacementY = 0;
		};

		CoSENode.prototype.propogateDisplacementToChildren = function (dX, dY) {
		  var nodes = this.getChild().getNodes();
		  var node;
		  for (var i = 0; i < nodes.length; i++) {
		    node = nodes[i];
		    if (node.getChild() == null) {
		      node.moveBy(dX, dY);
		      node.displacementX += dX;
		      node.displacementY += dY;
		    } else {
		      node.propogateDisplacementToChildren(dX, dY);
		    }
		  }
		};

		CoSENode.prototype.setPred1 = function (pred1) {
		  this.pred1 = pred1;
		};

		CoSENode.prototype.getPred1 = function () {
		  return pred1;
		};

		CoSENode.prototype.getPred2 = function () {
		  return pred2;
		};

		CoSENode.prototype.setNext = function (next) {
		  this.next = next;
		};

		CoSENode.prototype.getNext = function () {
		  return next;
		};

		CoSENode.prototype.setProcessed = function (processed) {
		  this.processed = processed;
		};

		CoSENode.prototype.isProcessed = function () {
		  return processed;
		};

		module.exports = CoSENode;

		/***/ }),
		/* 6 */
		/***/ (function(module, exports, __webpack_require__) {


		var FDLayout = __webpack_require__(0).FDLayout;
		var CoSEGraphManager = __webpack_require__(4);
		var CoSEGraph = __webpack_require__(3);
		var CoSENode = __webpack_require__(5);
		var CoSEEdge = __webpack_require__(2);
		var CoSEConstants = __webpack_require__(1);
		var FDLayoutConstants = __webpack_require__(0).FDLayoutConstants;
		var LayoutConstants = __webpack_require__(0).LayoutConstants;
		var Point = __webpack_require__(0).Point;
		var PointD = __webpack_require__(0).PointD;
		var Layout = __webpack_require__(0).Layout;
		var Integer = __webpack_require__(0).Integer;
		var IGeometry = __webpack_require__(0).IGeometry;
		var LGraph = __webpack_require__(0).LGraph;
		var Transform = __webpack_require__(0).Transform;

		function CoSELayout() {
		  FDLayout.call(this);

		  this.toBeTiled = {}; // Memorize if a node is to be tiled or is tiled
		}

		CoSELayout.prototype = Object.create(FDLayout.prototype);

		for (var prop in FDLayout) {
		  CoSELayout[prop] = FDLayout[prop];
		}

		CoSELayout.prototype.newGraphManager = function () {
		  var gm = new CoSEGraphManager(this);
		  this.graphManager = gm;
		  return gm;
		};

		CoSELayout.prototype.newGraph = function (vGraph) {
		  return new CoSEGraph(null, this.graphManager, vGraph);
		};

		CoSELayout.prototype.newNode = function (vNode) {
		  return new CoSENode(this.graphManager, vNode);
		};

		CoSELayout.prototype.newEdge = function (vEdge) {
		  return new CoSEEdge(null, null, vEdge);
		};

		CoSELayout.prototype.initParameters = function () {
		  FDLayout.prototype.initParameters.call(this, arguments);
		  if (!this.isSubLayout) {
		    if (CoSEConstants.DEFAULT_EDGE_LENGTH < 10) {
		      this.idealEdgeLength = 10;
		    } else {
		      this.idealEdgeLength = CoSEConstants.DEFAULT_EDGE_LENGTH;
		    }

		    this.useSmartIdealEdgeLengthCalculation = CoSEConstants.DEFAULT_USE_SMART_IDEAL_EDGE_LENGTH_CALCULATION;
		    this.springConstant = FDLayoutConstants.DEFAULT_SPRING_STRENGTH;
		    this.repulsionConstant = FDLayoutConstants.DEFAULT_REPULSION_STRENGTH;
		    this.gravityConstant = FDLayoutConstants.DEFAULT_GRAVITY_STRENGTH;
		    this.compoundGravityConstant = FDLayoutConstants.DEFAULT_COMPOUND_GRAVITY_STRENGTH;
		    this.gravityRangeFactor = FDLayoutConstants.DEFAULT_GRAVITY_RANGE_FACTOR;
		    this.compoundGravityRangeFactor = FDLayoutConstants.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR;

		    // variables for tree reduction support
		    this.prunedNodesAll = [];
		    this.growTreeIterations = 0;
		    this.afterGrowthIterations = 0;
		    this.isTreeGrowing = false;
		    this.isGrowthFinished = false;

		    // variables for cooling
		    this.coolingCycle = 0;
		    this.maxCoolingCycle = this.maxIterations / FDLayoutConstants.CONVERGENCE_CHECK_PERIOD;
		    this.finalTemperature = FDLayoutConstants.CONVERGENCE_CHECK_PERIOD / this.maxIterations;
		    this.coolingAdjuster = 1;
		  }
		};

		CoSELayout.prototype.layout = function () {
		  var createBendsAsNeeded = LayoutConstants.DEFAULT_CREATE_BENDS_AS_NEEDED;
		  if (createBendsAsNeeded) {
		    this.createBendpoints();
		    this.graphManager.resetAllEdges();
		  }

		  this.level = 0;
		  return this.classicLayout();
		};

		CoSELayout.prototype.classicLayout = function () {
		  this.nodesWithGravity = this.calculateNodesToApplyGravitationTo();
		  this.graphManager.setAllNodesToApplyGravitation(this.nodesWithGravity);
		  this.calcNoOfChildrenForAllNodes();
		  this.graphManager.calcLowestCommonAncestors();
		  this.graphManager.calcInclusionTreeDepths();
		  this.graphManager.getRoot().calcEstimatedSize();
		  this.calcIdealEdgeLengths();

		  if (!this.incremental) {
		    var forest = this.getFlatForest();

		    // The graph associated with this layout is flat and a forest
		    if (forest.length > 0) {
		      this.positionNodesRadially(forest);
		    }
		    // The graph associated with this layout is not flat or a forest
		    else {
		        // Reduce the trees when incremental mode is not enabled and graph is not a forest 
		        this.reduceTrees();
		        // Update nodes that gravity will be applied
		        this.graphManager.resetAllNodesToApplyGravitation();
		        var allNodes = new Set(this.getAllNodes());
		        var intersection = this.nodesWithGravity.filter(function (x) {
		          return allNodes.has(x);
		        });
		        this.graphManager.setAllNodesToApplyGravitation(intersection);

		        this.positionNodesRandomly();
		      }
		  } else {
		    if (CoSEConstants.TREE_REDUCTION_ON_INCREMENTAL) {
		      // Reduce the trees in incremental mode if only this constant is set to true 
		      this.reduceTrees();
		      // Update nodes that gravity will be applied
		      this.graphManager.resetAllNodesToApplyGravitation();
		      var allNodes = new Set(this.getAllNodes());
		      var intersection = this.nodesWithGravity.filter(function (x) {
		        return allNodes.has(x);
		      });
		      this.graphManager.setAllNodesToApplyGravitation(intersection);
		    }
		  }

		  this.initSpringEmbedder();
		  this.runSpringEmbedder();

		  return true;
		};

		CoSELayout.prototype.tick = function () {
		  this.totalIterations++;

		  if (this.totalIterations === this.maxIterations && !this.isTreeGrowing && !this.isGrowthFinished) {
		    if (this.prunedNodesAll.length > 0) {
		      this.isTreeGrowing = true;
		    } else {
		      return true;
		    }
		  }

		  if (this.totalIterations % FDLayoutConstants.CONVERGENCE_CHECK_PERIOD == 0 && !this.isTreeGrowing && !this.isGrowthFinished) {
		    if (this.isConverged()) {
		      if (this.prunedNodesAll.length > 0) {
		        this.isTreeGrowing = true;
		      } else {
		        return true;
		      }
		    }

		    this.coolingCycle++;

		    if (this.layoutQuality == 0) {
		      // quality - "draft"
		      this.coolingAdjuster = this.coolingCycle;
		    } else if (this.layoutQuality == 1) {
		      // quality - "default"
		      this.coolingAdjuster = this.coolingCycle / 3;
		    }

		    // cooling schedule is based on http://www.btluke.com/simanf1.html -> cooling schedule 3
		    this.coolingFactor = Math.max(this.initialCoolingFactor - Math.pow(this.coolingCycle, Math.log(100 * (this.initialCoolingFactor - this.finalTemperature)) / Math.log(this.maxCoolingCycle)) / 100 * this.coolingAdjuster, this.finalTemperature);
		    this.animationPeriod = Math.ceil(this.initialAnimationPeriod * Math.sqrt(this.coolingFactor));
		  }
		  // Operations while tree is growing again 
		  if (this.isTreeGrowing) {
		    if (this.growTreeIterations % 10 == 0) {
		      if (this.prunedNodesAll.length > 0) {
		        this.graphManager.updateBounds();
		        this.updateGrid();
		        this.growTree(this.prunedNodesAll);
		        // Update nodes that gravity will be applied
		        this.graphManager.resetAllNodesToApplyGravitation();
		        var allNodes = new Set(this.getAllNodes());
		        var intersection = this.nodesWithGravity.filter(function (x) {
		          return allNodes.has(x);
		        });
		        this.graphManager.setAllNodesToApplyGravitation(intersection);

		        this.graphManager.updateBounds();
		        this.updateGrid();
		        this.coolingFactor = FDLayoutConstants.DEFAULT_COOLING_FACTOR_INCREMENTAL;
		      } else {
		        this.isTreeGrowing = false;
		        this.isGrowthFinished = true;
		      }
		    }
		    this.growTreeIterations++;
		  }
		  // Operations after growth is finished
		  if (this.isGrowthFinished) {
		    if (this.isConverged()) {
		      return true;
		    }
		    if (this.afterGrowthIterations % 10 == 0) {
		      this.graphManager.updateBounds();
		      this.updateGrid();
		    }
		    this.coolingFactor = FDLayoutConstants.DEFAULT_COOLING_FACTOR_INCREMENTAL * ((100 - this.afterGrowthIterations) / 100);
		    this.afterGrowthIterations++;
		  }

		  var gridUpdateAllowed = !this.isTreeGrowing && !this.isGrowthFinished;
		  var forceToNodeSurroundingUpdate = this.growTreeIterations % 10 == 1 && this.isTreeGrowing || this.afterGrowthIterations % 10 == 1 && this.isGrowthFinished;

		  this.totalDisplacement = 0;
		  this.graphManager.updateBounds();
		  this.calcSpringForces();
		  this.calcRepulsionForces(gridUpdateAllowed, forceToNodeSurroundingUpdate);
		  this.calcGravitationalForces();
		  this.moveNodes();
		  this.animate();

		  return false; // Layout is not ended yet return false
		};

		CoSELayout.prototype.getPositionsData = function () {
		  var allNodes = this.graphManager.getAllNodes();
		  var pData = {};
		  for (var i = 0; i < allNodes.length; i++) {
		    var rect = allNodes[i].rect;
		    var id = allNodes[i].id;
		    pData[id] = {
		      id: id,
		      x: rect.getCenterX(),
		      y: rect.getCenterY(),
		      w: rect.width,
		      h: rect.height
		    };
		  }

		  return pData;
		};

		CoSELayout.prototype.runSpringEmbedder = function () {
		  this.initialAnimationPeriod = 25;
		  this.animationPeriod = this.initialAnimationPeriod;
		  var layoutEnded = false;

		  // If aminate option is 'during' signal that layout is supposed to start iterating
		  if (FDLayoutConstants.ANIMATE === 'during') {
		    this.emit('layoutstarted');
		  } else {
		    // If aminate option is 'during' tick() function will be called on index.js
		    while (!layoutEnded) {
		      layoutEnded = this.tick();
		    }

		    this.graphManager.updateBounds();
		  }
		};

		CoSELayout.prototype.calculateNodesToApplyGravitationTo = function () {
		  var nodeList = [];
		  var graph;

		  var graphs = this.graphManager.getGraphs();
		  var size = graphs.length;
		  var i;
		  for (i = 0; i < size; i++) {
		    graph = graphs[i];

		    graph.updateConnected();

		    if (!graph.isConnected) {
		      nodeList = nodeList.concat(graph.getNodes());
		    }
		  }

		  return nodeList;
		};

		CoSELayout.prototype.createBendpoints = function () {
		  var edges = [];
		  edges = edges.concat(this.graphManager.getAllEdges());
		  var visited = new Set();
		  var i;
		  for (i = 0; i < edges.length; i++) {
		    var edge = edges[i];

		    if (!visited.has(edge)) {
		      var source = edge.getSource();
		      var target = edge.getTarget();

		      if (source == target) {
		        edge.getBendpoints().push(new PointD());
		        edge.getBendpoints().push(new PointD());
		        this.createDummyNodesForBendpoints(edge);
		        visited.add(edge);
		      } else {
		        var edgeList = [];

		        edgeList = edgeList.concat(source.getEdgeListToNode(target));
		        edgeList = edgeList.concat(target.getEdgeListToNode(source));

		        if (!visited.has(edgeList[0])) {
		          if (edgeList.length > 1) {
		            var k;
		            for (k = 0; k < edgeList.length; k++) {
		              var multiEdge = edgeList[k];
		              multiEdge.getBendpoints().push(new PointD());
		              this.createDummyNodesForBendpoints(multiEdge);
		            }
		          }
		          edgeList.forEach(function (edge) {
		            visited.add(edge);
		          });
		        }
		      }
		    }

		    if (visited.size == edges.length) {
		      break;
		    }
		  }
		};

		CoSELayout.prototype.positionNodesRadially = function (forest) {
		  // We tile the trees to a grid row by row; first tree starts at (0,0)
		  var currentStartingPoint = new Point(0, 0);
		  var numberOfColumns = Math.ceil(Math.sqrt(forest.length));
		  var height = 0;
		  var currentY = 0;
		  var currentX = 0;
		  var point = new PointD(0, 0);

		  for (var i = 0; i < forest.length; i++) {
		    if (i % numberOfColumns == 0) {
		      // Start of a new row, make the x coordinate 0, increment the
		      // y coordinate with the max height of the previous row
		      currentX = 0;
		      currentY = height;

		      if (i != 0) {
		        currentY += CoSEConstants.DEFAULT_COMPONENT_SEPERATION;
		      }

		      height = 0;
		    }

		    var tree = forest[i];

		    // Find the center of the tree
		    var centerNode = Layout.findCenterOfTree(tree);

		    // Set the staring point of the next tree
		    currentStartingPoint.x = currentX;
		    currentStartingPoint.y = currentY;

		    // Do a radial layout starting with the center
		    point = CoSELayout.radialLayout(tree, centerNode, currentStartingPoint);

		    if (point.y > height) {
		      height = Math.floor(point.y);
		    }

		    currentX = Math.floor(point.x + CoSEConstants.DEFAULT_COMPONENT_SEPERATION);
		  }

		  this.transform(new PointD(LayoutConstants.WORLD_CENTER_X - point.x / 2, LayoutConstants.WORLD_CENTER_Y - point.y / 2));
		};

		CoSELayout.radialLayout = function (tree, centerNode, startingPoint) {
		  var radialSep = Math.max(this.maxDiagonalInTree(tree), CoSEConstants.DEFAULT_RADIAL_SEPARATION);
		  CoSELayout.branchRadialLayout(centerNode, null, 0, 359, 0, radialSep);
		  var bounds = LGraph.calculateBounds(tree);

		  var transform = new Transform();
		  transform.setDeviceOrgX(bounds.getMinX());
		  transform.setDeviceOrgY(bounds.getMinY());
		  transform.setWorldOrgX(startingPoint.x);
		  transform.setWorldOrgY(startingPoint.y);

		  for (var i = 0; i < tree.length; i++) {
		    var node = tree[i];
		    node.transform(transform);
		  }

		  var bottomRight = new PointD(bounds.getMaxX(), bounds.getMaxY());

		  return transform.inverseTransformPoint(bottomRight);
		};

		CoSELayout.branchRadialLayout = function (node, parentOfNode, startAngle, endAngle, distance, radialSeparation) {
		  // First, position this node by finding its angle.
		  var halfInterval = (endAngle - startAngle + 1) / 2;

		  if (halfInterval < 0) {
		    halfInterval += 180;
		  }

		  var nodeAngle = (halfInterval + startAngle) % 360;
		  var teta = nodeAngle * IGeometry.TWO_PI / 360;
		  var x_ = distance * Math.cos(teta);
		  var y_ = distance * Math.sin(teta);

		  node.setCenter(x_, y_);

		  // Traverse all neighbors of this node and recursively call this
		  // function.
		  var neighborEdges = [];
		  neighborEdges = neighborEdges.concat(node.getEdges());
		  var childCount = neighborEdges.length;

		  if (parentOfNode != null) {
		    childCount--;
		  }

		  var branchCount = 0;

		  var incEdgesCount = neighborEdges.length;
		  var startIndex;

		  var edges = node.getEdgesBetween(parentOfNode);

		  // If there are multiple edges, prune them until there remains only one
		  // edge.
		  while (edges.length > 1) {
		    //neighborEdges.remove(edges.remove(0));
		    var temp = edges[0];
		    edges.splice(0, 1);
		    var index = neighborEdges.indexOf(temp);
		    if (index >= 0) {
		      neighborEdges.splice(index, 1);
		    }
		    incEdgesCount--;
		    childCount--;
		  }

		  if (parentOfNode != null) {
		    //assert edges.length == 1;
		    startIndex = (neighborEdges.indexOf(edges[0]) + 1) % incEdgesCount;
		  } else {
		    startIndex = 0;
		  }

		  var stepAngle = Math.abs(endAngle - startAngle) / childCount;

		  for (var i = startIndex; branchCount != childCount; i = ++i % incEdgesCount) {
		    var currentNeighbor = neighborEdges[i].getOtherEnd(node);

		    // Don't back traverse to root node in current tree.
		    if (currentNeighbor == parentOfNode) {
		      continue;
		    }

		    var childStartAngle = (startAngle + branchCount * stepAngle) % 360;
		    var childEndAngle = (childStartAngle + stepAngle) % 360;

		    CoSELayout.branchRadialLayout(currentNeighbor, node, childStartAngle, childEndAngle, distance + radialSeparation, radialSeparation);

		    branchCount++;
		  }
		};

		CoSELayout.maxDiagonalInTree = function (tree) {
		  var maxDiagonal = Integer.MIN_VALUE;

		  for (var i = 0; i < tree.length; i++) {
		    var node = tree[i];
		    var diagonal = node.getDiagonal();

		    if (diagonal > maxDiagonal) {
		      maxDiagonal = diagonal;
		    }
		  }

		  return maxDiagonal;
		};

		CoSELayout.prototype.calcRepulsionRange = function () {
		  // formula is 2 x (level + 1) x idealEdgeLength
		  return 2 * (this.level + 1) * this.idealEdgeLength;
		};

		// Tiling methods

		// Group zero degree members whose parents are not to be tiled, create dummy parents where needed and fill memberGroups by their dummp parent id's
		CoSELayout.prototype.groupZeroDegreeMembers = function () {
		  var self = this;
		  // array of [parent_id x oneDegreeNode_id]
		  var tempMemberGroups = {}; // A temporary map of parent node and its zero degree members
		  this.memberGroups = {}; // A map of dummy parent node and its zero degree members whose parents are not to be tiled
		  this.idToDummyNode = {}; // A map of id to dummy node 

		  var zeroDegree = []; // List of zero degree nodes whose parents are not to be tiled
		  var allNodes = this.graphManager.getAllNodes();

		  // Fill zero degree list
		  for (var i = 0; i < allNodes.length; i++) {
		    var node = allNodes[i];
		    var parent = node.getParent();
		    // If a node has zero degree and its parent is not to be tiled if exists add that node to zeroDegres list
		    if (this.getNodeDegreeWithChildren(node) === 0 && (parent.id == undefined || !this.getToBeTiled(parent))) {
		      zeroDegree.push(node);
		    }
		  }

		  // Create a map of parent node and its zero degree members
		  for (var i = 0; i < zeroDegree.length; i++) {
		    var node = zeroDegree[i]; // Zero degree node itself
		    var p_id = node.getParent().id; // Parent id

		    if (typeof tempMemberGroups[p_id] === "undefined") tempMemberGroups[p_id] = [];

		    tempMemberGroups[p_id] = tempMemberGroups[p_id].concat(node); // Push node to the list belongs to its parent in tempMemberGroups
		  }

		  // If there are at least two nodes at a level, create a dummy compound for them
		  Object.keys(tempMemberGroups).forEach(function (p_id) {
		    if (tempMemberGroups[p_id].length > 1) {
		      var dummyCompoundId = "DummyCompound_" + p_id; // The id of dummy compound which will be created soon
		      self.memberGroups[dummyCompoundId] = tempMemberGroups[p_id]; // Add dummy compound to memberGroups

		      var parent = tempMemberGroups[p_id][0].getParent(); // The parent of zero degree nodes will be the parent of new dummy compound

		      // Create a dummy compound with calculated id
		      var dummyCompound = new CoSENode(self.graphManager);
		      dummyCompound.id = dummyCompoundId;
		      dummyCompound.paddingLeft = parent.paddingLeft || 0;
		      dummyCompound.paddingRight = parent.paddingRight || 0;
		      dummyCompound.paddingBottom = parent.paddingBottom || 0;
		      dummyCompound.paddingTop = parent.paddingTop || 0;

		      self.idToDummyNode[dummyCompoundId] = dummyCompound;

		      var dummyParentGraph = self.getGraphManager().add(self.newGraph(), dummyCompound);
		      var parentGraph = parent.getChild();

		      // Add dummy compound to parent the graph
		      parentGraph.add(dummyCompound);

		      // For each zero degree node in this level remove it from its parent graph and add it to the graph of dummy parent
		      for (var i = 0; i < tempMemberGroups[p_id].length; i++) {
		        var node = tempMemberGroups[p_id][i];

		        parentGraph.remove(node);
		        dummyParentGraph.add(node);
		      }
		    }
		  });
		};

		CoSELayout.prototype.clearCompounds = function () {
		  var childGraphMap = {};
		  var idToNode = {};

		  // Get compound ordering by finding the inner one first
		  this.performDFSOnCompounds();

		  for (var i = 0; i < this.compoundOrder.length; i++) {

		    idToNode[this.compoundOrder[i].id] = this.compoundOrder[i];
		    childGraphMap[this.compoundOrder[i].id] = [].concat(this.compoundOrder[i].getChild().getNodes());

		    // Remove children of compounds
		    this.graphManager.remove(this.compoundOrder[i].getChild());
		    this.compoundOrder[i].child = null;
		  }

		  this.graphManager.resetAllNodes();

		  // Tile the removed children
		  this.tileCompoundMembers(childGraphMap, idToNode);
		};

		CoSELayout.prototype.clearZeroDegreeMembers = function () {
		  var self = this;
		  var tiledZeroDegreePack = this.tiledZeroDegreePack = [];

		  Object.keys(this.memberGroups).forEach(function (id) {
		    var compoundNode = self.idToDummyNode[id]; // Get the dummy compound

		    tiledZeroDegreePack[id] = self.tileNodes(self.memberGroups[id], compoundNode.paddingLeft + compoundNode.paddingRight);

		    // Set the width and height of the dummy compound as calculated
		    compoundNode.rect.width = tiledZeroDegreePack[id].width;
		    compoundNode.rect.height = tiledZeroDegreePack[id].height;
		  });
		};

		CoSELayout.prototype.repopulateCompounds = function () {
		  for (var i = this.compoundOrder.length - 1; i >= 0; i--) {
		    var lCompoundNode = this.compoundOrder[i];
		    var id = lCompoundNode.id;
		    var horizontalMargin = lCompoundNode.paddingLeft;
		    var verticalMargin = lCompoundNode.paddingTop;

		    this.adjustLocations(this.tiledMemberPack[id], lCompoundNode.rect.x, lCompoundNode.rect.y, horizontalMargin, verticalMargin);
		  }
		};

		CoSELayout.prototype.repopulateZeroDegreeMembers = function () {
		  var self = this;
		  var tiledPack = this.tiledZeroDegreePack;

		  Object.keys(tiledPack).forEach(function (id) {
		    var compoundNode = self.idToDummyNode[id]; // Get the dummy compound by its id
		    var horizontalMargin = compoundNode.paddingLeft;
		    var verticalMargin = compoundNode.paddingTop;

		    // Adjust the positions of nodes wrt its compound
		    self.adjustLocations(tiledPack[id], compoundNode.rect.x, compoundNode.rect.y, horizontalMargin, verticalMargin);
		  });
		};

		CoSELayout.prototype.getToBeTiled = function (node) {
		  var id = node.id;
		  //firstly check the previous results
		  if (this.toBeTiled[id] != null) {
		    return this.toBeTiled[id];
		  }

		  //only compound nodes are to be tiled
		  var childGraph = node.getChild();
		  if (childGraph == null) {
		    this.toBeTiled[id] = false;
		    return false;
		  }

		  var children = childGraph.getNodes(); // Get the children nodes

		  //a compound node is not to be tiled if all of its compound children are not to be tiled
		  for (var i = 0; i < children.length; i++) {
		    var theChild = children[i];

		    if (this.getNodeDegree(theChild) > 0) {
		      this.toBeTiled[id] = false;
		      return false;
		    }

		    //pass the children not having the compound structure
		    if (theChild.getChild() == null) {
		      this.toBeTiled[theChild.id] = false;
		      continue;
		    }

		    if (!this.getToBeTiled(theChild)) {
		      this.toBeTiled[id] = false;
		      return false;
		    }
		  }
		  this.toBeTiled[id] = true;
		  return true;
		};

		// Get degree of a node depending of its edges and independent of its children
		CoSELayout.prototype.getNodeDegree = function (node) {
		  node.id;
		  var edges = node.getEdges();
		  var degree = 0;

		  // For the edges connected
		  for (var i = 0; i < edges.length; i++) {
		    var edge = edges[i];
		    if (edge.getSource().id !== edge.getTarget().id) {
		      degree = degree + 1;
		    }
		  }
		  return degree;
		};

		// Get degree of a node with its children
		CoSELayout.prototype.getNodeDegreeWithChildren = function (node) {
		  var degree = this.getNodeDegree(node);
		  if (node.getChild() == null) {
		    return degree;
		  }
		  var children = node.getChild().getNodes();
		  for (var i = 0; i < children.length; i++) {
		    var child = children[i];
		    degree += this.getNodeDegreeWithChildren(child);
		  }
		  return degree;
		};

		CoSELayout.prototype.performDFSOnCompounds = function () {
		  this.compoundOrder = [];
		  this.fillCompexOrderByDFS(this.graphManager.getRoot().getNodes());
		};

		CoSELayout.prototype.fillCompexOrderByDFS = function (children) {
		  for (var i = 0; i < children.length; i++) {
		    var child = children[i];
		    if (child.getChild() != null) {
		      this.fillCompexOrderByDFS(child.getChild().getNodes());
		    }
		    if (this.getToBeTiled(child)) {
		      this.compoundOrder.push(child);
		    }
		  }
		};

		/**
		* This method places each zero degree member wrt given (x,y) coordinates (top left).
		*/
		CoSELayout.prototype.adjustLocations = function (organization, x, y, compoundHorizontalMargin, compoundVerticalMargin) {
		  x += compoundHorizontalMargin;
		  y += compoundVerticalMargin;

		  var left = x;

		  for (var i = 0; i < organization.rows.length; i++) {
		    var row = organization.rows[i];
		    x = left;
		    var maxHeight = 0;

		    for (var j = 0; j < row.length; j++) {
		      var lnode = row[j];

		      lnode.rect.x = x; // + lnode.rect.width / 2;
		      lnode.rect.y = y; // + lnode.rect.height / 2;

		      x += lnode.rect.width + organization.horizontalPadding;

		      if (lnode.rect.height > maxHeight) maxHeight = lnode.rect.height;
		    }

		    y += maxHeight + organization.verticalPadding;
		  }
		};

		CoSELayout.prototype.tileCompoundMembers = function (childGraphMap, idToNode) {
		  var self = this;
		  this.tiledMemberPack = [];

		  Object.keys(childGraphMap).forEach(function (id) {
		    // Get the compound node
		    var compoundNode = idToNode[id];

		    self.tiledMemberPack[id] = self.tileNodes(childGraphMap[id], compoundNode.paddingLeft + compoundNode.paddingRight);

		    compoundNode.rect.width = self.tiledMemberPack[id].width;
		    compoundNode.rect.height = self.tiledMemberPack[id].height;
		  });
		};

		CoSELayout.prototype.tileNodes = function (nodes, minWidth) {
		  var verticalPadding = CoSEConstants.TILING_PADDING_VERTICAL;
		  var horizontalPadding = CoSEConstants.TILING_PADDING_HORIZONTAL;
		  var organization = {
		    rows: [],
		    rowWidth: [],
		    rowHeight: [],
		    width: 0,
		    height: minWidth, // assume minHeight equals to minWidth
		    verticalPadding: verticalPadding,
		    horizontalPadding: horizontalPadding
		  };

		  // Sort the nodes in ascending order of their areas
		  nodes.sort(function (n1, n2) {
		    if (n1.rect.width * n1.rect.height > n2.rect.width * n2.rect.height) return -1;
		    if (n1.rect.width * n1.rect.height < n2.rect.width * n2.rect.height) return 1;
		    return 0;
		  });

		  // Create the organization -> tile members
		  for (var i = 0; i < nodes.length; i++) {
		    var lNode = nodes[i];

		    if (organization.rows.length == 0) {
		      this.insertNodeToRow(organization, lNode, 0, minWidth);
		    } else if (this.canAddHorizontal(organization, lNode.rect.width, lNode.rect.height)) {
		      this.insertNodeToRow(organization, lNode, this.getShortestRowIndex(organization), minWidth);
		    } else {
		      this.insertNodeToRow(organization, lNode, organization.rows.length, minWidth);
		    }

		    this.shiftToLastRow(organization);
		  }

		  return organization;
		};

		CoSELayout.prototype.insertNodeToRow = function (organization, node, rowIndex, minWidth) {
		  var minCompoundSize = minWidth;

		  // Add new row if needed
		  if (rowIndex == organization.rows.length) {
		    var secondDimension = [];

		    organization.rows.push(secondDimension);
		    organization.rowWidth.push(minCompoundSize);
		    organization.rowHeight.push(0);
		  }

		  // Update row width
		  var w = organization.rowWidth[rowIndex] + node.rect.width;

		  if (organization.rows[rowIndex].length > 0) {
		    w += organization.horizontalPadding;
		  }

		  organization.rowWidth[rowIndex] = w;
		  // Update compound width
		  if (organization.width < w) {
		    organization.width = w;
		  }

		  // Update height
		  var h = node.rect.height;
		  if (rowIndex > 0) h += organization.verticalPadding;

		  var extraHeight = 0;
		  if (h > organization.rowHeight[rowIndex]) {
		    extraHeight = organization.rowHeight[rowIndex];
		    organization.rowHeight[rowIndex] = h;
		    extraHeight = organization.rowHeight[rowIndex] - extraHeight;
		  }

		  organization.height += extraHeight;

		  // Insert node
		  organization.rows[rowIndex].push(node);
		};

		//Scans the rows of an organization and returns the one with the min width
		CoSELayout.prototype.getShortestRowIndex = function (organization) {
		  var r = -1;
		  var min = Number.MAX_VALUE;

		  for (var i = 0; i < organization.rows.length; i++) {
		    if (organization.rowWidth[i] < min) {
		      r = i;
		      min = organization.rowWidth[i];
		    }
		  }
		  return r;
		};

		//Scans the rows of an organization and returns the one with the max width
		CoSELayout.prototype.getLongestRowIndex = function (organization) {
		  var r = -1;
		  var max = Number.MIN_VALUE;

		  for (var i = 0; i < organization.rows.length; i++) {

		    if (organization.rowWidth[i] > max) {
		      r = i;
		      max = organization.rowWidth[i];
		    }
		  }

		  return r;
		};

		/**
		* This method checks whether adding extra width to the organization violates
		* the aspect ratio(1) or not.
		*/
		CoSELayout.prototype.canAddHorizontal = function (organization, extraWidth, extraHeight) {

		  var sri = this.getShortestRowIndex(organization);

		  if (sri < 0) {
		    return true;
		  }

		  var min = organization.rowWidth[sri];

		  if (min + organization.horizontalPadding + extraWidth <= organization.width) return true;

		  var hDiff = 0;

		  // Adding to an existing row
		  if (organization.rowHeight[sri] < extraHeight) {
		    if (sri > 0) hDiff = extraHeight + organization.verticalPadding - organization.rowHeight[sri];
		  }

		  var add_to_row_ratio;
		  if (organization.width - min >= extraWidth + organization.horizontalPadding) {
		    add_to_row_ratio = (organization.height + hDiff) / (min + extraWidth + organization.horizontalPadding);
		  } else {
		    add_to_row_ratio = (organization.height + hDiff) / organization.width;
		  }

		  // Adding a new row for this node
		  hDiff = extraHeight + organization.verticalPadding;
		  var add_new_row_ratio;
		  if (organization.width < extraWidth) {
		    add_new_row_ratio = (organization.height + hDiff) / extraWidth;
		  } else {
		    add_new_row_ratio = (organization.height + hDiff) / organization.width;
		  }

		  if (add_new_row_ratio < 1) add_new_row_ratio = 1 / add_new_row_ratio;

		  if (add_to_row_ratio < 1) add_to_row_ratio = 1 / add_to_row_ratio;

		  return add_to_row_ratio < add_new_row_ratio;
		};

		//If moving the last node from the longest row and adding it to the last
		//row makes the bounding box smaller, do it.
		CoSELayout.prototype.shiftToLastRow = function (organization) {
		  var longest = this.getLongestRowIndex(organization);
		  var last = organization.rowWidth.length - 1;
		  var row = organization.rows[longest];
		  var node = row[row.length - 1];

		  var diff = node.width + organization.horizontalPadding;

		  // Check if there is enough space on the last row
		  if (organization.width - organization.rowWidth[last] > diff && longest != last) {
		    // Remove the last element of the longest row
		    row.splice(-1, 1);

		    // Push it to the last row
		    organization.rows[last].push(node);

		    organization.rowWidth[longest] = organization.rowWidth[longest] - diff;
		    organization.rowWidth[last] = organization.rowWidth[last] + diff;
		    organization.width = organization.rowWidth[instance.getLongestRowIndex(organization)];

		    // Update heights of the organization
		    var maxHeight = Number.MIN_VALUE;
		    for (var i = 0; i < row.length; i++) {
		      if (row[i].height > maxHeight) maxHeight = row[i].height;
		    }
		    if (longest > 0) maxHeight += organization.verticalPadding;

		    var prevTotal = organization.rowHeight[longest] + organization.rowHeight[last];

		    organization.rowHeight[longest] = maxHeight;
		    if (organization.rowHeight[last] < node.height + organization.verticalPadding) organization.rowHeight[last] = node.height + organization.verticalPadding;

		    var finalTotal = organization.rowHeight[longest] + organization.rowHeight[last];
		    organization.height += finalTotal - prevTotal;

		    this.shiftToLastRow(organization);
		  }
		};

		CoSELayout.prototype.tilingPreLayout = function () {
		  if (CoSEConstants.TILE) {
		    // Find zero degree nodes and create a compound for each level
		    this.groupZeroDegreeMembers();
		    // Tile and clear children of each compound
		    this.clearCompounds();
		    // Separately tile and clear zero degree nodes for each level
		    this.clearZeroDegreeMembers();
		  }
		};

		CoSELayout.prototype.tilingPostLayout = function () {
		  if (CoSEConstants.TILE) {
		    this.repopulateZeroDegreeMembers();
		    this.repopulateCompounds();
		  }
		};

		// -----------------------------------------------------------------------------
		// Section: Tree Reduction methods
		// -----------------------------------------------------------------------------
		// Reduce trees 
		CoSELayout.prototype.reduceTrees = function () {
		  var prunedNodesAll = [];
		  var containsLeaf = true;
		  var node;

		  while (containsLeaf) {
		    var allNodes = this.graphManager.getAllNodes();
		    var prunedNodesInStepTemp = [];
		    containsLeaf = false;

		    for (var i = 0; i < allNodes.length; i++) {
		      node = allNodes[i];
		      if (node.getEdges().length == 1 && !node.getEdges()[0].isInterGraph && node.getChild() == null) {
		        prunedNodesInStepTemp.push([node, node.getEdges()[0], node.getOwner()]);
		        containsLeaf = true;
		      }
		    }
		    if (containsLeaf == true) {
		      var prunedNodesInStep = [];
		      for (var j = 0; j < prunedNodesInStepTemp.length; j++) {
		        if (prunedNodesInStepTemp[j][0].getEdges().length == 1) {
		          prunedNodesInStep.push(prunedNodesInStepTemp[j]);
		          prunedNodesInStepTemp[j][0].getOwner().remove(prunedNodesInStepTemp[j][0]);
		        }
		      }
		      prunedNodesAll.push(prunedNodesInStep);
		      this.graphManager.resetAllNodes();
		      this.graphManager.resetAllEdges();
		    }
		  }
		  this.prunedNodesAll = prunedNodesAll;
		};

		// Grow tree one step 
		CoSELayout.prototype.growTree = function (prunedNodesAll) {
		  var lengthOfPrunedNodesInStep = prunedNodesAll.length;
		  var prunedNodesInStep = prunedNodesAll[lengthOfPrunedNodesInStep - 1];

		  var nodeData;
		  for (var i = 0; i < prunedNodesInStep.length; i++) {
		    nodeData = prunedNodesInStep[i];

		    this.findPlaceforPrunedNode(nodeData);

		    nodeData[2].add(nodeData[0]);
		    nodeData[2].add(nodeData[1], nodeData[1].source, nodeData[1].target);
		  }

		  prunedNodesAll.splice(prunedNodesAll.length - 1, 1);
		  this.graphManager.resetAllNodes();
		  this.graphManager.resetAllEdges();
		};

		// Find an appropriate position to replace pruned node, this method can be improved
		CoSELayout.prototype.findPlaceforPrunedNode = function (nodeData) {

		  var gridForPrunedNode;
		  var nodeToConnect;
		  var prunedNode = nodeData[0];
		  if (prunedNode == nodeData[1].source) {
		    nodeToConnect = nodeData[1].target;
		  } else {
		    nodeToConnect = nodeData[1].source;
		  }
		  var startGridX = nodeToConnect.startX;
		  var finishGridX = nodeToConnect.finishX;
		  var startGridY = nodeToConnect.startY;
		  var finishGridY = nodeToConnect.finishY;

		  var upNodeCount = 0;
		  var downNodeCount = 0;
		  var rightNodeCount = 0;
		  var leftNodeCount = 0;
		  var controlRegions = [upNodeCount, rightNodeCount, downNodeCount, leftNodeCount];

		  if (startGridY > 0) {
		    for (var i = startGridX; i <= finishGridX; i++) {
		      controlRegions[0] += this.grid[i][startGridY - 1].length + this.grid[i][startGridY].length - 1;
		    }
		  }
		  if (finishGridX < this.grid.length - 1) {
		    for (var i = startGridY; i <= finishGridY; i++) {
		      controlRegions[1] += this.grid[finishGridX + 1][i].length + this.grid[finishGridX][i].length - 1;
		    }
		  }
		  if (finishGridY < this.grid[0].length - 1) {
		    for (var i = startGridX; i <= finishGridX; i++) {
		      controlRegions[2] += this.grid[i][finishGridY + 1].length + this.grid[i][finishGridY].length - 1;
		    }
		  }
		  if (startGridX > 0) {
		    for (var i = startGridY; i <= finishGridY; i++) {
		      controlRegions[3] += this.grid[startGridX - 1][i].length + this.grid[startGridX][i].length - 1;
		    }
		  }
		  var min = Integer.MAX_VALUE;
		  var minCount;
		  var minIndex;
		  for (var j = 0; j < controlRegions.length; j++) {
		    if (controlRegions[j] < min) {
		      min = controlRegions[j];
		      minCount = 1;
		      minIndex = j;
		    } else if (controlRegions[j] == min) {
		      minCount++;
		    }
		  }

		  if (minCount == 3 && min == 0) {
		    if (controlRegions[0] == 0 && controlRegions[1] == 0 && controlRegions[2] == 0) {
		      gridForPrunedNode = 1;
		    } else if (controlRegions[0] == 0 && controlRegions[1] == 0 && controlRegions[3] == 0) {
		      gridForPrunedNode = 0;
		    } else if (controlRegions[0] == 0 && controlRegions[2] == 0 && controlRegions[3] == 0) {
		      gridForPrunedNode = 3;
		    } else if (controlRegions[1] == 0 && controlRegions[2] == 0 && controlRegions[3] == 0) {
		      gridForPrunedNode = 2;
		    }
		  } else if (minCount == 2 && min == 0) {
		    var random = Math.floor(Math.random() * 2);
		    if (controlRegions[0] == 0 && controlRegions[1] == 0) {
		      if (random == 0) {
		        gridForPrunedNode = 0;
		      } else {
		        gridForPrunedNode = 1;
		      }
		    } else if (controlRegions[0] == 0 && controlRegions[2] == 0) {
		      if (random == 0) {
		        gridForPrunedNode = 0;
		      } else {
		        gridForPrunedNode = 2;
		      }
		    } else if (controlRegions[0] == 0 && controlRegions[3] == 0) {
		      if (random == 0) {
		        gridForPrunedNode = 0;
		      } else {
		        gridForPrunedNode = 3;
		      }
		    } else if (controlRegions[1] == 0 && controlRegions[2] == 0) {
		      if (random == 0) {
		        gridForPrunedNode = 1;
		      } else {
		        gridForPrunedNode = 2;
		      }
		    } else if (controlRegions[1] == 0 && controlRegions[3] == 0) {
		      if (random == 0) {
		        gridForPrunedNode = 1;
		      } else {
		        gridForPrunedNode = 3;
		      }
		    } else {
		      if (random == 0) {
		        gridForPrunedNode = 2;
		      } else {
		        gridForPrunedNode = 3;
		      }
		    }
		  } else if (minCount == 4 && min == 0) {
		    var random = Math.floor(Math.random() * 4);
		    gridForPrunedNode = random;
		  } else {
		    gridForPrunedNode = minIndex;
		  }

		  if (gridForPrunedNode == 0) {
		    prunedNode.setCenter(nodeToConnect.getCenterX(), nodeToConnect.getCenterY() - nodeToConnect.getHeight() / 2 - FDLayoutConstants.DEFAULT_EDGE_LENGTH - prunedNode.getHeight() / 2);
		  } else if (gridForPrunedNode == 1) {
		    prunedNode.setCenter(nodeToConnect.getCenterX() + nodeToConnect.getWidth() / 2 + FDLayoutConstants.DEFAULT_EDGE_LENGTH + prunedNode.getWidth() / 2, nodeToConnect.getCenterY());
		  } else if (gridForPrunedNode == 2) {
		    prunedNode.setCenter(nodeToConnect.getCenterX(), nodeToConnect.getCenterY() + nodeToConnect.getHeight() / 2 + FDLayoutConstants.DEFAULT_EDGE_LENGTH + prunedNode.getHeight() / 2);
		  } else {
		    prunedNode.setCenter(nodeToConnect.getCenterX() - nodeToConnect.getWidth() / 2 - FDLayoutConstants.DEFAULT_EDGE_LENGTH - prunedNode.getWidth() / 2, nodeToConnect.getCenterY());
		  }
		};

		module.exports = CoSELayout;

		/***/ }),
		/* 7 */
		/***/ (function(module, exports, __webpack_require__) {


		var coseBase = {};

		coseBase.layoutBase = __webpack_require__(0);
		coseBase.CoSEConstants = __webpack_require__(1);
		coseBase.CoSEEdge = __webpack_require__(2);
		coseBase.CoSEGraph = __webpack_require__(3);
		coseBase.CoSEGraphManager = __webpack_require__(4);
		coseBase.CoSELayout = __webpack_require__(6);
		coseBase.CoSENode = __webpack_require__(5);

		module.exports = coseBase;

		/***/ })
		/******/ ]);
		}); 
	} (coseBase$1.__module));
	return coseBase$1.__module.exports;
}

exports.__require = requireCoseBase;
