static private int GetSource(int i, IntEdge edge, ref int virtualNode) { if (i > 0) { return(virtualNode++); } return(edge.Source); }
static private int GetTarget(int i, int span, IntEdge edge, int virtualNode) { if (i < span - 1) { return(virtualNode); } return(edge.Target); }
/// <summary> /// Creates a smoothed polyline /// </summary> internal SmoothedPolylineCalculator(IntEdge edgePathPar, Anchor[] anchorsP, GeometryGraph origGraph, SugiyamaLayoutSettings settings, LayerArrays la, ProperLayeredGraph layerGraph, Database databaseP) { this.database = databaseP; edgePath = edgePathPar; anchors = anchorsP; this.layerArrays = la; this.originalGraph = origGraph; this.settings = settings; this.layeredGraph = layerGraph; rightHierarchy = BuildRightHierarchy(); leftHierarchy = BuildLeftHierarchy(); }
private void InsertLayerEdgesForEdge(IntEdge edge, int[] layering, ref int virtualNode, List <int>[] layers) { int span = OriginalNodeLayer(edge.Source) - OriginalNodeLayer(edge.Target); edge.LayerEdges = new LayerEdge[span]; for (int i = 0; i < span; i++) { edge.LayerEdges[i] = new LayerEdge(GetSource(i, edge, ref virtualNode), GetTarget(i, span, edge, virtualNode), edge.CrossingWeight); } int l = OriginalNodeLayer(edge.Source) - 1; for (int i = 0; i < span; i++) { int node = edge.LayerEdges[i].Target; layering[node] = l; layers[l--].Add(node); } WalkTreeAndInsertLayerEdges(layering, layers, edge.Target, ref virtualNode); }
private IntPair GluedIntPair(IntEdge p) { return new IntPair(NodeToRepr(p.Source), NodeToRepr(p.Target)); }
private bool EdgeIsFlat(IntEdge ie) { return la.Y[ie.Source] == la.Y[ie.Target]; }
void DrawSplineBySmothingThePolyline(IntEdge edgePath) { var smoothedPolyline = new SmoothedPolylineCalculator(edgePath, Database.Anchors, OriginalGraph, settings, LayerArrays, ProperLayeredGraph, Database); ICurve spline = smoothedPolyline.GetSpline(); if (edgePath.Reversed) { edgePath.Curve = spline.Reverse(); edgePath.UnderlyingPolyline = smoothedPolyline.Reverse().GetPolyline; } else { edgePath.Curve = spline; edgePath.UnderlyingPolyline = smoothedPolyline.GetPolyline; } }
internal static int EdgeSpan(int[] layers, IntEdge e) { return layers[e.Source] - layers[e.Target]; }
void RouteEdgeWithLabel(IntEdge intEdge, Label label) { //we allow here for the edge to cross its own label Node sourceNode = routing.IntGraph.Nodes[intEdge.Source]; Node targetNode = routing.IntGraph.Nodes[intEdge.Target]; var sourcePort = new FloatingPort(sourceNode.BoundaryCurve, sourceNode.Center); var targetPort = new FloatingPort(targetNode.BoundaryCurve, targetNode.Center); ICurve labelObstacle = labelsToLabelObstacles[label]; var labelPort = new FloatingPort(labelObstacle, label.Center); SmoothedPolyline poly0; interactiveEdgeRouter.RouteSplineFromPortToPortWhenTheWholeGraphIsReady(sourcePort, labelPort, true, out poly0); SmoothedPolyline poly1; interactiveEdgeRouter.RouteSplineFromPortToPortWhenTheWholeGraphIsReady(labelPort, targetPort, true, out poly1); Site site = poly1.HeadSite.Next; Site lastSite = poly0.LastSite; lastSite.Next = site; site.Previous = lastSite; var eg = intEdge.Edge.EdgeGeometry; eg.SetSmoothedPolylineAndCurve(poly0); Arrowheads.TrimSplineAndCalculateArrowheads(eg, intEdge.Edge.Source.BoundaryCurve, intEdge.Edge.Target.BoundaryCurve, eg.Curve, false, settings.EdgeRoutingSettings.KeepOriginalSpline); }
void GetXCoordinatesOfVirtualNodesOfTheProperLayeredGraphForSkeletonEdge(IntEdge intEdge, LayerArrays layerArrays) { if (intEdge.LayerEdges == null || intEdge.LayerEdges.Count < 2) return; var edgeCurve = intEdge.Edge.Curve; var layerIndex = layerArrays.Y[intEdge.Source] - 1;//it is the layer of the highest virtual node of the edge for (int i = 1; i < intEdge.LayerEdges.Count; i++) { var v = intEdge.LayerEdges[i].Source; var layerY = layerToRecoveredYCoordinates[layerIndex--]; var layerLine = new LineSegment(new Point(originalGraph.Left, layerY), new Point(originalGraph.Right, layerY)); var intersection=Curve.CurveCurveIntersectionOne(edgeCurve, layerLine, false); skeletonVirtualVerticesToX[v] =intersection.IntersectionPoint.X; } }
internal void RegisterOriginalEdgeInMultiedges(IntEdge edge) { IntPair ip = new IntPair(edge.Source, edge.Target); List<IntEdge> o; if (multiedges.ContainsKey(ip) == false) multiedges[ip] = o = new List<IntEdge>(); else o = multiedges[ip]; o.Add(edge); }
internal NetworkEdge(IntEdge e) : base(e.Source, e.Target) { Weight = e.Weight; Separation = e.Separation; }
void CreateLayerEdgesUnderIntEdge(IntEdge ie) { int source = ie.Source; int target = ie.Target; int span = LayeredLayoutEngine.EdgeSpan(initialLayering, ie); ie.LayerEdges = new LayerEdge[span]; Debug.Assert(span > 0); if (span == 1) ie.LayerEdges[0] = new LayerEdge(ie.Source, ie.Target, ie.CrossingWeight); else { ie.LayerEdges[0] = new LayerEdge(source, numberOfNodesOfProperGraph, ie.CrossingWeight); for (int i = 0; i < span - 2; i++) ie.LayerEdges[i + 1] = new LayerEdge(numberOfNodesOfProperGraph++, numberOfNodesOfProperGraph, ie.CrossingWeight); ie.LayerEdges[span - 1] = new LayerEdge(numberOfNodesOfProperGraph++, target, ie.CrossingWeight); } }
static private int GetSource(int i, IntEdge edge, ref int virtualNode) { if (i > 0) return virtualNode++; return edge.Source; }
static private int GetTarget(int i, int span, IntEdge edge, int virtualNode) { if (i < span-1) return virtualNode; return edge.Target; }
private void InsertLayerEdgesForEdge(IntEdge edge, int[] layering, ref int virtualNode, List<int>[] layers) { int span = OriginalNodeLayer(edge.Source) - OriginalNodeLayer(edge.Target); edge.LayerEdges=new LayerEdge[span]; for (int i = 0; i < span; i++) edge.LayerEdges[i] = new LayerEdge(GetSource(i, edge, ref virtualNode), GetTarget(i, span, edge, virtualNode), edge.CrossingWeight); int l = OriginalNodeLayer(edge.Source) - 1; for (int i = 0; i < span; i++) { int node=edge.LayerEdges[i].Target; layering[node] = l; layers[l--].Add(node); } WalkTreeAndInsertLayerEdges(layering, layers, edge.Target, ref virtualNode); }
private int NumberOfVirtualNodesOnEdge(IntEdge edge) { return OriginalNodeLayer(edge.Source) - OriginalNodeLayer(edge.Target) - 1; }
void RouteEdgeWithNoLabel(IntEdge intEdge) { Node sourceNode = routing.IntGraph.Nodes[intEdge.Source]; Node targetNode = routing.IntGraph.Nodes[intEdge.Target]; var sourcePort = new FloatingPort(sourceNode.BoundaryCurve, sourceNode.Center); var targetPort = new FloatingPort(targetNode.BoundaryCurve, targetNode.Center); var eg = intEdge.Edge.EdgeGeometry; SmoothedPolyline sp; eg.Curve = interactiveEdgeRouter.RouteSplineFromPortToPortWhenTheWholeGraphIsReady(sourcePort, targetPort, true, out sp); Arrowheads.TrimSplineAndCalculateArrowheads(eg, intEdge.Edge.Source.BoundaryCurve, intEdge.Edge.Target.BoundaryCurve, eg.Curve, false, settings.EdgeRoutingSettings.KeepOriginalSpline); intEdge.Edge.EdgeGeometry = eg; }
internal IntEdge GluedIntEdge(IntEdge intEdge) { int sourceRepr = NodeToRepr(intEdge.Source); int targetRepr = NodeToRepr(intEdge.Target); IntEdge ie = new IntEdge(sourceRepr, targetRepr); ie.Separation = intEdge.Separation; ie.Weight = 0; ie.Edge = intEdge.Edge; return ie; }
///// <summary> ///// mark the vertex as one representing a label ///// or a middle of a multi edge ///// </summary> ///// <param name="db"></param> ///// <param name="bucket"></param> ///// <param name="parent"></param> ///// <param name="i"></param> internal static void RegisterDontStepOnVertex(Database db, IntEdge parent) { if (db.Multiedges[new IntPair(parent.Source, parent.Target)].Count > 1) { LayerEdge e = parent.LayerEdges[parent.LayerEdges.Count / 2]; db.MultipleMiddles.Insert(e.Source); } }
internal static NodeKind GetNodeKind(int vertexOffset, IntEdge edgePath) { return vertexOffset == 0 ? NodeKind.Top : (vertexOffset < edgePath.Count ? NodeKind.Internal : NodeKind.Bottom); }
IntEdge[] CreateIntEdges(GeometryGraph geometryGraph) { var edges = geometryGraph.Edges; var intEdges = new IntEdge[edges.Count]; int i = 0; foreach (var edge in edges) { if (edge.Source == null || edge.Target == null) throw new InvalidOperationException(); //"creating an edge with null source or target"); var intEdge = new IntEdge(nodeIdToIndex[edge.Source], nodeIdToIndex[edge.Target], edge); intEdges[i] = intEdge; i++; } return intEdges; }
/// <summary> /// Simpler constructor which initializes the internal graph representation automatically /// </summary> /// <param name="originalGraph"></param> /// <param name="settings"></param> internal LayeredLayoutEngine(GeometryGraph originalGraph, SugiyamaLayoutSettings settings) { if (originalGraph != null) { //enumerate the nodes - maps node indices to strings nodeIdToIndex = new Dictionary<Node, int>(); IList<Node> nodes = originalGraph.Nodes; int index = 0; foreach (Node n in nodes) { nodeIdToIndex[n] = index; index++; } var edges = originalGraph.Edges; var intEdges = new IntEdge[edges.Count]; int i = 0; foreach(var edge in edges){ if (edge.Source == null || edge.Target == null) throw new InvalidOperationException(); //"creating an edge with null source or target"); var intEdge = new IntEdge(nodeIdToIndex[edge.Source], nodeIdToIndex[edge.Target], edge); intEdges[i] = intEdge; i++; } IntGraph = new BasicGraph<Node, IntEdge>(intEdges, originalGraph.Nodes.Count) {Nodes = nodes}; this.originalGraph = originalGraph; sugiyamaSettings = settings; Database = new Database(); foreach (IntEdge e in IntGraph.Edges) database.RegisterOriginalEdgeInMultiedges(e); CycleRemoval(); } }
private int NumberOfVirtualNodesOnEdge(IntEdge edge) { return(OriginalNodeLayer(edge.Source) - OriginalNodeLayer(edge.Target) - 1); }
void RouteEdge(IntEdge edge) { if (edge.HasLabel) RouteEdgeWithLabel(edge, edge.Edge.Label); else RouteEdgeWithNoLabel(edge); }
private static LayerEdge LastEdge(IntEdge e) { return e.LayerEdges[e.LayerEdges.Count - 1]; }
private static LayerEdge FirstEdge(IntEdge e) { return e.LayerEdges[0]; }
void InsertVirtualEdgesIfNeeded(LayerArrays layerArrays) { if (constrainedOrdering != null) //if there are constraints we handle multiedges correctly return; foreach (var kv in database.Multiedges) // If there are an even number of multi-edges between two nodes then // add a virtual edge in the multi-edge dict to improve the placement, but only in case when the edge goes down only one layer. if (kv.Value.Count%2 == 0 && layerArrays.Y[kv.Key.First] - 1 == layerArrays.Y[kv.Key.Second]) { var newVirtualEdge = new IntEdge(kv.Key.First, kv.Key.Second); newVirtualEdge.Edge = new Edge(); newVirtualEdge.IsVirtualEdge = true; kv.Value.Insert(kv.Value.Count/2, newVirtualEdge); IntGraph.AddEdge(newVirtualEdge); } }
internal static int GetTarget(ref int currentVV, IntEdge e, int i, int span) { if (i < span - 1) return currentVV; return e.Target; }
///// <summary> ///// A quote from Gansner93. ///// The method involves constructing an auxiliary graph as illustrated in figure 4-2. ///// This transformation is the graphical analogue of the algebraic ///// transformation mentioned above for removing the absolute values ///// from the optimization problem. The nodes of the auxiliary graph Gў are the nodes of ///// the original graph G plus, for every edge e in G, there is a new node ne. ///// There are two kinds of edges in Gў. One edge class encodes the ///// cost of the original edges. Every edge e = (u,v) in G is replaced by two edges (ne ,u) ///// and (ne, v) with d = 0 and w = w(e)W(e). The other class of edges separates nodes in the same layer. ///// If v is the left neighbor of w, then Gў has an edge f = e(v,w) with d( f ) = r(v,w) and ///// w( f ) = 0. This edge forces the nodes to be sufficiently ///// separated but does not affect the cost of the layout. XLayoutGraph CreateXLayoutGraph(LayerArrays layerArrays) { int nOfVerts = properLayeredGraph.NodeCount; //create edges of XLayoutGraph var edges = new List<IntEdge>(); foreach (LayerEdge e in properLayeredGraph.Edges) { var n1 = new IntEdge(nOfVerts, e.Source); var n2 = new IntEdge(nOfVerts, e.Target); n1.Weight = n2.Weight = e.Weight; n1.Separation = 0; //these edge have 0 separation n2.Separation = 0; nOfVerts++; edges.Add(n1); edges.Add(n2); } foreach (var layer in layerArrays.Layers) for (int i = layer.Length - 1; i > 0; i--) { int source = layer[i]; int target = layer[i - 1]; var ie = new IntEdge(source, target); Anchor sourceAnchor = database.Anchors[source]; Anchor targetAnchor = database.Anchors[target]; double sep = sourceAnchor.LeftAnchor + targetAnchor.RightAnchor + sugiyamaSettings.NodeSeparation; ie.Separation = (int) (sep + 1); edges.Add(ie); } var ret = new XLayoutGraph(IntGraph, properLayeredGraph, layerArrays, edges, nOfVerts); ret.SetEdgeWeights(); return ret; }
internal static int GetSource(ref int currentVV, IntEdge e, int i) { if (i == 0) return e.Source; return currentVV++; }
static IntEdge CreateUpDownConstrainedIntEdge(IntPair intPair) { var intEdge = new IntEdge(intPair.x, intPair.y); intEdge.Weight = 0; //we do not want the edge weight to contribute in to the sum but just take the constraint into account intEdge.Separation = 1; return intEdge; }
void CreateSplineForNonSelfEdge(IntEdge es){ this.ProgressStep(); if (es.LayerEdges != null) { DrawSplineBySmothingThePolyline(es); if (!es.IsVirtualEdge) { es.UpdateEdgeLabelPosition(Database.Anchors); Arrowheads.TrimSplineAndCalculateArrowheads(es.Edge.EdgeGeometry, es.Edge.Source.BoundaryCurve, es.Edge.Target.BoundaryCurve, es.Curve, true, settings.EdgeRoutingSettings.KeepOriginalSpline); } } }