dagre-d3
Version:
A D3-based renderer for Dagre
150 lines • 725 kB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.dagreD3=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r}()({1:[function(require,module,exports){
/**
* @license
* Copyright (c) 2012-2013 Chris Pettitt
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
module.exports={graphlib:require("./lib/graphlib"),dagre:require("./lib/dagre"),intersect:require("./lib/intersect"),render:require("./lib/render"),util:require("./lib/util"),version:require("./lib/version")}},{"./lib/dagre":8,"./lib/graphlib":9,"./lib/intersect":10,"./lib/render":25,"./lib/util":27,"./lib/version":28}],2:[function(require,module,exports){var util=require("./util");module.exports={default:normal,normal:normal,vee:vee,undirected:undirected};function normal(parent,id,edge,type){var marker=parent.append("marker").attr("id",id).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto");var path=marker.append("path").attr("d","M 0 0 L 10 5 L 0 10 z").style("stroke-width",1).style("stroke-dasharray","1,0");util.applyStyle(path,edge[type+"Style"]);if(edge[type+"Class"]){path.attr("class",edge[type+"Class"])}}function vee(parent,id,edge,type){var marker=parent.append("marker").attr("id",id).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto");var path=marker.append("path").attr("d","M 0 0 L 10 5 L 0 10 L 4 5 z").style("stroke-width",1).style("stroke-dasharray","1,0");util.applyStyle(path,edge[type+"Style"]);if(edge[type+"Class"]){path.attr("class",edge[type+"Class"])}}function undirected(parent,id,edge,type){var marker=parent.append("marker").attr("id",id).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto");var path=marker.append("path").attr("d","M 0 5 L 10 5").style("stroke-width",1).style("stroke-dasharray","1,0");util.applyStyle(path,edge[type+"Style"]);if(edge[type+"Class"]){path.attr("class",edge[type+"Class"])}}},{"./util":27}],3:[function(require,module,exports){var util=require("./util");var d3=require("./d3");var addLabel=require("./label/add-label");module.exports=createClusters;function createClusters(selection,g){var clusters=g.nodes().filter(function(v){return util.isSubgraph(g,v)});var svgClusters=selection.selectAll("g.cluster").data(clusters,function(v){return v});svgClusters.selectAll("*").remove();svgClusters.enter().append("g").attr("class","cluster").attr("id",function(v){var node=g.node(v);return node.id}).style("opacity",0);svgClusters=selection.selectAll("g.cluster");util.applyTransition(svgClusters,g).style("opacity",1);svgClusters.each(function(v){var node=g.node(v);var thisGroup=d3.select(this);d3.select(this).append("rect");var labelGroup=thisGroup.append("g").attr("class","label");addLabel(labelGroup,node,node.clusterLabelPos)});svgClusters.selectAll("rect").each(function(c){var node=g.node(c);var domCluster=d3.select(this);util.applyStyle(domCluster,node.style)});var exitSelection;if(svgClusters.exit){exitSelection=svgClusters.exit()}else{exitSelection=svgClusters.selectAll(null);// empty selection
}util.applyTransition(exitSelection,g).style("opacity",0).remove();return svgClusters}},{"./d3":7,"./label/add-label":18,"./util":27}],4:[function(require,module,exports){"use strict";var _=require("./lodash");var addLabel=require("./label/add-label");var util=require("./util");var d3=require("./d3");module.exports=createEdgeLabels;function createEdgeLabels(selection,g){var svgEdgeLabels=selection.selectAll("g.edgeLabel").data(g.edges(),function(e){return util.edgeToId(e)}).classed("update",true);svgEdgeLabels.exit().remove();svgEdgeLabels.enter().append("g").classed("edgeLabel",true).style("opacity",0);svgEdgeLabels=selection.selectAll("g.edgeLabel");svgEdgeLabels.each(function(e){var root=d3.select(this);root.select(".label").remove();var edge=g.edge(e);var label=addLabel(root,g.edge(e),0,0).classed("label",true);var bbox=label.node().getBBox();if(edge.labelId){label.attr("id",edge.labelId)}if(!_.has(edge,"width")){edge.width=bbox.width}if(!_.has(edge,"height")){edge.height=bbox.height}});var exitSelection;if(svgEdgeLabels.exit){exitSelection=svgEdgeLabels.exit()}else{exitSelection=svgEdgeLabels.selectAll(null);// empty selection
}util.applyTransition(exitSelection,g).style("opacity",0).remove();return svgEdgeLabels}},{"./d3":7,"./label/add-label":18,"./lodash":21,"./util":27}],5:[function(require,module,exports){"use strict";var _=require("./lodash");var intersectNode=require("./intersect/intersect-node");var util=require("./util");var d3=require("./d3");module.exports=createEdgePaths;function createEdgePaths(selection,g,arrows){var previousPaths=selection.selectAll("g.edgePath").data(g.edges(),function(e){return util.edgeToId(e)}).classed("update",true);var newPaths=enter(previousPaths,g);exit(previousPaths,g);var svgPaths=previousPaths.merge!==undefined?previousPaths.merge(newPaths):previousPaths;util.applyTransition(svgPaths,g).style("opacity",1);
// Save DOM element in the path group, and set ID and class
svgPaths.each(function(e){var domEdge=d3.select(this);var edge=g.edge(e);edge.elem=this;if(edge.id){domEdge.attr("id",edge.id)}util.applyClass(domEdge,edge["class"],(domEdge.classed("update")?"update ":"")+"edgePath")});svgPaths.selectAll("path.path").each(function(e){var edge=g.edge(e);edge.arrowheadId=_.uniqueId("arrowhead");var domEdge=d3.select(this).attr("marker-end",function(){return"url("+makeFragmentRef(location.href,edge.arrowheadId)+")"}).style("fill","none");util.applyTransition(domEdge,g).attr("d",function(e){return calcPoints(g,e)});util.applyStyle(domEdge,edge.style)});svgPaths.selectAll("defs *").remove();svgPaths.selectAll("defs").each(function(e){var edge=g.edge(e);var arrowhead=arrows[edge.arrowhead];arrowhead(d3.select(this),edge.arrowheadId,edge,"arrowhead")});return svgPaths}function makeFragmentRef(url,fragmentId){var baseUrl=url.split("#")[0];return baseUrl+"#"+fragmentId}function calcPoints(g,e){var edge=g.edge(e);var tail=g.node(e.v);var head=g.node(e.w);var points=edge.points.slice(1,edge.points.length-1);points.unshift(intersectNode(tail,points[0]));points.push(intersectNode(head,points[points.length-1]));return createLine(edge,points)}function createLine(edge,points){var line=(d3.line||d3.svg.line)().x(function(d){return d.x}).y(function(d){return d.y});(line.curve||line.interpolate)(edge.curve);return line(points)}function getCoords(elem){var bbox=elem.getBBox();var matrix=elem.ownerSVGElement.getScreenCTM().inverse().multiply(elem.getScreenCTM()).translate(bbox.width/2,bbox.height/2);return{x:matrix.e,y:matrix.f}}function enter(svgPaths,g){var svgPathsEnter=svgPaths.enter().append("g").attr("class","edgePath").style("opacity",0);svgPathsEnter.append("path").attr("class","path").attr("d",function(e){var edge=g.edge(e);var sourceElem=g.node(e.v).elem;var points=_.range(edge.points.length).map(function(){return getCoords(sourceElem)});return createLine(edge,points)});svgPathsEnter.append("defs");return svgPathsEnter}function exit(svgPaths,g){var svgPathExit=svgPaths.exit();util.applyTransition(svgPathExit,g).style("opacity",0).remove()}},{"./d3":7,"./intersect/intersect-node":14,"./lodash":21,"./util":27}],6:[function(require,module,exports){"use strict";var _=require("./lodash");var addLabel=require("./label/add-label");var util=require("./util");var d3=require("./d3");module.exports=createNodes;function createNodes(selection,g,shapes){var simpleNodes=g.nodes().filter(function(v){return!util.isSubgraph(g,v)});var svgNodes=selection.selectAll("g.node").data(simpleNodes,function(v){return v}).classed("update",true);svgNodes.exit().remove();svgNodes.enter().append("g").attr("class","node").style("opacity",0);svgNodes=selection.selectAll("g.node");svgNodes.each(function(v){var node=g.node(v);var thisGroup=d3.select(this);util.applyClass(thisGroup,node["class"],(thisGroup.classed("update")?"update ":"")+"node");thisGroup.select("g.label").remove();var labelGroup=thisGroup.append("g").attr("class","label");var labelDom=addLabel(labelGroup,node);var shape=shapes[node.shape];var bbox=_.pick(labelDom.node().getBBox(),"width","height");node.elem=this;if(node.id){thisGroup.attr("id",node.id)}if(node.labelId){labelGroup.attr("id",node.labelId)}if(_.has(node,"width")){bbox.width=node.width}if(_.has(node,"height")){bbox.height=node.height}bbox.width+=node.paddingLeft+node.paddingRight;bbox.height+=node.paddingTop+node.paddingBottom;labelGroup.attr("transform","translate("+(node.paddingLeft-node.paddingRight)/2+","+(node.paddingTop-node.paddingBottom)/2+")");var root=d3.select(this);root.select(".label-container").remove();var shapeSvg=shape(root,bbox,node).classed("label-container",true);util.applyStyle(shapeSvg,node.style);var shapeBBox=shapeSvg.node().getBBox();node.width=shapeBBox.width;node.height=shapeBBox.height});var exitSelection;if(svgNodes.exit){exitSelection=svgNodes.exit()}else{exitSelection=svgNodes.selectAll(null);// empty selection
}util.applyTransition(exitSelection,g).style("opacity",0).remove();return svgNodes}},{"./d3":7,"./label/add-label":18,"./lodash":21,"./util":27}],7:[function(require,module,exports){
// Stub to get D3 either via NPM or from the global object
var d3;if(!d3){if(typeof require==="function"){try{d3=require("d3")}catch(e){
// continue regardless of error
}}}if(!d3){d3=window.d3}module.exports=d3},{d3:60}],8:[function(require,module,exports){
/* global window */
var dagre;if(typeof require==="function"){try{dagre=require("dagre")}catch(e){
// continue regardless of error
}}if(!dagre){dagre=window.dagre}module.exports=dagre},{dagre:61}],9:[function(require,module,exports){
/* global window */
var graphlib;if(typeof require==="function"){try{graphlib=require("graphlib")}catch(e){
// continue regardless of error
}}if(!graphlib){graphlib=window.graphlib}module.exports=graphlib},{graphlib:91}],10:[function(require,module,exports){module.exports={node:require("./intersect-node"),circle:require("./intersect-circle"),ellipse:require("./intersect-ellipse"),polygon:require("./intersect-polygon"),rect:require("./intersect-rect")}},{"./intersect-circle":11,"./intersect-ellipse":12,"./intersect-node":14,"./intersect-polygon":15,"./intersect-rect":16}],11:[function(require,module,exports){var intersectEllipse=require("./intersect-ellipse");module.exports=intersectCircle;function intersectCircle(node,rx,point){return intersectEllipse(node,rx,rx,point)}},{"./intersect-ellipse":12}],12:[function(require,module,exports){module.exports=intersectEllipse;function intersectEllipse(node,rx,ry,point){
// Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html
var cx=node.x;var cy=node.y;var px=cx-point.x;var py=cy-point.y;var det=Math.sqrt(rx*rx*py*py+ry*ry*px*px);var dx=Math.abs(rx*ry*px/det);if(point.x<cx){dx=-dx}var dy=Math.abs(rx*ry*py/det);if(point.y<cy){dy=-dy}return{x:cx+dx,y:cy+dy}}},{}],13:[function(require,module,exports){module.exports=intersectLine;
/*
* Returns the point at which two lines, p and q, intersect or returns
* undefined if they do not intersect.
*/function intersectLine(p1,p2,q1,q2){
// Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994,
// p7 and p473.
var a1,a2,b1,b2,c1,c2;var r1,r2,r3,r4;var denom,offset,num;var x,y;
// Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x +
// b1 y + c1 = 0.
a1=p2.y-p1.y;b1=p1.x-p2.x;c1=p2.x*p1.y-p1.x*p2.y;
// Compute r3 and r4.
r3=a1*q1.x+b1*q1.y+c1;r4=a1*q2.x+b1*q2.y+c1;
// Check signs of r3 and r4. If both point 3 and point 4 lie on
// same side of line 1, the line segments do not intersect.
if(r3!==0&&r4!==0&&sameSign(r3,r4)){return}
// Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0
a2=q2.y-q1.y;b2=q1.x-q2.x;c2=q2.x*q1.y-q1.x*q2.y;
// Compute r1 and r2
r1=a2*p1.x+b2*p1.y+c2;r2=a2*p2.x+b2*p2.y+c2;
// Check signs of r1 and r2. If both point 1 and point 2 lie
// on same side of second line segment, the line segments do
// not intersect.
if(r1!==0&&r2!==0&&sameSign(r1,r2)){return}
// Line segments intersect: compute intersection point.
denom=a1*b2-a2*b1;if(denom===0){return}offset=Math.abs(denom/2);
// The denom/2 is to get rounding instead of truncating. It
// is added or subtracted to the numerator, depending upon the
// sign of the numerator.
num=b1*c2-b2*c1;x=num<0?(num-offset)/denom:(num+offset)/denom;num=a2*c1-a1*c2;y=num<0?(num-offset)/denom:(num+offset)/denom;return{x:x,y:y}}function sameSign(r1,r2){return r1*r2>0}},{}],14:[function(require,module,exports){module.exports=intersectNode;function intersectNode(node,point){return node.intersect(point)}},{}],15:[function(require,module,exports){
/* eslint "no-console": off */
var intersectLine=require("./intersect-line");module.exports=intersectPolygon;
/*
* Returns the point ({x, y}) at which the point argument intersects with the
* node argument assuming that it has the shape specified by polygon.
*/function intersectPolygon(node,polyPoints,point){var x1=node.x;var y1=node.y;var intersections=[];var minX=Number.POSITIVE_INFINITY;var minY=Number.POSITIVE_INFINITY;polyPoints.forEach(function(entry){minX=Math.min(minX,entry.x);minY=Math.min(minY,entry.y)});var left=x1-node.width/2-minX;var top=y1-node.height/2-minY;for(var i=0;i<polyPoints.length;i++){var p1=polyPoints[i];var p2=polyPoints[i<polyPoints.length-1?i+1:0];var intersect=intersectLine(node,point,{x:left+p1.x,y:top+p1.y},{x:left+p2.x,y:top+p2.y});if(intersect){intersections.push(intersect)}}if(!intersections.length){console.log("NO INTERSECTION FOUND, RETURN NODE CENTER",node);return node}if(intersections.length>1){
// More intersections, find the one nearest to edge end point
intersections.sort(function(p,q){var pdx=p.x-point.x;var pdy=p.y-point.y;var distp=Math.sqrt(pdx*pdx+pdy*pdy);var qdx=q.x-point.x;var qdy=q.y-point.y;var distq=Math.sqrt(qdx*qdx+qdy*qdy);return distp<distq?-1:distp===distq?0:1})}return intersections[0]}},{"./intersect-line":13}],16:[function(require,module,exports){module.exports=intersectRect;function intersectRect(node,point){var x=node.x;var y=node.y;
// Rectangle intersection algorithm from:
// http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
var dx=point.x-x;var dy=point.y-y;var w=node.width/2;var h=node.height/2;var sx,sy;if(Math.abs(dy)*w>Math.abs(dx)*h){
// Intersection is top or bottom of rect.
if(dy<0){h=-h}sx=dy===0?0:h*dx/dy;sy=h}else{
// Intersection is left or right of rect.
if(dx<0){w=-w}sx=w;sy=dx===0?0:w*dy/dx}return{x:x+sx,y:y+sy}}},{}],17:[function(require,module,exports){var util=require("../util");module.exports=addHtmlLabel;function addHtmlLabel(root,node){var fo=root.append("foreignObject").attr("width","100000");var div=fo.append("xhtml:div");div.attr("xmlns","http://www.w3.org/1999/xhtml");var label=node.label;switch(typeof label){case"function":div.insert(label);break;case"object":
// Currently we assume this is a DOM object.
div.insert(function(){return label});break;default:div.html(label)}util.applyStyle(div,node.labelStyle);div.style("display","inline-block");
// Fix for firefox
div.style("white-space","nowrap");var client=div.node().getBoundingClientRect();fo.attr("width",client.width).attr("height",client.height);return fo}},{"../util":27}],18:[function(require,module,exports){var addTextLabel=require("./add-text-label");var addHtmlLabel=require("./add-html-label");var addSVGLabel=require("./add-svg-label");module.exports=addLabel;function addLabel(root,node,location){var label=node.label;var labelSvg=root.append("g");
// Allow the label to be a string, a function that returns a DOM element, or
// a DOM element itself.
if(node.labelType==="svg"){addSVGLabel(labelSvg,node)}else if(typeof label!=="string"||node.labelType==="html"){addHtmlLabel(labelSvg,node)}else{addTextLabel(labelSvg,node)}var labelBBox=labelSvg.node().getBBox();var y;switch(location){case"top":y=-node.height/2;break;case"bottom":y=node.height/2-labelBBox.height;break;default:y=-labelBBox.height/2}labelSvg.attr("transform","translate("+-labelBBox.width/2+","+y+")");return labelSvg}},{"./add-html-label":17,"./add-svg-label":19,"./add-text-label":20}],19:[function(require,module,exports){var util=require("../util");module.exports=addSVGLabel;function addSVGLabel(root,node){var domNode=root;domNode.node().appendChild(node.label);util.applyStyle(domNode,node.labelStyle);return domNode}},{"../util":27}],20:[function(require,module,exports){var util=require("../util");module.exports=addTextLabel;
/*
* Attaches a text label to the specified root. Handles escape sequences.
*/function addTextLabel(root,node){var domNode=root.append("text");var lines=processEscapeSequences(node.label).split("\n");for(var i=0;i<lines.length;i++){domNode.append("tspan").attr("xml:space","preserve").attr("dy","1em").attr("x","1").text(lines[i])}util.applyStyle(domNode,node.labelStyle);return domNode}function processEscapeSequences(text){var newText="";var escaped=false;var ch;for(var i=0;i<text.length;++i){ch=text[i];if(escaped){switch(ch){case"n":newText+="\n";break;default:newText+=ch}escaped=false}else if(ch==="\\"){escaped=true}else{newText+=ch}}return newText}},{"../util":27}],21:[function(require,module,exports){
/* global window */
var lodash;if(typeof require==="function"){try{lodash={defaults:require("lodash/defaults"),each:require("lodash/each"),isFunction:require("lodash/isFunction"),isPlainObject:require("lodash/isPlainObject"),pick:require("lodash/pick"),has:require("lodash/has"),range:require("lodash/range"),uniqueId:require("lodash/uniqueId")}}catch(e){
// continue regardless of error
}}if(!lodash){lodash=window._}module.exports=lodash},{"lodash/defaults":289,"lodash/each":290,"lodash/has":299,"lodash/isFunction":308,"lodash/isPlainObject":313,"lodash/pick":331,"lodash/range":333,"lodash/uniqueId":346}],22:[function(require,module,exports){"use strict";var util=require("./util");var d3=require("./d3");module.exports=positionClusters;function positionClusters(selection,g){var created=selection.filter(function(){return!d3.select(this).classed("update")});function translate(v){var node=g.node(v);return"translate("+node.x+","+node.y+")"}created.attr("transform",translate);util.applyTransition(selection,g).style("opacity",1).attr("transform",translate);util.applyTransition(created.selectAll("rect"),g).attr("width",function(v){return g.node(v).width}).attr("height",function(v){return g.node(v).height}).attr("x",function(v){var node=g.node(v);return-node.width/2}).attr("y",function(v){var node=g.node(v);return-node.height/2})}},{"./d3":7,"./util":27}],23:[function(require,module,exports){"use strict";var util=require("./util");var d3=require("./d3");var _=require("./lodash");module.exports=positionEdgeLabels;function positionEdgeLabels(selection,g){var created=selection.filter(function(){return!d3.select(this).classed("update")});function translate(e){var edge=g.edge(e);return _.has(edge,"x")?"translate("+edge.x+","+edge.y+")":""}created.attr("transform",translate);util.applyTransition(selection,g).style("opacity",1).attr("transform",translate)}},{"./d3":7,"./lodash":21,"./util":27}],24:[function(require,module,exports){"use strict";var util=require("./util");var d3=require("./d3");module.exports=positionNodes;function positionNodes(selection,g){var created=selection.filter(function(){return!d3.select(this).classed("update")});function translate(v){var node=g.node(v);return"translate("+node.x+","+node.y+")"}created.attr("transform",translate);util.applyTransition(selection,g).style("opacity",1).attr("transform",translate)}},{"./d3":7,"./util":27}],25:[function(require,module,exports){var _=require("./lodash");var d3=require("./d3");var layout=require("./dagre").layout;module.exports=render;
// This design is based on http://bost.ocks.org/mike/chart/.
function render(){var createNodes=require("./create-nodes");var createClusters=require("./create-clusters");var createEdgeLabels=require("./create-edge-labels");var createEdgePaths=require("./create-edge-paths");var positionNodes=require("./position-nodes");var positionEdgeLabels=require("./position-edge-labels");var positionClusters=require("./position-clusters");var shapes=require("./shapes");var arrows=require("./arrows");var fn=function(svg,g){preProcessGraph(g);var outputGroup=createOrSelectGroup(svg,"output");var clustersGroup=createOrSelectGroup(outputGroup,"clusters");var edgePathsGroup=createOrSelectGroup(outputGroup,"edgePaths");var edgeLabels=createEdgeLabels(createOrSelectGroup(outputGroup,"edgeLabels"),g);var nodes=createNodes(createOrSelectGroup(outputGroup,"nodes"),g,shapes);layout(g);positionNodes(nodes,g);positionEdgeLabels(edgeLabels,g);createEdgePaths(edgePathsGroup,g,arrows);var clusters=createClusters(clustersGroup,g);positionClusters(clusters,g);postProcessGraph(g)};fn.createNodes=function(value){if(!arguments.length)return createNodes;createNodes=value;return fn};fn.createClusters=function(value){if(!arguments.length)return createClusters;createClusters=value;return fn};fn.createEdgeLabels=function(value){if(!arguments.length)return createEdgeLabels;createEdgeLabels=value;return fn};fn.createEdgePaths=function(value){if(!arguments.length)return createEdgePaths;createEdgePaths=value;return fn};fn.shapes=function(value){if(!arguments.length)return shapes;shapes=value;return fn};fn.arrows=function(value){if(!arguments.length)return arrows;arrows=value;return fn};return fn}var NODE_DEFAULT_ATTRS={paddingLeft:10,paddingRight:10,paddingTop:10,paddingBottom:10,rx:0,ry:0,shape:"rect"};var EDGE_DEFAULT_ATTRS={arrowhead:"normal",curve:d3.curveLinear};function preProcessGraph(g){g.nodes().forEach(function(v){var node=g.node(v);if(!_.has(node,"label")&&!g.children(v).length){node.label=v}if(_.has(node,"paddingX")){_.defaults(node,{paddingLeft:node.paddingX,paddingRight:node.paddingX})}if(_.has(node,"paddingY")){_.defaults(node,{paddingTop:node.paddingY,paddingBottom:node.paddingY})}if(_.has(node,"padding")){_.defaults(node,{paddingLeft:node.padding,paddingRight:node.padding,paddingTop:node.padding,paddingBottom:node.padding})}_.defaults(node,NODE_DEFAULT_ATTRS);_.each(["paddingLeft","paddingRight","paddingTop","paddingBottom"],function(k){node[k]=Number(node[k])});
// Save dimensions for restore during post-processing
if(_.has(node,"width")){node._prevWidth=node.width}if(_.has(node,"height")){node._prevHeight=node.height}});g.edges().forEach(function(e){var edge=g.edge(e);if(!_.has(edge,"label")){edge.label=""}_.defaults(edge,EDGE_DEFAULT_ATTRS)})}function postProcessGraph(g){_.each(g.nodes(),function(v){var node=g.node(v);
// Restore original dimensions
if(_.has(node,"_prevWidth")){node.width=node._prevWidth}else{delete node.width}if(_.has(node,"_prevHeight")){node.height=node._prevHeight}else{delete node.height}delete node._prevWidth;delete node._prevHeight})}function createOrSelectGroup(root,name){var selection=root.select("g."+name);if(selection.empty()){selection=root.append("g").attr("class",name)}return selection}},{"./arrows":2,"./create-clusters":3,"./create-edge-labels":4,"./create-edge-paths":5,"./create-nodes":6,"./d3":7,"./dagre":8,"./lodash":21,"./position-clusters":22,"./position-edge-labels":23,"./position-nodes":24,"./shapes":26}],26:[function(require,module,exports){"use strict";var intersectRect=require("./intersect/intersect-rect");var intersectEllipse=require("./intersect/intersect-ellipse");var intersectCircle=require("./intersect/intersect-circle");var intersectPolygon=require("./intersect/intersect-polygon");module.exports={rect:rect,ellipse:ellipse,circle:circle,diamond:diamond};function rect(parent,bbox,node){var shapeSvg=parent.insert("rect",":first-child").attr("rx",node.rx).attr("ry",node.ry).attr("x",-bbox.width/2).attr("y",-bbox.height/2).attr("width",bbox.width).attr("height",bbox.height);node.intersect=function(point){return intersectRect(node,point)};return shapeSvg}function ellipse(parent,bbox,node){var rx=bbox.width/2;var ry=bbox.height/2;var shapeSvg=parent.insert("ellipse",":first-child").attr("x",-bbox.width/2).attr("y",-bbox.height/2).attr("rx",rx).attr("ry",ry);node.intersect=function(point){return intersectEllipse(node,rx,ry,point)};return shapeSvg}function circle(parent,bbox,node){var r=Math.max(bbox.width,bbox.height)/2;var shapeSvg=parent.insert("circle",":first-child").attr("x",-bbox.width/2).attr("y",-bbox.height/2).attr("r",r);node.intersect=function(point){return intersectCircle(node,r,point)};return shapeSvg}
// Circumscribe an ellipse for the bounding box with a diamond shape. I derived
// the function to calculate the diamond shape from:
// http://mathforum.org/kb/message.jspa?messageID=3750236
function diamond(parent,bbox,node){var w=bbox.width*Math.SQRT2/2;var h=bbox.height*Math.SQRT2/2;var points=[{x:0,y:-h},{x:-w,y:0},{x:0,y:h},{x:w,y:0}];var shapeSvg=parent.insert("polygon",":first-child").attr("points",points.map(function(p){return p.x+","+p.y}).join(" "));node.intersect=function(p){return intersectPolygon(node,points,p)};return shapeSvg}},{"./intersect/intersect-circle":11,"./intersect/intersect-ellipse":12,"./intersect/intersect-polygon":15,"./intersect/intersect-rect":16}],27:[function(require,module,exports){var _=require("./lodash");
// Public utility functions
module.exports={isSubgraph:isSubgraph,edgeToId:edgeToId,applyStyle:applyStyle,applyClass:applyClass,applyTransition:applyTransition};
/*
* Returns true if the specified node in the graph is a subgraph node. A
* subgraph node is one that contains other nodes.
*/function isSubgraph(g,v){return!!g.children(v).length}function edgeToId(e){return escapeId(e.v)+":"+escapeId(e.w)+":"+escapeId(e.name)}var ID_DELIM=/:/g;function escapeId(str){return str?String(str).replace(ID_DELIM,"\\:"):""}function applyStyle(dom,styleFn){if(styleFn){dom.attr("style",styleFn)}}function applyClass(dom,classFn,otherClasses){if(classFn){dom.attr("class",classFn).attr("class",otherClasses+" "+dom.attr("class"))}}function applyTransition(selection,g){var graph=g.graph();if(_.isPlainObject(graph)){var transition=graph.transition;if(_.isFunction(transition)){return transition(selection)}}return selection}},{"./lodash":21}],28:[function(require,module,exports){module.exports="0.6.4"},{}],29:[function(require,module,exports){
// https://d3js.org/d3-array/ v1.2.4 Copyright 2018 Mike Bostock
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?factory(exports):typeof define==="function"&&define.amd?define(["exports"],factory):factory(global.d3=global.d3||{})})(this,function(exports){"use strict";function ascending(a,b){return a<b?-1:a>b?1:a>=b?0:NaN}function bisector(compare){if(compare.length===1)compare=ascendingComparator(compare);return{left:function(a,x,lo,hi){if(lo==null)lo=0;if(hi==null)hi=a.length;while(lo<hi){var mid=lo+hi>>>1;if(compare(a[mid],x)<0)lo=mid+1;else hi=mid}return lo},right:function(a,x,lo,hi){if(lo==null)lo=0;if(hi==null)hi=a.length;while(lo<hi){var mid=lo+hi>>>1;if(compare(a[mid],x)>0)hi=mid;else lo=mid+1}return lo}}}function ascendingComparator(f){return function(d,x){return ascending(f(d),x)}}var ascendingBisect=bisector(ascending);var bisectRight=ascendingBisect.right;var bisectLeft=ascendingBisect.left;function pairs(array,f){if(f==null)f=pair;var i=0,n=array.length-1,p=array[0],pairs=new Array(n<0?0:n);while(i<n)pairs[i]=f(p,p=array[++i]);return pairs}function pair(a,b){return[a,b]}function cross(values0,values1,reduce){var n0=values0.length,n1=values1.length,values=new Array(n0*n1),i0,i1,i,value0;if(reduce==null)reduce=pair;for(i0=i=0;i0<n0;++i0){for(value0=values0[i0],i1=0;i1<n1;++i1,++i){values[i]=reduce(value0,values1[i1])}}return values}function descending(a,b){return b<a?-1:b>a?1:b>=a?0:NaN}function number(x){return x===null?NaN:+x}function variance(values,valueof){var n=values.length,m=0,i=-1,mean=0,value,delta,sum=0;if(valueof==null){while(++i<n){if(!isNaN(value=number(values[i]))){delta=value-mean;mean+=delta/++m;sum+=delta*(value-mean)}}}else{while(++i<n){if(!isNaN(value=number(valueof(values[i],i,values)))){delta=value-mean;mean+=delta/++m;sum+=delta*(value-mean)}}}if(m>1)return sum/(m-1)}function deviation(array,f){var v=variance(array,f);return v?Math.sqrt(v):v}function extent(values,valueof){var n=values.length,i=-1,value,min,max;if(valueof==null){while(++i<n){// Find the first comparable value.
if((value=values[i])!=null&&value>=value){min=max=value;while(++i<n){// Compare the remaining values.
if((value=values[i])!=null){if(min>value)min=value;if(max<value)max=value}}}}}else{while(++i<n){// Find the first comparable value.
if((value=valueof(values[i],i,values))!=null&&value>=value){min=max=value;while(++i<n){// Compare the remaining values.
if((value=valueof(values[i],i,values))!=null){if(min>value)min=value;if(max<value)max=value}}}}}return[min,max]}var array=Array.prototype;var slice=array.slice;var map=array.map;function constant(x){return function(){return x}}function identity(x){return x}function range(start,stop,step){start=+start,stop=+stop,step=(n=arguments.length)<2?(stop=start,start=0,1):n<3?1:+step;var i=-1,n=Math.max(0,Math.ceil((stop-start)/step))|0,range=new Array(n);while(++i<n){range[i]=start+i*step}return range}var e10=Math.sqrt(50),e5=Math.sqrt(10),e2=Math.sqrt(2);function ticks(start,stop,count){var reverse,i=-1,n,ticks,step;stop=+stop,start=+start,count=+count;if(start===stop&&count>0)return[start];if(reverse=stop<start)n=start,start=stop,stop=n;if((step=tickIncrement(start,stop,count))===0||!isFinite(step))return[];if(step>0){start=Math.ceil(start/step);stop=Math.floor(stop/step);ticks=new Array(n=Math.ceil(stop-start+1));while(++i<n)ticks[i]=(start+i)*step}else{start=Math.floor(start*step);stop=Math.ceil(stop*step);ticks=new Array(n=Math.ceil(start-stop+1));while(++i<n)ticks[i]=(start-i)/step}if(reverse)ticks.reverse();return ticks}function tickIncrement(start,stop,count){var step=(stop-start)/Math.max(0,count),power=Math.floor(Math.log(step)/Math.LN10),error=step/Math.pow(10,power);return power>=0?(error>=e10?10:error>=e5?5:error>=e2?2:1)*Math.pow(10,power):-Math.pow(10,-power)/(error>=e10?10:error>=e5?5:error>=e2?2:1)}function tickStep(start,stop,count){var step0=Math.abs(stop-start)/Math.max(0,count),step1=Math.pow(10,Math.floor(Math.log(step0)/Math.LN10)),error=step0/step1;if(error>=e10)step1*=10;else if(error>=e5)step1*=5;else if(error>=e2)step1*=2;return stop<start?-step1:step1}function sturges(values){return Math.ceil(Math.log(values.length)/Math.LN2)+1}function histogram(){var value=identity,domain=extent,threshold=sturges;function histogram(data){var i,n=data.length,x,values=new Array(n);for(i=0;i<n;++i){values[i]=value(data[i],i,data)}var xz=domain(values),x0=xz[0],x1=xz[1],tz=threshold(values,x0,x1);
// Convert number of thresholds into uniform thresholds.
if(!Array.isArray(tz)){tz=tickStep(x0,x1,tz);tz=range(Math.ceil(x0/tz)*tz,x1,tz);// exclusive
}
// Remove any thresholds outside the domain.
var m=tz.length;while(tz[0]<=x0)tz.shift(),--m;while(tz[m-1]>x1)tz.pop(),--m;var bins=new Array(m+1),bin;
// Initialize bins.
for(i=0;i<=m;++i){bin=bins[i]=[];bin.x0=i>0?tz[i-1]:x0;bin.x1=i<m?tz[i]:x1}
// Assign data to bins by value, ignoring any outside the domain.
for(i=0;i<n;++i){x=values[i];if(x0<=x&&x<=x1){bins[bisectRight(tz,x,0,m)].push(data[i])}}return bins}histogram.value=function(_){return arguments.length?(value=typeof _==="function"?_:constant(_),histogram):value};histogram.domain=function(_){return arguments.length?(domain=typeof _==="function"?_:constant([_[0],_[1]]),histogram):domain};histogram.thresholds=function(_){return arguments.length?(threshold=typeof _==="function"?_:Array.isArray(_)?constant(slice.call(_)):constant(_),histogram):threshold};return histogram}function quantile(values,p,valueof){if(valueof==null)valueof=number;if(!(n=values.length))return;if((p=+p)<=0||n<2)return+valueof(values[0],0,values);if(p>=1)return+valueof(values[n-1],n-1,values);var n,i=(n-1)*p,i0=Math.floor(i),value0=+valueof(values[i0],i0,values),value1=+valueof(values[i0+1],i0+1,values);return value0+(value1-value0)*(i-i0)}function freedmanDiaconis(values,min,max){values=map.call(values,number).sort(ascending);return Math.ceil((max-min)/(2*(quantile(values,.75)-quantile(values,.25))*Math.pow(values.length,-1/3)))}function scott(values,min,max){return Math.ceil((max-min)/(3.5*deviation(values)*Math.pow(values.length,-1/3)))}function max(values,valueof){var n=values.length,i=-1,value,max;if(valueof==null){while(++i<n){// Find the first comparable value.
if((value=values[i])!=null&&value>=value){max=value;while(++i<n){// Compare the remaining values.
if((value=values[i])!=null&&value>max){max=value}}}}}else{while(++i<n){// Find the first comparable value.
if((value=valueof(values[i],i,values))!=null&&value>=value){max=value;while(++i<n){// Compare the remaining values.
if((value=valueof(values[i],i,values))!=null&&value>max){max=value}}}}}return max}function mean(values,valueof){var n=values.length,m=n,i=-1,value,sum=0;if(valueof==null){while(++i<n){if(!isNaN(value=number(values[i])))sum+=value;else--m}}else{while(++i<n){if(!isNaN(value=number(valueof(values[i],i,values))))sum+=value;else--m}}if(m)return sum/m}function median(values,valueof){var n=values.length,i=-1,value,numbers=[];if(valueof==null){while(++i<n){if(!isNaN(value=number(values[i]))){numbers.push(value)}}}else{while(++i<n){if(!isNaN(value=number(valueof(values[i],i,values)))){numbers.push(value)}}}return quantile(numbers.sort(ascending),.5)}function merge(arrays){var n=arrays.length,m,i=-1,j=0,merged,array;while(++i<n)j+=arrays[i].length;merged=new Array(j);while(--n>=0){array=arrays[n];m=array.length;while(--m>=0){merged[--j]=array[m]}}return merged}function min(values,valueof){var n=values.length,i=-1,value,min;if(valueof==null){while(++i<n){// Find the first comparable value.
if((value=values[i])!=null&&value>=value){min=value;while(++i<n){// Compare the remaining values.
if((value=values[i])!=null&&min>value){min=value}}}}}else{while(++i<n){// Find the first comparable value.
if((value=valueof(values[i],i,values))!=null&&value>=value){min=value;while(++i<n){// Compare the remaining values.
if((value=valueof(values[i],i,values))!=null&&min>value){min=value}}}}}return min}function permute(array,indexes){var i=indexes.length,permutes=new Array(i);while(i--)permutes[i]=array[indexes[i]];return permutes}function scan(values,compare){if(!(n=values.length))return;var n,i=0,j=0,xi,xj=values[j];if(compare==null)compare=ascending;while(++i<n){if(compare(xi=values[i],xj)<0||compare(xj,xj)!==0){xj=xi,j=i}}if(compare(xj,xj)===0)return j}function shuffle(array,i0,i1){var m=(i1==null?array.length:i1)-(i0=i0==null?0:+i0),t,i;while(m){i=Math.random()*m--|0;t=array[m+i0];array[m+i0]=array[i+i0];array[i+i0]=t}return array}function sum(values,valueof){var n=values.length,i=-1,value,sum=0;if(valueof==null){while(++i<n){if(value=+values[i])sum+=value;// Note: zero and null are equivalent.
}}else{while(++i<n){if(value=+valueof(values[i],i,values))sum+=value}}return sum}function transpose(matrix){if(!(n=matrix.length))return[];for(var i=-1,m=min(matrix,length),transpose=new Array(m);++i<m;){for(var j=-1,n,row=transpose[i]=new Array(n);++j<n;){row[j]=matrix[j][i]}}return transpose}function length(d){return d.length}function zip(){return transpose(arguments)}exports.bisect=bisectRight;exports.bisectRight=bisectRight;exports.bisectLeft=bisectLeft;exports.ascending=ascending;exports.bisector=bisector;exports.cross=cross;exports.descending=descending;exports.deviation=deviation;exports.extent=extent;exports.histogram=histogram;exports.thresholdFreedmanDiaconis=freedmanDiaconis;exports.thresholdScott=scott;exports.thresholdSturges=sturges;exports.max=max;exports.mean=mean;exports.median=median;exports.merge=merge;exports.min=min;exports.pairs=pairs;exports.permute=permute;exports.quantile=quantile;exports.range=range;exports.scan=scan;exports.shuffle=shuffle;exports.sum=sum;exports.ticks=ticks;exports.tickIncrement=tickIncrement;exports.tickStep=tickStep;exports.transpose=transpose;exports.variance=variance;exports.zip=zip;Object.defineProperty(exports,"__esModule",{value:true})})},{}],30:[function(require,module,exports){
// https://d3js.org/d3-axis/ v1.0.12 Copyright 2018 Mike Bostock
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?factory(exports):typeof define==="function"&&define.amd?define(["exports"],factory):factory(global.d3=global.d3||{})})(this,function(exports){"use strict";var slice=Array.prototype.slice;function identity(x){return x}var top=1,right=2,bottom=3,left=4,epsilon=1e-6;function translateX(x){return"translate("+(x+.5)+",0)"}function translateY(y){return"translate(0,"+(y+.5)+")"}function number(scale){return function(d){return+scale(d)}}function center(scale){var offset=Math.max(0,scale.bandwidth()-1)/2;// Adjust for 0.5px offset.
if(scale.round())offset=Math.round(offset);return function(d){return+scale(d)+offset}}function entering(){return!this.__axis}function axis(orient,scale){var tickArguments=[],tickValues=null,tickFormat=null,tickSizeInner=6,tickSizeOuter=6,tickPadding=3,k=orient===top||orient===left?-1:1,x=orient===left||orient===right?"x":"y",transform=orient===top||orient===bottom?translateX:translateY;function axis(context){var values=tickValues==null?scale.ticks?scale.ticks.apply(scale,tickArguments):scale.domain():tickValues,format=tickFormat==null?scale.tickFormat?scale.tickFormat.apply(scale,tickArguments):identity:tickFormat,spacing=Math.max(tickSizeInner,0)+tickPadding,range=scale.range(),range0=+range[0]+.5,range1=+range[range.length-1]+.5,position=(scale.bandwidth?center:number)(scale.copy()),selection=context.selection?context.selection():context,path=selection.selectAll(".domain").data([null]),tick=selection.selectAll(".tick").data(values,scale).order(),tickExit=tick.exit(),tickEnter=tick.enter().append("g").attr("class","tick"),line=tick.select("line"),text=tick.select("text");path=path.merge(path.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor"));tick=tick.merge(tickEnter);line=line.merge(tickEnter.append("line").attr("stroke","currentColor").attr(x+"2",k*tickSizeInner));text=text.merge(tickEnter.append("text").attr("fill","currentColor").attr(x,k*spacing).attr("dy",orient===top?"0em":orient===bottom?"0.71em":"0.32em"));if(context!==selection){path=path.transition(context);tick=tick.transition(context);line=line.transition(context);text=text.transition(context);tickExit=tickExit.transition(context).attr("opacity",epsilon).attr("transform",function(d){return isFinite(d=position(d))?transform(d):this.getAttribute("transform")});tickEnter.attr("opacity",epsilon).attr("transform",function(d){var p=this.parentNode.__axis;return transform(p&&isFinite(p=p(d))?p:position(d))})}tickExit.remove();path.attr("d",orient===left||orient==right?tickSizeOuter?"M"+k*tickSizeOuter+","+range0+"H0.5V"+range1+"H"+k*tickSizeOuter:"M0.5,"+range0+"V"+range1:tickSizeOuter?"M"+range0+","+k*tickSizeOuter+"V0.5H"+range1+"V"+k*tickSizeOuter:"M"+range0+",0.5H"+range1);tick.attr("opacity",1).attr("transform",function(d){return transform(position(d))});line.attr(x+"2",k*tickSizeInner);text.attr(x,k*spacing).text(format);selection.filter(entering).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",orient===right?"start":orient===left?"end":"middle");selection.each(function(){this.__axis=position})}axis.scale=function(_){return arguments.length?(scale=_,axis):scale};axis.ticks=function(){return tickArguments=slice.call(arguments),axis};axis.tickArguments=function(_){return arguments.length?(tickArguments=_==null?[]:slice.call(_),axis):tickArguments.slice()};axis.tickValues=function(_){return arguments.length?(tickValues=_==null?null:slice.call(_),axis):tickValues&&tickValues.slice()};axis.tickFormat=function(_){return arguments.length?(tickFormat=_,axis):tickFormat};axis.tickSize=function(_){return arguments.length?(tickSizeInner=tickSizeOuter=+_,axis):tickSizeInner};axis.tickSizeInner=function(_){return arguments.length?(tickSizeInner=+_,axis):tickSizeInner};axis.tickSizeOuter=function(_){return arguments.length?(tickSizeOuter=+_,axis):tickSizeOuter};axis.tickPadding=function(_){return arguments.length?(tickPadding=+_,axis):tickPadding};return axis}function axisTop(scale){return axis(top,scale)}function axisRight(scale){return axis(right,scale)}function axisBottom(scale){return axis(bottom,scale)}function axisLeft(scale){return axis(left,scale)}exports.axisTop=axisTop;exports.axisRight=axisRight;exports.axisBottom=axisBottom;exports.axisLeft=axisLeft;Object.defineProperty(exports,"__esModule",{value:true})})},{}],31:[function(require,module,exports){
// https://d3js.org/d3-brush/ v1.1.5 Copyright 2019 Mike Bostock
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?factory(exports,require("d3-dispatch"),require("d3-drag"),require("d3-interpolate"),require("d3-selection"),require("d3-transition")):typeof define==="function"&&define.amd?define(["exports","d3-dispatch","d3-drag","d3-interpolate","d3-selection","d3-transition"],factory):(global=global||self,factory(global.d3=global.d3||{},global.d3,global.d3,global.d3,global.d3,global.d3))})(this,function(exports,d3Dispatch,d3Drag,d3Interpolate,d3Selection,d3Transition){"use strict";function constant(x){return function(){return x}}function BrushEvent(target,type,selection){this.target=target;this.type=type;this.selection=selection}function nopropagation(){d3Selection.event.stopImmediatePropagation()}function noevent(){d3Selection.event.preventDefault();d3Selection.event.stopImmediatePropagation()}var MODE_DRAG={name:"drag"},MODE_SPACE={name:"space"},MODE_HANDLE={name:"handle"},MODE_CENTER={name:"center"};function number1(e){return[+e[0],+e[1]]}function number2(e){return[number1(e[0]),number1(e[1])]}function toucher(identifier){return function(target){return d3Selection.touch(target,d3Selection.event.touches,identifier)}}var X={name:"x",handles:["w","e"].map(type),input:function(x,e){return x==null?null:[[+x[0],e[0][1]],[+x[1],e[1][1]]]},output:function(xy){return xy&&[xy[0][0],xy[1][0]]}};var Y={name:"y",handles:["n","s"].map(type),input:function(y,e){return y==null?null:[[e[0][0],+y[0]],[e[1][0],+y[1]]]},output:function(xy){return xy&&[xy[0][1],xy[1][1]]}};var XY={name:"xy",handles:["n","w","e","s","nw","ne","sw","se"].map(type),input:function(xy){return xy==null?null:number2(xy)},output:function(xy){return xy}};var cursors={overlay:"crosshair",selection:"move",n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"};var flipX={e:"w",w:"e",nw:"ne",ne:"nw",se:"sw",sw:"se"};var flipY={n:"s",s:"n",nw:"sw",ne:"se",se:"ne",sw:"nw"};var signsX={overlay:+1,selection:+1,n:null,e:+1,s:null,w:-1,nw:-1,ne:+1,se:+1,sw:-1};var signsY={overlay:+1,selection:+1,n:-1,e:null,s:+1,w:null,nw:-1,ne:-1,se:+1,sw:+1};function type(t){return{type:t}}
// Ignore right-click, since that should open the context menu.
function defaultFilter(){return!d3Selection.event.ctrlKey&&!d3Selection.event.button}function defaultExtent(){var svg=this.ownerSVGElement||this;if(svg.hasAttribute("viewBox")){svg=svg.viewBox.baseVal;return[[svg.x,svg.y],[svg.x+svg.width,svg.y+svg.height]]}return[[0,0],[svg.width.baseVal.value,svg.height.baseVal.value]]}function defaultTouchable(){return navigator.maxTouchPoints||"ontouchstart"in this}
// Like d3.local, but with the name “__brush” rather than auto-generated.
function local(node){while(!node.__brush)if(!(node=node.parentNode))return;return node.__brush}function empty(extent){return extent[0][0]===extent[1][0]||extent[0][1]===extent[1][1]}function brushSelection(node){var state=node.__brush;return state?state.dim.output(state.selection):null}function brushX(){return brush$1(X)}function brushY(){return brush$1(Y)}function brush(){return brush$1(XY)}function brush$1(dim){var extent=defaultExtent,filter=defaultFilter,touchable=defaultTouchable,keys=true,listeners=d3Dispatch.dispatch("start","brush","end"),handleSize=6,touchending;function brush(group){var overlay=group.property("__brush",initialize).selectAll(".overlay").data([type("overlay")]);overlay.enter().append("rect").attr("class","overlay").attr("pointer-events","all").attr("cursor",cursors.overlay).merge(overlay).each(function(){var extent=local(this).extent;d3Selection.select(this).attr("x",extent[0][0]).attr("y",extent[0][1]).attr("width",extent[1][0]-extent[0][0]).attr("height",extent[1][1]-extent[0][1])});group.selectAll(".selection").data([type("selection")]).enter().append("rect").attr("class","selection").attr("cursor",cursors.selection).attr("fill","#777").attr("fill-opacity",.3).attr("stroke","#fff").attr("shape-rendering","crispEdges");var handle=group.selectAll(".handle").data(dim.handles,function(d){return d.type});handle.exit().remove();handle.enter().append("rect").attr("class",function(d){return"handle handle--"+d.type}).attr("cursor",function(d){return cursors[d.type]});group.each(redraw).attr("fill","none").attr("pointer-events","all").on("mousedown.brush",started).filter(touchable).on("touchstart.brush",started).on("touchmove.brush",touchmoved).on("touchend.brush touchcancel.brush",touchended).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}brush.move=function(group,selection){if(group.selection){group.on("start.brush",function(){emitter(this,arguments).beforestart().start()}).on("interrupt.brush end.brush",function(){emitter(this,arguments).end()}).tween("brush",function(){var that=this,state=that.__brush,emit=emitter(that,arguments),selection0=state.selection,selection1=dim.input(typeof selection==="function"?selection.apply(this,arguments):selection,state.extent),i=d3Interpolate.interpolate(selection0,selection1);function tween(t){state.selection=t===1&&selection1===null?null:i(t);redraw.call(that);emit.brush()}return selection0!==null&&selection1!==null?tween:tween(1)})}else{group.each(function(){var that=this,args=arguments,state=that.__brush,selection1=dim.input(typeof selection==="function"?selection.apply(that,args):selection,state.extent),emit=emitter(that,args).beforestart();d3Transition.interrupt(that);state.selection=selection1===null?null:selection1;redraw.call(that);emit.start().brush().end()})}};brush.clear=function(group){brush.move(group,null)};function redraw(){var group=d3Selection.select(this),selection=local(this).selection;if(selection){group.selectAll(".selection").style("display",null).attr("x",selection[0][0]).attr("y",selection[0][1]).attr("width",selection[1][0]-selection[0][0]).attr("height",selection[1][1]-selection[0][1]);group.selectAll(".handle").style("display",null).attr("x",function(d){return d.type[d.type.length-1]==="e"?selection[1][0]-handleSize/2:selection[0][0]-handleSize/2}).attr("y",function(d){return d.type[0]==="s"?selection[1][1]-handleSize/2:selection[0][1]-handleSize/2}).attr("width",function(d){return d.type==="n"||d.type==="s"?selection[1][0]-selection[0][0]+handleSize:handleSize}).attr("height",function(d){return d.type==="e"||d.type==="w"?selection[1][1]-selection[0][1]+handleSize:handleSize})}else{group.selectAll(".selection,.handle").style("display","none").attr("x",null).attr("y",null).attr("width",null).attr("height",null)}}function emitter(that,args,clean){return!clean&&that.__brush.emitter||new Emitter(that,args)}function Emitter(that,args){this.that=that;this.args=args;this.state=that.__brush;this.active=0}Emitter.prototype={beforestart:function(){if(++this.active===1)this.state.emitter=this,this.starting=true;return this},start:function(){if(this.starting)this.starting=false,this.emit("start");else this.emit("brush");return this},brush:function(){this.emit("brush");return this},end:function(){if(--this.active===0)delete this.state.emitter,this.emit("end");return this},emit:function(type){d3Selection.customEvent(new BrushEvent(brush,type,dim.output(this.state.selection)),listeners.apply,listeners,[type,this.that,this.args])}};function started(){if(touchending&&!d3Selection.event.touches)return;if(!f