PageRenderTime 95ms CodeModel.GetById 6ms RepoModel.GetById 1ms app.codeStats 0ms

/Development/Graph#/Algorithms/Layout/ParameterizedLayoutAlgorithmBase.cs

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