Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.Netron/3.0.2672.12446/Netron.Diagramming.Core-3.0.2672.12446/Layout/BalloonTreeLayout.cs @ 2768

Last change on this file since 2768 was 2768, checked in by mkommend, 14 years ago

added solution folders and sources for the netron library (ticket #867)

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