I assume you mean the FindRoots method override. Alas, that method is essential in the virtualization process. Of course you can customize it to your own requirements. But something needs to find the root vertexes when there are absolutely zero Nodes.
Class VirtualizingForceDirectedLayout:ForceDirectedLayout
{
public ILinkModel Model{get;set};
public override ForceDirectedNetWork CreateNetWork(){
return new VirtualizingForceDirectedNetWork();
}
public override ForceDirectedNetWork MakeNetwork(IEnumerable<Node>nodes ,IEnumerable<Link> links){
var net =(VirtualizingForceDirectedNetwork)CreateNetwork();
net.AddData(this.Model);
return net;
}
}
I want to realize Virtualizing using ForceDirectedLayout.The FindRoots is essential,you said,but How can I implement this method in ForceDirectedLayout.
Sorry, no, I meant that it is essential to TreeLayout, but if you are implementing ForceDirectedLayout, that is not a problem.
I cannot find an implementation of a virtualized ForceDirectedLayout. I did find one for LayeredDigraphLayout. Perhaps if you see how that is implemented and compared it with how the VirtualizingTreeLayout is implemented, it will help implementing VirtualizingForceDirectedLayout.
Caution: this implementation may have a number of assumptions about the nodes or about the layout needed for the particular app that needed a virtualized LayeredDigraphLayout.
// Virtualizing LayeredDigraphLayout classes
// Here we try to ignore all methods and properties that deal with Nodes or Links.
// Instead we use Vertex and Edge classes that know about the model data.
// This layout implementation assumes the use of a GraphLinksModel (i.e. an ILinksModel).
public class VirtualizingLayeredDigraphLayout : LayeredDigraphLayout {
public ILinksModel Model { get; set; }
public NodeData SubGraph { get; set; } // the containing group's data
public override LayeredDigraphNetwork CreateNetwork() {
return new VirtualizingLayeredDigraphNetwork();
}
// ignore the arguments, because they assume the existence of Nodes and Links
public override LayeredDigraphNetwork MakeNetwork(IEnumerable<Node> nodes, IEnumerable<Link> links) {
var net = (VirtualizingLayeredDigraphNetwork)CreateNetwork();
if (this.Model != null) {
if (this.SubGraph != null) { // just add members of the given group
net.AddSubGraph(this.SubGraph, this.Model as ISubGraphLinksModel);
} else { // add all top-level nodes and links
net.AddTopLevelGraph(this.Model);
}
}
return net;
}
protected override double NodeMinLayerSpace(LayeredDigraphVertex v, bool topleft) {
var vv = v as VirtualizingLayeredDigraphVertex;
if (vv != null && vv.Data == null) return 0;
Rect r = v.Bounds;
Point p = v.Focus;
if (this.Direction == 90 || this.Direction == 270) {
if (topleft)
return p.Y+10;
else
return r.Height-p.Y+10;
} else {
if (topleft)
return p.X+10;
else
return r.Width-p.X+10;
}
}
protected override int NodeMinColumnSpace(LayeredDigraphVertex v, bool topleft) {
var vv = v as VirtualizingLayeredDigraphVertex;
if (vv != null && vv.Data == null) return 0;
Rect r = v.Bounds;
Point p = v.Focus;
if (this.Direction == 90 || this.Direction == 270) {
if (topleft)
return (int)(p.X/this.ColumnSpacing) + 1;
else
return (int)((r.Width-p.X)/this.ColumnSpacing) + 1;
} else {
if (topleft)
return (int)(p.Y/this.ColumnSpacing) + 1;
else
return (int)((r.Height-p.Y)/this.ColumnSpacing) + 1;
}
}
protected override double LinkStraightenWeight(LayeredDigraphEdge edge) {
var fromVertex = edge.FromVertex as VirtualizingLayeredDigraphVertex ;
var toVertex = edge.ToVertex as VirtualizingLayeredDigraphVertex;
if ((fromVertex != null && fromVertex.Data == null) && (toVertex != null && toVertex.Data == null))
return 8;
if ((fromVertex != null && fromVertex.Data == null) || (toVertex != null && toVertex.Data == null))
return 4;
return 1;
}
}
// Use Virtualizing versions of Vertex and Edge.
public class VirtualizingLayeredDigraphNetwork : LayeredDigraphNetwork {
public override LayeredDigraphVertex CreateVertex() {
return new VirtualizingLayeredDigraphVertex();
}
public override LayeredDigraphEdge CreateEdge() {
return new VirtualizingLayeredDigraphEdge();
}
private Dictionary<NodeData, VirtualizingLayeredDigraphVertex> NodeDataMap = new Dictionary<NodeData, VirtualizingLayeredDigraphVertex>();
private Dictionary<LinkData, VirtualizingLayeredDigraphEdge> LinkDataMap = new Dictionary<LinkData, VirtualizingLayeredDigraphEdge>();
// a replacement for LayeredDigraphNetwork.AddNodesAndLinks using top-level model data instead of Nodes or Links
public void AddTopLevelGraph(ILinksModel model) {
if (model == null) return;
NodeDataMap.Clear();
LinkDataMap.Clear();
ISubGraphLinksModel sgmodel = model as ISubGraphLinksModel;
var nodes = model.NodesSource as IEnumerable<NodeData>;
foreach (NodeData d in nodes) {
if (sgmodel == null || sgmodel.GetGroupForNode(d) == null) {
AddNodeData(d, model);
}
}
var links = model.LinksSource as IEnumerable<LinkData>;
foreach (LinkData d in links) {
if (sgmodel == null || sgmodel.GetGroupForLink(d) == null) {
AddLinkData(d, model);
}
}
}
// a replacement for LayeredDigraphNetwork.AddNodesAndLinks using a group's members' model data instead of Nodes or Links
public void AddSubGraph(NodeData sg, ISubGraphLinksModel model) {
if (sg == null || model == null) return;
NodeDataMap.Clear();
LinkDataMap.Clear();
foreach (NodeData d in model.GetMemberNodesForGroup(sg)) {
AddNodeData(d, model);
}
foreach (LinkData d in model.GetMemberLinksForGroup(sg)) {
AddLinkData(d, model);
}
}
public void AddNodeData(NodeData d, ILinksModel model) {
if (NodeDataMap.ContainsKey(d)) return;
// create and add VirtualizingLayeredDigraphVertex
var v = (VirtualizingLayeredDigraphVertex)CreateVertex();
v.Data = d;
NodeDataMap.Add(d, v);
AddVertex(v);
}
public void AddLinkData(LinkData d, ILinksModel model) {
if (LinkDataMap.ContainsKey(d)) return;
// find connected node data
var from = (NodeData)model.FindNodeByKey(d.From);
var to = (NodeData)model.FindNodeByKey(d.To);
if (from == null || to == null || from == to) return; // skip
// now find corresponding vertexes
VirtualizingLayeredDigraphVertex f;
NodeDataMap.TryGetValue(from, out f);
VirtualizingLayeredDigraphVertex t;
NodeDataMap.TryGetValue(to, out t);
if (f == null || t == null) return; // skip
// create and add VirtualizingLayeredDigraphEdge
var e = (VirtualizingLayeredDigraphEdge)CreateEdge();
e.Data = d;
e.FromVertex = f;
e.ToVertex = t;
AddEdge(e);
}
}
// Associate with NodeData rather than with Node.
public class VirtualizingLayeredDigraphVertex : LayeredDigraphVertex {
public NodeData Data {
get { return _Data; }
set {
_Data = value;
if (_Data != null) {
// use bounds information from the NodeData rather than the Node.Bounds!
this.Focus = new Point(_Data.Width/2, _Data.Height/2);
this.Bounds = VirtualizingPartManager.ComputeNodeBounds(_Data);
}
}
}
private NodeData _Data = null;
public override void CommitPosition() {
if (this.Data != null) {
this.Data.Location = this.Center; // set NodeData.Location instead of Node.Location!
} else {
base.CommitPosition();
}
}
}
// Associate with LinkData rather than with Link.
// NOTE: This does not support custom routing of links that is normally done by LayeredDigraphLayout
public class VirtualizingLayeredDigraphEdge : LayeredDigraphEdge {
public LinkData Data { get; set; }
}
I have read your code,but I still have no idea how to implement the VirtualizingForceDirectedLayout,beacause I don’t what should I do to do the initial layout before assigning to Diagram.Model with different layouts.
Our Costomer want to implement the Virtualizing with all the layout.