Free cookie consent management tool by TermsFeed Policy Generator

source: tags/3.3.0/HeuristicLab.ExtLibs/HeuristicLab.Netron/3.0.2672.12446/Netron.Diagramming.Core-3.0.2672.12446/Layout/BalloonTreeLayout.cs @ 3838

Last change on this file since 3838 was 3038, checked in by mkommend, 15 years ago

removed warnings from HeuristicLab.Netron (ticket #915)

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        #endregion
53
54        #region Methods
55        /// <summary>
56        /// Layouts this instance.
57        /// </summary>
58        public void Layout()
59        {
60            FirstWalk(LayoutRoot as INode);
61            SecondWalk(LayoutRoot as INode, null, LayoutRoot.Rectangle.X, LayoutRoot.Rectangle.Y, 1, 0);
62        }
63        /// <summary>
64        /// Inits this instance.
65        /// </summary>
66        /// <returns></returns>
67        private bool Init()
68        {
69
70
71            this.Graph = this.Model as IGraph;
72
73            if (Graph == null)
74                throw new InconsistencyException("The model has not been set and the Graph property is hence 'null'");
75
76            this.LayoutRoot = this.Controller.Model.LayoutRoot;//could be null if not set in the GUI
77            Graph.ClearSpanningTree();
78            Graph.MakeSpanningTree(LayoutRoot as INode);
79
80            Pars = new Dictionary<string, Params>();
81            if (Graph.Nodes.Count == 0)
82                return false;
83            if (Graph.Edges.Count == 0) //this layout is base on embedded springs in the connections
84                return false;
85
86
87            Params par;
88
89            foreach (INode node in Graph.Nodes)
90            {
91                par = new Params();
92                Pars.Add(node.Uid.ToString(), par);
93            }
94            return true;
95        }
96
97        /// <summary>
98        /// First traversal.
99        /// </summary>
100        /// <param name="n">The n.</param>
101        private void FirstWalk(INode n)
102        {
103            Params np = Pars[n.Uid.ToString()];
104            np.d = 0;
105            double s = 0;
106            if (n.Children != null)
107            {
108                foreach (INode c in n.Children)
109                {
110                    //if (!c.isVisible()) continue;
111                    FirstWalk(c);
112                    Params cp = Pars[c.Uid.ToString()];
113                    np.d = Math.Max(np.d, cp.r);
114                    cp.a = Math.Atan(((double)cp.r) / (np.d + cp.r));
115                    s += cp.a;
116                }
117            }
118            AdjustChildren(np, s);
119            SetRadius(np);
120        }
121        /// <summary>
122        /// Second traversal.
123        /// </summary>
124        /// <param name="n">The n.</param>
125        /// <param name="r">The r.</param>
126        /// <param name="x">The x.</param>
127        /// <param name="y">The y.</param>
128        /// <param name="l">The l.</param>
129        /// <param name="t">The t.</param>
130        private void SecondWalk(INode n, INode r, double x, double y, double l, double t)
131        {
132            setX(n, r, x);
133            setY(n, r, y);
134
135            Params np = Pars[n.Uid.ToString()];
136
137            double dd = l * np.d;
138            double p = t + Math.PI;
139            double fs = (n.ChildCount == 0 ? 0 : np.f / n.ChildCount);
140            double pr = 0;
141            if (n.Children != null)
142            {
143                foreach (INode c in n.Children)
144                {
145
146                    //if (!c.isVisible()) continue;
147                    Params cp = Pars[c.Uid.ToString()];
148                    double aa = np.c * cp.a;
149                    double rr = np.d * Math.Tan(aa) / (1 - Math.Tan(aa));
150                    p += pr + aa + fs;
151                    double xx = (l * rr + dd) * Math.Cos(p);
152                    double yy = (l * rr + dd) * Math.Sin(p);
153                    pr = aa;
154                    SecondWalk(c, n, x + xx, y + yy, l * np.c/*l*rr/cp.r*/, p);
155                }
156            }
157        }
158        /// <summary>
159        /// Sets the radius.
160        /// </summary>
161        /// <param name="np">The np.</param>
162        private void SetRadius(Params np)
163        {
164            np.r = Convert.ToInt32((Math.Max(np.d, m_minRadius) + 2 * np.d) / 2.1D);
165        }
166        /// <summary>
167        /// Adjusts the children.
168        /// </summary>
169        /// <param name="np">The np.</param>
170        /// <param name="s">The s.</param>
171        private void AdjustChildren(Params np, double s)
172        {
173            if (s > Math.PI)
174            {
175                np.c = Math.PI / s;
176                np.f = 0;
177            }
178            else
179            {
180                np.c = 1;
181                np.f = Math.PI - s;
182            }
183        }
184        /// <summary>
185        /// Runs this instance.
186        /// </summary>
187        public override void Run()
188        {
189            Run(2000);
190        }
191        /// <summary>
192        /// Runs the specified time.
193        /// </summary>
194        /// <param name="time">The time.</param>
195        public override void Run(int time)
196        {
197            worker = new BackgroundWorker();
198            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
199            worker.RunWorkerAsync(time);
200        }
201        /// <summary>
202        /// Stops this instance.
203        /// </summary>
204        public override void Stop()
205        {
206            if (worker != null && worker.IsBusy)
207                worker.CancelAsync();
208        }
209        /// <summary>
210        /// Handles the DoWork event of the worker control.
211        /// </summary>
212        /// <param name="sender">The source of the event.</param>
213        /// <param name="e">The <see cref="T:System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
214        private void worker_DoWork(object sender, DoWorkEventArgs e)
215        {
216            Init();
217            Layout();
218        }
219
220
221        #endregion
222
223        #region Classes
224
225        /// <summary>
226        /// Paramter blob to temporarily keep working data of one node.
227        /// </summary>
228        class Params
229        {
230            public int d;
231            public int r;
232            //public double rx;
233            //public double ry;
234            public double a;
235            public double c;
236            public double f;
237        }
238
239        #endregion
240    }
241}
Note: See TracBrowser for help on using the repository browser.