/// <summary> /// Initializes the positions of the vertices. Assign a random position inside the 'bounding box' to the vertices without positions. /// It does NOT modify the position of the other vertices. /// /// It generates an <code>IterationEnded</code> event. /// /// Bounding box: /// x coordinates: double.Epsilon - <code>width</code> /// y coordinates: double.Epsilon - <code>height</code> /// </summary> /// <param name="width">Width of the bounding box.</param> /// <param name="height">Height of the bounding box.</param> /// <param name="translate_x">Translates the generated x coordinate.</param> /// <param name="translate_y">Translates the generated y coordinate.</param> protected virtual void InitializeWithRandomPositions(double width, double height, double translate_x, double translate_y) { var rnd = new Random(Parameters.Seed); //initialize with random position foreach (TVertex v in VisitedGraph.Vertices) { //for vertices without assigned position if (!VertexPositions.ContainsKey(v)) { if (EnsureUniqueRandomInitialPositions) { Point newPoint; do { newPoint = new Point( Math.Max(double.Epsilon, rnd.NextDouble() * width + translate_x), Math.Max(double.Epsilon, rnd.NextDouble() * height + translate_y)); } while (VertexPositions.Values.Contains(newPoint)); VertexPositions[v] = newPoint; } else { VertexPositions[v] = new Point( Math.Max(double.Epsilon, rnd.NextDouble() * width + translate_x), Math.Max(double.Epsilon, rnd.NextDouble() * height + translate_y)); } } } }
public override void Compute(CancellationToken cancellationToken) { if (VisitedGraph.VertexCount == 1) { if (!VertexPositions.ContainsKey(VisitedGraph.Vertices.First())) { VertexPositions.Add(VisitedGraph.Vertices.First(), new Point(0, 0)); } return; } //initialize vertex positions InitializeWithRandomPositions(Parameters.Width, Parameters.Height); //initialize ISOM data foreach (var vertex in VisitedGraph.Vertices) { ISOMData isomData; if (!_isomDataDict.TryGetValue(vertex, out isomData)) { isomData = new ISOMData(); _isomDataDict[vertex] = isomData; } } _radius = Parameters.InitialRadius; var rnd = new Random(Parameters.Seed); for (var epoch = 0; epoch < Parameters.MaxEpoch; epoch++) { cancellationToken.ThrowIfCancellationRequested(); Adjust(cancellationToken, rnd); //Update Parameters var factor = Math.Exp(-1 * Parameters.CoolingFactor * (1.0 * epoch / Parameters.MaxEpoch)); _adaptation = Math.Max(Parameters.MinAdaption, factor * Parameters.InitialAdaption); if (_radius > Parameters.MinRadius && epoch % Parameters.RadiusConstantTime == 0) { _radius--; } //report /*if ( ReportOnIterationEndNeeded ) * OnIterationEnded( epoch, (double)epoch / (double)Parameters.MaxEpoch, "Iteration " + epoch + " finished.", true ); * else if (ReportOnProgressChangedNeeded) * OnProgressChanged( (double)epoch / (double)Parameters.MaxEpoch * 100 );*/ } }
/// <summary> /// Initializes the positions of the vertices. Assign a random position inside the 'bounding box' to the vertices without positions. /// It does NOT modify the position of the other vertices. /// /// It generates an <code>IterationEnded</code> event. /// /// Bounding box: /// x coordinates: double.Epsilon - <code>width</code> /// y coordinates: double.Epsilon - <code>height</code> /// </summary> /// <param name="width">Width of the bounding box.</param> /// <param name="height">Height of the bounding box.</param> /// <param name="translate_x">Translates the generated x coordinate.</param> /// <param name="translate_y">Translates the generated y coordinate.</param> protected virtual void InitializeWithRandomPositions(double width, double height, double translate_x, double translate_y) { var rnd = new Random(DateTime.Now.Millisecond); //initialize with random position foreach (TVertex v in VisitedGraph.Vertices) { //for vertices without assigned position if (!VertexPositions.ContainsKey(v)) { VertexPositions[v] = new Point( Math.Max(double.Epsilon, rnd.NextDouble() * width + translate_x), Math.Max(double.Epsilon, rnd.NextDouble() * height + translate_y)); } } }
protected override void InitializeWithRandomPositions(double width, double height, double translate_x, double translate_y) { var rnd = GetRandomWithCurrentSeed(); //initialize with random position foreach (TVertex v in VisitedGraph.Vertices) { //for vertices without assigned position if (!VertexPositions.ContainsKey(v)) { VertexPositions[v] = new Point( Math.Max(double.Epsilon, rnd.NextDouble() * width + translate_x), Math.Max(double.Epsilon, rnd.NextDouble() * height + translate_y)); } } }
public override void Compute(CancellationToken cancellationToken) { var groups = _params.GroupParametersList.Select(a => a.GroupId).OrderByDescending(a => a).ToList(); var listRect = new Dictionary <object, Rect>(); foreach (var group in groups) { cancellationToken.ThrowIfCancellationRequested(); var groupId = group; var gp = _params.GroupParametersList.First(a => a.GroupId == groupId); //get vertices of the same group //var vertices = new List<TVertex>(); var vertices = VisitedGraph.Vertices.Where(a => a.GroupId == groupId).ToList(); //skip processing if there are no vertices in this group if (vertices.Count == 0) { continue; } //get edges between vertices in the same group var edges = VisitedGraph.Edges.Where(a => a.Source.GroupId == a.Target.GroupId && a.Target.GroupId == groupId).ToList(); //create and compute graph for a group var graph = GenerateGroupGraph(vertices, edges); //inject custom vertex and edge set into existing algorithm gp.LayoutAlgorithm.ResetGraph(graph.Vertices, graph.Edges); //assign vertex sizes to internal algorithm if needed if (gp.LayoutAlgorithm.NeedVertexSizes) { gp.LayoutAlgorithm.VertexSizes = VertexSizes.Where(a => a.Key.GroupId == groupId) .ToDictionary(a => a.Key, b => b.Value); } gp.LayoutAlgorithm.Compute(cancellationToken); //Move vertices to bound box if layout algorithm don't use bounds if (gp.ZoneRectangle.HasValue && !gp.IsAlgorithmBounded) { var offsetX = gp.ZoneRectangle.Value.X; var offsetY = gp.ZoneRectangle.Value.Y; gp.LayoutAlgorithm.VertexPositions.ForEach(a => { a.Value.Offset(offsetX, offsetY); }); } //write results to global positions storage double?[] left = { null }; double?[] top = { null }; double?[] right = { null }; double?[] bottom = { null }; gp.LayoutAlgorithm.VertexPositions.ForEach(a => { left[0] = left[0].HasValue ? (a.Value.X < left[0] ? a.Value.X : left[0]) : a.Value.X; var w = a.Value.X + VertexSizes[a.Key].Width; var h = a.Value.Y + VertexSizes[a.Key].Height; right[0] = right[0].HasValue ? (w > right[0] ? w : right[0]) : w; top[0] = top[0].HasValue ? (a.Value.Y < top[0] ? a.Value.Y : top[0]) : a.Value.Y; bottom[0] = bottom[0].HasValue ? (h > bottom[0] ? h : bottom[0]) : h; if (VertexPositions.ContainsKey(a.Key)) { VertexPositions[a.Key] = a.Value; } else { VertexPositions.Add(a.Key, a.Value); } }); if (_params.ArrangeGroups) { if (left[0] == null) { left[0] = 0; } if (right[0] == null) { right[0] = 0; } if (top[0] == null) { top[0] = 0; } if (bottom[0] == null) { bottom[0] = 0; } listRect.Add(gp.GroupId, gp.ZoneRectangle ?? new Rect(new Point(left[0].Value, top[0].Value), new Point(right[0].Value, bottom[0].Value))); } } if (_params.ArrangeGroups) { cancellationToken.ThrowIfCancellationRequested(); var origList = listRect.ToDictionary(a => a.Key, a => a.Value); var ora = _params != null && _params.OverlapRemovalAlgorithm != null ? _params.OverlapRemovalAlgorithm : new FSAAlgorithm <object>(listRect, new OverlapRemovalParameters { HorizontalGap = 10, VerticalGap = 10 }); ora.Initialize(listRect); ora.Compute(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); ora.Rectangles.ForEach(a => { int group = (int)a.Key; //_params.GroupParametersList.FirstOrDefault(b => b.GroupId == (int)a.Key).ZoneRectangle = origList[a.Key]; ArrangeRectangle(a.Value, group, origList[a.Key]); }); } }
private void EdgeRoutingTest(TEdge ctrl) { //bad edge data check if (ctrl.Source.ID == -1 || ctrl.Target.ID == -1) { throw new GX_InvalidDataException("SimpleEdgeRouting() -> You must assign unique ID for each vertex to use SimpleER algo!"); } if (ctrl.Source.ID == ctrl.Target.ID || !VertexPositions.ContainsKey(ctrl.Target)) { return; } var start_point = VertexPositions[ctrl.Source]; // new Point(GraphAreaBase.GetX(ctrl.Source), GraphAreaBase.GetY(ctrl.Source)); var end_point = VertexPositions[ctrl.Target]; // new Point(GraphAreaBase.GetX(ctrl.Target), GraphAreaBase.GetY(ctrl.Target)); if (start_point == end_point) { return; } var originalSizes = getSizesCollection(ctrl, end_point); var CHECKLIST = new Dictionary <TVertex, KeyValuePair <TVertex, Rect> >(originalSizes); var leftSIZES = new Dictionary <TVertex, KeyValuePair <TVertex, Rect> >(originalSizes); var tempList = new List <Point>(); tempList.Add(start_point); bool HaveIntersections = true; //while we have some intersections - proceed while (HaveIntersections) { var cur_drawback = drawback_distance; while (true) { var item = CHECKLIST.Keys.FirstOrDefault(); //set last route point as current start point start_point = tempList.Last(); if (item == null) { //checked all vertices and no intersection was found - quit HaveIntersections = false; break; } else { var r = originalSizes[item].Value; Point checkpoint; //check for intersection point. if none found - remove vertex from checklist if (MathHelper.GetIntersectionPoint(r, start_point, end_point, out checkpoint) == -1) { CHECKLIST.Remove(item); continue; } var main_vector = new Vector(end_point.X - start_point.X, end_point.Y - start_point.Y); double X = 0; double Y = 0; //calculate drawback X coordinate if (start_point.X == checkpoint.X || Math.Abs(start_point.X - checkpoint.X) < cur_drawback) { X = start_point.X; } else if (start_point.X < checkpoint.X) { X = checkpoint.X - cur_drawback; } else { X = checkpoint.X + cur_drawback; } //calculate drawback Y coordinate if (start_point.Y == checkpoint.Y || Math.Abs(start_point.Y - checkpoint.Y) < cur_drawback) { Y = start_point.Y; } else if (start_point.Y < checkpoint.Y) { Y = checkpoint.Y - cur_drawback; } else { Y = checkpoint.Y + cur_drawback; } //set drawback checkpoint checkpoint = new Point(X, Y); bool isStartPoint = checkpoint == start_point; bool routeFound = false; bool viceversa = false; int counter = 1; var joint = new Point(); bool?blocked_direction = null; while (!routeFound) { //choose opposite vector side each cycle var signedDistance = viceversa ? side_distance : -side_distance; //get new point coordinate joint = new Point( checkpoint.X + signedDistance * counter * (main_vector.Y / main_vector.Length), checkpoint.Y - signedDistance * counter * (main_vector.X / main_vector.Length)); //now check if new point is in some other vertex var iresult = false; var forced_break = false; foreach (var sz in originalSizes) { if (sz.Value.Value.Contains(joint)) { iresult = true; //block this side direction if (blocked_direction == null) { blocked_direction = viceversa; } else { //both sides blocked - need to drawback forced_break = true; } break; } } if (forced_break) { break; } //get vector intersection if its ok if (!iresult) { iresult = MathHelper.IsIntersected(r, joint, end_point); } //if no vector intersection - we've found it! if (!iresult) { routeFound = true; blocked_direction = null; } else { //still have an intersection with current vertex HaveIntersections = true; //skip point search if too many attempts was made (bad logic hack) if (counter > 300) { break; } counter++; //switch vector search side if (blocked_direction == null || (blocked_direction == viceversa)) { viceversa = !viceversa; } } } //if blocked and this is not start point (nowhere to drawback) - then increase drawback distance if (blocked_direction != null && !isStartPoint) { //search has been blocked - need to drawback cur_drawback += drawback_distance; } else { //add new route point if we found it // if(routeFound) tempList.Add(joint); leftSIZES.Remove(item); } } //remove currently evaded obstacle vertex from the checklist CHECKLIST.Remove(item); } //assign possible left vertices as a new checklist if any intersections was found if (HaveIntersections) { CHECKLIST = new Dictionary <TVertex, KeyValuePair <TVertex, Rect> >(leftSIZES); } } //finally, add an end route point tempList.Add(end_point); if (EdgeRoutes.ContainsKey(ctrl)) { EdgeRoutes[ctrl] = tempList.Count > 2 ? tempList.ToArray() : null; } else { EdgeRoutes.Add(ctrl, tempList.Count > 2 ? tempList.ToArray() : null); } }