Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.ExtLibs/HeuristicLab.Netron/3.0.2672.12446/Netron.Diagramming.Core-3.0.2672.12446/Layout/BalloonTreeLayout.cs

Last change on this file was 4068, checked in by swagner, 14 years ago

Sorted usings and removed unused usings in entire solution (#1094)

File size: 6.1 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using Netron.Diagramming.Core.Analysis;
5namespace Netron.Diagramming.Core {
6  /// <summary>
7  /// <para>Layout that computes a circular "balloon-tree" layout of a tree.
8  /// This layout places children nodes radially around their parents, and is
9  ///equivalent to a top-down flattened view of a ConeTree.</para>
10  ///
11  /// <para>The algorithm used is that of G. Melançon and I. Herman from their
12  /// research paper Circular Drawings of Rooted Trees, Reports of the Centre for
13  /// Mathematics and Computer Sciences, Report Number INS–9817, 1998.</para>
14  /// </summary>
15  class BalloonTreeLayout : TreeLayoutBase {
16    #region Fields
17
18    private int m_minRadius = 2;
19    private Dictionary<string, Params> Pars;
20    BackgroundWorker worker;
21
22    #endregion
23
24    #region Properties
25
26
27    /// <summary>
28    /// Gets or sets the MinRadius
29    /// </summary>
30    public int MinRadius {
31      get { return m_minRadius; }
32      set { m_minRadius = value; }
33    }
34
35    #endregion
36
37    #region Constructor
38    ///<summary>
39    ///Default constructor
40    ///</summary>
41    public BalloonTreeLayout(IController controller)
42      : base("Balloon TreeLayout", controller) {
43    }
44    #endregion
45
46    #region Methods
47    /// <summary>
48    /// Layouts this instance.
49    /// </summary>
50    public void Layout() {
51      FirstWalk(LayoutRoot as INode);
52      SecondWalk(LayoutRoot as INode, null, LayoutRoot.Rectangle.X, LayoutRoot.Rectangle.Y, 1, 0);
53    }
54    /// <summary>
55    /// Inits this instance.
56    /// </summary>
57    /// <returns></returns>
58    private bool Init() {
59
60
61      this.Graph = this.Model as IGraph;
62
63      if (Graph == null)
64        throw new InconsistencyException("The model has not been set and the Graph property is hence 'null'");
65
66      this.LayoutRoot = this.Controller.Model.LayoutRoot;//could be null if not set in the GUI
67      Graph.ClearSpanningTree();
68      Graph.MakeSpanningTree(LayoutRoot as INode);
69
70      Pars = new Dictionary<string, Params>();
71      if (Graph.Nodes.Count == 0)
72        return false;
73      if (Graph.Edges.Count == 0) //this layout is base on embedded springs in the connections
74        return false;
75
76
77      Params par;
78
79      foreach (INode node in Graph.Nodes) {
80        par = new Params();
81        Pars.Add(node.Uid.ToString(), par);
82      }
83      return true;
84    }
85
86    /// <summary>
87    /// First traversal.
88    /// </summary>
89    /// <param name="n">The n.</param>
90    private void FirstWalk(INode n) {
91      Params np = Pars[n.Uid.ToString()];
92      np.d = 0;
93      double s = 0;
94      if (n.Children != null) {
95        foreach (INode c in n.Children) {
96          //if (!c.isVisible()) continue;
97          FirstWalk(c);
98          Params cp = Pars[c.Uid.ToString()];
99          np.d = Math.Max(np.d, cp.r);
100          cp.a = Math.Atan(((double)cp.r) / (np.d + cp.r));
101          s += cp.a;
102        }
103      }
104      AdjustChildren(np, s);
105      SetRadius(np);
106    }
107    /// <summary>
108    /// Second traversal.
109    /// </summary>
110    /// <param name="n">The n.</param>
111    /// <param name="r">The r.</param>
112    /// <param name="x">The x.</param>
113    /// <param name="y">The y.</param>
114    /// <param name="l">The l.</param>
115    /// <param name="t">The t.</param>
116    private void SecondWalk(INode n, INode r, double x, double y, double l, double t) {
117      setX(n, r, x);
118      setY(n, r, y);
119
120      Params np = Pars[n.Uid.ToString()];
121
122      double dd = l * np.d;
123      double p = t + Math.PI;
124      double fs = (n.ChildCount == 0 ? 0 : np.f / n.ChildCount);
125      double pr = 0;
126      if (n.Children != null) {
127        foreach (INode c in n.Children) {
128
129          //if (!c.isVisible()) continue;
130          Params cp = Pars[c.Uid.ToString()];
131          double aa = np.c * cp.a;
132          double rr = np.d * Math.Tan(aa) / (1 - Math.Tan(aa));
133          p += pr + aa + fs;
134          double xx = (l * rr + dd) * Math.Cos(p);
135          double yy = (l * rr + dd) * Math.Sin(p);
136          pr = aa;
137          SecondWalk(c, n, x + xx, y + yy, l * np.c/*l*rr/cp.r*/, p);
138        }
139      }
140    }
141    /// <summary>
142    /// Sets the radius.
143    /// </summary>
144    /// <param name="np">The np.</param>
145    private void SetRadius(Params np) {
146      np.r = Convert.ToInt32((Math.Max(np.d, m_minRadius) + 2 * np.d) / 2.1D);
147    }
148    /// <summary>
149    /// Adjusts the children.
150    /// </summary>
151    /// <param name="np">The np.</param>
152    /// <param name="s">The s.</param>
153    private void AdjustChildren(Params np, double s) {
154      if (s > Math.PI) {
155        np.c = Math.PI / s;
156        np.f = 0;
157      } else {
158        np.c = 1;
159        np.f = Math.PI - s;
160      }
161    }
162    /// <summary>
163    /// Runs this instance.
164    /// </summary>
165    public override void Run() {
166      Run(2000);
167    }
168    /// <summary>
169    /// Runs the specified time.
170    /// </summary>
171    /// <param name="time">The time.</param>
172    public override void Run(int time) {
173      worker = new BackgroundWorker();
174      worker.DoWork += new DoWorkEventHandler(worker_DoWork);
175      worker.RunWorkerAsync(time);
176    }
177    /// <summary>
178    /// Stops this instance.
179    /// </summary>
180    public override void Stop() {
181      if (worker != null && worker.IsBusy)
182        worker.CancelAsync();
183    }
184    /// <summary>
185    /// Handles the DoWork event of the worker control.
186    /// </summary>
187    /// <param name="sender">The source of the event.</param>
188    /// <param name="e">The <see cref="T:System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
189    private void worker_DoWork(object sender, DoWorkEventArgs e) {
190      Init();
191      Layout();
192    }
193
194
195    #endregion
196
197    #region Classes
198
199    /// <summary>
200    /// Paramter blob to temporarily keep working data of one node.
201    /// </summary>
202    class Params {
203      public int d;
204      public int r;
205      //public double rx;
206      //public double ry;
207      public double a;
208      public double c;
209      public double f;
210    }
211
212    #endregion
213  }
214}
Note: See TracBrowser for help on using the repository browser.