From 388813d0944a102e9278f7dd5adca97494bf32fa Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Tue, 16 Jul 2019 05:28:02 +0000 Subject: [PATCH] Simplify affinity, strengthen links --- Layout.js | 10 ++++++---- LayoutGroup.js | 18 ++++++++++++------ LayoutNode.js | 44 +++++++++++--------------------------------- 3 files changed, 29 insertions(+), 43 deletions(-) diff --git a/Layout.js b/Layout.js index 33fbdc8..e939491 100644 --- a/Layout.js +++ b/Layout.js @@ -57,15 +57,17 @@ class Layout { this.groups_ = []; for (let group of this.graph_.groups) { let nodes = this.nodesFromGraphNodes(group.nodes); - this.groups_.push(new LayoutGroup(group, this.nodesByPos_, nodes)); + this.groups_.push(new LayoutGroup(group, this.nodesByPos_, nodes, 'group')); } for (let subgraph of this.graph_.nodesBySubgraph.values()) { let nodes = this.nodesFromGraphNodes(subgraph); - this.groups_.push(new LayoutGroup(null, this.nodesByPos_, nodes)); + this.groups_.push(new LayoutGroup(null, this.nodesByPos_, nodes, + 'subgraph')); } for (let labelGroup of this.graph_.nodesByLabel.values()) { let nodes = this.nodesFromGraphNodes(labelGroup); - this.groups_.push(new LayoutGroup(null, this.nodesByPos_, nodes)); + this.groups_.push(new LayoutGroup(null, this.nodesByPos_, nodes, + 'labelgroup')); } } @@ -223,7 +225,7 @@ class Layout { addGroupPos() { for (let group of this.groups_) { - if (!group.hasGraphGroup()) { + if (!group.isType('group')) { continue; } let [min, max] = group.getMinMax(); diff --git a/LayoutGroup.js b/LayoutGroup.js index 709fcea..e930049 100644 --- a/LayoutGroup.js +++ b/LayoutGroup.js @@ -1,8 +1,9 @@ class LayoutGroup { - constructor(graphGroup, nodesByPos, nodes) { + constructor(graphGroup, nodesByPos, nodes, type) { this.graphGroup_ = graphGroup; this.nodesByPos_ = nodesByPos; this.nodes = new Set(nodes); + this.type = type; this.tension = 0; this.label = this.graphGroup_ ? this.graphGroup_.label : null; @@ -74,10 +75,15 @@ class LayoutGroup { return [min, max]; } - isContained(pos) { + // border is [left, right, top, bottom] + isContained(pos, border=[0,0,0,0]) { let [min, max] = this.getMinMax(); - return (pos[0] >= min[0] && pos[0] <= max[0] && - pos[1] >= min[1] && pos[1] <= max[1]); + return (pos[0] >= (min[0] - border[0]) && pos[0] <= (max[0] + border[1]) && + pos[1] >= (min[1] - border[2]) && pos[1] <= (max[1] + border[3])); + } + + isContainedWithMargin(pos) { + return this.isContained(pos, [1, 1, this.label ? 2 : 1, 1]); } getSteps() { @@ -106,7 +112,7 @@ class LayoutGroup { return steps; } - hasGraphGroup() { - return this.graphGroup_ != null; + isType(type) { + return this.type == type; } } diff --git a/LayoutNode.js b/LayoutNode.js index 710e397..258f9fc 100644 --- a/LayoutNode.js +++ b/LayoutNode.js @@ -35,49 +35,35 @@ class LayoutNode { // Keep unassociated subgroups together this.addAffinity(node, d => d); - // Keep one space between subgraphs - if (this.subgraph != node.subgraph && this.label != node.label) { - this.addAffinity(node, d => d <= 2 ? -INF : 0); - } - - // Am I in any labeled groups that node is not? - // If so, preserve two spaces above the group - if (asymDifference(this.labelGroups(this.groups), node.groups).size) { - this.addAffinity(node, - (d, v) => - (v[0] >= -1 && v[0] <= 1 && v[1] < 0 && v[1] >= -2) ? -INF : 0); - } - - // Preserve one space all around the group - if (asymDifference(this.graphGroups(this.groups), - this.graphGroups(node.groups)).size) { - this.addAffinity(node, d => d <= 2 ? -INF : 0); - } - // Try to stack nodes with the same label if (node.label == this.label) { this.addAffinity(node, (d, v) => v[0] == 0 ? 200 : 500); } for (let group of this.groups) { - // Ensure groups do not overlap + if (!group.isType('group') && !group.isType('subgraph')) { + continue; + } + + // Ensure groups do not overlap, with border if (group.nodes.has(node)) { continue; } - this.addAffinity(node, (d, v, p) => group.isContained(p) ? -INF : 0); + this.addAffinity(node, + (d, v, p) => group.isContainedWithMargin(p) ? -INF : 0); } } for (let link of this.links) { // Stronger affinity for links // Prefer to move toward the target instance - this.addAffinity(link.to, d => d <= 2 ? -INF : d * 11); - link.to.addAffinity(this, d => d <= 2 ? -INF : d * 9); + this.addAffinity(link.to, d => d <= 2 ? -INF : d * 40); + link.to.addAffinity(this, d => d <= 2 ? -INF : d * 35); } - // Affinity for groups + // Affinity within groups for (let group of this.groups) { - if (!group.hasGraphGroup()) { + if (!group.isType('group')) { continue; } for (let node of group.nodes) { @@ -86,14 +72,6 @@ class LayoutNode { } } - graphGroups(groups) { - return new Set(Array.from(groups).filter(g => g.hasGraphGroup())); - } - - labelGroups(groups) { - return new Set(Array.from(groups).filter(g => !!g.label)); - } - addAffinity(node, distanceToWeight) { if (this == node) { return;