You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			6561 lines
		
	
	
		
			188 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			6561 lines
		
	
	
		
			188 KiB
		
	
	
	
		
			JavaScript
		
	
| (self["webpackChunk_JUPYTERLAB_CORE_OUTPUT"] = self["webpackChunk_JUPYTERLAB_CORE_OUTPUT"] || []).push([[4047],{
 | |
| 
 | |
| /***/ 43203:
 | |
| /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
 | |
| 
 | |
| (function webpackUniversalModuleDefinition(root, factory) {
 | |
| 	if(true)
 | |
| 		module.exports = factory(__webpack_require__(54899));
 | |
| 	else {}
 | |
| })(this, function(__WEBPACK_EXTERNAL_MODULE_0__) {
 | |
| return /******/ (function(modules) { // webpackBootstrap
 | |
| /******/ 	// The module cache
 | |
| /******/ 	var installedModules = {};
 | |
| /******/
 | |
| /******/ 	// The require function
 | |
| /******/ 	function __nested_webpack_require_643__(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, __nested_webpack_require_643__);
 | |
| /******/
 | |
| /******/ 		// Flag the module as loaded
 | |
| /******/ 		module.l = true;
 | |
| /******/
 | |
| /******/ 		// Return the exports of the module
 | |
| /******/ 		return module.exports;
 | |
| /******/ 	}
 | |
| /******/
 | |
| /******/
 | |
| /******/ 	// expose the modules object (__webpack_modules__)
 | |
| /******/ 	__nested_webpack_require_643__.m = modules;
 | |
| /******/
 | |
| /******/ 	// expose the module cache
 | |
| /******/ 	__nested_webpack_require_643__.c = installedModules;
 | |
| /******/
 | |
| /******/ 	// identity function for calling harmony imports with the correct context
 | |
| /******/ 	__nested_webpack_require_643__.i = function(value) { return value; };
 | |
| /******/
 | |
| /******/ 	// define getter function for harmony exports
 | |
| /******/ 	__nested_webpack_require_643__.d = function(exports, name, getter) {
 | |
| /******/ 		if(!__nested_webpack_require_643__.o(exports, name)) {
 | |
| /******/ 			Object.defineProperty(exports, name, {
 | |
| /******/ 				configurable: false,
 | |
| /******/ 				enumerable: true,
 | |
| /******/ 				get: getter
 | |
| /******/ 			});
 | |
| /******/ 		}
 | |
| /******/ 	};
 | |
| /******/
 | |
| /******/ 	// getDefaultExport function for compatibility with non-harmony modules
 | |
| /******/ 	__nested_webpack_require_643__.n = function(module) {
 | |
| /******/ 		var getter = module && module.__esModule ?
 | |
| /******/ 			function getDefault() { return module['default']; } :
 | |
| /******/ 			function getModuleExports() { return module; };
 | |
| /******/ 		__nested_webpack_require_643__.d(getter, 'a', getter);
 | |
| /******/ 		return getter;
 | |
| /******/ 	};
 | |
| /******/
 | |
| /******/ 	// Object.prototype.hasOwnProperty.call
 | |
| /******/ 	__nested_webpack_require_643__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
 | |
| /******/
 | |
| /******/ 	// __webpack_public_path__
 | |
| /******/ 	__nested_webpack_require_643__.p = "";
 | |
| /******/
 | |
| /******/ 	// Load entry module and return exports
 | |
| /******/ 	return __nested_webpack_require_643__(__nested_webpack_require_643__.s = 7);
 | |
| /******/ })
 | |
| /************************************************************************/
 | |
| /******/ ([
 | |
| /* 0 */
 | |
| /***/ (function(module, exports) {
 | |
| 
 | |
| module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
 | |
| 
 | |
| /***/ }),
 | |
| /* 1 */
 | |
| /***/ (function(module, exports, __nested_webpack_require_3185__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var FDLayoutConstants = __nested_webpack_require_3185__(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, __nested_webpack_require_4002__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var FDLayoutEdge = __nested_webpack_require_4002__(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, __nested_webpack_require_4409__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var LGraph = __nested_webpack_require_4409__(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, __nested_webpack_require_4790__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var LGraphManager = __nested_webpack_require_4790__(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, __nested_webpack_require_5205__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var FDLayoutNode = __nested_webpack_require_5205__(0).FDLayoutNode;
 | |
| var IMath = __nested_webpack_require_5205__(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, __nested_webpack_require_8085__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var FDLayout = __nested_webpack_require_8085__(0).FDLayout;
 | |
| var CoSEGraphManager = __nested_webpack_require_8085__(4);
 | |
| var CoSEGraph = __nested_webpack_require_8085__(3);
 | |
| var CoSENode = __nested_webpack_require_8085__(5);
 | |
| var CoSEEdge = __nested_webpack_require_8085__(2);
 | |
| var CoSEConstants = __nested_webpack_require_8085__(1);
 | |
| var FDLayoutConstants = __nested_webpack_require_8085__(0).FDLayoutConstants;
 | |
| var LayoutConstants = __nested_webpack_require_8085__(0).LayoutConstants;
 | |
| var Point = __nested_webpack_require_8085__(0).Point;
 | |
| var PointD = __nested_webpack_require_8085__(0).PointD;
 | |
| var Layout = __nested_webpack_require_8085__(0).Layout;
 | |
| var Integer = __nested_webpack_require_8085__(0).Integer;
 | |
| var IGeometry = __nested_webpack_require_8085__(0).IGeometry;
 | |
| var LGraph = __nested_webpack_require_8085__(0).LGraph;
 | |
| var Transform = __nested_webpack_require_8085__(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;
 | |
| 
 | |
|   // Make polar to java cordinate conversion.
 | |
|   var cos_teta = Math.cos(teta);
 | |
|   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) {
 | |
|   var id = 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, __nested_webpack_require_45620__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var coseBase = {};
 | |
| 
 | |
| coseBase.layoutBase = __nested_webpack_require_45620__(0);
 | |
| coseBase.CoSEConstants = __nested_webpack_require_45620__(1);
 | |
| coseBase.CoSEEdge = __nested_webpack_require_45620__(2);
 | |
| coseBase.CoSEGraph = __nested_webpack_require_45620__(3);
 | |
| coseBase.CoSEGraphManager = __nested_webpack_require_45620__(4);
 | |
| coseBase.CoSELayout = __nested_webpack_require_45620__(6);
 | |
| coseBase.CoSENode = __nested_webpack_require_45620__(5);
 | |
| 
 | |
| module.exports = coseBase;
 | |
| 
 | |
| /***/ })
 | |
| /******/ ]);
 | |
| });
 | |
| 
 | |
| /***/ }),
 | |
| 
 | |
| /***/ 35302:
 | |
| /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
 | |
| 
 | |
| (function webpackUniversalModuleDefinition(root, factory) {
 | |
| 	if(true)
 | |
| 		module.exports = factory(__webpack_require__(43203));
 | |
| 	else {}
 | |
| })(this, function(__WEBPACK_EXTERNAL_MODULE_0__) {
 | |
| return /******/ (function(modules) { // webpackBootstrap
 | |
| /******/ 	// The module cache
 | |
| /******/ 	var installedModules = {};
 | |
| /******/
 | |
| /******/ 	// The require function
 | |
| /******/ 	function __nested_webpack_require_659__(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, __nested_webpack_require_659__);
 | |
| /******/
 | |
| /******/ 		// Flag the module as loaded
 | |
| /******/ 		module.l = true;
 | |
| /******/
 | |
| /******/ 		// Return the exports of the module
 | |
| /******/ 		return module.exports;
 | |
| /******/ 	}
 | |
| /******/
 | |
| /******/
 | |
| /******/ 	// expose the modules object (__webpack_modules__)
 | |
| /******/ 	__nested_webpack_require_659__.m = modules;
 | |
| /******/
 | |
| /******/ 	// expose the module cache
 | |
| /******/ 	__nested_webpack_require_659__.c = installedModules;
 | |
| /******/
 | |
| /******/ 	// identity function for calling harmony imports with the correct context
 | |
| /******/ 	__nested_webpack_require_659__.i = function(value) { return value; };
 | |
| /******/
 | |
| /******/ 	// define getter function for harmony exports
 | |
| /******/ 	__nested_webpack_require_659__.d = function(exports, name, getter) {
 | |
| /******/ 		if(!__nested_webpack_require_659__.o(exports, name)) {
 | |
| /******/ 			Object.defineProperty(exports, name, {
 | |
| /******/ 				configurable: false,
 | |
| /******/ 				enumerable: true,
 | |
| /******/ 				get: getter
 | |
| /******/ 			});
 | |
| /******/ 		}
 | |
| /******/ 	};
 | |
| /******/
 | |
| /******/ 	// getDefaultExport function for compatibility with non-harmony modules
 | |
| /******/ 	__nested_webpack_require_659__.n = function(module) {
 | |
| /******/ 		var getter = module && module.__esModule ?
 | |
| /******/ 			function getDefault() { return module['default']; } :
 | |
| /******/ 			function getModuleExports() { return module; };
 | |
| /******/ 		__nested_webpack_require_659__.d(getter, 'a', getter);
 | |
| /******/ 		return getter;
 | |
| /******/ 	};
 | |
| /******/
 | |
| /******/ 	// Object.prototype.hasOwnProperty.call
 | |
| /******/ 	__nested_webpack_require_659__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
 | |
| /******/
 | |
| /******/ 	// __webpack_public_path__
 | |
| /******/ 	__nested_webpack_require_659__.p = "";
 | |
| /******/
 | |
| /******/ 	// Load entry module and return exports
 | |
| /******/ 	return __nested_webpack_require_659__(__nested_webpack_require_659__.s = 1);
 | |
| /******/ })
 | |
| /************************************************************************/
 | |
| /******/ ([
 | |
| /* 0 */
 | |
| /***/ (function(module, exports) {
 | |
| 
 | |
| module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
 | |
| 
 | |
| /***/ }),
 | |
| /* 1 */
 | |
| /***/ (function(module, exports, __nested_webpack_require_3201__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var LayoutConstants = __nested_webpack_require_3201__(0).layoutBase.LayoutConstants;
 | |
| var FDLayoutConstants = __nested_webpack_require_3201__(0).layoutBase.FDLayoutConstants;
 | |
| var CoSEConstants = __nested_webpack_require_3201__(0).CoSEConstants;
 | |
| var CoSELayout = __nested_webpack_require_3201__(0).CoSELayout;
 | |
| var CoSENode = __nested_webpack_require_3201__(0).CoSENode;
 | |
| var PointD = __nested_webpack_require_3201__(0).layoutBase.PointD;
 | |
| var DimensionD = __nested_webpack_require_3201__(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;
 | |
|   var idToLNode = 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;
 | |
| 
 | |
| /***/ })
 | |
| /******/ ]);
 | |
| });
 | |
| 
 | |
| /***/ }),
 | |
| 
 | |
| /***/ 54899:
 | |
| /***/ (function(module) {
 | |
| 
 | |
| (function webpackUniversalModuleDefinition(root, factory) {
 | |
| 	if(true)
 | |
| 		module.exports = factory();
 | |
| 	else {}
 | |
| })(this, function() {
 | |
| return /******/ (function(modules) { // webpackBootstrap
 | |
| /******/ 	// The module cache
 | |
| /******/ 	var installedModules = {};
 | |
| /******/
 | |
| /******/ 	// The require function
 | |
| /******/ 	function __nested_webpack_require_543__(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, __nested_webpack_require_543__);
 | |
| /******/
 | |
| /******/ 		// Flag the module as loaded
 | |
| /******/ 		module.l = true;
 | |
| /******/
 | |
| /******/ 		// Return the exports of the module
 | |
| /******/ 		return module.exports;
 | |
| /******/ 	}
 | |
| /******/
 | |
| /******/
 | |
| /******/ 	// expose the modules object (__webpack_modules__)
 | |
| /******/ 	__nested_webpack_require_543__.m = modules;
 | |
| /******/
 | |
| /******/ 	// expose the module cache
 | |
| /******/ 	__nested_webpack_require_543__.c = installedModules;
 | |
| /******/
 | |
| /******/ 	// identity function for calling harmony imports with the correct context
 | |
| /******/ 	__nested_webpack_require_543__.i = function(value) { return value; };
 | |
| /******/
 | |
| /******/ 	// define getter function for harmony exports
 | |
| /******/ 	__nested_webpack_require_543__.d = function(exports, name, getter) {
 | |
| /******/ 		if(!__nested_webpack_require_543__.o(exports, name)) {
 | |
| /******/ 			Object.defineProperty(exports, name, {
 | |
| /******/ 				configurable: false,
 | |
| /******/ 				enumerable: true,
 | |
| /******/ 				get: getter
 | |
| /******/ 			});
 | |
| /******/ 		}
 | |
| /******/ 	};
 | |
| /******/
 | |
| /******/ 	// getDefaultExport function for compatibility with non-harmony modules
 | |
| /******/ 	__nested_webpack_require_543__.n = function(module) {
 | |
| /******/ 		var getter = module && module.__esModule ?
 | |
| /******/ 			function getDefault() { return module['default']; } :
 | |
| /******/ 			function getModuleExports() { return module; };
 | |
| /******/ 		__nested_webpack_require_543__.d(getter, 'a', getter);
 | |
| /******/ 		return getter;
 | |
| /******/ 	};
 | |
| /******/
 | |
| /******/ 	// Object.prototype.hasOwnProperty.call
 | |
| /******/ 	__nested_webpack_require_543__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
 | |
| /******/
 | |
| /******/ 	// __webpack_public_path__
 | |
| /******/ 	__nested_webpack_require_543__.p = "";
 | |
| /******/
 | |
| /******/ 	// Load entry module and return exports
 | |
| /******/ 	return __nested_webpack_require_543__(__nested_webpack_require_543__.s = 26);
 | |
| /******/ })
 | |
| /************************************************************************/
 | |
| /******/ ([
 | |
| /* 0 */
 | |
| /***/ (function(module, exports, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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, __nested_webpack_require_4947__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var LGraphObject = __nested_webpack_require_4947__(2);
 | |
| var IGeometry = __nested_webpack_require_4947__(8);
 | |
| var IMath = __nested_webpack_require_4947__(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, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| function LGraphObject(vGraphObject) {
 | |
|   this.vGraphObject = vGraphObject;
 | |
| }
 | |
| 
 | |
| module.exports = LGraphObject;
 | |
| 
 | |
| /***/ }),
 | |
| /* 3 */
 | |
| /***/ (function(module, exports, __nested_webpack_require_8167__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var LGraphObject = __nested_webpack_require_8167__(2);
 | |
| var Integer = __nested_webpack_require_8167__(10);
 | |
| var RectangleD = __nested_webpack_require_8167__(13);
 | |
| var LayoutConstants = __nested_webpack_require_8167__(0);
 | |
| var RandomSeed = __nested_webpack_require_8167__(16);
 | |
| var PointD = __nested_webpack_require_8167__(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 edge;
 | |
|   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 edge;
 | |
| 
 | |
|   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, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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, __nested_webpack_require_17549__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var LGraphObject = __nested_webpack_require_17549__(2);
 | |
| var Integer = __nested_webpack_require_17549__(10);
 | |
| var LayoutConstants = __nested_webpack_require_17549__(0);
 | |
| var LGraphManager = __nested_webpack_require_17549__(6);
 | |
| var LNode = __nested_webpack_require_17549__(3);
 | |
| var LEdge = __nested_webpack_require_17549__(1);
 | |
| var RectangleD = __nested_webpack_require_17549__(13);
 | |
| var Point = __nested_webpack_require_17549__(12);
 | |
| var LinkedList = __nested_webpack_require_17549__(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, __nested_webpack_require_27617__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var LGraph;
 | |
| var LEdge = __nested_webpack_require_27617__(1);
 | |
| 
 | |
| function LGraphManager(layout) {
 | |
|   LGraph = __nested_webpack_require_27617__(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();
 | |
|     var s = 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, __nested_webpack_require_38707__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var LayoutConstants = __nested_webpack_require_38707__(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, __nested_webpack_require_40298__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * This class maintains a list of static geometry related utility methods.
 | |
|  *
 | |
|  *
 | |
|  * Copyright: i-Vis Research Group, Bilkent University, 2007 - present
 | |
|  */
 | |
| 
 | |
| var Point = __nested_webpack_require_40298__(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 {
 | |
|       //not line, return null;
 | |
|     }
 | |
|   }
 | |
|   // 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 {
 | |
|         //not valid line, return null;
 | |
|       }
 | |
|     } 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, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| function Integer() {}
 | |
| 
 | |
| Integer.MAX_VALUE = 2147483647;
 | |
| Integer.MIN_VALUE = -2147483648;
 | |
| 
 | |
| module.exports = Integer;
 | |
| 
 | |
| /***/ }),
 | |
| /* 11 */
 | |
| /***/ (function(module, exports, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *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, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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, __nested_webpack_require_64072__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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 = __nested_webpack_require_64072__(0);
 | |
| var LGraphManager = __nested_webpack_require_64072__(6);
 | |
| var LNode = __nested_webpack_require_64072__(3);
 | |
| var LEdge = __nested_webpack_require_64072__(1);
 | |
| var LGraph = __nested_webpack_require_64072__(5);
 | |
| var PointD = __nested_webpack_require_64072__(4);
 | |
| var Transform = __nested_webpack_require_64072__(17);
 | |
| var Emitter = __nested_webpack_require_64072__(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) {
 | |
|     // update all edges
 | |
|     var edge;
 | |
|     var allEdges = this.graphManager.getAllEdges();
 | |
|     for (var i = 0; i < allEdges.length; i++) {
 | |
|       edge = allEdges[i];
 | |
|       //      this.update(edge);
 | |
|     }
 | |
| 
 | |
|     // recursively update nodes
 | |
|     var node;
 | |
|     var nodes = this.graphManager.getRoot().getNodes();
 | |
|     for (var i = 0; i < nodes.length; i++) {
 | |
|       node = 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, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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, __nested_webpack_require_81860__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var PointD = __nested_webpack_require_81860__(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, __nested_webpack_require_84747__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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 = __nested_webpack_require_84747__(15);
 | |
| var FDLayoutConstants = __nested_webpack_require_84747__(7);
 | |
| var LayoutConstants = __nested_webpack_require_84747__(0);
 | |
| var IGeometry = __nested_webpack_require_84747__(8);
 | |
| var IMath = __nested_webpack_require_84747__(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, __nested_webpack_require_100902__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var LEdge = __nested_webpack_require_100902__(1);
 | |
| var FDLayoutConstants = __nested_webpack_require_100902__(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, __nested_webpack_require_101387__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var LNode = __nested_webpack_require_101387__(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, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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, __nested_webpack_require_103173__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var UniqueIDGeneretor = __nested_webpack_require_103173__(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) {
 | |
|   var theId = 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, __nested_webpack_require_103901__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var UniqueIDGeneretor = __nested_webpack_require_103901__(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, __nested_webpack_require_105138__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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 = __nested_webpack_require_105138__(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, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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, __nested_webpack_require_115611__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| var layoutBase = function layoutBase() {
 | |
|   return;
 | |
| };
 | |
| 
 | |
| layoutBase.FDLayout = __nested_webpack_require_115611__(18);
 | |
| layoutBase.FDLayoutConstants = __nested_webpack_require_115611__(7);
 | |
| layoutBase.FDLayoutEdge = __nested_webpack_require_115611__(19);
 | |
| layoutBase.FDLayoutNode = __nested_webpack_require_115611__(20);
 | |
| layoutBase.DimensionD = __nested_webpack_require_115611__(21);
 | |
| layoutBase.HashMap = __nested_webpack_require_115611__(22);
 | |
| layoutBase.HashSet = __nested_webpack_require_115611__(23);
 | |
| layoutBase.IGeometry = __nested_webpack_require_115611__(8);
 | |
| layoutBase.IMath = __nested_webpack_require_115611__(9);
 | |
| layoutBase.Integer = __nested_webpack_require_115611__(10);
 | |
| layoutBase.Point = __nested_webpack_require_115611__(12);
 | |
| layoutBase.PointD = __nested_webpack_require_115611__(4);
 | |
| layoutBase.RandomSeed = __nested_webpack_require_115611__(16);
 | |
| layoutBase.RectangleD = __nested_webpack_require_115611__(13);
 | |
| layoutBase.Transform = __nested_webpack_require_115611__(17);
 | |
| layoutBase.UniqueIDGeneretor = __nested_webpack_require_115611__(14);
 | |
| layoutBase.Quicksort = __nested_webpack_require_115611__(24);
 | |
| layoutBase.LinkedList = __nested_webpack_require_115611__(11);
 | |
| layoutBase.LGraphObject = __nested_webpack_require_115611__(2);
 | |
| layoutBase.LGraph = __nested_webpack_require_115611__(5);
 | |
| layoutBase.LEdge = __nested_webpack_require_115611__(1);
 | |
| layoutBase.LGraphManager = __nested_webpack_require_115611__(6);
 | |
| layoutBase.LNode = __nested_webpack_require_115611__(3);
 | |
| layoutBase.Layout = __nested_webpack_require_115611__(15);
 | |
| layoutBase.LayoutConstants = __nested_webpack_require_115611__(0);
 | |
| layoutBase.NeedlemanWunsch = __nested_webpack_require_115611__(25);
 | |
| 
 | |
| module.exports = layoutBase;
 | |
| 
 | |
| /***/ }),
 | |
| /* 27 */
 | |
| /***/ (function(module, exports, __webpack_require__) {
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| 
 | |
| 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;
 | |
| 
 | |
| /***/ })
 | |
| /******/ ]);
 | |
| });
 | |
| 
 | |
| /***/ }),
 | |
| 
 | |
| /***/ 34047:
 | |
| /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
 | |
| 
 | |
| "use strict";
 | |
| __webpack_require__.r(__webpack_exports__);
 | |
| /* harmony export */ __webpack_require__.d(__webpack_exports__, {
 | |
| /* harmony export */   render: () => (/* binding */ render2)
 | |
| /* harmony export */ });
 | |
| /* harmony import */ var _chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(74999);
 | |
| /* harmony import */ var cytoscape__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(23207);
 | |
| /* harmony import */ var cytoscape_cose_bilkent__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(35302);
 | |
| /* harmony import */ var cytoscape_cose_bilkent__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(cytoscape_cose_bilkent__WEBPACK_IMPORTED_MODULE_2__);
 | |
| /* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(35321);
 | |
| 
 | |
| 
 | |
| // src/rendering-util/layout-algorithms/cose-bilkent/cytoscape-setup.ts
 | |
| 
 | |
| 
 | |
| 
 | |
| cytoscape__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z.use((cytoscape_cose_bilkent__WEBPACK_IMPORTED_MODULE_2___default()));
 | |
| 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
 | |
|       }
 | |
|     });
 | |
|   });
 | |
| }
 | |
| (0,_chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .__name */ .eW)(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
 | |
|     });
 | |
|   });
 | |
| }
 | |
| (0,_chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .__name */ .eW)(addEdges, "addEdges");
 | |
| function createCytoscapeInstance(data) {
 | |
|   return new Promise((resolve) => {
 | |
|     const renderEl = (0,d3__WEBPACK_IMPORTED_MODULE_3__/* .select */ .Ys)("body").append("div").attr("id", "cy").attr("style", "display:none");
 | |
|     const cy = (0,cytoscape__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)({
 | |
|       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) => {
 | |
|       _chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .log */ .cM.info("Cytoscape ready", e);
 | |
|       resolve(cy);
 | |
|     });
 | |
|   });
 | |
| }
 | |
| (0,_chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .__name */ .eW)(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;
 | |
|   });
 | |
| }
 | |
| (0,_chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .__name */ .eW)(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;
 | |
|   });
 | |
| }
 | |
| (0,_chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .__name */ .eW)(extractPositionedEdges, "extractPositionedEdges");
 | |
| 
 | |
| // src/rendering-util/layout-algorithms/cose-bilkent/layout.ts
 | |
| async function executeCoseBilkentLayout(data, _config) {
 | |
|   _chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .log */ .cM.debug("Starting cose-bilkent layout algorithm");
 | |
|   try {
 | |
|     validateLayoutData(data);
 | |
|     const cy = await createCytoscapeInstance(data);
 | |
|     const positionedNodes = extractPositionedNodes(cy);
 | |
|     const positionedEdges = extractPositionedEdges(cy);
 | |
|     _chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .log */ .cM.debug(`Layout completed: ${positionedNodes.length} nodes, ${positionedEdges.length} edges`);
 | |
|     return {
 | |
|       nodes: positionedNodes,
 | |
|       edges: positionedEdges
 | |
|     };
 | |
|   } catch (error) {
 | |
|     _chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .log */ .cM.error("Error in cose-bilkent layout algorithm:", error);
 | |
|     throw error;
 | |
|   }
 | |
| }
 | |
| (0,_chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .__name */ .eW)(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;
 | |
| }
 | |
| (0,_chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .__name */ .eW)(validateLayoutData, "validateLayoutData");
 | |
| 
 | |
| // src/rendering-util/layout-algorithms/cose-bilkent/render.ts
 | |
| var render = /* @__PURE__ */ (0,_chunk_AGHRB4JF_mjs__WEBPACK_IMPORTED_MODULE_0__/* .__name */ .eW)(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) => {
 | |
|       const _edgeLabel = 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;
 | |
| 
 | |
| 
 | |
| 
 | |
| /***/ })
 | |
| 
 | |
| }]);
 | |
| //# sourceMappingURL=4047.14d816f33b5d2f8ee675.js.map?v=14d816f33b5d2f8ee675
 |