@dagrejs/dagre 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dagre.js +161 -150
- package/dist/dagre.min.js +60 -60
- package/lib/acyclic.js +18 -10
- package/lib/add-border-segments.js +11 -19
- package/lib/coordinate-system.js +15 -5
- package/lib/data/list.js +7 -8
- package/lib/debug.js +14 -25
- package/lib/greedy-fas.js +30 -35
- package/lib/layout.js +102 -105
- package/lib/nesting-graph.js +21 -18
- package/lib/normalize.js +18 -22
- package/lib/order/add-subgraph-constraints.js +2 -6
- package/lib/order/barycenter.js +6 -14
- package/lib/order/build-layer-graph.js +13 -19
- package/lib/order/cross-count.js +10 -13
- package/lib/order/index.js +23 -23
- package/lib/order/init-order.js +7 -8
- package/lib/order/resolve-conflicts.js +19 -9
- package/lib/order/sort-subgraph.js +22 -16
- package/lib/order/sort.js +12 -13
- package/lib/parent-dummy-chains.js +19 -17
- package/lib/position/bk.js +84 -40
- package/lib/position/index.js +9 -10
- package/lib/rank/feasible-tree.js +17 -14
- package/lib/rank/index.js +15 -25
- package/lib/rank/network-simplex.js +39 -18
- package/lib/rank/util.js +12 -6
- package/lib/util.js +57 -42
- package/lib/version.js +1 -8
- package/package.json +3 -15
- package/lib/index.js +0 -38
- package/mjs-lib/acyclic.js +0 -62
- package/mjs-lib/add-border-segments.js +0 -35
- package/mjs-lib/coordinate-system.js +0 -65
- package/mjs-lib/data/list.js +0 -56
- package/mjs-lib/debug.js +0 -30
- package/mjs-lib/greedy-fas.js +0 -125
- package/mjs-lib/index.js +0 -9
- package/mjs-lib/layout.js +0 -405
- package/mjs-lib/nesting-graph.js +0 -120
- package/mjs-lib/normalize.js +0 -84
- package/mjs-lib/order/add-subgraph-constraints.js +0 -49
- package/mjs-lib/order/barycenter.js +0 -24
- package/mjs-lib/order/build-layer-graph.js +0 -71
- package/mjs-lib/order/cross-count.js +0 -64
- package/mjs-lib/order/index.js +0 -70
- package/mjs-lib/order/init-order.js +0 -34
- package/mjs-lib/order/resolve-conflicts.js +0 -116
- package/mjs-lib/order/sort-subgraph.js +0 -71
- package/mjs-lib/order/sort.js +0 -54
- package/mjs-lib/parent-dummy-chains.js +0 -82
- package/mjs-lib/position/bk.js +0 -409
- package/mjs-lib/position/index.js +0 -30
- package/mjs-lib/rank/feasible-tree.js +0 -93
- package/mjs-lib/rank/index.js +0 -46
- package/mjs-lib/rank/network-simplex.js +0 -233
- package/mjs-lib/rank/util.js +0 -58
- package/mjs-lib/util.js +0 -305
- package/mjs-lib/version.js +0 -1
package/dist/dagre.min.js
CHANGED
|
@@ -207,7 +207,7 @@ let cc=0;southEntries.forEach(entry=>{let index=entry.pos+firstIndex;tree[index]
|
|
|
207
207
|
*
|
|
208
208
|
* 1. Graph nodes will have an "order" attribute based on the results of the
|
|
209
209
|
* algorithm.
|
|
210
|
-
*/function order(g){let maxRank=util.maxRank(g),downLayerGraphs=buildLayerGraphs(g,util.range(1,maxRank+1),"inEdges"),upLayerGraphs=buildLayerGraphs(g,util.range(maxRank-1,-1,-1),"outEdges");let layering=initOrder(g);assignOrder(g,layering);let bestCC=Number.POSITIVE_INFINITY,best;for(let i=0,lastBest=0;lastBest<4;++i,++lastBest){sweepLayerGraphs(i%2?downLayerGraphs:upLayerGraphs,i%4>=2);layering=util.buildLayerMatrix(g);let cc=crossCount(g,layering);if(cc<bestCC){lastBest=0;best=Object.assign({},layering);bestCC=cc}}assignOrder(g,best)}function buildLayerGraphs(g,ranks,relationship){return ranks.map(function(rank){return buildLayerGraph(g,rank,relationship)})}function sweepLayerGraphs(layerGraphs,biasRight){let cg=new Graph;layerGraphs.forEach(function(lg){let root=lg.graph().root;let sorted=sortSubgraph(lg,root,cg,biasRight);sorted.vs.forEach((v,i)=>lg.node(v).order=i);addSubgraphConstraints(lg,cg,sorted.vs)})}function assignOrder(g,layering){Object.values(layering).forEach(layer=>layer.forEach((v,i)=>g.node(v).order=i))}},{"../util":27,"./add-subgraph-constraints":11,"./build-layer-graph":13,"./cross-count":14,"./init-order":16,"./sort-subgraph":18,"@dagrejs/graphlib":29}],16:[function(require,module,exports){"use strict";let util=require("../util");module.exports=initOrder;
|
|
210
|
+
*/function order(g,opts){if(opts&&typeof opts.customOrder==="function"){opts.customOrder(g,order);return}let maxRank=util.maxRank(g),downLayerGraphs=buildLayerGraphs(g,util.range(1,maxRank+1),"inEdges"),upLayerGraphs=buildLayerGraphs(g,util.range(maxRank-1,-1,-1),"outEdges");let layering=initOrder(g);assignOrder(g,layering);if(opts&&opts.disableOptimalOrderHeuristic){return}let bestCC=Number.POSITIVE_INFINITY,best;for(let i=0,lastBest=0;lastBest<4;++i,++lastBest){sweepLayerGraphs(i%2?downLayerGraphs:upLayerGraphs,i%4>=2);layering=util.buildLayerMatrix(g);let cc=crossCount(g,layering);if(cc<bestCC){lastBest=0;best=Object.assign({},layering);bestCC=cc}}assignOrder(g,best)}function buildLayerGraphs(g,ranks,relationship){return ranks.map(function(rank){return buildLayerGraph(g,rank,relationship)})}function sweepLayerGraphs(layerGraphs,biasRight){let cg=new Graph;layerGraphs.forEach(function(lg){let root=lg.graph().root;let sorted=sortSubgraph(lg,root,cg,biasRight);sorted.vs.forEach((v,i)=>lg.node(v).order=i);addSubgraphConstraints(lg,cg,sorted.vs)})}function assignOrder(g,layering){Object.values(layering).forEach(layer=>layer.forEach((v,i)=>g.node(v).order=i))}},{"../util":27,"./add-subgraph-constraints":11,"./build-layer-graph":13,"./cross-count":14,"./init-order":16,"./sort-subgraph":18,"@dagrejs/graphlib":29}],16:[function(require,module,exports){"use strict";let util=require("../util");module.exports=initOrder;
|
|
211
211
|
/*
|
|
212
212
|
* Assigns an initial order value for each node by performing a DFS search
|
|
213
213
|
* starting from nodes in the first rank. Nodes are assigned an order in their
|
|
@@ -277,7 +277,7 @@ parent=w;while((parent=g.parent(parent))!==lca){wPath.push(parent)}return{path:v
|
|
|
277
277
|
k0=0,
|
|
278
278
|
// Tracks the last node in this layer scanned for crossings with a type-1
|
|
279
279
|
// segment.
|
|
280
|
-
scanPos=0,prevLayerLength=prevLayer.length,lastNode=layer[layer.length-1];layer.forEach((v,i)=>{let w=findOtherInnerSegmentNode(g,v),k1=w?g.node(w).order:prevLayerLength;if(w||v===lastNode){layer.slice(scanPos,i+1).forEach(scanNode=>{g.predecessors(scanNode).forEach(u=>{let uLabel=g.node(u),uPos=uLabel.order;if((uPos<k0||k1<uPos)&&!(uLabel.dummy&&g.node(scanNode).dummy)){addConflict(conflicts,u,scanNode)}})});scanPos=i+1;k0=k1}});return layer}layering.reduce(visitLayer);return conflicts}function findType2Conflicts(g,layering){let conflicts={};function scan(south,southPos,southEnd,prevNorthBorder,nextNorthBorder){let v;util.range(southPos,southEnd).forEach(i=>{v=south[i];if(g.node(v).dummy){g.predecessors(v).forEach(u=>{let uNode=g.node(u);if(uNode.dummy&&(uNode.order<prevNorthBorder||uNode.order>nextNorthBorder)){addConflict(conflicts,u,v)}})}})}function visitLayer(north,south){let prevNorthPos=-1,nextNorthPos,southPos=0;south.forEach((v,southLookahead)=>{if(g.node(v).dummy==="border"){let predecessors=g.predecessors(v);if(predecessors.length){nextNorthPos=g.node(predecessors[0]).order;scan(south,southPos,southLookahead,prevNorthPos,nextNorthPos);southPos=southLookahead;prevNorthPos=nextNorthPos}}scan(south,southPos,south.length,nextNorthPos,north.length)});return south}layering.reduce(visitLayer);return conflicts}function findOtherInnerSegmentNode(g,v){if(g.node(v).dummy){return g.predecessors(v).find(u=>g.node(u).dummy)}}function addConflict(conflicts,v,w){if(v>w){let tmp=v;v=w;w=tmp}let conflictsV=conflicts[v];if(!conflictsV){conflicts[v]=conflictsV={}}conflictsV[w]=true}function hasConflict(conflicts,v,w){if(v>w){let tmp=v;v=w;w=tmp}return!!conflicts[v]&&conflicts[v].hasOwnProperty(w)}
|
|
280
|
+
scanPos=0,prevLayerLength=prevLayer.length,lastNode=layer[layer.length-1];layer.forEach((v,i)=>{let w=findOtherInnerSegmentNode(g,v),k1=w?g.node(w).order:prevLayerLength;if(w||v===lastNode){layer.slice(scanPos,i+1).forEach(scanNode=>{g.predecessors(scanNode).forEach(u=>{let uLabel=g.node(u),uPos=uLabel.order;if((uPos<k0||k1<uPos)&&!(uLabel.dummy&&g.node(scanNode).dummy)){addConflict(conflicts,u,scanNode)}})});scanPos=i+1;k0=k1}});return layer}layering.length&&layering.reduce(visitLayer);return conflicts}function findType2Conflicts(g,layering){let conflicts={};function scan(south,southPos,southEnd,prevNorthBorder,nextNorthBorder){let v;util.range(southPos,southEnd).forEach(i=>{v=south[i];if(g.node(v).dummy){g.predecessors(v).forEach(u=>{let uNode=g.node(u);if(uNode.dummy&&(uNode.order<prevNorthBorder||uNode.order>nextNorthBorder)){addConflict(conflicts,u,v)}})}})}function visitLayer(north,south){let prevNorthPos=-1,nextNorthPos,southPos=0;south.forEach((v,southLookahead)=>{if(g.node(v).dummy==="border"){let predecessors=g.predecessors(v);if(predecessors.length){nextNorthPos=g.node(predecessors[0]).order;scan(south,southPos,southLookahead,prevNorthPos,nextNorthPos);southPos=southLookahead;prevNorthPos=nextNorthPos}}scan(south,southPos,south.length,nextNorthPos,north.length)});return south}layering.length&&layering.reduce(visitLayer);return conflicts}function findOtherInnerSegmentNode(g,v){if(g.node(v).dummy){return g.predecessors(v).find(u=>g.node(u).dummy)}}function addConflict(conflicts,v,w){if(v>w){let tmp=v;v=w;w=tmp}let conflictsV=conflicts[v];if(!conflictsV){conflicts[v]=conflictsV={}}conflictsV[w]=true}function hasConflict(conflicts,v,w){if(v>w){let tmp=v;v=w;w=tmp}return!!conflicts[v]&&conflicts[v].hasOwnProperty(w)}
|
|
281
281
|
/*
|
|
282
282
|
* Try to align nodes into vertical "blocks" where possible. This algorithm
|
|
283
283
|
* attempts to align a node with one of its median neighbors. If the edge
|
|
@@ -495,7 +495,7 @@ let offset=Math.min(...g.nodes().map(v=>g.node(v).rank));let layers=[];g.nodes()
|
|
|
495
495
|
/*
|
|
496
496
|
* Returns a new function that wraps `fn` with a timer. The wrapper logs the
|
|
497
497
|
* time it takes to execute the function.
|
|
498
|
-
*/function time(name,fn){let start=Date.now();try{return fn()}finally{console.log(name+" time: "+(Date.now()-start)+"ms")}}function notime(name,fn){return fn()}let idCounter=0;function uniqueId(prefix){var id=++idCounter;return toString(prefix)+id}function range(start,limit,step=1){if(limit==null){limit=start;start=0}let endCon=i=>i<limit;if(step<0){endCon=i=>limit<i}const range=[];for(let i=start;endCon(i);i+=step){range.push(i)}return range}function pick(source,keys){const dest={};for(const key of keys){if(source[key]!==undefined){dest[key]=source[key]}}return dest}function mapValues(obj,funcOrProp){let func=funcOrProp;if(typeof funcOrProp==="string"){func=val=>val[funcOrProp]}return Object.entries(obj).reduce((acc,[k,v])=>{acc[k]=func(v,k);return acc},{})}function zipObject(props,values){return props.reduce((acc,key,i)=>{acc[key]=values[i];return acc},{})}},{"@dagrejs/graphlib":29}],28:[function(require,module,exports){module.exports="1.
|
|
498
|
+
*/function time(name,fn){let start=Date.now();try{return fn()}finally{console.log(name+" time: "+(Date.now()-start)+"ms")}}function notime(name,fn){return fn()}let idCounter=0;function uniqueId(prefix){var id=++idCounter;return toString(prefix)+id}function range(start,limit,step=1){if(limit==null){limit=start;start=0}let endCon=i=>i<limit;if(step<0){endCon=i=>limit<i}const range=[];for(let i=start;endCon(i);i+=step){range.push(i)}return range}function pick(source,keys){const dest={};for(const key of keys){if(source[key]!==undefined){dest[key]=source[key]}}return dest}function mapValues(obj,funcOrProp){let func=funcOrProp;if(typeof funcOrProp==="string"){func=val=>val[funcOrProp]}return Object.entries(obj).reduce((acc,[k,v])=>{acc[k]=func(v,k);return acc},{})}function zipObject(props,values){return props.reduce((acc,key,i)=>{acc[key]=values[i];return acc},{})}},{"@dagrejs/graphlib":29}],28:[function(require,module,exports){module.exports="1.1.2"},{}],29:[function(require,module,exports){
|
|
499
499
|
/**
|
|
500
500
|
* Copyright (c) 2014, Chris Pettitt
|
|
501
501
|
* All rights reserved.
|
|
@@ -544,26 +544,26 @@ var results=[];function dfs(v){var entry=visited[v]={onStack:true,lowlink:index,
|
|
|
544
544
|
* the queue. Adding and removing elements takes O(log n) time. A key can
|
|
545
545
|
* have its priority decreased in O(log n) time.
|
|
546
546
|
*/
|
|
547
|
-
class PriorityQueue{
|
|
547
|
+
class PriorityQueue{_arr=[];_keyIndices={};
|
|
548
548
|
/**
|
|
549
549
|
* Returns the number of elements in the queue. Takes `O(1)` time.
|
|
550
|
-
*/size(){return this
|
|
550
|
+
*/size(){return this._arr.length}
|
|
551
551
|
/**
|
|
552
552
|
* Returns the keys that are in the queue. Takes `O(n)` time.
|
|
553
|
-
*/keys(){return this
|
|
553
|
+
*/keys(){return this._arr.map(function(x){return x.key})}
|
|
554
554
|
/**
|
|
555
555
|
* Returns `true` if **key** is in the queue and `false` if not.
|
|
556
|
-
*/has(key){return this
|
|
556
|
+
*/has(key){return this._keyIndices.hasOwnProperty(key)}
|
|
557
557
|
/**
|
|
558
558
|
* Returns the priority for **key**. If **key** is not present in the queue
|
|
559
559
|
* then this function returns `undefined`. Takes `O(1)` time.
|
|
560
560
|
*
|
|
561
561
|
* @param {Object} key
|
|
562
|
-
*/priority(key){var index=this
|
|
562
|
+
*/priority(key){var index=this._keyIndices[key];if(index!==undefined){return this._arr[index].priority}}
|
|
563
563
|
/**
|
|
564
564
|
* Returns the key for the minimum element in this queue. If the queue is
|
|
565
565
|
* empty this function throws an Error. Takes `O(1)` time.
|
|
566
|
-
*/min(){if(this.size()===0){throw new Error("Queue underflow")}return this
|
|
566
|
+
*/min(){if(this.size()===0){throw new Error("Queue underflow")}return this._arr[0].key}
|
|
567
567
|
/**
|
|
568
568
|
* Inserts a new key into the priority queue. If the key already exists in
|
|
569
569
|
* the queue this function returns `false`; otherwise it will return `true`.
|
|
@@ -571,17 +571,17 @@ class PriorityQueue{#arr=[];#keyIndices={};
|
|
|
571
571
|
*
|
|
572
572
|
* @param {Object} key the key to add
|
|
573
573
|
* @param {Number} priority the initial priority for the key
|
|
574
|
-
*/add(key,priority){var keyIndices=this
|
|
574
|
+
*/add(key,priority){var keyIndices=this._keyIndices;key=String(key);if(!keyIndices.hasOwnProperty(key)){var arr=this._arr;var index=arr.length;keyIndices[key]=index;arr.push({key:key,priority:priority});this._decrease(index);return true}return false}
|
|
575
575
|
/**
|
|
576
576
|
* Removes and returns the smallest key in the queue. Takes `O(log n)` time.
|
|
577
|
-
*/removeMin(){this
|
|
577
|
+
*/removeMin(){this._swap(0,this._arr.length-1);var min=this._arr.pop();delete this._keyIndices[min.key];this._heapify(0);return min.key}
|
|
578
578
|
/**
|
|
579
579
|
* Decreases the priority for **key** to **priority**. If the new priority is
|
|
580
580
|
* greater than the previous priority, this function will throw an Error.
|
|
581
581
|
*
|
|
582
582
|
* @param {Object} key the key for which to raise priority
|
|
583
583
|
* @param {Number} priority the new priority for the key
|
|
584
|
-
*/decrease(key,priority){var index=this
|
|
584
|
+
*/decrease(key,priority){var index=this._keyIndices[key];if(priority>this._arr[index].priority){throw new Error("New priority is greater than current priority. "+"Key: "+key+" Old: "+this._arr[index].priority+" New: "+priority)}this._arr[index].priority=priority;this._decrease(index)}_heapify(i){var arr=this._arr;var l=2*i;var r=l+1;var largest=i;if(l<arr.length){largest=arr[l].priority<arr[largest].priority?l:largest;if(r<arr.length){largest=arr[r].priority<arr[largest].priority?r:largest}if(largest!==i){this._swap(i,largest);this._heapify(largest)}}}_decrease(index){var arr=this._arr;var priority=arr[index].priority;var parent;while(index!==0){parent=index>>1;if(arr[parent].priority<priority){break}this._swap(index,parent);index=parent}}_swap(i,j){var arr=this._arr;var keyIndices=this._keyIndices;var origArrI=arr[i];var origArrJ=arr[j];arr[i]=origArrJ;arr[j]=origArrI;keyIndices[origArrJ.key]=i;keyIndices[origArrI.key]=j}}module.exports=PriorityQueue},{}],44:[function(require,module,exports){"use strict";var DEFAULT_EDGE_NAME="\0";var GRAPH_NODE="\0";var EDGE_KEY_DELIM="";
|
|
585
585
|
// Implementation notes:
|
|
586
586
|
//
|
|
587
587
|
// * Node id query functions should return string ids for the nodes
|
|
@@ -591,49 +591,49 @@ class PriorityQueue{#arr=[];#keyIndices={};
|
|
|
591
591
|
// reference edges. This is because we need a performant way to look these
|
|
592
592
|
// edges up and, object properties, which have string keys, are the closest
|
|
593
593
|
// we're going to get to a performant hashtable in JavaScript.
|
|
594
|
-
class Graph{
|
|
594
|
+
class Graph{_isDirected=true;_isMultigraph=false;_isCompound=false;
|
|
595
595
|
// Label for the graph itself
|
|
596
|
-
|
|
596
|
+
_label;
|
|
597
597
|
// Defaults to be set when creating a new node
|
|
598
|
-
|
|
598
|
+
_defaultNodeLabelFn=()=>undefined;
|
|
599
599
|
// Defaults to be set when creating a new edge
|
|
600
|
-
|
|
600
|
+
_defaultEdgeLabelFn=()=>undefined;
|
|
601
601
|
// v -> label
|
|
602
|
-
|
|
602
|
+
_nodes={};
|
|
603
603
|
// v -> edgeObj
|
|
604
|
-
|
|
604
|
+
_in={};
|
|
605
605
|
// u -> v -> Number
|
|
606
|
-
|
|
606
|
+
_preds={};
|
|
607
607
|
// v -> edgeObj
|
|
608
|
-
|
|
608
|
+
_out={};
|
|
609
609
|
// v -> w -> Number
|
|
610
|
-
|
|
610
|
+
_sucs={};
|
|
611
611
|
// e -> edgeObj
|
|
612
|
-
|
|
612
|
+
_edgeObjs={};
|
|
613
613
|
// e -> label
|
|
614
|
-
|
|
615
|
-
/* Number of nodes in the graph. Should only be changed by the implementation.
|
|
616
|
-
/* Number of edges in the graph. Should only be changed by the implementation.
|
|
614
|
+
_edgeLabels={};
|
|
615
|
+
/* Number of nodes in the graph. Should only be changed by the implementation. */_nodeCount=0;
|
|
616
|
+
/* Number of edges in the graph. Should only be changed by the implementation. */_edgeCount=0;_parent;_children;constructor(opts){if(opts){this._isDirected=opts.hasOwnProperty("directed")?opts.directed:true;this._isMultigraph=opts.hasOwnProperty("multigraph")?opts.multigraph:false;this._isCompound=opts.hasOwnProperty("compound")?opts.compound:false}if(this._isCompound){
|
|
617
617
|
// v -> parent
|
|
618
|
-
this
|
|
618
|
+
this._parent={};
|
|
619
619
|
// v -> children
|
|
620
|
-
this
|
|
620
|
+
this._children={};this._children[GRAPH_NODE]={}}}
|
|
621
621
|
/* === Graph functions ========= */
|
|
622
622
|
/**
|
|
623
623
|
* Whether graph was created with 'directed' flag set to true or not.
|
|
624
|
-
*/isDirected(){return this
|
|
624
|
+
*/isDirected(){return this._isDirected}
|
|
625
625
|
/**
|
|
626
626
|
* Whether graph was created with 'multigraph' flag set to true or not.
|
|
627
|
-
*/isMultigraph(){return this
|
|
627
|
+
*/isMultigraph(){return this._isMultigraph}
|
|
628
628
|
/**
|
|
629
629
|
* Whether graph was created with 'compound' flag set to true or not.
|
|
630
|
-
*/isCompound(){return this
|
|
630
|
+
*/isCompound(){return this._isCompound}
|
|
631
631
|
/**
|
|
632
632
|
* Sets the label of the graph.
|
|
633
|
-
*/setGraph(label){this
|
|
633
|
+
*/setGraph(label){this._label=label;return this}
|
|
634
634
|
/**
|
|
635
635
|
* Gets the graph label.
|
|
636
|
-
*/graph(){return this
|
|
636
|
+
*/graph(){return this._label}
|
|
637
637
|
/* === Node functions ========== */
|
|
638
638
|
/**
|
|
639
639
|
* Sets the default node label. If newDefault is a function, it will be
|
|
@@ -641,24 +641,24 @@ this.#children={};this.#children[GRAPH_NODE]={}}}
|
|
|
641
641
|
* will be assigned as default label in case if no label was specified while
|
|
642
642
|
* setting a node.
|
|
643
643
|
* Complexity: O(1).
|
|
644
|
-
*/setDefaultNodeLabel(newDefault){this
|
|
644
|
+
*/setDefaultNodeLabel(newDefault){this._defaultNodeLabelFn=newDefault;if(typeof newDefault!=="function"){this._defaultNodeLabelFn=()=>newDefault}return this}
|
|
645
645
|
/**
|
|
646
646
|
* Gets the number of nodes in the graph.
|
|
647
647
|
* Complexity: O(1).
|
|
648
|
-
*/nodeCount(){return this
|
|
648
|
+
*/nodeCount(){return this._nodeCount}
|
|
649
649
|
/**
|
|
650
650
|
* Gets all nodes of the graph. Note, the in case of compound graph subnodes are
|
|
651
651
|
* not included in list.
|
|
652
652
|
* Complexity: O(1).
|
|
653
|
-
*/nodes(){return Object.keys(this
|
|
653
|
+
*/nodes(){return Object.keys(this._nodes)}
|
|
654
654
|
/**
|
|
655
655
|
* Gets list of nodes without in-edges.
|
|
656
656
|
* Complexity: O(|V|).
|
|
657
|
-
*/sources(){var self=this;return this.nodes().filter(v=>Object.keys(self
|
|
657
|
+
*/sources(){var self=this;return this.nodes().filter(v=>Object.keys(self._in[v]).length===0)}
|
|
658
658
|
/**
|
|
659
659
|
* Gets list of nodes without out-edges.
|
|
660
660
|
* Complexity: O(|V|).
|
|
661
|
-
*/sinks(){var self=this;return this.nodes().filter(v=>Object.keys(self
|
|
661
|
+
*/sinks(){var self=this;return this.nodes().filter(v=>Object.keys(self._out[v]).length===0)}
|
|
662
662
|
/**
|
|
663
663
|
* Invokes setNode method for each node in names list.
|
|
664
664
|
* Complexity: O(|names|).
|
|
@@ -668,46 +668,46 @@ this.#children={};this.#children[GRAPH_NODE]={}}}
|
|
|
668
668
|
* it is set as the value for the node. If label is not supplied and the node was
|
|
669
669
|
* created by this call then the default node label will be assigned.
|
|
670
670
|
* Complexity: O(1).
|
|
671
|
-
*/setNode(v,value){if(this
|
|
671
|
+
*/setNode(v,value){if(this._nodes.hasOwnProperty(v)){if(arguments.length>1){this._nodes[v]=value}return this}this._nodes[v]=arguments.length>1?value:this._defaultNodeLabelFn(v);if(this._isCompound){this._parent[v]=GRAPH_NODE;this._children[v]={};this._children[GRAPH_NODE][v]=true}this._in[v]={};this._preds[v]={};this._out[v]={};this._sucs[v]={};++this._nodeCount;return this}
|
|
672
672
|
/**
|
|
673
673
|
* Gets the label of node with specified name.
|
|
674
674
|
* Complexity: O(|V|).
|
|
675
|
-
*/node(v){return this
|
|
675
|
+
*/node(v){return this._nodes[v]}
|
|
676
676
|
/**
|
|
677
677
|
* Detects whether graph has a node with specified name or not.
|
|
678
|
-
*/hasNode(v){return this
|
|
678
|
+
*/hasNode(v){return this._nodes.hasOwnProperty(v)}
|
|
679
679
|
/**
|
|
680
680
|
* Remove the node with the name from the graph or do nothing if the node is not in
|
|
681
681
|
* the graph. If the node was removed this function also removes any incident
|
|
682
682
|
* edges.
|
|
683
683
|
* Complexity: O(1).
|
|
684
|
-
*/removeNode(v){var self=this;if(this
|
|
684
|
+
*/removeNode(v){var self=this;if(this._nodes.hasOwnProperty(v)){var removeEdge=e=>self.removeEdge(self._edgeObjs[e]);delete this._nodes[v];if(this._isCompound){this._removeFromParentsChildList(v);delete this._parent[v];this.children(v).forEach(function(child){self.setParent(child)});delete this._children[v]}Object.keys(this._in[v]).forEach(removeEdge);delete this._in[v];delete this._preds[v];Object.keys(this._out[v]).forEach(removeEdge);delete this._out[v];delete this._sucs[v];--this._nodeCount}return this}
|
|
685
685
|
/**
|
|
686
686
|
* Sets node p as a parent for node v if it is defined, or removes the
|
|
687
687
|
* parent for v if p is undefined. Method throws an exception in case of
|
|
688
688
|
* invoking it in context of noncompound graph.
|
|
689
689
|
* Average-case complexity: O(1).
|
|
690
|
-
*/setParent(v,parent){if(!this
|
|
690
|
+
*/setParent(v,parent){if(!this._isCompound){throw new Error("Cannot set parent in a non-compound graph")}if(parent===undefined){parent=GRAPH_NODE}else{
|
|
691
691
|
// Coerce parent to string
|
|
692
|
-
parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(ancestor)){if(ancestor===v){throw new Error("Setting "+parent+" as parent of "+v+" would create a cycle")}}this.setNode(parent)}this.setNode(v);this
|
|
692
|
+
parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(ancestor)){if(ancestor===v){throw new Error("Setting "+parent+" as parent of "+v+" would create a cycle")}}this.setNode(parent)}this.setNode(v);this._removeFromParentsChildList(v);this._parent[v]=parent;this._children[parent][v]=true;return this}_removeFromParentsChildList(v){delete this._children[this._parent[v]][v]}
|
|
693
693
|
/**
|
|
694
694
|
* Gets parent node for node v.
|
|
695
695
|
* Complexity: O(1).
|
|
696
|
-
*/parent(v){if(this
|
|
696
|
+
*/parent(v){if(this._isCompound){var parent=this._parent[v];if(parent!==GRAPH_NODE){return parent}}}
|
|
697
697
|
/**
|
|
698
698
|
* Gets list of direct children of node v.
|
|
699
699
|
* Complexity: O(1).
|
|
700
|
-
*/children(v=GRAPH_NODE){if(this
|
|
700
|
+
*/children(v=GRAPH_NODE){if(this._isCompound){var children=this._children[v];if(children){return Object.keys(children)}}else if(v===GRAPH_NODE){return this.nodes()}else if(this.hasNode(v)){return[]}}
|
|
701
701
|
/**
|
|
702
702
|
* Return all nodes that are predecessors of the specified node or undefined if node v is not in
|
|
703
703
|
* the graph. Behavior is undefined for undirected graphs - use neighbors instead.
|
|
704
704
|
* Complexity: O(|V|).
|
|
705
|
-
*/predecessors(v){var predsV=this
|
|
705
|
+
*/predecessors(v){var predsV=this._preds[v];if(predsV){return Object.keys(predsV)}}
|
|
706
706
|
/**
|
|
707
707
|
* Return all nodes that are successors of the specified node or undefined if node v is not in
|
|
708
708
|
* the graph. Behavior is undefined for undirected graphs - use neighbors instead.
|
|
709
709
|
* Complexity: O(|V|).
|
|
710
|
-
*/successors(v){var sucsV=this
|
|
710
|
+
*/successors(v){var sucsV=this._sucs[v];if(sucsV){return Object.keys(sucsV)}}
|
|
711
711
|
/**
|
|
712
712
|
* Return all nodes that are predecessors or successors of the specified node or undefined if
|
|
713
713
|
* node v is not in the graph.
|
|
@@ -718,7 +718,7 @@ parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(anc
|
|
|
718
718
|
* are also removed. In case of compound graph, if parent is rejected by filter,
|
|
719
719
|
* than all its children are rejected too.
|
|
720
720
|
* Average-case complexity: O(|E|+|V|).
|
|
721
|
-
*/filterNodes(filter){var copy=new this.constructor({directed:this
|
|
721
|
+
*/filterNodes(filter){var copy=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});copy.setGraph(this.graph());var self=this;Object.entries(this._nodes).forEach(function([v,value]){if(filter(v)){copy.setNode(v,value)}});Object.values(this._edgeObjs).forEach(function(e){if(copy.hasNode(e.v)&©.hasNode(e.w)){copy.setEdge(e,self.edge(e))}});var parents={};function findParent(v){var parent=self.parent(v);if(parent===undefined||copy.hasNode(parent)){parents[v]=parent;return parent}else if(parent in parents){return parents[parent]}else{return findParent(parent)}}if(this._isCompound){copy.nodes().forEach(v=>copy.setParent(v,findParent(v)))}return copy}
|
|
722
722
|
/* === Edge functions ========== */
|
|
723
723
|
/**
|
|
724
724
|
* Sets the default edge label or factory function. This label will be
|
|
@@ -726,15 +726,15 @@ parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(anc
|
|
|
726
726
|
* an edge or this function will be invoked each time when setting an edge
|
|
727
727
|
* with no label specified and returned value * will be used as a label for edge.
|
|
728
728
|
* Complexity: O(1).
|
|
729
|
-
*/setDefaultEdgeLabel(newDefault){this
|
|
729
|
+
*/setDefaultEdgeLabel(newDefault){this._defaultEdgeLabelFn=newDefault;if(typeof newDefault!=="function"){this._defaultEdgeLabelFn=()=>newDefault}return this}
|
|
730
730
|
/**
|
|
731
731
|
* Gets the number of edges in the graph.
|
|
732
732
|
* Complexity: O(1).
|
|
733
|
-
*/edgeCount(){return this
|
|
733
|
+
*/edgeCount(){return this._edgeCount}
|
|
734
734
|
/**
|
|
735
735
|
* Gets edges of the graph. In case of compound graph subgraphs are not considered.
|
|
736
736
|
* Complexity: O(|E|).
|
|
737
|
-
*/edges(){return Object.values(this
|
|
737
|
+
*/edges(){return Object.values(this._edgeObjs)}
|
|
738
738
|
/**
|
|
739
739
|
* Establish an edges path over the nodes in nodes list. If some edge is already
|
|
740
740
|
* exists, it will update its label, otherwise it will create an edge between pair
|
|
@@ -746,16 +746,16 @@ parent+="";for(var ancestor=parent;ancestor!==undefined;ancestor=this.parent(anc
|
|
|
746
746
|
* name. If label is supplied it is set as the value for the edge. If label is not
|
|
747
747
|
* supplied and the edge was created by this call then the default edge label will
|
|
748
748
|
* be assigned. The name parameter is only useful with multigraphs.
|
|
749
|
-
*/setEdge(){var v,w,name,value;var valueSpecified=false;var arg0=arguments[0];if(typeof arg0==="object"&&arg0!==null&&"v"in arg0){v=arg0.v;w=arg0.w;name=arg0.name;if(arguments.length===2){value=arguments[1];valueSpecified=true}}else{v=arg0;w=arguments[1];name=arguments[3];if(arguments.length>2){value=arguments[2];valueSpecified=true}}v=""+v;w=""+w;if(name!==undefined){name=""+name}var e=edgeArgsToId(this
|
|
749
|
+
*/setEdge(){var v,w,name,value;var valueSpecified=false;var arg0=arguments[0];if(typeof arg0==="object"&&arg0!==null&&"v"in arg0){v=arg0.v;w=arg0.w;name=arg0.name;if(arguments.length===2){value=arguments[1];valueSpecified=true}}else{v=arg0;w=arguments[1];name=arguments[3];if(arguments.length>2){value=arguments[2];valueSpecified=true}}v=""+v;w=""+w;if(name!==undefined){name=""+name}var e=edgeArgsToId(this._isDirected,v,w,name);if(this._edgeLabels.hasOwnProperty(e)){if(valueSpecified){this._edgeLabels[e]=value}return this}if(name!==undefined&&!this._isMultigraph){throw new Error("Cannot set a named edge when isMultigraph = false")}
|
|
750
750
|
// It didn't exist, so we need to create it.
|
|
751
751
|
// First ensure the nodes exist.
|
|
752
|
-
this.setNode(v);this.setNode(w);this
|
|
752
|
+
this.setNode(v);this.setNode(w);this._edgeLabels[e]=valueSpecified?value:this._defaultEdgeLabelFn(v,w,name);var edgeObj=edgeArgsToObj(this._isDirected,v,w,name);
|
|
753
753
|
// Ensure we add undirected edges in a consistent way.
|
|
754
|
-
v=edgeObj.v;w=edgeObj.w;Object.freeze(edgeObj);this
|
|
754
|
+
v=edgeObj.v;w=edgeObj.w;Object.freeze(edgeObj);this._edgeObjs[e]=edgeObj;incrementOrInitEntry(this._preds[w],v);incrementOrInitEntry(this._sucs[v],w);this._in[w][e]=edgeObj;this._out[v][e]=edgeObj;this._edgeCount++;return this}
|
|
755
755
|
/**
|
|
756
756
|
* Gets the label for the specified edge.
|
|
757
757
|
* Complexity: O(1).
|
|
758
|
-
*/edge(v,w,name){var e=arguments.length===1?edgeObjToId(this
|
|
758
|
+
*/edge(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);return this._edgeLabels[e]}
|
|
759
759
|
/**
|
|
760
760
|
* Gets the label for the specified edge and converts it to an object.
|
|
761
761
|
* Complexity: O(1)
|
|
@@ -763,21 +763,21 @@ v=edgeObj.v;w=edgeObj.w;Object.freeze(edgeObj);this.#edgeObjs[e]=edgeObj;increme
|
|
|
763
763
|
/**
|
|
764
764
|
* Detects whether the graph contains specified edge or not. No subgraphs are considered.
|
|
765
765
|
* Complexity: O(1).
|
|
766
|
-
*/hasEdge(v,w,name){var e=arguments.length===1?edgeObjToId(this
|
|
766
|
+
*/hasEdge(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);return this._edgeLabels.hasOwnProperty(e)}
|
|
767
767
|
/**
|
|
768
768
|
* Removes the specified edge from the graph. No subgraphs are considered.
|
|
769
769
|
* Complexity: O(1).
|
|
770
|
-
*/removeEdge(v,w,name){var e=arguments.length===1?edgeObjToId(this
|
|
770
|
+
*/removeEdge(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);var edge=this._edgeObjs[e];if(edge){v=edge.v;w=edge.w;delete this._edgeLabels[e];delete this._edgeObjs[e];decrementOrRemoveEntry(this._preds[w],v);decrementOrRemoveEntry(this._sucs[v],w);delete this._in[w][e];delete this._out[v][e];this._edgeCount--}return this}
|
|
771
771
|
/**
|
|
772
772
|
* Return all edges that point to the node v. Optionally filters those edges down to just those
|
|
773
773
|
* coming from node u. Behavior is undefined for undirected graphs - use nodeEdges instead.
|
|
774
774
|
* Complexity: O(|E|).
|
|
775
|
-
*/inEdges(v,u){var inV=this
|
|
775
|
+
*/inEdges(v,u){var inV=this._in[v];if(inV){var edges=Object.values(inV);if(!u){return edges}return edges.filter(edge=>edge.v===u)}}
|
|
776
776
|
/**
|
|
777
777
|
* Return all edges that are pointed at by node v. Optionally filters those edges down to just
|
|
778
778
|
* those point to w. Behavior is undefined for undirected graphs - use nodeEdges instead.
|
|
779
779
|
* Complexity: O(|E|).
|
|
780
|
-
*/outEdges(v,w){var outV=this
|
|
780
|
+
*/outEdges(v,w){var outV=this._out[v];if(outV){var edges=Object.values(outV);if(!w){return edges}return edges.filter(edge=>edge.w===w)}}
|
|
781
781
|
/**
|
|
782
782
|
* Returns all edges to or from node v regardless of direction. Optionally filters those edges
|
|
783
783
|
* down to just those between nodes v and w regardless of direction.
|
|
@@ -798,4 +798,4 @@ module.exports={Graph:require("./graph"),version:require("./version")}},{"./grap
|
|
|
798
798
|
* // ['a', 'b']
|
|
799
799
|
* g2.edges()
|
|
800
800
|
* // [ { v: 'a', w: 'b' } ]
|
|
801
|
-
*/function read(json){var g=new Graph(json.options).setGraph(json.value);json.nodes.forEach(function(entry){g.setNode(entry.v,entry.value);if(entry.parent){g.setParent(entry.v,entry.parent)}});json.edges.forEach(function(entry){g.setEdge({v:entry.v,w:entry.w,name:entry.name},entry.value)});return g}},{"./graph":44}],47:[function(require,module,exports){module.exports="2.
|
|
801
|
+
*/function read(json){var g=new Graph(json.options).setGraph(json.value);json.nodes.forEach(function(entry){g.setNode(entry.v,entry.value);if(entry.parent){g.setParent(entry.v,entry.parent)}});json.edges.forEach(function(entry){g.setEdge({v:entry.v,w:entry.w,name:entry.name},entry.value)});return g}},{"./graph":44}],47:[function(require,module,exports){module.exports="2.2.2"},{}]},{},[1])(1)});
|
package/lib/acyclic.js
CHANGED
|
@@ -1,32 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
let greedyFAS = require("./greedy-fas");
|
|
4
|
+
let uniqueId = require("./util").uniqueId;
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
run: run,
|
|
8
|
+
undo: undo
|
|
9
|
+
};
|
|
10
|
+
|
|
11
11
|
function run(g) {
|
|
12
|
-
let fas = g.graph().acyclicer === "greedy"
|
|
12
|
+
let fas = (g.graph().acyclicer === "greedy"
|
|
13
|
+
? greedyFAS(g, weightFn(g))
|
|
14
|
+
: dfsFAS(g));
|
|
13
15
|
fas.forEach(e => {
|
|
14
16
|
let label = g.edge(e);
|
|
15
17
|
g.removeEdge(e);
|
|
16
18
|
label.forwardName = e.name;
|
|
17
19
|
label.reversed = true;
|
|
18
|
-
g.setEdge(e.w, e.v, label,
|
|
20
|
+
g.setEdge(e.w, e.v, label, uniqueId("rev"));
|
|
19
21
|
});
|
|
22
|
+
|
|
20
23
|
function weightFn(g) {
|
|
21
24
|
return e => {
|
|
22
25
|
return g.edge(e).weight;
|
|
23
26
|
};
|
|
24
27
|
}
|
|
25
28
|
}
|
|
29
|
+
|
|
26
30
|
function dfsFAS(g) {
|
|
27
31
|
let fas = [];
|
|
28
32
|
let stack = {};
|
|
29
33
|
let visited = {};
|
|
34
|
+
|
|
30
35
|
function dfs(v) {
|
|
31
36
|
if (visited.hasOwnProperty(v)) {
|
|
32
37
|
return;
|
|
@@ -42,14 +47,17 @@ function dfsFAS(g) {
|
|
|
42
47
|
});
|
|
43
48
|
delete stack[v];
|
|
44
49
|
}
|
|
50
|
+
|
|
45
51
|
g.nodes().forEach(dfs);
|
|
46
52
|
return fas;
|
|
47
53
|
}
|
|
54
|
+
|
|
48
55
|
function undo(g) {
|
|
49
56
|
g.edges().forEach(e => {
|
|
50
57
|
let label = g.edge(e);
|
|
51
58
|
if (label.reversed) {
|
|
52
59
|
g.removeEdge(e);
|
|
60
|
+
|
|
53
61
|
let forwardName = label.forwardName;
|
|
54
62
|
delete label.reversed;
|
|
55
63
|
delete label.forwardName;
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
let util = require("./util");
|
|
2
|
+
|
|
3
|
+
module.exports = addBorderSegments;
|
|
2
4
|
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = addBorderSegments;
|
|
7
|
-
var util = _interopRequireWildcard(require("./util.js"));
|
|
8
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
9
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
10
5
|
function addBorderSegments(g) {
|
|
11
6
|
function dfs(v) {
|
|
12
7
|
let children = g.children(v);
|
|
@@ -14,32 +9,29 @@ function addBorderSegments(g) {
|
|
|
14
9
|
if (children.length) {
|
|
15
10
|
children.forEach(dfs);
|
|
16
11
|
}
|
|
12
|
+
|
|
17
13
|
if (node.hasOwnProperty("minRank")) {
|
|
18
14
|
node.borderLeft = [];
|
|
19
15
|
node.borderRight = [];
|
|
20
|
-
for (let rank = node.minRank, maxRank = node.maxRank + 1;
|
|
16
|
+
for (let rank = node.minRank, maxRank = node.maxRank + 1;
|
|
17
|
+
rank < maxRank;
|
|
18
|
+
++rank) {
|
|
21
19
|
addBorderNode(g, "borderLeft", "_bl", v, node, rank);
|
|
22
20
|
addBorderNode(g, "borderRight", "_br", v, node, rank);
|
|
23
21
|
}
|
|
24
22
|
}
|
|
25
23
|
}
|
|
24
|
+
|
|
26
25
|
g.children().forEach(dfs);
|
|
27
26
|
}
|
|
27
|
+
|
|
28
28
|
function addBorderNode(g, prop, prefix, sg, sgNode, rank) {
|
|
29
|
-
let label = {
|
|
30
|
-
width: 0,
|
|
31
|
-
height: 0,
|
|
32
|
-
rank: rank,
|
|
33
|
-
borderType: prop
|
|
34
|
-
};
|
|
29
|
+
let label = { width: 0, height: 0, rank: rank, borderType: prop };
|
|
35
30
|
let prev = sgNode[prop][rank - 1];
|
|
36
31
|
let curr = util.addDummyNode(g, "border", label, prefix);
|
|
37
32
|
sgNode[prop][rank] = curr;
|
|
38
33
|
g.setParent(curr, sg);
|
|
39
34
|
if (prev) {
|
|
40
|
-
g.setEdge(prev, curr, {
|
|
41
|
-
weight: 1
|
|
42
|
-
});
|
|
35
|
+
g.setEdge(prev, curr, { weight: 1 });
|
|
43
36
|
}
|
|
44
37
|
}
|
|
45
|
-
module.exports = exports.default;
|
package/lib/coordinate-system.js
CHANGED
|
@@ -1,37 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
module.exports = {
|
|
4
|
+
adjust: adjust,
|
|
5
|
+
undo: undo
|
|
6
|
+
};
|
|
7
|
+
|
|
8
8
|
function adjust(g) {
|
|
9
9
|
let rankDir = g.graph().rankdir.toLowerCase();
|
|
10
10
|
if (rankDir === "lr" || rankDir === "rl") {
|
|
11
11
|
swapWidthHeight(g);
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
+
|
|
14
15
|
function undo(g) {
|
|
15
16
|
let rankDir = g.graph().rankdir.toLowerCase();
|
|
16
17
|
if (rankDir === "bt" || rankDir === "rl") {
|
|
17
18
|
reverseY(g);
|
|
18
19
|
}
|
|
20
|
+
|
|
19
21
|
if (rankDir === "lr" || rankDir === "rl") {
|
|
20
22
|
swapXY(g);
|
|
21
23
|
swapWidthHeight(g);
|
|
22
24
|
}
|
|
23
25
|
}
|
|
26
|
+
|
|
24
27
|
function swapWidthHeight(g) {
|
|
25
28
|
g.nodes().forEach(v => swapWidthHeightOne(g.node(v)));
|
|
26
29
|
g.edges().forEach(e => swapWidthHeightOne(g.edge(e)));
|
|
27
30
|
}
|
|
31
|
+
|
|
28
32
|
function swapWidthHeightOne(attrs) {
|
|
29
33
|
let w = attrs.width;
|
|
30
34
|
attrs.width = attrs.height;
|
|
31
35
|
attrs.height = w;
|
|
32
36
|
}
|
|
37
|
+
|
|
33
38
|
function reverseY(g) {
|
|
34
39
|
g.nodes().forEach(v => reverseYOne(g.node(v)));
|
|
40
|
+
|
|
35
41
|
g.edges().forEach(e => {
|
|
36
42
|
let edge = g.edge(e);
|
|
37
43
|
edge.points.forEach(reverseYOne);
|
|
@@ -40,11 +46,14 @@ function reverseY(g) {
|
|
|
40
46
|
}
|
|
41
47
|
});
|
|
42
48
|
}
|
|
49
|
+
|
|
43
50
|
function reverseYOne(attrs) {
|
|
44
51
|
attrs.y = -attrs.y;
|
|
45
52
|
}
|
|
53
|
+
|
|
46
54
|
function swapXY(g) {
|
|
47
55
|
g.nodes().forEach(v => swapXYOne(g.node(v)));
|
|
56
|
+
|
|
48
57
|
g.edges().forEach(e => {
|
|
49
58
|
let edge = g.edge(e);
|
|
50
59
|
edge.points.forEach(swapXYOne);
|
|
@@ -53,6 +62,7 @@ function swapXY(g) {
|
|
|
53
62
|
}
|
|
54
63
|
});
|
|
55
64
|
}
|
|
65
|
+
|
|
56
66
|
function swapXYOne(attrs) {
|
|
57
67
|
let x = attrs.x;
|
|
58
68
|
attrs.x = attrs.y;
|
package/lib/data/list.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
1
|
/*
|
|
8
2
|
* Simple doubly linked list implementation derived from Cormen, et al.,
|
|
9
3
|
* "Introduction to Algorithms".
|
|
@@ -15,6 +9,7 @@ class List {
|
|
|
15
9
|
sentinel._next = sentinel._prev = sentinel;
|
|
16
10
|
this._sentinel = sentinel;
|
|
17
11
|
}
|
|
12
|
+
|
|
18
13
|
dequeue() {
|
|
19
14
|
let sentinel = this._sentinel;
|
|
20
15
|
let entry = sentinel._prev;
|
|
@@ -23,6 +18,7 @@ class List {
|
|
|
23
18
|
return entry;
|
|
24
19
|
}
|
|
25
20
|
}
|
|
21
|
+
|
|
26
22
|
enqueue(entry) {
|
|
27
23
|
let sentinel = this._sentinel;
|
|
28
24
|
if (entry._prev && entry._next) {
|
|
@@ -33,6 +29,7 @@ class List {
|
|
|
33
29
|
sentinel._next = entry;
|
|
34
30
|
entry._prev = sentinel;
|
|
35
31
|
}
|
|
32
|
+
|
|
36
33
|
toString() {
|
|
37
34
|
let strs = [];
|
|
38
35
|
let sentinel = this._sentinel;
|
|
@@ -44,16 +41,18 @@ class List {
|
|
|
44
41
|
return "[" + strs.join(", ") + "]";
|
|
45
42
|
}
|
|
46
43
|
}
|
|
47
|
-
|
|
44
|
+
|
|
48
45
|
function unlink(entry) {
|
|
49
46
|
entry._prev._next = entry._next;
|
|
50
47
|
entry._next._prev = entry._prev;
|
|
51
48
|
delete entry._next;
|
|
52
49
|
delete entry._prev;
|
|
53
50
|
}
|
|
51
|
+
|
|
54
52
|
function filterOutLinks(k, v) {
|
|
55
53
|
if (k !== "_next" && k !== "_prev") {
|
|
56
54
|
return v;
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
|
-
|
|
57
|
+
|
|
58
|
+
module.exports = List;
|