Reputation: 19879
I currently have a Force Layout:
http://bl.ocks.org/mbostock/4062045
So my data is simply nodes and links, but I'd like to create this Hierarchical Edge Bundling with the same data:
http://bl.ocks.org/mbostock/7607999
I'm having issues because my data isn't hierarchical. Its just nodes and links. I'm not sure how to make this work, but it must be possible.
Upvotes: 4
Views: 2493
Reputation: 1
Build external parent nodes based on the group attribute of the nodes. The whole graph consists of three levels: root, parent nodes of each group, leaf nodes(real nodes).
Please take a look at function gen_fake_data
, which hopefully helps u gain a better understanding.
P.S. the code may not work at jsfiddle, but works at my local environment.
https://jsfiddle.net/6rcc3n2e/
results of my randomly generated data
Upvotes: 0
Reputation: 10536
I believe the best approach would be to modify the data you have before applying bundle layout.
Specifically, you should be able to introduce a fictional root to make your data hierarchical. The root node could be:
a) parent for all nodes in your current data that have at least one child
or
b) parent for all nodes in your current data that do not have a parent.
What is better depends on your case (data/application).
While converting the data, you need to take care of two things on top of that: make sure your original data does not have cycles (that would prevent converting it to hierarchy), and you need to follow data format for bundle layout (for example, see json file http://bl.ocks.org/mbostock/raw/1044242/readme-flare-imports.json).
[
{
"name":"flare.analytics.cluster.AgglomerativeCluster",
"size":3938,
"imports":[
"flare.animate.Transitioner",
"flare.vis.data.DataList",
"flare.util.math.IMatrix",
"flare.analytics.cluster.MergeEdge",
"flare.analytics.cluster.HierarchicalCluster",
"flare.vis.data.Data"
]
},
{
"name":"flare.analytics.cluster.CommunityStructure",
"size":3812,
"imports":[
"flare.analytics.cluster.HierarchicalCluster",
"flare.animate.Transitioner",
"flare.vis.data.DataList",
"flare.analytics.cluster.MergeEdge",
"flare.util.math.IMatrix"
]
},
{
"name":"flare.analytics.cluster.HierarchicalCluster",
"size":6714,
"imports":[
"flare.vis.data.EdgeSprite",
"flare.vis.data.NodeSprite",
"flare.vis.data.DataList",
"flare.vis.data.Tree",
"flare.util.Arrays",
"flare.analytics.cluster.MergeEdge",
"flare.util.Sort",
"flare.vis.operator.Operator",
"flare.util.Property",
"flare.vis.data.Data"
]
},
{
"name":"flare.analytics.cluster.MergeEdge",
"size":743,
"imports":[
]
},
{
"name":"flare.analytics.graph.BetweennessCentrality",
"size":3534,
"imports":[
"flare.animate.Transitioner",
"flare.vis.data.NodeSprite",
"flare.vis.data.DataList",
"flare.util.Arrays",
"flare.vis.data.Data",
"flare.util.Property",
"flare.vis.operator.Operator"
]
},
{
"name":"flare.analytics.graph.LinkDistance",
"size":5731,
"imports":[
"flare.animate.Transitioner",
"flare.vis.data.NodeSprite",
"flare.vis.data.EdgeSprite",
"flare.analytics.graph.ShortestPaths",
"flare.vis.data.Data",
"flare.util.Property",
"flare.vis.operator.Operator"
]
},
{
"name":"flare.analytics.graph.MaxFlowMinCut",
"size":7840,
"imports":[
"flare.animate.Transitioner",
"flare.vis.data.NodeSprite",
"flare.vis.data.EdgeSprite",
"flare.vis.data.Data",
"flare.util.Property",
"flare.vis.operator.Operator"
]
},
{
"name":"flare.analytics.graph.ShortestPaths",
"size":5914,
"imports":[
"flare.vis.data.EdgeSprite",
"flare.vis.data.NodeSprite",
"flare.animate.Transitioner",
"flare.vis.operator.Operator",
"flare.util.heap.HeapNode",
"flare.util.heap.FibonacciHeap",
"flare.util.Property",
"flare.vis.data.Data"
]
},
{
"name":"flare.analytics.graph.SpanningTree",
"size":3416,
"imports":[
"flare.animate.Transitioner",
"flare.vis.data.NodeSprite",
"flare.vis.operator.IOperator",
"flare.vis.Visualization",
"flare.vis.data.TreeBuilder",
"flare.vis.operator.Operator"
]
},
{
"name":"flare.analytics.optimization.AspectRatioBanker",
"size":7074,
"imports":[
"flare.animate.Transitioner",
"flare.util.Arrays",
"flare.vis.data.DataSprite",
"flare.scale.Scale",
"flare.vis.axis.CartesianAxes",
"flare.vis.Visualization",
"flare.util.Property",
"flare.vis.operator.Operator"
]
},
{
"name":"flare.animate.Easing",
"size":17010,
"imports":[
"flare.animate.Transition"
]
},
{
"name":"flare.animate.FunctionSequence",
"size":5842,
"imports":[
"flare.util.Maths",
"flare.animate.Transition",
"flare.util.Arrays",
"flare.animate.Sequence",
"flare.animate.Transitioner"
]
},
{
"name":"flare.animate.interpolate.ArrayInterpolator",
"size":1983,
"imports":[
"flare.util.Arrays",
"flare.animate.interpolate.Interpolator"
]
},
{
"name":"flare.animate.interpolate.ColorInterpolator",
"size":2047,
"imports":[
"flare.animate.interpolate.Interpolator"
]
},
{
"name":"flare.animate.interpolate.DateInterpolator",
"size":1375,
"imports":[
"flare.animate.interpolate.Interpolator"
]
},
{
"name":"flare.animate.interpolate.Interpolator",
"size":8746,
"imports":[
"flare.animate.interpolate.NumberInterpolator",
"flare.animate.interpolate.ColorInterpolator",
"flare.animate.interpolate.PointInterpolator",
"flare.animate.interpolate.ObjectInterpolator",
"flare.animate.interpolate.MatrixInterpolator",
"flare.animate.interpolate.RectangleInterpolator",
"flare.animate.interpolate.DateInterpolator",
"flare.util.Property",
"flare.animate.interpolate.ArrayInterpolator"
]
},
{
"name":"flare.animate.interpolate.MatrixInterpolator",
"size":2202,
"imports":[
"flare.animate.interpolate.Interpolator"
]
},
{
"name":"flare.animate.interpolate.NumberInterpolator",
"size":1382,
"imports":[
"flare.animate.interpolate.Interpolator"
]
},
{
"name":"flare.animate.interpolate.ObjectInterpolator",
"size":1629,
"imports":[
"flare.animate.interpolate.Interpolator"
]
},
{
"name":"flare.animate.interpolate.PointInterpolator",
"size":1675,
"imports":[
"flare.animate.interpolate.Interpolator"
]
},
{
"name":"flare.animate.interpolate.RectangleInterpolator",
"size":2042,
"imports":[
"flare.animate.interpolate.Interpolator"
]
},
{
"name":"flare.animate.ISchedulable",
"size":1041,
"imports":[
"flare.animate.Scheduler"
]
},
{
"name":"flare.animate.Parallel",
"size":5176,
"imports":[
"flare.animate.Easing",
"flare.animate.Transition",
"flare.util.Arrays"
]
},
{
"name":"flare.animate.Pause",
"size":449,
"imports":[
"flare.animate.Transition"
]
},
{
"name":"flare.animate.Scheduler",
"size":5593,
"imports":[
"flare.animate.ISchedulable",
"flare.animate.Pause",
"flare.animate.Transition"
]
},
{
"name":"flare.animate.Sequence",
"size":5534,
"imports":[
"flare.animate.Easing",
"flare.util.Maths",
"flare.animate.Transition",
"flare.util.Arrays"
]
},
{
"name":"flare.animate.Transition",
"size":9201,
"imports":[
"flare.animate.Transitioner",
"flare.animate.TransitionEvent",
"flare.animate.Scheduler",
"flare.animate.Pause",
"flare.animate.Parallel",
"flare.animate.Easing",
"flare.animate.Sequence",
"flare.animate.ISchedulable",
"flare.util.Maths",
"flare.animate.Tween"
]
},
{
"name":"flare.animate.Transitioner",
"size":19975,
"imports":[
"flare.util.IValueProxy",
"flare.animate.Parallel",
"flare.animate.Easing",
"flare.animate.Sequence",
"flare.animate.Transition",
"flare.animate.Tween",
"flare.util.Property"
]
},
{
"name":"flare.animate.TransitionEvent",
"size":1116,
"imports":[
"flare.animate.Transition"
]
},
{
"name":"flare.animate.Tween",
"size":6006,
"imports":[
"flare.animate.Transitioner",
"flare.animate.Transition",
"flare.animate.interpolate.Interpolator",
"flare.util.Property"
]
},
{
"name":"flare.data.converters.Converters",
"size":721,
"imports":[
"flare.data.converters.IDataConverter",
"flare.data.converters.GraphMLConverter",
"flare.data.converters.JSONConverter",
"flare.data.converters.DelimitedTextConverter"
]
},
{
"name":"flare.data.converters.DelimitedTextConverter",
"size":4294,
"imports":[
"flare.data.DataSet",
"flare.data.DataUtil",
"flare.data.DataTable",
"flare.data.converters.IDataConverter",
"flare.data.DataSchema",
"flare.data.DataField"
]
},
{
"name":"flare.data.converters.GraphMLConverter",
"size":9800,
"imports":[
"flare.data.DataSet",
"flare.data.DataUtil",
"flare.data.DataTable",
"flare.data.converters.IDataConverter",
"flare.data.DataSchema",
"flare.data.DataField"
]
},
{
"name":"flare.data.converters.IDataConverter",
"size":1314,
"imports":[
"flare.data.DataSet",
"flare.data.DataSchema"
]
},
{
"name":"flare.data.converters.JSONConverter",
"size":2220,
"imports":[
"flare.data.DataSet",
"flare.data.DataUtil",
"flare.data.DataTable",
"flare.data.converters.IDataConverter",
"flare.data.DataSchema",
"flare.data.DataField",
"flare.util.Property"
]
},
{
"name":"flare.data.DataField",
"size":1759,
"imports":[
"flare.data.DataUtil"
]
},
{
"name":"flare.data.DataSchema",
"size":2165,
"imports":[
"flare.data.DataField",
"flare.util.Arrays"
]
},
.
.
.
{
"name":"flare.vis.Visualization",
"size":16540,
"imports":[
"flare.animate.Transitioner",
"flare.vis.operator.IOperator",
"flare.animate.Scheduler",
"flare.vis.events.VisualizationEvent",
"flare.vis.data.Tree",
"flare.vis.events.DataEvent",
"flare.vis.axis.Axes",
"flare.vis.axis.CartesianAxes",
"flare.util.Displays",
"flare.vis.operator.OperatorList",
"flare.vis.controls.ControlList",
"flare.animate.ISchedulable",
"flare.vis.data.Data"
]
}
]
Upvotes: 2
Reputation: 21
Hierarchical Edge Bundling requires that there be a hierarchy. It can even be arbitrary but without it there is no way to create the bundling effect. The bundling is determined by the hierarchies (elements with the same parent will bundle the same way).
Upvotes: 2