/sources/AssemblyVisualizer/Controls/Graph/GraphSharp/Layout/ParameterizedLayoutAlgorithmBase.cs

https://github.com/saeidmh83/AssemblyVisualizer · C# · 258 lines · 169 code · 34 blank · 55 comment · 10 complexity · edc3202ae529a5b54d57c63a29a6fe83 MD5 · raw file

  1. // Adopted, originally created as part of GraphSharp library
  2. // This code is distributed under Microsoft Public License
  3. // (for details please see \docs\Ms-PL)
  4. using System;
  5. using System.Collections.Generic;
  6. using AssemblyVisualizer.Controls.Graph.QuickGraph;
  7. using System.Linq;
  8. using System.Diagnostics;
  9. using System.Windows;
  10. namespace AssemblyVisualizer.Controls.Graph.GraphSharp.Layout
  11. {
  12. public abstract class ParameterizedLayoutAlgorithmBase<TVertex, TEdge, TGraph, TVertexInfo, TEdgeInfo, TParam> : ParameterizedLayoutAlgorithmBase<TVertex, TEdge, TGraph, TParam>, ILayoutAlgorithm<TVertex, TEdge, TGraph, TVertexInfo, TEdgeInfo>
  13. where TVertex : class
  14. where TEdge : IEdge<TVertex>
  15. where TGraph : IVertexAndEdgeListGraph<TVertex, TEdge>
  16. where TParam : class, ILayoutParameters
  17. {
  18. protected readonly IDictionary<TVertex, TVertexInfo> vertexInfos = new Dictionary<TVertex, TVertexInfo>();
  19. protected readonly IDictionary<TEdge, TEdgeInfo> edgeInfos = new Dictionary<TEdge, TEdgeInfo>();
  20. protected ParameterizedLayoutAlgorithmBase( TGraph visitedGraph )
  21. : base( visitedGraph, null, null ) { }
  22. protected ParameterizedLayoutAlgorithmBase( TGraph visitedGraph, IDictionary<TVertex, Point> vertexPositions,
  23. TParam oldParameters )
  24. : base( visitedGraph, vertexPositions, oldParameters )
  25. {
  26. }
  27. #region ILayoutAlgorithm<TVertex,TEdge,TGraph,TVertexInfo,TEdgeInfo> Members
  28. public IDictionary<TVertex, TVertexInfo> VertexInfos
  29. {
  30. get { return vertexInfos; }
  31. }
  32. public IDictionary<TEdge, TEdgeInfo> EdgeInfos
  33. {
  34. get { return edgeInfos; }
  35. }
  36. protected override ILayoutIterationEventArgs<TVertex> CreateLayoutIterationEventArgs( int iteration, double statusInPercent, string message, IDictionary<TVertex, Point> vertexPositions )
  37. {
  38. return new LayoutIterationEventArgs<TVertex, TEdge, TVertexInfo, TEdgeInfo>( iteration, statusInPercent, message, vertexPositions, vertexInfos, edgeInfos );
  39. }
  40. //public new event LayoutIterationEndedEventHandler<TVertex, TEdge, TVertexInfo, TEdgeInfo> IterationEnded;
  41. public override object GetVertexInfo( TVertex vertex )
  42. {
  43. TVertexInfo info;
  44. if ( VertexInfos.TryGetValue( vertex, out info ) )
  45. return info;
  46. return null;
  47. }
  48. public override object GetEdgeInfo( TEdge edge )
  49. {
  50. TEdgeInfo info;
  51. if ( EdgeInfos.TryGetValue( edge, out info ) )
  52. return info;
  53. return null;
  54. }
  55. #endregion
  56. }
  57. /// <summary>
  58. /// Use this class as a base class for your layout algorithm
  59. /// if it's parameter class has a default contstructor.
  60. /// </summary>
  61. /// <typeparam name="TVertex">The type of the vertices.</typeparam>
  62. /// <typeparam name="TEdge">The type of the edges.</typeparam>
  63. /// <typeparam name="TGraph">The type of the graph.</typeparam>
  64. /// <typeparam name="TParam">The type of the parameters. Must be based on the LayoutParametersBase.</typeparam>
  65. public abstract class DefaultParameterizedLayoutAlgorithmBase<TVertex, TEdge, TGraph, TParam> : ParameterizedLayoutAlgorithmBase<TVertex, TEdge, TGraph, TParam>
  66. where TVertex : class
  67. where TEdge : IEdge<TVertex>
  68. where TGraph : IVertexAndEdgeListGraph<TVertex, TEdge>
  69. where TParam : class, ILayoutParameters, new()
  70. {
  71. protected DefaultParameterizedLayoutAlgorithmBase(TGraph visitedGraph)
  72. : base(visitedGraph)
  73. {
  74. }
  75. protected DefaultParameterizedLayoutAlgorithmBase(TGraph visitedGraph, IDictionary<TVertex, Point> vertexPositions, TParam oldParameters)
  76. : base(visitedGraph, vertexPositions, oldParameters)
  77. {
  78. }
  79. protected override TParam DefaultParameters
  80. {
  81. get { return new TParam(); }
  82. }
  83. }
  84. /// <typeparam name="TVertex">Type of the vertices.</typeparam>
  85. /// <typeparam name="TEdge">Type of the edges.</typeparam>
  86. /// <typeparam name="TGraph">Type of the graph.</typeparam>
  87. /// <typeparam name="TParam">Type of the parameters. Must be based on the LayoutParametersBase.</typeparam>
  88. public abstract class ParameterizedLayoutAlgorithmBase<TVertex, TEdge, TGraph, TParam> : LayoutAlgorithmBase<TVertex, TEdge, TGraph>, IParameterizedLayoutAlgorithm<TParam>
  89. where TVertex : class
  90. where TEdge : IEdge<TVertex>
  91. where TGraph : IVertexAndEdgeListGraph<TVertex, TEdge>
  92. where TParam : class, ILayoutParameters
  93. {
  94. #region Properties
  95. /// <summary>
  96. /// Parameters of the algorithm. For more information see <see cref="LayoutParametersBase"/>.
  97. /// </summary>
  98. public TParam Parameters { get; protected set; }
  99. public ILayoutParameters GetParameters()
  100. {
  101. return Parameters;
  102. }
  103. public TraceSource TraceSource { get; protected set; }
  104. #endregion
  105. #region Constructors
  106. protected ParameterizedLayoutAlgorithmBase( TGraph visitedGraph )
  107. : this( visitedGraph, null, null ) { }
  108. protected ParameterizedLayoutAlgorithmBase( TGraph visitedGraph, IDictionary<TVertex, Point> vertexPositions,
  109. TParam oldParameters )
  110. : base( visitedGraph, vertexPositions )
  111. {
  112. InitParameters( oldParameters );
  113. TraceSource = new TraceSource( "LayoutAlgorithm", SourceLevels.All );
  114. }
  115. #endregion
  116. #region Initializers
  117. protected abstract TParam DefaultParameters { get; }
  118. /// <summary>
  119. /// Initializes the parameters (cloning or creating new parameter object with default values).
  120. /// </summary>
  121. /// <param name="oldParameters">Parameters from a prevorious layout. If it is null,
  122. /// the parameters will be set to the default ones.</param>
  123. protected void InitParameters( TParam oldParameters )
  124. {
  125. if (oldParameters == null)
  126. Parameters = DefaultParameters;
  127. else
  128. {
  129. Parameters = (TParam)oldParameters.Clone();
  130. }
  131. }
  132. /// <summary>
  133. /// Initializes the positions of the vertices. Assign a random position inside the 'bounding box' to the vertices without positions.
  134. /// It does NOT modify the position of the other vertices.
  135. ///
  136. /// It generates an <code>IterationEnded</code> event.
  137. ///
  138. /// Bounding box:
  139. /// x coordinates: double.Epsilon - <code>width</code>
  140. /// y coordinates: double.Epsilon - <code>height</code>
  141. /// </summary>
  142. /// <param name="width">Width of the bounding box.</param>
  143. /// <param name="height">Height of the bounding box.</param>
  144. protected virtual void InitializeWithRandomPositions( double width, double height )
  145. {
  146. InitializeWithRandomPositions( width, height, 0, 0 );
  147. }
  148. /// <summary>
  149. /// Initializes the positions of the vertices. Assign a random position inside the 'bounding box' to the vertices without positions.
  150. /// It does NOT modify the position of the other vertices.
  151. ///
  152. /// It generates an <code>IterationEnded</code> event.
  153. ///
  154. /// Bounding box:
  155. /// x coordinates: double.Epsilon - <code>width</code>
  156. /// y coordinates: double.Epsilon - <code>height</code>
  157. /// </summary>
  158. /// <param name="width">Width of the bounding box.</param>
  159. /// <param name="height">Height of the bounding box.</param>
  160. /// <param name="translate_x">Translates the generated x coordinate.</param>
  161. /// <param name="translate_y">Translates the generated y coordinate.</param>
  162. protected virtual void InitializeWithRandomPositions( double width, double height, double translate_x, double translate_y )
  163. {
  164. var rnd = new Random( DateTime.Now.Millisecond );
  165. //initialize with random position
  166. foreach ( TVertex v in VisitedGraph.Vertices )
  167. {
  168. //for vertices without assigned position
  169. if ( !VertexPositions.ContainsKey( v ) )
  170. {
  171. VertexPositions[v] =
  172. new Point(
  173. Math.Max( double.Epsilon, rnd.NextDouble() * width + translate_x ),
  174. Math.Max( double.Epsilon, rnd.NextDouble() * height + translate_y ) );
  175. }
  176. }
  177. }
  178. protected virtual void NormalizePositions()
  179. {
  180. lock ( SyncRoot )
  181. {
  182. NormalizePositions( VertexPositions );
  183. }
  184. }
  185. protected static void NormalizePositions( IDictionary<TVertex, Point> vertexPositions )
  186. {
  187. if ( vertexPositions == null || vertexPositions.Count == 0 )
  188. return;
  189. //get the topLeft position
  190. var topLeft = new Point( float.PositiveInfinity, float.PositiveInfinity );
  191. foreach ( var pos in vertexPositions.Values.ToArray() )
  192. {
  193. topLeft.X = Math.Min( topLeft.X, pos.X );
  194. topLeft.Y = Math.Min( topLeft.Y, pos.Y );
  195. }
  196. //translate with the topLeft position
  197. foreach ( var v in vertexPositions.Keys.ToArray() )
  198. {
  199. var pos = vertexPositions[v];
  200. pos.X -= topLeft.X;
  201. pos.Y -= topLeft.Y;
  202. vertexPositions[v] = pos;
  203. }
  204. }
  205. #endregion
  206. protected void OnIterationEnded( int iteration, double statusInPercent, string message, bool normalizePositions )
  207. {
  208. //copy the actual positions
  209. IDictionary<TVertex, Point> vertexPositions;
  210. lock ( SyncRoot )
  211. {
  212. vertexPositions = new Dictionary<TVertex, Point>( VertexPositions );
  213. }
  214. if ( normalizePositions )
  215. NormalizePositions( vertexPositions );
  216. var args = CreateLayoutIterationEventArgs( iteration, statusInPercent, message, vertexPositions );
  217. OnIterationEnded( args );
  218. }
  219. protected virtual ILayoutIterationEventArgs<TVertex> CreateLayoutIterationEventArgs( int iteration, double statusInPercent, string message, IDictionary<TVertex, Point> vertexPositions )
  220. {
  221. return new LayoutIterationEventArgs<TVertex, TEdge>( iteration, statusInPercent, message, vertexPositions );
  222. }
  223. }
  224. }