private void ComputeER(TEdge item, CancellationToken cancellationToken) { var startPt = GetClosestPoint(_validPoints, VertexPositions[item.Source]); var endPt = GetClosestPoint(_validPoints, VertexPositions[item.Target]); var lst = _pathFinder.FindPath(startPt, endPt); if (lst == null) { return; } var ptlst = new List <Point>(); foreach (var pt in lst) { cancellationToken.ThrowIfCancellationRequested(); var mi = _resMatrix[pt.X, pt.Y]; ptlst.Add(mi.Point); } if (EdgeRoutes.ContainsKey(item)) { EdgeRoutes[item] = ptlst.ToArray(); } else { EdgeRoutes.Add(new KeyValuePair <TEdge, Point[]>(item, ptlst.ToArray())); } }
/// <summary> /// Bundles edges of the graph. /// </summary> /// /// <param name="graph"> /// Graph whose edges should be bundled /// </param> /// /// <param name="rectangle"> /// Rectangle in which the graph is laid out. /// Control points of bundled edges should not fall outside of this rectangle. /// </param> public void BundleAllEdges(TGraph graph) { EdgeRoutes.Clear(); //this.rectangle = rectangle; directed = true; // as we use bidirectional by default AddDataForAllEdges(graph.Edges); //Stopwatch sw = new Stopwatch(); //sw.Start(); FindCompatibleEdges(edgeGroupData); //sw.Stop(); DivideAllEdges(subdivisionPoints); //sw = new Stopwatch(); //sw.Start(); for (var i = 0; i < iterations; i++) { MoveControlPoints(edgeGroupData); } //prevents oscillating movements for (var i = 0; i < 5; i++) { cooldown *= 0.5f; MoveControlPoints(edgeGroupData); } //sw.Stop(); cooldown = 1f; if (straightening > 0) { StraightenEdgesInternally(edgeGroupData, straightening); } foreach (var e in graph.Edges) { if (!e.IsSelfLoop) { var key = new KeyPair(e.Source.ID, e.Target.ID); var list2 = edgeGroupData[key].controlPoints.ToList(); //Point p1 = GeometryHelper.GetEdgeEndpointOnRectangle(VertexPositions[e.Source], VertexSizes[e.Source], list2.First()); //Point p2 = GeometryHelper.GetEdgeEndpointOnRectangle(VertexPositions[e.Target], VertexSizes[e.Target], list2.Last()); //list2.Insert(0, p1); list2.Add(p2); list2.Insert(0, list2.First()); list2.Add(list2.Last()); EdgeRoutes.Add(e, list2.ToArray()); } } }
public override void Compute(CancellationToken cancellationToken) { EdgeRoutes.Clear(); foreach (var edge in Graph.Edges) { EdgeRoutes.Add(edge, ComputeSingle(edge)); } }
/// <summary> /// Bundles specified edges. Shapes of all the other edges remain the same, /// so this method is faster than the one for bundling all edges, but also produces less optimal layout. /// </summary> /// /// <param name="graph"> /// Parent graph of the edge set /// </param> /// /// <param name="edges"> /// Edges that should be bundled /// </param> /// /// <param name="rectangle"> /// Rectangle in which the graph is laid out. /// Control points of bundled edges should not fall outside of this rectangle. /// </param> public void BundleEdges(TGraph graph, IEnumerable <TEdge> edges) { directed = true; AddAllExistingData(graph.Edges); AddEdgeDataForMovedEdges(edges); FindCompatibleEdges(movedEdgeGroupData); ResetMovedEdges(); for (var i = 0; i < iterations; i++) { MoveControlPoints(movedEdgeGroupData); } for (var i = 0; i < 5; i++) { cooldown *= 0.5f; MoveControlPoints(movedEdgeGroupData); } cooldown = 1f; if (straightening > 0) { StraightenEdgesInternally(movedEdgeGroupData, straightening); } foreach (var e in edges) { EdgeGroupData ed; var key = new KeyPair(e.Source.ID, e.Target.ID); movedEdgeGroupData.TryGetValue(key, out ed); if (ed != null) { var list2 = ed.controlPoints.ToList(); //Point p1 = GeometryHelper.GetEdgeEndpointOnRectangle(VertexPositions[e.Source], VertexSizes[e.Source], list2.First()); //Point p2 = GeometryHelper.GetEdgeEndpointOnRectangle(VertexPositions[e.Target], VertexSizes[e.Target], list2.Last()); //list2.Insert(0, p1); list2.Add(p2); if (list2.Count > 0) { list2.Insert(0, list2.First()); list2.Add(list2.Last()); } if (EdgeRoutes.ContainsKey(e)) { EdgeRoutes[e] = list2.ToArray(); } else { EdgeRoutes.Add(e, list2.ToArray()); } } //e.SetValue(ReservedMetadataKeys.PerEdgeIntermediateCurvePoints, ed.controlPoints); } }
public override void Compute(CancellationToken cancellationToken) { foreach (var edge in Graph.Edges) { var sourcePosition = VertexPositions[edge.Source]; var targetPosition = VertexPositions[edge.Target]; var sourceSize = VertexSizes[edge.Source]; var targetSize = VertexSizes[edge.Target]; if (sourcePosition.X != targetPosition.X) { EdgeRoutes.Add( edge, new[] { new Point(0, 0), new Point(targetPosition.X + targetSize.Width / 2, sourcePosition.Y + sourceSize.Height / 2), new Point(0, 0) }); } } }
private void EdgeRoutingTest(TEdge ctrl, CancellationToken cancellationToken) { //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 || !VertexSizes.ContainsKey(ctrl.Source) || !VertexSizes.ContainsKey(ctrl.Target)) { return; } var ss = VertexSizes[ctrl.Source]; var es = VertexSizes[ctrl.Target]; var startPoint = new Point(ss.X + ss.Width * 0.5, ss.Y + ss.Height * 0.5); var endPoint = new Point(es.X + es.Width * 0.5, es.Y + es.Height * 0.5); if (startPoint == endPoint) { return; } var originalSizes = getSizesCollection(ctrl, endPoint); 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(startPoint); bool haveIntersections = true; //while we have some intersections - proceed while (haveIntersections) { var curDrawback = drawback_distance; while (true) { cancellationToken.ThrowIfCancellationRequested(); var item = checklist.Keys.FirstOrDefault(); //set last route point as current start point startPoint = 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 (GetIntersectionPoint(r, startPoint, endPoint, out checkpoint) == -1) { checklist.Remove(item); continue; } var mainVector = new Vector(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y); double X = 0; double Y = 0; //calculate drawback X coordinate if (startPoint.X == checkpoint.X || Math.Abs(startPoint.X - checkpoint.X) < curDrawback) { X = startPoint.X; } else if (startPoint.X < checkpoint.X) { X = checkpoint.X - curDrawback; } else { X = checkpoint.X + curDrawback; } //calculate drawback Y coordinate if (startPoint.Y == checkpoint.Y || Math.Abs(startPoint.Y - checkpoint.Y) < curDrawback) { Y = startPoint.Y; } else if (startPoint.Y < checkpoint.Y) { Y = checkpoint.Y - curDrawback; } else { Y = checkpoint.Y + curDrawback; } //set drawback checkpoint checkpoint = new Point(X, Y); bool isStartPoint = checkpoint == startPoint; bool routeFound = false; bool viceversa = false; int counter = 1; var joint = new Point(); bool?blocked_direction = null; while (!routeFound) { cancellationToken.ThrowIfCancellationRequested(); //choose opposite vector side each cycle var signedDistance = viceversa ? side_distance : -side_distance; //get new point coordinate joint = new Point( checkpoint.X + signedDistance * counter * (mainVector.Y / mainVector.Length), checkpoint.Y - signedDistance * counter * (mainVector.X / mainVector.Length)); //now check if new point is in some other vertex var iresult = false; var forcedBreak = false; if (originalSizes.Any(sz => 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 forcedBreak = true; } } if (forcedBreak) { break; } //get vector intersection if its ok if (!iresult) { iresult = IsIntersected(r, joint, endPoint); } //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 curDrawback += 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(endPoint); if (EdgeRoutes.ContainsKey(ctrl)) { EdgeRoutes[ctrl] = tempList.Count > 2 ? tempList.ToArray() : null; } else { EdgeRoutes.Add(ctrl, tempList.Count > 2 ? tempList.ToArray() : null); } }