import { _ as __name, l as log } from './mermaid.core-m0ZQP3yq.js';
import { c as cytoscape$1 } from './cytoscape.esm-B7A0mjXA.js';
import { G as getDefaultExportFromCjs } from './i18n-CMo5lpzy.js';
import { s as select } from './select-k8gDf_61.js';
import './index-BvBk1Iap.js';
import './step-TZOpqHBK.js';
import './dispatch-tQmgj1It.js';

var cytoscapeCoseBilkent$1 = {exports: {}};

var coseBase$1 = {exports: {}};

var layoutBase$1 = {exports: {}};

var layoutBase = layoutBase$1.exports;

var hasRequiredLayoutBase;

function requireLayoutBase () {
	if (hasRequiredLayoutBase) return layoutBase$1.exports;
	hasRequiredLayoutBase = 1;
	(function (module, exports$1) {
		(function webpackUniversalModuleDefinition(root, factory) {
			module.exports = factory();
		})(layoutBase, function() {
		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$1, name, getter) {
		/******/ 		if(!__webpack_require__.o(exports$1, name)) {
		/******/ 			Object.defineProperty(exports$1, 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 = 26);
		/******/ })
		/************************************************************************/
		/******/ ([
		/* 0 */
		/***/ (function(module, exports$1, __webpack_require__) {


		function LayoutConstants() {}

		/**
		 * Layout Quality: 0:draft, 1:default, 2:proof
		 */
		LayoutConstants.QUALITY = 1;

		/**
		 * Default parameters
		 */
		LayoutConstants.DEFAULT_CREATE_BENDS_AS_NEEDED = false;
		LayoutConstants.DEFAULT_INCREMENTAL = false;
		LayoutConstants.DEFAULT_ANIMATION_ON_LAYOUT = true;
		LayoutConstants.DEFAULT_ANIMATION_DURING_LAYOUT = false;
		LayoutConstants.DEFAULT_ANIMATION_PERIOD = 50;
		LayoutConstants.DEFAULT_UNIFORM_LEAF_NODE_SIZES = false;

		// -----------------------------------------------------------------------------
		// Section: General other constants
		// -----------------------------------------------------------------------------
		/*
		 * Margins of a graph to be applied on bouding rectangle of its contents. We
		 * assume margins on all four sides to be uniform.
		 */
		LayoutConstants.DEFAULT_GRAPH_MARGIN = 15;

		/*
		 * Whether to consider labels in node dimensions or not
		 */
		LayoutConstants.NODE_DIMENSIONS_INCLUDE_LABELS = false;

		/*
		 * Default dimension of a non-compound node.
		 */
		LayoutConstants.SIMPLE_NODE_SIZE = 40;

		/*
		 * Default dimension of a non-compound node.
		 */
		LayoutConstants.SIMPLE_NODE_HALF_SIZE = LayoutConstants.SIMPLE_NODE_SIZE / 2;

		/*
		 * Empty compound node size. When a compound node is empty, its both
		 * dimensions should be of this value.
		 */
		LayoutConstants.EMPTY_COMPOUND_NODE_SIZE = 40;

		/*
		 * Minimum length that an edge should take during layout
		 */
		LayoutConstants.MIN_EDGE_LENGTH = 1;

		/*
		 * World boundaries that layout operates on
		 */
		LayoutConstants.WORLD_BOUNDARY = 1000000;

		/*
		 * World boundaries that random positioning can be performed with
		 */
		LayoutConstants.INITIAL_WORLD_BOUNDARY = LayoutConstants.WORLD_BOUNDARY / 1000;

		/*
		 * Coordinates of the world center
		 */
		LayoutConstants.WORLD_CENTER_X = 1200;
		LayoutConstants.WORLD_CENTER_Y = 900;

		module.exports = LayoutConstants;

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


		var LGraphObject = __webpack_require__(2);
		var IGeometry = __webpack_require__(8);
		var IMath = __webpack_require__(9);

		function LEdge(source, target, vEdge) {
		  LGraphObject.call(this, vEdge);

		  this.isOverlapingSourceAndTarget = false;
		  this.vGraphObject = vEdge;
		  this.bendpoints = [];
		  this.source = source;
		  this.target = target;
		}

		LEdge.prototype = Object.create(LGraphObject.prototype);

		for (var prop in LGraphObject) {
		  LEdge[prop] = LGraphObject[prop];
		}

		LEdge.prototype.getSource = function () {
		  return this.source;
		};

		LEdge.prototype.getTarget = function () {
		  return this.target;
		};

		LEdge.prototype.isInterGraph = function () {
		  return this.isInterGraph;
		};

		LEdge.prototype.getLength = function () {
		  return this.length;
		};

		LEdge.prototype.isOverlapingSourceAndTarget = function () {
		  return this.isOverlapingSourceAndTarget;
		};

		LEdge.prototype.getBendpoints = function () {
		  return this.bendpoints;
		};

		LEdge.prototype.getLca = function () {
		  return this.lca;
		};

		LEdge.prototype.getSourceInLca = function () {
		  return this.sourceInLca;
		};

		LEdge.prototype.getTargetInLca = function () {
		  return this.targetInLca;
		};

		LEdge.prototype.getOtherEnd = function (node) {
		  if (this.source === node) {
		    return this.target;
		  } else if (this.target === node) {
		    return this.source;
		  } else {
		    throw "Node is not incident with this edge";
		  }
		};

		LEdge.prototype.getOtherEndInGraph = function (node, graph) {
		  var otherEnd = this.getOtherEnd(node);
		  var root = graph.getGraphManager().getRoot();

		  while (true) {
		    if (otherEnd.getOwner() == graph) {
		      return otherEnd;
		    }

		    if (otherEnd.getOwner() == root) {
		      break;
		    }

		    otherEnd = otherEnd.getOwner().getParent();
		  }

		  return null;
		};

		LEdge.prototype.updateLength = function () {
		  var clipPointCoordinates = new Array(4);

		  this.isOverlapingSourceAndTarget = IGeometry.getIntersection(this.target.getRect(), this.source.getRect(), clipPointCoordinates);

		  if (!this.isOverlapingSourceAndTarget) {
		    this.lengthX = clipPointCoordinates[0] - clipPointCoordinates[2];
		    this.lengthY = clipPointCoordinates[1] - clipPointCoordinates[3];

		    if (Math.abs(this.lengthX) < 1.0) {
		      this.lengthX = IMath.sign(this.lengthX);
		    }

		    if (Math.abs(this.lengthY) < 1.0) {
		      this.lengthY = IMath.sign(this.lengthY);
		    }

		    this.length = Math.sqrt(this.lengthX * this.lengthX + this.lengthY * this.lengthY);
		  }
		};

		LEdge.prototype.updateLengthSimple = function () {
		  this.lengthX = this.target.getCenterX() - this.source.getCenterX();
		  this.lengthY = this.target.getCenterY() - this.source.getCenterY();

		  if (Math.abs(this.lengthX) < 1.0) {
		    this.lengthX = IMath.sign(this.lengthX);
		  }

		  if (Math.abs(this.lengthY) < 1.0) {
		    this.lengthY = IMath.sign(this.lengthY);
		  }

		  this.length = Math.sqrt(this.lengthX * this.lengthX + this.lengthY * this.lengthY);
		};

		module.exports = LEdge;

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


		function LGraphObject(vGraphObject) {
		  this.vGraphObject = vGraphObject;
		}

		module.exports = LGraphObject;

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


		var LGraphObject = __webpack_require__(2);
		var Integer = __webpack_require__(10);
		var RectangleD = __webpack_require__(13);
		var LayoutConstants = __webpack_require__(0);
		var RandomSeed = __webpack_require__(16);
		var PointD = __webpack_require__(4);

		function LNode(gm, loc, size, vNode) {
		  //Alternative constructor 1 : LNode(LGraphManager gm, Point loc, Dimension size, Object vNode)
		  if (size == null && vNode == null) {
		    vNode = loc;
		  }

		  LGraphObject.call(this, vNode);

		  //Alternative constructor 2 : LNode(Layout layout, Object vNode)
		  if (gm.graphManager != null) gm = gm.graphManager;

		  this.estimatedSize = Integer.MIN_VALUE;
		  this.inclusionTreeDepth = Integer.MAX_VALUE;
		  this.vGraphObject = vNode;
		  this.edges = [];
		  this.graphManager = gm;

		  if (size != null && loc != null) this.rect = new RectangleD(loc.x, loc.y, size.width, size.height);else this.rect = new RectangleD();
		}

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

		LNode.prototype.getEdges = function () {
		  return this.edges;
		};

		LNode.prototype.getChild = function () {
		  return this.child;
		};

		LNode.prototype.getOwner = function () {
		  //  if (this.owner != null) {
		  //    if (!(this.owner == null || this.owner.getNodes().indexOf(this) > -1)) {
		  //      throw "assert failed";
		  //    }
		  //  }

		  return this.owner;
		};

		LNode.prototype.getWidth = function () {
		  return this.rect.width;
		};

		LNode.prototype.setWidth = function (width) {
		  this.rect.width = width;
		};

		LNode.prototype.getHeight = function () {
		  return this.rect.height;
		};

		LNode.prototype.setHeight = function (height) {
		  this.rect.height = height;
		};

		LNode.prototype.getCenterX = function () {
		  return this.rect.x + this.rect.width / 2;
		};

		LNode.prototype.getCenterY = function () {
		  return this.rect.y + this.rect.height / 2;
		};

		LNode.prototype.getCenter = function () {
		  return new PointD(this.rect.x + this.rect.width / 2, this.rect.y + this.rect.height / 2);
		};

		LNode.prototype.getLocation = function () {
		  return new PointD(this.rect.x, this.rect.y);
		};

		LNode.prototype.getRect = function () {
		  return this.rect;
		};

		LNode.prototype.getDiagonal = function () {
		  return Math.sqrt(this.rect.width * this.rect.width + this.rect.height * this.rect.height);
		};

		/**
		 * This method returns half the diagonal length of this node.
		 */
		LNode.prototype.getHalfTheDiagonal = function () {
		  return Math.sqrt(this.rect.height * this.rect.height + this.rect.width * this.rect.width) / 2;
		};

		LNode.prototype.setRect = function (upperLeft, dimension) {
		  this.rect.x = upperLeft.x;
		  this.rect.y = upperLeft.y;
		  this.rect.width = dimension.width;
		  this.rect.height = dimension.height;
		};

		LNode.prototype.setCenter = function (cx, cy) {
		  this.rect.x = cx - this.rect.width / 2;
		  this.rect.y = cy - this.rect.height / 2;
		};

		LNode.prototype.setLocation = function (x, y) {
		  this.rect.x = x;
		  this.rect.y = y;
		};

		LNode.prototype.moveBy = function (dx, dy) {
		  this.rect.x += dx;
		  this.rect.y += dy;
		};

		LNode.prototype.getEdgeListToNode = function (to) {
		  var edgeList = [];
		  var self = this;

		  self.edges.forEach(function (edge) {

		    if (edge.target == to) {
		      if (edge.source != self) throw "Incorrect edge source!";

		      edgeList.push(edge);
		    }
		  });

		  return edgeList;
		};

		LNode.prototype.getEdgesBetween = function (other) {
		  var edgeList = [];

		  var self = this;
		  self.edges.forEach(function (edge) {

		    if (!(edge.source == self || edge.target == self)) throw "Incorrect edge source and/or target";

		    if (edge.target == other || edge.source == other) {
		      edgeList.push(edge);
		    }
		  });

		  return edgeList;
		};

		LNode.prototype.getNeighborsList = function () {
		  var neighbors = new Set();

		  var self = this;
		  self.edges.forEach(function (edge) {

		    if (edge.source == self) {
		      neighbors.add(edge.target);
		    } else {
		      if (edge.target != self) {
		        throw "Incorrect incidency!";
		      }

		      neighbors.add(edge.source);
		    }
		  });

		  return neighbors;
		};

		LNode.prototype.withChildren = function () {
		  var withNeighborsList = new Set();
		  var childNode;
		  var children;

		  withNeighborsList.add(this);

		  if (this.child != null) {
		    var nodes = this.child.getNodes();
		    for (var i = 0; i < nodes.length; i++) {
		      childNode = nodes[i];
		      children = childNode.withChildren();
		      children.forEach(function (node) {
		        withNeighborsList.add(node);
		      });
		    }
		  }

		  return withNeighborsList;
		};

		LNode.prototype.getNoOfChildren = function () {
		  var noOfChildren = 0;
		  var childNode;

		  if (this.child == null) {
		    noOfChildren = 1;
		  } else {
		    var nodes = this.child.getNodes();
		    for (var i = 0; i < nodes.length; i++) {
		      childNode = nodes[i];

		      noOfChildren += childNode.getNoOfChildren();
		    }
		  }

		  if (noOfChildren == 0) {
		    noOfChildren = 1;
		  }
		  return noOfChildren;
		};

		LNode.prototype.getEstimatedSize = function () {
		  if (this.estimatedSize == Integer.MIN_VALUE) {
		    throw "assert failed";
		  }
		  return this.estimatedSize;
		};

		LNode.prototype.calcEstimatedSize = function () {
		  if (this.child == null) {
		    return this.estimatedSize = (this.rect.width + this.rect.height) / 2;
		  } else {
		    this.estimatedSize = this.child.calcEstimatedSize();
		    this.rect.width = this.estimatedSize;
		    this.rect.height = this.estimatedSize;

		    return this.estimatedSize;
		  }
		};

		LNode.prototype.scatter = function () {
		  var randomCenterX;
		  var randomCenterY;

		  var minX = -LayoutConstants.INITIAL_WORLD_BOUNDARY;
		  var maxX = LayoutConstants.INITIAL_WORLD_BOUNDARY;
		  randomCenterX = LayoutConstants.WORLD_CENTER_X + RandomSeed.nextDouble() * (maxX - minX) + minX;

		  var minY = -LayoutConstants.INITIAL_WORLD_BOUNDARY;
		  var maxY = LayoutConstants.INITIAL_WORLD_BOUNDARY;
		  randomCenterY = LayoutConstants.WORLD_CENTER_Y + RandomSeed.nextDouble() * (maxY - minY) + minY;

		  this.rect.x = randomCenterX;
		  this.rect.y = randomCenterY;
		};

		LNode.prototype.updateBounds = function () {
		  if (this.getChild() == null) {
		    throw "assert failed";
		  }
		  if (this.getChild().getNodes().length != 0) {
		    // wrap the children nodes by re-arranging the boundaries
		    var childGraph = this.getChild();
		    childGraph.updateBounds(true);

		    this.rect.x = childGraph.getLeft();
		    this.rect.y = childGraph.getTop();

		    this.setWidth(childGraph.getRight() - childGraph.getLeft());
		    this.setHeight(childGraph.getBottom() - childGraph.getTop());

		    // Update compound bounds considering its label properties    
		    if (LayoutConstants.NODE_DIMENSIONS_INCLUDE_LABELS) {

		      var width = childGraph.getRight() - childGraph.getLeft();
		      var height = childGraph.getBottom() - childGraph.getTop();

		      if (this.labelWidth > width) {
		        this.rect.x -= (this.labelWidth - width) / 2;
		        this.setWidth(this.labelWidth);
		      }

		      if (this.labelHeight > height) {
		        if (this.labelPos == "center") {
		          this.rect.y -= (this.labelHeight - height) / 2;
		        } else if (this.labelPos == "top") {
		          this.rect.y -= this.labelHeight - height;
		        }
		        this.setHeight(this.labelHeight);
		      }
		    }
		  }
		};

		LNode.prototype.getInclusionTreeDepth = function () {
		  if (this.inclusionTreeDepth == Integer.MAX_VALUE) {
		    throw "assert failed";
		  }
		  return this.inclusionTreeDepth;
		};

		LNode.prototype.transform = function (trans) {
		  var left = this.rect.x;

		  if (left > LayoutConstants.WORLD_BOUNDARY) {
		    left = LayoutConstants.WORLD_BOUNDARY;
		  } else if (left < -LayoutConstants.WORLD_BOUNDARY) {
		    left = -LayoutConstants.WORLD_BOUNDARY;
		  }

		  var top = this.rect.y;

		  if (top > LayoutConstants.WORLD_BOUNDARY) {
		    top = LayoutConstants.WORLD_BOUNDARY;
		  } else if (top < -LayoutConstants.WORLD_BOUNDARY) {
		    top = -LayoutConstants.WORLD_BOUNDARY;
		  }

		  var leftTop = new PointD(left, top);
		  var vLeftTop = trans.inverseTransformPoint(leftTop);

		  this.setLocation(vLeftTop.x, vLeftTop.y);
		};

		LNode.prototype.getLeft = function () {
		  return this.rect.x;
		};

		LNode.prototype.getRight = function () {
		  return this.rect.x + this.rect.width;
		};

		LNode.prototype.getTop = function () {
		  return this.rect.y;
		};

		LNode.prototype.getBottom = function () {
		  return this.rect.y + this.rect.height;
		};

		LNode.prototype.getParent = function () {
		  if (this.owner == null) {
		    return null;
		  }

		  return this.owner.getParent();
		};

		module.exports = LNode;

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


		function PointD(x, y) {
		  if (x == null && y == null) {
		    this.x = 0;
		    this.y = 0;
		  } else {
		    this.x = x;
		    this.y = y;
		  }
		}

		PointD.prototype.getX = function () {
		  return this.x;
		};

		PointD.prototype.getY = function () {
		  return this.y;
		};

		PointD.prototype.setX = function (x) {
		  this.x = x;
		};

		PointD.prototype.setY = function (y) {
		  this.y = y;
		};

		PointD.prototype.getDifference = function (pt) {
		  return new DimensionD(this.x - pt.x, this.y - pt.y);
		};

		PointD.prototype.getCopy = function () {
		  return new PointD(this.x, this.y);
		};

		PointD.prototype.translate = function (dim) {
		  this.x += dim.width;
		  this.y += dim.height;
		  return this;
		};

		module.exports = PointD;

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


		var LGraphObject = __webpack_require__(2);
		var Integer = __webpack_require__(10);
		var LayoutConstants = __webpack_require__(0);
		var LGraphManager = __webpack_require__(6);
		var LNode = __webpack_require__(3);
		var LEdge = __webpack_require__(1);
		var RectangleD = __webpack_require__(13);
		var Point = __webpack_require__(12);
		var LinkedList = __webpack_require__(11);

		function LGraph(parent, obj2, vGraph) {
		  LGraphObject.call(this, vGraph);
		  this.estimatedSize = Integer.MIN_VALUE;
		  this.margin = LayoutConstants.DEFAULT_GRAPH_MARGIN;
		  this.edges = [];
		  this.nodes = [];
		  this.isConnected = false;
		  this.parent = parent;

		  if (obj2 != null && obj2 instanceof LGraphManager) {
		    this.graphManager = obj2;
		  } else if (obj2 != null && obj2 instanceof Layout) {
		    this.graphManager = obj2.graphManager;
		  }
		}

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

		LGraph.prototype.getNodes = function () {
		  return this.nodes;
		};

		LGraph.prototype.getEdges = function () {
		  return this.edges;
		};

		LGraph.prototype.getGraphManager = function () {
		  return this.graphManager;
		};

		LGraph.prototype.getParent = function () {
		  return this.parent;
		};

		LGraph.prototype.getLeft = function () {
		  return this.left;
		};

		LGraph.prototype.getRight = function () {
		  return this.right;
		};

		LGraph.prototype.getTop = function () {
		  return this.top;
		};

		LGraph.prototype.getBottom = function () {
		  return this.bottom;
		};

		LGraph.prototype.isConnected = function () {
		  return this.isConnected;
		};

		LGraph.prototype.add = function (obj1, sourceNode, targetNode) {
		  if (sourceNode == null && targetNode == null) {
		    var newNode = obj1;
		    if (this.graphManager == null) {
		      throw "Graph has no graph mgr!";
		    }
		    if (this.getNodes().indexOf(newNode) > -1) {
		      throw "Node already in graph!";
		    }
		    newNode.owner = this;
		    this.getNodes().push(newNode);

		    return newNode;
		  } else {
		    var newEdge = obj1;
		    if (!(this.getNodes().indexOf(sourceNode) > -1 && this.getNodes().indexOf(targetNode) > -1)) {
		      throw "Source or target not in graph!";
		    }

		    if (!(sourceNode.owner == targetNode.owner && sourceNode.owner == this)) {
		      throw "Both owners must be this graph!";
		    }

		    if (sourceNode.owner != targetNode.owner) {
		      return null;
		    }

		    // set source and target
		    newEdge.source = sourceNode;
		    newEdge.target = targetNode;

		    // set as intra-graph edge
		    newEdge.isInterGraph = false;

		    // add to graph edge list
		    this.getEdges().push(newEdge);

		    // add to incidency lists
		    sourceNode.edges.push(newEdge);

		    if (targetNode != sourceNode) {
		      targetNode.edges.push(newEdge);
		    }

		    return newEdge;
		  }
		};

		LGraph.prototype.remove = function (obj) {
		  var node = obj;
		  if (obj instanceof LNode) {
		    if (node == null) {
		      throw "Node is null!";
		    }
		    if (!(node.owner != null && node.owner == this)) {
		      throw "Owner graph is invalid!";
		    }
		    if (this.graphManager == null) {
		      throw "Owner graph manager is invalid!";
		    }
		    // remove incident edges first (make a copy to do it safely)
		    var edgesToBeRemoved = node.edges.slice();
		    var edge;
		    var s = edgesToBeRemoved.length;
		    for (var i = 0; i < s; i++) {
		      edge = edgesToBeRemoved[i];

		      if (edge.isInterGraph) {
		        this.graphManager.remove(edge);
		      } else {
		        edge.source.owner.remove(edge);
		      }
		    }

		    // now the node itself
		    var index = this.nodes.indexOf(node);
		    if (index == -1) {
		      throw "Node not in owner node list!";
		    }

		    this.nodes.splice(index, 1);
		  } else if (obj instanceof LEdge) {
		    var edge = obj;
		    if (edge == null) {
		      throw "Edge is null!";
		    }
		    if (!(edge.source != null && edge.target != null)) {
		      throw "Source and/or target is null!";
		    }
		    if (!(edge.source.owner != null && edge.target.owner != null && edge.source.owner == this && edge.target.owner == this)) {
		      throw "Source and/or target owner is invalid!";
		    }

		    var sourceIndex = edge.source.edges.indexOf(edge);
		    var targetIndex = edge.target.edges.indexOf(edge);
		    if (!(sourceIndex > -1 && targetIndex > -1)) {
		      throw "Source and/or target doesn't know this edge!";
		    }

		    edge.source.edges.splice(sourceIndex, 1);

		    if (edge.target != edge.source) {
		      edge.target.edges.splice(targetIndex, 1);
		    }

		    var index = edge.source.owner.getEdges().indexOf(edge);
		    if (index == -1) {
		      throw "Not in owner's edge list!";
		    }

		    edge.source.owner.getEdges().splice(index, 1);
		  }
		};

		LGraph.prototype.updateLeftTop = function () {
		  var top = Integer.MAX_VALUE;
		  var left = Integer.MAX_VALUE;
		  var nodeTop;
		  var nodeLeft;
		  var margin;

		  var nodes = this.getNodes();
		  var s = nodes.length;

		  for (var i = 0; i < s; i++) {
		    var lNode = nodes[i];
		    nodeTop = lNode.getTop();
		    nodeLeft = lNode.getLeft();

		    if (top > nodeTop) {
		      top = nodeTop;
		    }

		    if (left > nodeLeft) {
		      left = nodeLeft;
		    }
		  }

		  // Do we have any nodes in this graph?
		  if (top == Integer.MAX_VALUE) {
		    return null;
		  }

		  if (nodes[0].getParent().paddingLeft != undefined) {
		    margin = nodes[0].getParent().paddingLeft;
		  } else {
		    margin = this.margin;
		  }

		  this.left = left - margin;
		  this.top = top - margin;

		  // Apply the margins and return the result
		  return new Point(this.left, this.top);
		};

		LGraph.prototype.updateBounds = function (recursive) {
		  // calculate bounds
		  var left = Integer.MAX_VALUE;
		  var right = -Integer.MAX_VALUE;
		  var top = Integer.MAX_VALUE;
		  var bottom = -Integer.MAX_VALUE;
		  var nodeLeft;
		  var nodeRight;
		  var nodeTop;
		  var nodeBottom;
		  var margin;

		  var nodes = this.nodes;
		  var s = nodes.length;
		  for (var i = 0; i < s; i++) {
		    var lNode = nodes[i];

		    if (recursive && lNode.child != null) {
		      lNode.updateBounds();
		    }
		    nodeLeft = lNode.getLeft();
		    nodeRight = lNode.getRight();
		    nodeTop = lNode.getTop();
		    nodeBottom = lNode.getBottom();

		    if (left > nodeLeft) {
		      left = nodeLeft;
		    }

		    if (right < nodeRight) {
		      right = nodeRight;
		    }

		    if (top > nodeTop) {
		      top = nodeTop;
		    }

		    if (bottom < nodeBottom) {
		      bottom = nodeBottom;
		    }
		  }

		  var boundingRect = new RectangleD(left, top, right - left, bottom - top);
		  if (left == Integer.MAX_VALUE) {
		    this.left = this.parent.getLeft();
		    this.right = this.parent.getRight();
		    this.top = this.parent.getTop();
		    this.bottom = this.parent.getBottom();
		  }

		  if (nodes[0].getParent().paddingLeft != undefined) {
		    margin = nodes[0].getParent().paddingLeft;
		  } else {
		    margin = this.margin;
		  }

		  this.left = boundingRect.x - margin;
		  this.right = boundingRect.x + boundingRect.width + margin;
		  this.top = boundingRect.y - margin;
		  this.bottom = boundingRect.y + boundingRect.height + margin;
		};

		LGraph.calculateBounds = function (nodes) {
		  var left = Integer.MAX_VALUE;
		  var right = -Integer.MAX_VALUE;
		  var top = Integer.MAX_VALUE;
		  var bottom = -Integer.MAX_VALUE;
		  var nodeLeft;
		  var nodeRight;
		  var nodeTop;
		  var nodeBottom;

		  var s = nodes.length;

		  for (var i = 0; i < s; i++) {
		    var lNode = nodes[i];
		    nodeLeft = lNode.getLeft();
		    nodeRight = lNode.getRight();
		    nodeTop = lNode.getTop();
		    nodeBottom = lNode.getBottom();

		    if (left > nodeLeft) {
		      left = nodeLeft;
		    }

		    if (right < nodeRight) {
		      right = nodeRight;
		    }

		    if (top > nodeTop) {
		      top = nodeTop;
		    }

		    if (bottom < nodeBottom) {
		      bottom = nodeBottom;
		    }
		  }

		  var boundingRect = new RectangleD(left, top, right - left, bottom - top);

		  return boundingRect;
		};

		LGraph.prototype.getInclusionTreeDepth = function () {
		  if (this == this.graphManager.getRoot()) {
		    return 1;
		  } else {
		    return this.parent.getInclusionTreeDepth();
		  }
		};

		LGraph.prototype.getEstimatedSize = function () {
		  if (this.estimatedSize == Integer.MIN_VALUE) {
		    throw "assert failed";
		  }
		  return this.estimatedSize;
		};

		LGraph.prototype.calcEstimatedSize = function () {
		  var size = 0;
		  var nodes = this.nodes;
		  var s = nodes.length;

		  for (var i = 0; i < s; i++) {
		    var lNode = nodes[i];
		    size += lNode.calcEstimatedSize();
		  }

		  if (size == 0) {
		    this.estimatedSize = LayoutConstants.EMPTY_COMPOUND_NODE_SIZE;
		  } else {
		    this.estimatedSize = size / Math.sqrt(this.nodes.length);
		  }

		  return this.estimatedSize;
		};

		LGraph.prototype.updateConnected = function () {
		  var self = this;
		  if (this.nodes.length == 0) {
		    this.isConnected = true;
		    return;
		  }

		  var queue = new LinkedList();
		  var visited = new Set();
		  var currentNode = this.nodes[0];
		  var neighborEdges;
		  var currentNeighbor;
		  var childrenOfNode = currentNode.withChildren();
		  childrenOfNode.forEach(function (node) {
		    queue.push(node);
		    visited.add(node);
		  });

		  while (queue.length !== 0) {
		    currentNode = queue.shift();

		    // Traverse all neighbors of this node
		    neighborEdges = currentNode.getEdges();
		    var size = neighborEdges.length;
		    for (var i = 0; i < size; i++) {
		      var neighborEdge = neighborEdges[i];
		      currentNeighbor = neighborEdge.getOtherEndInGraph(currentNode, this);

		      // Add unvisited neighbors to the list to visit
		      if (currentNeighbor != null && !visited.has(currentNeighbor)) {
		        var childrenOfNeighbor = currentNeighbor.withChildren();

		        childrenOfNeighbor.forEach(function (node) {
		          queue.push(node);
		          visited.add(node);
		        });
		      }
		    }
		  }

		  this.isConnected = false;

		  if (visited.size >= this.nodes.length) {
		    var noOfVisitedInThisGraph = 0;

		    visited.forEach(function (visitedNode) {
		      if (visitedNode.owner == self) {
		        noOfVisitedInThisGraph++;
		      }
		    });

		    if (noOfVisitedInThisGraph == this.nodes.length) {
		      this.isConnected = true;
		    }
		  }
		};

		module.exports = LGraph;

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


		var LGraph;
		var LEdge = __webpack_require__(1);

		function LGraphManager(layout) {
		  LGraph = __webpack_require__(5); // It may be better to initilize this out of this function but it gives an error (Right-hand side of 'instanceof' is not callable) now.
		  this.layout = layout;

		  this.graphs = [];
		  this.edges = [];
		}

		LGraphManager.prototype.addRoot = function () {
		  var ngraph = this.layout.newGraph();
		  var nnode = this.layout.newNode(null);
		  var root = this.add(ngraph, nnode);
		  this.setRootGraph(root);
		  return this.rootGraph;
		};

		LGraphManager.prototype.add = function (newGraph, parentNode, newEdge, sourceNode, targetNode) {
		  //there are just 2 parameters are passed then it adds an LGraph else it adds an LEdge
		  if (newEdge == null && sourceNode == null && targetNode == null) {
		    if (newGraph == null) {
		      throw "Graph is null!";
		    }
		    if (parentNode == null) {
		      throw "Parent node is null!";
		    }
		    if (this.graphs.indexOf(newGraph) > -1) {
		      throw "Graph already in this graph mgr!";
		    }

		    this.graphs.push(newGraph);

		    if (newGraph.parent != null) {
		      throw "Already has a parent!";
		    }
		    if (parentNode.child != null) {
		      throw "Already has a child!";
		    }

		    newGraph.parent = parentNode;
		    parentNode.child = newGraph;

		    return newGraph;
		  } else {
		    //change the order of the parameters
		    targetNode = newEdge;
		    sourceNode = parentNode;
		    newEdge = newGraph;
		    var sourceGraph = sourceNode.getOwner();
		    var targetGraph = targetNode.getOwner();

		    if (!(sourceGraph != null && sourceGraph.getGraphManager() == this)) {
		      throw "Source not in this graph mgr!";
		    }
		    if (!(targetGraph != null && targetGraph.getGraphManager() == this)) {
		      throw "Target not in this graph mgr!";
		    }

		    if (sourceGraph == targetGraph) {
		      newEdge.isInterGraph = false;
		      return sourceGraph.add(newEdge, sourceNode, targetNode);
		    } else {
		      newEdge.isInterGraph = true;

		      // set source and target
		      newEdge.source = sourceNode;
		      newEdge.target = targetNode;

		      // add edge to inter-graph edge list
		      if (this.edges.indexOf(newEdge) > -1) {
		        throw "Edge already in inter-graph edge list!";
		      }

		      this.edges.push(newEdge);

		      // add edge to source and target incidency lists
		      if (!(newEdge.source != null && newEdge.target != null)) {
		        throw "Edge source and/or target is null!";
		      }

		      if (!(newEdge.source.edges.indexOf(newEdge) == -1 && newEdge.target.edges.indexOf(newEdge) == -1)) {
		        throw "Edge already in source and/or target incidency list!";
		      }

		      newEdge.source.edges.push(newEdge);
		      newEdge.target.edges.push(newEdge);

		      return newEdge;
		    }
		  }
		};

		LGraphManager.prototype.remove = function (lObj) {
		  if (lObj instanceof LGraph) {
		    var graph = lObj;
		    if (graph.getGraphManager() != this) {
		      throw "Graph not in this graph mgr";
		    }
		    if (!(graph == this.rootGraph || graph.parent != null && graph.parent.graphManager == this)) {
		      throw "Invalid parent node!";
		    }

		    // first the edges (make a copy to do it safely)
		    var edgesToBeRemoved = [];

		    edgesToBeRemoved = edgesToBeRemoved.concat(graph.getEdges());

		    var edge;
		    var s = edgesToBeRemoved.length;
		    for (var i = 0; i < s; i++) {
		      edge = edgesToBeRemoved[i];
		      graph.remove(edge);
		    }

		    // then the nodes (make a copy to do it safely)
		    var nodesToBeRemoved = [];

		    nodesToBeRemoved = nodesToBeRemoved.concat(graph.getNodes());

		    var node;
		    s = nodesToBeRemoved.length;
		    for (var i = 0; i < s; i++) {
		      node = nodesToBeRemoved[i];
		      graph.remove(node);
		    }

		    // check if graph is the root
		    if (graph == this.rootGraph) {
		      this.setRootGraph(null);
		    }

		    // now remove the graph itself
		    var index = this.graphs.indexOf(graph);
		    this.graphs.splice(index, 1);

		    // also reset the parent of the graph
		    graph.parent = null;
		  } else if (lObj instanceof LEdge) {
		    edge = lObj;
		    if (edge == null) {
		      throw "Edge is null!";
		    }
		    if (!edge.isInterGraph) {
		      throw "Not an inter-graph edge!";
		    }
		    if (!(edge.source != null && edge.target != null)) {
		      throw "Source and/or target is null!";
		    }

		    // remove edge from source and target nodes' incidency lists

		    if (!(edge.source.edges.indexOf(edge) != -1 && edge.target.edges.indexOf(edge) != -1)) {
		      throw "Source and/or target doesn't know this edge!";
		    }

		    var index = edge.source.edges.indexOf(edge);
		    edge.source.edges.splice(index, 1);
		    index = edge.target.edges.indexOf(edge);
		    edge.target.edges.splice(index, 1);

		    // remove edge from owner graph manager's inter-graph edge list

		    if (!(edge.source.owner != null && edge.source.owner.getGraphManager() != null)) {
		      throw "Edge owner graph or owner graph manager is null!";
		    }
		    if (edge.source.owner.getGraphManager().edges.indexOf(edge) == -1) {
		      throw "Not in owner graph manager's edge list!";
		    }

		    var index = edge.source.owner.getGraphManager().edges.indexOf(edge);
		    edge.source.owner.getGraphManager().edges.splice(index, 1);
		  }
		};

		LGraphManager.prototype.updateBounds = function () {
		  this.rootGraph.updateBounds(true);
		};

		LGraphManager.prototype.getGraphs = function () {
		  return this.graphs;
		};

		LGraphManager.prototype.getAllNodes = function () {
		  if (this.allNodes == null) {
		    var nodeList = [];
		    var graphs = this.getGraphs();
		    var s = graphs.length;
		    for (var i = 0; i < s; i++) {
		      nodeList = nodeList.concat(graphs[i].getNodes());
		    }
		    this.allNodes = nodeList;
		  }
		  return this.allNodes;
		};

		LGraphManager.prototype.resetAllNodes = function () {
		  this.allNodes = null;
		};

		LGraphManager.prototype.resetAllEdges = function () {
		  this.allEdges = null;
		};

		LGraphManager.prototype.resetAllNodesToApplyGravitation = function () {
		  this.allNodesToApplyGravitation = null;
		};

		LGraphManager.prototype.getAllEdges = function () {
		  if (this.allEdges == null) {
		    var edgeList = [];
		    var graphs = this.getGraphs();
		    graphs.length;
		    for (var i = 0; i < graphs.length; i++) {
		      edgeList = edgeList.concat(graphs[i].getEdges());
		    }

		    edgeList = edgeList.concat(this.edges);

		    this.allEdges = edgeList;
		  }
		  return this.allEdges;
		};

		LGraphManager.prototype.getAllNodesToApplyGravitation = function () {
		  return this.allNodesToApplyGravitation;
		};

		LGraphManager.prototype.setAllNodesToApplyGravitation = function (nodeList) {
		  if (this.allNodesToApplyGravitation != null) {
		    throw "assert failed";
		  }

		  this.allNodesToApplyGravitation = nodeList;
		};

		LGraphManager.prototype.getRoot = function () {
		  return this.rootGraph;
		};

		LGraphManager.prototype.setRootGraph = function (graph) {
		  if (graph.getGraphManager() != this) {
		    throw "Root not in this graph mgr!";
		  }

		  this.rootGraph = graph;
		  // root graph must have a root node associated with it for convenience
		  if (graph.parent == null) {
		    graph.parent = this.layout.newNode("Root node");
		  }
		};

		LGraphManager.prototype.getLayout = function () {
		  return this.layout;
		};

		LGraphManager.prototype.isOneAncestorOfOther = function (firstNode, secondNode) {
		  if (!(firstNode != null && secondNode != null)) {
		    throw "assert failed";
		  }

		  if (firstNode == secondNode) {
		    return true;
		  }
		  // Is second node an ancestor of the first one?
		  var ownerGraph = firstNode.getOwner();
		  var parentNode;

		  do {
		    parentNode = ownerGraph.getParent();

		    if (parentNode == null) {
		      break;
		    }

		    if (parentNode == secondNode) {
		      return true;
		    }

		    ownerGraph = parentNode.getOwner();
		    if (ownerGraph == null) {
		      break;
		    }
		  } while (true);
		  // Is first node an ancestor of the second one?
		  ownerGraph = secondNode.getOwner();

		  do {
		    parentNode = ownerGraph.getParent();

		    if (parentNode == null) {
		      break;
		    }

		    if (parentNode == firstNode) {
		      return true;
		    }

		    ownerGraph = parentNode.getOwner();
		    if (ownerGraph == null) {
		      break;
		    }
		  } while (true);

		  return false;
		};

		LGraphManager.prototype.calcLowestCommonAncestors = function () {
		  var edge;
		  var sourceNode;
		  var targetNode;
		  var sourceAncestorGraph;
		  var targetAncestorGraph;

		  var edges = this.getAllEdges();
		  var s = edges.length;
		  for (var i = 0; i < s; i++) {
		    edge = edges[i];

		    sourceNode = edge.source;
		    targetNode = edge.target;
		    edge.lca = null;
		    edge.sourceInLca = sourceNode;
		    edge.targetInLca = targetNode;

		    if (sourceNode == targetNode) {
		      edge.lca = sourceNode.getOwner();
		      continue;
		    }

		    sourceAncestorGraph = sourceNode.getOwner();

		    while (edge.lca == null) {
		      edge.targetInLca = targetNode;
		      targetAncestorGraph = targetNode.getOwner();

		      while (edge.lca == null) {
		        if (targetAncestorGraph == sourceAncestorGraph) {
		          edge.lca = targetAncestorGraph;
		          break;
		        }

		        if (targetAncestorGraph == this.rootGraph) {
		          break;
		        }

		        if (edge.lca != null) {
		          throw "assert failed";
		        }
		        edge.targetInLca = targetAncestorGraph.getParent();
		        targetAncestorGraph = edge.targetInLca.getOwner();
		      }

		      if (sourceAncestorGraph == this.rootGraph) {
		        break;
		      }

		      if (edge.lca == null) {
		        edge.sourceInLca = sourceAncestorGraph.getParent();
		        sourceAncestorGraph = edge.sourceInLca.getOwner();
		      }
		    }

		    if (edge.lca == null) {
		      throw "assert failed";
		    }
		  }
		};

		LGraphManager.prototype.calcLowestCommonAncestor = function (firstNode, secondNode) {
		  if (firstNode == secondNode) {
		    return firstNode.getOwner();
		  }
		  var firstOwnerGraph = firstNode.getOwner();

		  do {
		    if (firstOwnerGraph == null) {
		      break;
		    }
		    var secondOwnerGraph = secondNode.getOwner();

		    do {
		      if (secondOwnerGraph == null) {
		        break;
		      }

		      if (secondOwnerGraph == firstOwnerGraph) {
		        return secondOwnerGraph;
		      }
		      secondOwnerGraph = secondOwnerGraph.getParent().getOwner();
		    } while (true);

		    firstOwnerGraph = firstOwnerGraph.getParent().getOwner();
		  } while (true);

		  return firstOwnerGraph;
		};

		LGraphManager.prototype.calcInclusionTreeDepths = function (graph, depth) {
		  if (graph == null && depth == null) {
		    graph = this.rootGraph;
		    depth = 1;
		  }
		  var node;

		  var nodes = graph.getNodes();
		  var s = nodes.length;
		  for (var i = 0; i < s; i++) {
		    node = nodes[i];
		    node.inclusionTreeDepth = depth;

		    if (node.child != null) {
		      this.calcInclusionTreeDepths(node.child, depth + 1);
		    }
		  }
		};

		LGraphManager.prototype.includesInvalidEdge = function () {
		  var edge;

		  var s = this.edges.length;
		  for (var i = 0; i < s; i++) {
		    edge = this.edges[i];

		    if (this.isOneAncestorOfOther(edge.source, edge.target)) {
		      return true;
		    }
		  }
		  return false;
		};

		module.exports = LGraphManager;

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


		var LayoutConstants = __webpack_require__(0);

		function FDLayoutConstants() {}

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

		FDLayoutConstants.MAX_ITERATIONS = 2500;

		FDLayoutConstants.DEFAULT_EDGE_LENGTH = 50;
		FDLayoutConstants.DEFAULT_SPRING_STRENGTH = 0.45;
		FDLayoutConstants.DEFAULT_REPULSION_STRENGTH = 4500.0;
		FDLayoutConstants.DEFAULT_GRAVITY_STRENGTH = 0.4;
		FDLayoutConstants.DEFAULT_COMPOUND_GRAVITY_STRENGTH = 1.0;
		FDLayoutConstants.DEFAULT_GRAVITY_RANGE_FACTOR = 3.8;
		FDLayoutConstants.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR = 1.5;
		FDLayoutConstants.DEFAULT_USE_SMART_IDEAL_EDGE_LENGTH_CALCULATION = true;
		FDLayoutConstants.DEFAULT_USE_SMART_REPULSION_RANGE_CALCULATION = true;
		FDLayoutConstants.DEFAULT_COOLING_FACTOR_INCREMENTAL = 0.3;
		FDLayoutConstants.COOLING_ADAPTATION_FACTOR = 0.33;
		FDLayoutConstants.ADAPTATION_LOWER_NODE_LIMIT = 1000;
		FDLayoutConstants.ADAPTATION_UPPER_NODE_LIMIT = 5000;
		FDLayoutConstants.MAX_NODE_DISPLACEMENT_INCREMENTAL = 100.0;
		FDLayoutConstants.MAX_NODE_DISPLACEMENT = FDLayoutConstants.MAX_NODE_DISPLACEMENT_INCREMENTAL * 3;
		FDLayoutConstants.MIN_REPULSION_DIST = FDLayoutConstants.DEFAULT_EDGE_LENGTH / 10.0;
		FDLayoutConstants.CONVERGENCE_CHECK_PERIOD = 100;
		FDLayoutConstants.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR = 0.1;
		FDLayoutConstants.MIN_EDGE_LENGTH = 1;
		FDLayoutConstants.GRID_CALCULATION_CHECK_PERIOD = 10;

		module.exports = FDLayoutConstants;

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


		/**
		 * This class maintains a list of static geometry related utility methods.
		 *
		 *
		 * Copyright: i-Vis Research Group, Bilkent University, 2007 - present
		 */

		var Point = __webpack_require__(12);

		function IGeometry() {}

		/**
		 * This method calculates *half* the amount in x and y directions of the two
		 * input rectangles needed to separate them keeping their respective
		 * positioning, and returns the result in the input array. An input
		 * separation buffer added to the amount in both directions. We assume that
		 * the two rectangles do intersect.
		 */
		IGeometry.calcSeparationAmount = function (rectA, rectB, overlapAmount, separationBuffer) {
		  if (!rectA.intersects(rectB)) {
		    throw "assert failed";
		  }

		  var directions = new Array(2);

		  this.decideDirectionsForOverlappingNodes(rectA, rectB, directions);

		  overlapAmount[0] = Math.min(rectA.getRight(), rectB.getRight()) - Math.max(rectA.x, rectB.x);
		  overlapAmount[1] = Math.min(rectA.getBottom(), rectB.getBottom()) - Math.max(rectA.y, rectB.y);

		  // update the overlapping amounts for the following cases:
		  if (rectA.getX() <= rectB.getX() && rectA.getRight() >= rectB.getRight()) {
		    /* Case x.1:
		    *
		    * rectA
		    * 	|                       |
		    * 	|        _________      |
		    * 	|        |       |      |
		    * 	|________|_______|______|
		    * 			 |       |
		    *           |       |
		    *        rectB
		    */
		    overlapAmount[0] += Math.min(rectB.getX() - rectA.getX(), rectA.getRight() - rectB.getRight());
		  } else if (rectB.getX() <= rectA.getX() && rectB.getRight() >= rectA.getRight()) {
		    /* Case x.2:
		    *
		    * rectB
		    * 	|                       |
		    * 	|        _________      |
		    * 	|        |       |      |
		    * 	|________|_______|______|
		    * 			 |       |
		    *           |       |
		    *        rectA
		    */
		    overlapAmount[0] += Math.min(rectA.getX() - rectB.getX(), rectB.getRight() - rectA.getRight());
		  }
		  if (rectA.getY() <= rectB.getY() && rectA.getBottom() >= rectB.getBottom()) {
		    /* Case y.1:
		     *          ________ rectA
		     *         |
		     *         |
		     *   ______|____  rectB
		     *         |    |
		     *         |    |
		     *   ______|____|
		     *         |
		     *         |
		     *         |________
		     *
		     */
		    overlapAmount[1] += Math.min(rectB.getY() - rectA.getY(), rectA.getBottom() - rectB.getBottom());
		  } else if (rectB.getY() <= rectA.getY() && rectB.getBottom() >= rectA.getBottom()) {
		    /* Case y.2:
		    *          ________ rectB
		    *         |
		    *         |
		    *   ______|____  rectA
		    *         |    |
		    *         |    |
		    *   ______|____|
		    *         |
		    *         |
		    *         |________
		    *
		    */
		    overlapAmount[1] += Math.min(rectA.getY() - rectB.getY(), rectB.getBottom() - rectA.getBottom());
		  }

		  // find slope of the line passes two centers
		  var slope = Math.abs((rectB.getCenterY() - rectA.getCenterY()) / (rectB.getCenterX() - rectA.getCenterX()));
		  // if centers are overlapped
		  if (rectB.getCenterY() === rectA.getCenterY() && rectB.getCenterX() === rectA.getCenterX()) {
		    // assume the slope is 1 (45 degree)
		    slope = 1.0;
		  }

		  var moveByY = slope * overlapAmount[0];
		  var moveByX = overlapAmount[1] / slope;
		  if (overlapAmount[0] < moveByX) {
		    moveByX = overlapAmount[0];
		  } else {
		    moveByY = overlapAmount[1];
		  }
		  // return half the amount so that if each rectangle is moved by these
		  // amounts in opposite directions, overlap will be resolved
		  overlapAmount[0] = -1 * directions[0] * (moveByX / 2 + separationBuffer);
		  overlapAmount[1] = -1 * directions[1] * (moveByY / 2 + separationBuffer);
		};

		/**
		 * This method decides the separation direction of overlapping nodes
		 *
		 * if directions[0] = -1, then rectA goes left
		 * if directions[0] = 1,  then rectA goes right
		 * if directions[1] = -1, then rectA goes up
		 * if directions[1] = 1,  then rectA goes down
		 */
		IGeometry.decideDirectionsForOverlappingNodes = function (rectA, rectB, directions) {
		  if (rectA.getCenterX() < rectB.getCenterX()) {
		    directions[0] = -1;
		  } else {
		    directions[0] = 1;
		  }

		  if (rectA.getCenterY() < rectB.getCenterY()) {
		    directions[1] = -1;
		  } else {
		    directions[1] = 1;
		  }
		};

		/**
		 * This method calculates the intersection (clipping) points of the two
		 * input rectangles with line segment defined by the centers of these two
		 * rectangles. The clipping points are saved in the input double array and
		 * whether or not the two rectangles overlap is returned.
		 */
		IGeometry.getIntersection2 = function (rectA, rectB, result) {
		  //result[0-1] will contain clipPoint of rectA, result[2-3] will contain clipPoint of rectB
		  var p1x = rectA.getCenterX();
		  var p1y = rectA.getCenterY();
		  var p2x = rectB.getCenterX();
		  var p2y = rectB.getCenterY();

		  //if two rectangles intersect, then clipping points are centers
		  if (rectA.intersects(rectB)) {
		    result[0] = p1x;
		    result[1] = p1y;
		    result[2] = p2x;
		    result[3] = p2y;
		    return true;
		  }
		  //variables for rectA
		  var topLeftAx = rectA.getX();
		  var topLeftAy = rectA.getY();
		  var topRightAx = rectA.getRight();
		  var bottomLeftAx = rectA.getX();
		  var bottomLeftAy = rectA.getBottom();
		  var bottomRightAx = rectA.getRight();
		  var halfWidthA = rectA.getWidthHalf();
		  var halfHeightA = rectA.getHeightHalf();
		  //variables for rectB
		  var topLeftBx = rectB.getX();
		  var topLeftBy = rectB.getY();
		  var topRightBx = rectB.getRight();
		  var bottomLeftBx = rectB.getX();
		  var bottomLeftBy = rectB.getBottom();
		  var bottomRightBx = rectB.getRight();
		  var halfWidthB = rectB.getWidthHalf();
		  var halfHeightB = rectB.getHeightHalf();

		  //flag whether clipping points are found
		  var clipPointAFound = false;
		  var clipPointBFound = false;

		  // line is vertical
		  if (p1x === p2x) {
		    if (p1y > p2y) {
		      result[0] = p1x;
		      result[1] = topLeftAy;
		      result[2] = p2x;
		      result[3] = bottomLeftBy;
		      return false;
		    } else if (p1y < p2y) {
		      result[0] = p1x;
		      result[1] = bottomLeftAy;
		      result[2] = p2x;
		      result[3] = topLeftBy;
		      return false;
		    } else ;
		  }
		  // line is horizontal
		  else if (p1y === p2y) {
		      if (p1x > p2x) {
		        result[0] = topLeftAx;
		        result[1] = p1y;
		        result[2] = topRightBx;
		        result[3] = p2y;
		        return false;
		      } else if (p1x < p2x) {
		        result[0] = topRightAx;
		        result[1] = p1y;
		        result[2] = topLeftBx;
		        result[3] = p2y;
		        return false;
		      } else ;
		    } else {
		      //slopes of rectA's and rectB's diagonals
		      var slopeA = rectA.height / rectA.width;
		      var slopeB = rectB.height / rectB.width;

		      //slope of line between center of rectA and center of rectB
		      var slopePrime = (p2y - p1y) / (p2x - p1x);
		      var cardinalDirectionA = void 0;
		      var cardinalDirectionB = void 0;
		      var tempPointAx = void 0;
		      var tempPointAy = void 0;
		      var tempPointBx = void 0;
		      var tempPointBy = void 0;

		      //determine whether clipping point is the corner of nodeA
		      if (-slopeA === slopePrime) {
		        if (p1x > p2x) {
		          result[0] = bottomLeftAx;
		          result[1] = bottomLeftAy;
		          clipPointAFound = true;
		        } else {
		          result[0] = topRightAx;
		          result[1] = topLeftAy;
		          clipPointAFound = true;
		        }
		      } else if (slopeA === slopePrime) {
		        if (p1x > p2x) {
		          result[0] = topLeftAx;
		          result[1] = topLeftAy;
		          clipPointAFound = true;
		        } else {
		          result[0] = bottomRightAx;
		          result[1] = bottomLeftAy;
		          clipPointAFound = true;
		        }
		      }

		      //determine whether clipping point is the corner of nodeB
		      if (-slopeB === slopePrime) {
		        if (p2x > p1x) {
		          result[2] = bottomLeftBx;
		          result[3] = bottomLeftBy;
		          clipPointBFound = true;
		        } else {
		          result[2] = topRightBx;
		          result[3] = topLeftBy;
		          clipPointBFound = true;
		        }
		      } else if (slopeB === slopePrime) {
		        if (p2x > p1x) {
		          result[2] = topLeftBx;
		          result[3] = topLeftBy;
		          clipPointBFound = true;
		        } else {
		          result[2] = bottomRightBx;
		          result[3] = bottomLeftBy;
		          clipPointBFound = true;
		        }
		      }

		      //if both clipping points are corners
		      if (clipPointAFound && clipPointBFound) {
		        return false;
		      }

		      //determine Cardinal Direction of rectangles
		      if (p1x > p2x) {
		        if (p1y > p2y) {
		          cardinalDirectionA = this.getCardinalDirection(slopeA, slopePrime, 4);
		          cardinalDirectionB = this.getCardinalDirection(slopeB, slopePrime, 2);
		        } else {
		          cardinalDirectionA = this.getCardinalDirection(-slopeA, slopePrime, 3);
		          cardinalDirectionB = this.getCardinalDirection(-slopeB, slopePrime, 1);
		        }
		      } else {
		        if (p1y > p2y) {
		          cardinalDirectionA = this.getCardinalDirection(-slopeA, slopePrime, 1);
		          cardinalDirectionB = this.getCardinalDirection(-slopeB, slopePrime, 3);
		        } else {
		          cardinalDirectionA = this.getCardinalDirection(slopeA, slopePrime, 2);
		          cardinalDirectionB = this.getCardinalDirection(slopeB, slopePrime, 4);
		        }
		      }
		      //calculate clipping Point if it is not found before
		      if (!clipPointAFound) {
		        switch (cardinalDirectionA) {
		          case 1:
		            tempPointAy = topLeftAy;
		            tempPointAx = p1x + -halfHeightA / slopePrime;
		            result[0] = tempPointAx;
		            result[1] = tempPointAy;
		            break;
		          case 2:
		            tempPointAx = bottomRightAx;
		            tempPointAy = p1y + halfWidthA * slopePrime;
		            result[0] = tempPointAx;
		            result[1] = tempPointAy;
		            break;
		          case 3:
		            tempPointAy = bottomLeftAy;
		            tempPointAx = p1x + halfHeightA / slopePrime;
		            result[0] = tempPointAx;
		            result[1] = tempPointAy;
		            break;
		          case 4:
		            tempPointAx = bottomLeftAx;
		            tempPointAy = p1y + -halfWidthA * slopePrime;
		            result[0] = tempPointAx;
		            result[1] = tempPointAy;
		            break;
		        }
		      }
		      if (!clipPointBFound) {
		        switch (cardinalDirectionB) {
		          case 1:
		            tempPointBy = topLeftBy;
		            tempPointBx = p2x + -halfHeightB / slopePrime;
		            result[2] = tempPointBx;
		            result[3] = tempPointBy;
		            break;
		          case 2:
		            tempPointBx = bottomRightBx;
		            tempPointBy = p2y + halfWidthB * slopePrime;
		            result[2] = tempPointBx;
		            result[3] = tempPointBy;
		            break;
		          case 3:
		            tempPointBy = bottomLeftBy;
		            tempPointBx = p2x + halfHeightB / slopePrime;
		            result[2] = tempPointBx;
		            result[3] = tempPointBy;
		            break;
		          case 4:
		            tempPointBx = bottomLeftBx;
		            tempPointBy = p2y + -halfWidthB * slopePrime;
		            result[2] = tempPointBx;
		            result[3] = tempPointBy;
		            break;
		        }
		      }
		    }
		  return false;
		};

		/**
		 * This method returns in which cardinal direction does input point stays
		 * 1: North
		 * 2: East
		 * 3: South
		 * 4: West
		 */
		IGeometry.getCardinalDirection = function (slope, slopePrime, line) {
		  if (slope > slopePrime) {
		    return line;
		  } else {
		    return 1 + line % 4;
		  }
		};

		/**
		 * This method calculates the intersection of the two lines defined by
		 * point pairs (s1,s2) and (f1,f2).
		 */
		IGeometry.getIntersection = function (s1, s2, f1, f2) {
		  if (f2 == null) {
		    return this.getIntersection2(s1, s2, f1);
		  }

		  var x1 = s1.x;
		  var y1 = s1.y;
		  var x2 = s2.x;
		  var y2 = s2.y;
		  var x3 = f1.x;
		  var y3 = f1.y;
		  var x4 = f2.x;
		  var y4 = f2.y;
		  var x = void 0,
		      y = void 0; // intersection point
		  var a1 = void 0,
		      a2 = void 0,
		      b1 = void 0,
		      b2 = void 0,
		      c1 = void 0,
		      c2 = void 0; // coefficients of line eqns.
		  var denom = void 0;

		  a1 = y2 - y1;
		  b1 = x1 - x2;
		  c1 = x2 * y1 - x1 * y2; // { a1*x + b1*y + c1 = 0 is line 1 }

		  a2 = y4 - y3;
		  b2 = x3 - x4;
		  c2 = x4 * y3 - x3 * y4; // { a2*x + b2*y + c2 = 0 is line 2 }

		  denom = a1 * b2 - a2 * b1;

		  if (denom === 0) {
		    return null;
		  }

		  x = (b1 * c2 - b2 * c1) / denom;
		  y = (a2 * c1 - a1 * c2) / denom;

		  return new Point(x, y);
		};

		/**
		 * This method finds and returns the angle of the vector from the + x-axis
		 * in clockwise direction (compatible w/ Java coordinate system!).
		 */
		IGeometry.angleOfVector = function (Cx, Cy, Nx, Ny) {
		  var C_angle = void 0;

		  if (Cx !== Nx) {
		    C_angle = Math.atan((Ny - Cy) / (Nx - Cx));

		    if (Nx < Cx) {
		      C_angle += Math.PI;
		    } else if (Ny < Cy) {
		      C_angle += this.TWO_PI;
		    }
		  } else if (Ny < Cy) {
		    C_angle = this.ONE_AND_HALF_PI; // 270 degrees
		  } else {
		    C_angle = this.HALF_PI; // 90 degrees
		  }

		  return C_angle;
		};

		/**
		 * This method checks whether the given two line segments (one with point
		 * p1 and p2, the other with point p3 and p4) intersect at a point other
		 * than these points.
		 */
		IGeometry.doIntersect = function (p1, p2, p3, p4) {
		  var a = p1.x;
		  var b = p1.y;
		  var c = p2.x;
		  var d = p2.y;
		  var p = p3.x;
		  var q = p3.y;
		  var r = p4.x;
		  var s = p4.y;
		  var det = (c - a) * (s - q) - (r - p) * (d - b);

		  if (det === 0) {
		    return false;
		  } else {
		    var lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / det;
		    var gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / det;
		    return 0 < lambda && lambda < 1 && 0 < gamma && gamma < 1;
		  }
		};

		// -----------------------------------------------------------------------------
		// Section: Class Constants
		// -----------------------------------------------------------------------------
		/**
		 * Some useful pre-calculated constants
		 */
		IGeometry.HALF_PI = 0.5 * Math.PI;
		IGeometry.ONE_AND_HALF_PI = 1.5 * Math.PI;
		IGeometry.TWO_PI = 2.0 * Math.PI;
		IGeometry.THREE_PI = 3.0 * Math.PI;

		module.exports = IGeometry;

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


		function IMath() {}

		/**
		 * This method returns the sign of the input value.
		 */
		IMath.sign = function (value) {
		  if (value > 0) {
		    return 1;
		  } else if (value < 0) {
		    return -1;
		  } else {
		    return 0;
		  }
		};

		IMath.floor = function (value) {
		  return value < 0 ? Math.ceil(value) : Math.floor(value);
		};

		IMath.ceil = function (value) {
		  return value < 0 ? Math.floor(value) : Math.ceil(value);
		};

		module.exports = IMath;

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


		function Integer() {}

		Integer.MAX_VALUE = 2147483647;
		Integer.MIN_VALUE = -2147483648;

		module.exports = Integer;

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


		var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

		function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

		var nodeFrom = function nodeFrom(value) {
		  return { value: value, next: null, prev: null };
		};

		var add = function add(prev, node, next, list) {
		  if (prev !== null) {
		    prev.next = node;
		  } else {
		    list.head = node;
		  }

		  if (next !== null) {
		    next.prev = node;
		  } else {
		    list.tail = node;
		  }

		  node.prev = prev;
		  node.next = next;

		  list.length++;

		  return node;
		};

		var _remove = function _remove(node, list) {
		  var prev = node.prev,
		      next = node.next;


		  if (prev !== null) {
		    prev.next = next;
		  } else {
		    list.head = next;
		  }

		  if (next !== null) {
		    next.prev = prev;
		  } else {
		    list.tail = prev;
		  }

		  node.prev = node.next = null;

		  list.length--;

		  return node;
		};

		var LinkedList = function () {
		  function LinkedList(vals) {
		    var _this = this;

		    _classCallCheck(this, LinkedList);

		    this.length = 0;
		    this.head = null;
		    this.tail = null;

		    if (vals != null) {
		      vals.forEach(function (v) {
		        return _this.push(v);
		      });
		    }
		  }

		  _createClass(LinkedList, [{
		    key: "size",
		    value: function size() {
		      return this.length;
		    }
		  }, {
		    key: "insertBefore",
		    value: function insertBefore(val, otherNode) {
		      return add(otherNode.prev, nodeFrom(val), otherNode, this);
		    }
		  }, {
		    key: "insertAfter",
		    value: function insertAfter(val, otherNode) {
		      return add(otherNode, nodeFrom(val), otherNode.next, this);
		    }
		  }, {
		    key: "insertNodeBefore",
		    value: function insertNodeBefore(newNode, otherNode) {
		      return add(otherNode.prev, newNode, otherNode, this);
		    }
		  }, {
		    key: "insertNodeAfter",
		    value: function insertNodeAfter(newNode, otherNode) {
		      return add(otherNode, newNode, otherNode.next, this);
		    }
		  }, {
		    key: "push",
		    value: function push(val) {
		      return add(this.tail, nodeFrom(val), null, this);
		    }
		  }, {
		    key: "unshift",
		    value: function unshift(val) {
		      return add(null, nodeFrom(val), this.head, this);
		    }
		  }, {
		    key: "remove",
		    value: function remove(node) {
		      return _remove(node, this);
		    }
		  }, {
		    key: "pop",
		    value: function pop() {
		      return _remove(this.tail, this).value;
		    }
		  }, {
		    key: "popNode",
		    value: function popNode() {
		      return _remove(this.tail, this);
		    }
		  }, {
		    key: "shift",
		    value: function shift() {
		      return _remove(this.head, this).value;
		    }
		  }, {
		    key: "shiftNode",
		    value: function shiftNode() {
		      return _remove(this.head, this);
		    }
		  }, {
		    key: "get_object_at",
		    value: function get_object_at(index) {
		      if (index <= this.length()) {
		        var i = 1;
		        var current = this.head;
		        while (i < index) {
		          current = current.next;
		          i++;
		        }
		        return current.value;
		      }
		    }
		  }, {
		    key: "set_object_at",
		    value: function set_object_at(index, value) {
		      if (index <= this.length()) {
		        var i = 1;
		        var current = this.head;
		        while (i < index) {
		          current = current.next;
		          i++;
		        }
		        current.value = value;
		      }
		    }
		  }]);

		  return LinkedList;
		}();

		module.exports = LinkedList;

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


		/*
		 *This class is the javascript implementation of the Point.java class in jdk
		 */
		function Point(x, y, p) {
		  this.x = null;
		  this.y = null;
		  if (x == null && y == null && p == null) {
		    this.x = 0;
		    this.y = 0;
		  } else if (typeof x == 'number' && typeof y == 'number' && p == null) {
		    this.x = x;
		    this.y = y;
		  } else if (x.constructor.name == 'Point' && y == null && p == null) {
		    p = x;
		    this.x = p.x;
		    this.y = p.y;
		  }
		}

		Point.prototype.getX = function () {
		  return this.x;
		};

		Point.prototype.getY = function () {
		  return this.y;
		};

		Point.prototype.getLocation = function () {
		  return new Point(this.x, this.y);
		};

		Point.prototype.setLocation = function (x, y, p) {
		  if (x.constructor.name == 'Point' && y == null && p == null) {
		    p = x;
		    this.setLocation(p.x, p.y);
		  } else if (typeof x == 'number' && typeof y == 'number' && p == null) {
		    //if both parameters are integer just move (x,y) location
		    if (parseInt(x) == x && parseInt(y) == y) {
		      this.move(x, y);
		    } else {
		      this.x = Math.floor(x + 0.5);
		      this.y = Math.floor(y + 0.5);
		    }
		  }
		};

		Point.prototype.move = function (x, y) {
		  this.x = x;
		  this.y = y;
		};

		Point.prototype.translate = function (dx, dy) {
		  this.x += dx;
		  this.y += dy;
		};

		Point.prototype.equals = function (obj) {
		  if (obj.constructor.name == "Point") {
		    var pt = obj;
		    return this.x == pt.x && this.y == pt.y;
		  }
		  return this == obj;
		};

		Point.prototype.toString = function () {
		  return new Point().constructor.name + "[x=" + this.x + ",y=" + this.y + "]";
		};

		module.exports = Point;

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


		function RectangleD(x, y, width, height) {
		  this.x = 0;
		  this.y = 0;
		  this.width = 0;
		  this.height = 0;

		  if (x != null && y != null && width != null && height != null) {
		    this.x = x;
		    this.y = y;
		    this.width = width;
		    this.height = height;
		  }
		}

		RectangleD.prototype.getX = function () {
		  return this.x;
		};

		RectangleD.prototype.setX = function (x) {
		  this.x = x;
		};

		RectangleD.prototype.getY = function () {
		  return this.y;
		};

		RectangleD.prototype.setY = function (y) {
		  this.y = y;
		};

		RectangleD.prototype.getWidth = function () {
		  return this.width;
		};

		RectangleD.prototype.setWidth = function (width) {
		  this.width = width;
		};

		RectangleD.prototype.getHeight = function () {
		  return this.height;
		};

		RectangleD.prototype.setHeight = function (height) {
		  this.height = height;
		};

		RectangleD.prototype.getRight = function () {
		  return this.x + this.width;
		};

		RectangleD.prototype.getBottom = function () {
		  return this.y + this.height;
		};

		RectangleD.prototype.intersects = function (a) {
		  if (this.getRight() < a.x) {
		    return false;
		  }

		  if (this.getBottom() < a.y) {
		    return false;
		  }

		  if (a.getRight() < this.x) {
		    return false;
		  }

		  if (a.getBottom() < this.y) {
		    return false;
		  }

		  return true;
		};

		RectangleD.prototype.getCenterX = function () {
		  return this.x + this.width / 2;
		};

		RectangleD.prototype.getMinX = function () {
		  return this.getX();
		};

		RectangleD.prototype.getMaxX = function () {
		  return this.getX() + this.width;
		};

		RectangleD.prototype.getCenterY = function () {
		  return this.y + this.height / 2;
		};

		RectangleD.prototype.getMinY = function () {
		  return this.getY();
		};

		RectangleD.prototype.getMaxY = function () {
		  return this.getY() + this.height;
		};

		RectangleD.prototype.getWidthHalf = function () {
		  return this.width / 2;
		};

		RectangleD.prototype.getHeightHalf = function () {
		  return this.height / 2;
		};

		module.exports = RectangleD;

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


		var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

		function UniqueIDGeneretor() {}

		UniqueIDGeneretor.lastID = 0;

		UniqueIDGeneretor.createID = function (obj) {
		  if (UniqueIDGeneretor.isPrimitive(obj)) {
		    return obj;
		  }
		  if (obj.uniqueID != null) {
		    return obj.uniqueID;
		  }
		  obj.uniqueID = UniqueIDGeneretor.getString();
		  UniqueIDGeneretor.lastID++;
		  return obj.uniqueID;
		};

		UniqueIDGeneretor.getString = function (id) {
		  if (id == null) id = UniqueIDGeneretor.lastID;
		  return "Object#" + id + "";
		};

		UniqueIDGeneretor.isPrimitive = function (arg) {
		  var type = typeof arg === "undefined" ? "undefined" : _typeof(arg);
		  return arg == null || type != "object" && type != "function";
		};

		module.exports = UniqueIDGeneretor;

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


		function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

		var LayoutConstants = __webpack_require__(0);
		var LGraphManager = __webpack_require__(6);
		var LNode = __webpack_require__(3);
		var LEdge = __webpack_require__(1);
		var LGraph = __webpack_require__(5);
		var PointD = __webpack_require__(4);
		var Transform = __webpack_require__(17);
		var Emitter = __webpack_require__(27);

		function Layout(isRemoteUse) {
		  Emitter.call(this);

		  //Layout Quality: 0:draft, 1:default, 2:proof
		  this.layoutQuality = LayoutConstants.QUALITY;
		  //Whether layout should create bendpoints as needed or not
		  this.createBendsAsNeeded = LayoutConstants.DEFAULT_CREATE_BENDS_AS_NEEDED;
		  //Whether layout should be incremental or not
		  this.incremental = LayoutConstants.DEFAULT_INCREMENTAL;
		  //Whether we animate from before to after layout node positions
		  this.animationOnLayout = LayoutConstants.DEFAULT_ANIMATION_ON_LAYOUT;
		  //Whether we animate the layout process or not
		  this.animationDuringLayout = LayoutConstants.DEFAULT_ANIMATION_DURING_LAYOUT;
		  //Number iterations that should be done between two successive animations
		  this.animationPeriod = LayoutConstants.DEFAULT_ANIMATION_PERIOD;
		  /**
		   * Whether or not leaf nodes (non-compound nodes) are of uniform sizes. When
		   * they are, both spring and repulsion forces between two leaf nodes can be
		   * calculated without the expensive clipping point calculations, resulting
		   * in major speed-up.
		   */
		  this.uniformLeafNodeSizes = LayoutConstants.DEFAULT_UNIFORM_LEAF_NODE_SIZES;
		  /**
		   * This is used for creation of bendpoints by using dummy nodes and edges.
		   * Maps an LEdge to its dummy bendpoint path.
		   */
		  this.edgeToDummyNodes = new Map();
		  this.graphManager = new LGraphManager(this);
		  this.isLayoutFinished = false;
		  this.isSubLayout = false;
		  this.isRemoteUse = false;

		  if (isRemoteUse != null) {
		    this.isRemoteUse = isRemoteUse;
		  }
		}

		Layout.RANDOM_SEED = 1;

		Layout.prototype = Object.create(Emitter.prototype);

		Layout.prototype.getGraphManager = function () {
		  return this.graphManager;
		};

		Layout.prototype.getAllNodes = function () {
		  return this.graphManager.getAllNodes();
		};

		Layout.prototype.getAllEdges = function () {
		  return this.graphManager.getAllEdges();
		};

		Layout.prototype.getAllNodesToApplyGravitation = function () {
		  return this.graphManager.getAllNodesToApplyGravitation();
		};

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

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

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

		Layout.prototype.newEdge = function (vEdge) {
		  return new LEdge(null, null, vEdge);
		};

		Layout.prototype.checkLayoutSuccess = function () {
		  return this.graphManager.getRoot() == null || this.graphManager.getRoot().getNodes().length == 0 || this.graphManager.includesInvalidEdge();
		};

		Layout.prototype.runLayout = function () {
		  this.isLayoutFinished = false;

		  if (this.tilingPreLayout) {
		    this.tilingPreLayout();
		  }

		  this.initParameters();
		  var isLayoutSuccessfull;

		  if (this.checkLayoutSuccess()) {
		    isLayoutSuccessfull = false;
		  } else {
		    isLayoutSuccessfull = this.layout();
		  }

		  if (LayoutConstants.ANIMATE === 'during') {
		    // If this is a 'during' layout animation. Layout is not finished yet. 
		    // We need to perform these in index.js when layout is really finished.
		    return false;
		  }

		  if (isLayoutSuccessfull) {
		    if (!this.isSubLayout) {
		      this.doPostLayout();
		    }
		  }

		  if (this.tilingPostLayout) {
		    this.tilingPostLayout();
		  }

		  this.isLayoutFinished = true;

		  return isLayoutSuccessfull;
		};

		/**
		 * This method performs the operations required after layout.
		 */
		Layout.prototype.doPostLayout = function () {
		  //assert !isSubLayout : "Should not be called on sub-layout!";
		  // Propagate geometric changes to v-level objects
		  if (!this.incremental) {
		    this.transform();
		  }
		  this.update();
		};

		/**
		 * This method updates the geometry of the target graph according to
		 * calculated layout.
		 */
		Layout.prototype.update2 = function () {
		  // update bend points
		  if (this.createBendsAsNeeded) {
		    this.createBendpointsFromDummyNodes();

		    // reset all edges, since the topology has changed
		    this.graphManager.resetAllEdges();
		  }

		  // perform edge, node and root updates if layout is not called
		  // remotely
		  if (!this.isRemoteUse) {
		    var allEdges = this.graphManager.getAllEdges();
		    for (var i = 0; i < allEdges.length; i++) {
		      allEdges[i];
		      //      this.update(edge);
		    }
		    var nodes = this.graphManager.getRoot().getNodes();
		    for (var i = 0; i < nodes.length; i++) {
		      nodes[i];
		      //      this.update(node);
		    }

		    // update root graph
		    this.update(this.graphManager.getRoot());
		  }
		};

		Layout.prototype.update = function (obj) {
		  if (obj == null) {
		    this.update2();
		  } else if (obj instanceof LNode) {
		    var node = obj;
		    if (node.getChild() != null) {
		      // since node is compound, recursively update child nodes
		      var nodes = node.getChild().getNodes();
		      for (var i = 0; i < nodes.length; i++) {
		        update(nodes[i]);
		      }
		    }

		    // if the l-level node is associated with a v-level graph object,
		    // then it is assumed that the v-level node implements the
		    // interface Updatable.
		    if (node.vGraphObject != null) {
		      // cast to Updatable without any type check
		      var vNode = node.vGraphObject;

		      // call the update method of the interface
		      vNode.update(node);
		    }
		  } else if (obj instanceof LEdge) {
		    var edge = obj;
		    // if the l-level edge is associated with a v-level graph object,
		    // then it is assumed that the v-level edge implements the
		    // interface Updatable.

		    if (edge.vGraphObject != null) {
		      // cast to Updatable without any type check
		      var vEdge = edge.vGraphObject;

		      // call the update method of the interface
		      vEdge.update(edge);
		    }
		  } else if (obj instanceof LGraph) {
		    var graph = obj;
		    // if the l-level graph is associated with a v-level graph object,
		    // then it is assumed that the v-level object implements the
		    // interface Updatable.

		    if (graph.vGraphObject != null) {
		      // cast to Updatable without any type check
		      var vGraph = graph.vGraphObject;

		      // call the update method of the interface
		      vGraph.update(graph);
		    }
		  }
		};

		/**
		 * This method is used to set all layout parameters to default values
		 * determined at compile time.
		 */
		Layout.prototype.initParameters = function () {
		  if (!this.isSubLayout) {
		    this.layoutQuality = LayoutConstants.QUALITY;
		    this.animationDuringLayout = LayoutConstants.DEFAULT_ANIMATION_DURING_LAYOUT;
		    this.animationPeriod = LayoutConstants.DEFAULT_ANIMATION_PERIOD;
		    this.animationOnLayout = LayoutConstants.DEFAULT_ANIMATION_ON_LAYOUT;
		    this.incremental = LayoutConstants.DEFAULT_INCREMENTAL;
		    this.createBendsAsNeeded = LayoutConstants.DEFAULT_CREATE_BENDS_AS_NEEDED;
		    this.uniformLeafNodeSizes = LayoutConstants.DEFAULT_UNIFORM_LEAF_NODE_SIZES;
		  }

		  if (this.animationDuringLayout) {
		    this.animationOnLayout = false;
		  }
		};

		Layout.prototype.transform = function (newLeftTop) {
		  if (newLeftTop == undefined) {
		    this.transform(new PointD(0, 0));
		  } else {
		    // create a transformation object (from Eclipse to layout). When an
		    // inverse transform is applied, we get upper-left coordinate of the
		    // drawing or the root graph at given input coordinate (some margins
		    // already included in calculation of left-top).

		    var trans = new Transform();
		    var leftTop = this.graphManager.getRoot().updateLeftTop();

		    if (leftTop != null) {
		      trans.setWorldOrgX(newLeftTop.x);
		      trans.setWorldOrgY(newLeftTop.y);

		      trans.setDeviceOrgX(leftTop.x);
		      trans.setDeviceOrgY(leftTop.y);

		      var nodes = this.getAllNodes();
		      var node;

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

		Layout.prototype.positionNodesRandomly = function (graph) {

		  if (graph == undefined) {
		    //assert !this.incremental;
		    this.positionNodesRandomly(this.getGraphManager().getRoot());
		    this.getGraphManager().getRoot().updateBounds(true);
		  } else {
		    var lNode;
		    var childGraph;

		    var nodes = graph.getNodes();
		    for (var i = 0; i < nodes.length; i++) {
		      lNode = nodes[i];
		      childGraph = lNode.getChild();

		      if (childGraph == null) {
		        lNode.scatter();
		      } else if (childGraph.getNodes().length == 0) {
		        lNode.scatter();
		      } else {
		        this.positionNodesRandomly(childGraph);
		        lNode.updateBounds();
		      }
		    }
		  }
		};

		/**
		 * This method returns a list of trees where each tree is represented as a
		 * list of l-nodes. The method returns a list of size 0 when:
		 * - The graph is not flat or
		 * - One of the component(s) of the graph is not a tree.
		 */
		Layout.prototype.getFlatForest = function () {
		  var flatForest = [];
		  var isForest = true;

		  // Quick reference for all nodes in the graph manager associated with
		  // this layout. The list should not be changed.
		  var allNodes = this.graphManager.getRoot().getNodes();

		  // First be sure that the graph is flat
		  var isFlat = true;

		  for (var i = 0; i < allNodes.length; i++) {
		    if (allNodes[i].getChild() != null) {
		      isFlat = false;
		    }
		  }

		  // Return empty forest if the graph is not flat.
		  if (!isFlat) {
		    return flatForest;
		  }

		  // Run BFS for each component of the graph.

		  var visited = new Set();
		  var toBeVisited = [];
		  var parents = new Map();
		  var unProcessedNodes = [];

		  unProcessedNodes = unProcessedNodes.concat(allNodes);

		  // Each iteration of this loop finds a component of the graph and
		  // decides whether it is a tree or not. If it is a tree, adds it to the
		  // forest and continued with the next component.

		  while (unProcessedNodes.length > 0 && isForest) {
		    toBeVisited.push(unProcessedNodes[0]);

		    // Start the BFS. Each iteration of this loop visits a node in a
		    // BFS manner.
		    while (toBeVisited.length > 0 && isForest) {
		      //pool operation
		      var currentNode = toBeVisited[0];
		      toBeVisited.splice(0, 1);
		      visited.add(currentNode);

		      // Traverse all neighbors of this node
		      var neighborEdges = currentNode.getEdges();

		      for (var i = 0; i < neighborEdges.length; i++) {
		        var currentNeighbor = neighborEdges[i].getOtherEnd(currentNode);

		        // If BFS is not growing from this neighbor.
		        if (parents.get(currentNode) != currentNeighbor) {
		          // We haven't previously visited this neighbor.
		          if (!visited.has(currentNeighbor)) {
		            toBeVisited.push(currentNeighbor);
		            parents.set(currentNeighbor, currentNode);
		          }
		          // Since we have previously visited this neighbor and
		          // this neighbor is not parent of currentNode, given
		          // graph contains a component that is not tree, hence
		          // it is not a forest.
		          else {
		              isForest = false;
		              break;
		            }
		        }
		      }
		    }

		    // The graph contains a component that is not a tree. Empty
		    // previously found trees. The method will end.
		    if (!isForest) {
		      flatForest = [];
		    }
		    // Save currently visited nodes as a tree in our forest. Reset
		    // visited and parents lists. Continue with the next component of
		    // the graph, if any.
		    else {
		        var temp = [].concat(_toConsumableArray(visited));
		        flatForest.push(temp);
		        //flatForest = flatForest.concat(temp);
		        //unProcessedNodes.removeAll(visited);
		        for (var i = 0; i < temp.length; i++) {
		          var value = temp[i];
		          var index = unProcessedNodes.indexOf(value);
		          if (index > -1) {
		            unProcessedNodes.splice(index, 1);
		          }
		        }
		        visited = new Set();
		        parents = new Map();
		      }
		  }

		  return flatForest;
		};

		/**
		 * This method creates dummy nodes (an l-level node with minimal dimensions)
		 * for the given edge (one per bendpoint). The existing l-level structure
		 * is updated accordingly.
		 */
		Layout.prototype.createDummyNodesForBendpoints = function (edge) {
		  var dummyNodes = [];
		  var prev = edge.source;

		  var graph = this.graphManager.calcLowestCommonAncestor(edge.source, edge.target);

		  for (var i = 0; i < edge.bendpoints.length; i++) {
		    // create new dummy node
		    var dummyNode = this.newNode(null);
		    dummyNode.setRect(new Point(0, 0), new Dimension(1, 1));

		    graph.add(dummyNode);

		    // create new dummy edge between prev and dummy node
		    var dummyEdge = this.newEdge(null);
		    this.graphManager.add(dummyEdge, prev, dummyNode);

		    dummyNodes.add(dummyNode);
		    prev = dummyNode;
		  }

		  var dummyEdge = this.newEdge(null);
		  this.graphManager.add(dummyEdge, prev, edge.target);

		  this.edgeToDummyNodes.set(edge, dummyNodes);

		  // remove real edge from graph manager if it is inter-graph
		  if (edge.isInterGraph()) {
		    this.graphManager.remove(edge);
		  }
		  // else, remove the edge from the current graph
		  else {
		      graph.remove(edge);
		    }

		  return dummyNodes;
		};

		/**
		 * This method creates bendpoints for edges from the dummy nodes
		 * at l-level.
		 */
		Layout.prototype.createBendpointsFromDummyNodes = function () {
		  var edges = [];
		  edges = edges.concat(this.graphManager.getAllEdges());
		  edges = [].concat(_toConsumableArray(this.edgeToDummyNodes.keys())).concat(edges);

		  for (var k = 0; k < edges.length; k++) {
		    var lEdge = edges[k];

		    if (lEdge.bendpoints.length > 0) {
		      var path = this.edgeToDummyNodes.get(lEdge);

		      for (var i = 0; i < path.length; i++) {
		        var dummyNode = path[i];
		        var p = new PointD(dummyNode.getCenterX(), dummyNode.getCenterY());

		        // update bendpoint's location according to dummy node
		        var ebp = lEdge.bendpoints.get(i);
		        ebp.x = p.x;
		        ebp.y = p.y;

		        // remove the dummy node, dummy edges incident with this
		        // dummy node is also removed (within the remove method)
		        dummyNode.getOwner().remove(dummyNode);
		      }

		      // add the real edge to graph
		      this.graphManager.add(lEdge, lEdge.source, lEdge.target);
		    }
		  }
		};

		Layout.transform = function (sliderValue, defaultValue, minDiv, maxMul) {
		  if (minDiv != undefined && maxMul != undefined) {
		    var value = defaultValue;

		    if (sliderValue <= 50) {
		      var minValue = defaultValue / minDiv;
		      value -= (defaultValue - minValue) / 50 * (50 - sliderValue);
		    } else {
		      var maxValue = defaultValue * maxMul;
		      value += (maxValue - defaultValue) / 50 * (sliderValue - 50);
		    }

		    return value;
		  } else {
		    var a, b;

		    if (sliderValue <= 50) {
		      a = 9.0 * defaultValue / 500.0;
		      b = defaultValue / 10.0;
		    } else {
		      a = 9.0 * defaultValue / 50.0;
		      b = -8 * defaultValue;
		    }

		    return a * sliderValue + b;
		  }
		};

		/**
		 * This method finds and returns the center of the given nodes, assuming
		 * that the given nodes form a tree in themselves.
		 */
		Layout.findCenterOfTree = function (nodes) {
		  var list = [];
		  list = list.concat(nodes);

		  var removedNodes = [];
		  var remainingDegrees = new Map();
		  var foundCenter = false;
		  var centerNode = null;

		  if (list.length == 1 || list.length == 2) {
		    foundCenter = true;
		    centerNode = list[0];
		  }

		  for (var i = 0; i < list.length; i++) {
		    var node = list[i];
		    var degree = node.getNeighborsList().size;
		    remainingDegrees.set(node, node.getNeighborsList().size);

		    if (degree == 1) {
		      removedNodes.push(node);
		    }
		  }

		  var tempList = [];
		  tempList = tempList.concat(removedNodes);

		  while (!foundCenter) {
		    var tempList2 = [];
		    tempList2 = tempList2.concat(tempList);
		    tempList = [];

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

		      var index = list.indexOf(node);
		      if (index >= 0) {
		        list.splice(index, 1);
		      }

		      var neighbours = node.getNeighborsList();

		      neighbours.forEach(function (neighbour) {
		        if (removedNodes.indexOf(neighbour) < 0) {
		          var otherDegree = remainingDegrees.get(neighbour);
		          var newDegree = otherDegree - 1;

		          if (newDegree == 1) {
		            tempList.push(neighbour);
		          }

		          remainingDegrees.set(neighbour, newDegree);
		        }
		      });
		    }

		    removedNodes = removedNodes.concat(tempList);

		    if (list.length == 1 || list.length == 2) {
		      foundCenter = true;
		      centerNode = list[0];
		    }
		  }

		  return centerNode;
		};

		/**
		 * During the coarsening process, this layout may be referenced by two graph managers
		 * this setter function grants access to change the currently being used graph manager
		 */
		Layout.prototype.setGraphManager = function (gm) {
		  this.graphManager = gm;
		};

		module.exports = Layout;

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


		function RandomSeed() {}
		// adapted from: https://stackoverflow.com/a/19303725
		RandomSeed.seed = 1;
		RandomSeed.x = 0;

		RandomSeed.nextDouble = function () {
		  RandomSeed.x = Math.sin(RandomSeed.seed++) * 10000;
		  return RandomSeed.x - Math.floor(RandomSeed.x);
		};

		module.exports = RandomSeed;

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


		var PointD = __webpack_require__(4);

		function Transform(x, y) {
		  this.lworldOrgX = 0.0;
		  this.lworldOrgY = 0.0;
		  this.ldeviceOrgX = 0.0;
		  this.ldeviceOrgY = 0.0;
		  this.lworldExtX = 1.0;
		  this.lworldExtY = 1.0;
		  this.ldeviceExtX = 1.0;
		  this.ldeviceExtY = 1.0;
		}

		Transform.prototype.getWorldOrgX = function () {
		  return this.lworldOrgX;
		};

		Transform.prototype.setWorldOrgX = function (wox) {
		  this.lworldOrgX = wox;
		};

		Transform.prototype.getWorldOrgY = function () {
		  return this.lworldOrgY;
		};

		Transform.prototype.setWorldOrgY = function (woy) {
		  this.lworldOrgY = woy;
		};

		Transform.prototype.getWorldExtX = function () {
		  return this.lworldExtX;
		};

		Transform.prototype.setWorldExtX = function (wex) {
		  this.lworldExtX = wex;
		};

		Transform.prototype.getWorldExtY = function () {
		  return this.lworldExtY;
		};

		Transform.prototype.setWorldExtY = function (wey) {
		  this.lworldExtY = wey;
		};

		/* Device related */

		Transform.prototype.getDeviceOrgX = function () {
		  return this.ldeviceOrgX;
		};

		Transform.prototype.setDeviceOrgX = function (dox) {
		  this.ldeviceOrgX = dox;
		};

		Transform.prototype.getDeviceOrgY = function () {
		  return this.ldeviceOrgY;
		};

		Transform.prototype.setDeviceOrgY = function (doy) {
		  this.ldeviceOrgY = doy;
		};

		Transform.prototype.getDeviceExtX = function () {
		  return this.ldeviceExtX;
		};

		Transform.prototype.setDeviceExtX = function (dex) {
		  this.ldeviceExtX = dex;
		};

		Transform.prototype.getDeviceExtY = function () {
		  return this.ldeviceExtY;
		};

		Transform.prototype.setDeviceExtY = function (dey) {
		  this.ldeviceExtY = dey;
		};

		Transform.prototype.transformX = function (x) {
		  var xDevice = 0.0;
		  var worldExtX = this.lworldExtX;
		  if (worldExtX != 0.0) {
		    xDevice = this.ldeviceOrgX + (x - this.lworldOrgX) * this.ldeviceExtX / worldExtX;
		  }

		  return xDevice;
		};

		Transform.prototype.transformY = function (y) {
		  var yDevice = 0.0;
		  var worldExtY = this.lworldExtY;
		  if (worldExtY != 0.0) {
		    yDevice = this.ldeviceOrgY + (y - this.lworldOrgY) * this.ldeviceExtY / worldExtY;
		  }

		  return yDevice;
		};

		Transform.prototype.inverseTransformX = function (x) {
		  var xWorld = 0.0;
		  var deviceExtX = this.ldeviceExtX;
		  if (deviceExtX != 0.0) {
		    xWorld = this.lworldOrgX + (x - this.ldeviceOrgX) * this.lworldExtX / deviceExtX;
		  }

		  return xWorld;
		};

		Transform.prototype.inverseTransformY = function (y) {
		  var yWorld = 0.0;
		  var deviceExtY = this.ldeviceExtY;
		  if (deviceExtY != 0.0) {
		    yWorld = this.lworldOrgY + (y - this.ldeviceOrgY) * this.lworldExtY / deviceExtY;
		  }
		  return yWorld;
		};

		Transform.prototype.inverseTransformPoint = function (inPoint) {
		  var outPoint = new PointD(this.inverseTransformX(inPoint.x), this.inverseTransformY(inPoint.y));
		  return outPoint;
		};

		module.exports = Transform;

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


		function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

		var Layout = __webpack_require__(15);
		var FDLayoutConstants = __webpack_require__(7);
		var LayoutConstants = __webpack_require__(0);
		var IGeometry = __webpack_require__(8);
		var IMath = __webpack_require__(9);

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

		  this.useSmartIdealEdgeLengthCalculation = FDLayoutConstants.DEFAULT_USE_SMART_IDEAL_EDGE_LENGTH_CALCULATION;
		  this.idealEdgeLength = FDLayoutConstants.DEFAULT_EDGE_LENGTH;
		  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;
		  this.displacementThresholdPerNode = 3.0 * FDLayoutConstants.DEFAULT_EDGE_LENGTH / 100;
		  this.coolingFactor = FDLayoutConstants.DEFAULT_COOLING_FACTOR_INCREMENTAL;
		  this.initialCoolingFactor = FDLayoutConstants.DEFAULT_COOLING_FACTOR_INCREMENTAL;
		  this.totalDisplacement = 0.0;
		  this.oldTotalDisplacement = 0.0;
		  this.maxIterations = FDLayoutConstants.MAX_ITERATIONS;
		}

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

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

		FDLayout.prototype.initParameters = function () {
		  Layout.prototype.initParameters.call(this, arguments);

		  this.totalIterations = 0;
		  this.notAnimatedIterations = 0;

		  this.useFRGridVariant = FDLayoutConstants.DEFAULT_USE_SMART_REPULSION_RANGE_CALCULATION;

		  this.grid = [];
		};

		FDLayout.prototype.calcIdealEdgeLengths = function () {
		  var edge;
		  var lcaDepth;
		  var source;
		  var target;
		  var sizeOfSourceInLca;
		  var sizeOfTargetInLca;

		  var allEdges = this.getGraphManager().getAllEdges();
		  for (var i = 0; i < allEdges.length; i++) {
		    edge = allEdges[i];

		    edge.idealLength = this.idealEdgeLength;

		    if (edge.isInterGraph) {
		      source = edge.getSource();
		      target = edge.getTarget();

		      sizeOfSourceInLca = edge.getSourceInLca().getEstimatedSize();
		      sizeOfTargetInLca = edge.getTargetInLca().getEstimatedSize();

		      if (this.useSmartIdealEdgeLengthCalculation) {
		        edge.idealLength += sizeOfSourceInLca + sizeOfTargetInLca - 2 * LayoutConstants.SIMPLE_NODE_SIZE;
		      }

		      lcaDepth = edge.getLca().getInclusionTreeDepth();

		      edge.idealLength += FDLayoutConstants.DEFAULT_EDGE_LENGTH * FDLayoutConstants.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR * (source.getInclusionTreeDepth() + target.getInclusionTreeDepth() - 2 * lcaDepth);
		    }
		  }
		};

		FDLayout.prototype.initSpringEmbedder = function () {

		  var s = this.getAllNodes().length;
		  if (this.incremental) {
		    if (s > FDLayoutConstants.ADAPTATION_LOWER_NODE_LIMIT) {
		      this.coolingFactor = Math.max(this.coolingFactor * FDLayoutConstants.COOLING_ADAPTATION_FACTOR, this.coolingFactor - (s - FDLayoutConstants.ADAPTATION_LOWER_NODE_LIMIT) / (FDLayoutConstants.ADAPTATION_UPPER_NODE_LIMIT - FDLayoutConstants.ADAPTATION_LOWER_NODE_LIMIT) * this.coolingFactor * (1 - FDLayoutConstants.COOLING_ADAPTATION_FACTOR));
		    }
		    this.maxNodeDisplacement = FDLayoutConstants.MAX_NODE_DISPLACEMENT_INCREMENTAL;
		  } else {
		    if (s > FDLayoutConstants.ADAPTATION_LOWER_NODE_LIMIT) {
		      this.coolingFactor = Math.max(FDLayoutConstants.COOLING_ADAPTATION_FACTOR, 1.0 - (s - FDLayoutConstants.ADAPTATION_LOWER_NODE_LIMIT) / (FDLayoutConstants.ADAPTATION_UPPER_NODE_LIMIT - FDLayoutConstants.ADAPTATION_LOWER_NODE_LIMIT) * (1 - FDLayoutConstants.COOLING_ADAPTATION_FACTOR));
		    } else {
		      this.coolingFactor = 1.0;
		    }
		    this.initialCoolingFactor = this.coolingFactor;
		    this.maxNodeDisplacement = FDLayoutConstants.MAX_NODE_DISPLACEMENT;
		  }

		  this.maxIterations = Math.max(this.getAllNodes().length * 5, this.maxIterations);

		  this.totalDisplacementThreshold = this.displacementThresholdPerNode * this.getAllNodes().length;

		  this.repulsionRange = this.calcRepulsionRange();
		};

		FDLayout.prototype.calcSpringForces = function () {
		  var lEdges = this.getAllEdges();
		  var edge;

		  for (var i = 0; i < lEdges.length; i++) {
		    edge = lEdges[i];

		    this.calcSpringForce(edge, edge.idealLength);
		  }
		};

		FDLayout.prototype.calcRepulsionForces = function () {
		  var gridUpdateAllowed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
		  var forceToNodeSurroundingUpdate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

		  var i, j;
		  var nodeA, nodeB;
		  var lNodes = this.getAllNodes();
		  var processedNodeSet;

		  if (this.useFRGridVariant) {
		    if (this.totalIterations % FDLayoutConstants.GRID_CALCULATION_CHECK_PERIOD == 1 && gridUpdateAllowed) {
		      this.updateGrid();
		    }

		    processedNodeSet = new Set();

		    // calculate repulsion forces between each nodes and its surrounding
		    for (i = 0; i < lNodes.length; i++) {
		      nodeA = lNodes[i];
		      this.calculateRepulsionForceOfANode(nodeA, processedNodeSet, gridUpdateAllowed, forceToNodeSurroundingUpdate);
		      processedNodeSet.add(nodeA);
		    }
		  } else {
		    for (i = 0; i < lNodes.length; i++) {
		      nodeA = lNodes[i];

		      for (j = i + 1; j < lNodes.length; j++) {
		        nodeB = lNodes[j];

		        // If both nodes are not members of the same graph, skip.
		        if (nodeA.getOwner() != nodeB.getOwner()) {
		          continue;
		        }

		        this.calcRepulsionForce(nodeA, nodeB);
		      }
		    }
		  }
		};

		FDLayout.prototype.calcGravitationalForces = function () {
		  var node;
		  var lNodes = this.getAllNodesToApplyGravitation();

		  for (var i = 0; i < lNodes.length; i++) {
		    node = lNodes[i];
		    this.calcGravitationalForce(node);
		  }
		};

		FDLayout.prototype.moveNodes = function () {
		  var lNodes = this.getAllNodes();
		  var node;

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

		FDLayout.prototype.calcSpringForce = function (edge, idealLength) {
		  var sourceNode = edge.getSource();
		  var targetNode = edge.getTarget();

		  var length;
		  var springForce;
		  var springForceX;
		  var springForceY;

		  // Update edge length
		  if (this.uniformLeafNodeSizes && sourceNode.getChild() == null && targetNode.getChild() == null) {
		    edge.updateLengthSimple();
		  } else {
		    edge.updateLength();

		    if (edge.isOverlapingSourceAndTarget) {
		      return;
		    }
		  }

		  length = edge.getLength();

		  if (length == 0) return;

		  // Calculate spring forces
		  springForce = this.springConstant * (length - idealLength);

		  // Project force onto x and y axes
		  springForceX = springForce * (edge.lengthX / length);
		  springForceY = springForce * (edge.lengthY / length);

		  // Apply forces on the end nodes
		  sourceNode.springForceX += springForceX;
		  sourceNode.springForceY += springForceY;
		  targetNode.springForceX -= springForceX;
		  targetNode.springForceY -= springForceY;
		};

		FDLayout.prototype.calcRepulsionForce = function (nodeA, nodeB) {
		  var rectA = nodeA.getRect();
		  var rectB = nodeB.getRect();
		  var overlapAmount = new Array(2);
		  var clipPoints = new Array(4);
		  var distanceX;
		  var distanceY;
		  var distanceSquared;
		  var distance;
		  var repulsionForce;
		  var repulsionForceX;
		  var repulsionForceY;

		  if (rectA.intersects(rectB)) // two nodes overlap
		    {
		      // calculate separation amount in x and y directions
		      IGeometry.calcSeparationAmount(rectA, rectB, overlapAmount, FDLayoutConstants.DEFAULT_EDGE_LENGTH / 2.0);

		      repulsionForceX = 2 * overlapAmount[0];
		      repulsionForceY = 2 * overlapAmount[1];

		      var childrenConstant = nodeA.noOfChildren * nodeB.noOfChildren / (nodeA.noOfChildren + nodeB.noOfChildren);

		      // Apply forces on the two nodes
		      nodeA.repulsionForceX -= childrenConstant * repulsionForceX;
		      nodeA.repulsionForceY -= childrenConstant * repulsionForceY;
		      nodeB.repulsionForceX += childrenConstant * repulsionForceX;
		      nodeB.repulsionForceY += childrenConstant * repulsionForceY;
		    } else // no overlap
		    {
		      // calculate distance

		      if (this.uniformLeafNodeSizes && nodeA.getChild() == null && nodeB.getChild() == null) // simply base repulsion on distance of node centers
		        {
		          distanceX = rectB.getCenterX() - rectA.getCenterX();
		          distanceY = rectB.getCenterY() - rectA.getCenterY();
		        } else // use clipping points
		        {
		          IGeometry.getIntersection(rectA, rectB, clipPoints);

		          distanceX = clipPoints[2] - clipPoints[0];
		          distanceY = clipPoints[3] - clipPoints[1];
		        }

		      // No repulsion range. FR grid variant should take care of this.
		      if (Math.abs(distanceX) < FDLayoutConstants.MIN_REPULSION_DIST) {
		        distanceX = IMath.sign(distanceX) * FDLayoutConstants.MIN_REPULSION_DIST;
		      }

		      if (Math.abs(distanceY) < FDLayoutConstants.MIN_REPULSION_DIST) {
		        distanceY = IMath.sign(distanceY) * FDLayoutConstants.MIN_REPULSION_DIST;
		      }

		      distanceSquared = distanceX * distanceX + distanceY * distanceY;
		      distance = Math.sqrt(distanceSquared);

		      repulsionForce = this.repulsionConstant * nodeA.noOfChildren * nodeB.noOfChildren / distanceSquared;

		      // Project force onto x and y axes
		      repulsionForceX = repulsionForce * distanceX / distance;
		      repulsionForceY = repulsionForce * distanceY / distance;

		      // Apply forces on the two nodes    
		      nodeA.repulsionForceX -= repulsionForceX;
		      nodeA.repulsionForceY -= repulsionForceY;
		      nodeB.repulsionForceX += repulsionForceX;
		      nodeB.repulsionForceY += repulsionForceY;
		    }
		};

		FDLayout.prototype.calcGravitationalForce = function (node) {
		  var ownerGraph;
		  var ownerCenterX;
		  var ownerCenterY;
		  var distanceX;
		  var distanceY;
		  var absDistanceX;
		  var absDistanceY;
		  var estimatedSize;
		  ownerGraph = node.getOwner();

		  ownerCenterX = (ownerGraph.getRight() + ownerGraph.getLeft()) / 2;
		  ownerCenterY = (ownerGraph.getTop() + ownerGraph.getBottom()) / 2;
		  distanceX = node.getCenterX() - ownerCenterX;
		  distanceY = node.getCenterY() - ownerCenterY;
		  absDistanceX = Math.abs(distanceX) + node.getWidth() / 2;
		  absDistanceY = Math.abs(distanceY) + node.getHeight() / 2;

		  if (node.getOwner() == this.graphManager.getRoot()) // in the root graph
		    {
		      estimatedSize = ownerGraph.getEstimatedSize() * this.gravityRangeFactor;

		      if (absDistanceX > estimatedSize || absDistanceY > estimatedSize) {
		        node.gravitationForceX = -this.gravityConstant * distanceX;
		        node.gravitationForceY = -this.gravityConstant * distanceY;
		      }
		    } else // inside a compound
		    {
		      estimatedSize = ownerGraph.getEstimatedSize() * this.compoundGravityRangeFactor;

		      if (absDistanceX > estimatedSize || absDistanceY > estimatedSize) {
		        node.gravitationForceX = -this.gravityConstant * distanceX * this.compoundGravityConstant;
		        node.gravitationForceY = -this.gravityConstant * distanceY * this.compoundGravityConstant;
		      }
		    }
		};

		FDLayout.prototype.isConverged = function () {
		  var converged;
		  var oscilating = false;

		  if (this.totalIterations > this.maxIterations / 3) {
		    oscilating = Math.abs(this.totalDisplacement - this.oldTotalDisplacement) < 2;
		  }

		  converged = this.totalDisplacement < this.totalDisplacementThreshold;

		  this.oldTotalDisplacement = this.totalDisplacement;

		  return converged || oscilating;
		};

		FDLayout.prototype.animate = function () {
		  if (this.animationDuringLayout && !this.isSubLayout) {
		    if (this.notAnimatedIterations == this.animationPeriod) {
		      this.update();
		      this.notAnimatedIterations = 0;
		    } else {
		      this.notAnimatedIterations++;
		    }
		  }
		};

		//This method calculates the number of children (weight) for all nodes
		FDLayout.prototype.calcNoOfChildrenForAllNodes = function () {
		  var node;
		  var allNodes = this.graphManager.getAllNodes();

		  for (var i = 0; i < allNodes.length; i++) {
		    node = allNodes[i];
		    node.noOfChildren = node.getNoOfChildren();
		  }
		};

		// -----------------------------------------------------------------------------
		// Section: FR-Grid Variant Repulsion Force Calculation
		// -----------------------------------------------------------------------------

		FDLayout.prototype.calcGrid = function (graph) {

		  var sizeX = 0;
		  var sizeY = 0;

		  sizeX = parseInt(Math.ceil((graph.getRight() - graph.getLeft()) / this.repulsionRange));
		  sizeY = parseInt(Math.ceil((graph.getBottom() - graph.getTop()) / this.repulsionRange));

		  var grid = new Array(sizeX);

		  for (var i = 0; i < sizeX; i++) {
		    grid[i] = new Array(sizeY);
		  }

		  for (var i = 0; i < sizeX; i++) {
		    for (var j = 0; j < sizeY; j++) {
		      grid[i][j] = new Array();
		    }
		  }

		  return grid;
		};

		FDLayout.prototype.addNodeToGrid = function (v, left, top) {

		  var startX = 0;
		  var finishX = 0;
		  var startY = 0;
		  var finishY = 0;

		  startX = parseInt(Math.floor((v.getRect().x - left) / this.repulsionRange));
		  finishX = parseInt(Math.floor((v.getRect().width + v.getRect().x - left) / this.repulsionRange));
		  startY = parseInt(Math.floor((v.getRect().y - top) / this.repulsionRange));
		  finishY = parseInt(Math.floor((v.getRect().height + v.getRect().y - top) / this.repulsionRange));

		  for (var i = startX; i <= finishX; i++) {
		    for (var j = startY; j <= finishY; j++) {
		      this.grid[i][j].push(v);
		      v.setGridCoordinates(startX, finishX, startY, finishY);
		    }
		  }
		};

		FDLayout.prototype.updateGrid = function () {
		  var i;
		  var nodeA;
		  var lNodes = this.getAllNodes();

		  this.grid = this.calcGrid(this.graphManager.getRoot());

		  // put all nodes to proper grid cells
		  for (i = 0; i < lNodes.length; i++) {
		    nodeA = lNodes[i];
		    this.addNodeToGrid(nodeA, this.graphManager.getRoot().getLeft(), this.graphManager.getRoot().getTop());
		  }
		};

		FDLayout.prototype.calculateRepulsionForceOfANode = function (nodeA, processedNodeSet, gridUpdateAllowed, forceToNodeSurroundingUpdate) {

		  if (this.totalIterations % FDLayoutConstants.GRID_CALCULATION_CHECK_PERIOD == 1 && gridUpdateAllowed || forceToNodeSurroundingUpdate) {
		    var surrounding = new Set();
		    nodeA.surrounding = new Array();
		    var nodeB;
		    var grid = this.grid;

		    for (var i = nodeA.startX - 1; i < nodeA.finishX + 2; i++) {
		      for (var j = nodeA.startY - 1; j < nodeA.finishY + 2; j++) {
		        if (!(i < 0 || j < 0 || i >= grid.length || j >= grid[0].length)) {
		          for (var k = 0; k < grid[i][j].length; k++) {
		            nodeB = grid[i][j][k];

		            // If both nodes are not members of the same graph, 
		            // or both nodes are the same, skip.
		            if (nodeA.getOwner() != nodeB.getOwner() || nodeA == nodeB) {
		              continue;
		            }

		            // check if the repulsion force between
		            // nodeA and nodeB has already been calculated
		            if (!processedNodeSet.has(nodeB) && !surrounding.has(nodeB)) {
		              var distanceX = Math.abs(nodeA.getCenterX() - nodeB.getCenterX()) - (nodeA.getWidth() / 2 + nodeB.getWidth() / 2);
		              var distanceY = Math.abs(nodeA.getCenterY() - nodeB.getCenterY()) - (nodeA.getHeight() / 2 + nodeB.getHeight() / 2);

		              // if the distance between nodeA and nodeB 
		              // is less then calculation range
		              if (distanceX <= this.repulsionRange && distanceY <= this.repulsionRange) {
		                //then add nodeB to surrounding of nodeA
		                surrounding.add(nodeB);
		              }
		            }
		          }
		        }
		      }
		    }

		    nodeA.surrounding = [].concat(_toConsumableArray(surrounding));
		  }
		  for (i = 0; i < nodeA.surrounding.length; i++) {
		    this.calcRepulsionForce(nodeA, nodeA.surrounding[i]);
		  }
		};

		FDLayout.prototype.calcRepulsionRange = function () {
		  return 0.0;
		};

		module.exports = FDLayout;

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


		var LEdge = __webpack_require__(1);
		var FDLayoutConstants = __webpack_require__(7);

		function FDLayoutEdge(source, target, vEdge) {
		  LEdge.call(this, source, target, vEdge);
		  this.idealLength = FDLayoutConstants.DEFAULT_EDGE_LENGTH;
		}

		FDLayoutEdge.prototype = Object.create(LEdge.prototype);

		for (var prop in LEdge) {
		  FDLayoutEdge[prop] = LEdge[prop];
		}

		module.exports = FDLayoutEdge;

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


		var LNode = __webpack_require__(3);

		function FDLayoutNode(gm, loc, size, vNode) {
		  // alternative constructor is handled inside LNode
		  LNode.call(this, gm, loc, size, vNode);
		  //Spring, repulsion and gravitational forces acting on this node
		  this.springForceX = 0;
		  this.springForceY = 0;
		  this.repulsionForceX = 0;
		  this.repulsionForceY = 0;
		  this.gravitationForceX = 0;
		  this.gravitationForceY = 0;
		  //Amount by which this node is to be moved in this iteration
		  this.displacementX = 0;
		  this.displacementY = 0;

		  //Start and finish grid coordinates that this node is fallen into
		  this.startX = 0;
		  this.finishX = 0;
		  this.startY = 0;
		  this.finishY = 0;

		  //Geometric neighbors of this node
		  this.surrounding = [];
		}

		FDLayoutNode.prototype = Object.create(LNode.prototype);

		for (var prop in LNode) {
		  FDLayoutNode[prop] = LNode[prop];
		}

		FDLayoutNode.prototype.setGridCoordinates = function (_startX, _finishX, _startY, _finishY) {
		  this.startX = _startX;
		  this.finishX = _finishX;
		  this.startY = _startY;
		  this.finishY = _finishY;
		};

		module.exports = FDLayoutNode;

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


		function DimensionD(width, height) {
		  this.width = 0;
		  this.height = 0;
		  if (width !== null && height !== null) {
		    this.height = height;
		    this.width = width;
		  }
		}

		DimensionD.prototype.getWidth = function () {
		  return this.width;
		};

		DimensionD.prototype.setWidth = function (width) {
		  this.width = width;
		};

		DimensionD.prototype.getHeight = function () {
		  return this.height;
		};

		DimensionD.prototype.setHeight = function (height) {
		  this.height = height;
		};

		module.exports = DimensionD;

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


		var UniqueIDGeneretor = __webpack_require__(14);

		function HashMap() {
		  this.map = {};
		  this.keys = [];
		}

		HashMap.prototype.put = function (key, value) {
		  var theId = UniqueIDGeneretor.createID(key);
		  if (!this.contains(theId)) {
		    this.map[theId] = value;
		    this.keys.push(key);
		  }
		};

		HashMap.prototype.contains = function (key) {
		  UniqueIDGeneretor.createID(key);
		  return this.map[key] != null;
		};

		HashMap.prototype.get = function (key) {
		  var theId = UniqueIDGeneretor.createID(key);
		  return this.map[theId];
		};

		HashMap.prototype.keySet = function () {
		  return this.keys;
		};

		module.exports = HashMap;

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


		var UniqueIDGeneretor = __webpack_require__(14);

		function HashSet() {
		  this.set = {};
		}

		HashSet.prototype.add = function (obj) {
		  var theId = UniqueIDGeneretor.createID(obj);
		  if (!this.contains(theId)) this.set[theId] = obj;
		};

		HashSet.prototype.remove = function (obj) {
		  delete this.set[UniqueIDGeneretor.createID(obj)];
		};

		HashSet.prototype.clear = function () {
		  this.set = {};
		};

		HashSet.prototype.contains = function (obj) {
		  return this.set[UniqueIDGeneretor.createID(obj)] == obj;
		};

		HashSet.prototype.isEmpty = function () {
		  return this.size() === 0;
		};

		HashSet.prototype.size = function () {
		  return Object.keys(this.set).length;
		};

		//concats this.set to the given list
		HashSet.prototype.addAllTo = function (list) {
		  var keys = Object.keys(this.set);
		  var length = keys.length;
		  for (var i = 0; i < length; i++) {
		    list.push(this.set[keys[i]]);
		  }
		};

		HashSet.prototype.size = function () {
		  return Object.keys(this.set).length;
		};

		HashSet.prototype.addAll = function (list) {
		  var s = list.length;
		  for (var i = 0; i < s; i++) {
		    var v = list[i];
		    this.add(v);
		  }
		};

		module.exports = HashSet;

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


		var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

		function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

		/**
		 * A classic Quicksort algorithm with Hoare's partition
		 * - Works also on LinkedList objects
		 *
		 * Copyright: i-Vis Research Group, Bilkent University, 2007 - present
		 */

		var LinkedList = __webpack_require__(11);

		var Quicksort = function () {
		    function Quicksort(A, compareFunction) {
		        _classCallCheck(this, Quicksort);

		        if (compareFunction !== null || compareFunction !== undefined) this.compareFunction = this._defaultCompareFunction;

		        var length = void 0;
		        if (A instanceof LinkedList) length = A.size();else length = A.length;

		        this._quicksort(A, 0, length - 1);
		    }

		    _createClass(Quicksort, [{
		        key: '_quicksort',
		        value: function _quicksort(A, p, r) {
		            if (p < r) {
		                var q = this._partition(A, p, r);
		                this._quicksort(A, p, q);
		                this._quicksort(A, q + 1, r);
		            }
		        }
		    }, {
		        key: '_partition',
		        value: function _partition(A, p, r) {
		            var x = this._get(A, p);
		            var i = p;
		            var j = r;
		            while (true) {
		                while (this.compareFunction(x, this._get(A, j))) {
		                    j--;
		                }while (this.compareFunction(this._get(A, i), x)) {
		                    i++;
		                }if (i < j) {
		                    this._swap(A, i, j);
		                    i++;
		                    j--;
		                } else return j;
		            }
		        }
		    }, {
		        key: '_get',
		        value: function _get(object, index) {
		            if (object instanceof LinkedList) return object.get_object_at(index);else return object[index];
		        }
		    }, {
		        key: '_set',
		        value: function _set(object, index, value) {
		            if (object instanceof LinkedList) object.set_object_at(index, value);else object[index] = value;
		        }
		    }, {
		        key: '_swap',
		        value: function _swap(A, i, j) {
		            var temp = this._get(A, i);
		            this._set(A, i, this._get(A, j));
		            this._set(A, j, temp);
		        }
		    }, {
		        key: '_defaultCompareFunction',
		        value: function _defaultCompareFunction(a, b) {
		            return b > a;
		        }
		    }]);

		    return Quicksort;
		}();

		module.exports = Quicksort;

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


		var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

		function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

		/**
		 *   Needleman-Wunsch algorithm is an procedure to compute the optimal global alignment of two string
		 *   sequences by S.B.Needleman and C.D.Wunsch (1970).
		 *
		 *   Aside from the inputs, you can assign the scores for,
		 *   - Match: The two characters at the current index are same.
		 *   - Mismatch: The two characters at the current index are different.
		 *   - Insertion/Deletion(gaps): The best alignment involves one letter aligning to a gap in the other string.
		 */

		var NeedlemanWunsch = function () {
		    function NeedlemanWunsch(sequence1, sequence2) {
		        var match_score = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
		        var mismatch_penalty = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : -1;
		        var gap_penalty = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1;

		        _classCallCheck(this, NeedlemanWunsch);

		        this.sequence1 = sequence1;
		        this.sequence2 = sequence2;
		        this.match_score = match_score;
		        this.mismatch_penalty = mismatch_penalty;
		        this.gap_penalty = gap_penalty;

		        // Just the remove redundancy
		        this.iMax = sequence1.length + 1;
		        this.jMax = sequence2.length + 1;

		        // Grid matrix of scores
		        this.grid = new Array(this.iMax);
		        for (var i = 0; i < this.iMax; i++) {
		            this.grid[i] = new Array(this.jMax);

		            for (var j = 0; j < this.jMax; j++) {
		                this.grid[i][j] = 0;
		            }
		        }

		        // Traceback matrix (2D array, each cell is an array of boolean values for [`Diag`, `Up`, `Left`] positions)
		        this.tracebackGrid = new Array(this.iMax);
		        for (var _i = 0; _i < this.iMax; _i++) {
		            this.tracebackGrid[_i] = new Array(this.jMax);

		            for (var _j = 0; _j < this.jMax; _j++) {
		                this.tracebackGrid[_i][_j] = [null, null, null];
		            }
		        }

		        // The aligned sequences (return multiple possibilities)
		        this.alignments = [];

		        // Final alignment score
		        this.score = -1;

		        // Calculate scores and tracebacks
		        this.computeGrids();
		    }

		    _createClass(NeedlemanWunsch, [{
		        key: "getScore",
		        value: function getScore() {
		            return this.score;
		        }
		    }, {
		        key: "getAlignments",
		        value: function getAlignments() {
		            return this.alignments;
		        }

		        // Main dynamic programming procedure

		    }, {
		        key: "computeGrids",
		        value: function computeGrids() {
		            // Fill in the first row
		            for (var j = 1; j < this.jMax; j++) {
		                this.grid[0][j] = this.grid[0][j - 1] + this.gap_penalty;
		                this.tracebackGrid[0][j] = [false, false, true];
		            }

		            // Fill in the first column
		            for (var i = 1; i < this.iMax; i++) {
		                this.grid[i][0] = this.grid[i - 1][0] + this.gap_penalty;
		                this.tracebackGrid[i][0] = [false, true, false];
		            }

		            // Fill the rest of the grid
		            for (var _i2 = 1; _i2 < this.iMax; _i2++) {
		                for (var _j2 = 1; _j2 < this.jMax; _j2++) {
		                    // Find the max score(s) among [`Diag`, `Up`, `Left`]
		                    var diag = void 0;
		                    if (this.sequence1[_i2 - 1] === this.sequence2[_j2 - 1]) diag = this.grid[_i2 - 1][_j2 - 1] + this.match_score;else diag = this.grid[_i2 - 1][_j2 - 1] + this.mismatch_penalty;

		                    var up = this.grid[_i2 - 1][_j2] + this.gap_penalty;
		                    var left = this.grid[_i2][_j2 - 1] + this.gap_penalty;

		                    // If there exists multiple max values, capture them for multiple paths
		                    var maxOf = [diag, up, left];
		                    var indices = this.arrayAllMaxIndexes(maxOf);

		                    // Update Grids
		                    this.grid[_i2][_j2] = maxOf[indices[0]];
		                    this.tracebackGrid[_i2][_j2] = [indices.includes(0), indices.includes(1), indices.includes(2)];
		                }
		            }

		            // Update alignment score
		            this.score = this.grid[this.iMax - 1][this.jMax - 1];
		        }

		        // Gets all possible valid sequence combinations

		    }, {
		        key: "alignmentTraceback",
		        value: function alignmentTraceback() {
		            var inProcessAlignments = [];

		            inProcessAlignments.push({ pos: [this.sequence1.length, this.sequence2.length],
		                seq1: "",
		                seq2: ""
		            });

		            while (inProcessAlignments[0]) {
		                var current = inProcessAlignments[0];
		                var directions = this.tracebackGrid[current.pos[0]][current.pos[1]];

		                if (directions[0]) {
		                    inProcessAlignments.push({ pos: [current.pos[0] - 1, current.pos[1] - 1],
		                        seq1: this.sequence1[current.pos[0] - 1] + current.seq1,
		                        seq2: this.sequence2[current.pos[1] - 1] + current.seq2
		                    });
		                }
		                if (directions[1]) {
		                    inProcessAlignments.push({ pos: [current.pos[0] - 1, current.pos[1]],
		                        seq1: this.sequence1[current.pos[0] - 1] + current.seq1,
		                        seq2: '-' + current.seq2
		                    });
		                }
		                if (directions[2]) {
		                    inProcessAlignments.push({ pos: [current.pos[0], current.pos[1] - 1],
		                        seq1: '-' + current.seq1,
		                        seq2: this.sequence2[current.pos[1] - 1] + current.seq2
		                    });
		                }

		                if (current.pos[0] === 0 && current.pos[1] === 0) this.alignments.push({ sequence1: current.seq1,
		                    sequence2: current.seq2
		                });

		                inProcessAlignments.shift();
		            }

		            return this.alignments;
		        }

		        // Helper Functions

		    }, {
		        key: "getAllIndexes",
		        value: function getAllIndexes(arr, val) {
		            var indexes = [],
		                i = -1;
		            while ((i = arr.indexOf(val, i + 1)) !== -1) {
		                indexes.push(i);
		            }
		            return indexes;
		        }
		    }, {
		        key: "arrayAllMaxIndexes",
		        value: function arrayAllMaxIndexes(array) {
		            return this.getAllIndexes(array, Math.max.apply(null, array));
		        }
		    }]);

		    return NeedlemanWunsch;
		}();

		module.exports = NeedlemanWunsch;

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


		var layoutBase = function layoutBase() {
		  return;
		};

		layoutBase.FDLayout = __webpack_require__(18);
		layoutBase.FDLayoutConstants = __webpack_require__(7);
		layoutBase.FDLayoutEdge = __webpack_require__(19);
		layoutBase.FDLayoutNode = __webpack_require__(20);
		layoutBase.DimensionD = __webpack_require__(21);
		layoutBase.HashMap = __webpack_require__(22);
		layoutBase.HashSet = __webpack_require__(23);
		layoutBase.IGeometry = __webpack_require__(8);
		layoutBase.IMath = __webpack_require__(9);
		layoutBase.Integer = __webpack_require__(10);
		layoutBase.Point = __webpack_require__(12);
		layoutBase.PointD = __webpack_require__(4);
		layoutBase.RandomSeed = __webpack_require__(16);
		layoutBase.RectangleD = __webpack_require__(13);
		layoutBase.Transform = __webpack_require__(17);
		layoutBase.UniqueIDGeneretor = __webpack_require__(14);
		layoutBase.Quicksort = __webpack_require__(24);
		layoutBase.LinkedList = __webpack_require__(11);
		layoutBase.LGraphObject = __webpack_require__(2);
		layoutBase.LGraph = __webpack_require__(5);
		layoutBase.LEdge = __webpack_require__(1);
		layoutBase.LGraphManager = __webpack_require__(6);
		layoutBase.LNode = __webpack_require__(3);
		layoutBase.Layout = __webpack_require__(15);
		layoutBase.LayoutConstants = __webpack_require__(0);
		layoutBase.NeedlemanWunsch = __webpack_require__(25);

		module.exports = layoutBase;

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


		function Emitter() {
		  this.listeners = [];
		}

		var p = Emitter.prototype;

		p.addListener = function (event, callback) {
		  this.listeners.push({
		    event: event,
		    callback: callback
		  });
		};

		p.removeListener = function (event, callback) {
		  for (var i = this.listeners.length; i >= 0; i--) {
		    var l = this.listeners[i];

		    if (l.event === event && l.callback === callback) {
		      this.listeners.splice(i, 1);
		    }
		  }
		};

		p.emit = function (event, data) {
		  for (var i = 0; i < this.listeners.length; i++) {
		    var l = this.listeners[i];

		    if (event === l.event) {
		      l.callback(data);
		    }
		  }
		};

		module.exports = Emitter;

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

var coseBase = coseBase$1.exports;

var hasRequiredCoseBase;

function requireCoseBase () {
	if (hasRequiredCoseBase) return coseBase$1.exports;
	hasRequiredCoseBase = 1;
	(function (module, exports$1) {
		(function webpackUniversalModuleDefinition(root, factory) {
			module.exports = factory(requireLayoutBase());
		})(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$1, name, getter) {
		/******/ 		if(!__webpack_require__.o(exports$1, name)) {
		/******/ 			Object.defineProperty(exports$1, 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$1) {

		module.exports = __WEBPACK_EXTERNAL_MODULE_0__;

		/***/ }),
		/* 1 */
		/***/ (function(module, exports$1, __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$1, __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$1, __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$1, __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$1, __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$1, __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$1, __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));
	return coseBase$1.exports;
}

var cytoscapeCoseBilkent = cytoscapeCoseBilkent$1.exports;

var hasRequiredCytoscapeCoseBilkent;

function requireCytoscapeCoseBilkent () {
	if (hasRequiredCytoscapeCoseBilkent) return cytoscapeCoseBilkent$1.exports;
	hasRequiredCytoscapeCoseBilkent = 1;
	(function (module, exports$1) {
		(function webpackUniversalModuleDefinition(root, factory) {
			module.exports = factory(requireCoseBase());
		})(cytoscapeCoseBilkent, 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$1, name, getter) {
		/******/ 		if(!__webpack_require__.o(exports$1, name)) {
		/******/ 			Object.defineProperty(exports$1, 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 = 1);
		/******/ })
		/************************************************************************/
		/******/ ([
		/* 0 */
		/***/ (function(module, exports$1) {

		module.exports = __WEBPACK_EXTERNAL_MODULE_0__;

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


		var LayoutConstants = __webpack_require__(0).layoutBase.LayoutConstants;
		var FDLayoutConstants = __webpack_require__(0).layoutBase.FDLayoutConstants;
		var CoSEConstants = __webpack_require__(0).CoSEConstants;
		var CoSELayout = __webpack_require__(0).CoSELayout;
		var CoSENode = __webpack_require__(0).CoSENode;
		var PointD = __webpack_require__(0).layoutBase.PointD;
		var DimensionD = __webpack_require__(0).layoutBase.DimensionD;

		var defaults = {
		  // Called on `layoutready`
		  ready: function ready() {},
		  // Called on `layoutstop`
		  stop: function stop() {},
		  // 'draft', 'default' or 'proof" 
		  // - 'draft' fast cooling rate 
		  // - 'default' moderate cooling rate 
		  // - "proof" slow cooling rate
		  quality: 'default',
		  // include labels in node dimensions
		  nodeDimensionsIncludeLabels: false,
		  // number of ticks per frame; higher is faster but more jerky
		  refresh: 30,
		  // Whether to fit the network view after when done
		  fit: true,
		  // Padding on fit
		  padding: 10,
		  // Whether to enable incremental mode
		  randomize: true,
		  // Node repulsion (non overlapping) multiplier
		  nodeRepulsion: 4500,
		  // Ideal edge (non nested) length
		  idealEdgeLength: 50,
		  // Divisor to compute edge forces
		  edgeElasticity: 0.45,
		  // Nesting factor (multiplier) to compute ideal edge length for nested edges
		  nestingFactor: 0.1,
		  // Gravity force (constant)
		  gravity: 0.25,
		  // Maximum number of iterations to perform
		  numIter: 2500,
		  // For enabling tiling
		  tile: true,
		  // Type of layout animation. The option set is {'during', 'end', false}
		  animate: 'end',
		  // Duration for animate:end
		  animationDuration: 500,
		  // Represents the amount of the vertical space to put between the zero degree members during the tiling operation(can also be a function)
		  tilingPaddingVertical: 10,
		  // Represents the amount of the horizontal space to put between the zero degree members during the tiling operation(can also be a function)
		  tilingPaddingHorizontal: 10,
		  // Gravity range (constant) for compounds
		  gravityRangeCompound: 1.5,
		  // Gravity force (constant) for compounds
		  gravityCompound: 1.0,
		  // Gravity range (constant)
		  gravityRange: 3.8,
		  // Initial cooling factor for incremental layout
		  initialEnergyOnIncremental: 0.5
		};

		function extend(defaults, options) {
		  var obj = {};

		  for (var i in defaults) {
		    obj[i] = defaults[i];
		  }

		  for (var i in options) {
		    obj[i] = options[i];
		  }

		  return obj;
		}
		function _CoSELayout(_options) {
		  this.options = extend(defaults, _options);
		  getUserOptions(this.options);
		}

		var getUserOptions = function getUserOptions(options) {
		  if (options.nodeRepulsion != null) CoSEConstants.DEFAULT_REPULSION_STRENGTH = FDLayoutConstants.DEFAULT_REPULSION_STRENGTH = options.nodeRepulsion;
		  if (options.idealEdgeLength != null) CoSEConstants.DEFAULT_EDGE_LENGTH = FDLayoutConstants.DEFAULT_EDGE_LENGTH = options.idealEdgeLength;
		  if (options.edgeElasticity != null) CoSEConstants.DEFAULT_SPRING_STRENGTH = FDLayoutConstants.DEFAULT_SPRING_STRENGTH = options.edgeElasticity;
		  if (options.nestingFactor != null) CoSEConstants.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR = FDLayoutConstants.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR = options.nestingFactor;
		  if (options.gravity != null) CoSEConstants.DEFAULT_GRAVITY_STRENGTH = FDLayoutConstants.DEFAULT_GRAVITY_STRENGTH = options.gravity;
		  if (options.numIter != null) CoSEConstants.MAX_ITERATIONS = FDLayoutConstants.MAX_ITERATIONS = options.numIter;
		  if (options.gravityRange != null) CoSEConstants.DEFAULT_GRAVITY_RANGE_FACTOR = FDLayoutConstants.DEFAULT_GRAVITY_RANGE_FACTOR = options.gravityRange;
		  if (options.gravityCompound != null) CoSEConstants.DEFAULT_COMPOUND_GRAVITY_STRENGTH = FDLayoutConstants.DEFAULT_COMPOUND_GRAVITY_STRENGTH = options.gravityCompound;
		  if (options.gravityRangeCompound != null) CoSEConstants.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR = FDLayoutConstants.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR = options.gravityRangeCompound;
		  if (options.initialEnergyOnIncremental != null) CoSEConstants.DEFAULT_COOLING_FACTOR_INCREMENTAL = FDLayoutConstants.DEFAULT_COOLING_FACTOR_INCREMENTAL = options.initialEnergyOnIncremental;

		  if (options.quality == 'draft') LayoutConstants.QUALITY = 0;else if (options.quality == 'proof') LayoutConstants.QUALITY = 2;else LayoutConstants.QUALITY = 1;

		  CoSEConstants.NODE_DIMENSIONS_INCLUDE_LABELS = FDLayoutConstants.NODE_DIMENSIONS_INCLUDE_LABELS = LayoutConstants.NODE_DIMENSIONS_INCLUDE_LABELS = options.nodeDimensionsIncludeLabels;
		  CoSEConstants.DEFAULT_INCREMENTAL = FDLayoutConstants.DEFAULT_INCREMENTAL = LayoutConstants.DEFAULT_INCREMENTAL = !options.randomize;
		  CoSEConstants.ANIMATE = FDLayoutConstants.ANIMATE = LayoutConstants.ANIMATE = options.animate;
		  CoSEConstants.TILE = options.tile;
		  CoSEConstants.TILING_PADDING_VERTICAL = typeof options.tilingPaddingVertical === 'function' ? options.tilingPaddingVertical.call() : options.tilingPaddingVertical;
		  CoSEConstants.TILING_PADDING_HORIZONTAL = typeof options.tilingPaddingHorizontal === 'function' ? options.tilingPaddingHorizontal.call() : options.tilingPaddingHorizontal;
		};

		_CoSELayout.prototype.run = function () {
		  var ready;
		  var frameId;
		  var options = this.options;
		  this.idToLNode = {};
		  var layout = this.layout = new CoSELayout();
		  var self = this;

		  self.stopped = false;

		  this.cy = this.options.cy;

		  this.cy.trigger({ type: 'layoutstart', layout: this });

		  var gm = layout.newGraphManager();
		  this.gm = gm;

		  var nodes = this.options.eles.nodes();
		  var edges = this.options.eles.edges();

		  this.root = gm.addRoot();
		  this.processChildrenList(this.root, this.getTopMostNodes(nodes), layout);

		  for (var i = 0; i < edges.length; i++) {
		    var edge = edges[i];
		    var sourceNode = this.idToLNode[edge.data("source")];
		    var targetNode = this.idToLNode[edge.data("target")];
		    if (sourceNode !== targetNode && sourceNode.getEdgesBetween(targetNode).length == 0) {
		      var e1 = gm.add(layout.newEdge(), sourceNode, targetNode);
		      e1.id = edge.id();
		    }
		  }

		  var getPositions = function getPositions(ele, i) {
		    if (typeof ele === "number") {
		      ele = i;
		    }
		    var theId = ele.data('id');
		    var lNode = self.idToLNode[theId];

		    return {
		      x: lNode.getRect().getCenterX(),
		      y: lNode.getRect().getCenterY()
		    };
		  };

		  /*
		   * Reposition nodes in iterations animatedly
		   */
		  var iterateAnimated = function iterateAnimated() {
		    // Thigs to perform after nodes are repositioned on screen
		    var afterReposition = function afterReposition() {
		      if (options.fit) {
		        options.cy.fit(options.eles, options.padding);
		      }

		      if (!ready) {
		        ready = true;
		        self.cy.one('layoutready', options.ready);
		        self.cy.trigger({ type: 'layoutready', layout: self });
		      }
		    };

		    var ticksPerFrame = self.options.refresh;
		    var isDone;

		    for (var i = 0; i < ticksPerFrame && !isDone; i++) {
		      isDone = self.stopped || self.layout.tick();
		    }

		    // If layout is done
		    if (isDone) {
		      // If the layout is not a sublayout and it is successful perform post layout.
		      if (layout.checkLayoutSuccess() && !layout.isSubLayout) {
		        layout.doPostLayout();
		      }

		      // If layout has a tilingPostLayout function property call it.
		      if (layout.tilingPostLayout) {
		        layout.tilingPostLayout();
		      }

		      layout.isLayoutFinished = true;

		      self.options.eles.nodes().positions(getPositions);

		      afterReposition();

		      // trigger layoutstop when the layout stops (e.g. finishes)
		      self.cy.one('layoutstop', self.options.stop);
		      self.cy.trigger({ type: 'layoutstop', layout: self });

		      if (frameId) {
		        cancelAnimationFrame(frameId);
		      }

		      ready = false;
		      return;
		    }

		    var animationData = self.layout.getPositionsData(); // Get positions of layout nodes note that all nodes may not be layout nodes because of tiling

		    // Position nodes, for the nodes whose id does not included in data (because they are removed from their parents and included in dummy compounds)
		    // use position of their ancestors or dummy ancestors
		    options.eles.nodes().positions(function (ele, i) {
		      if (typeof ele === "number") {
		        ele = i;
		      }
		      // If ele is a compound node, then its position will be defined by its children
		      if (!ele.isParent()) {
		        var theId = ele.id();
		        var pNode = animationData[theId];
		        var temp = ele;
		        // If pNode is undefined search until finding position data of its first ancestor (It may be dummy as well)
		        while (pNode == null) {
		          pNode = animationData[temp.data('parent')] || animationData['DummyCompound_' + temp.data('parent')];
		          animationData[theId] = pNode;
		          temp = temp.parent()[0];
		          if (temp == undefined) {
		            break;
		          }
		        }
		        if (pNode != null) {
		          return {
		            x: pNode.x,
		            y: pNode.y
		          };
		        } else {
		          return {
		            x: ele.position('x'),
		            y: ele.position('y')
		          };
		        }
		      }
		    });

		    afterReposition();

		    frameId = requestAnimationFrame(iterateAnimated);
		  };

		  /*
		  * Listen 'layoutstarted' event and start animated iteration if animate option is 'during'
		  */
		  layout.addListener('layoutstarted', function () {
		    if (self.options.animate === 'during') {
		      frameId = requestAnimationFrame(iterateAnimated);
		    }
		  });

		  layout.runLayout(); // Run cose layout

		  /*
		   * If animate option is not 'during' ('end' or false) perform these here (If it is 'during' similar things are already performed)
		   */
		  if (this.options.animate !== "during") {
		    self.options.eles.nodes().not(":parent").layoutPositions(self, self.options, getPositions); // Use layout positions to reposition the nodes it considers the options parameter
		    ready = false;
		  }

		  return this; // chaining
		};

		//Get the top most ones of a list of nodes
		_CoSELayout.prototype.getTopMostNodes = function (nodes) {
		  var nodesMap = {};
		  for (var i = 0; i < nodes.length; i++) {
		    nodesMap[nodes[i].id()] = true;
		  }
		  var roots = nodes.filter(function (ele, i) {
		    if (typeof ele === "number") {
		      ele = i;
		    }
		    var parent = ele.parent()[0];
		    while (parent != null) {
		      if (nodesMap[parent.id()]) {
		        return false;
		      }
		      parent = parent.parent()[0];
		    }
		    return true;
		  });

		  return roots;
		};

		_CoSELayout.prototype.processChildrenList = function (parent, children, layout) {
		  var size = children.length;
		  for (var i = 0; i < size; i++) {
		    var theChild = children[i];
		    var children_of_children = theChild.children();
		    var theNode;

		    var dimensions = theChild.layoutDimensions({
		      nodeDimensionsIncludeLabels: this.options.nodeDimensionsIncludeLabels
		    });

		    if (theChild.outerWidth() != null && theChild.outerHeight() != null) {
		      theNode = parent.add(new CoSENode(layout.graphManager, new PointD(theChild.position('x') - dimensions.w / 2, theChild.position('y') - dimensions.h / 2), new DimensionD(parseFloat(dimensions.w), parseFloat(dimensions.h))));
		    } else {
		      theNode = parent.add(new CoSENode(this.graphManager));
		    }
		    // Attach id to the layout node
		    theNode.id = theChild.data("id");
		    // Attach the paddings of cy node to layout node
		    theNode.paddingLeft = parseInt(theChild.css('padding'));
		    theNode.paddingTop = parseInt(theChild.css('padding'));
		    theNode.paddingRight = parseInt(theChild.css('padding'));
		    theNode.paddingBottom = parseInt(theChild.css('padding'));

		    //Attach the label properties to compound if labels will be included in node dimensions  
		    if (this.options.nodeDimensionsIncludeLabels) {
		      if (theChild.isParent()) {
		        var labelWidth = theChild.boundingBox({ includeLabels: true, includeNodes: false }).w;
		        var labelHeight = theChild.boundingBox({ includeLabels: true, includeNodes: false }).h;
		        var labelPos = theChild.css("text-halign");
		        theNode.labelWidth = labelWidth;
		        theNode.labelHeight = labelHeight;
		        theNode.labelPos = labelPos;
		      }
		    }

		    // Map the layout node
		    this.idToLNode[theChild.data("id")] = theNode;

		    if (isNaN(theNode.rect.x)) {
		      theNode.rect.x = 0;
		    }

		    if (isNaN(theNode.rect.y)) {
		      theNode.rect.y = 0;
		    }

		    if (children_of_children != null && children_of_children.length > 0) {
		      var theNewGraph;
		      theNewGraph = layout.getGraphManager().add(layout.newGraph(), theNode);
		      this.processChildrenList(theNewGraph, children_of_children, layout);
		    }
		  }
		};

		/**
		 * @brief : called on continuous layouts to stop them before they finish
		 */
		_CoSELayout.prototype.stop = function () {
		  this.stopped = true;

		  return this; // chaining
		};

		var register = function register(cytoscape) {
		  //  var Layout = getLayout( cytoscape );

		  cytoscape('layout', 'cose-bilkent', _CoSELayout);
		};

		// auto reg for globals
		if (typeof cytoscape !== 'undefined') {
		  register(cytoscape);
		}

		module.exports = register;

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

var cytoscapeCoseBilkentExports = requireCytoscapeCoseBilkent();
const coseBilkent = /*@__PURE__*/getDefaultExportFromCjs(cytoscapeCoseBilkentExports);

cytoscape$1.use(coseBilkent);
function addNodes(nodes, cy) {
  nodes.forEach((node) => {
    const nodeData = {
      id: node.id,
      labelText: node.label,
      height: node.height,
      width: node.width,
      padding: node.padding ?? 0
    };
    Object.keys(node).forEach((key) => {
      if (!["id", "label", "height", "width", "padding", "x", "y"].includes(key)) {
        nodeData[key] = node[key];
      }
    });
    cy.add({
      group: "nodes",
      data: nodeData,
      position: {
        x: node.x ?? 0,
        y: node.y ?? 0
      }
    });
  });
}
__name(addNodes, "addNodes");
function addEdges(edges, cy) {
  edges.forEach((edge) => {
    const edgeData = {
      id: edge.id,
      source: edge.start,
      target: edge.end
    };
    Object.keys(edge).forEach((key) => {
      if (!["id", "start", "end"].includes(key)) {
        edgeData[key] = edge[key];
      }
    });
    cy.add({
      group: "edges",
      data: edgeData
    });
  });
}
__name(addEdges, "addEdges");
function createCytoscapeInstance(data) {
  return new Promise((resolve) => {
    const renderEl = select("body").append("div").attr("id", "cy").attr("style", "display:none");
    const cy = cytoscape$1({
      container: document.getElementById("cy"),
      // container to render in
      style: [
        {
          selector: "edge",
          style: {
            "curve-style": "bezier"
          }
        }
      ]
    });
    renderEl.remove();
    addNodes(data.nodes, cy);
    addEdges(data.edges, cy);
    cy.nodes().forEach(function(n) {
      n.layoutDimensions = () => {
        const nodeData = n.data();
        return { w: nodeData.width, h: nodeData.height };
      };
    });
    const layoutConfig = {
      name: "cose-bilkent",
      // @ts-ignore Types for cose-bilkent are not correct?
      quality: "proof",
      styleEnabled: false,
      animate: false
    };
    cy.layout(layoutConfig).run();
    cy.ready((e) => {
      log.info("Cytoscape ready", e);
      resolve(cy);
    });
  });
}
__name(createCytoscapeInstance, "createCytoscapeInstance");
function extractPositionedNodes(cy) {
  return cy.nodes().map((node) => {
    const data = node.data();
    const position = node.position();
    const positionedNode = {
      id: data.id,
      x: position.x,
      y: position.y
    };
    Object.keys(data).forEach((key) => {
      if (key !== "id") {
        positionedNode[key] = data[key];
      }
    });
    return positionedNode;
  });
}
__name(extractPositionedNodes, "extractPositionedNodes");
function extractPositionedEdges(cy) {
  return cy.edges().map((edge) => {
    const data = edge.data();
    const rscratch = edge._private.rscratch;
    const positionedEdge = {
      id: data.id,
      source: data.source,
      target: data.target,
      startX: rscratch.startX,
      startY: rscratch.startY,
      midX: rscratch.midX,
      midY: rscratch.midY,
      endX: rscratch.endX,
      endY: rscratch.endY
    };
    Object.keys(data).forEach((key) => {
      if (!["id", "source", "target"].includes(key)) {
        positionedEdge[key] = data[key];
      }
    });
    return positionedEdge;
  });
}
__name(extractPositionedEdges, "extractPositionedEdges");

// src/rendering-util/layout-algorithms/cose-bilkent/layout.ts
async function executeCoseBilkentLayout(data, _config) {
  log.debug("Starting cose-bilkent layout algorithm");
  try {
    validateLayoutData(data);
    const cy = await createCytoscapeInstance(data);
    const positionedNodes = extractPositionedNodes(cy);
    const positionedEdges = extractPositionedEdges(cy);
    log.debug(`Layout completed: ${positionedNodes.length} nodes, ${positionedEdges.length} edges`);
    return {
      nodes: positionedNodes,
      edges: positionedEdges
    };
  } catch (error) {
    log.error("Error in cose-bilkent layout algorithm:", error);
    throw error;
  }
}
__name(executeCoseBilkentLayout, "executeCoseBilkentLayout");
function validateLayoutData(data) {
  if (!data) {
    throw new Error("Layout data is required");
  }
  if (!data.config) {
    throw new Error("Configuration is required in layout data");
  }
  if (!data.rootNode) {
    throw new Error("Root node is required");
  }
  if (!data.nodes || !Array.isArray(data.nodes)) {
    throw new Error("No nodes found in layout data");
  }
  if (!Array.isArray(data.edges)) {
    throw new Error("Edges array is required in layout data");
  }
  return true;
}
__name(validateLayoutData, "validateLayoutData");

// src/rendering-util/layout-algorithms/cose-bilkent/render.ts
var render = /* @__PURE__ */ __name(async (data4Layout, svg, {
  insertCluster,
  insertEdge,
  insertEdgeLabel,
  insertMarkers,
  insertNode,
  log: log2,
  positionEdgeLabel
}, { algorithm: _algorithm }) => {
  const nodeDb = {};
  const clusterDb = {};
  const element = svg.select("g");
  insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId);
  const subGraphsEl = element.insert("g").attr("class", "subgraphs");
  const edgePaths = element.insert("g").attr("class", "edgePaths");
  const edgeLabels = element.insert("g").attr("class", "edgeLabels");
  const nodes = element.insert("g").attr("class", "nodes");
  log2.debug("Inserting nodes into DOM for dimension calculation");
  await Promise.all(
    data4Layout.nodes.map(async (node) => {
      if (node.isGroup) {
        const clusterNode = { ...node };
        clusterDb[node.id] = clusterNode;
        nodeDb[node.id] = clusterNode;
        await insertCluster(subGraphsEl, node);
      } else {
        const nodeWithPosition = { ...node };
        nodeDb[node.id] = nodeWithPosition;
        const nodeEl = await insertNode(nodes, node, {
          config: data4Layout.config,
          dir: data4Layout.direction || "TB"
        });
        const boundingBox = nodeEl.node().getBBox();
        nodeWithPosition.width = boundingBox.width;
        nodeWithPosition.height = boundingBox.height;
        nodeWithPosition.domId = nodeEl;
        log2.debug(`Node ${node.id} dimensions: ${boundingBox.width}x${boundingBox.height}`);
      }
    })
  );
  log2.debug("Running cose-bilkent layout algorithm");
  const updatedLayoutData = {
    ...data4Layout,
    nodes: data4Layout.nodes.map((node) => {
      const nodeWithDimensions = nodeDb[node.id];
      return {
        ...node,
        width: nodeWithDimensions.width,
        height: nodeWithDimensions.height
      };
    })
  };
  const layoutResult = await executeCoseBilkentLayout(updatedLayoutData, data4Layout.config);
  log2.debug("Positioning nodes based on layout results");
  layoutResult.nodes.forEach((positionedNode) => {
    const node = nodeDb[positionedNode.id];
    if (node?.domId) {
      node.domId.attr(
        "transform",
        `translate(${positionedNode.x}, ${positionedNode.y})`
      );
      node.x = positionedNode.x;
      node.y = positionedNode.y;
      log2.debug(`Positioned node ${node.id} at center (${positionedNode.x}, ${positionedNode.y})`);
    }
  });
  layoutResult.edges.forEach((positionedEdge) => {
    const edge = data4Layout.edges.find((e) => e.id === positionedEdge.id);
    if (edge) {
      edge.points = [
        { x: positionedEdge.startX, y: positionedEdge.startY },
        { x: positionedEdge.midX, y: positionedEdge.midY },
        { x: positionedEdge.endX, y: positionedEdge.endY }
      ];
    }
  });
  log2.debug("Inserting and positioning edges");
  await Promise.all(
    data4Layout.edges.map(async (edge) => {
      await insertEdgeLabel(edgeLabels, edge);
      const startNode = nodeDb[edge.start ?? ""];
      const endNode = nodeDb[edge.end ?? ""];
      if (startNode && endNode) {
        const positionedEdge = layoutResult.edges.find((e) => e.id === edge.id);
        if (positionedEdge) {
          log2.debug("APA01 positionedEdge", positionedEdge);
          const edgeWithPath = { ...edge };
          const paths = insertEdge(
            edgePaths,
            edgeWithPath,
            clusterDb,
            data4Layout.type,
            startNode,
            endNode,
            data4Layout.diagramId
          );
          positionEdgeLabel(edgeWithPath, paths);
        } else {
          const edgeWithPath = {
            ...edge,
            points: [
              { x: startNode.x || 0, y: startNode.y || 0 },
              { x: endNode.x || 0, y: endNode.y || 0 }
            ]
          };
          const paths = insertEdge(
            edgePaths,
            edgeWithPath,
            clusterDb,
            data4Layout.type,
            startNode,
            endNode,
            data4Layout.diagramId
          );
          positionEdgeLabel(edgeWithPath, paths);
        }
      }
    })
  );
  log2.debug("Cose-bilkent rendering completed");
}, "render");

// src/rendering-util/layout-algorithms/cose-bilkent/index.ts
var render2 = render;

export { render2 as render };
//# sourceMappingURL=cose-bilkent-S5V4N54A-BVPaKkGn.js.map
