├── LICENSE ├── css └── main.css ├── js ├── walker.js ├── field.js ├── player.js ├── main.js └── graph.js ├── index.html ├── README.md └── libs └── webcola.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Thomas Wagenaar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | .node { 2 | cursor: move; 3 | stroke-width: 1.5px; 4 | } 5 | .link { 6 | fill: none; 7 | stroke: #BDBDBD; 8 | stroke-width: 1.5px; 9 | opacity: 0.4; 10 | marker-end: url(#end-arrow); 11 | } 12 | .label { 13 | fill: #CCCCCC; 14 | font-size: 9px; 15 | text-anchor: middle; 16 | cursor: move; 17 | font-family: Arial; 18 | } 19 | .best { 20 | width: 100%; 21 | height: 800px; 22 | float: left; 23 | } 24 | #field { 25 | width: 100%; 26 | height: 800px; 27 | float:left; 28 | } 29 | .container { 30 | width: 100%; 31 | overflow: hidden; 32 | } 33 | #end-arrow{ 34 | opacity: 0.4; 35 | } 36 | .INPUT{ 37 | fill: #ff6666; 38 | stroke: #ff4d4d; 39 | } 40 | .OUTPUT{ 41 | fill : #ff8c66; 42 | stroke: #ff794d; 43 | } 44 | .LOGISTIC{ 45 | fill: #ffb366; 46 | stroke: #ffa64d; 47 | } 48 | .TANH{ 49 | fill: #ffd966; 50 | stroke: #ffd24d; 51 | } 52 | .IDENTITY{ 53 | fill: #ffff66; 54 | stroke: #ffff4d; 55 | } 56 | .STEP{ 57 | fill: #d9ff66; 58 | stroke: #d2ff4d; 59 | } 60 | .RELU{ 61 | fill: #b3ff66; 62 | stroke: #a6ff4d; 63 | } 64 | .SOFTSIGN{ 65 | fill: #8cff66; 66 | stroke: #79ff4d; 67 | } 68 | .SINUSOID{ 69 | fill: #66ff66; 70 | stroke: #4dff4d; 71 | } 72 | .GAUSSIAN{ 73 | fill: #66ff8c; 74 | stroke: #4dff79; 75 | } 76 | .BENT_IDENTITY{ 77 | fill: #66ffd9; 78 | stroke: #4dffd2; 79 | } 80 | .BIPOLAR{ 81 | fill: #66d9ff; 82 | stroke: #4dd2ff; 83 | } 84 | .BIPOLAR_SIGMOID{ 85 | fill: #66b3ff; 86 | stroke: #4da6ff; 87 | } 88 | .HARD_TANH{ 89 | fill: #668cff; 90 | stroke: #4d79ff; 91 | } 92 | .ABSOLUTE{ 93 | fill: #6666ff; 94 | stroke: #4d4dff; 95 | } 96 | .GATE{ 97 | fill: #003300; 98 | stroke: #001a00; 99 | } 100 | -------------------------------------------------------------------------------- /js/walker.js: -------------------------------------------------------------------------------- 1 | function Walker(){ 2 | this.x = START_X; 3 | this.y = START_Y; 4 | this.vx = 0; 5 | this.vy = 0; 6 | 7 | this.r = 10; 8 | 9 | this.angle = Math.random() * Math.PI * 2; 10 | } 11 | 12 | Walker.prototype = { 13 | /** Update the stats */ 14 | update: function(){ 15 | if(Math.random() > 0.5){ 16 | this.angle += Math.random()* 2 -1; 17 | } 18 | 19 | // Calculate next position 20 | this.ax = Math.cos(this.angle); 21 | this.ay = Math.sin(this.angle); 22 | this.vx += this.ax; 23 | this.vy += this.ay; 24 | 25 | // Limit speeds to maximum speed 26 | this.vx = this.vx > MAX_SPEED/2 ? MAX_SPEED/2 : this.vx < -MAX_SPEED/2 ? -MAX_SPEED/2 : this.vx; 27 | this.vy = this.vy > MAX_SPEED/2 ? MAX_SPEED/2 : this.vy < -MAX_SPEED/2 ? -MAX_SPEED/2 : this.vy; 28 | 29 | this.x += this.vx; 30 | this.y += this.vy; 31 | 32 | // Limit position to width and height 33 | this.x = this.x >= WIDTH ? WIDTH : this.x <= 0 ? 0 : this.x; 34 | this.y = this.y >= HEIGHT ? HEIGHT : this.y <= 0 ? 0 : this.y; 35 | 36 | if(this.x == 0 || this.x == WIDTH){ 37 | this.vx = -this.vx; 38 | this.angle += PI; 39 | } 40 | if(this.y == 0 || this.y == HEIGHT){ 41 | this.vy = -this.vy; 42 | this.angle += PI; 43 | } 44 | }, 45 | 46 | reset: function(){ 47 | this.x = START_X; 48 | this.y = START_Y; 49 | this.vx = 0; 50 | this.vy = 0; 51 | 52 | this.angle = Math.random() * Math.PI * 2; 53 | }, 54 | 55 | 56 | /** Display the walker on the field */ 57 | show: function(){ 58 | fill(0); 59 | ellipse(this.x, this.y, this.r*2); 60 | 61 | // Score radius 62 | noFill(); 63 | stroke('lightgreen'); 64 | strokeWeight(2); 65 | ellipse(this.x, this.y, SCORE_RADIUS*2); 66 | noStroke(); 67 | }, 68 | }; 69 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Target-seeking AI 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 |
23 |

Playing field

24 |

25 | The following neural agents are a result of 100+ generations of evolution. 26 | If you have any remarks, or have managed to improve the evolution process, 27 | please make a post 28 | here. You can also perform a pull request on this repo. The genomes 29 | are alive live at the moment (every 250 frames). Click on the field 30 | to relocate the target! 31 |

32 |
33 |
34 |

Best genome

35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | 43 |
44 |
45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /js/field.js: -------------------------------------------------------------------------------- 1 | /* Global vars */ 2 | var players = []; 3 | var walker = new Walker(); 4 | var iteration = 0; 5 | var highestScore = 0; 6 | 7 | /** Setup the canvas */ 8 | function setup(){ 9 | var canvas = createCanvas(WIDTH, HEIGHT); 10 | canvas.parent('field'); 11 | initNeat(); 12 | 13 | // Do some initial mutation 14 | if(!USE_TRAINED_POP){ 15 | for(var i = 0; i < 1; i++) neat.mutate(); 16 | } 17 | 18 | startEvaluation(); 19 | } 20 | 21 | function draw(){ 22 | clear(); 23 | squareGrid(); 24 | 25 | // Check if evaluation is done 26 | if(iteration == ITERATIONS){ 27 | endEvaluation(); 28 | iteration = 0; 29 | } 30 | 31 | // Update and visualise players 32 | for(var i = players.length - 1; i >= 0; i--){ 33 | var player = players[i]; 34 | 35 | // Some players are eaten during the iteration 36 | player.update(); 37 | player.show(); 38 | } 39 | 40 | walker.update(); 41 | walker.show(); 42 | 43 | iteration++; 44 | } 45 | 46 | /** Draw a square grid with grey lines */ 47 | function squareGrid(){ 48 | stroke(204, 204, 204, 160); 49 | strokeWeight(1); 50 | fill(255); 51 | for(var x = 0; x < WIDTH/40; x++){ 52 | line(x * 40, 0, x * 40, HEIGHT); 53 | } 54 | for(var y = 0; y < HEIGHT/40; y++){ 55 | line(0, y * 40, WIDTH, y * 40); 56 | } 57 | noStroke(); 58 | } 59 | 60 | /** Calculate distance between two points */ 61 | function distance(x1, y1, x2, y2){ 62 | var dx = x1 - x2; 63 | var dy = y1 - y2; 64 | 65 | return Math.sqrt(dx * dx + dy * dy); 66 | } 67 | 68 | /** Get a relative color between red and green */ 69 | var activationColor = function(value, max){ 70 | var power = 1 - Math.min(value/max, 1); 71 | var color = [255, 255, 0] 72 | 73 | if(power < 0.5){ 74 | color[0] = 2 * power * 255; 75 | } else { 76 | color[1] = (1.0 - 2 * (power - 0.5)) * 255; 77 | } 78 | 79 | return color; 80 | } 81 | 82 | /** Get the angle from one point to another */ 83 | function angleToPoint(x1, y1, x2, y2){ 84 | d = distance(x1, y1, x2, y2); 85 | dx = (x2-x1) / d; 86 | dy = (y2-y1) / d; 87 | 88 | a = Math.acos(dx); 89 | a = dy < 0 ? 2 * Math.PI - a : a; 90 | return a; 91 | } 92 | 93 | /** Set the walker to a new location */ 94 | function mouseClicked(){ 95 | if(mouseX >= 0 && mouseX <= WIDTH && mouseY >= 0 && mouseY <= HEIGHT){ 96 | walker.x = mouseX; 97 | walker.y = mouseY; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Target-seeking AI 2 | This repository shows how you can use [Neataptic](https://github.com/wagenaartje/neataptic) to succesfully teach neural networks to trace targets. You can see the genomes live in action [here](https://wagenaartje.github.io/target-seeking-ai/). These genomes have been trained for over 100 generations and are very effective. Visualisation done with [P5.js](https://p5js.org/). The next step would be adding collisions, to possibly reveal some interesting tactics. 3 | 4 | [Read an article on this repo here](https://wagenaartje.github.io/neataptic/articles/targetseeking/). 5 | 6 | These forks of this library are interesting to check out as well: 7 | 8 | * [corpr8's fork](https://corpr8.github.io/neataptic-targetseeking-tron/) 9 | gives each neural agent its own acceleration, as well as letting each arrow 10 | remain in the same place after each generation. This creates a much more 11 | 'fluid' process. 12 | 13 | ## Settings 14 | If you manage to optimize the settings, please perform either a pull request or create an issue [here](https://github.com/wagenaartje/neataptic/issues). 15 | 16 | #### Settings (contained in `js/main.js`): 17 | * `WIDTH` set the width of the playing field 18 | * `HEIGHT` set the height of the playing field 19 | * `MAX_SPEED` set the maximal multiplier speed a genome can have (smaller genomes move faster) 20 | * `START_X` set the x-location from which each genome (and the target) starts 21 | * `START_Y` set the y-location from which each genome (and the target) starts 22 | * `SCORE_RADIUS` set the distance to the target from where genomes get assigned score 23 | * `PLAYER_AMOUNT` set the amount of genomes that play on the field (population size) 24 | * `ITERATIONS` set the amount of iterations/frames each generation is tested for 25 | * `START_HIDDEN_SIZE` set the amount of hidden nodes each genome starts witch 26 | * `MUTATION_RATE` set the mutation rate 27 | * `ELITISM` set the amount of elitism 28 | 29 | Most important setting: 30 | * `USE_TRAINED_POP` setting this to `false` will start the evolution from scratch (USE THIS WHEN OPTIMIZING THE SETTINGS), setting this to `true` will use the pre-trained population 31 | 32 | #### Default setting values 33 | ```javascript 34 | var WIDTH = $('#field').width(); 35 | var HEIGHT = 800; 36 | var MAX_SPEED = 5; 37 | var START_X = WIDTH/2; 38 | var START_Y = HEIGHT/2; 39 | var SCORE_RADIUS = 100; 40 | 41 | // GA settings 42 | var PLAYER_AMOUNT = Math.round(2.3e-4 * WIDTH * HEIGHT); 43 | var ITERATIONS = 250; 44 | var MUTATION_RATE = 0.3; 45 | var ELITISM = Math.round(0.1 * PLAYER_AMOUNT); 46 | 47 | // Trained population 48 | var USE_TRAINED_POP = true; 49 | ``` 50 | -------------------------------------------------------------------------------- /js/player.js: -------------------------------------------------------------------------------- 1 | function Player(genome){ 2 | this.x = START_X; 3 | this.y = START_Y; 4 | this.vx = 0; 5 | this.vy = 0; 6 | this.r = 6; 7 | 8 | this.brain = genome; 9 | this.brain.score = 0; 10 | 11 | players.push(this); 12 | } 13 | 14 | Player.prototype = { 15 | /** Update the stats */ 16 | update: function(){ 17 | var input = this.detect(); 18 | var output = this.brain.activate(input); 19 | 20 | var moveangle = output[0] * 2 * PI; 21 | 22 | // Calculate next position 23 | this.ax = Math.cos(moveangle); 24 | this.ay = Math.sin(moveangle); 25 | this.vx += this.ax; 26 | this.vy += this.ay; 27 | 28 | // Limit speeds to maximum speed 29 | this.vx = this.vx > MAX_SPEED ? MAX_SPEED : this.vx < -MAX_SPEED ? -MAX_SPEED : this.vx; 30 | this.vy = this.vy > MAX_SPEED ? MAX_SPEED : this.vy < -MAX_SPEED ? -MAX_SPEED : this.vy; 31 | 32 | this.x += this.vx; 33 | this.y += this.vy; 34 | 35 | // Limit position to width and height 36 | this.x = this.x >= WIDTH ? WIDTH : this.x <= 0 ? 0 : this.x; 37 | this.y = this.y >= HEIGHT ? HEIGHT : this.y <= 0 ? 0 : this.y; 38 | 39 | if(this.x == 0 || this.x == WIDTH) this.vx = -this.vx; 40 | if(this.y == 0 || this.y == HEIGHT) this.vy = -this.vy; 41 | 42 | this.score(); 43 | }, 44 | 45 | /** Calculate fitness of this players genome **/ 46 | score: function(){ 47 | var dist = distance(this.x, this.y, walker.x, walker.y); 48 | if(!isNaN(dist) && dist < SCORE_RADIUS){ 49 | this.brain.score += SCORE_RADIUS - dist; 50 | } 51 | 52 | // Replace highest score to visualise 53 | highestScore = this.brain.score > highestScore ? this.brain.score : highestScore; 54 | }, 55 | 56 | /** Display the player on the field, parts borrowed from the CodingTrain */ 57 | show: function(){ 58 | // Draw a triangle rotated in the direction of velocity 59 | var angle = angleToPoint(this.x, this.y, this.x + this.vx, this.y + this.vy) + HALF_PI; 60 | var color = activationColor(this.brain.score, highestScore); 61 | 62 | push(); 63 | translate(this.x, this.y); 64 | rotate(angle); 65 | 66 | fill(color); 67 | beginShape(); 68 | vertex(0, -this.r * 2); 69 | vertex(-this.r, this.r * 2); 70 | vertex(this.r, this.r * 2); 71 | endShape(CLOSE); 72 | 73 | pop(); 74 | }, 75 | 76 | /** Detect and normalize inputs */ 77 | detect: function(){ 78 | var dist = Math.sqrt(this.x, this.y, walker.x, walker.y) / Math.sqrt(WIDTH**2 + HEIGHT**2); 79 | var targetAngle = angleToPoint(this.x, this.y, walker.x, walker.y) / TWO_PI; 80 | var vx = (this.vx + MAX_SPEED) / MAX_SPEED; 81 | var vy = (this.vy + MAX_SPEED) / MAX_SPEED; 82 | var tvx = (walker.vx + MAX_SPEED) / MAX_SPEED; 83 | var tvy = (walker.vy + MAX_SPEED) / MAX_SPEED; 84 | 85 | // NaN checking 86 | targetAngle = isNaN(targetAngle) ? 0 : targetAngle; 87 | dist = isNaN(dist) ? 0 : dist; 88 | 89 | return [vx, vy, tvx, tvy, targetAngle, dist]; 90 | }, 91 | }; 92 | -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | /** Rename vars */ 2 | var Neat = neataptic.Neat; 3 | var Methods = neataptic.Methods; 4 | var Config = neataptic.Config; 5 | var Architect = neataptic.Architect; 6 | 7 | /** Turn off warnings */ 8 | Config.warnings = false; 9 | 10 | /** Settings */ 11 | var WIDTH = $('#field').width(); 12 | var HEIGHT = 800; 13 | var MAX_SPEED = 5; 14 | var START_X = WIDTH/2; 15 | var START_Y = HEIGHT/2; 16 | var SCORE_RADIUS = 100; 17 | 18 | // GA settings 19 | var PLAYER_AMOUNT = Math.round(2.3e-4 * WIDTH * HEIGHT); 20 | var ITERATIONS = 250; 21 | var MUTATION_RATE = 0.3; 22 | var ELITISM = Math.round(0.1 * PLAYER_AMOUNT); 23 | 24 | // Trained population 25 | var USE_TRAINED_POP = true; 26 | 27 | /** Global vars */ 28 | var neat; 29 | 30 | /** Construct the genetic algorithm */ 31 | function initNeat(){ 32 | neat = new Neat( 33 | 6, 1, 34 | null, 35 | { 36 | mutation: [ 37 | Methods.Mutation.ADD_NODE, 38 | Methods.Mutation.SUB_NODE, 39 | Methods.Mutation.ADD_CONN, 40 | Methods.Mutation.SUB_CONN, 41 | Methods.Mutation.MOD_WEIGHT, 42 | Methods.Mutation.MOD_BIAS, 43 | Methods.Mutation.MOD_ACTIVATION, 44 | Methods.Mutation.ADD_GATE, 45 | Methods.Mutation.SUB_GATE, 46 | Methods.Mutation.ADD_SELF_CONN, 47 | Methods.Mutation.SUB_SELF_CONN, 48 | Methods.Mutation.ADD_BACK_CONN, 49 | Methods.Mutation.SUB_BACK_CONN 50 | ], 51 | popsize: PLAYER_AMOUNT, 52 | mutationRate: MUTATION_RATE, 53 | elitism: ELITISM 54 | } 55 | ); 56 | 57 | if(USE_TRAINED_POP){ 58 | neat.population = population; 59 | } 60 | 61 | // Draw the first graph 62 | drawGraph(neat.population[0].graph($('.best').width()/2, $('.best').height()/2), '.best'); 63 | } 64 | 65 | /** Start the evaluation of the current generation */ 66 | function startEvaluation(){ 67 | players = []; 68 | highestScore = 0; 69 | 70 | for(var genome in neat.population){ 71 | genome = neat.population[genome]; 72 | new Player(genome); 73 | } 74 | 75 | walker.reset(); 76 | } 77 | 78 | /** End the evaluation of the current generation */ 79 | function endEvaluation(){ 80 | console.log('Generation:', neat.generation, '- average score:', Math.round(neat.getAverage())); 81 | console.log('Fittest score:', Math.round(neat.getFittest().score)); 82 | 83 | // Networks shouldn't get too big 84 | for(var genome in neat.population){ 85 | genome = neat.population[genome]; 86 | genome.score -= genome.nodes.length * SCORE_RADIUS / 10; 87 | } 88 | 89 | // Sort the population by score 90 | neat.sort(); 91 | 92 | // Draw the best genome 93 | drawGraph(neat.population[0].graph($('.best').width()/2, $('.best').height()/2), '.best'); 94 | 95 | // Init new pop 96 | var newPopulation = []; 97 | 98 | // Elitism 99 | for(var i = 0; i < neat.elitism; i++){ 100 | newPopulation.push(neat.population[i]); 101 | } 102 | 103 | // Breed the next individuals 104 | for(var i = 0; i < neat.popsize - neat.elitism; i++){ 105 | newPopulation.push(neat.getOffspring()); 106 | } 107 | 108 | // Replace the old population with the new population 109 | neat.population = newPopulation; 110 | neat.mutate(); 111 | 112 | neat.generation++; 113 | startEvaluation(); 114 | } 115 | -------------------------------------------------------------------------------- /js/graph.js: -------------------------------------------------------------------------------- 1 | var NODE_RADIUS = 7; 2 | var REPEL_FORCE = 0; 3 | var LINK_DISTANCE = 100; 4 | 5 | var drawGraph = function(graph, panel) { 6 | var d3cola = cola.d3adaptor() 7 | .avoidOverlaps(true) 8 | .size([$('.best').width(), $('.best').height()]); 9 | 10 | var svg = d3.select(panel); 11 | 12 | d3.selectAll(panel + "> *").remove(); 13 | 14 | // define arrow markers for graph links 15 | svg.append('svg:defs').append('svg:marker') 16 | .attr('id', 'end-arrow') 17 | .attr('viewBox', '0 -5 10 10') 18 | .attr('refX', 6) 19 | .attr('markerWidth', 4) 20 | .attr('markerHeight', 4) 21 | .attr('orient', 'auto') 22 | .append('svg:path') 23 | .attr('d', 'M0,-5L10,0L0,5') 24 | 25 | graph.nodes.forEach(function (v) { v.height = v.width = 2 * NODE_RADIUS; }); 26 | 27 | d3cola 28 | .nodes(graph.nodes) 29 | .links(graph.links) 30 | .constraints(graph.constraints) 31 | .symmetricDiffLinkLengths(REPEL_FORCE) 32 | .linkDistance(LINK_DISTANCE) 33 | .start(10, 15, 20); 34 | 35 | var path = svg.selectAll(".link") 36 | .data(graph.links) 37 | .enter().append('svg:path') 38 | .attr('class', 'link') 39 | 40 | path.append("title") 41 | .text(function (d) { 42 | var text = ""; 43 | text += "Weight: " + Math.round(d.weight*1000)/1000 + "\n";; 44 | text += "Source: " + d.source.id + "\n";; 45 | text += "Target: " + d.target.id; 46 | return text; 47 | }); 48 | 49 | var node = svg.selectAll(".node") 50 | .data(graph.nodes) 51 | .enter().append("circle") 52 | .attr("class", function(d){ 53 | return "node " + d.name; 54 | }) 55 | .attr("r", function(d) { return NODE_RADIUS; }) 56 | 57 | .call(d3cola.drag); 58 | 59 | node.append("title") 60 | .text(function (d){ 61 | var text = ""; 62 | text += "Activation: " + Math.round(d.activation*1000)/1000 + "\n"; 63 | text += "Position: " + d.id; 64 | return text; 65 | }); 66 | 67 | var label = svg.selectAll(".label") 68 | .data(graph.nodes) 69 | .enter().append("text") 70 | .attr("class", "label") 71 | .text(function (d){return '(' + d.index + ') ' + d.name; }) 72 | .call(d3cola.drag) 73 | 74 | d3cola.on("tick", function () { 75 | // draw directed edges with proper padding from node centers 76 | path.attr('d', function (d) { 77 | var deltaX = d.target.x - d.source.x, 78 | deltaY = d.target.y - d.source.y, 79 | dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY), 80 | normX = deltaX / dist, 81 | normY = deltaY / dist; 82 | 83 | if(isNaN(normX)) normX = 0; 84 | if(isNaN(normY)) normY = 0; 85 | 86 | sourcePadding = NODE_RADIUS, 87 | targetPadding = NODE_RADIUS + 2, 88 | sourceX = d.source.x + (sourcePadding * normX), 89 | sourceY = d.source.y + (sourcePadding * normY), 90 | targetX = d.target.x - (targetPadding * normX), 91 | targetY = d.target.y - (targetPadding * normY); 92 | 93 | // Defaults for normal edge. 94 | drx = 0, 95 | dry = 0, 96 | xRotation = 0, // degrees 97 | largeArc = 0, // 1 or 0 98 | sweep = 1; // 1 or 0 99 | 100 | // Self edge. 101 | if (d.source.x === d.target.x && d.source.y === d.target.y) { 102 | drx = dist; 103 | dry = dist; 104 | xRotation = -45; 105 | largeArc = 1; 106 | drx = 20; 107 | dry = 20; 108 | targetX = targetX + 1; 109 | targetY = targetY + 1; 110 | } 111 | return 'M' + sourceX + ',' + sourceY + "A" + drx + "," + dry + " " + xRotation + "," + largeArc + "," + sweep + " " + targetX + ',' + targetY; 112 | }); 113 | 114 | node.attr("cx", function (d) { return d.x; }) 115 | .attr("cy", function (d) { return d.y; }) 116 | 117 | label 118 | .attr("x", function (d) { return d.x + 10; }) 119 | .attr("y", function (d) { return d.y - 10; }); 120 | }); 121 | }; 122 | -------------------------------------------------------------------------------- /libs/webcola.js: -------------------------------------------------------------------------------- 1 | var cola;!function(a){var b=function(){function a(){this.locks={}}return a.prototype.add=function(a,b){isNaN(b[0])||isNaN(b[1]),this.locks[a]=b},a.prototype.clear=function(){this.locks={}},a.prototype.isEmpty=function(){for(var a in this.locks)return!1;return!0},a.prototype.apply=function(a){for(var b in this.locks)a(b,this.locks[b])},a}();a.Locks=b;var c=function(){function a(a,c,e){void 0===e&&(e=null),this.D=c,this.G=e,this.threshold=1e-4,this.random=new d,this.project=null,this.x=a,this.k=a.length;var f=this.n=a[0].length;this.H=new Array(this.k),this.g=new Array(this.k),this.Hd=new Array(this.k),this.a=new Array(this.k),this.b=new Array(this.k),this.c=new Array(this.k),this.d=new Array(this.k),this.e=new Array(this.k),this.ia=new Array(this.k),this.ib=new Array(this.k),this.xtmp=new Array(this.k),this.locks=new b,this.minD=Number.MAX_VALUE;for(var g,h=f;h--;)for(g=f;--g>h;){var i=c[h][g];i>0&&id;++d){c[d]=new Array(a);for(var e=0;a>e;++e)c[d][e]=b(d,e)}return c},a.prototype.offsetDir=function(){for(var a=this,b=new Array(this.k),c=0,d=0;dc)){for(var d,e=new Array(this.k),f=new Array(this.k),g=new Array(this.k),h=0,i=0;c>i;++i){for(d=0;dj;++j)if(i!==j){for(var k=c;k--;){var l=0;for(d=0;d1e-9)break;var n=this.offsetDir();for(d=0;d1&&o>p||!isFinite(p))for(d=0;d1&&(q=1);var r=p*p,s=q*(o-p)/(r*o),t=-q/(r*o*o*o);for(isFinite(s)||console.log(s),d=0;de;++e)c+=a.dotProd(this.g[e],b[e]),a.rightMultiply(this.H[e],b[e],this.Hd[e]),d+=a.dotProd(b[e],this.Hd[e]);return 0!==d&&isFinite(d)?c/d:0},a.prototype.reduceStress=function(){this.computeDerivatives(this.x);for(var a=this.computeStepSize(this.g),b=0;be;++e)for(var f=0;d>f;++f)b[e][f]=a[e][f]},a.prototype.stepAndProject=function(b,c,d,e){a.copy(b,c),this.takeDescentStep(c[0],d[0],e),this.project&&this.project[0](b[0],b[1],c[0]),this.takeDescentStep(c[1],d[1],e),this.project&&this.project[1](c[0],b[1],c[1])},a.mApply=function(a,b,c){for(var d=a;d-->0;)for(var e=b;e-->0;)c(d,e)},a.prototype.matrixApply=function(b){a.mApply(this.k,this.n,b)},a.prototype.computeNextPosition=function(a,b){var c=this;this.computeDerivatives(a);var d=this.computeStepSize(this.g);this.stepAndProject(a,b,this.g,d);for(var e=0;e0;){var d=this.rungeKutta();c=Math.abs(b/d-1)b;++b)for(var d=b+1,e=this.n;e>d;++d){for(var f=0,g=0;g>16)/this.range},a.prototype.getNextBetween=function(a,b){return a+this.getNext()*(b-a)},a}();a.PseudoRandom=d}(cola||(cola={}));var __extends=this.__extends||function(a,b){function c(){this.constructor=a}for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);c.prototype=b.prototype,a.prototype=new c},cola;!function(a){var b;!function(b){function c(a,b,c){return(b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y)}function d(a,b,d){return c(a,b,d)>0}function e(a,b,d){return c(a,b,d)<0}function f(a){var b,d=a.slice(0).sort(function(a,b){return a.x!==b.x?b.x-a.x:b.y-a.y}),e=a.length,f=0,g=d[0].x;for(b=1;e>b&&d[b].x===g;++b);var h=b-1,i=[];if(i.push(d[f]),h===e-1)d[h].y!==d[f].y&&i.push(d[h]);else{var j,k=e-1,l=d[e-1].x;for(b=e-2;b>=0&&d[b].x===l;b--);for(j=b+1,b=h;++b<=j;)if(!(c(d[f],d[j],d[b])>=0&&j>b)){for(;i.length>1&&!(c(i[i.length-2],i[i.length-1],d[b])>0);)i.length-=1;b!=f&&i.push(d[b])}k!=j&&i.push(d[k]);var m=i.length;for(b=j;--b>=h;)if(!(c(d[k],d[h],d[b])>=0&&b>h)){for(;i.length>m&&!(c(i[i.length-2],i[i.length-1],d[b])>0);)i.length-=1;b!=f&&i.push(d[b])}}return i}function g(a,b,c){b.slice(0).sort(function(b,c){return Math.atan2(b.y-a.y,b.x-a.x)-Math.atan2(c.y-a.y,c.x-a.x)}).forEach(c)}function h(a,b){return{rtan:i(a,b),ltan:j(a,b)}}function i(a,b){var c,f,g,h,i,j=b.length-1;if(e(a,b[1],b[0])&&!d(a,b[j-1],b[0]))return 0;for(c=0,f=j;;){if(f-c===1)return d(a,b[c],b[f])?c:f;if(g=Math.floor((c+f)/2),i=e(a,b[g+1],b[g]),i&&!d(a,b[g-1],b[g]))return g;h=d(a,b[c+1],b[c]),h?i?f=g:d(a,b[c],b[g])?f=g:c=g:i&&e(a,b[c],b[g])?f=g:c=g}}function j(a,b){var c,f,g,h,i,j=b.length-1;if(d(a,b[j-1],b[0])&&!e(a,b[1],b[0]))return 0;for(c=0,f=j;;){if(f-c===1)return e(a,b[c],b[f])?c:f;if(g=Math.floor((c+f)/2),i=e(a,b[g+1],b[g]),d(a,b[g-1],b[g])&&!i)return g;h=e(a,b[c+1],b[c]),h?i?e(a,b[c],b[g])?f=g:c=g:f=g:i?c=g:d(a,b[c],b[g])?f=g:c=g}}function k(a,b,c,d,e,f){var g,h;g=c(b[0],a),h=d(a[g],b);for(var i=!1;!i;){for(i=!0;;){if(g===a.length-1&&(g=0),e(b[h],a[g],a[g+1]))break;++g}for(;;){if(0===h&&(h=b.length-1),f(a[g],b[h],b[h-1]))break;--h,i=!1}}return{t1:g,t2:h}}function l(a,b){var c=m(b,a);return{t1:c.t2,t2:c.t1}}function m(a,b){return k(a,b,i,j,d,e)}function n(a,b){return k(a,b,j,j,e,e)}function o(a,b){return k(a,b,i,i,d,d)}function p(b,c){for(var d=[],e=1,f=c.length;f>e;++e){var g=a.vpsc.Rectangle.lineIntersection(b.x1,b.y1,b.x2,b.y2,c[e-1].x,c[e-1].y,c[e].x,c[e].y);g&&d.push(g)}return d}function q(a,b){for(var d=a.length-1,e=b.length-1,f=new y,g=0;d>g;++g)for(var h=0;e>h;++h){var i=a[0==g?d-1:g-1],j=a[g],k=a[g+1],l=b[0==h?e-1:h-1],m=b[h],n=b[h+1],o=c(i,j,m),p=c(j,l,m),q=c(j,m,n),r=c(l,m,j),s=c(m,i,j),t=c(m,j,k);o>=0&&p>=0&&0>q&&r>=0&&s>=0&&0>t?f.ll=new x(g,h):0>=o&&0>=p&&q>0&&0>=r&&0>=s&&t>0?f.rr=new x(g,h):0>=o&&p>0&&0>=q&&r>=0&&0>s&&t>=0?f.rl=new x(g,h):o>=0&&0>p&&q>=0&&0>=r&&s>0&&0>=t&&(f.lr=new x(g,h))}return f}function r(a,b){for(var c=1,d=b.length;d>c;++c)if(e(b[c-1],b[c],a))return!1;return!0}function s(a,b){return!a.every(function(a){return!r(a,b)})}function t(a,b){if(s(a,b))return!0;if(s(b,a))return!0;for(var c=1,d=a.length;d>c;++c){var e=a[c],f=a[c-1];if(p(new v(f.x,f.y,e.x,e.y),b).length>0)return!0}return!1}var u=function(){function a(){}return a}();b.Point=u;var v=function(){function a(a,b,c,d){this.x1=a,this.y1=b,this.x2=c,this.y2=d}return a}();b.LineSegment=v;var w=function(a){function b(){a.apply(this,arguments)}return __extends(b,a),b}(u);b.PolyPoint=w,b.isLeft=c,b.ConvexHull=f,b.clockwiseRadialSweep=g,b.tangent_PolyPolyC=k,b.LRtangent_PolyPolyC=l,b.RLtangent_PolyPolyC=m,b.LLtangent_PolyPolyC=n,b.RRtangent_PolyPolyC=o;var x=function(){function a(a,b){this.t1=a,this.t2=b}return a}();b.BiTangent=x;var y=function(){function a(){}return a}();b.BiTangents=y;var z=function(a){function b(){a.apply(this,arguments)}return __extends(b,a),b}(u);b.TVGPoint=z;var A=function(){function a(a,b,c,d){this.id=a,this.polyid=b,this.polyvertid=c,this.p=d,d.vv=this}return a}();b.VisibilityVertex=A;var B=function(){function a(a,b){this.source=a,this.target=b}return a.prototype.length=function(){var a=this.source.p.x-this.target.p.x,b=this.source.p.y-this.target.p.y;return Math.sqrt(a*a+b*b)},a}();b.VisibilityEdge=B;var C=function(){function a(a,c){if(this.P=a,this.V=[],this.E=[],c)this.V=c.V.slice(0),this.E=c.E.slice(0);else{for(var d=a.length,e=0;d>e;e++)for(var f=a[e],g=0;g0&&this.E.push(new B(f[g-1].vv,i))}for(var e=0;d-1>e;e++)for(var j=a[e],g=e+1;d>g;g++){var k=a[g],l=b.tangents(j,k);for(var m in l){var n=l[m],o=j[n.t1],p=k[n.t2];this.addEdgeIfVisible(o,p,e,g)}}}}return a.prototype.addEdgeIfVisible=function(a,b,c,d){this.intersectsPolys(new v(a.x,a.y,b.x,b.y),c,d)||this.E.push(new B(a.vv,b.vv))},a.prototype.addPoint=function(a,b){var c=this.P.length;this.V.push(new A(this.V.length,c,0,a));for(var d=0;c>d;++d)if(d!==b){var e=this.P[d],f=h(a,e);this.addEdgeIfVisible(a,e[f.ltan],b,d),this.addEdgeIfVisible(a,e[f.rtan],b,d)}return a.vv},a.prototype.intersectsPolys=function(a,b,c){for(var d=0,e=this.P.length;e>d;++d)if(d!=b&&d!=c&&p(a,this.P[d]).length>0)return!0;return!1},a}();b.TangentVisibilityGraph=C,b.tangents=q,b.polysOverlap=t}(b=a.geom||(a.geom={}))}(cola||(cola={}));var cola;!function(a){var b;!function(a){var b=function(){function a(a){this.scale=a,this.AB=0,this.AD=0,this.A2=0}return a.prototype.addVariable=function(a){var b=this.scale/a.scale,c=a.offset/a.scale,d=a.weight;this.AB+=d*b*c,this.AD+=d*b*a.desiredPosition,this.A2+=d*b*b},a.prototype.getPosn=function(){return(this.AD-this.AB)/this.A2},a}();a.PositionStats=b;var c=function(){function a(a,b,c,d){void 0===d&&(d=!1),this.left=a,this.right=b,this.gap=c,this.equality=d,this.active=!1,this.unsatisfiable=!1,this.left=a,this.right=b,this.gap=c,this.equality=d}return a.prototype.slack=function(){return this.unsatisfiable?Number.MAX_VALUE:this.right.scale*this.right.position()-this.gap-this.left.scale*this.left.position()},a}();a.Constraint=c;var d=function(){function a(a,b,c){void 0===b&&(b=1),void 0===c&&(c=1),this.desiredPosition=a,this.weight=b,this.scale=c,this.offset=0}return a.prototype.dfdv=function(){return 2*this.weight*(this.position()-this.desiredPosition)},a.prototype.position=function(){return(this.block.ps.scale*this.block.posn+this.offset)/this.scale},a.prototype.visitNeighbours=function(a,b){var c=function(c,d){return c.active&&a!==d&&b(c,d)};this.cOut.forEach(function(a){return c(a,a.right)}),this.cIn.forEach(function(a){return c(a,a.left)})},a}();a.Variable=d;var e=function(){function a(a){this.vars=[],a.offset=0,this.ps=new b(a.scale),this.addVariable(a)}return a.prototype.addVariable=function(a){a.block=this,this.vars.push(a),this.ps.addVariable(a),this.posn=this.ps.getPosn()},a.prototype.updateWeightedPosition=function(){this.ps.AB=this.ps.AD=this.ps.A2=0;for(var a=0,b=this.vars.length;b>a;++a)this.ps.addVariable(this.vars[a]);this.posn=this.ps.getPosn()},a.prototype.compute_lm=function(a,b,c){var d=this,e=a.dfdv();return a.visitNeighbours(b,function(b,f){var g=d.compute_lm(f,a,c);f===b.right?(e+=g*b.left.scale,b.lm=g):(e+=g*b.right.scale,b.lm=-g),c(b)}),e/a.scale},a.prototype.populateSplitBlock=function(a,b){var c=this;a.visitNeighbours(b,function(b,d){d.offset=a.offset+(d===b.right?b.gap:-b.gap),c.addVariable(d),c.populateSplitBlock(d,a)})},a.prototype.traverse=function(a,b,c,d){var e=this;void 0===c&&(c=this.vars[0]),void 0===d&&(d=null),c.visitNeighbours(d,function(d,f){b.push(a(d)),e.traverse(a,b,f,c)})},a.prototype.findMinLM=function(){var a=null;return this.compute_lm(this.vars[0],null,function(b){!b.equality&&(null===a||b.lmd;++d){var f=a.vars[d];f.offset+=c,this.addVariable(f)}this.posn=this.ps.getPosn()},a.prototype.cost=function(){for(var a=0,b=this.vars.length;b--;){var c=this.vars[b],d=c.position()-c.desiredPosition;a+=d*d*c.weight}return a},a}();a.Block=e;var f=function(){function a(a){this.vs=a;var b=a.length;for(this.list=new Array(b);b--;){var c=new e(a[b]);this.list[b]=c,c.blockInd=b}}return a.prototype.cost=function(){for(var a=0,b=this.list.length;b--;)a+=this.list[b].cost();return a},a.prototype.insert=function(a){a.blockInd=this.list.length,this.list.push(a)},a.prototype.remove=function(a){var b=this.list.length-1,c=this.list[b];this.list.length=b,a!==c&&(this.list[a.blockInd]=c,c.blockInd=a.blockInd)},a.prototype.merge=function(a){var b=a.left.block,c=a.right.block,d=a.right.offset-a.left.offset-a.gap;b.vars.lengthg;++g){var h=d[g];if(!h.unsatisfiable){var i=h.slack();if((h.equality||b>i)&&(b=i,c=h,f=g,h.equality))break}}return f!==e&&(b=0?this.inactive.push(b):this.bs.merge(b)}}},a.prototype.solve=function(){this.satisfy();for(var a=Number.MAX_VALUE,b=this.bs.cost();Math.abs(a-b)>1e-4;)this.satisfy(),a=b,b=this.bs.cost();return b},a.LAGRANGIAN_TOLERANCE=-1e-4,a.ZERO_UPPERBOUND=-1e-10,a}();a.Solver=g}(b=a.vpsc||(a.vpsc={}))}(cola||(cola={}));var cola;!function(a){var b;!function(a){function b(a){return a.bounds="undefined"!=typeof a.leaves?a.leaves.reduce(function(a,b){return b.bounds.union(a)},p.empty()):p.empty(),"undefined"!=typeof a.groups&&(a.bounds=a.groups.reduce(function(a,c){return b(c).union(a)},a.bounds)),a.bounds=a.bounds.inflate(a.padding),a.bounds}function c(a,b,c,d){var e=b.rayIntersection(c.cx(),c.cy());e||(e={x:b.cx(),y:b.cy()});var f=c.rayIntersection(b.cx(),b.cy());f||(f={x:c.cx(),y:c.cy()});var g=f.x-e.x,h=f.y-e.y,i=Math.sqrt(g*g+h*h),j=i-d;a.sourceIntersection=e,a.targetIntersection=f,a.arrowStart={x:e.x+j*g/i,y:e.y+j*h/i}}function d(a,b,c){var d=b.rayIntersection(a.x,a.y);d||(d={x:b.cx(),y:b.cy()});var e=d.x-a.x,f=d.y-a.y,g=Math.sqrt(e*e+f*f);return{x:d.x-c*e/g,y:d.y-c*f/g}}function e(a,b){return a.pos>b.pos?1:a.pos=i);var k=new Array(j);for(h=0;i>h;++h){var l=b[h],m=new q(c[h],l,d.getCentre(l));k[h]=new r(!0,m,d.getOpen(l)),k[h+i]=new r(!1,m,d.getClose(l))}k.sort(e);var n=new Array,o=f();for(h=0;j>h;++h){var p=k[h],m=p.v;if(p.isOpen)o.insert(m),d.findNeighbours(m,o);else{o.remove(m);var s=function(b,c){var e=(d.getSize(b.r)+d.getSize(c.r))/2+g;n.push(new a.Constraint(b.v,c.v,e))},t=function(a,b,c){for(var d,e=m[a].iterator();null!==(d=e[a]());)c(d,m),d[b].remove(m)};t("prev","next",function(a,b){return s(a,b)}),t("next","prev",function(a,b){return s(b,a)})}}return console.assert(0===o.size),n}function i(a,b){var c=function(c,d){for(var e,f=b.findIter(a);null!==(e=f[c]());){var g=e.r.overlapX(a.r);if((0>=g||g<=e.r.overlapY(a.r))&&(a[c].insert(e),e[d].insert(a)),0>=g)break}};c("next","prev"),c("prev","next")}function j(a,b){var c=function(c,d){var e=b.findIter(a)[c]();null!==e&&e.r.overlapX(a.r)>0&&(a[c].insert(e),e[d].insert(a))};c("next","prev"),c("prev","next")}function k(a,b){return h(a,b,s,1e-6)}function l(a,b){return h(a,b,t,1e-6)}function m(a){return g(a,s,1e-6)}function n(a){return g(a,t,1e-6)}function o(b){var c=b.map(function(b){return new a.Variable(b.cx())}),d=a.generateXConstraints(b,c),e=new a.Solver(c,d);e.solve(),c.forEach(function(a,c){return b[c].setXCentre(a.position())}),c=b.map(function(b){return new a.Variable(b.cy())}),d=a.generateYConstraints(b,c),e=new a.Solver(c,d),e.solve(),c.forEach(function(a,c){return b[c].setYCentre(a.position())})}a.computeGroupBounds=b;var p=function(){function a(a,b,c,d){this.x=a,this.X=b,this.y=c,this.Y=d}return a.empty=function(){return new a(Number.POSITIVE_INFINITY,Number.NEGATIVE_INFINITY,Number.POSITIVE_INFINITY,Number.NEGATIVE_INFINITY)},a.prototype.cx=function(){return(this.x+this.X)/2},a.prototype.cy=function(){return(this.y+this.Y)/2},a.prototype.overlapX=function(a){var b=this.cx(),c=a.cx();return c>=b&&a.x=c&&this.x=b&&a.y=c&&this.yh;++h){var i=a.lineIntersection(b,c,d,e,f[h][0],f[h][1],f[h][2],f[h][3]);null!==i&&g.push({x:i.x,y:i.y})}return g},a.prototype.rayIntersection=function(a,b){var c=this.lineIntersections(this.cx(),this.cy(),a,b);return c.length>0?c[0]:null},a.prototype.vertices=function(){return[{x:this.x,y:this.y},{x:this.X,y:this.y},{x:this.X,y:this.Y},{x:this.x,y:this.Y},{x:this.x,y:this.y}]},a.lineIntersection=function(a,b,c,d,e,f,g,h){var i=c-a,j=g-e,k=d-b,l=h-f,m=l*i-j*k;if(0==m)return null;var n=a-e,o=b-f,p=j*o-l*n,q=p/m,r=i*o-k*n,s=r/m;return q>=0&&1>=q&&s>=0&&1>=s?{x:a+q*i,y:b+q*k}:null},a.prototype.inflate=function(b){return new a(this.x-b,this.X+b,this.y-b,this.Y+b)},a}();a.Rectangle=p,a.makeEdgeBetween=c,a.makeEdgeTo=d;var q=function(){function a(a,b,c){this.v=a,this.r=b,this.pos=c,this.prev=f(),this.next=f()}return a}(),r=function(){function a(a,b,c){this.isOpen=a,this.v=b,this.pos=c}return a}(),s={getCentre:function(a){return a.cx()},getOpen:function(a){return a.y},getClose:function(a){return a.Y},getSize:function(a){return a.width()},makeRect:function(a,b,c,d){return new p(c-d/2,c+d/2,a,b)},findNeighbours:i},t={getCentre:function(a){return a.cy()},getOpen:function(a){return a.x},getClose:function(a){return a.X},getSize:function(a){return a.height()},makeRect:function(a,b,c,d){return new p(a,b,c-d/2,c+d/2)},findNeighbours:j};a.generateXConstraints=k,a.generateYConstraints=l,a.generateXGroupConstraints=m,a.generateYGroupConstraints=n,a.removeOverlaps=o;var u=function(a){function b(b,c){a.call(this,0,c),this.index=b}return __extends(b,a),b}(a.Variable),v=function(){function c(c,d,e,f,g){var h=this;if(void 0===e&&(e=null),void 0===f&&(f=null),void 0===g&&(g=!1),this.nodes=c,this.groups=d,this.rootGroup=e,this.avoidOverlaps=g,this.variables=c.map(function(a,b){return a.variable=new u(b,1)}),f&&this.createConstraints(f),g&&e&&"undefined"!=typeof e.groups){c.forEach(function(b){if(!b.width||!b.height)return void(b.bounds=new a.Rectangle(b.x,b.x,b.y,b.y));var c=b.width/2,d=b.height/2;b.bounds=new a.Rectangle(b.x-c,b.x+c,b.y-d,b.y+d)}),b(e);var i=c.length;d.forEach(function(a){h.variables[i]=a.minVar=new u(i++,.01),h.variables[i]=a.maxVar=new u(i++,.01)})}}return c.prototype.createSeparation=function(b){return new a.Constraint(this.nodes[b.left].variable,this.nodes[b.right].variable,b.gap,"undefined"!=typeof b.equality?b.equality:!1)},c.prototype.makeFeasible=function(a){var b=this;if(this.avoidOverlaps){var c="x",d="width";"x"===a.axis&&(c="y",d="height");var e=a.offsets.map(function(a){return b.nodes[a.node]}).sort(function(a,b){return a[c]-b[c]}),f=null;e.forEach(function(a){f&&(a[c]=f[c]+f[d]+1),f=a})}},c.prototype.createAlignment=function(b){var c=this,d=this.nodes[b.offsets[0].node].variable;this.makeFeasible(b);var e="x"===b.axis?this.xConstraints:this.yConstraints;b.offsets.slice(1).forEach(function(b){var f=c.nodes[b.node].variable;e.push(new a.Constraint(d,f,b.offset,!0))})},c.prototype.createConstraints=function(a){var b=this,c=function(a){return"undefined"==typeof a.type||"separation"===a.type};this.xConstraints=a.filter(function(a){return"x"===a.axis&&c(a)}).map(function(a){return b.createSeparation(a)}),this.yConstraints=a.filter(function(a){return"y"===a.axis&&c(a)}).map(function(a){return b.createSeparation(a)}),a.filter(function(a){return"alignment"===a.type}).forEach(function(a){return b.createAlignment(a)})},c.prototype.setupVariablesAndBounds=function(a,b,c,d){this.nodes.forEach(function(e,f){e.fixed?(e.variable.weight=1e3,c[f]=d(e)):e.variable.weight=1;var g=(e.width||0)/2,h=(e.height||0)/2,i=a[f],j=b[f];e.bounds=new p(i-g,i+g,j-h,j+h)})},c.prototype.xProject=function(a,b,c){(this.rootGroup||this.avoidOverlaps||this.xConstraints)&&this.project(a,b,a,c,function(a){return a.px},this.xConstraints,m,function(a){return a.bounds.setXCentre(c[a.variable.index]=a.variable.position())},function(a){var b=c[a.minVar.index]=a.minVar.position(),d=c[a.maxVar.index]=a.maxVar.position(),e=a.padding/2;a.bounds.x=b-e,a.bounds.X=d+e})},c.prototype.yProject=function(a,b,c){(this.rootGroup||this.yConstraints)&&this.project(a,b,b,c,function(a){return a.py},this.yConstraints,n,function(a){return a.bounds.setYCentre(c[a.variable.index]=a.variable.position())},function(a){var b=c[a.minVar.index]=a.minVar.position(),d=c[a.maxVar.index]=a.maxVar.position(),e=a.padding/2;a.bounds.y=b-e,a.bounds.Y=d+e})},c.prototype.projectFunctions=function(){var a=this;return[function(b,c,d){return a.xProject(b,c,d)},function(b,c,d){return a.yProject(b,c,d)}]},c.prototype.project=function(a,c,d,e,f,g,h,i,j){this.setupVariablesAndBounds(a,c,e,f),this.rootGroup&&this.avoidOverlaps&&(b(this.rootGroup),g=g.concat(h(this.rootGroup))),this.solve(this.variables,g,d,e),this.nodes.forEach(i),this.rootGroup&&this.avoidOverlaps&&this.groups.forEach(j)},c.prototype.solve=function(b,c,d,e){var f=new a.Solver(b,c);f.setStartingPositions(d),f.setDesiredPositions(e),f.solve()},c}();a.Projection=v}(b=a.vpsc||(a.vpsc={}))}(cola||(cola={}));var PairingHeap=function(){function a(a){this.elem=a,this.subheaps=[]}return a.prototype.toString=function(a){for(var b="",c=!1,d=0;dk&&(i.d=k,i.prev=g,c.reduceKey(i.q,i,function(a,b){return a.q=b}))}}return e},a}();a.Calculator=e}(b=a.shortestpaths||(a.shortestpaths={}))}(cola||(cola={}));var cola;!function(a){var b=function(){function a(a,b,c){this.id=a,this.rect=b,this.children=c,this.leaf="undefined"==typeof c||0===c.length}return a}();a.NodeWrapper=b;var c=function(){function a(a,b,c,d,e){void 0===d&&(d=null),void 0===e&&(e=null),this.id=a,this.x=b,this.y=c,this.node=d,this.line=e}return a}();a.Vert=c;var d=function(){function a(b,c){this.s=b,this.t=c;var d=a.findMatch(b,c),e=c.slice(0).reverse(),f=a.findMatch(b,e);d.length>=f.length?(this.length=d.length,this.si=d.si,this.ti=d.ti,this.reversed=!1):(this.length=f.length,this.si=f.si,this.ti=c.length-f.ti-f.length,this.reversed=!0)}return a.findMatch=function(a,b){for(var c=a.length,d=b.length,e={length:0,si:-1,ti:-1},f=new Array(c),g=0;c>g;g++){f[g]=new Array(d);for(var h=0;d>h;h++)if(a[g]===b[h]){var i=f[g][h]=0===g||0===h?1:f[g-1][h-1]+1;i>e.length&&(e.length=i,e.si=g-i+1,e.ti=h-i+1)}else f[g][h]=0}return e},a.prototype.getSequence=function(){return this.length>=0?this.s.slice(this.si,this.si+this.length):[]},a}();a.LongestCommonSubsequence=d; 2 | var e=function(){function d(d,e,f){var g=this;void 0===f&&(f=12),this.originalnodes=d,this.groupPadding=f,this.leaves=null,this.nodes=d.map(function(a,c){return new b(c,e.getBounds(a),e.getChildren(a))}),this.leaves=this.nodes.filter(function(a){return a.leaf}),this.groups=this.nodes.filter(function(a){return!a.leaf}),this.cols=this.getGridDim("x"),this.rows=this.getGridDim("y"),this.groups.forEach(function(a){return a.children.forEach(function(b){return g.nodes[b].parent=a})}),this.root={children:[]},this.nodes.forEach(function(a){"undefined"==typeof a.parent&&(a.parent=g.root,g.root.children.push(a.id)),a.ports=[]}),this.backToFront=this.nodes.slice(0),this.backToFront.sort(function(a,b){return g.getDepth(a)-g.getDepth(b)});var h=this.backToFront.slice(0).reverse().filter(function(a){return!a.leaf});h.forEach(function(b){var c=a.vpsc.Rectangle.empty();b.children.forEach(function(a){return c=c.union(g.nodes[a].rect)}),b.rect=c.inflate(g.groupPadding)});var i=this.midPoints(this.cols.map(function(a){return a.x})),j=this.midPoints(this.rows.map(function(a){return a.y})),k=i[0],l=i[i.length-1],m=j[0],n=j[j.length-1],o=this.rows.map(function(a){return{x1:k,x2:l,y1:a.y,y2:a.y}}).concat(j.map(function(a){return{x1:k,x2:l,y1:a,y2:a}})),p=this.cols.map(function(a){return{x1:a.x,x2:a.x,y1:m,y2:n}}).concat(i.map(function(a){return{x1:a,x2:a,y1:m,y2:n}})),q=o.concat(p);q.forEach(function(a){return a.verts=[]}),this.verts=[],this.edges=[],o.forEach(function(a){return p.forEach(function(b){var d=new c(g.verts.length,b.x1,a.y1);a.verts.push(d),b.verts.push(d),g.verts.push(d);for(var e=g.backToFront.length;e-->0;){var f=g.backToFront[e],h=f.rect,i=Math.abs(d.x-h.cx()),j=Math.abs(d.y-h.cy());if(i0;){var d=c[0].rect,e=c.filter(function(b){return b.rect["overlap"+a.toUpperCase()](d)});b.push(e),e.forEach(function(a){return c.splice(c.indexOf(a),1)}),e[a]=this.avg(e.map(function(b){return b.rect["c"+a]()}))}return b.sort(function(b,c){return b[a]-c[a]}),b},d.prototype.getDepth=function(a){for(var b=0;a.parent!==this.root;)b++,a=a.parent;return b},d.prototype.midPoints=function(a){for(var b=a[1]-a[0],c=[a[0]-b/2],d=1;d.1)&&(j={pos:g[0][b],segments:[]},i.push(j)),j.segments.push(g)}return i},d.nudgeSegs=function(b,c,d,e,f,g){var h=e.length;if(!(1>=h)){for(var i=e.map(function(c){return new a.vpsc.Variable(c[0][b])}),j=[],k=0;h>k;k++)for(var l=0;h>l;l++)if(k!==l){var m=e[k],n=e[l],o=m.edgeid,p=n.edgeid,q=-1,r=-1;"x"==b?f(o,p)&&(m[0][c]=0&&j.push(new a.vpsc.Constraint(i[q],i[r],g))}var s=new a.vpsc.Solver(i,j);s.solve(),i.forEach(function(a,c){var f=e[c],g=a.position();f[0][b]=f[1][b]=g;var h=d[f.edgeid];f.i>0&&(h[f.i-1][1][b]=g),f.iMath.PI||e<-Math.PI)&&(e=d-c),e},d.isLeft=function(a,b,c){return(b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x)<=0},d.getOrder=function(a){for(var b={},c=0;c=j.length||l.ti+l.length>=k.length?(g=j[l.si+1],i=j[l.si-1],h=k[l.ti-1]):(g=j[l.si+l.length-2],h=j[l.si+l.length],i=k[l.ti+l.length]),c.push(d.isLeft(g,h,i)?{l:f,r:e}:{l:e,r:f})):c.push({l:e,r:f}))}return a.GridRouter.getOrder(c)},d.makeSegments=function(a){function b(a){return{x:a.x,y:a.y}}for(var c=function(a,b,c){return Math.abs((b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x))<.001},d=[],e=b(a[0]),f=1;f1&&k>1?1e3:0},p=n.PathFromNodeToNodeWithPrevCost(e.ports[0].id,f.ports[0].id,o),q=p.reverse().map(function(a){return d.verts[a]});return q.push(this.nodes[f.id].ports[0]),q.filter(function(a,b){return!(b0&&a.node===f&&q[b-1].node===f)})},d}();a.GridRouter=e}(cola||(cola={}));var cola;!function(a){function b(a,b){var c={};for(var d in a)c[d]={};for(var d in b)c[d]={};return Object.keys(c).length}function c(a,b){var c=0;for(var d in a)"undefined"!=typeof b[d]&&++c;return c}function d(a,b){var c={},d=function(a,b){"undefined"==typeof c[a]&&(c[a]={}),c[a][b]={}};return a.forEach(function(a){var c=b.getSourceIndex(a),e=b.getTargetIndex(a);d(c,e),d(e,c)}),c}function e(a,b,c,e){var f=d(a,e);a.forEach(function(a){var d=f[e.getSourceIndex(a)],g=f[e.getTargetIndex(a)];e.setLength(a,1+b*c(d,g))})}function f(a,d,f){void 0===f&&(f=1),e(a,f,function(a,d){return Math.sqrt(b(a,d)-c(a,d))},d)}function g(a,d,f){void 0===f&&(f=1),e(a,f,function(a,d){return Math.min(Object.keys(a).length,Object.keys(d).length)<1.1?0:c(a,d)/b(a,d)},d)}function h(a,b,c,d){var e=i(a,b,d),f={};e.filter(function(a){return a.length>1}).forEach(function(a){return a.forEach(function(b){return f[b]=a})});var g=[];return b.forEach(function(a){var b=d.getSourceIndex(a),e=d.getTargetIndex(a),h=f[b],i=f[e];h&&i&&h.component===i.component||g.push({axis:c,left:b,right:e,gap:d.getMinSeparation(a)})}),g}function i(a,b,c){function d(a){f[a]=j,g[a]=j,h[a]=!0,j+=1,k.push(a);for(var b=e[a],c=0;c=0;--c){var n=k[c];if(h[n]=!1,m.push(n),n===a){k.length=c;break}}l.push(m)}}for(var e=new Array(a),f=new Array(a),g=new Array(a),h=new Array(a),i=0;a>i;++i)e[i]=[],f[i]=-1,g[i]=0,h[i]=!1;for(var i=0;ii;++i)f[i]<0&&d(i);return l}a.symmetricDiffLinkLengths=f,a.jaccardLinkLengths=g,a.generateDirectedEdgeConstraints=h}(cola||(cola={}));var cola;!function(a){var b;!function(a){function b(a,c,d){a.forAll(function(a){if(a.isLeaf())c.leaves||(c.leaves=[]),c.leaves.push(a.id);else{var e=c;a.gid=d.length,(!a.isIsland()||a.predefined)&&(e={id:a.gid},c.groups||(c.groups=[]),c.groups.push(a.gid),d.push(e)),b(a.children,e,d)}})}function c(a,b){var c={};for(var d in a)d in b&&(c[d]=a[d]);return c}function d(b,c,d,e){for(var f=b.length,g=new a.Configuration(f,c,d,e);g.greedyMerge(););var h=[],i=g.getGroupHierarchy(h);return h.forEach(function(a){var c=function(c){var d=a[c];"number"==typeof d&&(a[c]=b[d])};c("source"),c("target")}),{groups:i,powerEdges:h}}var e=function(){function a(a,b,c){this.source=a,this.target=b,this.type=c}return a}();a.PowerEdge=e;var f=function(){function a(a,b,c,d){var e=this;if(this.linkAccessor=c,this.modules=new Array(a),this.roots=[],d)this.initModulesFromGroup(d);else{this.roots.push(new h);for(var f=0;a>f;++f)this.roots[0].add(this.modules[f]=new g(f))}this.R=b.length,b.forEach(function(a){var b=e.modules[c.getSourceIndex(a)],d=e.modules[c.getTargetIndex(a)],f=c.getType(a);b.outgoing.add(f,d),d.incoming.add(f,b)})}return a.prototype.initModulesFromGroup=function(a){var b=new h;this.roots.push(b);for(var c=0;cf;++f)for(var h=f+1;c>h;++h){var i=b[f],j=b[h];d[e++]={nEdges:this.nEdges(i,j),a:i,b:j}}return d},a.prototype.greedyMerge=function(){for(var a=0;a=this.R))return this.merge(c.a,c.b,a),!0}},a.prototype.nEdges=function(a,b){var c=a.incoming.intersection(b.incoming),d=a.outgoing.intersection(b.outgoing);return this.R-c.count()-d.count()},a.prototype.getGroupHierarchy=function(a){var c=this,d=[],f={};b(this.roots[0],f,d);var g=this.allEdges();return g.forEach(function(b){var f=c.modules[b.source],g=c.modules[b.target];a.push(new e("undefined"==typeof f.gid?b.source:d[f.gid],"undefined"==typeof g.gid?b.target:d[g.gid],b.type))}),d},a.prototype.allEdges=function(){var b=[];return a.getEdges(this.roots[0],b),b},a.getEdges=function(b,c){b.forAll(function(b){b.getEdges(c),a.getEdges(b.children,c)})},a}();a.Configuration=f;var g=function(){function a(a,b,c,d,e){void 0===b&&(b=new i),void 0===c&&(c=new i),void 0===d&&(d=new h),void 0===e&&(e=!1),this.id=a,this.outgoing=b,this.incoming=c,this.children=d,this.predefined=e}return a.prototype.getEdges=function(a){var b=this;this.outgoing.forAll(function(c,d){c.forAll(function(c){a.push(new e(b.id,c.id,d))})})},a.prototype.isLeaf=function(){return 0===this.children.count()},a.prototype.isIsland=function(){return 0===this.outgoing.count()&&0===this.incoming.count()},a}();a.Module=g;var h=function(){function a(){this.table={}}return a.prototype.count=function(){return Object.keys(this.table).length},a.prototype.intersection=function(b){var d=new a;return d.table=c(this.table,b.table),d},a.prototype.intersectionCount=function(a){return this.intersection(a).count()},a.prototype.contains=function(a){return a in this.table},a.prototype.add=function(a){this.table[a.id]=a},a.prototype.remove=function(a){delete this.table[a.id]},a.prototype.forAll=function(a){for(var b in this.table)a(this.table[b])},a.prototype.modules=function(){var a=[];return this.forAll(function(b){b.predefined||a.push(b)}),a},a}();a.ModuleSet=h;var i=function(){function a(){this.sets={},this.n=0}return a.prototype.count=function(){return this.n},a.prototype.contains=function(a){var b=!1;return this.forAllModules(function(c){b||c.id!=a||(b=!0)}),b},a.prototype.add=function(a,b){var c=a in this.sets?this.sets[a]:this.sets[a]=new h;c.add(b),++this.n},a.prototype.remove=function(a,b){var c=this.sets[a];c.remove(b),0===c.count()&&delete this.sets[a],--this.n},a.prototype.forAll=function(a){for(var b in this.sets)a(this.sets[b],b)},a.prototype.forAllModules=function(a){this.forAll(function(b){return b.forAll(a)})},a.prototype.intersection=function(b){var c=new a;return this.forAll(function(a,d){if(d in b.sets){var e=a.intersection(b.sets[d]),f=e.count();f>0&&(c.sets[d]=e,c.n+=f)}}),c},a}();a.LinkSets=i,a.getGroups=d}(b=a.powergraph||(a.powergraph={}))}(cola||(cola={}));var cola;!function(a){function b(a){a.fixed|=2,a.px=a.x,a.py=a.y}function c(a){a.fixed&=-7}function d(a){a.fixed|=4,a.px=a.x,a.py=a.y}function e(a){a.fixed&=-5}return a.d3adaptor=function(){var d=d3.dispatch("start","tick","end"),e=a.adaptor({trigger:function(a){d[a.type](a)},on:function(a,b){return d.on(a,b),e},kick:function(a){d3.timer(a)},drag:function(){var a=d3.behavior.drag().origin(function(a){return a}).on("dragstart.d3adaptor",b).on("drag.d3adaptor",function(a){a.px=d3.event.x,a.py=d3.event.y,e.resume()}).on("dragend.d3adaptor",c);return arguments.length?void this.call(a):a}});return e},a.adaptor=function(f){function g(a){return"function"==typeof r?+r.call(null,a):r}function h(a,b){a.length=b}function i(a){return"function"==typeof t?t(a):0}function j(a){return"number"==typeof a.source?a.source:a.source.index}function k(a){return"number"==typeof a.target?a.target:a.target.index}var l,m,n={},o=f.trigger,p=f.kick,q=[1,1],r=20,s=null,t=null,u=!1,v=!0,w=!1,x=[],y=[],z=[],A=null,B=[],C=[],D=null,E=null,F=null,G=.01,H=10,I=null;n.on=f.on,n.drag=f.drag,n.dragstart=b,n.dragend=c,n.mouseover=d,n.mouseout=e,n.tick=function(){if(G>l)return w=!1,o({type:"end",alpha:l=0,stress:m}),delete m,!0;{var a,b=x.length;B.length}E.locks.clear();for(var c=0;b>c;++c)if(a=x[c],a.fixed){("undefined"==typeof a.px||"undefined"==typeof a.py)&&(a.px=a.x,a.py=a.y);var d=[a.px,a.py];E.locks.add(c,d)}var e=E.rungeKutta();0===e?l=0:"undefined"!=typeof m&&(l=Math.abs(Math.abs(m/e)-1)),m=e;for(var c=0;b>c;++c)a=x[c],a.fixed?(a.x=a.px,a.y=a.py):(a.x=E.x[0][c],a.y=E.x[1][c]);o({type:"tick",alpha:l,stress:m})},n.nodes=function(a){if(!arguments.length){if(0===x.length&&B.length>0){var b=0;B.forEach(function(a){b=Math.max(b,a.source,a.target)}),x=new Array(++b);for(var c=0;b>c;++c)x[c]={}}return x}return x=a,n},n.groups=function(a){return arguments.length?(y=a,A={},y.forEach(function(a){"undefined"==typeof a.padding&&(a.padding=1),"undefined"!=typeof a.leaves&&a.leaves.forEach(function(b,c){(a.leaves[c]=x[b]).parent=a}),"undefined"!=typeof a.groups&&a.groups.forEach(function(b,c){(a.groups[c]=y[b]).parent=a})}),A.leaves=x.filter(function(a){return"undefined"==typeof a.parent}),A.groups=y.filter(function(a){return"undefined"==typeof a.parent}),n):y},n.powerGraphGroups=function(b){var c=a.powergraph.getGroups(x,B,J,A);return this.groups(c.groups),b(c),n},n.avoidOverlaps=function(a){return arguments.length?(u=a,n):u},n.handleDisconnected=function(a){return arguments.length?(v=a,n):v},n.flowLayout=function(a,b){return arguments.length||(a="y"),F={axis:a,getMinSeparation:"number"==typeof b?function(){return b}:b},n},n.links=function(a){return arguments.length?(B=a,n):B},n.constraints=function(a){return arguments.length?(C=a,n):C},n.distanceMatrix=function(a){return arguments.length?(D=a,n):D},n.size=function(a){return arguments.length?(q=a,n):q},n.defaultNodeSize=function(a){return arguments.length?(H=a,n):H},n.linkDistance=function(a){return arguments.length?(r="function"==typeof a?a:+a,s=null,n):"function"==typeof r?r():r},n.linkType=function(a){return t=a,n},n.convergenceThreshold=function(a){return arguments.length?(G="function"==typeof a?a:+a,n):G},n.alpha=function(a){return arguments.length?(a=+a,l?l=a>0?a:0:a>0&&(w||(w=!0,o({type:"start",alpha:l=a}),p(n.tick))),n):l};var J={getSourceIndex:j,getTargetIndex:k,setLength:h,getType:i};return n.symmetricDiffLinkLengths=function(b,c){return this.linkDistance(function(a){return b*a.length}),s=function(){a.symmetricDiffLinkLengths(B,J,c)},n},n.jaccardLinkLengths=function(b,c){return this.linkDistance(function(a){return b*a.length}),s=function(){a.jaccardLinkLengths(B,J,c)},n},n.start=function(){var b,c=this.nodes().length,d=c+2*y.length,e=(B.length,q[0]),f=q[1];s&&s();var h=new Array(d),i=new Array(d);z=new Array(d);var l=null,m=this.avoidOverlaps();x.forEach(function(a,b){a.index=b,"undefined"==typeof a.x&&(a.x=e/2,a.y=f/2),h[b]=a.x,i[b]=a.y});var o;D?o=D:(o=new a.shortestpaths.Calculator(d,B,j,k,g).DistanceMatrix(),l=a.Descent.createSquareMatrix(d,function(){return 2}),B.forEach(function(a){var b=j(a),c=k(a);l[b][c]=l[c][b]=1}));var p=a.Descent.createSquareMatrix(d,function(a,b){return o[a][b]});if(A&&"undefined"!=typeof A.groups){var b=c;y.forEach(function(){l[b][b+1]=l[b+1][b]=1e-6,p[b][b+1]=p[b+1][b]=.1,h[b]=0,i[b++]=0,h[b]=0,i[b++]=0})}else A={leaves:x,groups:[]};var r=C||[];F&&(J.getMinSeparation=F.getMinSeparation,r=r.concat(a.generateDirectedEdgeConstraints(c,B,F.axis,J)));var t=arguments.length>0?arguments[0]:0,u=arguments.length>1?arguments[1]:0,w=arguments.length>2?arguments[2]:0;this.avoidOverlaps(!1),E=new a.Descent([h,i],p),E.locks.clear();for(var b=0;c>b;++b){var I=x[b];if(I.fixed){I.px=I.x,I.py=I.y;var K=[I.x,I.y];E.locks.add(b,K)}}return E.threshold=G,E.run(t),r.length>0&&(E.project=new a.vpsc.Projection(x,y,A,r).projectFunctions()),E.run(u),this.avoidOverlaps(m),m&&(x.forEach(function(a,b){a.x=h[b],a.y=i[b]}),E.project=new a.vpsc.Projection(x,y,A,r,!0).projectFunctions(),x.forEach(function(a,b){h[b]=a.x,i[b]=a.y})),E.G=l,E.run(w),B.forEach(function(a){"number"==typeof a.source&&(a.source=x[a.source]),"number"==typeof a.target&&(a.target=x[a.target])}),x.forEach(function(a,b){a.x=h[b],a.y=i[b]}),!D&&v&&(a.applyPacking(a.separateGraphs(x,B),e,f,H),x.forEach(function(a,b){E.x[0][b]=a.x,E.x[1][b]=a.y})),n.resume()},n.resume=function(){return n.alpha(.1)},n.stop=function(){return n.alpha(0)},n.prepareEdgeRouting=function(b){I=new a.geom.TangentVisibilityGraph(x.map(function(a){return a.bounds.inflate(-b).vertices()}))},n.routeEdge=function(b,c){var d=[],e=new a.geom.TangentVisibilityGraph(I.P,{V:I.V,E:I.E}),f={x:b.source.x,y:b.source.y},g={x:b.target.x,y:b.target.y},h=e.addPoint(f,b.source.id),i=e.addPoint(g,b.target.id);e.addEdgeIfVisible(f,g,b.source.id,b.target.id),"undefined"!=typeof c&&c(e);var j=function(a){return a.source.id},k=function(a){return a.target.id},l=function(a){return a.length()},m=new a.shortestpaths.Calculator(e.V.length,e.E,j,k,l),n=m.PathFromNodeToNode(h.id,i.id);if(1===n.length||n.length===e.V.length)a.vpsc.makeEdgeBetween(b,b.source.innerBounds,b.target.innerBounds,5),d=[{x:b.sourceIntersection.x,y:b.sourceIntersection.y},{x:b.arrowStart.x,y:b.arrowStart.y}];else{for(var o=n.length-2,p=e.V[n[o]].p,q=e.V[n[0]].p,d=[b.source.innerBounds.rayIntersection(p.x,p.y)],r=o;r>=0;--r)d.push(e.V[n[r]].p);d.push(a.vpsc.makeEdgeTo(q,b.target.innerBounds,5))}return d},n.linkId=function(a){return j(a)+"-"+k(a)},n},a}(cola||(cola={})),RBTree=function(a){var b=function(a){var c=b.m[a];if(c.mod)return c.mod.exports;var d=c.mod={exports:{}};return c(d,d.exports),d.exports};return b.m={},b.m["./treebase"]=function(a){function b(){}function c(a){this._tree=a,this._ancestors=[],this._cursor=null}b.prototype.clear=function(){this._root=null,this.size=0},b.prototype.find=function(a){for(var b=this._root;null!==b;){var c=this._comparator(a,b.data);if(0===c)return b.data;b=b.get_child(c>0)}return null},b.prototype.findIter=function(a){for(var b=this._root,c=this.iterator();null!==b;){var d=this._comparator(a,b.data);if(0===d)return c._cursor=b,c;c._ancestors.push(b),b=b.get_child(d>0)}return null},b.prototype.lowerBound=function(a){return this._bound(a,this._comparator)},b.prototype.upperBound=function(a){function b(a,b){return c(b,a)}var c=this._comparator;return this._bound(a,b)},b.prototype.min=function(){var a=this._root;if(null===a)return null;for(;null!==a.left;)a=a.left;return a.data},b.prototype.max=function(){var a=this._root;if(null===a)return null;for(;null!==a.right;)a=a.right;return a.data},b.prototype.iterator=function(){return new c(this)},b.prototype.each=function(a){for(var b,c=this.iterator();null!==(b=c.next());)a(b)},b.prototype.reach=function(a){for(var b,c=this.iterator();null!==(b=c.prev());)a(b)},b.prototype._bound=function(a,b){for(var c=this._root,d=this.iterator();null!==c;){var e=this._comparator(a,c.data);if(0===e)return d._cursor=c,d;d._ancestors.push(c),c=c.get_child(e>0)}for(var f=d._ancestors.length-1;f>=0;--f)if(c=d._ancestors[f],b(a,c.data)>0)return d._cursor=c,d._ancestors.length=f,d;return d._ancestors.length=0,d},c.prototype.data=function(){return null!==this._cursor?this._cursor.data:null},c.prototype.next=function(){if(null===this._cursor){var a=this._tree._root;null!==a&&this._minNode(a)}else if(null===this._cursor.right){var b;do{if(b=this._cursor,!this._ancestors.length){this._cursor=null;break}this._cursor=this._ancestors.pop()}while(this._cursor.right===b)}else this._ancestors.push(this._cursor),this._minNode(this._cursor.right);return null!==this._cursor?this._cursor.data:null},c.prototype.prev=function(){if(null===this._cursor){var a=this._tree._root;null!==a&&this._maxNode(a)}else if(null===this._cursor.left){var b;do{if(b=this._cursor,!this._ancestors.length){this._cursor=null;break}this._cursor=this._ancestors.pop()}while(this._cursor.left===b)}else this._ancestors.push(this._cursor),this._maxNode(this._cursor.left);return null!==this._cursor?this._cursor.data:null},c.prototype._minNode=function(a){for(;null!==a.left;)this._ancestors.push(a),a=a.left;this._cursor=a},c.prototype._maxNode=function(a){for(;null!==a.right;)this._ancestors.push(a),a=a.right;this._cursor=a},a.exports=b},b.m.__main__=function(a){function c(a){this.data=a,this.left=null,this.right=null,this.red=!0}function d(a){this._root=null,this._comparator=a,this.size=0}function e(a){return null!==a&&a.red}function f(a,b){var c=a.get_child(!b);return a.set_child(!b,c.get_child(b)),c.set_child(b,a),a.red=!0,c.red=!1,c}function g(a,b){return a.set_child(!b,f(a.get_child(!b),!b)),f(a,b)}var h=b("./treebase");c.prototype.get_child=function(a){return a?this.right:this.left},c.prototype.set_child=function(a,b){a?this.right=b:this.left=b},d.prototype=new h,d.prototype.insert=function(a){var b=!1;if(null===this._root)this._root=new c(a),b=!0,this.size++;else{var d=new c(void 0),h=0,i=0,j=null,k=d,l=null,m=this._root;for(k.right=this._root;;){if(null===m?(m=new c(a),l.set_child(h,m),b=!0,this.size++):e(m.left)&&e(m.right)&&(m.red=!0,m.left.red=!1,m.right.red=!1),e(m)&&e(l)){var n=k.right===j;m===l.get_child(i)?k.set_child(n,f(j,!i)):k.set_child(n,g(j,!i))}var o=this._comparator(m.data,a);if(0===o)break;i=h,h=0>o,null!==j&&(k=j),j=l,l=m,m=m.get_child(h)}this._root=d.right}return this._root.red=!1,b},d.prototype.remove=function(a){if(null===this._root)return!1;var b=new c(void 0),d=b;d.right=this._root;for(var h=null,i=null,j=null,k=1;null!==d.get_child(k);){var l=k;i=h,h=d,d=d.get_child(k);var m=this._comparator(a,d.data);if(k=m>0,0===m&&(j=d),!e(d)&&!e(d.get_child(k)))if(e(d.get_child(!k))){var n=f(d,k);h.set_child(l,n),h=n}else if(!e(d.get_child(!k))){var o=h.get_child(!l);if(null!==o)if(e(o.get_child(!l))||e(o.get_child(l))){var p=i.right===h;e(o.get_child(l))?i.set_child(p,g(h,l)):e(o.get_child(!l))&&i.set_child(p,f(h,l));var q=i.get_child(p);q.red=!0,d.red=!0,q.left.red=!1,q.right.red=!1}else h.red=!1,o.red=!0,d.red=!0}}return null!==j&&(j.data=d.data,h.set_child(h.right===d,d.get_child(null===d.left)),this.size--),this._root=b.right,null!==this._root&&(this._root.red=!1),null!==j},a.exports=d},b("__main__")}(window);var cola;!function(a){var b={};return b.PADDING=10,b.GOLDEN_SECTION=(1+Math.sqrt(5))/2,b.FLOAT_EPSILON=1e-4,b.MAX_INERATIONS=100,a.applyPacking=function(a,c,d,e,f){function g(a){function b(a){var b=Number.MAX_VALUE,c=Number.MAX_VALUE,d=0,f=0;a.array.forEach(function(a){var g="undefined"!=typeof a.width?a.width:e,h="undefined"!=typeof a.height?a.height:e;g/=2,h/=2,d=Math.max(a.x+g,d),b=Math.min(a.x-g,b),f=Math.max(a.y+h,f),c=Math.min(a.y-h,c)}),a.width=d-b,a.height=f-c}a.forEach(function(a){b(a)})}function h(a){a.forEach(function(a){var b={x:0,y:0};a.array.forEach(function(a){b.x+=a.x,b.y+=a.y}),b.x/=a.array.length,b.y/=a.array.length;var c={x:b.x-a.width/2,y:b.y-a.height/2},d={x:a.x-c.x,y:a.y-c.y};a.array.forEach(function(a){a.x=a.x+d.x+p/2-r/2,a.y=a.y+d.y+q/2-s/2})})}function i(a){var c=Number.POSITIVE_INFINITY,d=0;a.sort(function(a,b){return b.height-a.height}),t=a.reduce(function(a,b){return a.widtht||n>b.FLOAT_EPSILON;){if(1!=k)var o=f-(f-e)/b.GOLDEN_SECTION,h=j(a,o);if(0!=k)var p=e+(f-e)/b.GOLDEN_SECTION,i=j(a,p);if(m=Math.abs(o-p),n=Math.abs(h-i),c>h&&(c=h,d=o),c>i&&(c=i,d=p),h>i?(e=o,o=p,h=i,k=1):(f=p,p=o,i=h,k=0),g++>100)break}j(a,d)}function j(a,b){v=[],r=0,s=0,u=o;for(var c=0;c=a.height&&v[e].x+v[e].width+a.width+b.PADDING-c<=b.FLOAT_EPSILON){d=v[e];break}v.push(a),void 0!==d?(a.x=d.x+d.width+b.PADDING,a.y=d.bottom,a.space_left=a.height,a.bottom=a.y,d.space_left-=a.height+b.PADDING,d.bottom+=a.height+b.PADDING):(a.y=u,u+=a.height+b.PADDING,a.x=n,a.bottom=a.y,a.space_left=a.height),a.y+a.height-s>-b.FLOAT_EPSILON&&(s=a.y+a.height-o),a.x+a.width-r>-b.FLOAT_EPSILON&&(r=a.x+a.width-n)}function l(a){var c=0;return a.forEach(function(a){return c+=a.width+b.PADDING}),c}function m(){return r/s}var n=0,o=0,p=c,q=d,f="undefined"!=typeof f?f:1,e="undefined"!=typeof e?e:0,r=0,s=0,t=0,u=0,v=[];0!=a.length&&(g(a),i(a),h(a))},a.separateGraphs=function(a,b){function c(a,b){if(void 0===d[a.index]){b&&(g++,f.push({array:[]})),d[a.index]=g,f[g-1].array.push(a);var h=e[a.index];if(h)for(var i=0;i